Split Array into Consecutive Subsequences of Size K or more

Last Updated : 18 Oct, 2025

Given an integer array arr[] that is sorted in increasing order and an integer k. Check whether it is possible to split arr[] 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 k or more.

Examples:

Input: arr[] = [2, 2, 3, 3, 4, 5], k = 2
Output: true
Explanation: arr can be split into three subsequence of length k - [2, 3], [2, 3], [4, 5].

Input: arr[] = [1, 1, 1, 1, 1], k = 4
Output: false
Explanation: It is impossible to split array into consecutive increasing subsequences of length 4 or more.

Try It Yourself
redirect icon

[Approach] Using MinHeap - O(n log(n)) Time and O(n) Space

The main idea is to use a min-heap and create a pair containing the element and its consecutive count, then push it into the min-heap. As we go through each element:

  • If the element is consecutive to the top element of the heap, we increase its consecutive count.
  • If it’s not consecutive, we check whether the top element’s count is at least k — if yes, we keep it; otherwise, return false.
  • We continue this process of adding pairs and updating counts until all elements are processed.
  • At the end, we ensure that all remaining subsequences in the heap have a length of at least k before returning true.
C++
//Driver Code Starts
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
//Driver Code Ends


bool isPossible(vector<int>& arr, int k) {
    
    auto comp = [](pair<int,int> a, pair<int,int> b) {
        if(a.first == b.first)
        
        // smaller length has higher priority
            return a.second > b.second; 
            
        // smaller number has higher priority
        return a.first > b.first;       
    };
    
    // Min-heap stores pairs:
    //{number, length of subsequence ending with this number}
    priority_queue<pair<int,int>, vector<pair<int,int>>, decltype(comp)> pq(comp);

    int i = 0;
    while(i < arr.size()) {
        if(pq.empty()) {
            
            // If heap is empty, start a new subsequence
            pq.push({arr[i], 1});
            i++;
        }
        else {
            auto top = pq.top();
            if(arr[i] == top.first) {
                
                // If current number same as top, 
                //start a new subsequence
                pq.push({arr[i], 1});
                i++;
            }
            else if(arr[i] == top.first + 1) {
                
                // If current number is consecutive, 
                //extend the subsequence
                pq.pop();
                pq.push({arr[i], top.second + 1});
                i++;
            }
            else {
                
                // If current number is not 
                //consecutive, check if the top subsequence is valid
                if(top.second < k) return false;
                pq.pop();
            }
        }
    }

    // After processing all numbers, 
    //ensure all subsequences have length >= k
    while(!pq.empty()) {
        if(pq.top().second < k) return false;
        pq.pop();
    }

//Driver Code Starts

    return true;
}

int main() {
    vector<int> arr = {2, 2, 3, 3, 4, 5};
    int k = 2;

    if(isPossible(arr, k))
        cout << "true" << endl;
    else
        cout << "false" << endl;

    return 0;
}

//Driver Code Ends
Java
//Driver Code Starts
import java.util.PriorityQueue;
import java.util.Comparator;

class GFG {
//Driver Code Ends


    static boolean isPossible(int[] arr, int k) {

        // Min-heap stores pairs: {number, length of 
        //subsequence ending with this number}
        PriorityQueue<int[]> pq = new PriorityQueue<>(new Comparator<int[]>() {
            public int compare(int[] a, int[] b) {
                if(a[0] == b[0]) 
                    // smaller length has higher priority
                    return a[1] - b[1]; 
                // smaller number has higher priority
                return a[0] - b[0];       
            }
        });

        int i = 0;
        while(i < arr.length) {
            if(pq.isEmpty()) {
                // If heap is empty, start a new subsequence
                pq.add(new int[]{arr[i], 1});
                i++;
            }
            else {
                int[] top = pq.peek();
                if(arr[i] == top[0]) {
                    // If current number same as top, 
                    //start a new subsequence
                    pq.add(new int[]{arr[i], 1});
                    i++;
                }
                else if(arr[i] == top[0] + 1) {
                    // If current number is consecutive, 
                    //extend the subsequence
                    pq.poll();
                    pq.add(new int[]{arr[i], top[1] + 1});
                    i++;
                }
                else {
                    // If current number is not 
                    //consecutive, check if top subsequence is valid
                    if(top[1] < k) return false;
                    pq.poll();
                }
            }
        }

        // After processing all numbers,
        //ensure all subsequences have length >= k
        while(!pq.isEmpty()) {
            if(pq.peek()[1] < k) return false;
            pq.poll();
        }

        return true;
    }


//Driver Code Starts
    public static void main(String[] args) {
        int[] arr = {2, 2, 3, 3, 4, 5};
        int k = 2;

        if(isPossible(arr, k))
            System.out.println("true");
        else
            System.out.println("false");
    }
}

