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:
- If K is not a divisor of N, no possible set of required subsequences exist. Hence, print No.
- Store the indices of each integer in a Set data structure. It can be efficiently stored using a map that has the structure of key-set pair.
- Maintain a visited array to keep track of indices that are already included in a subsequence.
- Iterate for each i in the range [0, N), and if the integer at the current index is not already visited, perform the following steps:
- Using the upper_bound function, find the smallest index of arr[i] + 1 in the range [i+1, N) and update the value of the last element of the current subsequence with it.
- Repeat the above-mentioned step K-1 number of times until a complete subsequence of K integers has been created.
- During any iteration, if the required integer does not exist, no possible set of required subsequences exist. Hence, print No. Otherwise, print Yes.
Below is the implementation of the above approach:Â
C++
// 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; } |
Java
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
# 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 |
C#
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__ |
Javascript
<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> |
Â
Â
No
Â
Â
Time Complexity: O(N*log N)
Auxiliary Space: O(N)
Â
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!