算法:贪心算法

引言

376. 摆动序列 - 力扣(LeetCode)

55. 跳跃游戏 - 力扣(LeetCode)

45. 跳跃游戏 II - 力扣(LeetCode)

134. 加油站 - 力扣(LeetCode)

135. 分发糖果 - 力扣(LeetCode)

代码

第一题

这是一道简单的贪心题目,目的是找最长的摆动序列,我们的想法就是记录上一个差值和本次差值,只要差值相反,那么我们就对结果+1

cpp 复制代码
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if (nums.size() <= 1) {
            return nums.size();
        }
        
        int preDiff = 0;
        int curDiff = 0;
        int res = 1; 
        
        for (int i = 0; i < nums.size() - 1; i++) {
            curDiff = nums[i + 1] - nums[i];
            if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {
                res++;
                preDiff = curDiff;  
            }
        }
        
        return res;
    }
};

第二题

这一题思路不是很难,但是实现起来却比较困难,就是要实现一个最大的覆盖面积在已经遍历过了的点里面,而且还要做到循环的处理,这里就是改变了停止的条件,cover每一次都是要保证是最大的,而只要遍历的点超过了这个最大的覆盖区,说明根本到达不了这个地方。

cpp 复制代码
class Solution {
public:
    bool canJump(vector<int>& nums) {
        int cover = 0;
        if (nums.size() == 1) {
            return true;
        }
        for (int i = 0; i <= cover; i++) {
            cover = max(cover, i + nums[i]);
            if (cover >= nums.size() - 1) {
                return true;
            }
        }
        return false;
    }
};

第三题

这一题相比于上一题有一个不同的地方就是判断走到终点要几步,那么我们可以延续上一题的思路,我们每当走到一个范围的终点的时候就会更新我们的范围,不过在更新之前我们会判断这个范围与终点之间的关系。不过这一题和上一题有一个不同的地方就是这一题的范围不是在一边循环一边变化的,是走完一个范围之后才会更新的,这个也是因为我们题目里面已经保证了可以到达终点。

cpp 复制代码
class Solution {
public:
    int jump(vector<int>& nums) {
        if (nums.size() == 1) {
            return 0;
        }
        int ans = 0;
        int nextDistance = 0;
        int curDistance = 0;
        for (int i = 0; i < nums.size(); i++) {
            nextDistance = max(nums[i] + i, nextDistance);
            if (i == curDistance) {
                ans++;
                curDistance = nextDistance;
                if (nextDistance >= nums.size() - 1) {
                    break;
                }
            }
        }
        return ans;
    }
};

第四题

我们创建一个数组来记录一下两个数组的差,这样子就可以转化问题为:从哪一个地方开始相加可以让和一直是正数。首先我们一定要先判断一下整个和相加一定要是正数,否则无论从哪里开始都不可能保证是正数。然后我们按照顺序开始相加,但是只要遇到了负数我们就从下一个开始重新计数。首先我们一开始都会对这个方法有疑问,因为如果满足之后的和是正数,但是一定可以保证再次加上之前的数也能是正数嘛~~~ 但是注意:我们之前已经单独判断所有和加上去一定是正数了,所以我们现在的所有操作是找到起点,因为是这个起点是一定存在的,既然之前的点已经测试过了不可以,那么就往后面继续测呗~~~

cpp 复制代码
class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        vector<int> nums(gas.size(), 0);
        for (int i = 0; i < gas.size(); i++) {
            nums[i] = gas[i] - cost[i];
        }
        int index = gas.size();
        int sum = 0;
        for (int i = 0; i < index; i++) {
            sum += nums[i];
        }
        if (sum < 0) {
            return -1;
        }
        sum = 0;
        int startPos = 0;
        bool flag = true;
        for (int i = 0; i < index; i++) {
            sum += nums[i];
            if (sum < 0) {
                sum = 0;
                startPos = i + 1;
                continue;
            }
        }
        return startPos;
    }
};

第五题

这一题很难,因为我们需要顾及左边又要顾及右边,这种题目我们千万不要一下子兼顾两边,我们要遍历两边,先左边再右边。我们先把所有的数组都设置为1,然后从左到右遍历,只要右边比左边大,那么右边的值就比左边的值大1。然后我们再从右边到左边遍历,也就是如果右边大于左边,那么就比左边的糖果大1,但是因为也要满足上一次遍历的结果,也就是右边比左边大的这个,所以我们要利用上一次已经得到的结果+1。不过一定要注意的是,这两个数组是两个结果,所以很可能对于一个点有两个结果,我们为了要满足两次遍历的结果,所以要取最大值。比如有可能1 2 3 4 5 1,那么对于5这个数我们最后的结果应该是5个糖果。

cpp 复制代码
class Solution {
public:
    int candy(vector<int>& ratings) {
        int sum = 0;
        vector<int> res(ratings.size(), 1);
        int index = ratings.size();
        for (int i = 1; i < index; i++) {
            if (ratings[i] > ratings[i - 1]) {
                res[i] = res[i - 1] + 1;
            }
        }
        for (int i = index - 1; i > 0; i--) {
            if (ratings[i - 1] > ratings[i]) {
                res[i - 1] = max(res[i - 1], res[i] + 1);
            }
        }
        for (int result : res) {
            sum += result;
        }
        return sum;
    }
};
相关推荐
On The Road :8 小时前
深入理解 JVM 垃圾回收:GC 是什么、如何判定垃圾、四大回收算法全解析
jvm·算法
Rabitebla8 小时前
【Linux学习笔记】进程篇(九):进程的创建与退出——fork、写时拷贝与退出码
linux·c++·笔记·学习
时间的拾荒人9 小时前
CMake 实战指南:从基础语法到静态库/动态库制作与链接
开发语言·c++·面试
道尔柯南9 小时前
C++ STL 入门详解:从认识标准模板库到掌握学习方法
java·c++·学习方法
微尘hjx9 小时前
【Deep-OC-SORT 03】多轨迹算法Deep-OC-SORT-卡尔曼滤波预测过程
算法·yolo·目标跟踪·ultralytics·车跟踪·轨迹算法·deep-oc-sort
老师我太想进步了202611 小时前
【数据结构-3】算法美学之降复杂度
数据结构·算法
机器人零零壹17 小时前
技术白皮书:iRobotCAM如何解决机器人激光切割应用中的核心难点,从CAD离线编程到双目视觉定位与轨迹自适应提升复杂空间曲线切割的精度、效率与柔性化水平
人工智能·算法
布莱克60518 小时前
C/C++ 中变量的声明与定义:区别、联系与常见误区
c语言·开发语言·c++·声明·定义
ZhengEnCi19 小时前
大模型的分类到底怎么分:从基础模型到推理模型、从通用到专用的完整图谱
算法
取名真是20 小时前
Python 算法知识点从基础到进阶
开发语言·python·算法