最长递增子序列 (LIS) 问题是找到给定序列的最长子序列的长度,使子序列的所有元素按递增顺序排序。例如,{10, 22, 9, 33, 21, 50, 41, 60, 80}的LIS长度为6,LIS为{10, 22, 33, 50, 60, 80}。
例子:
Input : arr[] = {3, 10, 2, 1, 20}
Output : Length of LIS = 3
The longest increasing subsequence is 3, 10, 20
Input : arr[] = {3, 2}
Output : Length of LIS = 1
The longest increasing subsequences are {3} and {2}
Input : arr[] = {50, 3, 10, 7, 40, 80}
Output : Length of LIS = 4
The longest increasing subsequence is {3, 7, 40, 80}
重叠子问题:
考虑到上述实现,以下是大小为 4 的数组的递归树。 lis(n) 为我们提供了 arr[] 的 LIS 长度。
lis(4)
/ |
lis(3) lis(2) lis(1)
/ /
lis(2) lis(1) lis(1)
/
lis(1)
我们可以看到有很多子问题被一次又一次地解决了。所以这个问题具有重叠子结构的性质,并且可以通过使用 Memoization 或 Tabulation 来避免相同子问题的重新计算。以下是 LIS 问题的列表实现。
C++
/* Dynamic Programming C/C++ implementation of LIS problem */
#include
#include
/* lis() returns the length of the longest increasing
subsequence in arr[] of size n */
int lis(int arr[], int n)
{
int *lis, i, j, max = 0;
lis = (int*)malloc(sizeof(int) * n);
/* Initialize LIS values for all indexes */
for (i = 0; i < n; i++)
lis[i] = 1;
/* Compute optimized LIS values in bottom up manner */
for (i = 1; i < n; i++)
for (j = 0; j < i; j++)
if (arr[i] > arr[j] && lis[i] < lis[j] + 1)
lis[i] = lis[j] + 1;
/* Pick maximum of all LIS values */
for (i = 0; i < n; i++)
if (max < lis[i])
max = lis[i];
/* Free memory to avoid memory leak */
free(lis);
return max;
}
/* Driver program to test above function */
int main()
{
int arr[] = { 10, 22, 9, 33, 21, 50, 41, 60 };
int n = sizeof(arr) / sizeof(arr[0]);
printf("Length of lis is %d\n", lis(arr, n));
return 0;
}
Java
/* Dynamic Programming Java implementation
of LIS problem */
import java.util.*;
class GFG
{
/*
* lis() returns the length of the longest
* increasing subsequence in arr[] of size n
*/
static int lis(int[] arr, int n)
{
int max = 0;
int[] lst = new int[n];
// initialize LIS values for all indexes
Arrays.fill(lst, 1);
/* Compute optimized LIS values
in bottom up manner */
for (int i = 1; i < n; i++)
{
for (int j = 0; j < i; j++)
{
if (arr[i] > arr[j] &&
lst[i] < lst[j] + 1)
lst[i] = lst[j] + 1;
}
}
/* Pick maximum of all LIS values */
for (int i = 0; i < n; i++)
if (max < lst[i])
max = lst[i];
return max;
}
// Driver Code
public static void main(String[] args)
{
int[] arr = { 10, 22, 9, 33, 21, 50, 41, 60 };
int n = arr.length;
System.out.println("Length of lis is " +
lis(arr, n));
}
}
// This code is contributed by
// sanjeev2552
Python3
# Dyanmic Programming python3
# implementation of LIS problem
# lis() returns the length of the
# longest increasing subsequence
# in arr[] of size n
def lis(arr, n):
i, j, maxm = 0, 0, 0
# initialize LIS values for all indexes
lst = [1 for s in range(n)]
for i in range(1, n):
for j in range(0, i):
if (arr[i] > arr[j] and
lst[i] < lst[j] + 1):
lst[i] = lst[j] + 1
# Pick maximum of all LIS values
for i in range(0, n):
if maxm < lst[i]:
maxm = lst[i]
return maxm
# Driver Code
arr = [10, 22, 9, 33, 21, 50, 41, 60]
n = len(arr)
print("Length of lst is", lis(arr, n))
# This code is contributed
# by Mohit kumar 29
C#
/* Dynamic Programming Java implementation
of LIS problem */
using System;
public class GFG
{
/*
* lis() returns the length of the longest
* increasing subsequence in arr[] of size n
*/
static int lis(int[] arr, int n)
{
int max = 0;
int[] lst = new int[n];
// initialize LIS values for all indexes
Array.Fill(lst, 1);
/* Compute optimized LIS values
in bottom up manner */
for (int i = 1; i < n; i++)
{
for (int j = 0; j < i; j++)
{
if (arr[i] > arr[j] && lst[i] < lst[j] + 1)
{
lst[i] = lst[j] + 1;
}
}
}
/* Pick maximum of all LIS values */
for (int i = 0; i < n; i++)
if (max < lst[i])
max = lst[i];
return max;
}
// Driver code
static public void Main ()
{
int[] arr = { 10, 22, 9, 33, 21, 50, 41, 60 };
int n = arr.Length;
Console.WriteLine("Length of lis is " + lis(arr, n));
}
}
// This code is contributed by avanitrachhadiya2155
Javascript
C++
#include
using namespace std;
int longest_increasing_subsequence(vector& arr)
{
vector ans;
int n = arr.size();
for (int i = 0; i < n; i++) {
auto it
= lower_bound(ans.begin(), ans.end(), arr[i]);
if (it == ans.end()) {
ans.push_back(arr[i]);
}
else {
*it = arr[i];
}
}
return ans.size();
}
int main()
{
vector a = { 10, 22, 9, 33, 21, 50, 41, 60 };
int ans = longest_increasing_subsequence(a);
cout << ans;
return 0;
}
输出:
Length of lis is 5
请参阅关于动态规划的完整文章 |设置 3(最长递增子序列)了解更多详情!
方法 2:基于下限的方法
算法 :
1. 迭代数组。
2. 声明一个新数组ans来添加新构造的递增子序列。
2. 对于每个索引,如果lower_bound 指向数组ans的结尾,则将其推入向量ans 中。
3. 返回ans数组大小。
C++
#include
using namespace std;
int longest_increasing_subsequence(vector& arr)
{
vector ans;
int n = arr.size();
for (int i = 0; i < n; i++) {
auto it
= lower_bound(ans.begin(), ans.end(), arr[i]);
if (it == ans.end()) {
ans.push_back(arr[i]);
}
else {
*it = arr[i];
}
}
return ans.size();
}
int main()
{
vector a = { 10, 22, 9, 33, 21, 50, 41, 60 };
int ans = longest_increasing_subsequence(a);
cout << ans;
return 0;
}
输出
5
想要从精选的视频和练习题中学习,请查看C++ 基础课程,从基础到高级 C++ 和C++ STL 课程,了解语言和 STL。要完成从学习语言到 DS Algo 等的准备工作,请参阅完整的面试准备课程。