今天是贪心算法学习的第二天,愈发感觉贪心算法非常的抽象,有一些思维上的东西确实有点难想到,希望在做题过程中能够加强贪心算法这部分的思维。
122.买卖股票的最佳时机 II
题目链接:122. 买卖股票的最佳时机 II - 力扣(LeetCode)
这个题还挺简单的,其实就是把价格数组中的元素差求出来,对所有的正向元素差累加即可。具体代码实现如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
vector<int> nums(prices.size(),0);
int sum=0;
for(int i=0;i<prices.size()-1;i++) nums[i]=prices[i+1]-prices[i];
for(int i=0;i<nums.size();i++) if(nums[i]>0) sum+=nums[i];
return sum;
}
};
55. 跳跃游戏
这个题目其实我个人感觉思想会比较偏向动态规划,他通过遍历数组每个元素,判断出该元素之前的所有元素所能到达的最远下标。如果某个点的最远下标超过了数组最大下标,就说明可以跳到终点。反之则不可以。具体代码实现如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
if(nums.size()==1&&nums[0]==0) return true;
int cover=0;
for(int i=0;i<=cover;i++)
{
cover=max(cover,nums[i]+i);
if(cover>=nums.size()-1) return true;
}
return false;
}
};
45.跳跃游戏II
题目链接:45. 跳跃游戏 II - 力扣(LeetCode)
这个题目是上面题目的加强版,要求得到跳到终点的最少跳数。我对于贪心的解法是不太理解的,感觉用动态规划去看会更好理解一些。依旧是遍历数组元素,得到每个点及其之前点所能到达的最远距离。然后从头开始跳,每次跳到元素的最大距离,并进行次数的累加。具体代码实现如下:
class Solution {
public:
int jump(vector<int>& nums) {
vector<int> dp(nums.size(),0);
int maxl=0;
for(int i=0;i<nums.size();i++){
maxl=max(maxl,nums[i]+i);
dp[i]=maxl;
}
int index=0;
int num=0;
while(index<nums.size()-1)
{
index=dp[index];
num++;
}
return num;
}
};
1005.K次取反后最大化的数组和
题目链接:1005. K 次取反后最大化的数组和 - 力扣(LeetCode)
这个题目是给出一个数组和次数k,需要将数组内的元素有选择的翻转k次,从而使得和最大。我一开始的做法是翻转最小元素然后重新排序,这样的时间复杂度非常高。题解的做法是写一个绝对值的排序,然后翻转所有负数,如果k还有剩的,就翻转最小的数。具体代码实现如下:
class Solution {
public:
static bool cmp(int a,int b)
{
return abs(a)>abs(b);
}
int largestSumAfterKNegations(vector<int>& nums, int k) {
sort(nums.begin(),nums.end(),cmp);
int num=k;
for(int i=0;i<nums.size();i++)
{
if(nums[i]<0&&num>0)
{
nums[i]*=-1;
num--;
}
}
if(num>0)
{
for(int i=1;i<=num;i++) nums[nums.size()-1]=-nums[nums.size()-1];
}
int sum=0;
for(int i=0;i<nums.size();i++) sum+=nums[i];
return sum;
}
};