53.最大子序和
思路:
最大子序列和是一个非常经典的动态规划问题,是应该时刻牢记于心的:
此题目中,首先定义dp数组,dp[i]的含义代表 “以nums[i]为结尾的子串的最大序列和”,由此不难发现,dp[i]要么等于dp[i-1]+nums[i](dp[i-1]>=0),要么就等于nums[i] (dp[i-1]<0),所以,状态转移方程也不难写出:
dp[i] = max(dp[i-1]+nums[i],nums[i]);
有了状态转移方程,动态规划就不是难事了
代码:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int maxSum = INT_MIN;
int len = nums.size();
vector<int> dp(len);
dp[0] = nums[0];
for(int i=1;i<len;i++){
dp[i] = max(dp[i-1]+nums[i],nums[i]);
maxSum = dp[i]>maxSum?dp[i]:maxSum;
}
return max(maxSum,nums[0]);
}
};
55.跳跃游戏
思路:
只需要从后向前遍历,用lastpos来代表当前位置需要到达的最远处,如i+nums[i]>=lastpos,就说明可以到达,向前更新lastpos,直到lastpos为0
代码:
class Solution {
public:
bool canJump(vector<int>& nums) {
int lastpos = nums.size()-1;
for(int i=nums.size()-1;i>=0;i--){
if(i+nums[i]>=lastpos){
lastpos=i;
}
}
return lastpos == 0;
}
};
相关题目:跳跃游戏II:
思路:
此题可以利用贪心的思想来解决:
对于当前起跳点i来说,能够跳到的最远的距离应该是i+nums[i],而在i到nums[i]之间的这些数,又可以作为新的起跳点,我们只需要在这些新的起跳点中,找到可以到达距离最远的那个(也就是i+nums[i]最大的),因为这样在下一次可以获得最大的起跳范围,例如下图中的
2,3,1,1,4
起跳点为2,则下一次可以跳到3,1,而
1+nums[1]=1+3=4,
2+nums[2]=2+1=3,
所以选择从3的位置起跳,用begin标志起跳区间的起点,用end标记起跳区间的终点,用temp标记begin与end之间i+nums[i]的最大值,则下一次迭代中,begin=end,end=temp+1;
完成赋值也就代表着完成了一次跳跃,令ans++
代码:
class Solution {
public:
int jump(vector<int>& nums) {
int ans=0,begin=0,end=1;
while(end<nums.size()){
int temp = 0;
for(int i=begin;i<end;i++){
temp = max(temp,i+nums[i]);
}
begin = end;
end = temp+1;
ans++;
}
return ans;
}
};
56.合并区间
思路:
为了方便处理,首先利用sort对intervals按照字典序进行排序,之后对二维向量从前往后进行遍历,遍历的过程中,对于能否进行合并做出判断
能够合并的条件是:
下一个区间的左端点值小于等于当前区间的右端点值
合并的方法是:
如果能够合并,则将当前区间的右端点改成:max(当前区间的右端点,下一个区间的右端点)
这样,区间包含与区间交错的情况都包括进去了
由于刚开始进行了sort,所以不用特意考虑右端点
代码
class Solution {
public:
vector<vector<int>> merge(vector<vector<int>>& intervals) {
vector<vector<int>> ans;
//特判
if(intervals.empty()) return ans;
sort(intervals.begin(),intervals.end());
for(int i=0;i<intervals.size();i++){
vector<int> temp = intervals[i];
while(i+1<intervals.size() && temp[1]>=intervals[i+1][0]){
++i;
temp[1] = max(temp[1],intervals[i][1]);
}
ans.push_back(temp);
}
return ans;
}
};