给你一个整数数组 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
我解这道题用到的有:【动态规划】(Dynamic Programming 简称DP)。io
解题方式并不惟一,不要局限于一种方法。class
动态规划解题四部曲(非准确):找出原问题--->将原问题分解为规模更小的子问题--->当规模小到必定程度时,答案出现或者很容易求出--->将小的问题合并成原来的问题。
循环
一样以数组 {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数组找出最大值。
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等等,须要多加努力。