当前位置: 首页 > article >正文

【代码随想录|贪心算法03】

134.加油站

题目链接: 134. 加油站 - 力扣(LeetCode)

这道题是问我从哪个点开始遍历我的加油油量减去消耗掉的油量都为正,我感觉死扣根本想不出来一点。

这里的思路是保存每个站的的加油量减去消耗量(cursum),他为正我肯定就能进行遍历,然后如果一个不小心,你油不够了(cursum<0),那这个点前面的点肯定都不够这个点消耗的了,因为题目说存在解结果是唯一的,那我只要从后面的第一个油是正数的点开始遍历就足够了(按道理我第二个油是正数的点可能也可以,但是题目说只有一个解所以取第一个)

//错误代码
class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int totalsum=0,cursum=0,start=0;
        for(int i=0;i<gas.size();i++){
            totalsum=gas[i]-cost[i];
            cursum=gas[i]-cost[i];
            if(cursum<0){
                start=i+1;
                break;//不能直接退出,后面可能还有负数点
            }
        }
        if(totalsum<0)return -1;
        return start;

    }
};

在做的时候,发现我这个不对,我最开始想的是我要第一个正数点那,取到了我退出了不就好了,然后报错的一组数据是

gas:[1, 2, 3, 4, 5]

cost:[3, 4, 5, 1, 2]

那么我每个站点需要消耗的量

rest:[-2,-2,-2,3,3]

这里如果cursum取到负数就退出的话我结果就会是1了,后来想想 我确实是要从负数的下一个作为起点,但是当我遇到负数的时候还要进行统计,因为有可能我负数的后面还是负数,所以不能直接退出。遇到负数的时候把cursum置零老老实实继续遍历吧~

//正确代码
class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int totalsum = 0, cursum = 0, 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;//每个站点需要消耗的量加起来都是负数了,肯定找不到
        else
            return start;
    }
};

135.分发糖果

题目链接135. 分发糖果 - 力扣(LeetCode)

这道题如果两边一起比较的话写代码会很混乱,这里思路是先从前往后进行遍历,右边孩子评分和左边孩子评分进行比较,给糖果,然后从后往前进行遍历,左边孩子评分和右边孩子评分进行比较,更新最大糖果值。

局部最优:满足从前往后遍历和从后往前遍历的孩子都拿到相应的糖果。

全局最优:相邻的孩子中,评分高的孩子获得更多的糖果。

class Solution {
public:
    int candy(vector<int>& ratings) {
        int result = 0;
        vector<int> candy(ratings.size(), 1);
        for (int i = 1; i < ratings.size(); i++) {
            if (ratings[i] > ratings[i - 1]) {
                candy[i] = candy[i - 1] + 1;
            }//右边孩子和左边孩子进行比较,所以从第二个开始
        }
        for (int i = ratings.size() - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                candy[i] = max(candy[i + 1] + 1, candy[i]);
            }//左边孩子和右边孩子进行比较,所以从倒数第二个开始
        }
        for (int i = 0; i < ratings.size(); i++) {
            result += candy[i];//统计总共的糖果数
        }
        return result;
    }
};

860.柠檬水找零

题目链接:860. 柠檬水找零 - 力扣(LeetCode)

这里有三种情况

一、收到的钱是5

那就美滋滋,也不用补

二、收到的钱是10

得看看我现在还有没有5块哦,没有就只能return false了

三、收到的钱是20

优先补10块+5块的,其次再补3个5块。 因为我的5块可以补10块和20,但是10块只能补20,所以优先把10块的给用了。

class Solution {
public:
    bool lemonadeChange(vector<int>& bills) {
        int five = 0, ten = 0, twenty = 0;
        for (int bill : bills) {
            if (bill == 5) {
                five++;
            }
            if (bill == 10) {
                if (five > 0) {
                    five--;
                    ten++;
                } else
                    return false;
            }
            if (bill == 20) {
                if (ten > 0 && five > 0) {
                    ten--;
                    five--;
                } else if (five >= 3) {
                    five -= 3;
                } else
                    return false;
            }
        }
        return true;
    }
};

