LeetCode面试经典150题—12 加油站

  • 暴力 + 剪枝

    最容易想到的暴力解法就是挨个遍历,假设下标 i 是出发时加油站的编号,变量 sum 存储当前剩余油量,从下标 j = i 开始维护更新 sum 值
     
    sum += (gas[j % len] - cost[j % len]);
    当 sum 小于 0 时,说明从 i 出发不能完成环路行驶,跳出循环从下一个下标开始

    这里有几点剪枝操作:

    1、总油量大于等于总耗油量:即 gas 数组中的总和大于等于 cost 数组中的总和,才可能完成环路行驶,否则直接返回 -1
     
    //sum(int[] nums) 是自定义方法
    if (sum(gas) < sum(cost)) return -1;
    2、若只有一个加油站,需通过 gas 和 cost 中数值的大小比较判断能否完成
     
    //len = gas.length
    if(len < 2) return gas[0] >= cost[0] ? 0 : -1;
    3、出发点的油量大于到下一个点的耗油量
     
    gas[i] > cost[i]
    总代码:
        public static int canCompleteCircuit(int[] gas, int[] cost) {
            int len = gas.length;
            if(len < 2) return gas[0] >= cost[0] ? 0 : -1;
            if (sum(gas) < sum(cost)) return -1;
    
            for (int i = 0; i < len; i++) {
                if (gas[i] > cost[i]){
                    int sum = 0;
                    //从下标 i 开始
                    for (int j = i; j <= i + len; j++) {
                        //注意下标值
                        sum += (gas[j % len] - cost[j % len]);
                        if (sum < 0) break;
                    }
                    if (sum >= 0) return i;
                }
            }
            return -1;
        }
    
        public static int sum(int[] nums) {
            int sum = 0;
            for (int i = 0; i < nums.length; i++) {
                sum += nums[i];
            }
            return sum;
        }
    
  • 填坑思想

    看到一个很有参考价值的想法:

亏空最严重的一个点必须放在最后一步走,等着前面剩余的救助

        这个想法是在找 gas[i] - cost[i] 总和的最低点 minIndex,这个最低点就是亏空最严重的地方,那么将这个点放在最后去经过就是最安全的,即将 minIndex 的下一个点作为出发点

        这里要注意一个判断条件:出发点的油量大于到下一个点的耗油量

        代码如下:

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

  • 5
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值