Talentd
FleetCode
Make and follow sheets.Sign in

Split Array into Consecutive Subsequences solution and explanation

MediumArrayGreedyHash TableHeap (Priority Queue)5 min read52.7% acceptanceUpdated 9 Apr 2026
Arrays | Leetcode 659 | Split Array Into Consecutive SubsequencesNideesh Terapalli · 16:20 · 21K viewsWatch on YouTube
9 more videos on this problem
  1. Arrays | Leetcode 659 | Split Array Into Consecutive SubsequencesNideesh Terapalli · 16:20 · 21K views
  2. LeetCode 659. Split Array into Consecutive Subsequences v1Happy Coding · 13:12 · 12K views
  3. Leetcode 659 Split Array into Consecutive Subsequences | SDE preparation Sheet link belowCoding Decoded · 16:57 · 10K views
  4. Split Array into Consecutive Subsequences || Leetcode Daily ChallengeCodeFreaks · 13:59 · 5K views
  5. Daily Leetcode #871: Aug 19, 2022 - 659. Split Array into Consecutive SubsequencesProgramming Live with Larry · 10:59 · 2K views
  6. LeetCode 659. Split Array into Consecutive Subsequences v2Happy Coding · 16:24 · 2K views
  7. 659. Split Array into Consecutive Subsequences | English | MediumSimple Code - 단순코드 · 11:10 · 1K views
  8. Split Array Subsequences | GFG POTD TODAY 24 Oct | JAVA/C++ | LeetCode 659Akshay Anil · 18:31 · 1K views
  9. 659. Split Array into Consecutive Subsequences || Medium || August Daily ChallengeCoding with Jenish · 16:32 · 981 views
  10. leetcode 659 Split Array into Consecutive SubsequencesGradCode · 39:42 · 916 views

The problem

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 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.

Approach overview

Problem Overview: You receive a sorted integer array and must determine whether it can be split into one or more subsequences of consecutive integers, each with length at least 3. Every element must belong to exactly one subsequence.

Approach 1: Greedy Hash Map (Iterative) (Time: O(n), Space: O(n))

This approach uses two hash maps. The first map freq tracks how many times each number appears. The second map need tracks how many subsequences are currently waiting for a specific next number. Iterate through the array and try to append the current number to an existing subsequence if need[num] > 0. If not possible, attempt to start a new subsequence using num, num+1, num+2 by checking their counts in freq. If neither option works, forming valid subsequences is impossible. The greedy insight: always extend an existing subsequence before creating a new one. This avoids leaving short sequences that cannot reach length 3. This method heavily relies on fast hash table lookups and is the standard optimal solution using a greedy strategy.

Approach 2: Min-Heap Tracking Subsequence Lengths (Time: O(n log n), Space: O(n))

Another strategy maintains active subsequences using a min-heap. Each heap entry represents a subsequence ending at a specific value and stores its length. When processing a number, check if there is a subsequence ending at num - 1. If one exists, extend the shortest such subsequence (pop from heap, increment length, push back with new end). If none exists, start a new subsequence of length 1. After processing all numbers, verify that every subsequence has length at least 3. The heap ensures the shortest subsequence grows first, which prevents invalid short chains. This technique demonstrates how a priority queue can manage competing subsequences efficiently.

Approach 3: Recursive Backtracking (Time: Exponential worst-case, Space: O(n))

A recursive solution tries to build subsequences by deciding where each number should go. Maintain partial subsequences and recursively attempt to extend them or start new ones. Each recursive branch chooses a subsequence whose last element is num - 1 or creates a new sequence. Pruning occurs when a sequence cannot possibly reach length 3. While conceptually simple, the branching factor grows quickly, leading to exponential time in the worst case. This method mainly helps illustrate the problem constraints before discovering the greedy pattern.

Recommended for interviews: The greedy hash map solution is what interviewers expect. It demonstrates recognition of the greedy invariant (extend existing subsequences first) and efficient use of frequency counting with hash maps. Discussing the heap method also shows strong understanding of alternative designs, but the O(n) greedy approach is considered the optimal answer.

Approach 1: Approach 1: Iterative Solution

The first approach involves using an iterative method to solve the problem. This generally involves using loops to traverse and manage the input data while making use of auxiliary data structures to optimize the solution.

def iterative_solution(arr):
    for i in arr:
        print(i, end=' ')
public void iterativeSolution(int[] arr) {
    for (int i = 0; i < arr.length; i++) {
        System.out.print(arr[i] + " ");
    }
}
#include <iostream>
void iterativeSolution(std::vector<int>& arr) {
    for (int i = 0; i < arr.size(); ++i) {
        std::cout << arr[i] << " ";
    }
}
function iterativeSolution(arr) {
    arr.forEach(num => console.log(num));
}
#include <stdio.h>
void iterativeSolution(int arr[], int n) {
    // Example iteration
    for (int i = 0; i < n; i++) {
        printf("%d ", arr[i]);
    }
}
void IterativeSolution(int[] arr) {
    foreach (var num in arr) {
        Console.Write(num + " ");
    }
}

The Python implementation uses a simple loop to iterate over the list and print each element. Modify the loop body to adjust the functionality as needed.

