代码随想录-2023/08/02

78 阅读1分钟

贪心算法

860.柠檬水找零

解题思路:贪心

  1. 遇到5, 不用找零, 5元硬币的次数+1
  2. 遇到10, 判断能否找0, 不能找零直接返回false
  3. 遇到20, 优先找零15, 其次判断再找零三个五元, 最后无法找零则返回false

代码:

class Solution {
    public boolean lemonadeChange(int[] bills) {
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(bills[0], 1);
        for(int i=1; i<bills.length; i++){
            // 不用找零
            if(bills[i] == 5){
                map.put(5, map.getOrDefault(5, 0) + 1);
            }else if(bills[i] == 10){
                // 必须找零 5 元
                if(map.getOrDefault(5, 0) > 0){
                    map.put(5, map.getOrDefault(5, 0) - 1);
                    map.put(10, map.getOrDefault(10, 0) + 1);
                }else return false;
            }else if(bills[i] == 20){
                if(map.getOrDefault(10, 0) > 0 && map.getOrDefault(5, 0) > 0){
                    map.put(10, map.getOrDefault(10, 0) - 1);
                    map.put(5, map.getOrDefault(5, 0) - 1);
                    map.put(20, map.getOrDefault(20, 0) + 1);
                }else if(map.getOrDefault(5, 0) > 2) {
                    map.put(5, map.getOrDefault(5, 0) - 3);
                    map.put(20, map.getOrDefault(20, 0) + 1);
                }
                else return false;
            }
        }

        return true;
    }
}

406.根据身高重建队列

解题思路:贪心-排序+插入

  1. 先按照身高排序, 身高较高的排在前面, 若身高相同, 则位置小的靠前
  2. 排序后, 对每个元素进行插入排序, 将其放在对应的位置上即可
  3. 因为排序后, 元素移动不会影响整个队列的结果

代码:

class Solution {
    public int[][] reconstructQueue(int[][] people) {
        // 按照身高降序排序, 然后根据位置插入
        List<int[]> list = new ArrayList<>();
        for(int[] arr: people){
            list.add(arr);
        }
        Collections.sort(list, (c1,c2) -> {
            if(c1[0] == c2[0]) return c1[1]-c2[1];
            else return c2[0]-c1[0];
        });

        // 按照位置插入
        List<int[]> ans = new ArrayList<>();
        for(int i=0; i<list.size(); i++){
            int[] a = list.get(i);
            ans.add(a[1], a);
        }
        
        return ans.toArray(new int[people.length][]);
    }
}

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

解题思路:重叠区间

  1. 从下标为1的元素开始, 判断后端区间和前面区间是否有重叠
  2. 若有重叠, 则将新区间置为重叠区间的交集
  3. 若无区间, 则代表所使用的弓箭数量+1, 且无需更新区间

代码:

class Solution {
    public int findMinArrowShots(int[][] points) {
        Arrays.sort(points, (c1,c2)->Integer.compare(c1[0], c2[0]));

        int ans =  1;
        // 用list记录上一箭区间
        LinkedList<int[]> list = new LinkedList<>();
        list.add(points[0]);
        for(int i=1; i<points.length; i++) {
            int[] pre = list.getLast();
            // 没有重叠区间
            if(pre[1] < points[i][0]) {
                list.add(points[i]);
                ans++;
            }else {
                list.removeLast();
                list.add(new int[]{Math.max(pre[0], points[i][0]), Math.min(pre[1], points[i][1])});
            }
        }

        return ans;
    }
}