Given an array arr[] containing n integers. The problem is to count number of increasing subsequences in the array of size k.
Examples:
Input : arr[] = {2, 6, 4, 5, 7},
k = 3
Output : 5
The subsequences of size '3' are:
{2, 6, 7}, {2, 4, 5}, {2, 4, 7},
{2, 5, 7} and {4, 5, 7}.
Input : arr[] = {12, 8, 11, 13, 10, 15, 14, 16, 20},
k = 4
Output : 39
Approach: The idea is to use Dynamic Programming by define 2D matrix, say dp[][]. dp[i][j] stores the count of increasing subsequences of size i ending with element arr[j]. So dp[i][j] can be defined as:
dp[i][j] = 1, where i = 1 and 1 <= j <= n
dp[i][j] = sum(dp[i-1][j]), where 1 < i <= k, i <= j <= n and arr[m] < arr[j] for (i-1) <= m < j.
Below is the implementation of above approach:
// C++ implementation to count number of // increasing subsequences of size k #include <bits/stdc++.h> using namespace std;
// function to count number of increasing // subsequences of size k int numOfIncSubseqOfSizeK( int arr[], int n, int k)
{ int dp[k][n], sum = 0;
memset (dp, 0, sizeof (dp));
// count of increasing subsequences of size 1
// ending at each arr[i]
for ( int i = 0; i < n; i++)
dp[0][i] = 1;
// building up the matrix dp[][]
// Here 'l' signifies the size of
// increasing subsequence of size (l+1).
for ( int l = 1; l < k; l++) {
// for each increasing subsequence of size 'l'
// ending with element arr[i]
for ( int i = l; i < n; i++) {
// count of increasing subsequences of size 'l'
// ending with element arr[i]
dp[l][i] = 0;
for ( int j = l - 1; j < i; j++) {
if (arr[j] < arr[i])
dp[l][i] += dp[l - 1][j];
}
}
}
// sum up the count of increasing subsequences of
// size 'k' ending at each element arr[i]
for ( int i = k - 1; i < n; i++)
sum += dp[k - 1][i];
// required number of increasing
// subsequences of size k
return sum;
} // Driver program to test above int main()
{ int arr[] = { 12, 8, 11, 13, 10, 15, 14, 16, 20 };
int n = sizeof (arr) / sizeof (arr[0]);
int k = 4;
cout << "Number of Increasing Subsequences of size "
<< k << " = " << numOfIncSubseqOfSizeK(arr, n, k);
return 0;
} |
//Java implementation to count number of // increasing subsequences of size k class GFG {
// function to count number of increasing // subsequences of size k static int numOfIncSubseqOfSizeK( int arr[], int n, int k) {
int dp[][] = new int [k][n], sum = 0 ;
// count of increasing subsequences of size 1
// ending at each arr[i]
for ( int i = 0 ; i < n; i++) {
dp[ 0 ][i] = 1 ;
}
// building up the matrix dp[][]
// Here 'l' signifies the size of
// increasing subsequence of size (l+1).
for ( int l = 1 ; l < k; l++) {
// for each increasing subsequence of size 'l'
// ending with element arr[i]
for ( int i = l; i < n; i++) {
// count of increasing subsequences of size 'l'
// ending with element arr[i]
dp[l][i] = 0 ;
for ( int j = l - 1 ; j < i; j++) {
if (arr[j] < arr[i]) {
dp[l][i] += dp[l - 1 ][j];
}
}
}
}
// sum up the count of increasing subsequences of
// size 'k' ending at each element arr[i]
for ( int i = k - 1 ; i < n; i++) {
sum += dp[k - 1 ][i];
}
// required number of increasing
// subsequences of size k
return sum;
}
// Driver program to test above public static void main(String[] args) {
int arr[] = { 12 , 8 , 11 , 13 , 10 , 15 , 14 , 16 , 20 };
int n = arr.length;
int k = 4 ;
System.out.print( "Number of Increasing Subsequences of size "
+ k + " = " + numOfIncSubseqOfSizeK(arr, n, k));
}
} // This code is contributed by 29AjayKumar |
# Python3 implementation to count number # of increasing subsequences of size k import math as mt
# function to count number of increasing # subsequences of size k def numOfIncSubseqOfSizeK(arr, n, k):
dp = [[ 0 for i in range (n)]
for i in range (k)]
# count of increasing subsequences
# of size 1 ending at each arr[i]
for i in range (n):
dp[ 0 ][i] = 1
# building up the matrix dp[][]
# Here 'l' signifies the size of
# increasing subsequence of size (l+1).
for l in range ( 1 , k):
# for each increasing subsequence of
# size 'l' ending with element arr[i]
for i in range (l, n):
# count of increasing subsequences of
# size 'l' ending with element arr[i]
dp[l][i] = 0
for j in range (l - 1 , i):
if (arr[j] < arr[i]):
dp[l][i] + = dp[l - 1 ][j]
# Sum up the count of increasing subsequences
# of size 'k' ending at each element arr[i]
Sum = 0
for i in range (k - 1 , n):
Sum + = dp[k - 1 ][i]
# required number of increasing
# subsequences of size k
return Sum
# Driver Code arr = [ 12 , 8 , 11 , 13 , 10 ,
15 , 14 , 16 , 20 ]
n = len (arr)
k = 4
print ( "Number of Increasing Subsequences of size" ,
k, "=" , numOfIncSubseqOfSizeK(arr, n, k))
# This code is contributed by # Mohit kumar 29 |
// C# implementation to count number of // increasing subsequences of size k using System;
public class GFG {
// function to count number of increasing // subsequences of size k static int numOfIncSubseqOfSizeK( int []arr, int n, int k) {
int [,]dp = new int [k,n]; int sum = 0;
// count of increasing subsequences of size 1
// ending at each arr[i]
for ( int i = 0; i < n; i++) {
dp[0,i] = 1;
}
// building up the matrix dp[,]
// Here 'l' signifies the size of
// increasing subsequence of size (l+1).
for ( int l = 1; l < k; l++) {
// for each increasing subsequence of size 'l'
// ending with element arr[i]
for ( int i = l; i < n; i++) {
// count of increasing subsequences of size 'l'
// ending with element arr[i]
dp[l,i] = 0;
for ( int j = l - 1; j < i; j++) {
if (arr[j] < arr[i]) {
dp[l,i] += dp[l - 1,j];
}
}
}
}
// sum up the count of increasing subsequences of
// size 'k' ending at each element arr[i]
for ( int i = k - 1; i < n; i++) {
sum += dp[k - 1,i];
}
// required number of increasing
// subsequences of size k
return sum;
}
// Driver program to test above public static void Main() {
int []arr = {12, 8, 11, 13, 10, 15, 14, 16, 20};
int n = arr.Length;
int k = 4;
Console.Write( "Number of Increasing Subsequences of size "
+ k + " = " + numOfIncSubseqOfSizeK(arr, n, k));
}
} // This code is contributed by 29AjayKumar |
<script> // JavaScript implementation to count number of // increasing subsequences of size k // function to count number of increasing // subsequences of size k function numOfIncSubseqOfSizeK(arr, n, k)
{
let dp = new Array(k), sum = 0;
// Loop to create 2D array using 1D array
for (let i = 0; i < dp.length; i++) {
dp[i] = new Array(2);
}
// count of increasing subsequences of size 1
// ending at each arr[i]
for (let i = 0; i < n; i++) {
dp[0][i] = 1;
}
// building up the matrix dp[][]
// Here 'l' signifies the size of
// increasing subsequence of size (l+1).
for (let l = 1; l < k; l++) {
// for each increasing subsequence of size 'l'
// ending with element arr[i]
for (let i = l; i < n; i++) {
// count of increasing subsequences of size 'l'
// ending with element arr[i]
dp[l][i] = 0;
for (let j = l - 1; j < i; j++) {
if (arr[j] < arr[i]) {
dp[l][i] += dp[l - 1][j];
}
}
}
}
// sum up the count of increasing subsequences of
// size 'k' ending at each element arr[i]
for (let i = k - 1; i < n; i++) {
sum += dp[k - 1][i];
}
// required number of increasing
// subsequences of size k
return sum;
}
// Driver code let arr = [12, 8, 11, 13, 10, 15, 14, 16, 20];
let n = arr.length;
let k = 4;
document.write( "Number of Increasing Subsequences of size "
+ k + " = " + numOfIncSubseqOfSizeK(arr, n, k));
</script> |
<?php // PHP implementation to count // number of increasing // subsequences of size k // function to count number // of increasing subsequences // of size k function numOfIncSubseqOfSizeK( $arr ,
$n , $k )
{ $dp = array ( array ());
$sum = 0;
$dp = array_fill (0, $n + 1, false);
// count of increasing
// subsequences of size 1
// ending at each arr[i]
for ( $i = 0; $i < $n ; $i ++)
$dp [0][ $i ] = 1;
// building up the matrix
// dp[][]. Here 'l' signifies
// the size of increasing
// subsequence of size (l+1).
for ( $l = 1; $l < $k ; $l ++)
{
// for each increasing
// subsequence of size 'l'
// ending with element arr[i]
for ( $i = $l ; $i < $n ; $i ++)
{
// count of increasing
// subsequences of size 'l'
// ending with element arr[i]
$dp [ $l ][ $i ] = 0;
for ( $j = $l - 1; $j < $i ; $j ++)
{
if ( $arr [ $j ] < $arr [ $i ])
$dp [ $l ][ $i ] += $dp [ $l - 1][ $j ];
}
}
}
// sum up the count of increasing
// subsequences of size 'k' ending
// at each element arr[i]
for ( $i = $k - 1; $i < $n ; $i ++)
$sum += $dp [ $k - 1][ $i ];
// required number of increasing
// subsequences of size k
return $sum ;
} // Driver Code $arr = array (12, 8, 11, 13,
10, 15, 14, 16, 20);
$n = sizeof( $arr );
$k = 4;
echo "Number of Increasing " .
"Subsequences of size " ,
$k , " = " ,
numOfIncSubseqOfSizeK( $arr ,
$n , $k );
// This code is contributed // by akt_mit ?> |
Number of Increasing Subsequences of size 4 = 39
Time Complexity: O(kn2).
Auxiliary Space: O(kn).
Segment Tree Approach
For every element arr[i], we need to search for all arr[i]-1 as these are the elements that can be appended to arr[i] to make increasing subsequence. This is very much similar to COUNT LONGEST INCREASING SUBSEQUENCES. We use a vector of size K for each node in segment Tree signifying the length of LIS of size K ending at node.
Stepping down the array to smaller numbers with same ordering will reduce the space complexity as well.
If arr[i] has vector K={1,3,2}, signifies there is one K=1 length LIS ending at arr[i]
three K=2 length LIS ending at arr[i]
two K=3 length LIS ending at arr[i]
If arr[j] is greater than arr[i], then arr[j] can appended after arr[i]. So the vector of arr[j] becomes {1,1,3}.
The K=1 remains the same since every element itself is a single length(K=1) subsequence.
We will take subsequences of length K=1 from arr[i] in the K=2 of arr[j] Since all the K=1 increasing subsequences of arr[i] becomes K=2 length increasing subsequences when arr[j] is added to arr[i].
Similarly all the K=2 length subsequences of arr[i] becomes K=3 length subsequences for arr[j] as arr[j] gets appended to K=2 subsequences of arr[i]. We are not adding here, because we are calculating ways, not length.
Simply saying vec_j[K]=vec_i[K-1], where K>1
Below is the implementation of above approach:
#include <bits/stdc++.h> using namespace std;
vector<vector< long long >>tree; /* vector<long long> represents the number of ways
LIS of size K ending at node can be formed */
int RANKER(vector< int >& arr) {
int n = arr.size();
vector< int > temp = arr;
sort(temp.begin(), temp.end());
unordered_map< int , int > mpp;
int mx = 0;
for ( int i = 0; i < n; i++) {
if (mpp.find(temp[i]) == mpp.end()) {
mpp[temp[i]] = mx;
mx++;
}
}
for ( int i = 0; i < n; i++) {
arr[i] = mpp[arr[i]];
}
return mx;
} vector< long long > summation(vector< long long >& left, vector< long long >& right, int k) {
// ADD WAYS, REMEMBER NO NEED TO TAKE MAX, WE ARE FINDING WAYS, NOT LENGTH.
// So each K will contribute to final answer
vector< long long > res(k + 1, 0);
for ( int i = 1; i <= k; i++) {
res[i] = left[i] + right[i];
}
return res;
} vector< long long > query( int start, int end, int parent, int qstart, int qend, int k) {
if (end < qstart || qend < start) {
return vector< long long >(k + 1, 0);
}
if (qstart <= start && qend >= end) {
return tree[parent];
}
int mid = (start + end) / 2;
vector< long long > left = query(start, mid, 2 * parent + 1, qstart, qend, k);
vector< long long > right = query(mid + 1, end, 2 * parent + 2, qstart, qend, k);
return summation(left, right, k);
} void update( int start, int end, int parent, int index, vector< long long >& updateThis, int k) {
if (index < start || index > end) {
return ;
}
if (start == end) {
tree[parent] = summation(updateThis, tree[parent], k);
return ;
}
int mid = (start + end) / 2;
if (index > mid) {
update(mid + 1, end, 2 * parent + 2, index, updateThis, k);
}
else {
update(start, mid, 2 * parent + 1, index, updateThis, k);
}
vector< long long > left = tree[2 * parent + 1];
vector< long long > right = tree[2 * parent + 2];
tree[parent] = summation(left, right, k);
return ;
} int numOfIncSubseqOfSizeK(vector< int >& arr, int K) {
int n = arr.size();
int mx = RANKER(arr);
tree.resize(4 * mx + 1, vector< long long >(K + 1, 0));
for ( int i = 0; i < n; i++) {
vector< long long > Kj(K + 1, 0); // K length ways
Kj[1] = 1; // K=1 is element itself
if (arr[i] > 0) { // arr[0] cannot be queried, since its the lowest
/* Querying the longest LIS K array where arr[i] can append to*/
vector< long long > Ki = query(0, mx, 0, 0, arr[i] - 1, K);
for ( int k = 2; k <= K; k++) { // As explained before
Kj[k] = Ki[k - 1];
}
}
update(0, mx, 0, arr[i], Kj, K); // update Kj array for arr[i]
}
return tree[0][K]; // answer is at kth index of root's K array
} int main() {
vector< int > arr = { 12, 8, 11, 13, 10, 15, 14, 16, 20 };
int k = 4;
cout << "Number of Increasing Subsequences of size "
<< k << " = " << numOfIncSubseqOfSizeK(arr, k);
return 0;
} // Code by RainX (ABHIJIT ROY, NIT AGARTALA) |
// Java program for the above approach import java.util.*;
public class GFG {
static List<List<Long> > tree
= new ArrayList<>(); /* List of Lists, where each
inner List represents the
number of ways
LIS of size K ending at
node can be formed */
public static void main(String[] args)
{
List<Integer> arr = Arrays.asList( 12 , 8 , 11 , 13 , 10 ,
15 , 14 , 16 , 20 );
int k = 4 ;
System.out.println(
"Number of Increasing Subsequences of size " + k
+ " = " + numOfIncSubseqOfSizeK(arr, k));
}
// Function to convert original array to ranks
static int RANKER(List<Integer> arr)
{
int n = arr.size();
List<Integer> temp = new ArrayList<>(arr);
temp.sort(Comparator.naturalOrder());
Map<Integer, Integer> mpp = new HashMap<>();
int mx = 0 ;
for ( int i = 0 ; i < n; i++) {
if (!mpp.containsKey(temp.get(i))) {
mpp.put(temp.get(i), mx);
mx++;
}
}
for ( int i = 0 ; i < n; i++) {
arr.set(i, mpp.get(arr.get(i)));
}
return mx;
}
// Function to add ways of two sets of LIS
static List<Long> summation(List<Long> left,
List<Long> right, int k)
{
// ADD WAYS, REMEMBER NO NEED TO TAKE MAX, WE ARE
// FINDING WAYS, NOT LENGTH. So each K will
// contribute to the final answer
List<Long> res = new ArrayList<>(
Collections.nCopies(k + 1 , 0L));
for ( int i = 1 ; i <= k; i++) {
res.set(i, left.get(i) + right.get(i));
}
return res;
}
// Function to perform a range query in the segment tree
static List<Long> query( int start, int end, int parent,
int qstart, int qend, int k)
{
if (end < qstart || qend < start) {
return new ArrayList<>(
Collections.nCopies(k + 1 , 0L));
}
if (qstart <= start && qend >= end) {
return tree.get(parent);
}
int mid = (start + end) / 2 ;
List<Long> left = query(start, mid, 2 * parent + 1 ,
qstart, qend, k);
List<Long> right = query(
mid + 1 , end, 2 * parent + 2 , qstart, qend, k);
return summation(left, right, k);
}
// Function to update the segment tree after processing
// an element
static void update( int start, int end, int parent,
int index, List<Long> updateThis,
int k)
{
if (index < start || index > end) {
return ;
}
if (start == end) {
tree.set(
parent,
summation(updateThis, tree.get(parent), k));
return ;
}
int mid = (start + end) / 2 ;
if (index > mid) {
update(mid + 1 , end, 2 * parent + 2 , index,
updateThis, k);
}
else {
update(start, mid, 2 * parent + 1 , index,
updateThis, k);
}
List<Long> left = tree.get( 2 * parent + 1 );
List<Long> right = tree.get( 2 * parent + 2 );
tree.set(parent, summation(left, right, k));
}
// Main function to calculate the number of increasing
// subsequences of size K
static long numOfIncSubseqOfSizeK(List<Integer> arr,
int K)
{
int n = arr.size();
int mx = RANKER(arr);
tree = new ArrayList<>(Collections.nCopies(
4 * mx + 1 , new ArrayList<>(Collections.nCopies(
K + 1 , 0L))));
for ( int i = 0 ; i < n; i++) {
List<Long> Kj = new ArrayList<>(
Collections.nCopies(K + 1 , 0L));
Kj.set( 1 , 1L);
if (arr.get(i) > 0 ) {
List<Long> Ki
= query( 0 , mx, 0 , 0 , arr.get(i) - 1 , K);
for ( int k = 2 ; k <= K; k++) {
Kj.set(k, Ki.get(k - 1 ));
}
}
update( 0 , mx, 0 , arr.get(i), Kj, K);
}
return tree.get( 0 ).get(
K); // answer is at kth index of root's K array
}
} // This code is contributed by Susobhan Akhuli |
from typing import List , Dict
tree = []
def RANKER(arr: List [ int ]) - > int :
n = len (arr)
temp = arr.copy()
temp.sort()
mpp = {}
mx = 0
for i in range (n):
if temp[i] not in mpp:
mpp[temp[i]] = mx
mx + = 1
for i in range (n):
arr[i] = mpp[arr[i]]
return mx
def summation(left: List [ int ], right: List [ int ], k: int ) - > List [ int ]:
# ADD WAYS, REMEMBER NO NEED TO TAKE MAX, WE ARE FINDING WAYS, NOT LENGTH.
# So each K will contribute to final answer
res = [ 0 ] * (k + 1 )
for i in range ( 1 , k + 1 ):
res[i] = left[i] + right[i]
return res
def query(start: int , end: int , parent: int , qstart: int , qend: int , k: int ) - > List [ int ]:
if end < qstart or qend < start:
return [ 0 ] * (k + 1 )
if qstart < = start and qend > = end:
return tree[parent]
mid = (start + end) / / 2
left = query(start, mid, 2 * parent + 1 , qstart, qend, k)
right = query(mid + 1 , end, 2 * parent + 2 , qstart, qend, k)
return summation(left, right, k)
def update(start: int , end: int , parent: int , index: int , updateThis: List [ int ], k: int ) - > None :
if index < start or index > end:
return
if start = = end:
tree[parent] = summation(updateThis, tree[parent], k)
return
mid = (start + end) / / 2
if index > mid:
update(mid + 1 , end, 2 * parent + 2 , index, updateThis, k)
else :
update(start, mid, 2 * parent + 1 , index, updateThis, k)
left = tree[ 2 * parent + 1 ]
right = tree[ 2 * parent + 2 ]
tree[parent] = summation(left, right, k)
return
def numOfIncSubseqOfSizeK(arr: List [ int ], K: int ) - > int :
n = len (arr)
mx = RANKER(arr)
global tree
tree = [[ 0 ] * (K + 1 ) for _ in range ( 4 * mx + 1 )]
for i in range (n):
# K length ways
Kj = [ 0 ] * (K + 1 )
# K=1 is element itself
Kj[ 1 ] = 1
# arr[0] cannot be queried, since its the lowest
if arr[i] > 0 :
# Querying the longest LIS K array where arr[i] can append to
Ki = query( 0 , mx, 0 , 0 , arr[i] - 1 , K)
# As explained before
for k in range ( 2 , K + 1 ):
Kj[k] = Ki[k - 1 ]
# update Kj array for arr[i]
update( 0 , mx, 0 , arr[i], Kj, K)
# answer is at kth index of root's K array
return tree[ 0 ][K]
if __name__ = = '__main__' :
arr = [ 12 , 8 , 11 , 13 , 10 , 15 , 14 , 16 , 20 ]
k = 4
print ( "Number of Increasing Subsequences of size" , k, "=" , numOfIncSubseqOfSizeK(arr, k))
# This code is contributed by shivhack999 |
// C# program for the above approach using System;
using System.Collections.Generic;
using System.Linq;
public class GFG
{ static List<List< long >> tree; /* List<long> represents the number of ways
LIS of size K ending at node can be formed */
static int RANKER(List< int > arr)
{
int n = arr.Count;
List< int > temp = new List< int >(arr);
temp.Sort();
Dictionary< int , int > mpp = new Dictionary< int , int >();
int mx = 0;
for ( int i = 0; i < n; i++)
{
if (!mpp.ContainsKey(temp[i]))
{
mpp[temp[i]] = mx;
mx++;
}
}
for ( int i = 0; i < n; i++)
{
arr[i] = mpp[arr[i]];
}
return mx;
}
static List< long > Summation(List< long > left, List< long > right, int k)
{
// ADD WAYS, REMEMBER NO NEED TO TAKE MAX, WE ARE FINDING WAYS, NOT LENGTH.
// So each K will contribute to the final answer
List< long > res = new List< long >( new long [k + 1]);
for ( int i = 1; i <= k; i++)
{
res[i] = left[i] + right[i];
}
return res;
}
static List< long > Query( int start, int end, int parent, int qstart, int qend, int k)
{
if (end < qstart || qend < start)
{
return new List< long >( new long [k + 1]);
}
if (qstart <= start && qend >= end)
{
return tree[parent];
}
int mid = (start + end) / 2;
List< long > left = Query(start, mid, 2 * parent + 1, qstart, qend, k);
List< long > right = Query(mid + 1, end, 2 * parent + 2, qstart, qend, k);
return Summation(left, right, k);
}
static void Update( int start, int end, int parent, int index, List< long > updateThis, int k)
{
if (index < start || index > end)
{
return ;
}
if (start == end)
{
tree[parent] = Summation(updateThis, tree[parent], k);
return ;
}
int mid = (start + end) / 2;
if (index > mid)
{
Update(mid + 1, end, 2 * parent + 2, index, updateThis, k);
}
else
{
Update(start, mid, 2 * parent + 1, index, updateThis, k);
}
List< long > left = tree[2 * parent + 1];
List< long > right = tree[2 * parent + 2];
tree[parent] = Summation(left, right, k);
return ;
}
static int NumOfIncSubseqOfSizeK(List< int > arr, int K)
{
int n = arr.Count;
int mx = RANKER(arr);
tree = new List<List< long >>( new List< long >[4 * mx + 1].Select(_ => new List< long >( new long [K + 1])));
for ( int i = 0; i < n; i++)
{
List< long > Kj = new List< long >( new long [K + 1]); // K length ways
Kj[1] = 1; // K=1 is the element itself
if (arr[i] > 0) // arr[0] cannot be queried, since it's the lowest
{
/* Querying the longest LIS K array where arr[i] can append to */
List< long > Ki = Query(0, mx, 0, 0, arr[i] - 1, K);
for ( int k = 2; k <= K; k++) // As explained before
{
Kj[k] = Ki[k - 1];
}
}
Update(0, mx, 0, arr[i], Kj, K); // update Kj array for arr[i]
}
return ( int )tree[0][K]; // answer is at the kth index of the root's K array
}
static void Main()
{
List< int > arr = new List< int > { 12, 8, 11, 13, 10, 15, 14, 16, 20 };
int k = 4;
Console.WriteLine($ "Number of Increasing Subsequences of size {k} = {NumOfIncSubseqOfSizeK(arr, k)}" );
}
} // This code is contributed by Susobhan Akhuli |
let tree = []; /* array of arrays, where each inner array represents the number of ways
LIS of size K ending at node can be formed */
function RANKER(arr) {
let n = arr.length;
let temp = [...arr];
temp.sort((a, b) => a - b);
let mpp = new Map();
let mx = 0;
for (let i = 0; i < n; i++) {
if (!mpp.has(temp[i])) {
mpp.set(temp[i], mx);
mx++;
}
}
for (let i = 0; i < n; i++) {
arr[i] = mpp.get(arr[i]);
}
return mx;
} function summation(left, right, k) {
// ADD WAYS, REMEMBER NO NEED TO TAKE MAX, WE ARE FINDING WAYS, NOT LENGTH.
// So each K will contribute to final answer
let res = new Array(k + 1).fill(0);
for (let i = 1; i <= k; i++) {
res[i] = left[i] + right[i];
}
return res;
} function query(start, end, parent, qstart, qend, k) {
if (end < qstart || qend < start) {
return new Array(k + 1).fill(0);
}
if (qstart <= start && qend >= end) {
return tree[parent];
}
let mid = Math.floor((start + end) / 2);
let left = query(start, mid, 2 * parent + 1, qstart, qend, k);
let right = query(mid + 1, end, 2 * parent + 2, qstart, qend, k);
return summation(left, right, k);
} function update(start, end, parent, index, updateThis, k) {
if (index < start || index > end) {
return ;
}
if (start === end) {
tree[parent] = summation(updateThis, tree[parent], k);
return ;
}
let mid = Math.floor((start + end) / 2);
if (index > mid) {
update(mid + 1, end, 2 * parent + 2, index, updateThis, k);
} else {
update(start, mid, 2 * parent + 1, index, updateThis, k);
}
let left = tree[2 * parent + 1];
let right = tree[2 * parent + 2];
tree[parent] = summation(left, right, k);
return ;
} function numOfIncSubseqOfSizeK(arr, K) {
const n = arr.length;
const mx = RANKER(arr);
tree = new Array(4 * mx + 1).fill().map(() => new Array(K + 1).fill(0));
for (let i = 0; i < n; i++) {
const Kj = new Array(K + 1).fill(0);
Kj[1] = 1;
if (arr[i] > 0) {
const Ki = query(0, mx, 0, 0, arr[i] - 1, K);
for (let k = 2; k <= K; k++) {
Kj[k] = Ki[k - 1];
}
}
update(0, mx, 0, arr[i], Kj, K);
}
return tree[0][K];
} const arr = [12, 8, 11, 13, 10, 15, 14, 16, 20]; const k = 4; console.log(`Number of Increasing Subsequences of size ${k} = ${numOfIncSubseqOfSizeK(arr, k)}`); |
Number of Increasing Subsequences of size 4 = 39
Time Complexity: O(n*K*logn). For each index, we need to do query(logn) and update in K array(k)
Auxiliary Space: O(kn).