首页 > 编程语言 >Day 29 贪心算法 Part03

Day 29 贪心算法 Part03

时间:2024-07-31 14:49:56浏览次数:11  
标签:map return int Part03 gas 29 ++ length Day

今天的题目真是给我做恶心了

134. 加油站

暴力方法很容易写出来,但在力扣上运行会超时。

class Solution {
    int[] gas;
    int[] cost;
    public int canCompleteCircuit(int[] gas, int[] cost) {
        this.gas = gas;
        this.cost = cost;
        for(int i = 0; i < gas.length; i++){
            if(gas[i] < cost[i]) continue;
            if(isVaild(i)) return i;
        }
        return -1;
    }
    public boolean isVaild(int index){
        int oil = 0;
        for(int i = index; i < index + gas.length; i++){
            int ind = i % gas.length;
            oil = oil + gas[ind] - cost[ind];
            if(oil < 0) return false;
        }
        return true;
    }
}

这个解法有点太优雅了,太难想到。gas = [1,2,3,4,5] cost = [3,4,5,1,2]对于这两个我们可以求其差值,dif = [-2,-2,-2,3,3],其实本题的题意就是要使得从某个位置出发,dif的累加和始终大于等于0。然而我们可以发现,无论从哪个位置开始累加,累加和的曲线是完全平行的,但是上下会有差别(这个我不知道怎么证明,全凭感觉)。所以,无论从哪个点出发,最小值出现的位置并不会发生改变。因此,就从0出发,找到累加和最小值的位置,其下一个点就是出发点(亏空最严重的一个点必须放在最后一步走,等着前面剩余的救助)。当然这里还需要考虑dif总和小于0,说明不存在出发点。

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int sum = 0;
        int minIndex = 0;
        int minValue = Integer.MAX_VALUE;
        for(int i = 0; i < gas.length; i++){
            sum += gas[i] - cost[i];
            if(sum <= minValue){
                minIndex = i;
                minValue = sum;
            }
        }
        return sum < 0 ? -1 : (minIndex+1) % gas.length;
    }
}

135. 分发糖果

努力去理解了,但还是理解不了,只能靠背了。但是背只能记忆怎么去做的步骤,为什么能保证正确性其实是不明白的。

思路就看题解吧

class Solution {
    /**
         分两个阶段
         1、起点下标1 从左往右,只要 右边 比 左边 大,右边的糖果=左边 + 1
         2、起点下标 ratings.length - 2 从右往左, 只要左边 比 右边 大,此时 左边的糖果应该 取本身的糖果数(符合比它左边大) 和 右边糖果数 + 1 二者的最大值,这样才符合 它比它左边的大,也比它右边大
    */
    public int candy(int[] ratings) {
        int len = ratings.length;
        int[] candyVec = new int[len];
        candyVec[0] = 1;
        for (int i = 1; i < len; i++) {
            candyVec[i] = (ratings[i] > ratings[i - 1]) ? candyVec[i - 1] + 1 : 1;
        }

        for (int i = len - 2; i >= 0; i--) {
            if (ratings[i] > ratings[i + 1]) {
                candyVec[i] = Math.max(candyVec[i], candyVec[i + 1] + 1);
            }
        }
        int ans = 0;
        for (int num : candyVec) {
            ans += num;
        }
        return ans;
    }
}

860. 柠檬水找零

也就只能做这个题了,今天的题目放它就是为了不把人完全打击至死吧我觉得。

class Solution {
    public boolean lemonadeChange(int[] bills) {
        int[] map = new int[3];
        for(int num : bills){
            if(num == 5) map[0]++;
            if(num == 10) {
                map[1]++;
                if(--map[0] < 0) return false;
            }
            if(num == 20){
                map[2]++;
                if(map[1] > 0){
                    map[1]--;
                    if(--map[0] < 0) return false;
                }else{
                    map[0] -= 3;
                    if(map[0] < 0) return false;
                }
            }
        }
        return true;
    }
}

406. 根据身高重建队列

我只能想到暴力解法,但时间复杂度很高。先简单叙述思路,也能帮助对题解的理解。

根据身高对原数组升序排序,相同身高的则根据k升序。用res数组存储最终的结果,用两层循环去遍历,第一层循环代表将要填充的为位置,第二层对people进行遍历,若符合条件(res中已存元素中,身高大于等于当前person的数量恰好等于将要插入的k)就插入。填充满了就返回结果。由于插入每次都能保证是唯一且正确的,所以不会出现错误的情况。这里的贪心就在于,(5,0)和(7, 0)尽管都能放在第一个位置,但由于排序,先进行填充的一定是(5, 0)。

