leetcode300题最长上升子序列(动态规划和非规划实现)

题目:

给定一个无序的整数数组,找到其中最长上升子序列的长度。

示例:

输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

说明:

    可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
    你算法的时间复杂度应该为 O(n2) 。

进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?

直接上代码,代码中有分析:

第一个方法动态规划实现代码复杂度较低,leetcode跑分地

第二种结合2分法效率较高


public class 最长上升子序列 {

    /**
     * 动态规划实现:
     * 第一步:定义dp数组dp[i] 代表扫描到第i个点的时候,加入i的最长上升子序列(这里注意是i一定要加入的时候的最长子序列),
     * 加入i以后通过循环找   0到i-1的节点 中小于nums[i]的最大上升子序列就是当i加入后的dp[i]
     * 结果:遍历n个节点取最大的上升子序列dp
     * 时间复杂度:O(n平方)
     * <p>
     * <p>
     * 另外还有O(n log n)的时间复杂度就和动态规划没有关系了,是另外一种解法:
     * 每次dp[i]只存当遍历到i的时候通过二分查找nums[i]的值在dp中的位置。替换(注意是替换,长度是不变的)
     * 为什么要这样?因为这样保证dp中的元素是有序的可以使用二分查找,另外通过替换最小值,可以使后续节点更好的加入dp中举个例子:
     * <p>
     * nums = 11,12,13,1,2,3,4,5
     * 第1步dp=11
     * 第2步dp=11,12
     * 第3步dp =11,12,13
     * 第4步dp = 1,12,13
     * 第5步dp =1,2,13
     * 第6步dp=1,2,3
     * 第7步dp=1,2,3,4
     *
     * @param nums
     * @return
     */
    public static int lengthOfLIS(int[] nums) {
        if (nums == null || nums.length == 0) {
            return 0;
        }
        int ans = 1;
        int n = nums.length;
        //第一步定义dp方程
        int dp[] = new int[n];
        dp[0] = 1;
        //第二步刻画状态转移方程
        for (int i = 1; i < n; i++) {
            int temp = -Integer.MAX_VALUE;
            for (int j = i - 1; j >= 0; j--) {
                if (nums[j] < nums[i]) {
                    temp = Math.max(dp[j], temp);
                }
            }
            dp[i] = temp == -Integer.MAX_VALUE ? 1 : temp + 1;
        }
        //打印答案
        for (int l = 0; l < n; l++) {
            ans = Math.max(ans, dp[l]);
        }
        return ans;
    }

    //二分法
    public static int lengthOfLIS2(int[] nums) {
        int[] dp = new int[nums.length];
        int len = 0;
        for (int num : nums) {
            int i = Arrays.binarySearch(dp, 0, len, num);
            if (i < 0) {
                i = -(i + 1);
            }
            dp[i] = num;
            if (i == len) {
                len++;
            }
        }
        return len;
    }


    public static void main(String[] args) {
        int[] nums = {-2, -1};
        System.out.println(lengthOfLIS(nums));
    }
发布了23 篇原创文章 · 获赞 4 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq1076472549/article/details/103955243