动态规划系列leetcode413、64
前言:这两道题目都不算很难,递推公式不难推导,而且递推公式不会因为考虑不全面导致错误。413题等差数列的个数推导有规律可循。 这两题都是采用我自己的思路写的,还有可以优化的空间。
文章目录
413. 等差数列划分
如果一个数列至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。
例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差数列。
给你一个整数数组 nums ,返回数组 nums 中所有为等差数组的子数组个数。
子数组 是数组中的一个连续序列。示例 1:
输入:nums = [1,2,3,4]
输出:3
解释:nums 中有三个子等差数组:[1, 2, 3]、[2, 3, 4] 和 [1,2,3,4] 自身。来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/arithmetic-slices
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路:
1.递推公式推导:
由于题目规定至少有三个元素,任意两个相邻元素的差相同才能构成等差数列。对于一个包含多个n个元素的等差数列,其所有子数列个数是多少呢?
对于nums = [1,2,3]时,其等差数列个数为1,当nums = [1,2,3,4]其等差数列个数为[1, 2, 3]、[2, 3, 4] 和 [1,2,3,4] ,共三个,除去包含的前一个等差数列数[1, 2, 3]还剩两个。
因此我们可以推导出对于一个长度为n(n>=3)的等差数列,其等差数列个数为长度为n-1的等差数列个数加1,即dp[i] = dp[i-1] +1。
2、初始化:
dp数组全部初始化为0即可。
3、遍历:
我们可以从下标为2的位置开始遍历,每次遍历进行下列判断:
判断与前两个元素是否构成等差元素,若构成则dp[i] = dp[i-1] +1;若不构成则从下一个位置继续判断与前两个元素是否构成等差数列。
int numberOfArithmeticSlices(int* nums, int numsSize) {
if (numsSize < 3) {
return 0;
}
int dp[5000] = {0};
int i = 0, sum = 0;
for(i = 2; i < numsSize; ++i)
{
if(nums[i] - nums[i-1] == nums[i-1] - nums[i-2])
{
dp[i] = dp[i-1]+1;
}
}
for(i = 0; i < numsSize; ++i)
{
sum+=dp[i];
}
return sum;
}
二、64. 最小路径和
给定一个包含非负整数的 m x n 网格 grid ,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。如果一个数列至少有三个元素 ,并且任意两个相邻元素之差相同,则称该数列为等差数列。
例如,[1,3,5,7,9]、[7,7,7,7] 和 [3,-1,-5,-9] 都是等差数列。
给你一个整数数组 nums ,返回数组 nums 中所有为等差数组的子数组个数。
子数组 是数组中的一个连续序列。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/arithmetic-slices
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
输入:grid = [[1,3,1],[1,5,1],[4,2,1]]
输出:7
解释:因为路径 1→3→1→1→1 的总和最小。
1、递推公式推导:
因为每次只能向下或者向右移动,对于[m,n]位置来说,路径选择[m,n-1]和[m-1,n]位置中较小的那个加上自己位置的数字即是该位置的最小路径。
dp[m][n] = min(dp[m][n-1],dp[m-1][n]) + grid[i][j];
2、初始化
对于第0列或者第0行来说只能通过向下或者向右移动到达 ,因此第0列或者第0行的最小路径就是前一个或者上一个位置的路径加上自己位置的数字。
3、遍历顺序
因为已经对第0行、第0列初始化了,所以只要从第1行,第1列开始遍历二维数组即可。
int minPathSum(int** grid, int gridSize, int* gridColSize){
int dp[200][200] = {0};
int i = 0, j = 0, sum = 0;
for(i = 0; i < gridSize; ++i)
{
sum = sum + grid[i][0];
dp[i][0] = sum;
}
sum = 0;
for(i = 0; i < gridColSize[0]; ++i)
{
sum = sum + grid[0][i];
dp[0][i] = sum ;
}
for(i = 1; i < gridSize; ++i)
{
for(j = 1; j < gridColSize[1]; ++j)
{
sum = dp[i][j-1]>dp[i-1][j]?dp[i-1][j]:dp[i][j-1];
dp[i][j] = sum + grid[i][j];
}
}
return dp[gridSize-1][gridColSize[0]-1];
}
总结
由于刚刚接触动态规划,因此写的代码还有优化的空间,这两题的dp数组都可以进行缩小。