标签:时间复杂度 nbsp exp with span long 有一个 元素 i++
对于一个序列{3, 2, 6, 4, 5, 1},它包含很多递增子序列{3, 6}, {2,6}, {2, 4, 5}, {1}
其中最长的递增子序列是{2, 4, 5}
for (i=N; i>0; --i) {1. 找到所有长度为i的子序列; //复杂度为(N!)/(i!)(N-i)! O(exp(N)) 2. 判断是否其中有一个为递增子序列
}
基本思想:将一个复杂问题,分解为更小的子问题
首先定义LIS[i],表示以D[i]结尾的最长子序列
对于矢量D = {3, 2, 6, 4, 5, 1}; LIS[0]: 3 LIS[1]: 2 LIS[2]: 2,6 LIS[3]: 2,4 LIS[4]: 2,4,5 LIS[5]: 1
给出递推公式
LIS[0] = D[0]
LIS[i] = MAX(LIS[j] | j <i, D[j] <D[i]) + "D[i]"
解释:
当我们求LIS[i]时,对于任意j<i,LIS[j]都已知
在所有已知的LIS中,找出结尾的元素值小于D[i],长度最长的一个
然后在后面加上D[i]元素,即为LIS[i]
using namespace std; void prt(vector<int>& arr, string msg = "") { cout << msg << " "; for (auto i: arr) { cout << i << " "; } cout << endl; } void calc_LIS(vector<int>& D) { vector< vector<int> > L(D.size()); // The longest increasing subsequence ends with D[i] L[0].push_back(D[0]); for (int i=1; i<D.size(); i++) { for(int j=0; j<i; j++) { if ( (D[j] < D[i]) && ( L[i].size() < L[j].size() ) ) { L[i] = L[j]; } } L[i].push_back(D[i]); } for (auto x: L) { prt(x); } } int main() { int a[] = {3, 2, 6, 4, 5, 1}; vector<int> arr(a, a + sizeof(a)/sizeof(a[0])); prt(arr, "Data In:"); calc_LIS(arr); return 0; }
时间复杂度是O(N^2)
动态规范的基本思想是以一定的空间开销,显著缩短时间开销
算法实践--最长递增子序列(Longest Increasing Subsquence)
标签:时间复杂度 nbsp exp with span long 有一个 元素 i++
原文地址:https://www.cnblogs.com/logchen/p/10260913.html