Правильный алгоритм игры двух стеков на HackerRank

Я просто попытался проблему на основе стека на HackerRank

https://www.hackerrank.com/challenges/game-of-two-stacks

Alexa имеет два стека неотрицательных целых чисел, стек A и стек B, где индекс 0 обозначает верхнюю часть стека. Alexa бросает вызов Нику, чтобы играть в следующую игру:

в каждом движении Ник может удалить одно целое число из верхней части стека A или B стека.

Ник сохраняет текущую сумму чисел он достает из двух стопок.

Ник дисквалифицируется из игры, если в любой момент его текущая сумма становится больше некоторого целого числа X, заданного в начале игры.

окончательный счет Ника-это общее количество целых чисел, которые он удалил из двух стеков.

найти максимально возможный счет Ник может достичь (т. е. максимальное количество целых чисел, которые он может удалить без дисквалификации) во время каждой игры и распечатать его на новом линия.

для каждой из игр выведите целое число в новой строке, обозначающее максимально возможный результат, которого Ник может достичь без дисквалификации.

Sample Input 0

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

Sample Output 

4

ниже мой код я попробовал жадный подход, взяв минимальный элемент из верхней части стека и добавив его к сумме. Он отлично работает для некоторых тестовых случаев, но не работает для остальных, как для приведенного ниже ввода

1
67
19 9 8 13 1 7 18 0 19 19 10 5 15 19 0 0 16 12 5 10 - Stack A
11 17 1 18 14 12 9 18 14 3 4 13 4 12 6 5 12 16 5 11 16 8 16 3 7 8 3 3 0 1 13 4 10 7 14 - Stack B

мой код дает 5 но правильное решение-это 6 в элементы выскочили в серии являются 19,9,8,11,17,1 Первые три элемента из стека A & затем из стека B.

**

Я не понимаю алгоритм, он выглядит как DP для меня может кто угодно помогите мне с подходом / алгоритмом?

**

public class Default {

    public static void main(String[] args) throws IOException {

        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

        int numOfGames = Integer.parseInt(br.readLine());
        for (int i = 0; i < numOfGames; i++) {
            String[] tmp = br.readLine().split(" ");
            int numOfElementsStackOne = Integer.parseInt(tmp[0]);
            int numOfElementsStackTwo = Integer.parseInt(tmp[1]);
            int limit = Integer.parseInt(tmp[2]);
            int sum = 0;
            int popCount = 0;

            Stack<Integer> stackOne = new Stack<Integer>();
            Stack<Integer> stackTwo = new Stack<Integer>();

            String[] stOne = br.readLine().split(" ");
            String[] stTwo = br.readLine().split(" ");

            for (int k = numOfElementsStackOne - 1; k >= 0; k--) {
                stackOne.push(Integer.parseInt(stOne[k]));
            }

            for (int j = numOfElementsStackTwo - 1; j >= 0; j--) {
                stackTwo.push(Integer.parseInt(stTwo[j]));
            }

            while (sum <= limit) {
                int pk1 = 0;
                int pk2 = 0;
                if (stackOne.isEmpty()) {
                    sum = sum + stackTwo.pop();
                    popCount++;
                } else if (stackTwo.isEmpty()) {
                    sum = sum + stackOne.pop();
                    popCount++;
                } 
                else if (!stackOne.isEmpty() && !stackTwo.isEmpty()) {
                    pk1 = stackOne.peek();
                    pk2 = stackTwo.peek();

                    if (pk1 <= pk2) {
                        sum = sum + stackOne.pop();
                        popCount++;
                    } else {
                        sum = sum + stackTwo.pop();
                        popCount++;
                    }
                } else if(stackOne.isEmpty() && stackTwo.isEmpty()){
                    break;
                }
            }

            int score = (popCount>0)?(popCount-1):0;
            System.out.println(score);
        }
    }
}

3 ответов


Ok Я попытаюсь объяснить алгоритм, который в основном может решить эту проблему с O (n), вам нужно попробовать кодировать его самостоятельно.

я объясню это на простом примере, и вы можете отразить его

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

сначала вам нужно будет создать 2 массива, массив будет содержать суммирование всего числа до его индекса стека, например, для стека A у вас будет этот массив

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

то же самое будет сделано для стека Б

2 3 11 16

затем для каждого массива начните итерацию с конца массива, пока не достигнете числа, меньшего или равного "сумме, которую вы не должны превышать"

Теперь ваша текущая сумма-это сумма точки, которую вы достигли в обоих массивах, должна быть 10 +3 = 13, поэтому для достижения 10 абсолютно необходимо удалить больше записей

чтобы удалить дополнительные записи, мы будем снова перемещать индексы в массиве, чтобы решить, какой массив для перемещения его индекса запись, на которую вы указываете (10 для массива 1 и 3 для массива 2), и устройство по индексу+1 (10/3 ~ 3) , (3/2 ~1) затем переместите индекс на наибольшее значение и пересчитайте сумму

если оба значения равны, логично переместить индекс на значение, которое имеет большую разницу с предыдущим (помните, что мы перемещаем индекс в обратном порядке).

результатом будет сумма индексов +2.


решение в 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)

Это решение работает отлично.... надеюсь, это поможет ...

   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;
    }
}