Leetcode分类——贪心算法
- 一、贪心法
- 二、贪心的前提
- 三、算法举例
- Leetcode 455
- Leetcode 402
- 其他题目
- Leetcode 376
- Leetcode 55
- Leetcode 452
一、贪心法
遵循某种规律,不断贪心地选取最优策略来求解。
二、贪心的前提
最优解能够划分成多个次优解,例如找零钱问题中,零钱的种类必须是倍数包含关系(如100,20,10,15,1元),如果包含了50元或7元类型,贪心法求解可能出错,此时应该使用动态规划来做。
三、算法举例
Leetcode 455
题目
代码语言:javascript复制假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
注意:
你可以假设胃口值为正。
一个小朋友最多只能拥有一块饼干。
示例 1:
输入: [1,2,3], [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
示例 2:
输入: [1,2], [1,2,3]
输出: 2
解释:
你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。
你拥有的饼干数量和尺寸都足以让所有孩子满足。
所以你应该输出2.
贪心规律
- 如果某个饼干不能满足该孩子,一定不能满足需求因子更大的孩子;
- 如果能用更小的饼干满足该孩子,则没必要用更大的;
- 需求因子小的孩子更容易被满足,故应从小到大开始分配。
算法思路
- 对饼干大小和孩子的需求因子从小到大排序;
- 二路遍历,满足条件即比较下一个,直至一路完毕。
class Solution {
public int findContentChildren(int[] g, int[] s) {
//步骤1:排序
Arrays.sort(g);
Arrays.sort(s);
int count = 0, childIndex = 0, cookieIndex = 0;
//步骤2:遍历比较
while (childIndex < g.length && cookieIndex < s.length) {
if (g[childIndex] <= s[cookieIndex]) {
//只有匹配成功,才开始比较下一个(需求因子更大的),计数器也要加1
count;
childIndex;
}
//无论成功失败,饼干序列都要加1
cookieIndex;
}
return count;
}
}
Leetcode 402
题目,贪心算法经常和堆栈等数据结构一起出现
代码语言:javascript复制给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小。
注意:
num 的长度小于 10002 且 ≥ k。
num 不会包含任何前导零。
示例 1 :
输入: num = "1432219", k = 3
输出: "1219"
解释: 移除掉三个数字 4, 3, 和 2 形成一个新的最小的数字 1219。
示例 2 :
输入: num = "10200", k = 1
输出: "200"
解释: 移掉首位的 1 剩下的数字为 200. 注意输出不能有任何前导零。
示例 3 :
输入: num = "10", k = 2
输出: "0"
解释: 从原数字移除所有的数字,剩余为空就是0。
贪心规律
- 从高位向地位遍历,如果对应的数字大于下一位数字,则把该位去掉。
算法思路
- 最暴力的解法,删除k个数字即从最高位开始遍历k次;
- 如何简化:利用栈存储,依次压栈,如果当先待压入的数字小于栈顶元素,则弹栈。(比较过的位数不用动,已经是最小的了)
特殊情况
- 如果栈空后k仍大于0怎么办?——
- 如果存在0怎么办?——
public String removeKdigits1(String num, int k) {
Stack<Integer> stack = new Stack<>();
String res = "";
//遍历整个字符串
for (int i = 0; i < num.length(); i){
int number = num.charAt(i) - '0';
//贪心算法删除数字,一个数字可以一直删
while (!stack.empty() && stack.peek() > number && k > 0) {
stack.pop();
--k;
}
//首位不为0,或者0不在首位时,入栈
if (number != 0 || !stack.empty())
stack.push(number);
}
//k还有剩余的情况
while (!stack.empty() && k > 0) {
stack.pop();
--k;
}
//将栈内数字输出到字符串
while (!stack.empty()){
res = stack.pop() res;
}
return (res == "")? "0" : res;
}
其他题目
Leetcode 376
贪心规律:当序列有一段连续的递增或递减时,为形成摇摆子序列,我们只需要保留这段连续的递增或递减的首尾元素,这样更可能使得尾部的后一个元素成为摇摆子序列的下一个元素。