热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

贪心策略在算法设计中的应用与优化

贪心算法在算法设计中具有广泛的应用,特别是在解决优化问题时表现出色。本文通过分析经典问题“买卖股票的最佳时机II”,探讨了贪心策略的基本原理及其在实际问题中的应用。通过实例分析,展示了贪心算法如何通过局部最优选择逐步达到全局最优解,并讨论了其在时间和空间复杂度上的优势。此外,还提出了一些优化方法,以提高算法的效率和适用性。


贪心算法


    • 什么是贪心算法
    • [122. 买卖股票的最佳时机 II](https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/)
      • 代码

    • [455. 分发饼干](https://leetcode.cn/problems/assign-COOKIEs/)
      • 思路
      • 代码

    • [435. 无重叠区间](https://leetcode.cn/problems/non-overlapping-intervals/)
      • 1.动态规划
      • 2.贪心

    • [55. 跳跃游戏](https://leetcode-cn.com/problems/jump-game/) (medium)
      • 1.动态规划
      • 2.贪心

    • [881. 救生艇](https://leetcode.cn/problems/boats-to-save-people/)
      • 思路
      • 代码

    • [452. 用最少数量的箭引爆气球](https://leetcode.cn/problems/minimum-number-of-arrows-to-burst-balloons/)
      • 代码

    • [134. 加油站](https://leetcode.cn/problems/gas-station/)
      • 思路
      • 代码

    • [860. 柠檬水找零](https://leetcode.cn/problems/lemonade-change/)
      • 代码





什么是贪心算法

贪心法,又称贪心算法,贪婪算法,在对问题求解时,总是做出在当前看来最好的选择,期望通过每个阶段的局部最优选择达到全局最优,但结果不一定最优

适用场景:简单的说,问题能够分解成子问题来解决,子问题的最优解能递推到最终问题的最优解,就能用贪心算法的到最后的最优解,这种子问题最优解称为最优子结构

贪心算法与动态规划的不同点在于它对每个子问题的解决方案都做出当前的最优选择,不能回退,而动态规划会保留之前的运算结果,并根据之前的结果进行选择,有回退的功能,贪心是动态规划的理想化的情况。


122. 买卖股票的最佳时机 II

难度中等

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润

示例 1:

输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3 。
总利润为 4 + 3 = 7 。

示例 2:

输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4 。
总利润为 4 。

示例 3:

输入:prices = [7,6,4,3,1]
输出:0
解释:在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0 。

提示:


  • 1 <&#61; prices.length <&#61; 3 * 104
  • 0 <&#61; prices[i] <&#61; 104

ds_56


  • 思路&#xff1a;因为不限制交易次数&#xff0c;只要今天价格比昨天高&#xff0c;就交易&#xff0c;利润为正累加&#xff0c;最后的和就是最大的利润&#xff0c;注意第一天是没有利润的&#xff0c;这道题之所以可以用贪心是因为局部最优&#xff1a;收集每天的正利润&#xff0c;可以推导出&#xff0c;全局最优&#xff1a;求得最大利润
  • 复杂度分析&#xff1a;时间复杂度O(n)&#xff0c;n是数组的长度。空间复杂度是O(1)

代码

class Solution {
public int maxProfit(int[] prices) {
int n &#61; prices.length;
int res &#61; 0;
for (int i &#61; 1; i < n; &#43;&#43;i) {
//今天价格和昨天的差值是否为正&#xff0c;如果为正累加进去&#xff0c;为负则加0
res &#43;&#61; Math.max(0, prices[i] - prices[i - 1]);
}
return res;
}
}

455. 分发饼干

难度简单

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

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

示例 1:

输入: g &#61; [1,2,3], s &#61; [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干&#xff0c;3个孩子的胃口值分别是&#xff1a;1,2,3。
虽然你有两块小饼干&#xff0c;由于他们的尺寸都是1&#xff0c;你只能让胃口值是1的孩子满足。
所以你应该输出1。

示例 2:

输入: g &#61; [1,2], s &#61; [1,2,3]
输出: 2
解释:
你有两个孩子和三块小饼干&#xff0c;2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.

提示&#xff1a;


  • 1 <&#61; g.length <&#61; 3 * 104
  • 0 <&#61; s.length <&#61; 3 * 104
  • 1 <&#61; g[i], s[j] <&#61; 231 - 1

思路


  • 思路&#xff1a;大尺寸的饼干既可以满足胃口大的孩子也可以满足胃口小的孩子&#xff0c;那么就应该优先满足胃口大的。排序两个数组&#xff0c;从右到左遍历&#xff0c;用大饼干首先满足胃口大的小孩
  • 复杂度&#xff1a;时间复杂度O(mlogm &#43; nlogn)。空间复杂度O(logm &#43; logn)

代码

class Solution {
public int findContentChildren(int[] g, int[] s) {
//排序
Arrays.sort(g);
Arrays.sort(s);
int nums &#61; 0;
int index &#61; s.length -1;//饼干的下标
for (int i &#61; g.length - 1; i >&#61; 0; i--) {
//如果当前饼干能够分给要求最大的孩子
if(index >&#61; 0 && s[index] >&#61; g[i]){
nums&#43;&#43;;
index--;
}
}
return nums;
}
}

435. 无重叠区间

难度中等

给定一个区间的集合 intervals &#xff0c;其中 intervals[i] &#61; [starti, endi] 。返回 需要移除区间的最小数量&#xff0c;使剩余区间互不重叠

示例 1:

输入: intervals &#61; [[1,2],[2,3],[3,4],[1,3]]
输出: 1
解释: 移除 [1,3] 后&#xff0c;剩下的区间没有重叠。

示例 2:

输入: intervals &#61; [ [1,2], [1,2], [1,2] ]
输出: 2
解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。

示例 3:

输入: intervals &#61; [ [1,2], [2,3] ]
输出: 0
解释: 你不需要移除任何区间&#xff0c;因为它们已经是无重叠的了。

提示:


  • 1 <&#61; intervals.length <&#61; 105
  • intervals[i].length &#61;&#61; 2
  • -5 * 104 <&#61; starti

ds_143


1.动态规划


  • 思路&#xff1a;dp[i]表示前i个区间中最大不重合区间的个数&#xff0c;首先将区间数组按左边界排序&#xff0c;找出intervals中最多有多少个不重复的区间&#xff0c;动态规划方程dp[i] &#61; Math.max(dp[i], dp[j] &#43; 1)。intervals的长度减去最多的不重复的区间 就是最少删除区间的个数
  • 复杂度&#xff1a;时间复杂度O(n^2)&#xff0c;两层嵌套循环leetcode执行超时 复杂度过高。空间复杂度O(n)&#xff0c;dp数组的空间

超时

public int eraseOverlapIntervals(int[][] intervals) {
int n &#61; intervals.length;
int[] dp &#61; new int[n];
//按照左边界排序
Arrays.sort(intervals,(o1,o2)->{
return o1[0] - o2[0];
});
Arrays.fill(dp, 1);

for (int i &#61; 1; i < n; &#43;&#43;i) {
for (int j &#61; 0; j < i; &#43;&#43;j) {
if (intervals[j][1] <&#61; intervals[i][0]) {
dp[i] &#61; Math.max(dp[i], dp[j] &#43; 1);
}
}
}
return n - Arrays.stream(dp).max().getAsInt();
}

2.贪心

ds_142


  • 思路&#xff1a;intervals按右边界排序&#xff0c;然后从左往右遍历&#xff0c;右边界结束的越早&#xff0c;留给后面的区间的空间就越大&#xff0c;不重合的区间个数就越多&#xff0c;intervals的长度减去最多的不重复的区间 就是最少删除区间的个数
  • 复杂度&#xff1a;时间复杂度O(nlogn)&#xff0c;数组排序O(nlogn)&#xff0c;循环一次数组O(n)。空间复杂度O(logn)&#xff0c;排序需要的栈空间

https://leetcode.cn/problems/non-overlapping-intervals/solution/435-wu-zhong-die-qu-jian-tan-xin-jing-di-qze0/

class Solution {
public int eraseOverlapIntervals(int[][] intervals) {
//按照右边界排序
//按右边界排序&#xff0c;然后从左往右遍历&#xff0c;右边界结束的越早&#xff0c;
//留给后面的区间的空间就越大&#xff0c;不重合的区间个数就越多
public int eraseOverlapIntervals(int[][] intervals) {
Arrays.sort(intervals,(o1,o2)->{
return Integer.compare(o1[1],o2[1]);
});
int n &#61; intervals.length;
int nums &#61; 0;
int right &#61; intervals[0][1];
for (int i &#61; 1; i < n; i&#43;&#43;) {
if(intervals[i][0] < right){
//如果重叠就丢掉
nums&#43;&#43;;
}else{
//不重叠就更新
right &#61; intervals[i][1];
}
}
return nums;

}
}

能不能用贪心算法需要满足贪心选择性&#xff0c;贪心算法正确的的证明可以用反证法

以这一题为例&#xff1a;


  • 我们的思路是保留最多的不重合的区间&#xff0c;所以按照区间结尾排序&#xff0c;区间结尾结束的越早且和前一个区间不重叠的&#xff0c;就加入最多不重复的区间中&#xff0c;我们称为算法a&#xff0c;假如算法a中的某一个步骤是选择区间[a, b]&#xff0c;我们称为区间A。
  • 假设这个选择不正确&#xff0c;也就是说算法a得到的不是最优解。
  • 我们假设存在另一个算法c能得到最优解&#xff0c;算法c中的一个步骤是选择区间[c, d]&#xff0c;我们称为区间C&#xff0c;使得它是最优解中的一个区间&#xff0c;其中d>b,因为算法a选择的是结尾最先结束且不重合的区间&#xff0c;如果算法a不正确&#xff0c;又因为区间数组中的区间是固定的&#xff0c;则其他算法c肯定存在d>b的情况。
  • 我们用区间A替换区间C完全不影响算法c的结果&#xff0c;因为b,所以不影响区间C后面区间的结果。所以我们选择了区间A也构成了一个最优解。而我们假设的是选择区间A不是最优解&#xff0c;所以和之前的假设矛盾&#xff0c;所以算法a是正确的贪心算法

55. 跳跃游戏 &#xff08;medium&#xff09;

难度中等

给定一个非负整数数组 nums &#xff0c;你最初位于数组的 第一个下标

数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标。

示例 1&#xff1a;

输入&#xff1a;nums &#61; [2,3,1,1,4]
输出&#xff1a;true
解释&#xff1a;可以先跳 1 步&#xff0c;从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。

示例 2&#xff1a;

输入&#xff1a;nums &#61; [3,2,1,0,4]
输出&#xff1a;false
解释&#xff1a;无论怎样&#xff0c;总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 &#xff0c; 所以永远不可能到达最后一个下标。

1.动态规划


  • 思路&#xff1a;dp[i]表示能否到达位置i&#xff0c;对每个位置i判断能否通过前面的位置跳跃过来&#xff0c;当前位置j能达到&#xff0c;并且当前位置j加上能到达的位置如果超过了i&#xff0c;那dp[i]更新为ture&#xff0c;便是i位置也可以到达。
  • 复杂度&#xff1a;时间复杂度O(n^2)&#xff0c;空间复杂度O(n)

class Solution {
public boolean canJump(int[] nums) {
int n &#61; nums.length;
boolean[] dp &#61; new boolean[n];
dp[0] &#61; true;
for (int i &#61; 1; i < n; i&#43;&#43;) {
for (int j &#61; 0; j < i; j&#43;&#43;) {
//当前位置j能达到&#xff0c;并且当前位置j加上能到达的位置如果超过了i&#xff0c;那dp[i]更新为ture&#xff0c;便是i位置也可以到达
if(dp[j] &#61;&#61; true && nums[j] &#43; j >&#61; i){
dp[i] &#61; true;
break;
}
}
}
return dp[n - 1];
}
}

2.贪心


  • 思路&#xff1a;不用考虑每一步跳跃到那个位置&#xff0c;而是尽可能的跳跃到最远的位置&#xff0c;看最多能覆盖的位置&#xff0c;不断更新能覆盖的距离。
  • 复杂度&#xff1a;时间复杂度O(n)&#xff0c;遍历一边。空间复杂度O(1)

ds_147

public boolean canJump(int[] nums) {
if (nums.length &#61;&#61; 1) {
return true;
}
int cover &#61; nums[0];//能覆盖的最远距离
for (int i &#61; 0; i <&#61; cover; i&#43;&#43;) {
cover &#61; Math.max(cover, i &#43; nums[i]);//当前覆盖距离cover和当前位置加能跳跃的距离中取一个较大者
// 覆盖距离超过或等于nums.length - 1 说明能到达终点
if (cover >&#61; nums.length - 1) {
return true;
}
}
return false;//循环完成之后 还没返回true 就是不能达到终点
}

881. 救生艇

难度中等

给定数组 peoplepeople[i]表示第 i 个人的体重 &#xff0c;船的数量不限&#xff0c;每艘船可以承载的最大重量为 limit

每艘船最多可同时载两人&#xff0c;但条件是这些人的重量之和最多为 limit

返回 承载所有人所需的最小船数

示例 1&#xff1a;

输入&#xff1a;people &#61; [1,2], limit &#61; 3
输出&#xff1a;1
解释&#xff1a;1 艘船载 (1, 2)

示例 2&#xff1a;

输入&#xff1a;people &#61; [3,2,2,1], limit &#61; 3
输出&#xff1a;3
解释&#xff1a;3 艘船分别载 (1, 2), (2) 和 (3)

示例 3&#xff1a;

输入&#xff1a;people &#61; [3,5,3,4], limit &#61; 5
输出&#xff1a;4
解释&#xff1a;4 艘船分别载 (3), (3), (4), (5)

提示&#xff1a;


  • 1 <&#61; people.length <&#61; 5 * 104
  • 1 <&#61; people[i] <&#61; limit <&#61; 3 * 104

思路

ds_155


  • 思路&#xff1a;题意是一条船只能坐2人&#xff0c;要求尽可能的用少的船装下这些人。所以可以用贪心策略。让更多的人组成2人组&#xff0c;而且这些2人组的两人重量加起来不超过船的载重。所以可以先排序people&#xff0c;用双指针从两边向中间遍历&#xff0c;让重的人和轻的人组成2人组&#xff0c;如果当前最重的人和最轻的人的重量和超过了载重&#xff0c;那只能让重的人先乘一条船。
  • 复杂度&#xff1a;时间复杂度O(nlogn)&#xff0c;排序的复杂度。空间复杂度O(logn)&#xff0c;排序的栈空间

代码

public int numRescueBoats(int[] people, int limit) {
int n &#61; people.length;
Arrays.sort(people);
int left &#61; 0;
int right &#61; n-1;
int nums &#61; 0;
//让最重的最轻的先走
while (left <&#61; right){
if(people[right] &#43; people[left] <&#61; limit){
right--;
left&#43;&#43;;
nums&#43;&#43;;
}else{
//让最重的一个人走
right--;
nums&#43;&#43;;
}
}
return nums;
}

452. 用最少数量的箭引爆气球

难度中等719收藏分享切换为英文接收动态反馈

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

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

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

示例 1&#xff1a;

输入&#xff1a;points &#61; [[10,16],[2,8],[1,6],[7,12]]
输出&#xff1a;2
解释&#xff1a;气球可以用2支箭来爆破:
-在x &#61; 6处射出箭&#xff0c;击破气球[2,8]和[1,6]。
-在x &#61; 11处发射箭&#xff0c;击破气球[10,16]和[7,12]。

示例 2&#xff1a;

输入&#xff1a;points &#61; [[1,2],[3,4],[5,6],[7,8]]
输出&#xff1a;4
解释&#xff1a;每个气球需要射出一支箭&#xff0c;总共需要4支箭。

示例 3&#xff1a;

输入&#xff1a;points &#61; [[1,2],[2,3],[3,4],[4,5]]
输出&#xff1a;2
解释&#xff1a;气球可以用2支箭来爆破:
- 在x &#61; 2处发射箭&#xff0c;击破气球[1,2]和[2,3]。
- 在x &#61; 4处射出箭&#xff0c;击破气球[3,4]和[4,5]。


有点类似前面的最小区间,注意不能直接o1[1] - o2[1] 有个案例会溢出


ds_163


  • 思路&#xff1a;区间按照结尾从小到大排序&#xff0c;循环数组&#xff0c;如果后面一个区间的开始大于前一个区间的结尾 就需要新增一支箭。
  • 复杂度&#xff1a;时间复杂度O(nlogn)&#xff0c;排序的复杂度O(nlogn)&#xff0c;循环数组的复杂度O(n)。空间复杂度O(logn)&#xff0c;排序栈空间

代码

class Solution {
public int findMinArrowShots(int[][] points) {

//按照右边界升序排序
Arrays.sort(points, (o1, o2) -> {
return Integer.compare(o1[1], o2[1]);
});
int n &#61; points.length;
// for (int[] point : points) {
// for (int i : point) {
// System.out.print(i &#43; " ");
// }
// System.out.println();
// }
int nums &#61; 1;
int right &#61; points[0][1];

//如果下一个的左边比之前的右边大 nums&#43;1
for (int i &#61; 1; i < n; i&#43;&#43;) {
if (points[i][0] > right) {
right &#61; points[i][1];
nums&#43;&#43;;
}
}
return nums;
}
}

134. 加油站

难度中等

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

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

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

示例 1:

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

示例 2:

输入: gas &#61; [2,3,4], cost &#61; [3,4,3]
输出: -1
解释:
你不能从 0 号或 1 号加油站出发&#xff0c;因为没有足够的汽油可以让你行驶到下一个加油站。
我们从 2 号加油站出发&#xff0c;可以获得 4 升汽油。 此时油箱有 &#61; 0 &#43; 4 &#61; 4 升汽油
开往 0 号加油站&#xff0c;此时油箱有 4 - 3 &#43; 2 &#61; 3 升汽油
开往 1 号加油站&#xff0c;此时油箱有 3 - 3 &#43; 3 &#61; 3 升汽油
你无法返回 2 号加油站&#xff0c;因为返程需要消耗 4 升汽油&#xff0c;但是你的油箱只有 3 升汽油。
因此&#xff0c;无论怎样&#xff0c;你都不可能绕环路行驶一周。

提示:


  • gas.length &#61;&#61; n
  • cost.length &#61;&#61; n
  • 1 <&#61; n <&#61; 105
  • 0 <&#61; gas[i], cost[i] <&#61; 104

思路


ds_173
  • 思路&#xff1a;首先判断总油量是否小于总油耗&#xff0c;如果是则肯定不能走一圈。如果否&#xff0c;那肯定能跑一圈。接下来就是循环数组&#xff0c;从第一个站开始&#xff0c;计算每一站剩余的油量&#xff0c;如果油量为负了&#xff0c;就以这个站为起点从新计算。如果到达某一个点为负&#xff0c;说明起点到这个点中间的所有站点都不能到达该点。
  • 复杂度&#xff1a;时间复杂度O(n)&#xff0c;空间复杂度O(1)

代码

class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int n &#61; gas.length;
int sumGas &#61; 0;
int sumCost &#61; 0;
for (int i &#61; 0; i < n; i&#43;&#43;) {
sumGas &#43;&#61; gas[i];
sumCost &#43;&#61; cost[i];
}
//如果总油量小于总距离,失败
if (sumGas < sumCost) {
return -1;
}
int currentGas &#61; 0;
int start &#61; 0;
for (int i &#61; 0; i < n; i&#43;&#43;) {
currentGas &#43;&#61; gas[i] - cost[i];
//如果到达下一站的时候油量为负数 就以这个站为起点 从新计算
if (currentGas < 0) {
currentGas &#61; 0;
start &#61; i &#43; 1;
}
}
return start;
}
}

860. 柠檬水找零

难度简单

在柠檬水摊上&#xff0c;每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品&#xff0c;&#xff08;按账单 bills 支付的顺序&#xff09;一次购买一杯。

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

注意&#xff0c;一开始你手头没有任何零钱。

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

示例 1&#xff1a;

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

示例 2&#xff1a;

输入&#xff1a;bills &#61; [5,5,10,10,20]
输出&#xff1a;false
解释&#xff1a;
前 2 位顾客那里&#xff0c;我们按顺序收取 2 张 5 美元的钞票。
对于接下来的 2 位顾客&#xff0c;我们收取一张 10 美元的钞票&#xff0c;然后返还 5 美元。
对于最后一位顾客&#xff0c;我们无法退回 15 美元&#xff0c;因为我们现在只有两张 10 美元的钞票。
由于不是每位顾客都得到了正确的找零&#xff0c;所以答案是 false。

代码

class Solution {
public boolean lemonadeChange(int[] bills) {
int five &#61; 0, ten &#61; 0;
for (int bill : bills) {
if (bill &#61;&#61; 5) {
five&#43;&#43;;
} else if (bill &#61;&#61; 10) {
if (five &#61;&#61; 0) {
return false;
}
five--;
ten&#43;&#43;;
} else {
if (five > 0 && ten > 0) {
five--;
ten--;
} else if (five >&#61; 3) {
five -&#61; 3;
} else {
return false;
}
}
}
return true;

}
}






推荐阅读
  • 理解浏览器历史记录(2)hashchange、pushState
    阅读目录1.hashchange2.pushState本文也是一篇基础文章。继上文之后,本打算去研究pushState,偶然在一些信息中发现了锚点变 ... [详细]
  • 长期从事ABAP开发工作的专业人士,在面对行业新趋势时,往往需要重新审视自己的发展方向。本文探讨了几位资深专家对ABAP未来走向的看法,以及开发者应如何调整技能以适应新的技术环境。 ... [详细]
  • 从理想主义者的内心深处萌发的技术信仰,推动了云原生技术在全球范围内的快速发展。本文将带你深入了解阿里巴巴在开源领域的贡献与成就。 ... [详细]
  • 本文详细介绍了如何正确设置Shadowsocks公共代理,包括调整超时设置、检查系统限制、防止滥用及遵守DMCA法规等关键步骤。 ... [详细]
  • 在1995年,Simon Plouffe 发现了一种特殊的求和方法来表示某些常数。两年后,Bailey 和 Borwein 在他们的论文中发表了这一发现,这种方法被命名为 Bailey-Borwein-Plouffe (BBP) 公式。该问题要求计算圆周率 π 的第 n 个十六进制数字。 ... [详细]
  • 本文探讨了如何将个人经历,特别是非传统的职业路径,转化为职业生涯中的优势。通过作者的亲身经历,展示了舞蹈生涯对商业思维的影响。 ... [详细]
  • Java 中的十进制样式 getZeroDigit()方法,示例 ... [详细]
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • CRZ.im:一款极简的网址缩短服务及其安装指南
    本文介绍了一款名为CRZ.im的极简网址缩短服务,该服务采用PHP和SQLite开发,体积小巧,约10KB。本文还提供了详细的安装步骤,包括环境配置、域名解析及Nginx伪静态设置。 ... [详细]
  • Irish budget airline Ryanair announced plans to significantly increase its route network from Frankfurt Airport, marking a direct challenge to Lufthansa, Germany's leading carrier. ... [详细]
  • 我的读书清单(持续更新)201705311.《一千零一夜》2006(四五年级)2.《中华上下五千年》2008(初一)3.《鲁滨孙漂流记》2008(初二)4.《钢铁是怎样炼成的》20 ... [详细]
  • 近期尝试从www.hub.sciverse.com网站通过编程手段获取数据时遇到问题,起初尝试使用WebBrowser控件进行数据抓取,但发现使用GET方法翻页时,返回的HTML代码始终相同。进一步探究后了解到,该网站的数据是通过Ajax异步加载的,可通过HTTP查看详细的JSON响应。 ... [详细]
  • Jupyter Notebook多语言环境搭建指南
    本文详细介绍了如何在Linux环境下为Jupyter Notebook配置Python、Python3、R及Go四种编程语言的环境,包括必要的软件安装和配置步骤。 ... [详细]
  • Android与JUnit集成测试实践
    本文探讨了如何在Android项目中集成JUnit进行单元测试,并详细介绍了修改AndroidManifest.xml文件以支持测试的方法。 ... [详细]
  • 深入解析WebP图片格式及其应用
    随着互联网技术的发展,无论是PC端还是移动端,图片数据流量占据了很大比重。尤其在高分辨率屏幕普及的背景下,如何在保证图片质量的同时减少文件大小,成为了亟待解决的问题。本文将详细介绍Google推出的WebP图片格式,探讨其在实际项目中的应用及优化策略。 ... [详细]
author-avatar
手机用户2502863361
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有