Complexity

Time Complexity: O(n), where n is the number of elements in the list.
Space Complexity: O(1).

Try this approach in the editor

Approach 2: Approach 2: Recursive Solution

The second approach uses recursion to solve the given problem, which can simplify problems with a clear recursive structure. This involves a base case and a recursive call that processes a subset of the data.

def recursive_solution(arr, index=0):
    if index < len(arr):
        print(arr[index], end=' ')
        recursive_solution(arr, index + 1)
public void recursiveSolution(int[] arr, int index) {
    if (index < arr.length) {
        System.out.print(arr[index] + " ");
        recursiveSolution(arr, index + 1);
    }
}
#include <iostream>
void recursiveSolution(std::vector<int>& arr, int index) {
    if (index < arr.size()) {
        std::cout << arr[index] << " ";
        recursiveSolution(arr, index + 1);
    }
}
function recursiveSolution(arr, index = 0) {
    if (index < arr.length) {
        console.log(arr[index]);
        recursiveSolution(arr, index + 1);
    }
}
#include <stdio.h>
void recursiveSolution(int arr[], int index, int n) {
    if (index < n) {
        printf("%d ", arr[index]);
        recursiveSolution(arr, index + 1, n);
    }
}
void RecursiveSolution(int[] arr, int index) {
    if (index < arr.Length) {
        Console.Write(arr[index] + " ");
        RecursiveSolution(arr, index + 1);
    }
}

In Python, recursion is used to print elements of the list. It stops when the index reaches the length of the list.

Complexity

Time Complexity: O(n).
Space Complexity: O(n) due to recursion stack frames.

Try this approach in the editor

Approach 3: Default Approach

func isPossible(nums []int) bool {
	d := map[int]*hp{}
	for _, v := range nums {
		if d[v] == nil {
			d[v] = new(hp)
		}
		if h := d[v-1]; h != nil {
			heap.Push(d[v], heap.Pop(h).(int)+1)
			if h.Len() == 0 {
				delete(d, v-1)
			}
		} else {
			heap.Push(d[v], 1)
		}
	}
	for _, q := range d {
		if q.IntSlice[0] < 3 {
			return false
		}
	}
	return true
}

type hp struct{ sort.IntSlice }

func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() any {
	a := h.IntSlice
	v := a[len(a)-1]
	h.IntSlice = a[:len(a)-1]
	return v
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Approach 1: Iterative Solution

Time Complexity: O(n), where n is the number of elements in the list.
Space Complexity: O(1).

Approach 2: Recursive Solution

Time Complexity: O(n).
Space Complexity: O(n) due to recursion stack frames.

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Greedy with Hash MapsO(n)O(n)Best general solution. Optimal for sorted arrays with frequent lookups.
Min-Heap Subsequence TrackingO(n log n)O(n)Useful when explicitly tracking subsequence lengths or demonstrating heap usage.
Recursive BacktrackingExponentialO(n)Educational approach to explore all placements before discovering greedy optimization.

Frequently asked questions

Is Split Array into Consecutive Subsequences easy or hard?

The problem is rated Medium on LeetCode but often feels tricky because the greedy rule is not obvious at first. Once the idea of prioritizing extension of existing subsequences is understood, the implementation becomes straightforward with hash maps.

Split Array into Consecutive Subsequences Python/Java solution

Python and Java implementations typically follow the greedy hash map approach using dictionaries or HashMaps. Track freq and need maps, iterate through the array, extend existing subsequences first, and only create new subsequences when the next two numbers are available.

How to solve Split Array into Consecutive Subsequences in O(n)?

Maintain two maps: freq[num] for remaining occurrences and need[num] for subsequences waiting for that number. Iterate through the array. If need[num] > 0, extend that subsequence. Otherwise check if freq[num+1] and freq[num+2] exist to start a new sequence. Update counts accordingly. If neither option works, return false.

What is the best approach for Split Array into Consecutive Subsequences?

The optimal approach is a greedy algorithm using two hash maps: one for remaining frequencies and one for subsequences expecting the next value. For each number, extend an existing subsequence if possible; otherwise start a new sequence of length three. This runs in O(n) time with O(n) space and is the standard solution used in most editorial explanations.

Is Split Array into Consecutive Subsequences asked at Google/Amazon/Meta?

This problem appears in interview preparation lists for companies like Google, Amazon, and Meta because it tests greedy reasoning with hash maps and sequence construction. Variations involving interval extension or sequence grouping are also common in backend and systems interviews.

What data structure is used in Split Array into Consecutive Subsequences?

The most common implementation uses hash maps to track element frequencies and subsequence requirements. Some alternative solutions use a min-heap (priority queue) to track the lengths of active subsequences ending at each value.

What is the time complexity of Split Array into Consecutive Subsequences?

The optimal greedy hash map solution runs in O(n) time because each element is processed once and hash lookups are constant time. Space complexity is O(n) to store frequency counts and subsequence expectations. Heap-based alternatives run in O(n log n).

Comments

Now write it yourselfClose this page and solve Split Array into Consecutive Subsequences in the editor, without looking.
Practise Split Array into Consecutive Subsequences