【leetcode】300. Longest Increasing Subsequence(c/c++)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/maotianyi941005/article/details/81330389

原题链接

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?

我的代码:

思路:参考-》(我的代码基本是参考这位大神的了,因为自己的做法考虑不全,不知道怎么写了

           开辟一个vector maxlis存数组nums每一位之前(包含这一位)的最长递增序列长度,即maxlis[i]记的是nums[i]的最长递增长度,

         maxlis数组初始化全为1,因为最短为自己为一个递增序列,长度为1;

        maxlis[i]的计算规则是:遍历 j = 0...i-1,  maxlis[i] = max(maxlis[j] + 1)  if (nums[j] < nums[i])

        lisNum存的是全局最长递增序列长度,即max(maxlis][]),maxlis[i]计算完毕后进行比较记录。

 int lengthOfLIS(vector<int>& nums) {
       
          vector<int> maxlis(nums.size(),1);
          int len = nums.size();
          int lisNum = 1;
          int i,j;
          if(len == 0 || len == 1) return len;
          else{

             for(i = 1;i < len; i++) {
                 for (j = 0; j < i; j++) {
                        if (nums[i] > nums[j]) maxlis[i] = max(maxlis[j] + 1, maxlis[i]);
                 }
                 if (maxlis[i] > lisNum) lisNum = maxlis[i];
                }

         }
        return lisNum;


    }

完整调试代码

//
// Created by maotianyi on 2018/8/1.
//

#include<iostream>
#include <cstdio>
#include <vector>
using namespace std;


int main(){
    vector<int> nums = {10,22,9,33,21,50,41,60,80};
    vector<int> maxlis(nums.size(),1);
    int len = nums.size();
    int lisNum = 1;
    int i,j;
    if(len == 0 || len == 1) return len;
    else{

        for(i = 1;i < len; i++) {
            for (j = 0; j < i; j++) {
                if (nums[i] > nums[j]) maxlis[i] = max(maxlis[j] + 1, maxlis[i]);
            }
            if (maxlis[i] > lisNum) lisNum = maxlis[i];
        }

    }
    printf("%d",lisNum);


    return 0;
}

大神的算法2:(动态规划 二分查找)O(nlogn)

      help[i]表示最长子序列长度为i时的最小的结尾num值(例如在数组[1,2,5,3,7]中,长度为3的子序列有[1,2,3],[1,2,5],[2,5,7]三个,取最小的结尾数字,那么help[3]=3)。

     对于数字m,我们只需要找到找到最大的满足help[j] < m的j,那么就意味着把m接在help[j]这个数字后面就可以了,这个子序列的长度是j+1,同时我们需要判断m是否比原来的help[j+1]小,如果m更小的话就需要更新help[j+1]=m,这一定是一个单调递增的数组(因为要求子序列必须是单调递增的,那么序列长度为i+1的子序列最后一个数字一定比序列长度为i的子序列最后一个数字要大),那么我们就可以通过二分查找来找到满足条件的j,因此把原来查找的复杂度由O(n)降为O(logn)。

    时间复杂度分析:如上分析,对于每个m,复杂度为O(logn),有n个数字,因此时间复杂度为O(nlogn),需要额外的help数组,空间复杂度为O(n)。

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        if(nums.size()==0)
            return 0;
        vector<int> help(nums.size()+1,0);
        help[1] = nums[0];
        int maxlen = 1;
        for(int i= 1;i<nums.size();i++){
            int left = 1;
            int right = maxlen;
            while(left<=right){//二分查找
                int mid = (left+right)/2;
                if(help[mid]<nums[i])
                    left = mid+1;
                else
                    right = mid-1;
            }
            help[left] = nums[i];//维护help数组
            if(left>maxlen)//left值是nums[i]的子序列长度
                maxlen=left;
        }
        return maxlen;
    }
};

作者:cornerCao
链接:https://www.acwing.com/solution/leetcode/content/287/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

猜你喜欢

转载自blog.csdn.net/maotianyi941005/article/details/81330389