当前位置: 首页 > news >正文

力扣——最长递增子序列

题目链接:

链接

题目描述:

在这里插入图片描述

思路:

思路一:动态规划

类似于“单词拆分”,需要遍历之前的元素 对应的最大长度,然后找到最大的
设第 i i i个元素对应的最长递增序列长度是 d p ( i ) dp(i) dp(i),每一个 d p ( i ) dp(i) dp(i)最初都是1

则:当 n u m s [ i ] > n u m s [ j ] nums[i] > nums[j] nums[i]>nums[j] 时,有
d p ( i ) = m a x { d p ( i ) , d p ( j ) + 1 } dp(i) = max\{ dp(i) ,dp(j) + 1 \} dp(i)=max{dp(i)dp(j)+1}
返回dp中的最大值就行

思路二

贪心 + 二分查找

要找最长的递增序列,就期望递增的幅度最小,相同长度下,递增的幅度越小,后面可以满足递增的元素就越多(不一定),按照这种思路写代码会存在一个问题:我们并不知道后面是否会有更多的满足递增的元素,如:0 2 6 7 4,最长的是0 2 6 7,但是按照上面的思路我们会选择0 2 4,

所以,我们也需要记录下已经遍历到的最长的递增序列及长度,我们可以使用一个数组d记录“已经遍历到的最长的递增序列”,如 0 2 6 7 len = 4,

如果有更长的递增序列,d里面的元素就应该被覆盖掉

怎么覆盖呢?当我们遇到更小的元素后,就可以把更小的元素放进d里面合适的位置使d继续满足递增,如0 2 4 7

  • 如果后面有 相对于4 递增的数据(假设原数组是:0 2 6 7 4 5 6):则d变成 0 2 4 5 6,len=5
  • 如果后面是 相对于7 递增的数据(假设原数组是:0 2 6 7 4 8):则d变成 0 2 4 7 8

(这里d从索引1开始存放元素)
总结:

  • 如果 d [ j ] < n u m [ i ] < d [ l e n ] d[j]<num[i] < d[len] d[j]<num[i]<d[len],就把 n u m [ i ] num[i] num[i]放入d数组中间
  • 如果 n u m [ i ] > d [ l e n ] num[i] > d[len] num[i]>d[len],就把 n u m [ i ] num[i] num[i]放入d数组末尾,同时len++

这里 “把 n u m [ i ] num[i] num[i]放入d数组中间”,可以用二分法

注意:最后得到的d数组不一定是最长递增序列,实际上d只能记录某个最长序列的最后一个元素d[len]

实现代码:

class Solution {
    public int lengthOfLIS(int[] nums) {
        if(nums.length == 0) return 0;
        int[] dp = new int[nums.length];//这里直接用 当前元素的位置 存放 最大长度就行
        dp[0] = 1;
        int ans = 1;
        for(int i = 1; i < nums.length; i++){
            dp[i] = 1;
            for(int j = 0; j < i; j++){
                if(nums[i]>nums[j]){
                    dp[i] = Math.max(dp[i],dp[j]+1);
                }
            }
            ans = Math.max(ans,dp[i]);
        }
        return ans;
    }
}
class Solution {
    public int lengthOfLIS(int[] nums) {
        int len = 1, n = nums.length;
        if(n ==0) {
            return 0;
        }

        int[] d = new int[n+1];
        d[len] = nums[0];//的d[1] = nums[0]

        for(int i = 1; i < n; i++){
            if(nums[i]>d[len]){
                d[++len] = nums[i];
            }else{
                int left = 1, right = len, pos = 0;//pos表示d里面小于nums[i]的数的索引
                while(left <= right){
                    int mid = (right -left) / 2 + left;
                    if(d[mid] < nums[i]){
                        pos = mid;
                        left = mid + 1;
                    }else{
                        right = mid - 1;
                    }
                }
                d[pos + 1] = nums[i];
            }
        }
        return len;
    }
}

相关文章:

  • (二)未来十至二十年的信息技术核心领域(AI、数据库、编程语言)完全零基础者的学习路径与技能提升策略
  • StableDiffusion打包 项目迁移 项目分发 0
  • DeepSeek如何辅助学术写作的性质研究?
  • 什么是回调函数
  • Linux版本控制器Git【Ubuntu系统】
  • RPA 与 AI 结合:开启智能自动化新时代
  • Wireshark Lua 插件教程
  • window基于wsl部署vllm流程及踩坑经历(包含cuda toolkit、nvcc版本问题)
  • 【leetcode hot 100 15】三数之和
  • StableDiffusion本地部署 2
  • TCP的三次握手与四次挥手:建立与终止连接的关键步骤
  • pta天梯L1-003 个位数统计
  • 点云配准技术的演进与前沿探索:从传统算法到深度学习融合(3)
  • Linux上用C++和GCC开发程序实现不同MySQL实例下单个Schema之间的稳定高效的数据迁移
  • Android应用app实现AI电话机器人接打电话
  • 【杂谈】-2025年2月五大大型语言模型(LLMs)
  • 有没有比黑暗森林更黑暗的理论
  • YOLO 检测到人通俗易懂的原理
  • AnythingLLM+LM Studio本地知识库构建
  • kotlin的函数标准库使用
  • 商务部新闻发言人就出口管制管控名单答记者问
  • 为何选择上海?两家外企提到营商环境、人才资源……
  • 第78届戛纳电影节开幕,罗伯特·德尼罗领取终身成就奖
  • 第四届长三角国际应急博览会开幕,超3000件前沿装备技术亮相
  • 广东省人大教科文卫委原主任委员梁万里被开除党籍:退休后受贿仍不知止
  • 特朗普开启第二任期首次外访:中东行主打做生意,不去以色列