//Driver Code Ends
Python
#Driver Code Starts
import heapq
#Driver Code Ends


def isPossible(arr, k):
    
    # Min-heap stores pairs: (number, length of 
    # subsequence ending with this number)
    pq = []

    i = 0
    while i < len(arr):
        if not pq:
            
            # If heap is empty, start a new subsequence
            heapq.heappush(pq, (arr[i], 1))
            i += 1
        else:
            top = pq[0]
            if arr[i] == top[0]:
                
                # If current number same as top, 
                # start a new subsequence
                heapq.heappush(pq, (arr[i], 1))
                i += 1
            elif arr[i] == top[0] + 1:
                
                # If current number is consecutive,
                # extend the subsequence
                heapq.heappop(pq)
                heapq.heappush(pq, (arr[i], top[1] + 1))
                i += 1
            else:
                
                # If current number is not consecutive
                # check if the top subsequence is valid
                if top[1] < k:
                    return False
                heapq.heappop(pq)

    # After processing all numbers, 
    # ensure all subsequences have length >= k
    while pq:
        if pq[0][1] < k:
            return False
        heapq.heappop(pq)

    return True


#Driver Code Starts

if __name__ == "__main__":
    arr = [2, 2, 3, 3, 4, 5]
    k = 2

    if isPossible(arr, k):
        print("true")
    else:
        print("false")

#Driver Code Ends
C#
//Driver Code Starts
using System;
using System.Collections.Generic;

class Heap {
    private List<Tuple<int,int>> pq = new List<Tuple<int,int>>();

    private bool Compare(Tuple<int,int> a, Tuple<int,int> b) {
        
         // smaller number has higher priority
        if(a.Item1 != b.Item1) return a.Item1 < b.Item1;
            
         // smaller length has higher priority
        return a.Item2 < b.Item2;
    }

    // push the element 
    public void Push(Tuple<int,int> t) {
        pq.Add(t);
        int i = pq.Count - 1;
        while(i > 0) {
            int parent = (i - 1) / 2;
            if(Compare(pq[i], pq[parent])) {
                var temp = pq[i];
                pq[i] = pq[parent];
                pq[parent] = temp;
                i = parent;
            }
            else break;
        }
    }
 
    // pop the element
    public Tuple<int,int> Pop()  {
        if(pq.Count == 0) return null;
        var ret = pq[0];
        pq[0] = pq[pq.Count - 1];
        pq.RemoveAt(pq.Count - 1);

        int i = 0;
        while(true)  {
            int left = 2*i + 1;
            int right = 2*i + 2;
            int smallest = i;

            if(left < pq.Count && Compare(pq[left], pq[smallest])) smallest = left;
            if(right < pq.Count && Compare(pq[right], pq[smallest])) smallest = right;

            if(smallest != i)
            {
                var temp = pq[i];
                pq[i] = pq[smallest];
                pq[smallest] = temp;
                i = smallest;
            }
            else break;
        }
        return ret;
    }

    public Tuple<int,int> Top() {
        return pq.Count > 0 ? pq[0] : null;
    }

    public int Count() => pq.Count;
}


