Python 2784.py
class Solution:
def isGood(self, nums: List[int]) -> bool:
# remove numbers, must be empty at the end
need = set(range(1, len(nums)))
high = 0
for n in nums:
need.discard(n)
if n == len(nums) - 1: # highest number must occur twice
high += 1
return high == 2 and not need
Difficulty
and has an acceptance rate of about 57% (300k+ submissions).
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 isGood that determines whether a list of integers satisfies a specific structural property. The property requires that every integer from 1 up to len(nums) - 1 appears at least once, that the integer equal to len(nums) - 1 appears exactly twice, and that no other values remain unaccounted for after processing the list. The method returns True only when all these conditions are met; otherwise it returns False.
Key Steps
The algorithm begins by constructing a set named need that contains the expected range of values. This set is built using range(1, len(nums)), which yields all integers from 1 up to one less than the length of the input list. The set represents the numbers that must be observed at least once.
need = set(range(1, len(nums)))
A counter variable high is initialized to zero. This counter tracks the number of times the highest permissible value-len(nums) - 1-appears in the input.
high = 0
The method then iterates over each element n in the input list nums. For every element, the algorithm attempts to remove it from the need set using discard. The discard operation silently ignores the call if the element is not present, which means the algorithm does not raise an exception when encountering unexpected values.
for n in nums:
need.discard(n)
Within the same loop, the algorithm checks whether the current element equals the highest allowed value, len(nums) - 1. When this condition holds, the high counter is incremented.
if n == len(nums) - 1:
high += 1
After processing all elements, the method evaluates two conditions: that high equals 2, ensuring the highest value occurs exactly twice, and that the need set is empty, confirming that every required number from 1 to len(nums) - 1 has been seen at least once. The logical conjunction of these two checks determines the final Boolean result.
return high == 2 and not need
Edge Cases Handled
The code gracefully handles inputs that contain numbers outside the expected range. Because discard does not raise an error for missing elements, any value not in need is simply ignored, allowing the algorithm to continue without interruption. This behavior ensures that extraneous values do not cause a crash and that the final condition not need will correctly reflect missing required numbers.
When the input list is empty, range(1, len(nums)) produces an empty range, resulting in an empty need set. The loop body does not execute, leaving high at zero. The final return statement evaluates high == 2 as false, yielding False, which aligns with the expectation that an empty list cannot satisfy the defined property.
If the list contains exactly two occurrences of the highest value and no other numbers, the need set will still contain the numbers from 1 up to len(nums) - 2. Because those numbers are never discarded, not need evaluates to false, and the method returns False. This demonstrates that the algorithm correctly requires the presence of all intermediate values, not just the highest one.
When the list includes duplicate occurrences of numbers other than the highest, the discard operation removes the number on its first appearance and silently ignores subsequent duplicates. The presence of extra duplicates does not affect the emptiness of need, allowing the method to focus solely on the existence of required values rather than their exact frequencies, except for the special handling of the highest value.
Performance Optimizations
The implementation leverages a set for constant-time membership checks and removals. By using discard instead of a conditional check followed by removal, the code avoids an explicit existence test, reducing the number of operations per element. The single pass through the input list ensures that each element is examined exactly once, minimizing overhead.
The counter high is incremented only when the element matches the highest permissible value, avoiding unnecessary arithmetic for other elements. The final boolean expression combines both required conditions in a single return statement, eliminating additional branching or temporary variables.
Overall, the algorithm achieves an efficient traversal with minimal auxiliary data structures, focusing on set operations that are optimized in the underlying Python runtime.
ELI5 - Simplified Explanation
Imagine a box full of number cards. The goal is to see if the box follows a special rule. First, think about how many cards are in the box. If there are five cards total, the rule says some cards need to be the numbers one, two, three, and four.
The code starts by making a collection of all those required numbers. Then, it looks at every card in the box one by one. If a card matches one of the required numbers, that number gets crossed off a list because it has been found.
At the same time, the code watches for the biggest number in the group. If the box has five cards, the biggest number is four. The rule says that this biggest number must appear exactly twice. A counter keeps track of how many times that big number shows up.
Once every card has been checked, the code looks to see if all the smaller numbers were found and if the biggest number appeared exactly twice. If everything matches the rule, the box is good.
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 | Java | C++ | Python | TS | ||||
| WalkCCC | Java | C++ | Python | ||||||
| leetcode.ca | Java | C++ | C# | Go | Python | TS | |||
| Progiez | Java | C++ | Python | ||||||
| github | charles-wangkai | Java | |||||||
| fsq | Rust | ||||||||
| JoshCrozier | JS | ||||||||
| varunu28 | Java | ||||||||
| withaarzoo | C++ | ||||||||
| AlgoMonster | C++, Python, Java, TypeScript | ||||||||
| WalkCCC | C++, Python, Java | ||||||||
| leetcode.ca | C++, C#, Go, Java, Python, TypeScript | ||||||||
| Progiez | C++, Java, Python | ||||||||
| charles-wangkai | Java | ||||||||
| fsq | Rust | ||||||||
| JoshCrozier | JavaScript | ||||||||
| varunu28 | Java | ||||||||
| withaarzoo | C++ |
Videos
Solved On The Same Day
- problem 953: Verifying an Alien Dictionary
- problem 961: N-Repeated Element in Size 2N Array
- problem 2264: Largest 3-Same-Digit Number in String
- problem 2682: Find the Losers of the Circular Game
- problem 2848: Points That Intersect With Cars
- problem 2869: Minimum Operations to Collect Elements
- problem 890: Find and Replace Pattern
- problem 954: Array of Doubled Pairs
- problem 959: Regions Cut By Slashes
- problem 966: Vowel Spellchecker
- problem 1202: Smallest String With Swaps
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