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

1、题目描述

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

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

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

  题目分析

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

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

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

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

2、用到的算法思想

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

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

3、思路

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

  一样以数组 {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数组找出最大值。

4、代码实现(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; } }

5、完成时间

    2021-01-28  15:48:57

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

相关文章
相关标签/搜索