238. 除了自身以外数组的乘积
中等
解题思路:左右乘积
java
class Solution {
public int[] productExceptSelf(int[] nums) {
// 维护从左起的乘积,第一个元素为1
// 维护从右起的乘积,从右起第一个元素为1
int n = nums.length;
int[] leftMul = new int[n];
int[] rightMul = new int[n];
// 从左到右
leftMul[0] = 1;
for (int i = 1; i < n; i++) {
leftMul[i] = leftMul[i-1] * nums[i-1];
}
// 从右到左
rightMul[n-1] = 1;
for (int i = n - 2; i >= 0; i--) {
rightMul[i] = rightMul[i+1] * nums[i+1];
}
// 计算结果
int[] res = new int[n];
for (int i = 0; i < n; i++) {
res[i] = leftMul[i] * rightMul[i];
}
return res;
}
}
时间复杂度O(N),空间复杂度O(N),
和接雨水这道题类似,
空间复杂度为O(N),实际上分别用数组存储左右乘积,可以省略,直接使用ans存储
java
class Solution {
public int[] productExceptSelf(int[] nums) {
// 维护从左起的乘积,第一个元素为1
// 维护从右起的乘积,从右起第一个元素为1
int n = nums.length;
int[] res = new int[n];
// 从左到右
res[0] = 1;
for (int i = 1; i < n; i++) {
res[i] = res[i-1] * nums[i-1];
}
// 从右到左
int R = 1;
for (int i = n - 1; i >= 0; i--) {
res[i] = res[i] * R;
R *= nums[i];
}
// 计算结果
return res;
}
}
134. 加油站
中等
解题思路:
超时
我能想到,从每个加油站出发,尝试能不能走一圈后回来,
例如从当前i出发,则当前到达下一个位置剩余油量为cur = gasi - costi,如果cur < 0,说明从当前i出发不能绕一圈。
跳过当前下一个位置是(i + 1) % n,如何说明走了一圈了,可以统计一下步骤
java
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
if(n == 1) return gas[0] >= cost[0] ? 0 : -1;
// 枚举出发位置
for (int start = 0; start < n; start++) {
int i = start;
int cur = 0;
int step = 0;
while (step < n) {
// 计算从i到i+1,剩下的油量
cur += gas[i] - cost[i];
if (cur < 0) {
break;
}
i = (i + 1) % n;
step++;
}
if (step == n) {
return start;
}
}
return -1;
}
}
break,是终止当前的while循环。
上述方法是暴力枚举超时的,
如何从O(N^2)优化到O(N),可以用贪心,
如果从起点A无法到达B,那么从A到B之间的任何一个点出发,也绝对无法到达B,因此可以直接把起点更新为B的下一个位置。
因此由于要走一个循环,所以总的油量大于等于总消耗即可,就一定有解,反之没有,
java
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
// 记录总油量
int totalSum = 0;
// 记录当前起点出发,到当前位置的累计油量差值
int curSum = 0;
int start = 0;
for (int i = 0; i < n; i++) {
// 计算差值
int diff = gas[i] - cost[i];
totalSum += diff;
curSum += diff;
// 局部剪枝
// 如果从当前位置出发,油量变为负
// 说明start,i之间任意一个位置出发都不能完成
// 直接从下一个位置出发
if (curSum < 0) {
start = i + 1;
curSum = 0;
}
}
return totalSum >= 0 ? start : -1;
}
}