最长递增子序列 Longest Incresing Subsequence

来源:互联网 发布:今天网络 编辑:程序博客网 时间:2024/06/01 17:30

问题: 求一个一位数组(N个元素)中最长递增子序列的长度。

例如: 在序列1,-1, 2,-3, 4,-5, 6,-7中,最长递增子序列为1,2,4,6.


解法一: 假设在目标数组array[]的前i个元素中,以array[i]为结尾的最长递增子序列的长度为LIS[i]。那么

LIS[i + 1] = max{1, LIS[k] + 1}, array[i + 1] > array[k], for any k <= i;


解法二: 解法一每次求LIS[i + 1],需要遍历LIS[0...i],时间复杂度为O(N*N)。如果LIS[]是排好序的,可以用二分搜索使复杂度降到O(N*logN)。

LIS[i]保存长度为i + 1的最长递归子序列的最大值(序列最后的一个值)的最小值。


C++实现:

#include <iostream>using namespace std;int longestIncresingSubsequence1(int array[], int n){int ret = 1;int *LIS = new int[n];for (int i = 0; i < n; ++i){LIS[i] = 1;for (int j = 0; j < i; ++j){if (array[i] > array[j] && LIS[j] + 1 > LIS[i]){LIS[i] = LIS[j] + 1;}}}for (int i = 0; i < n; ++i)ret = (ret < LIS[i]) ? LIS[i] : ret;delete []LIS;return ret;}int longestIncresingSubsequence2(int array[], int n){int *LIS = new int[n];LIS[0] = array[0];int nMaxLIS = 0;for (int i = 1; i < n; ++i){int m;int l = 0, r = nMaxLIS;while (l <= r){m = (l + r) / 2;if (array[i] < LIS[m])r = m - 1;else if (array[i] > LIS[m])l = m + 1;elsebreak;}if (array[i] == LIS[m])continue;if (m == nMaxLIS){if (array[i] > LIS[m]){nMaxLIS++;LIS[nMaxLIS] = array[i];}else if (array[i] < LIS[m]){LIS[m] = array[i];}}else if (array[i] < LIS[m])LIS[m] = array[i];else if (array[i] > LIS[m] && array[i] < LIS[m + 1]){LIS[m + 1] = array[i];}}delete []LIS;return nMaxLIS + 1;}int main(){int Seq[8] = {1, -1, 2, -3, 4, -5, 6, -7};cout << longestIncresingSubsequence1(Seq, 8) << endl;cout << longestIncresingSubsequence2(Seq, 8) << endl;}


0 0