Hacker Rank游戏:双堆栈递归解法

huangapple go评论87阅读模式
英文:

Hacker Rank Game of Two stacks recursive solution

问题

我在 HackerRank 上解决了“两个堆栈游戏”问题,但卡住了。问题是我的解决方案在其他测试案例中不起作用。

Alexa 有两个非负整数堆栈,堆栈 A 和堆栈 B,索引 0 表示堆栈顶部。Alexa 向尼克发出挑战,玩以下游戏:

在每一步中,尼克可以从堆栈 A 或堆栈 B 的顶部移除一个整数。

尼克将从两个堆栈中移除的整数保持累加和。

如果在任何时候尼克的累加和大于游戏开始时给定的整数 X,则尼克被取消游戏资格。

尼克的最终得分是他从两个堆栈中移除的整数总数。

找到尼克在每场游戏中可以实现的最大可能得分(即最多可以移除的整数数量),并在新的一行上打印出来。

对于每场游戏,打印一个整数,表示尼克可以在不被取消资格的情况下达到的最大可能得分。

示例输入

    1 -> 游戏数量
    10 -> 和不应超过 10
    4 2 4 6 1  -> 堆栈 A
    2 1 8 5 -> 堆栈 B

示例输出为

    4

我的代码如下:

    static int twoStacks(int x, int[] a, int[] b) {
            Stack<Integer> s1 = new Stack<Integer>();
            Stack<Integer> s2 = new Stack<Integer>();
    
            for(int i=a.length-1; i>=0; i--)
                s1.push(a[i]);
    
            for(int i=b.length-1; i>=0; i--)
                s2.push(b[i]);    
    
            return moves(x, s1, s2, 0);
        }
        static int moves(int x, Stack<Integer> a, Stack<Integer> b, int moves){
            
            if(x == 0 ) return moves-1;
            if(x < 0 ) return moves-1;
    
            int moves1 = a.isEmpty() ? moves : moves(x-a.pop(), a, b, moves+1);
            int moves2 = b.isEmpty() ? moves : moves(x-b.pop(), a, b, moves+1);
    
            return Math.max(moves1, moves2);
    
        }

请问您能否帮助我找出问题所在,并找出正确的递归方法?很多人已经通过循环方法解决了这个问题,但我想用递归来解决。方法很简单,我们首先要遍历堆栈一,直到达到所需的和,然后开始处理堆栈二。每当和大于所需和时,我们从堆栈 1 中删除最后一个数字。
英文:

I was solving problem for game of two stacks on Hackers rank and got stuck. Problem is my solution is not working for other test cases.

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

Alexa has two stacks of non-negative integers, stack A and stack B where index 0 denotes the top of the stack. Alexa challenges Nick to play the following game:

In each move, Nick can remove one integer from the top of either stack A or B stack.

Nick keeps a running sum of the integers he removes from the two stacks.

Nick is disqualified from the game if, at any point, his running sum becomes greater than some integer X given at the beginning of the game.

Nick's final score is the total number of integers he has removed from the two stacks.

find the maximum possible score Nick can achieve (i.e., the maximum number of integers he can remove without being disqualified) during each game and print it on a new line.

For each of the games, print an integer on a new line denoting the maximum possible score Nick can achieve without being disqualified.

Sample input

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

Sample output is

4

My code is :

static int twoStacks(int x, int[] a, int[] b) {
        Stack&lt;Integer&gt; s1 = new Stack&lt;Integer&gt;();
        Stack&lt;Integer&gt; s2 = new Stack&lt;Integer&gt;();

        for(int i=a.length-1; i&gt;=0; i--)
            s1.push(a[i]);

        for(int i=b.length-1; i&gt;=0; i--)
            s2.push(b[i]);    

        return moves(x, s1, s2, 0);
    }
    static int moves(int x, Stack&lt;Integer&gt; a, Stack&lt;Integer&gt; b, int moves){
        
        if(x == 0 ) return moves-1;
        if(x &lt; 0 ) return moves-1;

        int moves1 = a.isEmpty() ? moves : moves(x-a.pop(), a, b, moves+1);
        int moves2 = b.isEmpty() ? moves : moves(x-b.pop(), a, b, moves+1);

        return Math.max(moves1, moves2);

    }

Please can you help me by figuring out what's wrong and what would be the correct recursive approach. A lot of people have solved it by loop method but i want to solve this by recursively. The approach is simple, we have to first traverse the stack one until the required sum is reached then we start approaching the second stack. Whenever sum is greater from required one we delete the last number from the stack 1.

