第一遍刷了一些动态规划的题目,很多只能参考别人的思路后写出来的。但还是没有掌握动态规划的精髓,所以回过来重新来一遍,并记录一下解题思路,以及每道题目的优化的方法。
- 题目:404. 一和零
给你一个二进制字符串数组 strs 和两个整数 m 和 n 。
请你找出并返回 strs 的最大子集的大小,该子集中 最多 有 m 个 0 和 n 个 1 。
如果 x 的所有元素也是 y 的元素,集合 x 是集合 y 的 子集 。
普通解法
- dp数据定义
定义dp[m+1][n+1],意义为当前有i个0,j个1时子集的个数。 - 转换公式
dp[i][j] = max(1 + dp[i - n0][j - n1], dp[i][j]);
n0 表示当前字符串所包含的0的个数,n1表示包含的1的个数;
//核心代码
for (int z = m; z >= n0; z--){
for (int o = n; o >= n1; o--){
dp[z][o] = max(1 + dp[z - n0][o - n1], dp[z][o]);
}
}
/**
* 选取一个字符串后,将每种可能(即z个0,o个1,且满足题意的情况)都取子串个数的最大值
* dp[m][n]既是最终的结果。
**/
- 题目:300. 最长递增子序列
给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。
子序列是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。
普通解法
- dp数组定义
定义dp[len],len为整数数组长度。表示从0到第i个位置子串所能构成满足题意的子序列最大长度。 - 核心代码
int j = i -1;
while (j >= 0)
{
if (nums[j] < nums[i]){
dp[i] = max(dp[j] + 1, dp[i]);
}
j--;
}
// 对于第i个元素,需要遍历i之前所有比nums[i]小的元素所能构成最大子序列。
该方法时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)
我也试了从后往前遍历,即i从len-2开始递减到0,计算到len-1位置,所能构成子序列的方式,用时少了一倍。
- 题目:978. 最长湍流子数组
当 A 的子数组 A[i], A[i+1], …, A[j] 满足下列条件时,我们称其为湍流子数组:
若 i <= k < j,当 k 为奇数时, A[k] > A[k+1],且当 k 为偶数时,A[k] < A[k+1];
或 若 i <= k < j,当 k 为偶数时,A[k] > A[k+1] ,且当 k 为奇数时, A[k] < A[k+1]。
也就是说,如果比较符号在子数组中的每个相邻元素对之间翻转,则该子数组是湍流子数组。
返回 A 的最大湍流子数组的长度。
普通解法
- dp数组定义
定义dp[len],len为整数数组长度。表示加入当前元素后所能构成最大的子数组的长度。 - 转换公式
如果arr[i] < arr[ i -1] 且 arr[i] < arr[i + 1], 或者 arr[i] > arr[ i -1] 且 arr[i] > arr[i + 1],则当前dp[i] = dp[i - 1] + 1 - 关键代码
bool is_up = arr[1] < arr[0] ? true : false;
// dp[0] = 1;
for (size_t i = 1; i < len; i++)
{
if (arr[i] == arr[i - 1]){
is_up = -1;
}
else if ((is_up == 1 && arr[i] < arr[i - 1]) ||
(is_up == 0 && arr[i] > arr[i - 1])){
dp[i] = dp[i - 1] + 1;
max_l = max_l < dp[i] ? dp[i] : max_l;
is_up = 1 - is_up;
}else{
if (arr[i] < arr[i - 1]){
dp[i] = 2;
is_up = 0;
}else if(arr[i] > arr[i - 1]){
dp[i] = 2;
is_up = 1;
}
}
}
- Reference
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-turbulent-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
4万+

被折叠的 条评论
为什么被折叠?