class Solution {
    public int[][] reconstructQueue(int[][] people) {
        Arrays.sort(people, (a, b) -> {
            if(a[0] - b[0] == 0) return a[1] - b[1];
            return a[0] - b[0];
        });
        int[][] res = new int[people.length][];
        boolean[] visited = new boolean[people.length];
        
        for(int i = 0; i < people.length; i++){
            for(int j = 0; j < people.length; j++){
                if(visited[j]) continue;
                if(isValid(res, people[j], i)) {
                    visited[j] = true;
                    res[i] = people[j];
                    break;
                }
            }
        }
        return res;
    }

    public boolean isValid(int[][] res, int[] person, int len){
        int h = person[0]; int k = person[1];
        for(int i = 0; i < len; i++){
            if(res[i][0] >= h) k--;
        }
        return k == 0;
    }
}

标签:map,return,int,Part03,gas,29,++,length,Day
From: https://www.cnblogs.com/12sleep/p/18334576

相关文章

  • 学习Java的日子 Day60 JSP
    JSP核心技术1.什么是JSPJSP和servle技术一样,都是SUN公司定义的一种用于开发动态web资源的技术。JSP实际上就是ServletJSP这门技术的最大的特点在于,写jsp就像在写html,但它相比html而言,html只能为用户提供静态数据,而Jsp技术允许在页面中嵌套java代码,为用户提供动态数据......
  • Day15 二叉树Part2 初见回溯(二叉树相关)
    任务110.平衡二叉树给定一个二叉树,判断它是否是平衡二叉树思路典型的树形DP,每个节点向它的左右孩子收集信息,然后利用收集到的信息判断当前节点,最后再将信息传给上层。对于本题,每个节点要判断以自己为根的树是否是平衡二叉树,需要判断3个条件:自己的左子树是否平衡自己的右子......
  • C++学习04day--引用
    案例代码:会发现最后程序执行完,打印X,最后还是100C++与C语言类似,C++中函数的参数是形式参数,即是实参的拷贝,所以修改的不是实参,所以X不改变,因此我们引入引用引用:即为某个已存在的变量名,引用变量与被引用变量公用一块内存空间,比如土豆和马铃薯都是同一种东西的不同命名。通过在......
  • 基于ads1292的心电信号采集之芯片关键点备忘
    一前记团队在作基于ads1292的心电数据采集时候,遇到了一些问题。这里做一个记录和备忘。也希望能帮的到同样遇到困难的朋友。 二关注点1reset引脚不能悬空,这个悬空的时候,笔者发现ads1292无法正常工作。  2.start信号在单独使用的时候,不要接GND......
  • Atcoder ABC296 F
    AtcoderABC296FF-SimultaneousSwap链接:F-SimultaneousSwap(atcoder.jp)简要题意:问题陈述给你两个\(N\)数字序列:\(A=(A_1,A_2,\ldots,A_N)\)和\(B=(B_1,B_2,\ldots,B_N)\)。高桥可以重复下面的操作任意多次(可能为零)。在\(1\)和\(N\)之间选择三......
  • C语言7~8 DAY
    循环结构什么是循环代码的重复执行,就叫做循环。循环的分类无限循环:程序设计中尽量避免无限循环。(程序中的无限循环必须可控)有限循环:循环限定循环次数或者循环的条件。循环的构成循环体循环条件当型循环的实现while语法:while(循环条件){循环语句;}说......
  • C语言6 DAY
    分支结构分支结构:又被称为选择结构。概念选择结构:根据条件成立与否,选择相应的操作。条件构建关系表达式:含有关系运算符的表达式(>,<,>=,<=,!=,==)逻辑表达式:含有其逻辑运算符的表达式(&&,||,!),往往是用来构建复杂的符合条件,比如:if(year%100==0&&year%4!=0)//既有关系表达式......
  • 代码随想录 day40 打家劫舍 及其变体
    打家劫舍打家劫舍解题思路动态规划解决问题,通过前两个值决定第三个值,需要注意的是初始值的选择,第二个的值是取前两个数中较大的,这样是为了保证跳过不需要取的值知识点动态规划心得初始值的选择没有考虑到,其余的都写出来了打家劫舍二打家劫舍二解题思路前一题的改进,只......
  • Leetcode每日一题 20240729 682.棒球比赛
    题目描述你现在是一场采用特殊赛制棒球比赛的记录员。这场比赛由若干回合组成,过去几回合的得分可能会影响以后几回合的得分。比赛开始时,记录是空白的。你会得到一个记录操作的字符串列表ops,其中ops[i]是你需要记录的第i项操作,ops遵循下述规则:整数x:表示本回合新获......
  • Leetcode每日一题 20240730 2961.双模幂运算
    题目描述给你一个下标从0开始的二维数组variables,其中variables[i]=[ai,bi,ci,mi],以及一个整数target。如果满足以下公式,则下标i是好下标:0<=i<variables.length((aibi%10)ci)%mi==target返回一个由好下标组成的数组,顺序不限。2961.双模幂......