gas-station

题目

题目连接
gas-station_第1张图片
题目大意:在一个环形的路径中,给一个数组是加气站给加的气,另一个数组是从一个加气站到另一个的消耗,问是否能够存在从一个加气站开始开空气的车并返回原点?

思路

首先数据预处理,将gas和cost做差为diff。
最优的策略肯定是在环形数组中的diff的最大连续序列的开始处开始,找到这个index
然后从index看是否能够走回原点

循环数组的最大连续序列和

最大连续序列分为两种情况,一种是不成环也就是不先经过最后一个节点在经过第一个节点。另一种是成环的最大连续序列和,既求出最小连续序列,下一个位置即使最大,,,。那么求出这两种情况的最大和就是循环数组的最大连续序列的和。
index为不成环的最大连续序列的开始或者为最小连续序列的下一个位置

不成环的最大连续序列和

用dp[i]表示以i结尾的最大连续序列的和,prev表示以i结尾的最大连续序列的和的开始下标。
如果dp[i-1]>=0 dp[i] = dp[i-1]+diff[i] prev[i] = prev[i-1]
否则 dp[i] = diff[i] prev[i] = i;

如果求最小连续序列和的话
if dp[i-1]>=0 dp[i] = diff[i] prev[i] = i;
否则 p[i-1]>=0 dp[i] = dp[i-1]+diff[i] prev[i] = prev[i-1]
最后找到最大的或者最小的

public class Solution {
    //最大序列开始节点
    int max = Integer.MIN_VALUE,index1;
    //最小序列下一个节点
    int min = Integer.MAX_VALUE ,index2;
    public int canCompleteCircuit(int[] gas, int[] cost) {
        //求得每一点开始能够剩余的gas
        int[] surplus = new int[gas.length];
        int sum = 0;
        for(int i=0;i<gas.length;i++){
            surplus[i] = gas[i] - cost[i];
            sum += surplus[i];
        }
        //开始节点是最大序列的开始节点
        getMaxSubSquence(surplus);
        //求出在非循环数组的最大序列
        getMinSubSquence(surplus);
        //拿出最大的 然后的到开始节点
        int max2 = sum - min;
        int indexOfStart = max>max2?index1:index2;

        int j = indexOfStart;



        //从开始节点循环遍历一遍 如果能到自己则返回该节点否则返回-1
        int count = 0;
        for(int i=0;i<surplus.length;i++){
            count += surplus[j];
            if(count<0){
                return -1;
            }
            if(j!=surplus.length-1){
                j++;
            }else{
                j = 0;
            }
        }
        return indexOfStart;
    }
    public void getMinSubSquence(int[] surplus){
        if(surplus==null ||surplus.length==0){
            return ;
        }
        //以i结尾的最小连续子序列的和
        int[] dp = new int[surplus.length];
        //表示以i结尾最小连续子序列的开始index
        dp[0] = surplus[0];

        for(int i=1;i<surplus.length;i++){
            if(dp[i-1]<=0){

                dp[i]  = dp[i-1] + surplus[i];
            }else{

                dp[i] = surplus[i];
            }
        }
        for(int i=0;i<dp.length;i++){
            if(dp[i]<min){
                min = dp[i];
                if(i!=dp.length-1){
                    index2 = i+1;
                }else{
                    index2 = 0;
                }
            }
        }

    }
    public void getMaxSubSquence(int[] surplus){
        if(surplus==null ||surplus.length==0){
            return ;
        }
        //以i结尾的最大连续子序列的和
        int[] dp = new int[surplus.length];
        //表示以i结尾最大连续子序列的开始index
        int[] prev = new int [surplus.length];
        dp[0] = surplus[0];
        prev[0] = 0;
        for(int i=1;i<surplus.length;i++){
            if(dp[i-1]>=0){
                prev[i] = prev[i-1];
                dp[i]  = dp[i-1] + surplus[i];
            }else{
                prev[i] = i;
                dp[i] = surplus[i];
            }
        }
        //搜索一遍 找到最大的那个值
        for(int i=0;i<dp.length;i++){
            if(dp[i]>max){
                max = dp[i];
                index1 = prev[i];
            }
        }
    }
}
添加笔记

你可能感兴趣的:(数据)