Check if given Array can be divided into subsequences of K increasing consecutive integers
Last Updated :
10 Feb, 2023
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++
#include <bits/stdc++.h>
using namespace std;
bool isPossible(vector< int > nums, int K)
{
int N = nums.size();
if (N % K != 0 || K > N) {
return false ;
}
map< int , set< int > > idx;
for ( int i = 0; i < nums.size(); i++) {
idx[nums[i]].insert(i);
}
int visited[N] = { 0 };
int total_visited = 0;
for ( int i = 0; i < nums.size(); i++) {
if (visited[i]) {
continue ;
}
int num = nums[i];
int last_index = i;
visited[i] = 1;
total_visited++;
for ( int j = num + 1; j < num + K; j++) {
if (idx[j].size() == 0) {
return false ;
}
auto it = idx[j].upper_bound(last_index);
if (it == idx[j].end()
|| *it <= last_index) {
return false ;
}
last_index = *it;
visited[last_index] = 1;
total_visited++;
idx[j].erase(it);
}
}
return total_visited == N;
}
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 {
public static boolean isPossible(List<Integer> nums, int K) {
int N = nums.size();
if (N % K != 0 || K > N) {
return false ;
}
Map<Integer, TreeSet<Integer>> idx = new HashMap<>();
for ( int i = 0 ; i < nums.size(); i++) {
idx.computeIfAbsent(nums.get(i), k -> new TreeSet<>()).add(i);
}
boolean [] visited = new boolean [N];
int total_visited = 0 ;
for ( int i = 0 ; i < nums.size(); i++) {
if (visited[i]) {
continue ;
}
int num = nums.get(i);
int last_index = i;
visited[i] = true ;
total_visited++;
for ( int j = num + 1 ; j < num + K; j++) {
if (!idx.containsKey(j) || idx.get(j).size() == 0 ) {
return false ;
}
int next_index = idx.get(j).tailSet(last_index + 1 ).first();
if (next_index <= last_index) {
return false ;
}
last_index = next_index;
visited[last_index] = true ;
total_visited++;
idx.get(j).remove(last_index);
}
}
return total_visited == N;
}
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
def isPossible(nums, K):
N = len (nums)
if (N % K ! = 0 or K > N):
return False
idx = {}
for i in range (N):
if nums[i] in idx:
idx[nums[i]].add(i)
else :
idx[nums[i]] = {i}
visited = [ 0 ] * N
total_visited = 0
for i in range (N):
if (visited[i]):
continue
num = nums[i]
last_index = i
visited[i] = 1
total_visited + = 1
for j in range (num + 1 , num + K):
if j not in idx or len (idx[j]) = = 0 :
return False
temp = False
for it in idx[j]:
if it > last_index:
last_index = it
temp = True
break
if (temp = = False ):
return False
visited[last_index] = 1
total_visited + = 1
idx[j].remove(it)
return total_visited = = N
arr = [ 4 , 3 , 1 , 2 ]
K = 2
if (isPossible(arr, K)):
print ( "Yes" )
else :
print ( "No" )
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
public class GFG
{
public static bool isPossible(List< int > nums, int K)
{
int N = nums.Count;
if (N % K != 0 || K > N) {
return false ;
}
Dictionary< int , SortedSet< int > > idx
= new Dictionary< int , SortedSet< int > >();
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);
}
bool [] visited = new bool [N];
int total_visited = 0;
for ( int i = 0; i < nums.Count; i++) {
if (visited[i]) {
continue ;
}
int num = nums[i];
int last_index = i;
visited[i] = true ;
total_visited++;
for ( int j = num + 1; j < num + K; j++) {
if (!idx.ContainsKey(j)
|| idx[j].Count == 0) {
return false ;
}
int next_index
= idx[j]
.Where(x => x > last_index + 1)
.First();
if (next_index <= last_index) {
return false ;
}
last_index = next_index;
visited[last_index] = true ;
total_visited++;
idx[j].Remove(last_index);
}
}
return total_visited == N;
}
static public void Main()
{
List< int > arr = new List< int >{ 4, 3, 1, 2 };
int K = 2;
Console.WriteLine(isPossible(arr, K) ? "Yes"
: "No" );
}
}
|
Javascript
<script>
function isPossible(nums, K){
let N = nums.length
if (N % K != 0 || K > N)
return false
let idx = new Map()
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)
}
}
let visited = new Array(N).fill(0)
total_visited = 0
for (let i=0;i<N;i++){
if (visited[i])
continue
let num = nums[i]
let last_index = i
visited[i] = 1
total_visited += 1
for (let j=num+1;j<num+K;j++){
if (idx.has(j) == false || idx[j].length == 0)
return false
temp = false
for (let it of idx[j]){
if (it > last_index){
last_index = it
temp = true
break
}
if (temp == false )
return false
}
visited[last_index] = 1
total_visited += 1
idx[j]. delete (it)
}
}
return (total_visited == N)
}
let arr = [4, 3, 1, 2]
let K = 2
if (isPossible(arr, K))
document.write( "Yes" , "</br>" )
else
document.write( "No" , "</br>" )
</script>
|
Time Complexity: O(N*log N)
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...