zoukankan      html  css  js  c++  java
  • LeetCode300. 最长递增子序列

    ☆☆☆☆思路:本题是经典的LIS问题。两种解法,动态规划 和 二分查找。

    方法1:动态规划。时间复杂度为O(n^2)

    方法2:二分查找,时间复杂度为O(nlogn)

    【举一反三】: (1)该题为不连续的情况,延伸求最长连续递增子序列长度,见LeetCode674. 最长连续递增序列

            (2)除了要会求子序列的长度,还要会求出最长的子序列是什么

    代码1:动态规划

    class Solution {
        /**
         *  dp[i]表示 以nums[i]为结尾的最长上升子序列的长度
         *      初始化:都为 1.每个数都单独是长度为1的上升子序列
         */
        public int lengthOfLIS(int[] nums) {
            if (nums == null || nums.length == 0) return 0;
            int[] dp = new int[nums.length];
            Arrays.fill(dp, 1);
            int res = 1;
            // dp[0]为1, 从 nums[1]开始递推
            for (int i = 1; i < nums.length; i++) {
                for (int j = 0; j < i; j++) {
                    // nums[i] 可以跟在 nums[j] 后面
                    if (nums[j] < nums[i]) {
                        // 以哪个数结尾的最大递增子序列更大,就选其作为倒数第二个数
                        dp[i] = Math.max(dp[i], dp[j] + 1);
                    }
                }
                res = Math.max(res, dp[i]);  // 所有dp[i]中取最大的
            }
            return res;
        }
    }

     补充:如何根据dp数组求出最长递增子序列是什么?------------参考左神P203

        private int[] generateLIS(int[] nums) {
            int[] dp = new int[nums.length];
            Arrays.fill(dp, 1);
            for (int i = 1; i < nums.length; i++) {
                for (int j = 0; j < i; j++) {
                    if (nums[j] < nums[i]) {
                        dp[i] = Math.max(dp[i], dp[j] + 1);
                    }
                }
            }
            // Step1. 遍历dp数组,找到最大值以及位置;
            int len = 0;  // 最大值,也即最长递增子序列的长度
            int index = 0;
            for (int i = 0; i < dp.length; i++) {
                if (dp[i] > len) {
                    len = dp[i];
                    index = i;
                }
            }
            int[] lis = new int[len];
            lis[--len] = nums[index]; // 最长递增子序列以nums[index]结尾
            // Step2. 每次从右向左遍历,寻找当前数的前一个数(满足1.比当前数的值小;2.比当前数对应的dp值小1)
            for (int i = index - 1; i >= 0; i--) {
                if (nums[i] < nums[index] && dp[i] == dp[index] - 1) {
                    lis[--len] = nums[i];
                    index = i;
                }
            }
            return lis;
        }

    代码2:二分查找

    M

  • 相关阅读:
    《C#微信开发系列(2)-自定义菜单管理》
    《C#微信开发系列(1)-启用开发者模式》
    python多进程: multiprocessing Pool 和tqdm
    前端
    python 缓存
    python pymysql
    python paramiko模块
    Linux之TCPIP内核参数优化
    python进程、线程、协程、IO多路复用
    python socket
  • 原文地址:https://www.cnblogs.com/HuangYJ/p/14217172.html
Copyright © 2011-2022 走看看