zoukankan      html  css  js  c++  java
  • 最长递增子序列

    这是一道经典的动态规划题
    最长递增子序列问题:在一列数中寻找一些数,这些数满足:任意两个数a[i]和a[j],若i<j,必有a[i]<a[j],这样最长的子序列称为最长递增子序列。
    设dp[i]表示以i为结尾的最长递增子序列的长度,则状态转移方程为:
    dp[i] = max{dp[j]+1}, 1<=j<i,a[j]<a[i].

     1 int lengthOfLIS(vector<int>& nums) {
     2         int size = nums.size();
     3         if(size ==0) return 0;
     4         vector<int> dp(size,1);
     5         for(int i = 1; i < size;i++){
     6             for(int j = i-1; j >= 0 ;j--){
     7                 if(nums[i]>nums[j]){
     8                     dp[i] = max(dp[i],dp[j]+1);
     9                 }
    10             }
    11         }
    12         int max_l = dp[0];
    13         for(auto d : dp)
    14             max_l = max(max_l,dp);
    15         return max_l;
    16     }

    这样简单的复杂度为O(n^2),其实还有更好的方法。

    http://yzmduncan.iteye.com/blog/1546503

    http://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/

    考虑两个数a[x]和a[y],x<y且a[x]<a[y],且dp[x]=dp[y],当a[t]要选择时,到底取哪一个构成最优的呢?显然选取a[x]更有潜力,因为可能存在a[x]<a[z]<a[y],这样a[t]可以获得更优的值。在这里给我们一个启示,当dp[t]一样时,尽量选择更小的a[x].

    Our strategy determined by the following conditions,

    1. If A[i] is smallest among all end candidates of active lists, we will start new active list of length 1.

    2. If A[i] is largest among all end candidates of active lists, we will clone the largest active list, and extend it by A[i].

    3. If A[i] is in between, we will find a list with largest end element that is smaller than A[i]. Clone and extend this list by A[i]. We will discard all other lists of same length as that of this modified list.

    举个栗子

    It will be clear with an example, let us take example from wiki {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15}.

    A[0] = 0. Case 1. There are no active lists, create one.
    0.
    -----------------------------------------------------------------------------
    A[1] = 8. Case 2. Clone and extend.
    0.
    0, 8.
    -----------------------------------------------------------------------------
    A[2] = 4. Case 3. Clone, extend and discard.
    0.
    0, 4.
    0, 8. Discarded
    -----------------------------------------------------------------------------
    A[3] = 12. Case 2. Clone and extend.
    0.
    0, 4.
    0, 4, 12.
    -----------------------------------------------------------------------------
    A[4] = 2. Case 3. Clone, extend and discard.
    0.
    0, 2.
    0, 4. Discarded.
    0, 4, 12.
    -----------------------------------------------------------------------------
    A[5] = 10. Case 3. Clone, extend and discard.
    0.
    0, 2.
    0, 2, 10.
    0, 4, 12. Discarded.
    -----------------------------------------------------------------------------
    A[6] = 6. Case 3. Clone, extend and discard.
    0.
    0, 2.
    0, 2, 6.
    0, 2, 10. Discarded.
    -----------------------------------------------------------------------------
    A[7] = 14. Case 2. Clone and extend.
    0.
    0, 2.
    0, 2, 6.
    0, 2, 6, 14.
    -----------------------------------------------------------------------------
    A[8] = 1. Case 3. Clone, extend and discard.
    0.
    0, 1.
    0, 2. Discarded.
    0, 2, 6.
    0, 2, 6, 14.
    -----------------------------------------------------------------------------
    A[9] = 9. Case 3. Clone, extend and discard.
    0.
    0, 1.
    0, 2, 6.
    0, 2, 6, 9.
    0, 2, 6, 14. Discarded.
    -----------------------------------------------------------------------------
    A[10] = 5. Case 3. Clone, extend and discard.
    0.
    0, 1.
    0, 1, 5.
    0, 2, 6. Discarded.
    0, 2, 6, 9.
    -----------------------------------------------------------------------------
    A[11] = 13. Case 2. Clone and extend.
    0.
    0, 1.
    0, 1, 5.
    0, 2, 6, 9.
    0, 2, 6, 9, 13.
    -----------------------------------------------------------------------------
    A[12] = 3. Case 3. Clone, extend and discard.
    0.
    0, 1.
    0, 1, 3.
    0, 1, 5. Discarded.
    0, 2, 6, 9.
    0, 2, 6, 9, 13.
    -----------------------------------------------------------------------------
    A[13] = 11. Case 3. Clone, extend and discard.
    0.
    0, 1.
    0, 1, 3.
    0, 2, 6, 9.
    0, 2, 6, 9, 11.
    0, 2, 6, 9, 13. Discarded.
    -----------------------------------------------------------------------------
    A[14] = 7. Case 3. Clone, extend and discard.
    0.
    0, 1.
    0, 1, 3.
    0, 1, 3, 7.
    0, 2, 6, 9. Discarded.
    0, 2, 6, 9, 11.
    ----------------------------------------------------------------------------
    A[15] = 15. Case 2. Clone and extend.
    0.
    0, 1.
    0, 1, 3.
    0, 1, 3, 7.
    0, 2, 6, 9, 11.
    0, 2, 6, 9, 11, 15. <-- LIS List
    ----------------------------------------------------------------------------
    所以代码如下
     1 int binary_search(vector<int>& result, int start,int end,int target){
     2     while(start < end-1){
     3         int mid = (start+end)>>1;
     4         if(result[mid] >= target) end = mid ;
     5         else start = mid;
     6     }
     7     return end;
     8 }
     9 
    10 int lengthOfLIS(vector<int>& nums){
    11     if(nums.empty()) return 0;
    12     vector<int> result;
    13     result.push_back(nums[0]);
    14     for(int i = 1; i < nums.size();i++){
    15         if(nums[i] < result[0]) result[0] = nums[i];
    16         else if(nums[i] > result.back()) result.push_back(nums[i]);
    17         else{
    18             int index = binary_search(result,0,result.size()-1,nums[i]);
    19             result[index] = nums[i];
    20         }        
    21     }
    22     return result.size();
    23 }

    如果你对stl源码足够熟悉,binary_search函数可以用lower_bound()来代替。

    所以简化版代码如下:

    1 int lengthOfLIS(vector<int>& nums) {
    2     vector<int> res;
    3     for(int i=0; i<nums.size(); i++) {
    4         auto it = std::lower_bound(res.begin(), res.end(), nums[i]);
    5         if(it==res.end()) res.push_back(nums[i]);
    6         else *it = nums[i];
    7     }
    8     return res.size();
    9 }

     这里其实也用到了耐心排序的思想,可以看博客了解。http://www.cnblogs.com/kkun/archive/2011/11/23/2260291.html

  • 相关阅读:
    C++11: reference_wrapper
    mac 查看目前哪些进程占用哪些端口
    Intellij IDEA 10.5 语言设置
    linux中的strip命令简介------给文件脱衣服
    HashMap的key可以是可变的对象吗???
    java BIO/NIO/AIO 学习
    java 反射
    Java线程同步
    maven modules
    设计模式在cocos2d-x中的使用--简单工厂模式(Simple Factory)
  • 原文地址:https://www.cnblogs.com/CarryPotMan/p/5388921.html
Copyright © 2011-2022 走看看