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

  • 相关阅读:
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    Apache Spark RDD(Resilient Distributed Datasets)论文
    Apache Spark 2.2.0 中文文档
    Apache Spark 2.2.0 中文文档
    【机器学习实战】第10章 K-Means(K-均值)聚类算法
    [译]flexbox全揭秘
  • 原文地址:https://www.cnblogs.com/CarryPotMan/p/5388921.html
Copyright © 2011-2022 走看看