• 每日一题 300最长递增子序列(贪心+二分)(灵神模版)


    题目

    LIS
    给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

    子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

    示例 1:

    输入:nums = [10,9,2,5,3,7,101,18]
    输出:4
    解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。
    示例 2:

    输入:nums = [0,1,0,3,2,3]
    输出:4
    示例 3:

    输入:nums = [7,7,7,7,7,7,7]
    输出:1

    提示:

    1 <= nums.length <= 2500
    -104 <= nums[i] <= 104

    题解

    子集型回溯

    回溯三问

    1. 当前问题:以nums[i]结尾的LIS
    2. 当前操作:枚举nums[j]
    3. 下一个子问题:以nums[j]结尾的LIS
    //记忆化搜索
    class Solution {
        private int[] nums, cache;
    
        public int lengthOfLIS(int[] nums) {
            this.nums = nums;
            int n = nums.length;
            cache = new int[n];
            int res = 0;
            for (int i = 0; i < n; i++) {
                res = Math.max(res, dfs(i));
            }
            return res;
        }
    
        private int dfs(int i) {
            if (cache[i] > 0) {
                return cache[i];
            }
            for (int j = 0; j < i; j++) {
                if (nums[j] < nums[i]) {
                    cache[i] = Math.max(cache[i], dfs(j));
                }
            }
            //最后需要加上nums[i],因此需要+1
            return ++cache[i];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    递推

    //递推
    class Solution {
        public int lengthOfLIS(int[] nums) {
            int n = nums.length;
            int[] f = new int[n];
            int res = 0;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < i; j++) {
                    if (nums[j] < nums[i]) {
                        f[i] = Math.max(f[i], f[j]);
                    }
                }
                res = Math.max(res, ++f[i]);
            }
            return res;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    贪心+二分

    g[i]表示长度为i+1的IS(递增子序列)的最小值
    例如,nums=[1,6,7,2,4,5,3]
    nums = 1
    nums = 1 6
    nums = 1 6 7
    nums = 1 2 7
    nums = 1 2 4
    nums = 1 2 4 5
    nums = 1 2 3 5

    class Solution {
       public int lengthOfLIS(int[] nums) {
           List<Integer> g = new ArrayList<>();
           for (int x : nums) {
               int j = lowerBound(g, x);
               if (j == g.size()) {
                   g.add(x);
               } else {
                   g.set(j, x);
               }
           }
           return g.size();
       }
    
       public int lowerBound(List<Integer> g, int target) {
           int left = 0, right = g.size() - 1;
           while (left <= right) {
               int mid = (right - left) / 2 + left;
               if (g.get(mid) < target) {
                   left = mid + 1;
               } else {
                   right = mid - 1;
               }
           }
           return left;
       }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    空间优化

    class Solution {
        public int lengthOfLIS(int[] nums) {
            int ng = 0;
            for (int x : nums) {
                int j = lowerBound(nums, ng - 1, x);
                nums[j] = x;
                if (j == ng) {
                    ng++;
                } 
            }
            return ng;
        }
    
        public int lowerBound(int nums[], int right, int target) {
            int left = 0;
            while (left <= right) {
                int mid = (right - left) / 2 + left;
                if (nums[mid] < target) {
                    left = mid + 1;
                } else {
                    right = mid - 1;
                }
            }
            return left;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
  • 相关阅读:
    C语言经典例题-17
    免费的ChatGPT与StableDiffusion AI绘画 二合一 附在线地址
    DRM全解析 —— plane详解(4)
    B3627 立方根
    个人服务器到期,项目下线,新的开始
    RabbitMQ集群配置以及负载均衡配置
    JS实现关闭网页广告弹窗特效
    题目 1074: 数字整除
    Nacos 的安装与服务的注册
    arcgis js 缓冲区分析(GP服务)
  • 原文地址:https://blog.csdn.net/fffffall/article/details/133821539