答案1

得分: 2

你正在使用一个实际的堆栈,并弹出(更改)元素,但你正在使用一种暴力算法,该算法依赖于元素不被更改。

我将通过一个示例进行说明:

4 2 4 1  -&gt; 堆栈 A
2 1 8 5 -&gt; 堆栈 B

这个问题的正确答案是:堆栈A[4 2 4 1] 堆栈B[2 1 8 5] = 9 < 10,因此是 4。

你对这个问题的回答将会是:堆栈A[4 2 4 1] 堆栈B[2 1 8 5] = 9 < 10,所以是 4。

这是相同的数字,但是完全错误。当位于 4 后面时,我们如何处理那个被锁在 1 后面的 1 呢? 这是它发生的方式:

  1. 从堆栈A弹出开始,添加了 4 = 4。移动次数 = 1
  2. 从堆栈A弹出 1,添加了 2 = 6。移动次数 = 2
  3. 从堆栈A弹出 2,添加了 4 = 10。 10 >= 10,所以移动次数减 1。移动次数 = 2。注意在这里 4 已经被永久移除。
  4. 从堆栈B弹出 2,添加了 2 = 8。移动次数 = 3
  5. 从堆栈A弹出 4,添加了 1 = 9。移动次数 = 4
    ...
    ...

你可以选择以下之一:

  1. 使用一种不同的算法,可以适应数据被更改的情况。这可能是你提到的“循环”方法(我还没有看到它,所以不确定)。
  2. 使用模拟堆栈而不是真实的堆栈,并模拟“弹出”操作。模拟堆栈实际上不会删除任何内容。

将你的代码修改为使用模拟堆栈的示例代码:

static int twoStacks(int x, int[] a, int[] b) {
    return moves(x, a, 0, b, 0, 0);
}

static int moves(int x, int[] a, int aHead, int[] b, int bHead, int moves){
    if (x <= 0) return moves - 1;

    int moves1 = (aHead < a.length) ? moves(x - a[aHead], a, aHead + 1, b, bHead, moves + 1) : moves;
    int moves2 = (bHead < b.length) ? moves(x - b[bHead], a, aHead, b, bHead + 1, moves + 1) : moves;

    return Math.max(moves1, moves2);
}
英文:

You are using an actual stack and popping (altering) elements, but you are doing a brute force algorithm that relies on the elements not being altered.

I will illustrate using an example:

4 2 4 1  -&gt; Stack A
2 1 8 5 -&gt; Stack B

The correct answer to this question is: StackA[4 2 4 1] StackB[2 1 8 5] = 9 < 10, so 4.

Your answer to this problem will be: StackA[4 2 4 1] StackB[2 1 8 5] = 9 < 10, so 4.

It's the same number, but it's completely wrong. How do we consume that 1 when it's locked behind the 4? This is how it happens:

  1. StackA is popped from start. and 4 is added = 4. moves = 1
  2. StackA is popped from 1. and 2 is added = 6. moves = 2
  3. StackA is popped from 2. and 4 is added = 10. 10 >= 10, so moves-1. moves = 2. Note that 4 has been permanently removed here.
  4. StackB is popped from 2. and 2 is added = 8. moves = 3
  5. StackA is popped from 4. and 1 is added = 9. moves = 4
    ...
    ...

You can do either of the following:

  1. Use a different algorithm that can accommodate the data being altered. This may be the "loop" method you were referring to (haven't seen it so don't know if it is).
  2. Use a simulated stack instead of a real one, and simulate the "pop". The simulated stack do not actually remove anything.

Sample code of your code being altered to use a simulated stack:

static int twoStacks(int x, int[] a, int[] b) {
    return moves(x, s1, 0, s2, 0, 0);
}

static int moves(int x, int[] a, int aHead, int[] b, int bHead, int moves){
    if (x &lt;= 0) return moves - 1;

    int moves1 = (aHead &lt; a.length) ? moves(x - a[aHead], a, aHead + 1, b, bHead, moves + 1) : moves;
    int moves2 = (bHead &lt; b.length) ? moves(x - b[bHead], a, aHead, b, bHead + 1, moves + 1) : moves;

    return Math.max(moves1, moves2);
}

huangapple
  • 本文由 发表于 2020年8月23日 17:07:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/63545219.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定