1.加油站
在一条环路上有 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升汽油。
因此,无论怎样,你都不可能绕环路行驶一周。
解法:
我们首先要知道能走完整个环的前提是gas的总量要大于cost的总量,这样才会有起点的存在。假设开始设置起点start = 0, 并从这里出发,如果当前的gas值大于cost值,就可以继续前进,此时到下一个站点,剩余的gas加上当前的gas再减去cost,看是否大于0,若大于0,则继续前进。当到达某一站点时,若这个值小于0了,则说明从起点到这个点中间的任何一个点都不能作为起点,则把起点设为下一个点,继续遍历。当遍历完整个环时,当前保存的起点即为所求。
public int canCompleteCircuit(int[] gas, int[] cost) {
int sum=0;
int total=0;
int start=0;
for(int i=0;i<gas.length;i++){
total+=gas[i]-cost[i];
sum+=gas[i]-cost[i];
if(sum<0){
start=i+1;
sum=0;
}
}
return total>=0 ? start:-1;
}
2.跳跃游戏
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
示例 1:
输入: [2,3,1,1,4]
输出: true
解释: 从位置 0 到 1 跳 1 步, 然后跳 3 步到达最后一个位置。
示例 2:
输入: [3,2,1,0,4]
输出: false
解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。
解法一:
public class Solution {
public boolean canJump(int[] A) {
if(A.length<=1) return true;
//从当前位置可达终点的最小距离
int n=1;
for(int i=A.length-2;i>=1;i--){
if(A[i]>=n){
n=1;
}else{
n++;
}
}
if(A[0]>=n){
return true;
}else{
return false;
}
}
}
解法二:
public boolean canJump(int[] A) {
//从起点能到达的最远位置
int maxReach=0;
for(int i=0;i<A.length && i<=maxReach;i++){
maxReach=Math.max(maxReach,i+A[i]);
}
if(maxReach>=A.length-1){
return true;
}else{
return false;
}
}
3.连续子数组的最大和
给定一个整数数组,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
解法:
从头开始累加元素,当tempSum的值为正时,为后面带来正收益,继续加上下一个元素;为负时为后面带来负收益,应舍弃。maxSum记录tempSum最大值。
public class Solution {
public int maxSubArray(int[] A) {
int maxSum=A[0];
int tempSum=0;
for(int i=0;i<A.length;i++){
if(tempSum<0){
tempSum=0;
}
tempSum+=A[i];
maxSum=Math.max(tempSum,maxSum);
}
return maxSum;
}
}