class GFG {
//Driver Code Ends

    
    static bool isPossible(int[] arr, int k) {
        
        // Min-heap stores pairs:
        // {number, length of subsequence ending with this number}
        Heap pq = new Heap();
        int i = 0;

        while(i < arr.Length) {
            
             // If heap is empty, start a new subsequence
            if(pq.Count() == 0) {
                pq.Push(Tuple.Create(arr[i], 1));
                i++;
            }
            else {
                var top = pq.Top();
                
                // If current number same as top, 
                //start a new subsequence
                if(arr[i] == top.Item1) {
                    pq.Push(Tuple.Create(arr[i], 1));
                    i++;
                }
                
                // If current number is consecutive, 
                //extend the subsequenc
                else if(arr[i] == top.Item1 + 1) {
                    var popped = pq.Pop();
                    pq.Push(Tuple.Create(arr[i], popped.Item2 + 1));
                    i++;
                }
                
                  // If current number is not 
                //consecutive, check if the top subsequence is valid
                else {
                    if(top.Item2 < k) return false;
                    pq.Pop();
                }
            }
        }

        // After processing all numbers, 
        //ensure all subsequences have length >= k
        while(pq.Count() > 0) {
                if(pq.Top().Item2 < k) return false;
                pq.Pop();
        }
    
        return true;
    }


//Driver Code Starts
static void Main() {
    int[] arr = {2, 2, 3, 3, 4, 5};
    int k = 2;
    
     if(isPossible(arr, k))
        Console.WriteLine("true");
    else
        Console.WriteLine("false");
    }
}

//Driver Code Ends
JavaScript
//Driver Code Starts
function comparePair(a, b) {
    if (a[0] === b[0]) {
  
        // smaller length has higher priority
        return a[1] - b[1];
    }
    
    // smaller number has higher priority
    return a[0] - b[0];
}

class MinHeap {
    constructor() {
        this.data = [];
    }

    push(item) {
        this.data.push(item);
        this._heapifyUp();
    }

    pop() {
        if (this.data.length === 0) return null;
        if (this.data.length === 1) return this.data.pop();
        const top = this.data[0];
        this.data[0] = this.data.pop();
        this._heapifyDown();
        return top;
    }

    top() {
        return this.data[0] || null;
    }

    size() {
        return this.data.length;
    }

    _heapifyUp() {
        let idx = this.data.length - 1;
        while (idx > 0) {
            let parent = Math.floor((idx - 1) / 2);
            if (comparePair(this.data[parent], this.data[idx]) <= 0) break;
            [this.data[parent], this.data[idx]] = [this.data[idx], this.data[parent]];
            idx = parent;
        }
    }

    _heapifyDown() {
        let idx = 0;
        const length = this.data.length;
        while (true) {
            let left = 2 * idx + 1;
            let right = 2 * idx + 2;
            let smallest = idx;

            if (left < length && comparePair(this.data[left], this.data[smallest]) < 0)
                smallest = left;
            if (right < length && comparePair(this.data[right], this.data[smallest]) < 0)
                smallest = right;

            if (smallest === idx) break;
            [this.data[idx], this.data[smallest]] = [this.data[smallest], this.data[idx]];
            idx = smallest;
        }
    }
}
//Driver Code Ends


function isPossible(arr, k) {
    
    // Min-heap stores pairs: {number, length of subsequence ending with this number}
    const pq = new MinHeap();

    let i = 0;
    while (i < arr.length) {
        if (pq.size() === 0) {
           
            // If heap is empty, start a new subsequence
            pq.push([arr[i], 1]);
            i++;
        } else {
            const top = pq.top();
            if (arr[i] === top[0]) {
              
                // If current number same as top,
                //start a new subsequence
                pq.push([arr[i], 1]);
                i++;
            } else if (arr[i] === top[0] + 1) {
              
                // If current number is consecutive, 
                //extend the subsequence
                pq.pop();
                pq.push([arr[i], top[1] + 1]);
                i++;
            } else {
               
                // If current number is not consecutive,
                //check if the top subsequence is valid
                if (top[1] < k) return false;
                pq.pop();
            }
        }
    }

    // After processing all numbers, 
    //ensure all subsequences have length >= k
    while (pq.size() > 0) {
        const top = pq.pop();
        if (top[1] < k) return false;
    }

    return true;
}


//Driver Code Starts
// Driver code
const arr = [2, 2, 3, 3, 4, 5];
const k = 2;

console.log(isPossible(arr, k) ? "true" : "false");

//Driver Code Ends

Output
true


Comment