Count number of increasing subsequences of size k
Last Updated :
12 Dec, 2023
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++
// 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
//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
# 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#
// 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
JavaScript
<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
// 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
?>
OutputNumber 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:
C++
#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
// 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
Python3
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#
// 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
JavaScript
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)}`);
OutputNumber 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).
Similar Reads
Count number of increasing sub-sequences : O(NlogN) Given an array arr[] of length N, the task is to find the number of strictly increasing sub-sequences in the given array.Examples: Input: arr[] = {1, 2, 3} Output: 7 All increasing sub-sequences will be: 1) {1} 2) {2} 3) {3} 4) {1, 2} 5) {1, 3} 6) {2, 3} 7) {1, 2, 3} Thus, answer = 7Input: arr[] = {
12 min read
Number of Longest Increasing Subsequences Given an array arr[] of size n, the task is to count the number of longest increasing subsequences present in the given array.Examples:Input: arr[] = [2, 2, 2, 2, 2]Output: 5Explanation: The length of the longest increasing subsequence is 1, i.e. {2}. Therefore, count of longest increasing subsequen
15+ min read
Count all increasing subsequences Given an array arr[] of integers (values lie in range from 0 to 9). The task is to count the number of strictly increasing subsequences that can be formed from this array. Note: A strictly increasing subsequence is a sequence where each element is greater than the previous one, and the elements are
10 min read
Count the number of non-increasing subarrays Given an array of N integers. The task is to count the number of subarrays (of size at least one) that are non-increasing. Examples: Input : arr[] = {1, 4, 3} Output : 4 The possible subarrays are {1}, {4}, {3}, {4, 3}. Input :{4, 3, 2, 1} Output : 10 The possible subarrays are: {4}, {3}, {2}, {1},
6 min read
Number of subsequences of the form a^i b^j c^k Given a string, count number of subsequences of the form aibjck, i.e., it consists of i âaâ characters, followed by j âbâ characters, followed by k âcâ characters where i >= 1, j >=1 and k >= 1. Note: Two subsequences are considered different if the set of array indexes picked for the 2 sub
15+ min read