Day37~860.柠檬水找零、406.根据身高重建队列、452. 用最少数量的箭引爆气球

116 阅读2分钟

摘要

本文主要介绍了LeetCode贪心算法的几个题目,包括860.柠檬水找零、406.根据身高重建队列、452. 用最少数量的箭引爆气球。

1、860.柠檬水找零

1.1 思路

  • 局部最优:优先消耗10美元,因为5美元的找零用处更大,能多留着就多留着

  • 3 种情况

    1. 账单是5: 5++
    2. 账单是10: 5--, 10++
    3. 账单是20: 10--,5--,20++; 5--,5--,20++

1.2 代码

    public boolean lemonadeChange(int[] bills) {
        int five = 0;
        int ten = 0;
        int twenty = 0;
​
        for(int bill : bills) {
            if(bill == 5) {
                five++;
            } else if(bill == 10) {
                if(five > 0) {
                    five--;
                    ten++;
                } else {
                    return false;
                }
            } else {
                if(ten > 0 && five > 0) {
                    five--;
                    ten--;
                    twenty++;
                } else if(five >= 3) {
                    five -= 3;
                    twenty++;
                } else {
                    return false;
                }
            }
        }
        return true;
    }

2、406.根据身高重建队列

2.1 思路

解题思路

  • 先确定身高维度,然后再去确定k这个维度,最后得出题目要求的数列
  • 按照身高排序之后,优先按身高高的people的k来插入,后序插入节点也不会影响前面已经插入的节点,最终按照k的规则完成了队列。
  • 数组排序

    • Arrays.sort(people, (a, b) -> {
          if (a[0] == b[0]) return a[1] - b[1];
          return b[0] - a[0];
      });
      
  • LinkedList 按下标添加元素

    • LinkedList<int[]> que = new LinkedList<>();
      for (int[] p : people) {
          que.add(p[1],p);
      }
      
  • 集合转数组

    • que.toArray(new int[people.length][]);
      

插入过程

排序完的people: [[7,0], [7,1], [6,1], [5,0], [5,2],[4,4]]

插入的过程:

  • 插入[7,0]:[[7,0]]
  • 插入[7,1]:[[7,0],[7,1]]
  • 插入[6,1]:[[7,0],[6,1],[7,1]]
  • 插入[5,0]:[[5,0],[7,0],[6,1],[7,1]]
  • 插入[5,2]:[[5,0],[7,0],[5,2],[6,1],[7,1]]
  • 插入[4,4]:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]

此时就按照题目的要求完成了重新排列。

2.2 代码

    public int[][] reconstructQueue(int[][] people) {
        Arrays.sort(people, (a, b) -> {
            if(a[0] == b[0]) {
                return a[1] - b[1];
            }
            return b[0] - a[0];
        });
​
        LinkedList<int[]> queue = new LinkedList<>();
        for(int[] p : people) {
            queue.add(p[1], p);
        }
        return queue.toArray(new int[people.length][]);
    }

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

3.1 思路

  • 如果当前气球的左边界大于前一个气球的右边界,说明一定要多加一个弓箭
  • 反之则代表当前气球与前一个气球重叠,当前气球的右边界取当前气球和前一个气球有边界的最小值

3.2 代码

    public int findMinArrowShots(int[][] points) {
        Arrays.sort(points, (a, b) -> {
            return Integer.compare(a[0], b[0]);
        });
​
        int count = 1;
        for(int i=1; i<points.length; i++) {
            if(points[i][0] > points[i-1][1]) {
                count++;
            } else {
                points[i][1] = Math.min(points[i-1][1], points[i][1]);
            }
        }
        return count;
    }

参考资料

代码随想录-860.柠檬水找零

代码随想录-406.根据身高重建队列

代码随想录-452. 用最少数量的箭引爆气球