目录
简单
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。
对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
示例 1:
输入: g = [1,2,3], s = [1,1] 输出: 1 解释: 你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。 虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。 所以你应该输出1。
示例 2:
输入: g = [1,2], s = [1,2,3] 输出: 2 解释: 你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。 你拥有的饼干数量和尺寸都足以让所有孩子满足。 所以你应该输出2.
提示:
1 <= g.length <= 3 * 1040 <= s.length <= 3 * 1041 <= g[i], s[j] <= 231 - 1用可满足该孩子的最小饼干去喂该孩子
- class Solution {
- // 方法用于找到可以匹配的孩子和饼干的数量
- public int findContentChildren(int[] g, int[] s) {
- // 对孩子的胃口大小数组和饼干大小数组进行排序
- Arrays.sort(g);
- Arrays.sort(s);
-
- // begin变量用于记录饼干数组当前检查的起始位置
- int begin = 0;
- // count变量用于记录成功匹配的孩子和饼干的数量
- int count = 0;
-
- // 遍历孩子的胃口大小数组
- for(int i = 0; i < g.length; i++){
- // 从begin开始遍历饼干大小数组
- for(int j = begin; j < s.length; j++){
- // 如果找到一块饼干的大小大于等于当前孩子的胃口
- if(s[j] >= g[i]){
- // 更新begin为当前饼干的后一个位置,这样下次就不需要再检查这块饼干
- begin = j + 1;
- // 匹配成功,count加1
- count++;
- // 跳出内层循环,继续检查下一个孩子的胃口
- break;
- }
- }
- }
- // 返回成功匹配的孩子和饼干的数量
- return count;
- }
- }
简单
给你一个整数数组 nums 和一个整数 k ,按以下方法修改该数组:
i 并将 nums[i] 替换为 -nums[i] 。重复这个过程恰好 k 次。可以多次选择同一个下标 i 。
以这种方式修改数组后,返回数组 可能的最大和 。
示例 1:
输入:nums = [4,2,3], k = 1 输出:5 解释:选择下标 1 ,nums 变为 [4,-2,3] 。
示例 2:
输入:nums = [3,-1,0,2], k = 3 输出:6 解释:选择下标 (1, 2, 2) ,nums 变为 [3,1,0,2] 。
示例 3:
输入:nums = [2,-3,-1,5,-4], k = 2 输出:13 解释:选择下标 (1, 4) ,nums 变为 [2,3,-1,5,4] 。
提示:
1 <= nums.length <= 104-100 <= nums[i] <= 1001 <= k <= 104排序后取反k次,优先取反负数,负数全部取反后,排序得到最小的非负数,对其进行k次取反后得到最大的sum
- class Solution {
- // 方法用于计算在数组nums上进行k次取反操作后可能得到的最大和
- public int largestSumAfterKNegations(int[] nums, int k) {
- int sum = 0;
-
- // 先对数组进行排序,这样负数会排在前面
- Arrays.sort(nums);
-
- // 遍历数组,将负数取反(如果k还有剩余并且当前数字是负数)
- for(int i = 0; i < nums.length; i++){
- if(k > 0 && nums[i] < 0){
- nums[i] = -nums[i]; // 取反当前负数
- k--; // k剩余次数减1
- }
- }
-
- // 再次对数组进行排序,因为取反操作可能改变了数组的顺序
- Arrays.sort(nums);
-
- // 如果k还有剩余且为奇数,则将最小的数取反(这样可以得到最大和)
- if(k > 0 && k % 2 == 1){
- nums[0] = -nums[0];
- }
-
- // 计算排序后数组的总和
- for(int i = 0; i < nums.length; i++){
- sum += nums[i];
- }
-
- // 返回计算得到的最大和
- return sum;
- }
- }
笨蛋写法,每次取反都取最小的
- class Solution {
- public int largestSumAfterKNegations(int[] nums, int k) {
-
- int sum = 0;
- for(int i = 0; i < k; i++){
- Arrays.sort(nums);
- nums[0] = -nums[0];
- }
- for(int i = 0; i < nums.length; i++){
- sum += nums[i];
- }
- return sum;
- }
- }
简单
在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。
每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。
注意,一开始你手头没有任何零钱。
给你一个整数数组 bills ,其中 bills[i] 是第 i 位顾客付的账。如果你能给每位顾客正确找零,返回 true ,否则返回 false 。
示例 1:
输入:bills = [5,5,5,10,20] 输出:true 解释: 前 3 位顾客那里,我们按顺序收取 3 张 5 美元的钞票。 第 4 位顾客那里,我们收取一张 10 美元的钞票,并返还 5 美元。 第 5 位顾客那里,我们找还一张 10 美元的钞票和一张 5 美元的钞票。 由于所有客户都得到了正确的找零,所以我们输出 true。
示例 2:
输入:bills = [5,5,10,10,20] 输出:false 解释: 前 2 位顾客那里,我们按顺序收取 2 张 5 美元的钞票。 对于接下来的 2 位顾客,我们收取一张 10 美元的钞票,然后返还 5 美元。 对于最后一位顾客,我们无法退回 15 美元,因为我们现在只有两张 10 美元的钞票。 由于不是每位顾客都得到了正确的找零,所以答案是 false。
提示:
1 <= bills.length <= 105bills[i] 不是 5 就是 10 或是 20 我的思路:因为美元10只能给账单20找零,而美元5可以给账单10和账单20找零,美元5更万能!所以找零优先用10元面值
- class Solution {
- // 判断是否能通过5元和10元找零满足所有顾客
- public boolean lemonadeChange(int[] bills) {
- // 使用一个数组来统计各个面额的纸币数量,数组下标代表纸币面额,从1到20
- int[] count = new int[21];
-
- // 遍历每张纸币
- for(int i = 0; i < bills.length; i++){
- // 当前纸币的面额出现次数加1
- count[bills[i]] += 1;
-
- // 需要的找零金额,初始值为当前纸币面额减去5
- int change = bills[i] - 5;
-
- // 当需要找零的金额大于等于10,并且还有10元纸币可用时
- while(change >= 10 && count[10] > 0){
- // 使用一张10元纸币找零
- count[10] -= 1;
- // 更新找零金额,减去10
- change -= 10;
- }
-
- // 当剩余的找零金额大于等于5,并且还有5元纸币可用时
- while(change >= 5 && count[5] > 0){
- // 使用一张5元纸币找零
- count[5] -= 1;
- // 更新找零金额,减去5
- change -= 5;
- }
-
- // 如果找零金额仍然不为0,说明当前纸币无法找零
- if(change != 0){
- return false;
- }
- }
-
- // 如果所有纸币都能成功找零,返回true
- return true;
- }
- }
找零有如下三种情况:
此时大家就发现 情况一,情况二,都是固定策略,都不用我们来做分析了,而唯一不确定的其实在情况三。
而情况三逻辑也不复杂甚至感觉纯模拟就可以了,其实情况三这里是有贪心的。
账单是20的情况,为什么要优先消耗一个10和一个5呢?
因为美元10只能给账单20找零,而美元5可以给账单10和账单20找零,美元5更万能!
所以局部最优:遇到账单20,优先消耗美元10,完成本次找零。全局最优:完成全部账单的找零。
- class Solution {
- public boolean lemonadeChange(int[] bills) {
- // five表示当前拥有的5元纸币数量
- int five = 0;
- // ten表示当前拥有的10元纸币数量
- int ten = 0;
-
- // 遍历顾客支付的每张纸币
- for (int i = 0; i < bills.length; i++) {
- // 如果当前纸币是5元
- if (bills[i] == 5) {
- // 增加5元纸币的数量
- five++;
- }
- // 如果当前纸币是10元
- else if (bills[i] == 10) {
- // 需要找零5元,因此减少5元纸币的数量
- five--;
- // 增加10元纸币的数量
- ten++;
- }
- // 如果当前纸币是20元
- else if (bills[i] == 20) {
- // 优先使用10元和5元纸币找零
- if (ten > 0) {
- // 如果有10元纸币,则使用一张10元纸币找零
- ten--;
- // 同时使用一张5元纸币找零
- five--;
- } else {
- // 如果没有10元纸币,则使用三张5元纸币找零
- five -= 3;
- }
- }
- // 如果在找零过程中5元或10元纸币数量变为负数,说明无法找零,返回false
- if (five < 0 || ten < 0) return false;
- }
-
- // 如果所有纸币都能成功找零,返回true
- return true;
- }
- }