文章目录
- 写在前面
- Tag
- 题目来源
- 题目解读
- 解题方法
- 方法一:暴力枚举
- 方法二:一次遍历
- 写在最后
写在前面
本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更……
专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删:
- Tag:介绍本题牵涉到的知识点、数据结构;
- 题目来源:贴上题目的链接,方便大家查找题目并完成练习;
- 题目解读:复述题目(确保自己真的理解题目意思),并强调一些题目重点信息;
- 解题思路:介绍一些解题思路,每种解题思路包括思路讲解、实现代码以及复杂度分析;
- 知识回忆:针对今天介绍的题目中的重点内容、数据结构进行回顾总结。
Tag
【一次遍历】【数组】
题目来源
面试经典150 | 134. 加油站
题目解读
在一个环形的路上有有限个加油站,在每个加油站可以获得相对应油,从一个油站前往下一个加油站需要消耗一些油。你可以从环形路上的任何一个加油站出发,向下一加油站方向进发,如果你能从某个加油站出发最后环绕一圈又回到了开始出发的加油站,请返回加油站的编号(从 0
开始),否则返回 -1
。
如果存在解,则保证它是唯一的。
解题方法
方法一:暴力枚举
我们遍历加油站,以每一个加油站作为起始出发,判断从哪一个起点出发可以环绕一圈。如果从某一个起点出发,可以顺利的跑完一圈,中途不会出现前往下一个加油站油不够的情况,那么这个起点就是唯一的答案。
容易想到的方法要么是实现起来较难,要么是时间复杂度太高,少有那种最容易想起来的方法就是最优的解法。暴力解法的时间复杂度为 O ( n 2 ) O(n^2) O(n2), n n n 为加油站的数量,本题的数据规模达到 1 0 5 10^5 105, O ( n 2 ) O(n^2) O(n2) 的时间复杂度一定超时。
方法二:一次遍历
记 rest = gas[i] - cost[i]
表示从 i
到达下一个加油站后剩余的油量(包括加油和消耗)。
特判情况:如果走完一圈剩下的油量小于 0
,说明无论从哪个起点出发都不可能走完一圈,此时返回 -1
。
接下里对到达的加油站进行一次遍历,使用变量 start
记录出发位置,变量 currSum
表示从 0
到当前的 i
的剩余油量的累加和。如果 currSum < 0
,表明在区间 [0, i]
内都不能作为出发的起点(因为在这个区间内选择任何一个起点,到加油站 i
都会断油),这时候出发的位置只能从 i+1
算起,我们还要更新 currSum = 0
,开始新的累加。
最后,直接返回 start
即为唯一的出发起点。
特判情况,我们不需要独立计算走完一圈剩余的油量 totalSum
,我们可以在一次遍历中进行计算。
实现代码
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int currSum = 0;
int totalSum = 0; //记录走完一圈剩余的油量
int start = 0;
for (int i = 0; i < gas.size(); ++i) {
int rest = gas[i] - cost[i];
currSum += rest;
totalSum += rest;
if (currSum < 0) {
start = i + 1;
currSum = 0;
}
}
// 走完一圈剩余的油量 < 0
if (totalSum < 0) return -1;
return start;
}
};
复杂度分析
时间复杂度: O ( n ) O(n) O(n), n n n 为加油站的数量。
空间复杂度: O ( 1 ) O(1) O(1)。
写在最后
如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。
如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。
最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 👍 哦。