LeetCode经典例题|134. 加油站|运用坐标系数学思维一步解决

134. 加油站

在这里插入图片描述
这道题刚看很容易就想到了暴力或者回溯+剪枝。
这是一个有增有减的过程,就好像坐标系上的一个个点,连在一起形成一条上下起伏的折线。

1. 做坐标轴

比如 gas = [1,2,3,4,5], cost = [3,4,5,1,2]
从0号汽车站开始出发,一直到回到起点,存油量折现。
图1
当它从0号加油站行驶到3号加油站的时候,存油量还剩-6,这个时候是存油量最低的时候。
我们可以再试着从1号加油站、2号加油站出发试试
在这里插入图片描述
从1号加油站出发,也就意味着此时邮箱为空,也就是X坐标轴其实移动1号加油站,然后把之前的0-1号线段,拼凑到最后面。
所以折线自身其实并没有改变,起伏的趋势依然一样,最低点无论坐标轴以什么为0点,都还是最低点。
在这里插入图片描述
这一段必须理解,不然理解不了什么情况下说明存在解。

同时,从2号加油站出发,也是同理
11111

注意一下坐标含义

(3,-2): 从2号加油站出发,到达3号加油站的时候,我的油量只剩下-2了。

2. 从何时开始最优

很明显,从油箱油量最低的那一站A开始,去出发,肯定是最优解。
因为从A往后,油箱里的油量肯定都是要高于那一站的。
换句话说,无论从哪一个加油站开始,到达A时,邮箱油量肯定是最低。
只有从这一站出发,才能保证后续的补给足够。
从坐标轴来看,以最低点为原点,各站点存油量为正数才有可能最多。

3. 什么时候保证是有解的

如果只考虑某个点存油量是不是负数,明显有问题,因为它后续的加油站可以再存。
但是如果我们是以最低点A为原点,最终肯定还是到达A站点时,它的存油量是最少的。
上面已经分析过,曲线的起伏趋势是不会变的,最低点永远都是最低点。
那我们只要保证:
以最低点A为起点,最终再到达A站点时,它的存油量>=0,说明肯定够。
由于解唯一,而A是最优解,说明A就是唯一解。

4. 代码

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        // 做存油坐标系,找到存油量最少的点minIndex,以它为起点。
        int space=0;
        int minSpace=Integer.MAX_VALUE;
        int minIndex=0;
        for(int i=0;i<gas.length;i++){
            // 存油量
            space += gas[i]-cost[i];
            if(minSpace > space){
                minSpace = space;
                minIndex = i;
            }
        }
        // 如果最后存油量<0,说明肯定是不够的
        return space>=0 ? (minIndex+1)%gas.length : -1;
    }
}

为什么最后是返回minIndex+1呢

比如遍历从0开始,gas[i]-cost[i]=-2,那就满足,于是minIndex=0,它已经减去了当前站到下一站的耗油量,实际意义是,从0站出发后,到达一站时存油量最少,为-2。
假设求出2站为最低点,就是从0站一直从2站出发后,到达3站时,存油量最少。
那我们当然是要从3站出发。

总结:思路很值得借鉴,以坐标轴的形式来思考此类问题。但是坐标点含义,以及代码中定义的细节等需要注意。

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

范大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值