【LeetCode-面试算法经典-Java实现】【134-Gas Station(加油站问题)】
来源:互联网 发布:tensorflow 数据结构 编辑:程序博客网 时间:2024/06/05 09:26
【134-Gas Station(加油站问题】
【LeetCode-面试算法经典-Java实现】【所有题目目录索引】
原题
There are N gas stations along a circular route, where the amount of gas at station i is gas[i].
You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.
Return the starting gas station’s index if you can travel around the circuit once, otherwise return -1.
Note:
The solution is guaranteed to be unique.
题目大意
沿环形路线有N个加油站,其中气体在车站i是量是gas[i]。你有车有无限容量的气罐,从加油站i到下一个加油站站点i+1,要消耗cost[i]的气体。你开始旅程时,气罐是空的。回到起始加油站的指数,选择一个起点开始旅游,如果你能在周围环形旅行一次,就返回开始的加油站索引,否则返回-1。
注意: 答案保证是唯一的。
解题思路
假设从站点 i 出发,到达站点 k 之前,依然能保证油箱里油没见底儿,从k 出发后,见底儿了。那么就说明 diff[i] + diff[i+1] + … + diff[k] < 0,而除掉diff[k]以外,从diff[i]开始的累加都是 >= 0的。也就是说diff[i] 也是 >= 0的,这个时候我们还有必要从站点 i + 1尝试吗?仔细一想就知道:车要是从站点 i+1出发,到达站点k后,甚至还没到站点k,油箱就见底儿了,因为少加了站点 i 的油。。。
因此,当我们发现到达k 站点邮箱见底儿后,i 到 k 这些站点都不用作为出发点来试验了,肯定不满足条件,只需要从k+1站点尝试即可!因此解法时间复杂度从O(n2)降到了 O(2n)。之所以是O(2n),是因为将k+1站作为始发站,车得绕圈开回k,来验证k+1是否满足。
等等,真的需要这样吗?
我们模拟一下过程:
a. 最开始,站点0是始发站,假设车开出站点p后,油箱空了,假设sum1 = diff[0] +diff[1] + … + diff[p],可知sum1 < 0;
b. 根据上面的论述,我们将p+1作为始发站,开出q站后,油箱又空了, 设sum2 = diff[p+1] +diff[p+2] + … + diff[q],可知sum2 < 0。
c. 将q+1作为始发站,假设一直开到了未循环的最末站,油箱没见底儿,设sum3 = diff[q+1] +diff[q+2] + … + diff[size-1],可知sum3 >= 0。
要想知道车能否开回 q 站,其实就是在sum3 的基础上,依次加上 diff[0] 到 diff[q],看看sum3在这个过程中是否会小于0。但是我们之前已经知道 diff[0] 到 diff[p-1] 这段路,油箱能一直保持非负,因此我们只要算算sum3 + sum1是否 <0,就知道能不能开到 p+1站了。
如果能从p+1站开出,只要算算sum3 + sum1 + sum2 是否 < 0,就知都能不能开回q站了。
因为 sum1, sum2 都 < 0,因此如果 sum3 + sum1 + sum2 >=0 那么sum3 + sum1 必然 >= 0,也就是说,只要sum3 + sum1 + sum2 >=0,车必然能开回q站。而sum3 + sum1 + sum2 其实就是 diff数组的总和 Total,遍历完所有元素已经算出来了。
因此 Total 能否 >= 0,就是是否存在这样的站点的 充分必要条件。
这样时间复杂度进一步从O(2n)降到了 O(n)。
代码实现
算法实现类
public class Solution { public int canCompleteCircuit(int[] gas, int[] cost) { // 参数检验 if (gas == null || cost == null || gas.length == 0 || gas.length != cost.length) { return -1; } // 记录访问的起始点 int start = 0; // 加的气和消耗的气的总差值 int total = 0; // 从start位置开始,加的气和消耗的气的总差值 int sum = 0; for (int i = 0; i < gas.length; i++) { total += (gas[i] - cost[i]); // 如是油箱没有油了 if (sum < 0) { // 重新设置油箱中的油 sum = gas[i] - cost[i]; // 记录新的起点位置 start = i; } else { // 油箱中还有油,更新油箱中的油数 sum += (gas[i] - cost[i]); } } return total >= 0 ? start : -1; } // 下面的方法会超时O(N^2)时间复杂度 public int canCompleteCircuit2(int[] gas, int[] cost) { // 参数检验 if (gas == null || cost == null || gas.length == 0 || gas.length != cost.length) { return -1; } // 剩下的气体,开始时为0 int leftGas = 0; // 开始出发的站点 int start = 0; // 结束的站点 int end = 1; // 未走一周 while (start < gas.length) { // 到达下一个站后的气体简便量 leftGas = gas[start] - cost[start]; // 可以走到下一个站 if (leftGas > 0) { // 记录下一个站 end = (start + 1) % gas.length; // 如果一直可以到下一个站就持续进行操作 while (start != end && (leftGas += (gas[end] - cost[end])) >= 0) { end = (end + 1) % gas.length; } // 说明已经遍历了一周 if (start == end) { return start; } } start++; } return -1; }}
评测结果
点击图片,鼠标不释放,拖动一段位置,释放后在新的窗口中查看完整图片。
特别说明
欢迎转载,转载请注明出处【http://blog.csdn.net/derrantcm/article/details/47678215】
- 【LeetCode-面试算法经典-Java实现】【134-Gas Station(加油站问题)】
- Gas Station 加油站问题 @LeetCode
- 【LeetCode】加油站问题 gas station
- LeetCode-Gas Station(加油站问题)
- LeetCode | Gas Station(加油站)
- leetcode 134. Gas Station 加油站问题
- LeetCode OJ 之 Gas Station (加油站)
- LeetCode 134. Gas Station(加油站)
- Gas Station 加油站问题【oj】
- Gas Station (环形加油站)
- 134. Gas Station(加油站)
- [leetcode-134]Gas Station(java)
- LeetCode之Gas Station --环形加油站周游
- [leetcode] 134 Gas Station(经典dp || 贪心)
- Leetcode 134(Gas Station)
- LeetCode(134) Gas Station
- LeetCode-134. Gas Station(JAVA)加气站问题
- [Leetcode] Gas Station (Java)
- 数据结构--队列
- [latex] 格式控制
- LeetCode 题解(171): Jump Game
- 【LeetCode-面试算法经典-Java实现】【129-Sum Root to Leaf Numbers(所有根到叶子结点组组成的数字相加)】
- 【LeetCode-面试算法经典-Java实现】【130-Surrounded Regions(环绕区域)】
- 【LeetCode-面试算法经典-Java实现】【134-Gas Station(加油站问题)】
- Hibernate 通用操作类 BaseHibernateDao
- C语言的指针
- 在MFC中添加多个音乐
- 集合的遍历
- Node.js开发入门—使用AngularJS内置服务
- 在Android上使用Google V8 JS 引擎
- C++内存管理详解
- 开发相关琐碎记录