我刚刚在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);
}
}
}
答案 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)
我看到有一个解决方案,您将其标记为正确,但是我有一个简单的解决方案
这是该解决方案的代码示例:
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)
接受的答案是错误的。如图所示,在以下测试用例中失败了。
对于给定的测试用例,如果最大和不应超过10,则正确答案为5。但是,如果我们遵循Amer Qarabsa的方法,答案将是3。我们可以遵循Geeky coder方法。