Leetcode 300 Longest Increasing Sequence
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
分析
dp解法,啥时候用dp呢
dp[i]: nums[i]为结尾的最长递增序列长度nums: [10, 9, 2, 5, 3, 7, 101, 18]
对应dp: [1, 1, 1, 2, 2, 3, 4, 4]dp中最大值即为最长递增序列长度
如何求解dp呢?
dp[i] = max( dp[j](j∈0-i-1) && nums[j] < nums[i] )
动态规划问题的基本特征
- 最优子结构
母问题的最优解包含其子问题的最优解,我们就称此问题具有最优子结构。即也就是说,子问题最优时,母问题通过优化一定能求得最优解- 子问题重叠
子问题本质上是和母问题一样的,只是问题的输入参数不一样,就可以称之为子问题重叠,这是动态规划解决问题的高效的本质所在,我们可以利用很多子问题具有相同的输入参数这一个性质,来减少计算量。- 问题存在边界
子问题在一定情况下就不存在子问题了, 我们称这种情况为问题存在边界,对于自顶向上和自底向下的方法,边界分别是问题的出口和入口。- 子问题相互独立
个子问题在求解最优解时事相互独立的,即本子问题的求解和其他平行子问题是不相干的。当平行子问题解决后,选择权交给母问题时,它才会考虑各子问题之间的关系,是求最大值还是最小值,还是要做相关的运算得到母问题的最优解。
解法
dp
public class Solution {
public int lengthOfLIS(int[] nums) {
if(nums.length <=1) return nums.length;
int[] dp = new int[nums.length];
int longest = 1;
dp[0] = 1;
for(int i=1;i<nums.length;i++){
int temp = 0;
for(int j=0;j<i;j++){ //精髓
if(nums[j]<nums[i] && dp[j]>temp){
temp = dp[j];
}
}
dp[i] = temp+1;
longest = Math.max(longest, dp[i]); // 边求dp,边求最大值
}
return longest;
}
}
这里没有什么背景,有些题目喜欢加上背景,要去理解题意,抓住问题核心:最长递增序列