Open In App

Check if given Array can be divided into subsequences of K increasing consecutive integers

Given an array arr[] of N integers and a positive integer K, the task is to check if it is possible to divide the array into increasing subsequences of K consecutive integers such each element can contribute in only a single subsequence.

Example:



Input: arr[] = {1, 2, 1, 3, 2, 3}, K = 3
Output: Yes
Explanation: The given array can be divided as {1, 2, 1, 3, 2, 3} => {1, 2, 3} and {1, 2, 1, 3, 2, 3} => {1, 2, 3}. Both subsequences have 3 consecutive integers in increasing order.

Input: arr[] = {4, 3, 1, 2}, K = 2
Output: No



 

Approach: The above problem can be solved using a Greedy Approach using Binary Search. It can be observed that for any integer arr[i], the most optimal choice is to choose the smallest index of arr[i] + 1 in the subarray arr[i+1, N). Using this observation, follow the below steps to solve the given problem:

Below is the implementation of the above approach: 




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to check if the array can
// be divided into subsequences of K
// consecutive integers in increasing order
bool isPossible(vector<int> nums, int K)
{
    int N = nums.size();
 
    // If N is not divisible by K or
    // K>N, no possible set of required
    // subsequences exist
    if (N % K != 0 || K > N) {
        return false;
    }
 
    // Stores the indices of each
    // element in a set
    map<int, set<int> > idx;
 
    // Stores the index of each number
    for (int i = 0; i < nums.size(); i++) {
        idx[nums[i]].insert(i);
    }
 
    // Stores if the integer at current
    // index is already included in
    // a subsequence
    int visited[N] = { 0 };
 
    // Stores the count of total
    // visited elements
    int total_visited = 0;
 
    for (int i = 0; i < nums.size(); i++) {
 
        // If current integer is already
        // in a subsequence
        if (visited[i]) {
            continue;
        }
 
        // Stores the value of last element
        // of the current subsequence
        int num = nums[i];
 
        // Stores the index of last element
        // of the current subsequence
        int last_index = i;
 
        // Mark Visited
        visited[i] = 1;
 
        // Increment the visited count
        total_visited++;
 
        // Find the next K-1 elements of the
        // subsequence starting from index i
        for (int j = num + 1; j < num + K; j++) {
 
            // No valid index found
            if (idx[j].size() == 0) {
                return false;
            }
 
            // Find index of j such that it
            // is greater than last_index
            auto it = idx[j].upper_bound(last_index);
 
            // if no such index found,
            // return false
            if (it == idx[j].end()
                || *it <= last_index) {
                return false;
            }
 
            // Update last_index
            last_index = *it;
 
            // Mark current index as visited
            visited[last_index] = 1;
 
            // Increment total_visited by 1
            total_visited++;
 
            // Remove the index from set because
            // it has been already used
            idx[j].erase(it);
        }
    }
 
    // Return the result
    return total_visited == N;
}
 
// Driver Code
int main()
{
    vector<int> arr = { 4, 3, 1, 2 };
    int K = 2;
    cout << (isPossible(arr, K) ? "Yes" : "No");
 
    return 0;
}




import java.util.*;
 
