Correct Algorithm for Game of two stacks on HackerRank

I see that there exist a solution and you marked it as correct, but I have a simple solution

  1. add all elements from stack one that satisfy condition <= x
  2. every element you add push it on stack called elements_from_a
  3. set counter to size of stack
  4. try add elements from stack b if sum > x so remove last element you added you can get it from stack elements_from_a
  5. increment bstack counter with each add , decrements from astack with each remove
  6. compare sum of steps with count and adjust count return count

here is code sample for the solution :

def twoStacks(x, a, b):
sumx = 0
asteps = 0
bsteps = 0
elements = []
maxIndex = 0

while len(a) > 0 and sumx + a[0] <= x :
    nextvalue =  a.pop(0)
    sumx+=nextvalue
    asteps+=1
    elements.append(nextvalue)

maxIndex = asteps


while len(b) > 0 and len(elements) > 0:
    sumx += b.pop(0)
    bsteps+=1
    while sumx > x and len(elements) > 0 :
        lastValue = elements.pop()
        asteps-=1
        sumx -= lastValue



    if sumx <= x and bsteps + asteps > maxIndex :
        maxIndex = bsteps + asteps



return maxIndex

I hope this is more simple solution.


solution in python3

# stack implementation
class Stack:
    lis = []

    def __init__(self, l):
        self.lis = l[::-1]

    def push(self, data):
        self.lis.append(data)

    def peek(self):
        return self.lis[-1]

    def pop(self):
        self.lis.pop()

    def is_empty(self):
        return len(self.lis) == 0


# number of test cases
tests = int(input())
for i in range(tests):
    na, nb, x = map(int, input().split(' '))
    a = list(map(int, input().split(' ')))
    b = list(map(int, input().split(' ')))
    temp = []
    stk_a = Stack(a)
    stk_b = Stack(b)
    score = 0
    count = 0
# first taking elements from stack A , till score becomes just less than desired total
    for j in range(len(a)):
        if score + stk_a.peek() <= x:
            score += stk_a.peek()

            count += 1
            temp.append(stk_a.peek())
            # storing the popped elements in temporary stack such that we can again remove them from score
            # when we find better element in stack B
            stk_a.pop()
# this is maximum number of moves using only stack A
    max_now = count
# now iterating through stack B for element lets say k which on adding to total score should be less than desired
    # or else we will remove each element of stack A from score till it becomes just less than desired total.
    for k in range(len(b)):
        score += stk_b.peek()
        stk_b.pop()
        count += 1
        while score > x and count > 0 and len(temp) > 0:
            count = count - 1
            score = score - temp[-1]
            temp.pop()
        # if the score after adding element from stack B is greater than max_now then we have new set of moves which will also lead
        # to just less than desired so we should pick maximum of both
        if score <= x and count > max_now:
            max_now = count
    print(max_now)

This solution works great.... i hope it helps ...

   import java.util.Scanner;

public class Solution {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);

        int g = sc.nextInt();
        for (int tc = 0; tc < g; tc++) {
            int n = sc.nextInt();
            int m = sc.nextInt();
            int x = sc.nextInt();
            int[] a = readArray(sc, n);
            int[] b = readArray(sc, m);

            System.out.println(solve(a, b, x));
        }

        sc.close();
    }

    static int[] readArray(Scanner sc, int size) {
        int[] result = new int[size];
        for (int i = 0; i < result.length; i++) {
            result[i] = sc.nextInt();
        }
        return result;
    }

    static int solve(int[] a, int[] b, int x) {
        int lengthB = 0;
        int sum = 0;
        while (lengthB < b.length && sum + b[lengthB] <= x) {
            sum += b[lengthB];
            lengthB++;
        }

        int maxScore = lengthB;
        for (int lengthA = 1; lengthA <= a.length; lengthA++) {
            sum += a[lengthA - 1];

            while (sum > x && lengthB > 0) {
                lengthB--;
                sum -= b[lengthB];
            }

            if (sum > x) {
                break;
            }

            maxScore = Math.max(maxScore, lengthA + lengthB);
        }
        return maxScore;
    }
}

Ok I will try to explain an algorithm which basically can solve this issue with O(n), you need to try coding it yourself.

I will explain it on the simple example and you can reflect it

1 -> Number of games
10 -> sum should not exceed 10  
4 2 4 6 1  -> Stack A
2 1 8 5 -> Stack B

First you will need to creat 2 arrays, the array will contain the summation of all the number up to its index of the stack, for example for stack A you will have this array

4 6 10 16 17  //index 0 ->4

Same will be done for stack B

2 3 11 16

then for each array start iterating from the end of the array until you reach a number less than or equal to the "sum you should not exceed"

now your current sum is the sum of the point you reached in both arrays, should be 10 +3 = 13 so in order to reach 10 will absolutely need to remove more entries

to remove the additional entries we will be moving the indexes on the array again, to decide which array to move it's index take the entry you are pointing at (10 for array 1 and 3 for array 2) and device it by index+1 (10/3 ~ 3) , (3/2 ~1) then move the index for the highest value and recalculate the sum

Suppose we have:

a = 1 1 1 211 2
b = 1 85

and maxSum = 217 Now, on calculating prefix sums,

a' = 1 2 3 214 216
and b' = 1 86
current sum = 86+216 > 217

so to decide which index to remove, we compare `

216/5~43.2` and `86/2=43`, 

so we move pointer in a'. BUT, that doesn't solve it - `

214+86 is still > 217!!` 

Had we removed 86, it would've been better! So we should always go ahead by removing the one which has larger difference with previous element!

In case both values are equal its logical to move the index on the value which has larger difference with its previous ( remember we are moving the index in reverse order).

the result will be the sum of the indexes +2.