134. 加油站

在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。

package com.leetcode.july;

/**
 * @author jiayoo
 *  2018 / 7 /23
 *  在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

    你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

    如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。

    说明: 

    如果题目有解,该答案即为唯一答案。
    输入数组均为非空数组,且长度相同。
    输入数组中的元素均为非负数。
 *  https://leetcode-cn.com/problems/gas-station/description/
 *  分类 : 贪心算法。
 *  难度: 中等
 *
 */
public class Demo4 {

    public static void main(String[] args) {
        Demo4  d4 = new Demo4();
        int[] g1 = {1,2,3,4,5}; 
        int[] c1 = {3,4,5,1,2};
        int[] g2 = {2,3,4};
        int[] c2 = {3,4,3};
        System.out.println(d4.canCompleteCircuit(g1, c1));
        System.out.println(d4.canCompleteCircuit(g2, c2));
    }



    /**
     * @param gas
     * @param cost
     * 这个算法比下面一个算法复杂度高。
     * 但应该更好理解一点。
     * 
     * @return
     */
    public int canCompleteCircuit(int[] gas, int[] cost) {

        int i, j, len1, k;
        len1 = gas.length;
        int[] arr = new int[len1];
        for (i = 0; i < len1; i++) {
            arr[i] = gas[i] - cost[i];
        }
        int count = 0; // 记录当前已经走过的加油站的数量
        int max = 0; // 记录当前油量
        k = 0; // 这里记录的是偏移量

        /*
         * 第一个for 保证每一个加油站都被计算到
         * 第二个for 用于判断每一加油站 是否 符合题目要求
         * k 用来 计算偏移量  使 第二个for 确实是按 顺序 进行行走的 即实现了循环 
         * 1. max 用来记录 当前油量  如果小于零 显然无法继续前行 换下一个
         * 2. 不小于零的情况  使 计数count ++, 并且 让 偏移量k 加1
         * 3. 跳出第二个for 以后 则 判断 这个加油站是否符合要求   
         * 4. 最后 如果遍历完所有加油站后依旧没找到 则 返回-1
         * */

        for(i = 0; i < len1; i++) {
            k = i;
            for (j = 0; j < len1; j++) {
                if (k >= len1) {
                    max += arr[k-len1];
                }else {
                    max += arr[k];
                }
                if(max < 0) {
                    max = 0;
                    break;
                }
                k++;
                count++;    
            }
            if (count >= len1 ) {

                return i;
            }       
            count = 0;          
        }
        return -1;

    }


      /**
     * @param gas  得到 
     * @param cost 花费
     * 
     * 这个算法显然比上面的那个要好 , 但是一开始并没有想到
     * sum 可以看作是 判断 当前位置是否真的可以走通 小于 0 表示当前位置走不通 
     * total 表示 判断 整个 数组是否走的通  只有 total 大于零 才走的通   这点很重要
     * 用一个for 就行了  很取巧   
     * 1.首先  看最后  total 只有大于等于零  才返回 index, 这样就保证了 index 确实 是存在
     * 2. 在for循环里  通过 sum  判断 当前 位置 一直到结束都没有出错 , 并且 不管 index 位于何处 都能判断
     * 它前面 的 位置 是错误的, 整条路又走的通, 因此 起点位置就是当前位置。  
     * 
     * @return 返回可以走的路径
     */
    public int canCompleteCircuit1(int[] gas, int[] cost) {
            if(gas==null||gas.length==0||cost==null||cost.length==0||gas.length!=cost.length){
                return -1;
            }
            int sum=0;
            int total=0;
            int index=0;

            for(int i=0;i<gas.length;i++){
                sum+=gas[i]-cost[i];
                total+=gas[i]-cost[i];
                if(sum<0){
                    index=i+1;
                    sum=0;
                }
            }
            if(total<0){
                return -1;
            }
            return index;
        }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值