class GFG {
    // Function to check if the array can
    // be divided into subsequences of K
    // consecutive integers in increasing order
    public static boolean isPossible(List<Integer> nums, int K) {
        int N = nums.size();
 
        // If N is not divisible by K or
        // K>N, no possible set of required
        // subsequences exist
        if (N % K != 0 || K > N) {
            return false;
        }
 
        // Stores the indices of each
        // element in a set
        Map<Integer, TreeSet<Integer>> idx = new HashMap<>();
 
        // Stores the index of each number
        for (int i = 0; i < nums.size(); i++) {
            idx.computeIfAbsent(nums.get(i), k -> new TreeSet<>()).add(i);
        }
 
        // Stores if the integer at current
        // index is already included in
        // a subsequence
        boolean[] visited = new boolean[N];
 
        // Stores the count of total
        // visited elements
        int total_visited = 0;
 
        for (int i = 0; i < nums.size(); i++) {
 
            // If current integer is already
            // in a subsequence
            if (visited[i]) {
                continue;
            }
 
            // Stores the value of last element
// of the current subsequence
int num = nums.get(i);
                  // Stores the index of last element
        // of the current subsequence
        int last_index = i;
 
        // Mark Visited
        visited[i] = true;
 
        // Increment the visited count
        total_visited++;
 
        // Find the next K-1 elements of the
        // subsequence starting from index i
        for (int j = num + 1; j < num + K; j++) {
 
            // No valid index found
            if (!idx.containsKey(j) || idx.get(j).size() == 0) {
                return false;
            }
 
            // Find index of j such that it
            // is greater than last_index
            int next_index = idx.get(j).tailSet(last_index + 1).first();
 
            // if no such index found,
            // return false
            if (next_index <= last_index) {
                return false;
            }
 
            // Update last_index
            last_index = next_index;
 
            // Mark current index as visited
            visited[last_index] = true;
 
            // Increment total_visited by 1
            total_visited++;
 
            // Remove the index from set because
            // it has been already used
            idx.get(j).remove(last_index);
        }
    }
 
    // Return the result
    return total_visited == N;
}
 
// Driver Code
public static void main(String[] args) {
    List<Integer> arr = Arrays.asList(4, 3, 1, 2);
    int K = 2;
    System.out.println(isPossible(arr, K) ? "Yes" : "No");
}
}




# Python3 program for the above approach
 
# Function to check if the array can
# be divided into subsequences of K
# consecutive integers in increasing order
def isPossible(nums, K):
    N = len(nums)
     
    # If N is not divisible by K or
    # K>N, no possible set of required
    # subsequences exist
    if (N % K != 0 or K > N):
        return False
       
     # Stores the indices of each
    # element in a set
    idx = {}
     
     # Stores the index of each number
    for i in range(N):
        if nums[i] in idx:
            idx[nums[i]].add(i)
        else:
            idx[nums[i]] = {i}
             
    # Stores if the integer at current
    # index is already included in
    # a subsequence
    visited = [0]*N
     
    # Stores the count of total
    # visited elements
    total_visited = 0
    for i in range(N):
       
        # If current integer is already
        # in a subsequence
        if(visited[i]):
            continue
             
        # Stores the value of last element
        # of the current subsequence
        num = nums[i]
         
        # Stores the index of last element
        # of the current subsequence
        last_index = i
         
        # Marked visited
        visited[i] = 1
         
         # Increment the visited count
        total_visited += 1
         
        # Find the next K-1 elements of the
        # subsequence starting from index i
        for j in range(num+1, num+K):
           
           # No valid index found
            if j not in idx or len(idx[j]) == 0:
                return False
            temp = False
             
            # Find index of j such that it
            # is greater than last_index
            for it in idx[j]:
                if it > last_index:
                    last_index = it
                    temp = True
                    break
            if(temp == False):
                return False
               
            # Update last index
            visited[last_index] = 1
             
            # Mark current index as visited
             
             # Increment total_visited by 1
            total_visited += 1
             
            # Remove the index
            idx[j].remove(it)
             
            # Return the result
    return total_visited == N
 
# Driver code
arr = [4, 3, 1, 2]
K = 2
if (isPossible(arr, K)):
    print("Yes")
else:
    print("No")
     
# This code is contributed by parthmanchanda81




using System;
using System.Collections.Generic;
using System.Linq;
 
public class GFG
{
 
