感觉贪心算法很奇怪,完全没有模版套,,,,真是苦了鼠鼠我😭只能把做到的每一题都记下来,有空来看看
455.分发饼干
class Solution {
public:
int findContentChildren(vector<int>& g, vector<int>& s) {
int count = 0;
sort(g.begin(),g.end());
sort(s.begin(),s.end());
int index = s.size() - 1;//饼干or胃口都行
for (int i = g.size() - 1; i >= 0; i--){ //先胃口
if (index >= 0 && g[i] <= s[index]){ //后饼干
index--;
count++;
}
}
return count;
}
};
很简单的一题,有思路就不难写,主要是语法,,,刚学c++好多都不会,知道要干嘛,但是就写不出来,,,,,,代码不能停
376.摆动序列
看到题目的思路:遍历一遍原数组,然后得到差值组成的列表,然后再逐个判断是否一正一负or一负一正(不知道如何实现)
得,题目看错了😅还要删除原数组
class Solution {
public:
int wiggleMaxLength(vector<int>& nums) {
// 如果数组长度小于2,直接返回长度
if(nums.size() < 2) return nums.size();
// 定义常量表示三种状态
const int begin = 0; // 初始状态
const int up = 1; // 上升状态
const int down = 2; // 下降状态
// 初始化当前状态为初始状态
int state = begin;
// 摆动序列的初始长度为1,因为至少包含第一个元素
int length = 1;
// 从第二个元素开始遍历数组
for(int i = 1; i < nums.size(); i++) {
switch(state) {
case begin:
// 初始状态时,如果当前元素大于前一个元素,状态转为上升,序列长度+1
if(nums[i - 1] < nums[i]) {
state = up;
length++;
}
// 初始状态时,如果当前元素小于前一个元素,状态转为下降,序列长度+1
else if(nums[i - 1] > nums[i]) {
state = down;
length++;
}
break;
case up:
// 上升状态时,如果当前元素小于前一个元素,状态转为下降,序列长度+1
if(nums[i - 1] > nums[i]) {
state = down;
length++;
}
break;
case down:
// 下降状态时,如果当前元素大于前一个元素,状态转为上升,序列长度+1
if(nums[i - 1] < nums[i]) {
state = up;
length++;
}
break;
}
}
// 返回最长摆动序列的长度
return length;
}
};
53.最大子数组和
毫无头绪ing感觉像动规,不像贪心
每个都加一下然后储存起来?然后比较?
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int len = nums.size();
//dp[i]表示的是以nums[i]为结尾的连续子数组的最大和
vector<int> dp(len);//初始化一个大小为 len 的 vector叫dp
int ret;
dp[0] = nums[0];
ret = dp[0];
for (int i = 1; i < len; i++){
dp[i] = max(dp[i - 1] + nums[i], nums[i]);
if (dp[i] > ret) ret = dp[i];
}
return ret;
}
};
膜拜大佬,找dp的能力太重要了,可惜我没有,,,,,看了大佬的逻辑以后茅塞顿开。
122.买卖股票的最佳时机ll
找到前一个最小的,然后用后面的大的减去小的,后面以此类推?感觉有点奇怪,,,
class Solution {
public:
int maxProfit(vector<int>& prices) {
int profit = 0;
for (int i = 1; i < prices.size(); i++){
int temp = prices[i] - prices[i - 1];
if (temp > 0) profit += temp;
}
return profit;
}
};
k神yyds!想法太精妙了太秀了我哭了😭我怎么就想不到
k:所有上涨交易日都买卖(赚到所有利润),所有下降交易日都不买卖(永不亏钱)。等价于每天都买卖!等价于每天都买卖!等价于每天都买卖!tql!
55.跳跃游戏
原先的思路是检查从后往前能否到达每一个位置,如果遇到0则返回false。,然后一直有样例过不了,硬着头皮改只能从130多到一百五十多,,,后来看了别人题解的思路,自己琢磨着写了这个
class Solution {
public:
bool canJump(vector<int>& nums) {
int maxreach = 0;
for (int i = 0; i < nums.size(); i++){
if (maxreach < i) return false;
maxreach = max(maxreach, i + nums[i]);
}
if (maxreach >= nums.size() - 1) return true;
else return false;
}
};
45.跳跃游戏ll
上一题是判断是否可以到达终点,这一题是要找到跳跃次数最少的是几。
class Solution {
public:
int jump(vector<int>& nums) {
int ans = 0;
int start = 0;
int end = 1;
while(end < nums.size()){
int maxPos = 0;
for (int i =start; i < end; i++){
maxPos = max(maxPos, i + nums[i]);
}
start = end;
end = maxPos + 1;
ans ++;
}
return ans;
}
};
喵啊喵啊!直接上图(来自Ikaruga大佬画的图,简直一目了然)
马克一下思路
1005.k次取反后最大化的数组和
想了半天,觉得很多情况很复杂,然后被编程熊大佬秒了,一句话就解释完了所有事情:
情况1,若负数数量大于等于k,则将最小的k个负数变为正数。
情况2,若负数数量小于k,则将所有负数变为正数,之后根据 k 减去负数的数量的剩余值的奇偶性,进一步判断。
若剩余值为偶数,则不用管。
若剩余值为奇数,减去绝对值最小的值。
class Solution {
public:
int largestSumAfterKNegations(vector<int>& nums, int k) {
int sum = 0, absmin = 10000;
for(int i = 0; i < nums.size(); i++){
absmin = min(abs(nums[i]), absmin);
sum += nums[i];
}
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size() && k; i++, k--){
if (nums[i] >= 0) break;
sum += 2 * abs(nums[i]);
}
if (k > 0 && (k & 1)) sum -= 2 * absmin;
return sum;
}
};
关于求sum,我自己写的代码是先把数组排序了一下,然后后面发现乱了。编程熊大佬是先求了sum和整个数组中绝对值最小的然后再排序,然后在原sum的基础上进行加减。最后一句更是神,一句话概括了我脑子里乱七八糟分的情况,,,,,
134.加油站
第一反应,遍历,从0开始挨个试,反正结果唯一,但是暴力好像很难写的样子,,,然后看了代码随想录的暴力解法,for和while用的好巧,我不会,,,,
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
for (int i = 0; i < cost.size(); i++) {
int rest = gas[i] - cost[i]; // 记录剩余油量
int index = (i + 1) % cost.size();
while (rest > 0 && index != i) { // 模拟以i为起点行驶一圈(如果有rest==0,那么答案就不唯一了)
rest += gas[index] - cost[index];
index = (index + 1) % cost.size();
}
// 如果以i为起点跑一圈,剩余油量>=0,返回该起始位置
if (rest >= 0 && index == i) return i;
}
return -1;
}
};
然后看到一个使用了贪心的,就是在该点油量-消耗若<0,则一定不能从该点开始出发,所以一搜索到<0的(为i)就从i+1开始往后继续找<0的,是为贪心。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int curSum = 0;
int totalSum = 0;
int start = 0;
for (int i = 0; i < gas.size(); i++){
curSum += gas[i] - cost[i];
totalSum += gas[i] - cost[i];
if (curSum < 0){
start = i + 1;
curSum = 0;
}
}
if (totalSum < 0) return -1;
return start;
}
};
很巧妙!
135.分发糖果
这题我写过一遍了,但是现在又忘记了。。。大致思路是,先设一个新数组,里面元素都是1,然后从右到左贪心一遍,从左到右贪心一遍,第一遍好像是看大小,逐个+1,第二遍好像是取max啥的,,,
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> candyVec(ratings.size(), 1);//所有元素初始化为1
for (int i = 1; i < ratings.size(); i++){
if (ratings[i] > ratings[i - 1]) candyVec[i] = candyVec[i - 1] + 1;
}
for (int i = ratings.size() - 2; i >= 0; i--){
if(ratings[i] > ratings[i + 1]){
candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1);
}
}
int result = 0;
for (int i = 0; i < candyVec.size(); i++) result+= candyVec[i];
return result;
}
};
记错了,是先从左到右,再从右到左
转行了,不刷题了!神清气爽啊啊啊啊啊
力扣,江湖路远,有缘再会。