时间:2019-07- 29 到 2019-08-02
题目类型:
1.动态规划
303(区域和检索,数组不可变) 简单,求数组num[i]到num[j]的和
300(最长上升子序列)
初始值,dp[0] = 1;
状态转移方程:
for(int i = 1; i < n; i++)
{
int temp = 0;
for(int j = 0; j < i; j++)
{
if(nums[i] > nums[j])
{
temp = max(temp,dp[j]);
}
}
dp[i] = temp + 1;
//cout<<i<<" "<<dp[i]<<endl;
if(dp[i] > maxV)
maxV = dp[i];
}
}
279(完全平方数)
思路:dp[n]数组中初始值为n,即最大为n = 1 + 1 + 1 + 1 ······,然后从sqrt(n) -- 1,找到dp[n] = min(dp[n],dp[n-j*j]+1);
代码:
for(int i = 0; i <= n; i++)
{
dp[i] = i;
for(int j = sqrt(i); j > 0; j--)
{
dp[i] = min(dp[i],dp[i-j*j]+1);
}
}
总结:第一次没做出来,以为n很大,不能申请足够大的数组长度,结果测试用例根本没那么大。leetcode上很多问题的描述都不明确,经常不给n的范围,数组大小限制。
746(使用最小花费爬楼梯) dp[i] = min(dp[i-1],dp[i-2]) + cost[i]; 简单
264(丑数Ⅱ)
dp[1] = 1;
for(int i = 2; i <=n ;i++)
{
int temp = min(2*dp[n2],min(3*dp[n3],5*dp[n5]));
if(temp == 2 * dp[n2]) n2++;
if(temp == 3 * dp[n3]) n3++;
if(temp == 5 * dp[n5]) n5++;
dp[i] = temp;
}
221(最大正方形)
思路:构造一个二维数组dp[][],代表第i行,第j列的位置的边长,初始化dp数组值等于matrix数组值
if(matrix[i][j] == '1') dp[i][j] = min(dp[i-1][j],min(dp[i][j-1],dp[i-1][j-1])) + 1;
代码:
for(int i = 1; i < m; i++)
{
for(int j = 1; j < n; j++)
{
if(matrix[i][j] == '1')
{
//cout<<dp[i-1][j]<<" "<<dp[i][j-1]<<" "<<dp[i-1][j-1]<<endl;
dp[i][j] = getMin(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]) + 1;
//cout<<i<<" "<<j<<" "<<dp[i][j]<<endl;
if(max < dp[i][j])
max = dp[i][j];
}
}
}
213(打家劫舍Ⅱ)
思路:去掉第一个元素和去掉最后一个元素分别求一个dp数组,取最大值为结果
509(斐波那契数) 同 70(爬楼梯)
思路:dp[i] = dp[i-1] + dp[i-2];
64(最小路径和)
思路:dp[i][j] = min(dp[i][j-1],dp[i-1][j]) + grid[i][j];
63(不同路径Ⅱ)
思路:dp[i][j] = dp[i][j-1]+dp[i-1][j];
62(不同路径)
思路:同上, dp[i][j] = dp[i-1][j] + dp[i][j-1];
53(最大子序和)
思路:dp[i+1] = max(dp[i]+nums[i],nums[i]);
总结:
动态规划问题刚入门,很多东西都还不清楚,做题总是上来就找动态转移方程,找不到方程就感觉很难下手。
动态规划知识参考: