【算法系列之贪心算法III】leetcode135. 分发糖果

news/2024/11/8 9:06:24/

134. 加油站

力扣题目链接

在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

给定两个整数数组 gascost ,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。

输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
输出: 3
解释:
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。

解决思路

  1. 如果gas的和比cost的和要小,那么是不存在的。
  2. 从索引0开始计算的gas和比cost的和要小,更新索引的起始位置。

Java实现

class Solution {public int canCompleteCircuit(int[] gas, int[] cost) {int n = gas.length;int sum = 0;int curSum = 0;int start = 0;for (int i = 0; i < gas.length; i++) {sum += gas[i] - cost[i];curSum += gas[i] - cost[i];if (curSum < 0) {start = (i + 1) % n;curSum = 0;}}if (sum < 0) {return -1;}return start;}
}

135. 分发糖果

力扣题目链接

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

  • 每个孩子至少分配到 1 个糖果。
  • 相邻两个孩子评分更高的孩子会获得更多的糖果。

请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目

输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。

解决思路

  1. 左侧遍历,保证left数组始终满足当右边比左边大,糖果也多一个。
  2. 右侧遍历,也保证。获取两者的最大值。

Java实现

class Solution {public int candy(int[] ratings) {int n = ratings.length;int[] left = new int[n];for (int i = 0; i < ratings.length; i++) {if (i > 0 && ratings[i] > ratings[i - 1]) {left[i] = left[i - 1] + 1;} else {left[i] = 1;}}int res = 0;int right = 0;for (int i = n - 1; i >= 0; i--) {if (i < n - 1 && ratings[i] > ratings[i + 1]) {right++;} else {right = 1;}res += Math.max(right, left[i]);}return res;}
}

860.柠檬水找零

力扣题目链接

在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。

每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。

注意,一开始你手头没有任何零钱。

给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false

输入:bills = [5,5,5,10,20]
输出:true
解释:
前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。
第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。
第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。
由于所有客户都得到了正确的找零,所以我们输出 true。

解决思路

  1. 计算手中5元和10元的数量。当有20元找零的时候,先选择1张10元和1张5元的。

Java实现

class Solution {public boolean lemonadeChange(int[] bills) {int five = 0;int ten = 0;for (int i = 0; i < bills.length; i++) {if (bills[i] == 5) {five++;} else if (bills[i] == 10) {if (five == 0) {return false;}ten++;five--;} else {if (five > 0 && ten > 0) {five--;ten--;} else if (five >= 3) {five -= 3;} else {return false;}}}return true;}
}

406.根据身高重建队列

力扣题目链接

假设有打乱顺序的一群人站成一个队列,数组 people 表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好ki 个身高大于或等于 hi 的人。

请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性(queue[0] 是排在队列前面的人)。

输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
解释:
编号为 0 的人身高为 5 ,没有身高更高或者相同的人排在他前面。
编号为 1 的人身高为 7 ,没有身高更高或者相同的人排在他前面。
编号为 2 的人身高为 5 ,有 2 个身高更高或者相同的人排在他前面,即编号为 0 和 1 的人。
编号为 3 的人身高为 6 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
编号为 4 的人身高为 4 ,有 4 个身高更高或者相同的人排在他前面,即编号为 0、1、2、3 的人。
编号为 5 的人身高为 7 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。
因此 [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 是重新构造后的队列。

解决思路

  1. 进行排序,按照身高由大到小,k由小到大的顺序。
  2. 身高由大到小,先插入身高高的,因为后面的数据不会影响前面人。矮个子挡不到高个子。

Java实现

class Solution {public int[][] reconstructQueue(int[][] people) {Arrays.sort(people, new Comparator<int[]>() {@Overridepublic int compare(int[] o1, int[] o2) {if (o1[0] != o2[0]) {return o2[0] - o1[0];} else {return o1[1] - o2[1];}}});List<int[]> que = new ArrayList<>();for (int[] p : people) {que.add(p[1], p);}return que.toArray(new int[que.size()][]);}
}

在这里插入图片描述


http://www.ppmy.cn/news/673974.html

相关文章

用Java二进制运算、位移运算、逻辑运算

一、对于有符号数据 有符号数&#xff1a;首位&#xff08;最高位&#xff09;数字&#xff08;1表示负数&#xff0c;0表示正数&#xff09; 源码 反码 补码 正数&#xff1a;源码&#xff0c;反码&#xff0c;补码都相同 零&#xff1a;源码&#xff0c;反码&#xff0c;补码…

银行卡预留号码注销了怎么改?

需要去银行网点修改&#xff08;银行上班时间&#xff09;&#xff0c;带上身份证、银行卡和手机&#xff0c;需要注意的是当前银行卡预留号码&#xff0c;必须是本人在用的&#xff0c;不能绑定他人的手机号码。 银行上班时间&#xff1a;周一至周五上午9&#xff1a;00-下午…

ubuntu注销用户

sudo pkill Xorg 删除搜狗拼音 https://www.cnblogs.com/exmyth/p/4066016.html

Linux系统的注销与关闭

注销 字符界面下输入 logout或exit命令。 关闭系统 对于应用于一个多用户多任务状态下的网络服务器来说&#xff0c;除了某些特殊原因&#xff0c;一般情况下系统很少关闭系统&#xff0c;关闭系统时需要注意&#xff1a; 查看系统使用状态通知在线用户关机的时刻使用正确的…

个人公众号注销方法_微信公众号怎么注销,注销方法

【导读】2017年微信公众号怎么注销&#xff1f;注销方法有哪些&#xff1f;根据最新消息&#xff0c;2017年4月12日起&#xff0c;微信公众号可以自主注销&#xff0c;用户在核实身份信息或者验证帐号主体后&#xff0c;可以在公众号后台-“公众号设置”-“原始ID”中&#xff…

工信部推出号码“一键解绑”功能:淘宝、微博手机号可一次性解绑

点击上方“码农突围”&#xff0c;马上关注 这里是码农充电第一站&#xff0c;回复“666”&#xff0c;获取一份专属大礼包 真爱&#xff0c;请设置“星标”或点个“在看” 近日&#xff0c;据Tech星球报道&#xff0c;工信部旗下的中国信息通信研究院推出“一键解绑”功能&…

联通炫铃注销

大家都希望别人拨打自己手机的时候可以听到简洁的嘟嘟声&#xff0c;而不是万年不变的炫铃&#xff0c;其实炫铃早已过时了&#xff0c;更换还要money 可是每次换套餐或者办新卡都会默认开通炫铃&#xff0c;真讨厌啊&#xff0c;ZHOU_VIP在这里教大家一个方法&#xff1a; …

如何查已经欠费的联通手机号码

朋友办了一张联通手机卡&#xff0c;但是由于一些原因不再继续使用了&#xff0c;后来又想用了&#xff0c;发现欠费了&#xff0c;通过打 10010 知道欠了4块多&#xff0c;想着也欠的不多&#xff0c;充一下话费继续用。于是想着用支付宝、微信等给给手机充话费继续用。但是忽…