1. 程式人生 > >LeetCode題解:longest-increasing-subsequence(最長遞增子序列)

LeetCode題解:longest-increasing-subsequence(最長遞增子序列)

題目描述

Example:
Input: [10,9,2,5,3,7,101,18]
Output: 4 

Explanation: 
The longest increasing subsequence is [2,3,7,101], the length is 4. 

Note:
There may be more than one result, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?

思路

這是一個經典的動態規劃演算法,假設v[i]代表最後節點為第i個節點的最長遞增子序列的長度,那麼更新的狀態方程為:

v [ i ] = m a

x ( v [ j ] ) + 1 ,
j i v[i] = max(v[j])+1, 其中j到i是連通的。

O(n²)級別的演算法一

class Solution {
public:

    int lengthOfLIS(vector<int>& nums) {
        int * length = new int[nums.size()]();
        int max = 0, result = 0;
        for (int i = 0; i < nums.size(); i++) {
        	max = 0;
        	for (int j = 0; j < i; j++) {
        		if (nums[j] < nums[i]) {
        			max = max < length[j] ? length[j] : max;
				}
        	}
        	max++;
        	length[i] = max;
        	result = result < max ? max : result;
        }
        delete [] length;
        return result;
    }
};

在這裡插入圖片描述

仍需努力仍需努力。

O(nlog(n))級別的演算法二

之前我們在更新時,不得不遍歷整個位於當前元素之前的元素來更新長度,有沒有更好的方法呢?

在此之前,我們需要先確認遞增序列的幾個性質:

  • 如果有一個長度為m的遞增子序列A,當新的元素K加入時,要形成一條長為m+1的新序列,則K必須大於A的最後一個元素——記為last(A)。
  • 如果有兩個長度均為m的遞增子序列A和B,那麼當K大於min(last(A), last(B))時,會獲得一條長為m+1的新序列。
  • 令B[i] = k的含義為:長度為i的最短子序列的最小的最後一個值為k,那麼當i變大時,B[i]是嚴格遞增的。(這個在直觀上很好想象,當然通過反證法也是可以證明的)。
  • 如果有c > a 且 c < b, 且B[m] = a, B[m+1] = b, 那麼B[m+1]=c。

所以,由上文的性質一和二,推出了性質三的資料結構的性質。而最後一個性質給出了這種結構的更新方法,以及嚴格遞增下二分法的實現可能。
程式碼如下:

class Solution {
public:

    int bisearch(int start, int end, int* S, int key) {
        if (S[end] < key) {
            return end+1;
        }
        //針對(2,2)這種情況 
        if (S[end] == key) {
        	return end;
		}
        int mid = (start+end)/2;
        if (S[mid] > key) {
            if ( S[mid-1] < key) {
                return mid;
            }
            return bisearch(start, mid-1, S, key);
        }
        return bisearch(mid+1, end, S, key);
    }

    int lengthOfLIS(vector<int>& nums) {
    	//針對[] 
    	if (nums.empty()) {
    		return 0;
		}
        int * length = new int[nums.size()+1]();
        int pos = 0, end = 1;
        length[1] = nums[0];
        //針對負數情況 
        length[0] = -10086;
        for (int i = 1; i < nums.size(); i++) {
            pos = bisearch(1, end, length, nums[i]);
            end = end < pos ? pos:end;
            length[pos] = nums[i];
        }
        delete [] length;
        return end;
    }
};

撒花兒~
在這裡插入圖片描述