  // Function to check if the array can
  // be divided into subsequences of K
  // consecutive integers in increasing order
  public static bool isPossible(List<int> nums, int K)
  {
    int N = nums.Count;
 
    // If N is not divisible by K or
    // K>N, no possible set of required
    // subsequences exist
    if (N % K != 0 || K > N) {
      return false;
    }
 
 
    // Stores the indices of each
    // element in a set
    Dictionary<int, SortedSet<int> > idx
      = new Dictionary<int, SortedSet<int> >();
 
    // Stores the index of each number
    for (int i = 0; i < nums.Count; i++) {
      if (!idx.ContainsKey(nums[i])) {
        idx.Add(nums[i], new SortedSet<int>());
      }
 
      idx[nums[i]].Add(i);
    }
 
    // Stores if the integer at current
    // index is already included in
    // a subsequence
    bool[] visited = new bool[N];
 
    // Stores the count of total
    // visited elements
    int total_visited = 0;
 
    for (int i = 0; i < nums.Count; i++) {
 
      // If current integer is already
      // in a subsequence
      if (visited[i]) {
        continue;
      }
 
      // Stores the value of last element
      // of the current subsequence
      int num = nums[i];
      // Stores the index of last element
      // of the current subsequence
      int last_index = i;
 
      // Mark Visited
      visited[i] = true;
 
      // Increment the visited count
      total_visited++;
 
      // Find the next K-1 elements of the
      // subsequence starting from index i
      for (int j = num + 1; j < num + K; j++) {
 
        // No valid index found
        if (!idx.ContainsKey(j)
            || idx[j].Count == 0) {
          return false;
        }
 
        // Find index of j such that it
        // is greater than last_index
        int next_index
          = idx[j]
          .Where(x => x > last_index + 1)
          .First();
 
        // if no such index found,
        // return false
        if (next_index <= last_index) {
          return false;
        }
 
        // Update last_index
        last_index = next_index;
 
        // Mark current index as visited
        visited[last_index] = true;
 
        // Increment total_visited by 1
        total_visited++;
 
        // Remove the index from set because
        // it has been already used
        idx[j].Remove(last_index);
      }
    }
 
    // Return the result
    return total_visited == N;
  }
 
  // Driver Code
  static public void Main()
  {
    List<int> arr = new List<int>{ 4, 3, 1, 2 };
    int K = 2;
    Console.WriteLine(isPossible(arr, K) ? "Yes"
                      : "No");
  }
}
 
// This code is contributed by akashish__




<script>
 
// JavaScript program for the above approach
 
// Function to check if the array can
// be divided into subsequences of K
// consecutive integers in increasing order
function isPossible(nums, K){
    let N = nums.length
     
    // If N is not divisible by K or
    // K>N, no possible set of required
    // subsequences exist
    if (N % K != 0 || K > N)
        return false
       
     // Stores the indices of each
    // element in a set
    let idx = new Map()
     
     // Stores the index of each number
    for(let i = 0; i < N; i++){
        if(idx.has(nums[i]))
            idx.get(nums[i]).add(i)
        else{
            idx.set(nums[i],new Set())
            idx.get(nums[i]).add(i)
        }
    }
             
    // Stores if the integer at current
    // index is already included in
    // a subsequence
    let visited = new Array(N).fill(0)
     
    // Stores the count of total
    // visited elements
    total_visited = 0
    for(let i=0;i<N;i++){
       
        // If current integer is already
        // in a subsequence
        if(visited[i])
            continue
             
        // Stores the value of last element
        // of the current subsequence
        let num = nums[i]
         
        // Stores the index of last element
        // of the current subsequence
        let last_index = i
         
        // Marked visited
        visited[i] = 1
         
         // Increment the visited count
        total_visited += 1
         
        // Find the next K-1 elements of the
        // subsequence starting from index i
        for(let j=num+1;j<num+K;j++){
           
           // No valid index found
            if(idx.has(j) == false || idx[j].length == 0)
                return false
            temp = false
             
            // Find index of j such that it
            // is greater than last_index
            for(let it of idx[j]){
                if(it > last_index){
                    last_index = it
                    temp = true
                    break
                }
                if(temp == false)
                    return false
            }
               
            // Update last index
            visited[last_index] = 1
             
            // Mark current index as visited
             
             // Increment total_visited by 1
            total_visited += 1
             
            // Remove the index
            idx[j].delete(it)
             
            // Return the result
        }
    }
    return (total_visited == N)
}
 
// Driver code
let arr = [4, 3, 1, 2]
let K = 2
if (isPossible(arr, K))
    document.write("Yes","</br>")
else
    document.write("No","</br>")
     
// This code is contributed by shinjanpatra
 
</script>

 
 

Output: 
No

 

 

Time Complexity: O(N*log N)
Auxiliary Space: O(N)

 


Article Tags :