Algorithm for truck moving around a circle of gas stations

前端 未结 11 1368
陌清茗
陌清茗 2020-12-13 07:08

You have a truck moving around a circular track with gas stations spaced out around the circle. Each station has a finite amount of gas. The gas tank on the truck is infinit

相关标签:
11条回答
  • 2020-12-13 07:44

    starting from any station, try to move to the next one (to the right). If you can't (run out of gas), we have to take gas from the left of the starting point (move starting station to the left).

        start = 0
        end = start
        amount = 0
        for i in range(n):
            if amount > 0:
                amount += (gas[end] - cost[end])
                end = (end + 1) % n
            else:
                start = (start - 1 + n) % n
                amount += (gas[start] - cost[start])
    
        if amount >= 0: return start    
        return -1
    

    `

    0 讨论(0)
  • 2020-12-13 07:45

    The solution to this problem is based on a greedy algorithm. It is based on the following two observations.

    1. if the total gas > cost, there must be a start index to finish the circle, else there isn't;

    2. as to an index i, if from i, j is the first index that we cannot reach, then any index from i to j, cannot be the start index.

    For more explanation, have a look at the following link - Gas Station problem.

    0 讨论(0)
  • 2020-12-13 07:45
    static int find(int A[], int B[]) {     
        for (int start = 0; start < A.length; start++) {
            int x = findIndex(A, B, start);
            if (x != -1)
                return x;
        }
        return -1;
    }
    
    static int findIndex(int A[], int B[], int start) {
        int total=0;
        int N = A.length;
        for (int i = start; i < start + A.length; i++) {
            int c = A[i % N] - B[i % N];
            total += c;
            if (total < 0) {
                total = 0;
                return -1;
            }
        }
        return start;
    }
    

    Test cases:

    1. Test case A : { 1, 2, 3, 4, 5 }, B : { 1, 3, 2, 4, 5 } --> index 2
    2. Test case A : {2,2,1}, B : {2,1,2} index --> 0
    3. Test case A : {1,2}, B {2,1} --> index 1
    4. Test case A : {1,2,1}, B {2,1,3} --> index -1
    0 讨论(0)
  • 2020-12-13 07:50

    Let cost be an array of the costs to the next station and gas be an array of how much fuel we can refill

    We calculate the difference between gas[i] and cost[i], called diff, where i is the current gas station we are at.

    If cost[i] > gas[i] (or diff < 0), it means we need to have at least cost[i] - gas[i] fuel when arriving at station i to make it to the next stop, i + 1. If cost[i] <= gas[i] (diff >= 0), it is a valid starting point because we can start without gas, fill up, and head to the next station. At worst, we will reach the next stop with an empty tank. At best, we will have extra fuel left when we reach i+1 (diff > 0)

    We actually don’t have to start from one station, traverse n gas stations successfully to find out whether there is a valid tour! As long as summed fuel >= summed cost, there will be a valid tour. So we just need to do an O(n) pass of the arrays

    More analysis:

    Case1: Tank drops below 0

    This will only happen at a stop where diff < 0. There might be another starting point after that which collects enough excess fuel after traveling one round to pass this station. However, all those stations which we have passed before will not help, so we do not need to consider them (look at case 2 explanation).

    Case 2: Tank currently >=0, but we encounter another valid starting point

    We can safely ignore this because:

    A —— B —— C. If B can reach C, and A can reach B, then A can reach C.

    Case 3: Tank currently >=0, not a valid starting point

    Continue proceeding to the next one

    Case 4: Managed to reach the original starting point!

    Yay!

    def find_starting_station(gas, cost):
        sum_gas = sum_cost = tank = start = 0
    
        for i in range(0, len(gas)):
            sum_gas += gas[i]
            sum_cost += cost[i]
            tank += gas[i] - cost[i]
    
            if tank < 0:
                tank = 0
                start = i+1
    
        if sum_gas < sum_cost: 
            return -1 
    
        return start
    
    0 讨论(0)
  • 2020-12-13 07:50

    We are given with 2 arrays, one for amount of gas available at bunk Bi and one for the amount of gas we spend to reach from i to i+1. We try to start from the first bunker and assume it to be the solution. When even we see that residue gas + available gas at bunker is < amount of gas required we reset the solution to the next index repeat the process till we reach the starting point(our last assumed solution)

    public int getStationIndex() {
        int answer = -1;
        if (gasAvailableArray.length != gasExpenditureArray.length) {
            throw new IllegalArgumentException("Invalid input array provided");
        }
    
        Queue<Integer> queue = new ArrayDeque<>();
        int residue = 0;
        for (int index = 0; ; ) {
            if (index >= gasAvailableArray.length) {
                index = index % (gasAvailableArray.length - 1);
            }
            if (index == answer) {
                return answer;
            }
            if (residue + gasAvailableArray[index] - gasExpenditureArray[index] >= 0) {
       // Only set a new answer when we had a reset in last iteration
                if (answer == -1) {
                    answer = index;               
                }
                residue += gasAvailableArray[index] - gasExpenditureArray[index];
                queue.add(index);
            } else {
                while (!queue.isEmpty()) {
                    queue.poll();
                }
    
            }
            answer = -1;
            index++;
        }
    }
    
    0 讨论(0)
  • 2020-12-13 07:55
    static int findIndex(int A[], int B[]) {
        int N = A.length;
        int start=0;
        boolean isBreak=false;
        int total = 0;
        do {
            for(int i=start;i<start+A.length;i++) {         
                int c = A[i%N] - B[i%N];
                total +=c;          
                if(total < 0) {
                    total= 0;
                    isBreak=true;
                    break;
                }                   
            }
            if(isBreak) {
                start++;
                isBreak=false;
            } else {
                return start;
            }
        } while(start < A.length);
        return -1;
    }
    
    0 讨论(0)
提交回复
热议问题