1. 程式人生 > >leecode 300. Longest Increasing Subsequence

leecode 300. Longest Increasing Subsequence

要求 ati The 函數 一個 longest 添加 () Go

Given an unsorted array of integers, find the length of 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], therefore the length is 4. 

Note:

  • There may be more than one LIS combination, 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?

題目大意:找出無序數組中最長上升子序列的長度, 時間復雜度要求為O(nlgn);

最直接的辦法是暴力求解,記錄下每個位置的上升序列長度, 當要計算某個位置的上升序列長度的時候,就向前面找到比該值小且上升序列的長度和該位置的上升序列長度差值不超過一的數; 這樣做的方法簡單,但是會進行很多重復的查詢;

改進辦法:用一個數組來模擬棧lis,這個數組按照記錄出現的升序數字, 當新出現的數字比棧頂的數字大, 則添加到棧中,否則更新數組中的數;

Input: [10,9,2,5,3,7,101,18]
初始lis={10}
依次遍歷數組:出現的是9, 9比棧頂元素小, 查找9應該插入的位置, lis更新為{9}
2: 依舊是更新的操作, {2}
5: 5比棧頂元素大, 添加到棧中, {2, 5};
3: 把3插入到lis中, lis更新為{2, 3}
7: 把7添加到lis中, lis更新為{2,3,7}
101: 把101添加到lis中, 更新為{2,3,7, 101}
18: 插入到lis中, 更新為{2, 3, 7, 18}
可以發現只有在新出現的數字比棧頂元素大的時候,lis的大小才會改變, 其他情況不會改變lis的大小,但會把lis中某一個元素替換掉
如最後一步,把101替換為18, 這樣做的意義是什麽, 是為了讓上升序列更有潛力, 加入數組擴展為 10,9,2,5,3,7,101,18, 50, 90; 如果沒有把101替換為18,最長子序列的長度會保持在4, 這顯然是錯誤;
lis中保存的並不是正確的最長上升子序列, 但是其長度和最長上升子序列是相同的;
這裏用了stl庫中的lower_bounder函數, 函數返回和num相同或者第一個比num大的數的位置, 我們通過這個位置來跟新lis中的元素
 1 class Solution {
 2 public:
 3     int lengthOfLIS(vector<int>& nums) {
 4         if(nums.size()==0) return 0;
 5         auto m=nums.begin();
 6         for(auto num:nums){
 7             auto it=lower_bound(nums.begin(), m, num);
 8             *it=num;
 9             if(it==m) m++;
10         }
11          return m-nums.begin();
12     }
13 };

leecode 300. Longest Increasing Subsequence