leetcode300. 最长上升子序列升子序列

给定一个无序的整数数组,找到其中最长上升子序列的长度。

输入: [10,9,2,5,3,7,101,18]
输出: 4 
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4

1,动态规划,(本题动态规划是比较好理解的,但显然效率比较低)

int lengthOfLIS(vector<int>& nums) {
        int len=nums.size();
        int maxlen=0;
        //if(len==0) return 0;
        //if(len==1) return 1;
        vector<int> dp(len,1)for(int i=0;i<len;i++){
            for(int j=0;j<i;j++){
                if(nums[j]<nums[i])
                    dp[i]=max(dp[i],dp[j]+1);           
                                  
            }
            maxlen=max(maxlen,dp[i]); 
        }
        return maxlen;
    }

dp[i] 表示以 nums[i] 这个数结尾的最长递增子序列的长度。
当时作此题时,dp数组习惯初始化为0.,结果一直不对,比结果少一,。后来参考了,才知道**dp需要初始化为1,**这样进行理解,不管整体结果,本身当前值就是一个最小子序列,长度为1。
时间复杂度 O(N^2)。

2,二分查找(真的很难想到,也不好理解)(在安利一次啊,不明白流程如何操作循环的,去debug一下l)
纸牌方法解释此题

在这里插入图片描述
每次处理一张扑克牌不是要找一个合适的牌堆顶来放吗,牌堆顶的牌不是有序吗,这就能用到二分查找了:用二分查找来搜索当前牌应放置的位置。

int lengthOfLIS(vector<int>& nums) {
        int len=nums.size();
        vector<int> res(len);
        int maxlen=0;
        //for(int num : nums){
           //int num=nums[i];
           
        //按照左侧边界进行二分查找
        for(int i=0;i<len;i++){
            //要处理的扑克牌
           
            int left=0,right=maxlen;
            while(left<right){
                int mid=(left+right)/2;
                if(res[mid]<nums[i])
                    left=mid+1;
                else
                    right=mid;
            }
            /*********************************/
        
            // 没找到合适的牌堆,新建一堆
            if(maxlen==left)
                maxlen++;
                // 把这张牌放到牌堆顶
            res[left]=nums[i];           
        }
        return maxlen;
    }
    int main() {
        vector<int> nums{ 6,3,5,10,11,2,9,14,13,7,4,8,12 };
        lengthOfLIS(nums);
        return 0;
    }

二分搜索

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值