ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LC 300. 最长递增子序列

2022-02-21 16:03:34  阅读:125  来源: 互联网

标签:... LC nums 300 递增 int -- dp size


class Solution {
    /**
    暴力法 + dp
    思路: 
        dp[i] 表示, 必须以第 i 个位置结束的最长递增子序列的长度
            每到一个位置, 都要回头扫描一遍已经遍历过数组, 如果存在
            比当前位置的数值小的数组, 从他的 dp 中获取它的长度 + 1
            可以得到 dp[i] 位置当前的一个可能取值, 去 0...i - 1 
            这段区间中所有可能取值的最大值, 就是 dp[i] 位置的答案, 
            如果 0...i - 1 这段区间的数值都比 nums[i] 大, 那么 
            dp[i] = 1 
     */
    public int lengthOfLIS(int[] nums) {
        int N = nums.length;
        if (N == 1) return 1;   // 如果数组长度位置, 那么最长递增子序列就是 1
        // dp[i] 表示, 必须以第 i 个位置结束的最长递增子序列的长度
        int[] dp = new int[N];
        dp[0] = 1;  // dp[0] 必为 1
        int ans = 1;
        for (int i = 1; i < N; i++) { 
            dp[i] = 1;
            // 扫描 0...i-1 区域的可能取值
            for (int j = i - 1; j >= 0; j--) {
                if (nums[i] > nums[j])  // 找到一个可能取值
                    // 取最大的那个
                    dp[i] = Math.max(dp[j] + 1, dp[i]);
            }
            ans = Math.max(ans, dp[i]);
        }
        return ans;
    }
}
class Solution {
    /**
    二分 + dp
    思路: 
        dp 数组含义, 到达 i 位置的最长递增子序列是谁
            先在 dp 数组的有效区域找到第一个比 当前数值 nums[i] 大的
        用 nums[i] 去更新这个数; 找不到就追加在最后, size++
        比如:    [10,9,2,5,3,7,101,18]
        i == 0, 10  --> size = 1, dp = [10,0....]      // 0....表示无效区域
        i == 1, 9   --> size = 1, dp = [9,0....]
        i == 2, 2   --> size = 1, dp = [2,0....]
        i == 3, 5   --> size = 2, dp = [2,5,0...]       
        i == 4, 3   --> size = 2, dp = [2,3,0...]
        i == 5, 7   --> size = 3, dp = [2,3,7,0...]
        i == 6, 101 --> size = 4, dp = [2,3,7,101,0...]
        i == 7, 18  --> size = 4, dp = [2,3,7,18,0...]

        因为 dp 数组是有序, 所以我们能通过二分查找快速确定要找的位置
        整体时间复杂度 O(n * log n)
     */

    public int lengthOfLIS(int[] nums) {
        int N = nums.length;
        if (N == 1) return 1;
        int[] dp = new int[N];
        int size = 1;

        dp[0] = nums[0];
        for (int i = 1; i < N; i++) {
            // 找 dp 数组中第一个比 nums[i] 大
            int mostLeftBigIndex = search(dp, size, nums[i]);
            if (mostLeftBigIndex == -1) {
                // 如果找不到, 在后面追加
                dp[size++] = nums[i];
            } else {
                // 找到了, 用当前位置的值, 更新 dp 的对应位置
                dp[mostLeftBigIndex] = nums[i];
            }
        }
        return size;
    }
    // 二分查找, 找数组中第一个比 key 大
    private int search(int[] dp, int size, int key) {
        int l = 0, r = size - 1;
        int res = -1;
        while (l <= r) {
            int m = (l + r) / 2;
            if (dp[m] >= key) {
                res = m;
                r = m - 1;
            } else {
                l = m + 1;
            }
        }
        return res;
    }
}

 

标签:...,LC,nums,300,递增,int,--,dp,size
来源: https://www.cnblogs.com/yxqc1223/p/15919219.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有