面试经典150题0424
Leetcode134 加油站
思路:从头遍历每个加油站,并检查以该加油站为起点,最终能否行驶一周。可以通过减小被检查的加油站数目,来降低总的时间复杂度。
从加油站x
出发,每经过一个加油站就加一次油(包括起始加油站),最后一个可以到达的加油站是y
。这就说明:
第一个式子表明无法到达加油站y
的下一个加油站,第二个式子表明可以到达y
和之前的所有加油站。
现在考虑任意一个位于x,y
之间的加油站z
,现在考虑从该加油站出发能否到达加油站y
的下一个加油站,即判断
∑
i
=
z
y
=
g
a
s
[
i
]
\sum_{i=z}^y = gas[i]
i=z∑y=gas[i]和
∑
i
=
z
y
c
o
s
[
i
]
\sum_{i=z}^ycos[i]
i=z∑ycos[i]之间的关系。
从上面的推导中,能够得出结论:从 x,y
之间的任何一个加油站出发,都无法到达加油站 y
的下一个加油站。
首先检查第0个加油站,并试图判断能否环绕一周;如果不能,就从第一个无法到达的加油站开始继续检查。
public static int canCompleteCircuit(int[] gas, int[] cost){
int len = gas.length;
int i = 0;
while (i < len){
int cnt = 0;
int sumGas = 0, sumCost = 0;
while (cnt < len){
int j = (i + cnt) % len;
sumGas += gas[j];
sumCost += cost[j];
if(sumCost > sumGas){
break;
}
cnt++;
}
if(cnt == len){
return i;
}
// 找到不能到达的下一个加油站
i += cnt + 1;
}
return -1;
}
Leetcode135 分发糖果
假设学生A和学生B左右相邻,A在B左边;
- 从左向右遍历评分数组,当
rating[i] > ratings[i-1]
时,res[i] = res[i-1] + 1
,这样就会满足第i
个学生的糖果比i-1
个学生糖果多(第i
个学生评分高于第i-1
个学生时)。 - 从右向左遍历评分数组,当
rating[i] > rating[i+1] && res[i] <= res[i+1]
时,res[i] = res[i+1] + 1
,这样就会满足第i
个学生的糖果比第i+1
个学生的糖果多(第i
个学生的评分高于第i-1
个学生时)。
public static int candy(int[] ratings){
int[] res = new int[ratings.length];
Arrays.fill(res, 1);
for (int i = 1; i < ratings.length; i++) {
if(ratings[i] > ratings[i-1]){
res[i] = res[i-1] + 1;
}
}
for(int i = ratings.length - 2; i >= 0; i--){
if(ratings[i] > ratings[i+1] && res[i] <= res[i+1]){
res[i] = res[i+1] + 1;
}
}
return Arrays.stream(res).sum();
}