HackerRank

时间:2017-05-20 08:41:13

标签: java algorithm data-structures stack

我刚刚在HackerRank上尝试了基于堆栈的问题

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

Alexa有两个非负整数堆栈,堆栈A和堆栈B,其中索引0表示堆栈的顶部。 Alexa挑战尼克参加以下比赛:

在每次移动中,Nick都可以从堆栈A或B堆栈的顶部删除一个整数。

Nick保留了他从两个堆栈中删除的整数的运行总和。

如果在任何时候,他的跑动总和大于比赛开始时给定的整数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&的前三个元素然后来自Stack 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);
        }
    }
}

6 个答案:

答案 0 :(得分:6)

好的我会尝试解释一个基本上可以用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

对堆栈B也是如此

2 3 11 16

然后每个数组开始从数组的末尾开始迭代,直到你得到一个小于或等于“你不应该超过的总和”的数字

现在你的当前总和是你在两个数组中达到的点的总和,应该是10 + 3 = 13所以为了达到10将绝对需要删除更多的条目

删除附加条目,我们将再次移动数组上的索引,以决定移动它的索引的索引取你指向的条目(数组1为10,数组2为3),并按索引设置+1(10 / 3~3),(3 / 2~1)然后将索引移动到最高值并重新计算总和

如果两个值都相等,则其逻辑可以移动与之前具有较大差异的值的索引(请记住我们以相反的顺序移动索引)。​​

结果将是索引+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)

答案 2 :(得分:1)

这个解决方案效果很好....我希望它有所帮助...

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

答案 3 :(得分:0)

void traversal(int &max, int x, std::vector<int> &a, int pos_a,
           std::vector<int> &b, int pos_b) {

  if (pos_a < a.size() and a[pos_a] <= x) {
    max = std::max(pos_a + pos_b + 1, max);
    traversal(max, x - a[pos_a], a, pos_a + 1, b, pos_b);
  }

  if (pos_b < b.size() and b[pos_b] <= x) {
    max = std::max(pos_a + pos_b + 1, max);
    traversal(max, x - b[pos_b], a, pos_a, b, pos_b + 1);
  }
}

int twoStacks(int x, std::vector<int> &a, std::vector<int> &b) {
  int max = 0;
  traversal(max, x, a, 0, b, 0);
  return max;
}

一个易于理解的递归解决方案。此解决方案将2个堆栈作为有向图进行遍历。

答案 4 :(得分:0)

我看到有一个解决方案,您将其标记为正确,但是我有一个简单的解决方案

  1. 添加堆栈1中满足条件<= x
  2. 的所有元素
  3. 添加的每个元素都将其推送到称为elements_from_a的堆栈
  4. 将计数器设置为堆栈大小
  5. 如果sum> x,请尝试从堆栈b中添加元素,因此删除添加的最后一个元素可以从堆栈elements_from_a中获取它
  6. 每个add都增加bstack计数器,每个remove都使astack递减
  7. 比较步骤总数和计数并调整计数返回计数

这是该解决方案的代码示例:

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

我希望这是更简单的解决方案。

答案 5 :(得分:0)

接受的答案是错误的。如图所示,在以下测试用例中失败了。

enter image description here

对于给定的测试用例,如果最大和不应超过10,则正确答案为5。但是,如果我们遵循Amer Qarabsa的方法,答案将是3。我们可以遵循Geeky coder方法。