406.根据身高重建队列

题目链接:406. 根据身高重建队列 - 力扣(LeetCode)

因为这道题要从两个维度来考虑,所以要分别从两边开始贪

如果先从前面有k个人的k开始贪的话身高确定不下来,k也确定不下来,因为前面按照k从小到大排列 k根本就不能代表前面有多少人,比如说[1,0][1,0][1,0][1,1],你的k等于1,但是前面有3个人

所以要从身高(h)开始排

排之前:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]

排之后:people=[[7,0], [7,1], [6,1], [5,0], [5,2], [4,4]]

身高(h)确定下来之后再确定k(前面有k个人),就挨着一个个进行比较,身高低前面排的人少的就给他插到前面去,因为这样也不会影响后面的结点

过程:

  • 插入[7,0]:[[7,0]]
  • 插入[7,1]:[[7,0],[7,1]]
  • 插入[6,1]:[[7,0],[6,1],[7,1]]
  • 插入[5,0]:[[5,0],[7,0],[6,1],[7,1]]
  • 插入[5,2]:[[5,0],[7,0],[5,2],[6,1],[7,1]]
  • 插入[4,4]:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
class Solution {
public:
    static bool cmp(vector<int>& a, vector<int>& b) {
        if (a[0] == b[0])
            return a[1] < b[1];
        return a[0] > b[0];//身高从大到小排,身高相同k大的排后面
    }
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(), people.end(), cmp);
        vector<vector<int>> que;
        for (int i = 0; i < people.size(); i++) {
            int position = people[i][1];
            que.insert(que.begin() + position, people[i]);//把整个顶点数据插到相应位置
        }
        return que;
    }
};


http://www.kler.cn/a/420852.html

相关文章:

  • CTF-PWN: WEB_and_PWN [第一届“吾杯”网络安全技能大赛 Calculator] 赛后学习(不会)
  • 深入探索 HarmonyOS 的 Navigation 组件:灵活的页面管理与动态导航
  • MATLAB —— 机械臂工作空间,可达性分析
  • java将word docx pdf转换为图片(不需要额外下载压缩包,直接导入maven坐标)
  • uniapp使用扩展组件uni-data-select出现的问题汇总
  • 【Linux】应用层协议—HTTP
  • 【Trick】adb指令运行时出现 Error: Activity class {xxx} does not exist.
  • 学习笔记048——Java字节流
  • Kotlin 协程的异常处理
  • 蓝象智联携手西电发布GaiaGPT,夯实数据安全底座
  • python(18) : flask_sqlalchemy 配置sqlserver数据库对象
  • 设计模式之 建造者模式 C# 范例
  • 细说STM32单片机用定时器触发DAC输出三角波并通过串口观察波形的方法
  • Microi吾码产品深度测评:轻量级企业管理应用的全方位剖析
  • Python生日祝福烟花
  • 怎么使用开源的 FFmpeg 命令行工具压缩视频大小
  • 【贪心算法】贪心算法五
  • “量子跃迁与数据织网:深入探索K最近邻算法在高维空间中的优化路径、神经网络融合技术及未来机器学习生态系统的构建“
  • java网络通信(三):TCP通信、实现客户端-服务端消息通信
  • 详细介绍下oracle建库过程中核心脚本dbcore.bsq
  • Linux系统编程之进程控制
  • 华为的USG6000为什么不能ping通
  • 微信小程序 运行出错 弹出提示框(获取token失败,请重试 或者 请求失败)
  • 深入探索HarmonyOS next与ArkTS探索
  • Ubuntu桥接模式设置静态IP
  • 【错误记录】Android Studio 开发环境内存占用过多 ( 记录内存使用情况 )