Python 2150.py
class Solution:
def findLonely(self, nums: List[int]) -> List[int]:
nums.sort()
for i in range(len(nums)):
if i > 0:
if nums[i - 1] >= nums[i] - 1:
continue
if i < len(nums) - 1:
if nums[i + 1] <= nums[i] + 1:
continue
yield nums[i]
Difficulty
and has an acceptance rate of about 64% (100k+ submissions).
Typical patterns to solve this problem:
- Array
- Counting
- Hash Table
AI Disclaimer
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.
See this dedicated page for more details.
Code Walkthrough
Overview
The provided implementation defines a method that extracts the “lonely” numbers from an input list. A number is considered lonely when there is no other element in the list that is equal to it, one less than it, or one greater than it. The algorithm follows three logical phases: sorting the input, scanning the sorted sequence while applying neighbor-based conditions, and lazily emitting qualifying values.
Sorting Phase
The first operation arranges the elements in non-decreasing order.
nums.sort()
Sorting guarantees that any two numbers that could affect each other’s loneliness are positioned next to one another. This ordering eliminates the need for nested loops or repeated searches, allowing the subsequent scan to rely solely on immediate neighbors.
Iteration and Conditional Checks
A for loop walks through every index of the sorted list. For each position, two guard clauses examine the surrounding elements when they exist.
for i in range(len(nums)):
if i > 0:
if nums[i - 1] >= nums[i] - 1:
continue
if i < len(nums) - 1:
if nums[i + 1] <= nums[i] + 1:
continue
The first guard activates only when a predecessor is present (i > 0). It discards the current element if the previous value is greater than or equal to one less than the current value, which covers the cases where the predecessor is the same number or exactly one smaller.
The second guard activates only when a successor exists (i < len(nums) - 1). It discards the current element if the next value is less than or equal to one more than the current value, handling the symmetric situation where the successor is the same number or exactly one larger.
By using continue statements, the loop skips further processing for any element that fails either neighbor test, ensuring that only numbers isolated by at least a gap of two on both sides survive to the next stage.
Yielding Lonely Elements
When an index passes both neighbor checks, the method yields the corresponding value.
yield nums[i]
Yielding turns the method into a generator, producing results on demand rather than constructing a full list up front. This approach reduces memory consumption, especially for large inputs where only a small fraction of numbers qualify as lonely.
Edge Cases Handled
The logic naturally accommodates several boundary conditions:
- Empty Input - The loop body never executes, resulting in an empty generator.
- Single-Element List - Both neighbor guards are bypassed because the index is neither greater than zero nor less than the last index, allowing the sole element to be yielded as lonely.
- Duplicate Values - When identical numbers appear consecutively, the predecessor guard detects that the previous element is not less than the current value minus one, causing the duplicate to be skipped.
- Consecutive Sequences - In a run such as
[3,4,5], each interior element fails at least one neighbor guard because the adjacent numbers differ by exactly one, preventing any of them from being yielded. - Numbers at the Extremes - The first and last elements are evaluated with only one neighbor guard, correctly handling cases where loneliness depends on a single side.
Performance Optimizations
The design leverages sorting to bring potential conflicts into adjacency, which eliminates the need for costly global searches. After sorting, the algorithm proceeds with a single linear pass, using early continue statements to avoid unnecessary evaluations for elements that are already known to be non-lonely. The generator pattern further optimizes resource usage by emitting results incrementally, allowing callers to consume the output without incurring the overhead of an intermediate collection.
ELI5 - Simplified Explanation
Imagine a long line of numbered blocks scattered on the floor. First, the blocks are put in order from the smallest number to the biggest number, just like lining up toys by size. Now, look at each block one by one. To see if a block is lonely, check the neighbors right next to it.
If there is a block with the same number as the current one, or if there is a block with a number that is exactly one higher or one lower, then the current block is not lonely because it has friends close by. Think of this like playing a game where you only pick the blocks that are standing by themselves with nobody nearby. If a block has no friends next to it, it gets to stay.
Code Quality
Complexity Analysis
As a rule of thumb, the maximum input size for one second execution time is
- factorial: up to 10 elements
- exponential: up to 20 elements
- polynomial: a few thousand elements
- loglinear: up to 100,000 elements
- linear: a few million elements
- logarithmic: a billion elements
- constant: practically unlimited
Other Solutions
Obviously, I did that after I solved the problem myself.
In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.
And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.
(click on a column header to sort the table)
| author | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| author | solutions | |||||||||
| www | AlgoMonster | C++ | Java | Python | TS | |||||
| WalkCCC | C++ | Java | Python | |||||||
| leetcode.ca | C++ | Java | Python | Go | TS | |||||
| Progiez | C++ | Java | Python | |||||||
| github | black-shadows | C++ | ||||||||
| charles-wangkai | Java | |||||||||
| everthis | JS | |||||||||
| fartem | Ruby | |||||||||
| fsq | C++ | |||||||||
| JoshCrozier | JS | |||||||||
| lkwq007 | Python | |||||||||
| martianoff | Scala | |||||||||
| suxrobGM | C# | |||||||||
| varunu28 | Java | |||||||||
| AlgoMonster | C++, Python, Java, TypeScript | |||||||||
| WalkCCC | C++, Python, Java | |||||||||
| leetcode.ca | C++, Go, Java, Python, TypeScript | |||||||||
| Progiez | C++, Java, Python | |||||||||
| black-shadows | C++, C++ | |||||||||
| charles-wangkai | Java | |||||||||
| everthis | JavaScript | |||||||||
| fartem | Ruby | |||||||||
| fsq | C++ | |||||||||
| JoshCrozier | JavaScript | |||||||||
| lkwq007 | Python | |||||||||
| martianoff | Scala | |||||||||
| suxrobGM | C# | |||||||||
| varunu28 | Java |
Videos
Similar Problems
- problem 1838: Frequency of the Most Frequent Element
Solved On The Same Day
- problem 880: Decoded String at Index
- problem 912: Sort an Array
- problem 923: 3Sum With Multiplicity
- problem 973: K Closest Points to Origin
- problem 1010: Pairs of Songs With Total Durations Divisible by 60
- problem 1054: Distant Barcodes
- problem 1079: Letter Tile Possibilities
- problem 1090: Largest Values From Labels
- problem 1347: Minimum Number of Steps to Make Two Strings Anagram
- problem 1366: Rank Teams by Votes
- problem 1419: Minimum Number of Frogs Croaking
- problem 1738: Find Kth Largest XOR Coordinate Value
- problem 1814: Count Nice Pairs in an Array
- problem 1985: Find the Kth Largest Integer in the Array
- problem 2018: Check if Word Can Be Placed In Crossword
- problem 2182: Construct String With Repeat Limit
- problem 2225: Find Players With Zero or One Losses
- problem 2232: Minimize Result by Adding Parentheses to Expression
- problem 2244: Minimum Rounds to Complete All Tasks
- problem 2284: Sender With Largest Word Count
- problem 2343: Query Kth Smallest Trimmed Number
- problem 2526: Find Consecutive Integers from a Data Stream
- problem 2844: Minimum Operations to Make a Special Number
- problem 2860: Happy Students
- problem 906: Super Palindromes
- problem 992: Subarrays with K Different Integers
- problem 1106: Parsing A Boolean Expression
- problem 1601: Maximum Number of Achievable Transfer Requests
- problem 2081: Sum of k-Mirror Numbers
- problem 2122: Recover the Original Array
- problem 2416: Sum of Prefix Scores of Strings
Extra
- Tech Stack - my development environment and tools
- AI - how AI helped me create this website (NOT solving the problems)
- Progress - progression over time
- Quality - code quality