zoukankan      html  css  js  c++  java
  • [LeetCode每日1题][中等] 300. 最长上升子序列

    题目

    300. 最长上升子序列 - 力扣(LeetCode)
    在这里插入图片描述

    DP解法

    思路

    开一个长度与原数组相同的数组dp,初始值dp[0]=1。dp数组元素的含义是:到当前索引为止,最大的递增子序列长度。接下来开始遍历数组,设当前索引为index,在0..index范围内,找出小于当前元素的那些元素,它们对应的dp值中的最大值+1,即为本轮结果。遍历完成后,dp数组中的最大值即为答案。

    复杂度分析

    O(n2)

    实现

    class Solution {
    public:
        int lengthOfLIS(vector<int>& nums) {
            if(nums.size()<2) return nums.size();
            vector<int> dp(nums.size());
            dp[0] = 1;
            int ans = dp[0];
            for(int i = 0; i < dp.size(); i++) {
                int maxval = 0;
                for(int j = i-1 ; j >= 0; j--) {
                    if(nums[j] < nums[i]) {
                        maxval = max(maxval,dp[j]);
                    }
                }
                dp[i] = maxval + 1;
                ans = max(ans,dp[i]);
            }
            return ans;
        }
    };
    

    贪心+二分解法

    思路

    开一个tails数组,tails[1] = nums[0],元素的含义为:当递增子序列的长度为index时,对应长度子序列的最后一个值(我们希望这个值尽可能小)。然后开始遍历原数组,如果当前元素大于 tails数组最后一个有效元素(最后一个非初值的元素),则说明子序列长度可以增长,tails[++index] = 当前元素。否则,二分查找tails数组中最后一个小于当前元素的那个元素索引,更新tails[这个索引+1] = 当前元素。最后的index即为答案。

    复杂度分析

    O(nlogn)

    实现

    class Solution {
    public:
        int lengthOfLIS(vector<int>& nums) {
            if(nums.size()<2) return nums.size();
            vector<int> tails(nums.size()+1);
            int len = 1;
            tails[len] = nums[0];
            for(int i=1;i<nums.size();i++) {
                if(tails[len]<nums[i]) tails[++len] = nums[i];
                else {
                    int pos = 0, begin = 1,end = len;
                    while(begin<=end) {
                        int mid = begin + (end-begin)/2;
                        if(tails[mid]<nums[i]) {
                            pos = mid;
                            begin = mid+1;
                        } else {
                            end = mid-1;
                        }
                    }
                    tails[pos+1] = nums[i];
                }
            }
            return len;
        }
    };
    

    一种更简洁的写法

    class Solution {
    public:
    	int lengthOfLIS(vector<int>& nums) {
    		vector<int> minnums;
    		for (int v : nums) {
    			if (minnums.size() == 0 || v > minnums.back())
    				minnums.push_back(v);
    			else {
    				auto it = lower_bound(minnums.begin(), minnums.end(), v);
    				*it = v;
    			}
    		}
    		return minnums.size();
    	}
    };
    

    参考

    官方题解
    方法二图解
    [笔记]二分查找的几种写法_EvergIow的博客-CSDN博客

  • 相关阅读:
    ubuntu下minicom和usb串口转接
    linux下 驱动模块编译步骤
    linux下的压缩解压命令
    GitLab 数据备份和恢复
    GitLab 项目创建后地址由Localhost改为实际IP的方法
    GitLab-Runner 安装配置
    GitLab 的安装及汉化
    用yum rpm 快速安装zabbix agent
    RabbitMQ的用户管理方法
    Linux下安装部署RabbitMQ
  • 原文地址:https://www.cnblogs.com/zaynq/p/12679076.html
Copyright © 2011-2022 走看看