ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

408算法练习——加油站(数组)

2021-07-26 21:34:42  阅读:176  来源: 互联网

标签:开往 int 汽油 加油站 算法 数组 油箱 408


加油站

问题链接:https://leetcode-cn.com/problems/gas-station/

一、问题描述  

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

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

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

说明: 

如果题目有解,该答案即为唯一答案。
输入数组均为非空数组,且长度相同。
输入数组中的元素均为非负数。


示例 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 可为起始索引。


示例 2:

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

输出: -1

解释:
你不能从 0 号或 1 号加油站出发,因为没有足够的汽油可以让你行驶到下一个加油站。
我们从 2 号加油站出发,可以获得 4 升汽油。 此时油箱有 = 0 + 4 = 4 升汽油
开往 0 号加油站,此时油箱有 4 - 3 + 2 = 3 升汽油
开往 1 号加油站,此时油箱有 3 - 3 + 3 = 3 升汽油
你无法返回 2 号加油站,因为返程需要消耗 4 升汽油,但是你的油箱只有 3 升汽油。
因此,无论怎样,你都不可能绕环路行驶一周。

 

二、问题分析

  最直观的方法就是把所有起点都算一遍。这么做当然可以,但是会增加时间复杂度。如果计算所有起点出发的循环,就很容易发现在多次循环中包含大量重复计算。所以可以把计算结果保存下来,后续如果需要的时候直接取用。可以把这种方法叫做记账法(备忘录法)

  对于该问题,因为每走一步都要计算汽油的消耗和添加,那么就创建一个数组,保存从当前位置出发到达下一位置时油箱里的油量。当然,这里就需要一个假设条件了。假如汽车可以向未来贷油,也就是说,汽车没油也能跑。数组中就可以保存负值,负值的含义就是欠下的油。

  

 

   不难发现,如果debt数组中所有的值相加为负就说明不管从哪里开始走,汽车的油总是不够用的。

  接下来考虑和不为0的情况,因为从表面看上去如果数组和大于等于0,是有可能环游一周,但是如果中间出现连续的负数呢?是否有可能使车停在某个位置加不上油?这需要经过证明才能确定。

  简单证明:假设debt在某个位置值为正,把他记作d_i,如果在d_i后出现连续的负数,使得d_i加上这些负值的结果为负,那么从i位置出发就无法环游一周。如果数组中有多对这样的案例,那么数组加和最终值一定是负值,否则汽车总能找到一个出发点完成环游。这个证明不是严谨的数学证明,但是是一个推理过程。如果代码通过了所有测试,那么很有可能说明该方法可行。

 

三、算法及代码

  

 1 class Solution {
 2     public int canCompleteCircuit(int[] gas, int[] cost) {
 3         int[] debt = new int[gas.length]; 
 4         int count = 0;
 5         for(int i=0;i<gas.length;i++){//构建debt数组并求和
 6             debt[i] = gas[i]-cost[i];
 7             count = count + debt[i];
 8         }
 9         if(count<0){
10             return -1;
11         }
12         /*
13         接下来找起始点,找起始点的想法和上面证明可行性用的类似,
14         如果从一个正数出发在与后面的数字求和的过程中出现负数,那么就说明不能从该位置出发
15          */
16         for(int i=0;i<debt.length;i++){
17             int x = 0;
18             for(int j=i;j<debt.length;j++){//两个for循环实现循环遍历的功能
19                 if(x < 0){
20                     break;
21                 }else{
22                     x = x+debt[j];
23                 }
24             }
25             for(int k=0;k<i;k++){
26                 if(x < 0){
27                     break;
28                 }else{
29                     x = x+debt[k];
30                 }
31             }
32             if(x >= 0){
33                 return i;
34             }
35         }
36         return 0; 
37     }
38 }

测试通过,说明具有可行性

 

标签:开往,int,汽油,加油站,算法,数组,油箱,408
来源: https://www.cnblogs.com/zyq79434/p/15063385.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有