Longest Increasing Subsequence using BIT
Last Updated :
01 Jul, 2022
Given an array arr, the task is to find the length of The Longest Increasing Sequence using Binary Indexed Tree (BIT)
Examples:
Input: arr = {6, 5, 1, 3, 2, 4, 8, 7}
Output: 4
Explanation:
The possible subsequences are
{1 2 4 7}, {1 2 4 8},
{1 3 4 8}, {1 3 4 7}
Now insert the elements one by one from left to right:
6 is inserted: max length till 5 = 0, ans for 6 is 1
5 is inserted: max length till 4 = 0, ans for 5 is 1
1 is inserted: max length till 0 = 2, ans for 1 is 1
3 is inserted: max length till 2 = 1, ans for 3 is 2
2 is inserted: max length till 1 = 1, ans for 2 is 2
4 is inserted: max length till 3 = 2, ans for 4 is 3
8 is inserted: max length till 7 = 3, ans for 8 is 4
7 is inserted: max length till 6 = 3, ans for 7 is 4
Input: arr = {1, 2, 3, 4, 1, 5}
Output: 5
Prerequisite for this post: Binary Indexed Tree
Approach:
- First, use coordinate compression (replace all values of the array to numbers ranging from 1 to N). This will reduce the maximum number in the array and help us solve the above problem in NlogN time. Also, this will help us to reduce memory.
- Make a new array BIT of length N + 1.
- Now, traverse the array from left to right and add the current element to the BIT.
- When ith element (A[i]) is inserted in the BIT, check for the length of the longest subsequence that can be formed till A[i] - 1. Let this value be x. If x + 1 is greater than the current element in BIT, update the BIT.
Below is the implementation of the above approach:
C++
// C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
// Function to map
// numbers using coordinate
// compression
void coordinateCompression(int arr[], int n)
{
// Set will store
// all unique numbers
set<int> s;
for (int i = 0; i < n; i++) {
s.insert(arr[i]);
}
// Map will store
// the new elements
int index = 0;
map<int, int> mp;
set<int>::iterator itr;
for (itr = s.begin(); itr != s.end(); itr++) {
// For every new number in the set,
index++;
// Increment the index of the
// current number and store it
// in a hashmap. Here index
// for every element is the
// new value with the
// current element is replaced
mp[*itr] = index;
}
for (int i = 0; i < n; i++) {
// now change the current element
// to range 1 to N.
arr[i] = mp[arr[i]];
}
}
// Function to calculate
// length of maximum
// increasing sequence till
// i'th index
int query(int BIT[], int index, int n)
{
int ans = 0;
while (index > 0) {
ans = max(ans, BIT[index]);
// Go to parent node
index -= index & (-index);
}
return ans;
}
// Function for updating
// BIT array for maximum
// increasing sequence till
// i'th index
void update(int BIT[], int index, int n)
{
// If 4 is inserted in BIT,
// check for maximum length
// subsequence till element 3.
// Let this subsequence length be x.
// If x + 1 is greater than
// the current element in BIT,
// update the BIT array
int x = query(BIT, index - 1, n);
int value = x + 1;
while (index <= n) {
// Store maximum length subsequence length till index
// Here index is the
// coordinate compressed element
BIT[index] = max(BIT[index], value);
// Go to child node and update that node
index += index & (-index);
}
}
// Function to calculate
// maximum Longest Increasing
// Sequence length
int findLISLength(int arr[], int n)
{
coordinateCompression(arr, n);
int BIT[n + 1];
// Initialising BIT array
for (int i = 0; i <= n; i++) {
BIT[i] = 0;
}
for (int i = 0; i < n; i++) {
// Add elements
// from left to right
// in BIT
update(BIT, arr[i], n);
}
int ans = query(BIT, n, n);
return ans;
}
// Driver code
int main()
{
int arr[] = { 6, 5, 1, 3, 2, 4, 8, 7 };
int n = sizeof(arr) / sizeof(int);
int ans = findLISLength(arr, n);
cout << ans << endl;
return 0;
}
Java
// Java implementation of the approach
import java.util.*;
class GFG
{
// Function to map numbers using
// coordinate compression
static void coordinateCompression(int arr[],
int n)
{
// Set will store
// all unique numbers
Set<Integer> s = new HashSet<>();
for (int i = 0; i < n; i++)
{
s.add(arr[i]);
}
// Map will store
// the new elements
int index = 0;
HashMap<Integer, Integer> mp =
new HashMap<Integer, Integer>();
for (int itr : s)
{
// For every new number in the set,
index++;
// Increment the index of the
// current number and store it
// in a hashmap. Here index
// for every element is the
// new value with the
// current element is replaced
mp.put(itr, index);
}
for (int i = 0; i < n; i++)
{
// now change the current element
// to range 1 to N.
arr[i] = mp.get(arr[i]);
}
}
// Function to calculate length of maximum
// increasing sequence till i'th index
static int query(int BIT[], int index, int n)
{
int ans = 0;
while (index > 0)
{
ans = Math.max(ans, BIT[index]);
// Go to parent node
index -= index & (-index);
}
return ans;
}
// Function for updating BIT array for
// maximum increasing sequence till
// i'th index
static void update(int BIT[],
int index, int n)
{
// If 4 is inserted in BIT,
// check for maximum length
// subsequence till element 3.
// Let this subsequence length be x.
// If x + 1 is greater than
// the current element in BIT,
// update the BIT array
int x = query(BIT, index - 1, n);
int value = x + 1;
while (index <= n)
{
// Store maximum length subsequence length
// till index. Here index is the
// coordinate compressed element
BIT[index] = Math.max(BIT[index], value);
// Go to child node and update that node
index += index & (-index);
}
}
// Function to calculate maximum
// Longest Increasing Sequence length
static int findLISLength(int arr[], int n)
{
coordinateCompression(arr, n);
int []BIT = new int[n + 1];
// Initialising BIT array
for (int i = 0; i <= n; i++)
{
BIT[i] = 0;
}
for (int i = 0; i < n; i++)
{
// Add elements from left to right
// in BIT
update(BIT, arr[i], n);
}
int ans = query(BIT, n, n);
return ans;
}
// Driver code
public static void main(String[] args)
{
int arr[] = { 6, 5, 1, 3, 2, 4, 8, 7 };
int n = arr.length;
int ans = findLISLength(arr, n);
System.out.println(ans);
}
}
// This code is contributed by Rajput-Ji
Python3
# Python3 program for the above approach
# Function to map
# numbers using coordinate
# compression
def coordinateCompression(arr, n):
# Set will store
# all unique numbers
s = dict()
for i in range(n):
s[arr[i]] = 1
# Map will store
# the new elements
index = 0
mp = dict()
for itr in sorted(s):
# For every new number in the set,
index += 1
# Increment the index of the
# current number and store it
# in a hashmap. Here index
# for every element is the
# new value with the
# current element is replaced
mp[itr] = index
for i in range(n):
# now change the current element
# to range 1 to N.
arr[i] = mp[arr[i]]
# Function to calculate
# length of maximum
# increasing sequence till
# i'th index
def query(BIT, index, n):
ans = 0
while (index > 0):
ans = max(ans, BIT[index])
# Go to parent node
index -= index & (-index)
return ans
# Function for updating
# BIT array for maximum
# increasing sequence till
# i'th index
def update(BIT, index, n):
# If 4 is inserted in BIT,
# check for maximum length
# subsequence till element 3.
# Let this subsequence length be x.
# If x + 1 is greater than
# the current element in BIT,
# update the BIT array
x = query(BIT, index - 1, n)
value = x + 1
while (index <= n):
# Store maximum length subsequence length till index
# Here index is the
# coordinate compressed element
BIT[index] = max(BIT[index], value)
# Go to child node and update that node
index += index & (-index)
# Function to calculate
# maximum Longest Increasing
# Sequence length
def findLISLength(arr, n):
coordinateCompression(arr, n)
BIT = [0]*(n + 1)
for i in range(n):
# Add elements
# from left to right
# in BIT
update(BIT, arr[i], n)
ans = query(BIT, n, n)
return ans
# Driver code
arr=[6, 5, 1, 3, 2, 4, 8, 7]
n = len(arr)
ans = findLISLength(arr, n)
print(ans)
# This code is contributed mohit kumar 29
C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
class GFG{
// Function to map numbers using
// coordinate compression
static void coordinateCompression(int []arr,
int n)
{
// Set will store
// all unique numbers
HashSet<int> s = new HashSet<int>();
for (int i = 0; i < n; i++)
{
s.Add(arr[i]);
}
// Map will store
// the new elements
int index = 0;
Dictionary<int,
int> mp = new Dictionary<int,
int>();
foreach (int itr in s)
{
// For every new number in the set,
index++;
// Increment the index of the
// current number and store it
// in a hashmap. Here index
// for every element is the
// new value with the
// current element is replaced
mp.Add(itr, index);
}
for (int i = 0; i < n; i++)
{
// now change the current element
// to range 1 to N.
arr[i] = mp[arr[i]];
}
}
// Function to calculate
// length of maximum increasing
// sequence till i'th index
static int query(int []BIT,
int index, int n)
{
int ans = 0;
while (index > 0)
{
ans = Math.Max(ans,
BIT[index]);
// Go to parent node
index -= index & (-index);
}
return ans;
}
// Function for updating BIT array for
// maximum increasing sequence till
// i'th index
static void update(int []BIT,
int index, int n)
{
// If 4 is inserted in BIT,
// check for maximum length
// subsequence till element 3.
// Let this subsequence length be x.
// If x + 1 is greater than
// the current element in BIT,
// update the BIT array
int x = query(BIT, index - 1, n);
int value = x + 1;
while (index <= n)
{
// Store maximum length subsequence length
// till index. Here index is the
// coordinate compressed element
BIT[index] = Math.Max(BIT[index], value);
// Go to child node and update that node
index += index & (-index);
}
}
// Function to calculate maximum
// longest Increasing Sequence length
static int findLISLength(int []arr,
int n)
{
coordinateCompression(arr, n);
int []BIT = new int[n + 1];
// Initialising BIT array
for (int i = 0; i <= n; i++)
{
BIT[i] = 0;
}
for (int i = 0; i < n; i++)
{
// Add elements from
// left to right in BIT
update(BIT, arr[i], n);
}
int ans = query(BIT, n, n) / 2;
return ans;
}
// Driver code
public static void Main(String[] args)
{
int []arr = {6, 5, 1, 3,
2, 4, 8, 7};
int n = arr.Length;
int ans = findLISLength(arr, n);
Console.WriteLine(ans);
}
}
// This code is contributed by gauravrajput1
JavaScript
<script>
// JavaScript implementation of the approach
// Function to map numbers using
// coordinate compression
function coordinateCompression(arr, n) {
// Set will store
// all unique numbers
let s = new Set();
for (let i = 0; i < n; i++) {
s.add(arr[i]);
}
// Map will store
// the new elements
let index = 0;
let mp = new Map();
for (let itr of s) {
// For every new number in the set,
index++;
// Increment the index of the
// current number and store it
// in a hashmap. Here index
// for every element is the
// new value with the
// current element is replaced
mp.set(itr, index);
}
for (let i = 0; i < n; i++) {
// now change the current element
// to range 1 to N.
arr[i] = mp.get(arr[i]);
}
}
// Function to calculate length of maximum
// increasing sequence till i'th index
function query(BIT, index, n) {
let ans = 0;
while (index > 0) {
ans = Math.max(ans, BIT[index]);
// Go to parent node
index -= index & (-index);
}
return ans;
}
// Function for updating BIT array for
// maximum increasing sequence till
// i'th index
function update(BIT, index, n) {
// If 4 is inserted in BIT,
// check for maximum length
// subsequence till element 3.
// Let this subsequence length be x.
// If x + 1 is greater than
// the current element in BIT,
// update the BIT array
let x = query(BIT, index - 1, n);
let value = x + 1;
while (index <= n) {
// Store maximum length subsequence length
// till index. Here index is the
// coordinate compressed element
BIT[index] = Math.max(BIT[index], value);
// Go to child node and update that node
index += index & (-index);
}
}
// Function to calculate maximum
// Longest Increasing Sequence length
function findLISLength(arr, n) {
coordinateCompression(arr, n);
let BIT = new Array(n + 1);
// Initialising BIT array
for (let i = 0; i <= n; i++) {
BIT[i] = 0;
}
for (let i = 0; i < n; i++) {
// Add elements from left to right
// in BIT
update(BIT, arr[i], n);
}
let ans = query(BIT, n, n) / 2;
return ans;
}
// Driver code
let arr = [6, 5, 1, 3, 2, 4, 8, 7];
let n = arr.length;
let ans = findLISLength(arr, n);
document.write(ans);
// This code is contributed by _saurabh_jaiswal
</script>
Time Complexity: O(N*log(N))
Auxiliary Space: O(N)
Similar Reads
Longest Increasing Subsequence in C++
In this article, we will learn the concept of the Longest Increasing Subsequence (LIS) in a given sequence using C++ language. The LIS problem is about finding the longest subsequence of a sequence in which the elements are in sorted order, from lowest to highest, and not necessarily contiguous.Exam
9 min read
Longest Increasing Subsequence (LIS)
Given an array arr[] of size n, the task is to find the length of the Longest Increasing Subsequence (LIS) i.e., the longest possible subsequence in which the elements of the subsequence are sorted in increasing order.Examples: Input: arr[] = [3, 10, 2, 1, 20]Output: 3Explanation: The longest increa
14 min read
Longest Increasing Subsequence(LIS) using two arrays
Given two arrays A[] and B[] of size N. Your Task is to find Longest Increasing Subsequence(LIS) in another array C[] such that array C[] is formed by following rules: C[i] = A[i] or C[i] = B[i] for all i from 1 to N.Examples: Input: A[] = {2, 3, 1}, B[] = {1, 2, 1}Output: 2Explanation: Form C[] as
9 min read
Longest Decreasing Subsequence
Given an array of N integers, find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in strictly decreasing order. Examples: Input: arr[] = [15, 27, 14, 38, 63, 55, 46, 65, 85] Output: 3 Explanation: The longest decreasing subsequence is {
14 min read
Longest Increasing consecutive subsequence
Given N elements, write a program that prints the length of the longest increasing consecutive subsequence. Examples: Input : a[] = {3, 10, 3, 11, 4, 5, 6, 7, 8, 12} Output : 6 Explanation: 3, 4, 5, 6, 7, 8 is the longest increasing subsequence whose adjacent element differs by one. Input : a[] = {6
10 min read
Longest Increasing Odd Even Subsequence
Given an array of size n. The problem is to find the length of the subsequence in the given array such that all the elements of the subsequence are sorted in increasing order and also they are alternately odd and even. Note that the subsequence could start either with the odd number or with the even
8 min read
Find the Second Longest Increasing Subsequence
Given an array arr[] of integers, the task is to find the length of the second longest increasing subsequence (LIS). Examples: Input: arr[] = {1, 2, 3, 4}Output: 3 Explanation: Here the length of LIS is 4 which is whole array and length of second LIS is 3 which can be any sequence, {1, 2, 3} or {1,
15+ 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
Longest Bitonic Subsequence
Given an array arr[] containing n positive integers, a subsequence of numbers is called bitonic if it is first strictly increasing, then strictly decreasing. The task is to find the length of the longest bitonic subsequence. Note: Only strictly increasing (no decreasing part) or a strictly decreasin
15+ min read
Longest dividing subsequence
You are given an array A of size N. Your task is to find the length of largest dividing sub sequence.A dividing sequence is a sequence a1, a2, â¦, aN where ai divides aj whenever i < j. For example, 3, 15, 60, 720 is a dividing sequence. input- The first line of each test case is N, where N is the
5 min read