2.动态规划设计:最长递增子序列

dp数组的遍历方向

我相信读者做动态规划问题时,肯定会对dp数组的遍历顺序有些头疼。我们拿二维dp数组来举例,有时候我们是正向遍历:
//正向遍历
int[][] dp = new int[m][n];  
for (int i = 0; i < m; i++)  
	 for (int j = 0; j < n; j++)  
	 // 计算 dp[i][j]
//有时候也会反向遍历
for (int i = m - 1; i >= 0; i--)  
 for (int j = n - 1; j >= 0; j--)  
 	// 计算 dp[i][j]
// 斜着遍历数组  
for (int l = 2; l <= n; l++) {  
 for (int i = 0; i <= n - l; i++) {  
	 int j = l + i - 1;  
	 // 计算 dp[i][j]  
	 }  
}

那么,如果仔细观察的话可以发现其中的原因的。你只要把住两点就行了:

1、遍历的过程中,所需的状态必须是已经计算出来的

2、遍历的终点必须是存储结果的那个位置

最长递增子序列(LeetCode 300题 难度:中等)

动态规划的核心就是数学归纳法

			先假设这个结论在k<N时候成立,那么根据这个假设,在想办法,推出在k=N时结论也成立,如果能够证明出来,那么对于任意的k 就都成立了

难点:定义清楚dp数组到底代表什么?

	我们这样定义:dp[i]表示以nums[i]这个数字结尾的最长递增子序列
	解释:
		现在我们想求dp[5]的值,那么也就是要求以nums[5]为结尾的这个数的最长递增子序列
		nums[5]=3,既然是递增子序列,只要找到前面那么结尾比3小的子序列,然后把3接到最后面,就可形成新的递增子序列,而且长度要+1;

//初始条件
// 因为最小 是 1
Arrays.fill(dp,1);

for (int i = 0; i < nums.length; i++) {  
    for (int j = 0; j < i; j++) {  
        if(nums[i]>nums[j]){  
            //求 nums[5]的递增子序列,只需要找到5前面的某个 比5小的数字的 子序列然后 +1(自己)  
			 //找第五个数的递增子序列,只需要找到 前面比5小的那个数字的 递增子序列 然后 +自己  
 			dp[i]=Math.max(dp[i],dp[j]+1);  
        }  
    }  
	//保存一下递增子序列的最大值
    res=Math.max(dp[i],res);  
}

至此 这道题的就完结啦、、、、

二分搜索解法:

不讲啦太麻烦啦

posted @ 2021-07-05 23:10  宋佳强  阅读(64)  评论(0)    收藏  举报