[豪の算法奇妙冒险] 代码随想录算法训练营第二十九天 | 134-加油站、135-分发糖果、860-柠檬水找零、406-根据身高重建队列

代码随想录算法训练营第二十九天 | 134-加油站、135-分发糖果、860-柠檬水找零、406-根据身高重建队列


LeetCode134 加油站

题目链接:https://leetcode.cn/problems/gas-station/

文章讲解:https://programmercarl.com/0134.加油站.html

视频讲解:https://www.bilibili.com/video/BV1jA411r7WX/?vd_source=b989f2b109eb3b17e8178154a7de7a51

​ 首先想到的是暴力法,遍历每一个加油站为起点的情况,模拟一圈。如果跑了一圈,中途没有断油,而且最后油量大于等于0,则说明这个起点是符合题意的

​ 但是暴力方法时间复杂度是O(n^2),样例超时,未能AC

image-20260115195817691

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        for(int i = 0; i < gas.length; i++){
            int restGas = gas[i] - cost[i];
            int index = (i+1) % gas.length;
            while(restGas > 0 && index != i){
                restGas += gas[index] - cost[index];
                index = (index+1) % gas.length;
            }
            if(restGas >= 0 && index == i){
                return i;
            }
        }
        return -1;
    }
}

​ 如果总油量减去总消耗大于等于零,则一定可以跑完一圈(因为当start = i+1, 且这个start没有被后序的更新替代,则说明从start到数组结束位置(gas.size()-1)之间的sum为正数,若记该sum为B,start之前的sum为A,那么A+B=totalSum, 已知totalSum>=0, A<0, B>0, 所以B>-A, 走完一圈的B+A>=0),说明各个站点的加油站剩油量rest[i]相加一定是大于等于零的

​ 每个加油站的剩余量rest[i]为gas[i] - cost[i],i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油,那么起始位置从i+1算起,再从0计算curSum

image-20260115202343276

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int totalSum = 0;
        int curSum = 0;
        int start = 0;
        for(int i = 0; i < gas.length; i++){
            totalSum += gas[i] - cost[i];
            curSum += gas[i] - cost[i];
            if(curSum < 0){
                curSum = 0;
                start = i+1;
            }
        }
        if(totalSum < 0){
            return -1;
        }
        return start;
    }
}

LeetCode135 分发糖果

题目链接:https://leetcode.cn/problems/candy/description/

文章讲解:https://programmercarl.com/0135.分发糖果.html

视频讲解:https://www.bilibili.com/video/BV1ev4y1r7wN/?vd_source=b989f2b109eb3b17e8178154a7de7a51

​ 主要是要一步一步处理,防止顾此失彼

​ 先确保比左边分数高的人有的糖果数更多,再确保比右边分数高的人有的糖果数更多,最后再统计总糖数即得到题解

image-20260115204335833

class Solution {
    public int candy(int[] ratings) {
        int[] giveCandy = new int[ratings.length];
        giveCandy[0] = 1;
        for(int i = 1; i < ratings.length; i++){
            if(ratings[i] > ratings[i-1]){
                giveCandy[i] = giveCandy[i-1] + 1;
            }else{
                giveCandy[i] = 1;
            }
        }
        for(int i = ratings.length - 2; i >= 0; i--){
            if(ratings[i] > ratings[i+1]){
                giveCandy[i] = Math.max(giveCandy[i+1] + 1, giveCandy[i]);
            }
        }
        int totalSum = 0;
        for(int i = 0; i < ratings.length; i++){
            totalSum += giveCandy[i];
        }
        return totalSum;
    }
}

LeetCode860 柠檬水找零

题目链接:https://leetcode.cn/problems/lemonade-change/description/

文章讲解:https://programmercarl.com/0860.柠檬水找零.html

视频讲解:https://www.bilibili.com/video/BV12x4y1j7DD/?vd_source=b989f2b109eb3b17e8178154a7de7a51

​ 按顺序处理即可,别多想

image-20260115210602602

class Solution {
    public boolean lemonadeChange(int[] bills) {
        int fiveNum = 0;
        int tenNum = 0;
        int twentyNum = 0;
        for(int i = 0; i < bills.length; i++){
            switch(bills[i]){
                case 5: fiveNum++;break;
                case 10:
                    fiveNum--;
                    tenNum++;
                    break;
                case 20:
                    if(tenNum > 0){
                        tenNum--;
                        fiveNum--;
                    }else{
                        fiveNum -= 3;
                    }
            }
            if(fiveNum < 0){
                return false;
            }
        }
        return true;
    }
}

LeetCode406 根据身高重建队列

题目链接:https://leetcode.cn/problems/queue-reconstruction-by-height/description/

文章讲解:https://programmercarl.com/0406.根据身高重建队列.html

视频讲解:https://www.bilibili.com/video/BV1EA411675Y/?vd_source=b989f2b109eb3b17e8178154a7de7a51

​ 关于出现两个维度一起考虑的情况,其技巧都是确定一边然后贪心另一边,两边一起考虑,就会顾此失彼

image-20260115221034837

class Solution {
    public int[][] reconstructQueue(int[][] people) {
        // 身高从大到小排(身高相同k小的站前面)
        Arrays.sort(people, (a, b) -> {
            if (a[0] == b[0]) return a[1] - b[1];   // a - b 是升序排列,故在a[0] == b[0]的狀況下,會根據k值升序排列
            return b[0] - a[0];   //b - a 是降序排列,在a[0] != b[0],的狀況會根據h值降序排列
        });

        LinkedList<int[]> que = new LinkedList<>();
        for (int[] p : people) {
            que.add(p[1],p);   //Linkedlist.add(index, value),會將value插入到指定index裡。
        }

        return que.toArray(new int[people.length][]);
    }
}
posted @ 2026-01-15 22:12  SchwarzShu  阅读(1)  评论(0)    收藏  举报