算法刷题(LeetCode:300、最长递增子序列)

一、题目描述

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

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

  来源:力扣(LeetCode)
  链接:https://leetcode-cn.com/problems/longest-increasing-subsequence

  题目分析

    如他的题目所描述,需要求出【最长递增子序列】的【长度】。

    几个关键词:最长、严格递增、长度。

    此处的严格递增指:1,2,7,7的最长递增子序列长度为3,因为7和7相等,没有递增。

    举几个例子:如{0,3,1,6,2,2,7}它的递增子序列有:{0,3,6,7} ,{0,1,6,7}, {0,1,2,7}以及一些更短的递增子序列,而我们的目标就是求出这些子序列中长度的最大值。

二、用到的算法思想

  我解这道题用到的有:【动态规划】(Dynamic Programming 简称DP)。

  解题方式并不唯一,不要局限于一种方法。

三、思路

  动态规划解题四部曲(非准确):找出原问题--->将原问题分解为规模更小的子问题--->当规模小到一定程度时,答案出现或者很容易求出--->将小的问题合并成原来的问题。

  同样以数组 {0,3,1,6,2,2,7}为例:

    我们可以很容易的有一种思路,前6个数的最长递增子序列,前5个数.........

    验证这种思路是否可行:

      {0,3,1,6,2,2,7} 的最长子序列长度为4,此时7在最长子序列当中。

    在去掉7以后数组变为

      {0,3,1,6,2,2} 最长子序列为3。说明7在最长子序列中,除去也不影响子问题的解。

    再将最后的2一处数组,变为:

      {0,3,1,6,2} 最长子序列依旧为3,说明除去的2不在最长子序列中,除去依旧不影响子问题的解。

    ......省略.....

    由此可见,无论被移除数组的那一位是否在最长子序列中,都不影响子问题的解。因此,这个问题具有【最优子结构性质】。

    所以,我们已经无限接近答案了:

      建立一个dp数组,长度为【数组长度+1】。

      初始化:dp[0] = 0; dp[i] = 1; (i = 1,2,3...n);

      接着为表中填入数据,从数组arr第1位开始:填入1;

                    第2位:arr[1]与arr[0]比较,看arr[1]是否>arr[0](即是否递增),如果递增,则判断dp[i+1]和dp[i] + 1两者谁大。

                    第3位:同2,但是需要循环,直到数组下标为0的位置.......

      {0,3,1,6,2,2,7} 填入的最终dp数组应该为: {0, 1, 2, 2, 3, 3, 3, 4}。

    需要注意的是:最大值不一定在dp数字最后一位,如:{0,3,1,6,2,2,7,0,0,0} 它最终的dp数组为:{0, 1, 2, 2, 3, 3, 3, 4, 1,1, 1}, 所以需要循环一次dp数组找出最大值。

四、代码实现(Java)

class Solution {
    public int lengthOfLIS(int[] nums) {
        int[] dp = new int[nums.length+1];
        dp[0] = 0;
        for(int i = 0; i < nums.length; i++){
            dp[i+1] = 1;
            for(int j = i; j >= 0; j--){
                if(nums[i] > nums[j]){
                    dp[i+1] = getMax(dp[j+1]+1, dp[i+1]);
                }
            }
        }
        int max = 0;
        for(int i = 0; i <= nums.length; i++){
            if(dp[i] > max)
                max = dp[i];
        }
        return max;
    }
    public int getMax(int m, int n){
        return m > n ? m : n;
    }
}

五、完成时间

    2021-01-28  15:48:57

    最近几天在研究动态规划,刷了七八道题,渐渐地有了一些感觉,但动态规划也分好多种类,比如区间dp,背包dp,树形dp等等,需要多加努力。

 

posted @ 2021-01-28 15:52  新衫如旧  阅读(142)  评论(0)    收藏  举报