Can split array into consecutive subsequences in JavaScript

We are required to write a JavaScript function that takes in an array of sorted integers and determines if we can split it into consecutive subsequences of at least 3 elements each.

Problem Statement

Our function should return true if we can split the array into 1 or more subsequences where each subsequence consists of consecutive integers and has length at least 3, false otherwise.

Input:

const arr = [1, 2, 3, 3, 4, 5];

Expected Output:

true

Explanation: We can split the array into two consecutive subsequences:

1, 2, 3
3, 4, 5

Algorithm Approach

The solution uses a greedy approach with two key data structures:

  • count: Tracks frequency of each number
  • needed: Tracks how many numbers are needed to extend existing subsequences

For each number, we either extend an existing subsequence or start a new one with at least 3 consecutive elements.

Implementation

const arr = [1, 2, 3, 3, 4, 5];

const canSplit = (arr = []) => {
    // Count frequency of each number
    const count = arr.reduce((acc, num) => {
        acc[num] = (acc[num] || 0) + 1;
        return acc;
    }, {});
    
    // Track numbers needed to extend subsequences
    const needed = {};
    
    for (const num of arr) {
        // Skip if this number is already used
        if (count[num] <= 0) {
            continue;
        }
        
        count[num] -= 1;
        
        // Try to extend existing subsequence
        if (needed[num] > 0) {
            needed[num] -= 1;
            needed[num + 1] = (needed[num + 1] || 0) + 1;
        }
        // Try to start new subsequence of length 3
        else if (count[num + 1] > 0 && count[num + 2] > 0) {
            count[num + 1] -= 1;
            count[num + 2] -= 1;
            needed[num + 3] = (needed[num + 3] || 0) + 1;
        }
        // Cannot form valid subsequence
        else {
            return false;
        }
    }
    
    return true;
};

console.log(canSplit(arr));
true

Step-by-Step Execution

Let's trace through the algorithm with [1, 2, 3, 3, 4, 5]:

const arr = [1, 2, 3, 3, 4, 5];

console.log("Initial count:", {1: 1, 2: 1, 3: 2, 4: 1, 5: 1});

// Processing num = 1: Start new subsequence [1,2,3]
// Processing num = 2: Already used in subsequence [1,2,3]
// Processing num = 3: Extend subsequence to [1,2,3,4]
// Processing num = 3: Start new subsequence [3,4,5]
// Processing num = 4: Already used in subsequences
// Processing num = 5: Already used in subsequence [3,4,5]

console.log("Result: All numbers successfully placed in valid subsequences");
Initial count: { '1': 1, '2': 1, '3': 2, '4': 1, '5': 1 }
Result: All numbers successfully placed in valid subsequences

Additional Test Cases

// Test case 1: Valid split
console.log("Test 1:", canSplit([1, 2, 3, 3, 4, 4, 5, 5])); // true

// Test case 2: Invalid - cannot form subsequence of length 3
console.log("Test 2:", canSplit([1, 2, 3, 4, 4, 5])); // false

// Test case 3: Valid - single long subsequence
console.log("Test 3:", canSplit([1, 2, 3, 4, 5])); // true
Test 1: true
Test 2: false  
Test 3: true

Time and Space Complexity

  • Time Complexity: O(n) where n is the length of the array
  • Space Complexity: O(k) where k is the number of unique elements

Conclusion

This greedy algorithm efficiently determines if an array can be split into consecutive subsequences of length ? 3. It prioritizes extending existing subsequences over creating new ones, ensuring optimal partitioning.

Updated on: 2026-03-15T23:19:00+05:30

311 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements