Leetcode刷题_贪心相关_c++版

news2024/11/29 22:44:35

(1)455分发饼干–简单

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
在这里插入图片描述

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        //升序排序
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int cookie = 0;
        int child = 0;
        //贪心算法,尽可能用小饼干满足更多孩子
        while(cookie < s.size() && child < g.size()){
            if(g[child] <= s[cookie]){
                //该孩子满足了,满足下一个孩子
                child++;
                
            }
            //如果未满足,则当前饼干一定不能满足剩下的孩子,移动到下一块
            //如果满足,则当前饼干被消耗,移动到下一块
            cookie++;
        }
        return child;
    }
};

在这里插入图片描述

(2)376摆动序列–中等

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。

例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。

相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。
子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。

给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。
在这里插入图片描述
在这里插入图片描述
连续递增或递减时,选择红色点

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if(nums.size()==0) return 0;
        if(nums.size()==1) return 1;
        //利用状态机转换
        //三个状态
        static const int begin = 0;
        static const int up = 1;
        static const int down = 2;
        int STATE = begin;
        int maxLength = 1;//初始长度为1
        for(int i = 1; i< nums.size(); i++){
            switch(STATE){
            //当状态为begin时
                case begin:
                    if(nums[i]>nums[i-1]){
                        STATE = up;
                        maxLength++;
                    }
                    else if(nums[i] < nums[i-1]){
                        STATE = down;
                        maxLength++;
                    }
                    //如果两数相等,不发生状态转换
                    break;
                case up:
                    
                    if(nums[i] < nums[i-1]){
                        STATE = down;
                        maxLength ++;
                    }
                    //如果两数相等或后一个大于前一个,不发生状态转换
                    break;
                case down:
                    
                    if(nums[i] > nums[i-1]){
                        STATE = up;
                        maxLength ++;
                    }
                    //如果两数相等或后一个小于前一个,不发生状态转换
                    break;
            }
        }return maxLength;



    }
};

在这里插入图片描述

(3)402移调k位数–中等

给你一个以字符串表示的非负整数 num 和一个整数 k ,移除这个数中的 k 位数字,使得剩下的数字最小。请你以字符串形式返回这个最小的数字。
在这里插入图片描述

#include<string>
using namespace std;
class Solution {
public:
    string removeKdigits(string num, int k) {
        if(k >= num.size()) return "0";
        vector<int> S;
        string result = "";
        int number;
        for(int i = 0; i< num.length(); i++){
            //从高位开始,保留尽可能小的数
            number = num[i] - '0';//字符串转换为数字,0要用单引号,表示一个字符,双引号表示一个字符串
            while(S.size()> 0 && number < S[S.size() - 1] && k>0){
                //if(S.size() == 1 && number == 0) break;//如果栈中只有一个元素,且新来的元素是0,不能用0替换栈顶
                S.pop_back();//如果新元素比栈顶小,就保留新元素
                k--;
            }
                
            //0不能作为开头元素
            if(number != 0 || S.size() != 0 ){
                S.push_back(number);
            }
            
        }
        if(S.size() == 0 || k >= S.size()) return "0";

        //如果序列都遍历完而k还未用完时,得到的栈中元素一定是单调递增的。
        while(k > 0) {
            S.pop_back();
            k--;
        }

        if(S.size() == 0) return "0";

        for(int i = 0; i< S.size(); i++){
            //char tmp = S[i]+'0';
            //result = result+ tmp;//这样转字符,超长用例会报超时,不知道为啥
            result.append(1,S[i]+'0');//在当前字符串结尾添加1个字符
		
        }
        return result;
    }
};

在这里插入图片描述
append函数的用法参考:https://blog.csdn.net/weixin_42258743/article/details/107964192

(4)55跳跃游戏

给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。
在这里插入图片描述

法一:

class Solution {
public:
    bool canJump(vector<int>& nums) {
        //关键在于如何选择下一条的节点
        //下一跳能跳的越远越有利,因此选择能达到最远的节点
        if(nums.size()== 1) return true;
        int next_index = -1;
        int index = 0;
        int max_distance = 0;//此处赋值为负数的话会导致与size函数返回值(无符号数)比较出错
        while((index+max_distance <= (nums.size()-1)) && (next_index != index)){
            //下一跳等于当前下标,则证明不能到达
            //下一条等于大于总长度,则证明可到达
            max_distance = 0;
            //index更新至下一跳处
            if (next_index != -1) index = next_index;
            //cout<<"index = "<< index << " next_index = "<<next_index<<endl;
            if(nums[index] == 0) break;
            else{
                for(int i = 1; i<= nums[index] && (i+index<nums.size()); i++){
                //遍历从index到index+nums[i]能到达的所有元素,找出最远距离
                    if((i+nums[i+index]) > max_distance){
                        max_distance = (i+nums[i+index]);
                        next_index = index+i;
                        //cout<< " i="<<i<<" max_distance=" << max_distance<<endl;
                    }

                }
            }

            //cout<<"index = "<< index << " next_index = "<<next_index<<endl;
            
        }
        if((index+max_distance >= (nums.size()-1)) ) return true;
        return false;
    }
};

在这里插入图片描述

法二:

class Solution {
public:
    bool canJump(vector<int>& nums) {
        if(nums.size() == 1) return true;
        int length = nums.size();//总长度
        int tmp = nums[0];//tmp记录当前能到达的最远距离
        int i = 1;
        for(i; (i< length && tmp > 0); i++){
            tmp--;
            cout<< "tmp="<<tmp<<" nums[" << i<<"]=" << nums[i]<< " ";
            //如果当前节点能到达的距离比之前的远,tmp更新为当前节点的值
            if(nums[i] > tmp){ 
                tmp = nums[i];
            }
            //cout<< tmp << "picked"<<endl;
        }
        //cout<< "tmp="<<tmp<<endl;
        if(i >= length && tmp >= 0) return true;
        return false;

    }
};

在这里插入图片描述

(5)45跳跃游戏二–中等

给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。

每个元素 nums[i] 表示从索引 i 向前跳转的最大长度。换句话说,如果你在 nums[i] 处,你可以跳转到任意 nums[i + j] 处:

0 <= j <= nums[i]
i + j < n
返回到达 nums[n - 1] 的最小跳跃次数。生成的测试用例可以到达 nums[n - 1]。

在这里插入图片描述
此题根据跳跃游戏的 法一 改编得到
https://blog.csdn.net/weixin_44343355/article/details/128772719

class Solution {
public:
    int jump(vector<int>& nums) {
        //关键在于如何选择下一条的节点
        //下一跳能跳的越远越有利,因此选择能达到最远的节点
        if(nums.size() < 2) return 0;
        int next_index = 0;
        int index = 0;
        int max_distance = nums[0];//此处赋值为负数的话会导致与size函数返回值(无符号数)比较出错
        int jump_times = 0;
        int length = nums.size();
        while(((max_distance) < length -1)){
            //最远能到的距离等于大于总长度,则证明可到达

            for(int i = 1; i<= nums[index] && (i+index<nums.size()); i++){
            //遍历从index到index+nums[i]能到达的所有元素,找出最远距离
                if((i+nums[i+index]+index) > max_distance){
                    max_distance = (i+nums[i+index]+index);
                    next_index = index+i;
                    
                    //cout<< " i="<<i<<" max_distance=" << max_distance<<endl;
                }
                
            }
            index = next_index;
            jump_times++;

        }
        return jump_times+1;


    }
};

在这里插入图片描述

(6)452用最少数量的箭引爆气球–中等

有一些球形气球贴在一堵用 XY 平面表示的墙面上。墙面上的气球记录在整数数组 points ,其中points[i] = [xstart, xend] 表示水平直径在 xstart 和 xend之间的气球。你不知道气球的确切 y 坐标。

一支弓箭可以沿着 x 轴从不同点 完全垂直 地射出。在坐标 x 处射出一支箭,若有一个气球的直径的开始和结束坐标为 xstart,xend, 且满足 xstart ≤ x ≤ xend,则该气球会被 引爆 。可以射出的弓箭的数量 没有限制 。 弓箭一旦被射出之后,可以无限地前进。

给你一个数组 points ,返回引爆所有气球所必须射出的 最小 弓箭数 。

在这里插入图片描述

//注意,此处需要加引用
bool cmp(const vector<int> &a, const vector<int> &b){
    return a[0] < b[0];
}

class Solution {
public:

    int findMinArrowShots(vector<vector<int>>& points) {
        if(points.size() == 1) return 1;
        sort(points.begin(), points.end(), cmp);//按左端点从小到大升序排序
        int length = points.size();
        int shootNum = 1;
        int shooter_begin = points[0][0];
        int shooter_end = points[0][1];
        for(int i = 1;i<length;i++){
            //如果新节点的左端点在shooter的范围内,则说明两区间有重合部分,需要一箭即可射穿
            if(points[i][0] >= shooter_begin && points[i][0] <= shooter_end){
                //更新shooter的左端点
                shooter_begin = points[i][0];
                
                //如果shooter的右端点大于新节点的右端点,则更新右端点
                if(points[i][1] <= shooter_end){
                    shooter_end = points[i][1];
                }
            }
            //如果无交集,则新选择一个射手
            else{
                shootNum++;
                shooter_begin = points[i][0];
                shooter_end = points[i][1];
            }
        }
        return shootNum;

    }
};

在这里插入图片描述

(7)871最低加油次数–困难

汽车从起点出发驶向目的地,该目的地位于出发位置东面 target 英里处。

沿途有加油站,用数组 stations 表示。其中 stations[i] = [positioni, fueli] 表示第 i 个加油站位于出发位置东面 positioni 英里处,并且有 fueli 升汽油。

假设汽车油箱的容量是无限的,其中最初有 startFuel 升燃料。它每行驶 1 英里就会用掉 1 升汽油。当汽车到达加油站时,它可能停下来加油,将所有汽油从加油站转移到汽车中。

为了到达目的地,汽车所必要的最低加油次数是多少?如果无法到达目的地,则返回 -1 。

注意:如果汽车到达加油站时剩余燃料为 0,它仍然可以在那里加油。如果汽车到达目的地时剩余燃料为 0,仍然认为它已经到达目的地。

在这里插入图片描述
此题的思路与跳跃游戏二中的思路类似,都是求最小跳跃次数,用贪心的思想

class Solution {
public:
    int minRefuelStops(int target, int startFuel, vector<vector<int>>& stations) {
        if(stations.size() == 0){
            if(target > startFuel) return -1;
            else return 0;
        }
        // if(stations.size() == 1){
        //     if(target < startFuel) return 0;
        //     else if(stations[0][0] > startFuel || (stations[0][1]+startFuel) < target) return -1;
        //     else return 1;
        // }
        int leftFuel = startFuel;//剩余油量
        priority_queue<int, vector<int>, less<int>> maxFuel;//途中站点的最大油量,加过油的站点就不能再加油了,所以用 堆来存储,依次输出最大站点
        int addFuelTimes = 0;//加油次数
        int i = 0;
        int maxfuel = 0;
        vector<int> target_vector;
        target_vector.push_back(target);
        target_vector.push_back(0);
        stations.push_back(target_vector);
        for(i = 0; i< stations.size(); i++){
            //cout<< "i="<<i<<" ";
            leftFuel = startFuel - stations[i][0];//剩余油量
            //剩余油量小于等于0,则表明过程中需要加一次油
            //无法到达该点,先加油
            while(leftFuel < 0 && maxFuel.size()>0){
                
                maxfuel = maxFuel.top();
                maxFuel.pop();
                leftFuel = leftFuel + maxfuel;
                startFuel = startFuel +maxfuel;
                addFuelTimes ++;
            }
            if(leftFuel<0) return -1;
            maxFuel.push(stations[i][1]);

            //前面所有站点的油都加完了,如果还到不了该点,返回无法到达
            
            //cout<<endl;
            

            }return addFuelTimes;
            
    
        }
    
};  

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1007991.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Web之tomcat

[TOC]&#xff08;文章目录&#xff09; 1.程序架构 1.C/S(client/server) 比如&#xff1a;QQ、 微信、 LOL 优点&#xff1a;有一部分代码写在客户端&#xff0c; 用户体验比较好。 缺点&#xff1a; 服务器更新&#xff0c;客户端也要随着更新。 占用资源大。 2. B/S(brows…

【盘点】设计师更偏爱Telerik Kendo UI界面库的4个理由!

就像许多开发人员(错误地)认为设计软件和工具对他们没有任何用处一样&#xff0c;许多设计人员也错误地认为&#xff0c;当涉及到以开发人员为中心的软件和工具时&#xff0c;对他们没有任何价值。事实上&#xff0c;如果双方都愿意走出自己的舒适区去探索&#xff0c;他们都会…

在微信小程序上怎么实现多门店管理功能

微信小程序已经成为连接线上与线下的重要工具&#xff0c;尤其对于拥有多家门店的企业来说&#xff0c;通过微信小程序可以实现多门店管理&#xff0c;提高管理效率和用户体验。下面&#xff0c;我将为大家详细介绍如何在微信小程序上实现多门店管理功能。 一、确定多门店管理功…

打印日志遇到的问题,logback与zookeeper冲突

在做项目时需要打印日志引入了logback打印日志&#xff0c;但是一直无法打印&#xff0c;于是一路查找原因。发现zookeeper中默认带的有个logback和我自己引入的logback版本冲突了&#xff0c;这样直接使用exclusions标签将zookeeper中自带的日志框架全部排除即可 按理说到这一…

【leetcode 力扣刷题】栈—波兰式///逆波兰式相关知识和题目

波兰式、逆波兰式相关知识和题目 波兰式、逆波兰式介绍常规表达式转换成逆波兰式编程让常规表达式转换成逆波兰式逆波兰式运算过程常规表达式转换成波兰式编程让常规表达式转换成波兰式波兰式运算过程 150. 逆波兰式表达式求值224. 基本计算器227. 基本计算器Ⅱ282. 给表达式添…

【每日一题】852. 山脉数组的峰顶索引

852. 山脉数组的峰顶索引 - 力扣&#xff08;LeetCode&#xff09; 符合下列属性的数组 arr 称为 山脉数组 &#xff1a; arr.length > 3存在 i&#xff08;0 < i < arr.length - 1&#xff09;使得&#xff1a; arr[0] < arr[1] < ... arr[i-1] < arr[i] ar…

Linux重装qemu和libvirt

要重装qemu和libvirtd在CentOS上&#xff0c;请按照以下步骤操作&#xff1a; 首先&#xff0c;请确保您具有root权限或sudo访问权限。 首先&#xff0c;您需要卸载现有的qemu和libvirt软件包。使用以下命令&#xff1a; sudo yum remove qemu-kvm qemu-img libvirt在卸载完成…

MySQL基础终端命令与Python简单操作MySQL

文章目录 MySQL终端命令1. 进入mysql2. 创建数据库3. 选择数据库4. 创建数据表1. 主键约束2. 外键约束3. 非空约束4. 唯一约束5. 使用默认约束6. 设置id为自增列 5. 查看数据表6. 修改数据表1. 修改表名2. 修改表的字段类型3. 修改表的字段名4. 为表添加字段5. 删除字段6. 调整…

HTML的学习 Day01

《网页设计与制作》是web前端开发技术中静态网页中的内容&#xff0c;主要包括html、css、js中的静态内容部分&#xff0c;是专业基础课程。 随着5G时代的到来&#xff0c;人工智能与物联网结合行业的飞速发展&#xff0c;更多的互联网的崛起。这肯定就比如伴随着对移动互联网…

05-Redis高可用集群之水平扩展

上一篇&#xff1a;04-Redis哨兵高可用架构 1.概要说明 Redis3.0以后的版本虽然有了集群功能&#xff0c;提供了比之前版本的哨兵模式更高的性能与可用性&#xff0c;但是集群的水平扩展却比较麻烦&#xff0c;今天就来带大家看看redis高可用集群如何做水平扩展&#xff0c;…

Houdini 灯光插件工作流程,如何将 HDR Light Studio 与 Houdini 结合使用?

如何不额外购买硬件&#xff0c;流畅的运行Houdini&#xff1a; Houdini项目渲染慢&#xff0c;本地硬件配置不够&#xff0c;想要加速渲染&#xff0c;在不增加额外的硬件成本投入的情况下&#xff0c;最好的解决方式是使用渲云云渲染&#xff0c;在云端批量渲染&#xff0c;…

高效通过指定秒数分割视频,定制你的片段!

大家好&#xff01;在处理电脑上的视频文件时&#xff0c;如果需要从指定秒数处进行分割视频&#xff0c;传统的方法可能会显得非常繁琐和费时。为了让您能够轻松实现这一需求&#xff0c;我们为您提供了一种高效的方法&#xff0c;让您能够精准地从指定秒数处分割视频&#xf…

出现线程安全问题的原因和解决方案

文章目录 一、什么是线程安全问题二、出现线程安全问题的原因三、解决方案3.1加锁 一、什么是线程安全问题 某些代码在单线程环境下执行结果完全正确&#xff0c;但在多线程环境下执行就会出现Bug&#xff0c;这就是“线程安全问题”。 下面以一个变量n自增两次&#xff0c;每…

Linux【一】

目录 一、Linux操作系统发展历史 Unix Minix Linux 二、Linux简介 Linux是什么 Linux的版本 Linux内核版本 Linux发行版本 Linux应用领域&#xff1f; Linux注意事项 三、Linux目录 系统目录 用户目录 文件颜色 四、Linux命令行基本操作 Linux命令格式&#x…

小程序中会员如何绑定身份证信息

在小程序中&#xff0c;会员绑定身份证信息是一项重要且常见的功能&#xff0c;可以帮助商家更好地了解用户的身份信息&#xff0c;提供个性化的服务和保障用户的权益。例如生日礼物&#xff0c;还有以及医保支付等需要实名认证的场景等。下面将介绍一些小程序中会员如何绑定身…

Open Feign

Open Feign 在前面的学习中&#xff0c;我们使用了Ribbon的负载均衡功能&#xff0c;简化了远程调用时的代码&#xff1a; String user this.restTemplate.getForObject("http://spring-provider/provider/" id, String.class);如果就学到这里&#xff0c;可能以…

Zebec 生态 AMA 回顾:Nautilus 以及 $ZBC 的未来

在 9 月 7 日&#xff0c;Zebec 创始人 Sam 做客社区&#xff0c;并进行了“Nautilus Chain 以及 $ZBC 的未来”主题的 AMA 访谈。Sam 在本次访谈中对 Nautilus Chain 生态的价值捕获、Zebec 生态布局规划、可能会推出的 Nautilus Chain 治理通证 NAUT 进行了解读。本文将对本次…

基于SSM的医院在线挂号预约系统的设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

人大女王金融硕士项目——应以长远的眼光去规划自己的人生蓝图

我们的现在的生活都是过去努力的结果&#xff0c;你的未来如何是由今后的努力决定。我们不要停滞不前&#xff0c;应从长远的眼光去规划自己的人生蓝图。你有想过在职攻读人民大学与加拿大女王大学金融硕士项目来提升自己吗&#xff1f; 着我国经济迅猛的发展&#xff0c;金融…

鸿蒙HarmonyOS应用开发初体验

最近华为发布mt60新机火了&#xff0c;作为一名移动开发程序员&#xff0c;对鸿蒙系统开发移动端就很感兴趣了。 开发工具&#xff1a;HUAWEI DevEco Studio和SDK下载和升级 | HarmonyOS开发者 下载完后按默认安装就可以了&#xff0c;界面跟AS很类似&#xff0c;之前我jdk环…