2229. Check if an Array Is Consecutive π
Problem Description
You are given an integer array nums
. Your task is to determine if the array contains consecutive integers.
An array is considered consecutive if it contains every integer in a continuous range from the minimum value to the maximum value, with no gaps or duplicates. Specifically, if x
is the minimum value in the array and the array has length n
, then the array must contain exactly the integers [x, x+1, x+2, ..., x+n-1]
.
For example:
- The array
[4, 5, 6, 7]
is consecutive because it contains all integers from 4 to 7 - The array
[1, 3, 4, 5]
is not consecutive because it's missing the number 2 - The array
[1, 2, 2, 3]
is not consecutive because it contains a duplicate (2 appears twice)
Return true
if the array is consecutive, otherwise return false
.
The solution checks three conditions that must all be true for an array to be consecutive:
- All elements must be unique (no duplicates)
- The number of unique elements must equal the array length
- The difference between the maximum and minimum values plus 1 must equal the array length
This works because in a consecutive sequence of n
numbers starting from min
, the maximum value would be min + n - 1
, so max - min + 1 = n
.
Intuition
To determine if an array contains consecutive integers, we need to think about what properties a consecutive sequence must have.
First, let's consider what happens when we have n
consecutive integers starting from some value x
. The sequence would be [x, x+1, x+2, ..., x+n-1]
. The smallest value is x
and the largest value is x+n-1
. This means the difference between the maximum and minimum values is exactly n-1
, or equivalently, max - min + 1 = n
.
However, just checking if max - min + 1 = n
isn't enough. Consider the array [1, 2, 4, 5]
- here max = 5
, min = 1
, and n = 4
. We get 5 - 1 + 1 = 5
, which doesn't equal 4, so this correctly identifies it as non-consecutive. But what about [1, 2, 2, 3]
? Here max = 3
, min = 1
, n = 4
, and 3 - 1 + 1 = 3
, which also doesn't equal 4. But the reason is different - we have duplicates!
This leads us to realize that for an array to be consecutive, it must also contain no duplicate values. If we have duplicates, we can't possibly have all the integers in the range because we'd be "wasting" array positions on repeated values.
Therefore, we arrive at the key insight: an array is consecutive if and only if:
- It has no duplicates (checked by comparing
len(set(nums))
withlen(nums)
) - The range it spans (
max - min + 1
) exactly matches the number of elements
We can elegantly combine these checks into a single expression: len(set(nums)) == max - min + 1 == len(nums)
. This verifies that the number of unique elements equals both the expected range size and the actual array length.
Learn more about Sorting patterns.
Solution Approach
The solution uses a hash table (set) to efficiently check for duplicates and implements a mathematical relationship to verify consecutiveness.
Implementation Steps:
-
Find the minimum and maximum values: We use Python's built-in
min()
andmax()
functions to find the smallest and largest elements in the array. These operations scan through the array once each.mi, mx = min(nums), max(nums)
-
Create a set from the array: Converting the list to a set automatically removes any duplicate values. This gives us a collection containing only unique elements from the original array.
set(nums)
-
Perform the three-way equality check: We verify that all three conditions are equal:
len(set(nums)) == mx - mi + 1 == len(nums)
This checks:
len(set(nums))
: The number of unique elements in the arraymx - mi + 1
: The expected count of integers in the range[mi, mx]
inclusivelen(nums)
: The total number of elements in the original array
Why this works:
If the array contains consecutive integers from mi
to mx
, there should be exactly mx - mi + 1
distinct integers. For example, the range [3, 4, 5, 6]
has 6 - 3 + 1 = 4
integers.
The three-way equality ensures:
- No duplicates exist (unique count equals total count)
- No gaps exist in the sequence (unique count equals the range size)
- All conditions are satisfied simultaneously
Time and Space Complexity:
- Time:
O(n)
wheren
is the length of the array (for creating the set and finding min/max) - Space:
O(n)
for storing the set
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with a few examples to understand how it works.
Example 1: Consecutive array [4, 2, 3, 5]
-
First, find the minimum and maximum values:
min = 2
,max = 5
-
Create a set from the array:
set([4, 2, 3, 5]) = {2, 3, 4, 5}
- Number of unique elements:
4
-
Check the three-way equality:
len(set(nums))
=4
(unique elements)max - min + 1
=5 - 2 + 1
=4
(expected range size)len(nums)
=4
(original array length)
Since
4 == 4 == 4
, the result istrue
. The array contains consecutive integers from 2 to 5.
Example 2: Non-consecutive array with gap [1, 3, 4, 5]
-
Find min and max:
min = 1
,max = 5
-
Create set:
set([1, 3, 4, 5]) = {1, 3, 4, 5}
- Number of unique elements:
4
-
Check equality:
len(set(nums))
=4
max - min + 1
=5 - 1 + 1
=5
len(nums)
=4
Since
4 β 5
, the result isfalse
. The array is missing the number 2.
Example 3: Non-consecutive array with duplicate [1, 2, 2, 3]
-
Find min and max:
min = 1
,max = 3
-
Create set:
set([1, 2, 2, 3]) = {1, 2, 3}
- Number of unique elements:
3
-
Check equality:
len(set(nums))
=3
max - min + 1
=3 - 1 + 1
=3
len(nums)
=4
Since
3 β 4
, the result isfalse
. The duplicate 2 prevents consecutiveness.
The beauty of this approach is that it catches both types of violations (gaps and duplicates) with a single elegant check.
Solution Implementation
1class Solution:
2 def isConsecutive(self, nums: List[int]) -> bool:
3 # Find the minimum and maximum values in the array
4 min_val, max_val = min(nums), max(nums)
5
6 # For consecutive integers:
7 # 1. No duplicates: len(set(nums)) == len(nums)
8 # 2. Range check: max_val - min_val + 1 == len(nums)
9 # 3. Both conditions must be satisfied simultaneously
10 return len(set(nums)) == max_val - min_val + 1 == len(nums)
11
1class Solution {
2 public boolean isConsecutive(int[] nums) {
3 // Initialize minimum with first element, maximum with 0
4 int minValue = nums[0];
5 int maxValue = 0;
6
7 // Use HashSet to detect duplicates
8 Set<Integer> uniqueNumbers = new HashSet<>();
9
10 // Iterate through all numbers in the array
11 for (int currentNumber : nums) {
12 // Check for duplicates - if add() returns false, number already exists
13 if (!uniqueNumbers.add(currentNumber)) {
14 return false;
15 }
16
17 // Update minimum and maximum values
18 minValue = Math.min(minValue, currentNumber);
19 maxValue = Math.max(maxValue, currentNumber);
20 }
21
22 // For consecutive numbers, the difference between max and min plus 1
23 // should equal the array length
24 // Example: [4,5,6,7] -> max=7, min=4, difference=3, plus 1 = 4 (array length)
25 return maxValue - minValue + 1 == nums.length;
26 }
27}
28
1class Solution {
2public:
3 bool isConsecutive(vector<int>& nums) {
4 // Use hash set to track unique elements and detect duplicates
5 unordered_set<int> uniqueNumbers;
6
7 // Initialize min and max values with first element and 0
8 int minValue = nums[0];
9 int maxValue = 0;
10
11 // Iterate through all numbers in the array
12 for (int currentNum : nums) {
13 // Check if current number already exists (duplicate found)
14 if (uniqueNumbers.count(currentNum)) {
15 return false;
16 }
17
18 // Add current number to the set
19 uniqueNumbers.insert(currentNum);
20
21 // Update minimum and maximum values
22 minValue = min(minValue, currentNum);
23 maxValue = max(maxValue, currentNum);
24 }
25
26 // Check if the range [min, max] forms consecutive integers
27 // For consecutive integers: max - min + 1 should equal array size
28 return (maxValue - minValue + 1) == nums.size();
29 }
30};
31
1/**
2 * Checks if an array contains consecutive integers (when sorted)
3 * @param nums - Array of numbers to check
4 * @returns true if numbers form a consecutive sequence, false otherwise
5 */
6function isConsecutive(nums: number[]): boolean {
7 // Initialize minimum with first element, maximum with 0
8 let minimum: number = nums[0];
9 let maximum: number = 0;
10
11 // Set to track unique numbers and detect duplicates
12 const uniqueNumbers: Set<number> = new Set<number>();
13
14 // Iterate through all numbers in the array
15 for (const currentNumber of nums) {
16 // Check if we've seen this number before (duplicate found)
17 if (uniqueNumbers.has(currentNumber)) {
18 return false;
19 }
20
21 // Add current number to the set
22 uniqueNumbers.add(currentNumber);
23
24 // Update minimum and maximum values
25 minimum = Math.min(minimum, currentNumber);
26 maximum = Math.max(maximum, currentNumber);
27 }
28
29 // Check if the range equals the array length
30 // For consecutive numbers: max - min + 1 should equal array length
31 return maximum - minimum + 1 === nums.length;
32}
33
Time and Space Complexity
Time Complexity: O(n)
The time complexity is determined by the following operations:
min(nums)
:O(n)
- iterates through all elements to find minimummax(nums)
:O(n)
- iterates through all elements to find maximumset(nums)
:O(n)
- creates a set from n elementslen(set(nums))
:O(1)
- getting length of setlen(nums)
:O(1)
- getting length of list- Comparisons:
O(1)
- comparing three values
Since these operations are performed sequentially (not nested), the overall time complexity is O(n) + O(n) + O(n) + O(1) = O(n)
, where n
is the length of the array nums
.
Space Complexity: O(n)
The space complexity comes from creating a set from the input array. The set(nums)
operation creates a new data structure that, in the worst case where all elements are unique, stores n
elements. The variables mi
and mx
only use O(1)
additional space. Therefore, the total space complexity is O(n)
, where n
is the length of the array nums
.
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Empty Array Handling
The current solution will crash when given an empty array because min()
and max()
cannot operate on empty sequences.
Problem Example:
nums = []
min(nums) # Raises ValueError: min() arg is an empty sequence
Solution: Add an edge case check at the beginning:
def isConsecutive(self, nums: List[int]) -> bool:
if not nums:
return False # or True, depending on problem requirements
min_val, max_val = min(nums), max(nums)
return len(set(nums)) == max_val - min_val + 1 == len(nums)
2. Single Element Array Ambiguity
A single-element array like [5]
technically contains consecutive integers (just one), but the problem statement might not clearly define this case.
Problem Example:
nums = [5] # Current solution returns True, but is this the intended behavior?
Solution: Clarify requirements and potentially add explicit handling:
def isConsecutive(self, nums: List[int]) -> bool:
if len(nums) <= 1:
return True # Single element or empty is trivially consecutive
min_val, max_val = min(nums), max(nums)
return len(set(nums)) == max_val - min_val + 1 == len(nums)
3. Integer Overflow in Other Languages
While Python handles large integers gracefully, implementing this solution in languages like Java or C++ could face integer overflow when calculating max_val - min_val + 1
.
Problem Example:
nums = [-2147483648, 2147483647] # Min and max 32-bit integers # max_val - min_val + 1 would overflow in 32-bit arithmetic
Solution: Use appropriate data types or rearrange the calculation:
def isConsecutive(self, nums: List[int]) -> bool:
if not nums:
return False
min_val, max_val = min(nums), max(nums)
# Rearrange to avoid overflow: check if max - min == len - 1
return len(set(nums)) == len(nums) and max_val - min_val == len(nums) - 1
4. Misunderstanding the Three-Way Equality
Developers might incorrectly assume that checking only two conditions is sufficient, missing edge cases.
Problem Example:
# Checking only uniqueness and range might miss cases nums = [1, 2, 4, 5] # Has 4 unique elements, max-min+1 = 5 # Without checking len(nums), we might incorrectly validate this
Solution: Always maintain the complete three-way check or explicitly separate the conditions for clarity:
def isConsecutive(self, nums: List[int]) -> bool:
if not nums:
return False
unique_nums = set(nums)
min_val, max_val = min(nums), max(nums)
# Explicitly check all three conditions
has_no_duplicates = len(unique_nums) == len(nums)
covers_full_range = max_val - min_val + 1 == len(nums)
return has_no_duplicates and covers_full_range
Which type of traversal does breadth first search do?
Recommended Readings
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Want a Structured Path to Master System Design Too? Donβt Miss This!