给定一个数组arr ,任务是使用二进制索引树(BIT)查找最长增长序列的长度
例子:
Input: arr = {6, 5, 1, 3, 2, 4, 8, 7}
Output: 4
Explanantion:
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
这篇文章的前提条件:二进制索引树
方法:
- 首先,使用坐标压缩(将数组的所有值替换为1到N范围内的数字)。这将减少阵列中的最大数量,并帮助我们在NlogN时间内解决上述问题。另外,这将有助于我们减少内存。
- 制作一个长度为N + 1的新数组BIT。
- 现在,从左到右遍历数组并将当前元素添加到BIT。
- 当第(i [A])个元素插入BIT中时,检查直到A [i] – 1为止可以形成的最长子序列的长度。令该值为x。如果x +1大于BIT中的当前元素,请更新BIT。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Function to map
// numbers using coordinate
// compression
void coordinateCompression(int arr[], int n)
{
// Set will store
// all unique numbers
set s;
for (int i = 0; i < n; i++) {
s.insert(arr[i]);
}
// Map will store
// the new elements
int index = 0;
map mp;
set::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 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
// Sequene length
int findLISLength(int arr[], int n)
{
coordinateCompression(arr, n);
int BIT[n + 1];
// Intialising 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 s = new HashSet<>();
for (int i = 0; i < n; i++)
{
s.add(arr[i]);
}
// Map will store
// the new elements
int index = 0;
HashMap mp =
new HashMap();
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 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 Sequene length
static int findLISLength(int arr[], int n)
{
coordinateCompression(arr, n);
int []BIT = new int[n + 1];
// Intialising 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 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
# Sequene 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 s = new HashSet();
for (int i = 0; i < n; i++)
{
s.Add(arr[i]);
}
// Map will store
// the new elements
int index = 0;
Dictionary mp = new Dictionary();
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 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 Sequene length
static int findLISLength(int []arr,
int n)
{
coordinateCompression(arr, n);
int []BIT = new int[n + 1];
// Intialising 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
输出:
4
时间复杂度: O(N * log(N))