day4
最小路径和
- 动态规划,会了最小路径那道题,这一个也差不多。走到每一个格子,最小的路径和都是当前格子的数+min(左边格子的最小路径和,右边格子的最小路径和);换成递推公式也就是
dp[m][n] = min(dp[m-1][n], dp[m][n-1]) + grid[m][n]。要是想优化内存,只需要创建dp[n],采用公式dp[n] = min(dp[n-1], dp[n]) + grid[m][n],也就是用i=1; i<n; ++i遍历dp,在区间(i,n)记录的是上一行格子的最小路径和、区间[1,i]记录的是当前行格子的最小路径和
int minPathSum(vector<vector<int>>& grid) {
int m = grid.size(), n=grid[0].size();
vector<int> dp = grid[0];
// 初始化dp数组为第一行格子的最小路径和
int i=1;
for(; i<n; ++i){
dp[i] += dp[i-1];
}
for(i=1; i<m; ++i){
// 先更新当前行的最左侧格子,再往右更新格子的路径和
dp[0] += grid[i][0];
// 递推公式:dp[n] = min(dp[n-1], dp[n]) + grid[m][n];
for(int j=1; j<n; ++j){
dp[j] = min(dp[j-1], dp[j])+grid[i][j];
}
}
return dp[n-1];
}
跳跃游戏
- 从0开始想要走到最后的格子,必然能在每一个格子都有多余的步数可以走下去。直接记录每一个格子最大的可前进步数,如果还没走到最后但可前进步数为0,则返回false
bool canJump(vector<int>& nums) {
if(nums.size()<2) return true;
// 每一次都选择状态最大的
int status = nums[0];
int i=0;
for(; status>0 && i<nums.size(); ++i){
--status;
if(nums[i] > status) status = nums[i];
}
return i==nums.size();
}
我一开始的思路是暴力记录每一个位置拥有的状态,要是所有的状态都减为0且当前位置不是最后一个,就说明不能到达最后一个位置;我当时采用vector记录所有的步子,每移动一个位置,vector中所有数字-1,要是有元素为0则删除,实时监测vector是否为空。最后卡在删除为0元素这一步。
买卖股票的最佳时机
int maxProfit(vector<int>& prices) {
// 一个tag记录目前碰到的最小的元素,用一个值记录当前遇到的最大的差值
int tag=0, money=0;
for(int i=0; i<prices.size(); ++i){
int tem = prices[i] - prices[tag];
tag = tem>=0 ? tag : i;
if(tem > money) money = tem;
}
return money;
}
开始用的是暴力法,两个指针一左一右进行迭代,要是左边位置上的值小于右边位置且右-左>上一次的右-左,则更新两个负责记录位置的指针。于是光荣超时
int maxProfit(vector<int>& prices) {
// 双指针:用两个针记录左侧的最小和右侧的最大
int left = 0, right=prices.size()-1, money=0;
for(int i=0; i<prices.size()-1; ++i){
for(int j=prices.size()-1; j>i; --j){
int tem = prices[j] - prices[i];
if(tem > money){
right = j; left = i; money=tem;
}
}
}
return money;
}