最长递增子序列 Longest Increasing Subsequence (LIS)

来源:互联网 发布:程序员代码面试指南 编辑:程序博客网 时间:2024/04/27 19:10

题目描述:The longest Increasing Subsequence (LIS) problem is to find the length of the longest subsequence of a given sequence such that all elements of the subsequence are sorted in increasing order. For example, length of LIS for { 10, 22, 9, 33, 21, 50, 41, 60, 80 } is 6 and LIS is {10, 22, 33, 50, 60, 80}.

题目大致意思是,在数组中找出最长的递增子序列,并返回其长度。

解法一:

L[i]代表以A[i]结尾时的LIS,那么L[i]可以用以下公式表示,

L[i] = {1 + max(L[j]) },其中j<i&&A[j]<A[i].

DP:时间复杂度O(N^2),空间复杂度O(N)

那么可以有如下代码:

int lis(vector<int> & A){int len = A.size();int maxL = 0;vector<int> L(len,1);for(int i = 1; i<len; i++){for(int j = 0; j<i; j++){if(A[j] < A[i] && (L[j]+1)>L[i])L[i] = L[j] + 1;}}for(int i = 0; i<len; i++){if(maxL < L[i])maxL = L[i];}return maxL;}

 

解法二:

用vector<int> B 记录当前“最长最优”的子序列,最优的意思表示子序列中每个位置上的数字都是当前最小的,为什么要使每个位置上的数字都最优?如果A[i]大于B中所有数,那么当然可以将LIS加1,如果没有,说明当前数字并不能使LIS发生什么变化,但是我们需要在B中寻找到刚刚大于A[i]的数,用A[i]替换,从而使所有的位置上的数字最小,由于B严格递增的,所有可以用二分查找,找到替换位置,比如当前遍历到A[i],从B中找到正好比A[i]大的数,用A[i]替换。下面,用一个例子说明:

给定数组{10,22,9,33,21,50,41,60,80},每一步得到的最长最优子序列为:

10

10,22

9,22

9,22,33

9,21,33

9,21,33,50

9,21,33,41

9,21,33,41,60

9,21,33,41,60,80

最后返回B的长度,即为LIS。

时间复杂度O(N*logN),空间复杂度O(N)

int lis(vector<int> & A){int len = A.size();if(len == 0) return 0;vector<int> B;B.push_back(A[0]);for(int i = 1 ; i < len; i++){int left = 0,right = B.size()-1;while(left < right - 1){int mid = (left+right)/2;if(B[mid] > A[i])right = mid;elseleft = mid;}if(B[left] > A[i])B[left] = A[i];else if(B[right] > A[i]){B[right] = A[i];}elseB.push_back(A[i]);}return B.size();}



0 0
原创粉丝点击