[LeetCode] 134.加油站

加油站

描述

在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。
你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。
如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。

样例

输入: 
gas  = [1,2,3,4,5]
cost = [3,4,5,1,2]

输出: 3

解释:3 号加油站(索引为 3)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。

原题链接

思路

暴力搜索,以每一个加油站为起点,检查从该加油站出发,是否可以完成一圈。

gas_count:走到第K个站点,剩余油量
如果gas_count<0,说明无法到达下一个站点
在这里插入图片描述

因为可能走了已经超过一圈,需要确定当前在第几个站点。可以通过 (出发站点+走过的站点个数)除以 站点总个数 得到的余数确定当前所处的站点位置。
即:k=(i+j)%n

实现

public class Main {
    //遍历每个加油站,检查以该加油站为起点,是否能走过一圈
    public static int canCompleteCircuit(int[] gas, int[] cost) {
        int n=gas.length;
        //遍历每个加油站
        for (int i = 0,j=0; i < n; i++) {
            int count=0;
            //j 记录走过的站点个数,n个是一圈
            for (j = 0; j < n; j++) {
                //确定第几站
                //出发点+走过的站点个数 除以总数,余数就是当前站点位置
                int k=(i+j)%n;
                //剩余油量
                count+=gas[k]-cost[k];
                if (count<0){
                    break;
                }
            }
            //如果已经走了一圈了说明i点符合条件
            if (j>=n){
                return i;
            }
        }
        return -1;
    }
  }

优化
当以第 i 个加油站为出发点时,经过了 j 个站点后到达K站点,在前往下一个站点时失败了,那么在 i 到达K站点时,途径的所有站点,以其中任意一个站点为起点,都会在K站点失败。

因此,跳过这些会失败的站点,避免重复走,从 第i+j+1的站点处重新出发,检查之后的站点是否可以完成一圈。

public class T134_1 {
    public static int canCompleteCircuit(int[] gas, int[] cost) {
        int n=gas.length;
        //优化:当以 i 为出发点时,经过了 j 站点,在 k 站点处失败了,
        //那么途径的任一个站点为起点到该点同样会失败,
        //因此直接跳过这些失败的站点,从 i+j+1 处重新开始

        //以i站点为起点
        for (int i = 0,j=0; i < n; i+=j+1) {
            int count=0;
            //j 记录走过的站点个数,n个是一圈
            for (j = 0; j < n; j++) {
                //确定第几站,加油站是环形的
                //出发点+走过的站点个数 除以总数,余数就是当前站点位置
                int k=(i+j)%n;
                //剩余油量
                count+=gas[k]-cost[k];
                if (count<0){
                    break;
                }
            }
            //如果已经走了一圈了说明i点符合条件
            if (j>=n){
                return i;
            }
        }
        return -1;
    }
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值