LIS最长递增子序列
给定一个长度为N的数组,找出一个最长的单调递增子序列。
例如:给定数组A{5,6,7,1,2,8},则其最长的单调递增子序列为{5,6,7,8},长度为4。
一种思路是将其转换成LCS问题:将A数组排序后:A'{1, 2, 5, 6, 7, 8}
因为,原数组A的子序列顺序保持不变,而且排序后A'本身就是递增的,这样,就保证了两序列的最长公共子序列的递增特性。如此,若想求数组A的最长递增子序列,其实就是求数组A与它的排序数组A‘的最长公共子序列。
此外,本题可以直接使用动态规划求解。
算法如下:
设长度为N的数组为{a0,a1, a2, ...an-1},则 假定以aj结尾的数组序列的最长递增子序列 长度为L(j),则L(j)={ max(L(i))+1, i<j且 a[i]<a[j] }。也就是说,我们需要遍历在j之 前的所有位置i(从0到j-1),找出满足条件 a[i]<a[j]的L(i),求出max(L(i))+1即为L(j)的 值。最后,我们遍历所有的L(j)(从0到N-1), 找出最大值即为最大递增子序列。时间复杂 度为O(N2)。
代码如下:
1 #include <iostream> 2 3 using namespace std; 4 5 int LisLength(int a[], int m) 6 { 7 int longest[m]; 8 for(int i = 0; i < m; ++i) 9 { 10 longest[i] = 1; 11 } 12 for(int i = 1; i < m; ++i) 13 { 14 for(int j = 0; j < i; ++j) 15 { 16 if(a[j] < a[i] && longest[i] < longest[j] + 1) 17 { 18 longest[i] = longest[j] + 1; 19 } 20 } 21 } 22 int max = 1; 23 for(int i = 0; i < m; ++i) 24 { 25 if(longest[i] > max) 26 { 27 max = longest[i]; 28 } 29 } 30 return max; 31 } 32 33 int main(int argc, const char *argv[]) 34 { 35 int a[6] = {5, 6, 7, 1, 2, 0}; 36 int max = LisLength(a, 6); 37 cout << max << endl; 38 return 0; 39 }
注意if判断条件,前一位小于i位,并且i位结尾的最长序列小于前一位最长序列+1,循环就一直进行下去。