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++ 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> |
No
Time Complexity: O(N*log N)
Auxiliary Space: O(N)