Split Array into Consecutive Subsequences - Complete Solution Guide
Split Array into Consecutive Subsequences is LeetCode problem 659, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.
Problem Statement
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: Each subsequence is a consecutive increasing sequence (i.e. each integer is exactly one more than the previous integer). All subsequences have a length of 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
Detailed Explanation
The problem asks us to determine if a given sorted (non-decreasing order) integer array `nums` can be split into one or more subsequences. Each subsequence must be a consecutive increasing sequence (each element is exactly one greater than the previous) and must have a length of at least 3. The function should return `true` if such a split is possible, and `false` otherwise. A subsequence is formed by deleting some (or none) elements from the original array without changing the order of the remaining elements.
Solution Approach
The solution uses a greedy approach. It iterates through the sorted array `nums`, processing each number `x`. For each `x`, it checks if it can extend an existing subsequence (ending in `x-1`). If so, it extends the subsequence by decrementing the count of subsequences ending in `x-1` and incrementing the count of subsequences ending in `x`. If `x` cannot extend an existing subsequence, it checks if a new subsequence of length 3 can be started, by checking for the presence of `x+1` and `x+2`. If so, it decrements their frequencies and adds a new subsequence ending at `x+2`. If neither of these is possible, the array cannot be split as required, and the function returns `false`. If the entire array is processed, and no issues are encountered, the function returns `true`.
Step-by-Step Algorithm
- Step 1: Initialize two frequency counters (hash maps), `freq` and `tails`. `freq` stores the remaining frequency of each number in `nums`. `tails` stores the number of subsequences ending with a particular number.
- Step 2: Iterate through the input array `nums`.
- Step 3: For each number `x`, check if its frequency in `freq` is greater than 0. If not, skip to the next number.
- Step 4: Decrement the frequency of `x` in `freq`.
- Step 5: Check if we can extend an existing subsequence (i.e., a subsequence ending in `x-1`). If `tails[x-1] > 0`, then decrement `tails[x-1]` and increment `tails[x]`.
- Step 6: If we cannot extend an existing subsequence, check if we can start a new subsequence of length 3, by checking if `freq[x+1] > 0` and `freq[x+2] > 0`. If so, decrement `freq[x+1]`, decrement `freq[x+2]`, and increment `tails[x+2]`.
- Step 7: If neither extending an existing subsequence nor starting a new subsequence of length 3 is possible, return `false`.
- Step 8: After iterating through all numbers in `nums`, return `true`.
Key Insights
- Insight 1: The core idea is to greedily extend existing subsequences whenever possible to minimize the creation of new ones, as subsequences must have a length of at least 3.
- Insight 2: Using two hash maps (or frequency counters) is crucial. One (`freq`) tracks the remaining frequency of each number in the input array. The other (`tails`) tracks the number of subsequences ending with a particular number.
- Insight 3: The problem relies on the array being sorted. This allows us to process the numbers in order and greedily extend existing subsequences without needing to backtrack or consider all possible combinations.
Complexity Analysis
Time Complexity: O(n)
Space Complexity: O(n)
Topics
This problem involves: Array, Hash Table, Greedy, Heap (Priority Queue).
Companies
Asked at: PhonePe.