求解HackerRank两栈游戏问题:贪心实现无法通过测试用例求助
两栈游戏问题:贪心解法错误排查
问题描述
给定两个整数栈和一个maxSum值,要求找出从两个栈顶移除元素的最大数量,使得移除元素的总和不超过maxSum。
示例
stack 1: 4 2 4 6 1
stack 2: 2 1 8 5
maxSum=10
输出=4(可移除4、2、2、1,总和4+2+2+1=9≤10)
我的解法问题
我采用贪心思路:每次选择两个栈顶中较小的元素加入总和,直到总和超过maxSum。但代码无法通过多个测试用例,作为DSA新手,恳请帮忙排查问题。
我的代码
int twoStacks(int maxSum, vector<int> a, vector<int> b) { int count=0; int sum=0; int i=0; int j=0; while(sum<=maxSum){ if(i<a.size() && j<b.size() && sum+min(a[i],b[j])<=maxSum){ sum+=min(a[i],b[j]); count++; if(min(a[i],b[j])==a[i]){ i++; } else{ j++; } } else if(i>=a.size() && j<b.size() && sum+b[j]<=maxSum){ sum+=b[j]; count++; j++; } else if(i<a.size() && j>=b.size() && sum+a[i]<=maxSum){ sum+=a[i]; count++; i++; } else{ break; } } return count; }
问题根源:贪心策略的局限性
你的贪心思路(每次选当前栈顶较小的元素)无法覆盖所有最优情况,因为局部最优不代表全局最优。举个反例:
- stack1: [3, 0, 0, 0]
- stack2: [2, 2]
- maxSum=4
按你的贪心逻辑,会先选stack2的2(sum=2,count=1),再选stack2的2(sum=4,count=2),但最优解是选stack1的3+0+0(sum=3≤4,count=3),数量更多。这说明只看当前最小元素,会错过后续能拿更多元素的组合。
正确解法:前缀和+双指针
正确的思路是先累加其中一个栈的元素到最大可能数量,再逐步替换为另一个栈的元素,记录过程中的最大总数量。这种方法能覆盖所有可能的元素组合,时间复杂度为O(n+m),效率很高。
代码实现
int twoStacks(int maxSum, vector<int> a, vector<int> b) { int n = a.size(), m = b.size(); int sum = 0, count = 0; // 先累加栈a的元素,直到总和超过maxSum while (count < n && sum + a[count] <= maxSum) { sum += a[count]; count++; } int max_count = count; // 记录当前最大数量 // 逐步减少栈a的元素,同时加入栈b的元素,更新最大数量 int j = 0; while (count > 0 && j < m) { sum -= a[--count]; // 移除一个栈a的元素 // 尽可能加入栈b的元素 while (j < m && sum + b[j] <= maxSum) { sum += b[j]; j++; } max_count = max(max_count, count + j); // 更新最大数量 } return max_count; }
解法说明
- 前缀累加:先把栈a的元素逐个加入总和,直到无法再加入,此时得到栈a能单独拿的最大数量。
- 双指针替换:从栈a的最大数量开始,逐个移除元素,同时尝试加入栈b的元素,每次计算当前总数量(栈a剩余数量+栈b已加入数量),记录最大值。
- 覆盖所有组合:这种方式遍历了所有“k个栈a元素+l个栈b元素”的合法组合,确保找到数量最多的那一组。
内容的提问来源于stack exchange,提问作者Gourav kr Singh
相关产品推荐
相关产品推荐

