You are given an integer array nums
that is sorted in non-decreasing order.
Determine if it is possible to split nums
into one or more subsequences such that both of the following conditions are true:
3
or more.Return true
if you can split nums
according to the above conditions, or false
otherwise.
A subsequence of an array is a new array that is formed from the original array by deleting some (can be none) of the elements without disturbing the relative positions of the remaining elements. (i.e., [1,3,5]
is a subsequence of [1,2,3,4,5]
while [1,3,2]
is not).
Example 1:
Input: nums = [1,2,3,3,4,5] Output: true Explanation: nums can be split into the following subsequences: [1,2,3,3,4,5] --> 1, 2, 3 [1,2,3,3,4,5] --> 3, 4, 5
Example 2:
Input: nums = [1,2,3,3,4,4,5,5] Output: true Explanation: nums can be split into the following subsequences: [1,2,3,3,4,4,5,5] --> 1, 2, 3, 4, 5 [1,2,3,3,4,4,5,5] --> 3, 4, 5
Example 3:
Input: nums = [1,2,3,4,4,5] Output: false Explanation: It is impossible to split nums into consecutive increasing subsequences of length 3 or more.
Constraints:
1 <= nums.length <= 104
-1000 <= nums[i] <= 1000
nums
is sorted in non-decreasing order.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force method involves checking absolutely every possible way to split the given set of numbers. We explore all combinations, ensuring each resulting sequence meets the 'consecutive' and 'at least 3 elements' requirements. This approach guarantees finding a solution, if one exists, by sheer exhaustive testing.
Here's how the algorithm would work step-by-step:
def split_array_into_consecutive_subsequences(numbers):
def can_split(remaining_numbers, sequences):
if not remaining_numbers:
return True
first_number = remaining_numbers[0]
for sequence_length in range(3, len(remaining_numbers) + 1):
potential_sequence = [first_number + i for i in range(sequence_length)]
# Check if a potential consecutive sequence exists
if all(number in remaining_numbers for number in potential_sequence):
new_remaining_numbers = list(remaining_numbers)
for number in potential_sequence:
new_remaining_numbers.remove(number)
# Recursively check if the rest can be split
if can_split(new_remaining_numbers, sequences + [potential_sequence]):
return True
return False
# Try every starting point to create the sequences
for start_index in range(len(numbers)):
if can_split(numbers, []):
return True
# Return false if no split is found
return False
The trick is to efficiently track how many unfinished sequences we have waiting for the next number. We use this information to greedily extend sequences whenever possible, creating new sequences only when absolutely necessary.
Here's how the algorithm would work step-by-step:
def is_possible_to_split(nums):
number_counts = {}
for number in nums:
number_counts[number] = number_counts.get(number, 0) + 1
tails = {}
for number in nums:
if number_counts[number] == 0:
continue
if tails.get(number - 1, 0) > 0:
# Extend an existing sequence.
tails[number - 1] -= 1
tails[number] = tails.get(number, 0) + 1
number_counts[number] -= 1
elif number_counts.get(number, 0) > 0 and \
number_counts.get(number + 1, 0) > 0 and \
number_counts.get(number + 2, 0) > 0:
# Start a new sequence.
number_counts[number] -= 1
number_counts[number + 1] -= 1
number_counts[number + 2] -= 1
tails[number + 2] = tails.get(number + 2, 0) + 1
else:
# Cannot extend or start a sequence.
return False
return True
Case | How to Handle |
---|---|
Empty input array | Return False since no subsequences can be formed. |
Input array with fewer than 3 elements | Return False because a consecutive subsequence must have length at least 3. |
Input array with all the same numbers (e.g., [1, 1, 1, 1]) | Return False as it's impossible to create consecutive subsequences of length at least 3. |
Negative numbers in the input array | The frequency map correctly handles negative numbers and their counts. |
Presence of zero in the input array | The logic will properly check for consecutive sequences including zero. |
Array is sorted but no consecutive sequence of length 3 or more exists | The algorithm should return False in this scenario after iterating through the array. |
The input array is very large, causing potential memory issues if storing all numbers | Use an iterative approach with constant space instead of recursion to avoid stack overflow. |
Integer overflow when checking for consecutive values | Ensure that data types used for calculations (e.g., next value checks) can accommodate potentially large numbers. |