如题
先来暴力解决方法,找到存油量大于消耗量的每一个站,然后进行测试,
public static int canCompleteCircuit(int[] gas, int[] cost) {
int rest = 0; //剩余油量
int flag = 0; //标志, 为 1代表当前余量大于等于0
for(int i =0;i<gas.length;i++){
if(gas[i]>=cost[i]) { //遍历判断起点
rest=gas[i]-cost[i];
flag=1;
for(int l =1;l<gas.length;l++) { //后续遍历
if(l+i<gas.length) { //对应正向遍历未到尾部
rest=rest+gas[l+i]-cost[l+i];
}else { //对应到达尾部后遍历头部
rest = rest+gas[l+i-gas.length]-cost[l+i-gas.length];
}
if(rest<0){ //出现余量不足情况 需切换起点
flag=0;
break;
}
flag=1;
}
}
if(flag==1){ //当次遍历全程余量不为负 返回起点index
return i;
}
}
return -1;
}
很显然可以实现当前目标,但是循环及判断过多,运行时间过长。是否存在优化可能。
先从此方法出发,观察发现有过多冗余运算,其最终结果仅仅与对应index上的差值有关,从此处着手优化。
public static int canCompleteCircuit1(int[] gas, int[] cost) {
int[]diff = new int[gas.length];
for(int i=0;i<gas.length;i++) {
diff[i]=gas[i]-cost[i];
}
int rest = 0; //剩余油量
int flag = 0; //标志, 为 1代表当前余量大于等于0
for(int i =0;i<diff.length;i++){
if(diff[i]>0) { //遍历判断起点
rest=diff[i];
flag=1;
for(int l =1;l<diff.length;l++) { //后续遍历
if(l+i<diff.length) { //对应正向遍历未到尾部
rest=rest+diff[l+i];
}else { //对应到达尾部后遍历头部
rest = rest+diff[l+i-diff.length];
}
if(rest<0){ //出现余量不足情况 需切换起点
flag=0;
break;
}
flag=1;
}
}
if(flag==1){ //当次遍历全程余量不为负 返回起点index
return i;
}
}
return -1;
}
接着优化。
从题设分析出发,确认若存在题解则唯一。首先确认一点,存在可行解的前提是gas总和大于cost总和。第二点假设index处为唯一解,则可以确认index之前的cost总和减去gas总和达到最大值,
public static int canCompleteCircuit2(int[] gas, int[] cost) {
int sum = 0; //总体差值,判断是否存在可行解
int maxdiff = 0; //gas和值减去cost和值最小处
int maxindex = -1; //最小处的index,取-1应对最优解为0情况
for(int i =0;i<gas.length;i++) {
int diff = gas[i]-cost[i]; //对应index的差值
sum=sum+diff;
if(sum<maxdiff) {
maxdiff=sum;
maxindex = i;
}
}
if(sum>=0) { //当length大于1时 ,出发点为最大值后一位
return maxindex+1;
}
return -1;
}
测试通过