#P3066. 计算堆栈中的剩余数字(100分)
-
1000ms
Tried: 96
Accepted: 50
Difficulty: 4
所属公司 :
华为od
-
算法标签>模拟
计算堆栈中的剩余数字(100分)
题面描述:
这个题目要求我们模拟一个栈的操作,将一系列正整数依次入栈。每当新元素入栈时,如果这个元素等于栈中某个连续子序列的和(子序列长度在 2 到 x 之间),则出栈这些元素,并将 m(等于 2 * n_1,其中 n_1 是当前入栈元素)入栈。最终,输出栈中剩余元素的值,栈顶元素在左侧,用空格隔开。输入为正整数的字符串,数字之间用空格分隔,数量范围为 1 到 1000。
思路:
数据范围只有1000直接用vector模拟入栈出栈的过程即可,注意可能会出现连续出栈的情况所以要递归实现。
思路分析
-
栈的模拟:
- 使用一个动态数组(
vector)来模拟栈的行为,支持push_back(入栈)和pop_back(出栈)操作。
- 使用一个动态数组(
-
递归出栈处理:
- 每次入栈后,检查栈顶元素是否满足替换条件。
- 如果满足条件,则出栈相应的元素,并入栈新的元素。
- 由于出栈操作可能会导致新的栈顶元素满足条件,因此需要使用递归方法来处理连续出栈的情况,直到没有更多元素满足条件。
-
和的计算:
- 在检查替换条件时,需计算栈顶元素n1和其下y−1个元素的和。通过遍历栈的部分元素来计算和。
cpp
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
int main(){
string line;
// 读取整行输入
getline(cin, line);
// 使用字符串流分割输入
stringstream ss(line);
string num_str;
vector<long long> stack; // 使用long long避免溢出
while(ss >> num_str){
long long num = stoll(num_str);
stack.push_back(num); // 入栈
// 检查是否需要替换
while(true){
bool replaced = false;
// y从2到当前栈大小
for(int y=2; y<=stack.size(); y++){
long long n1 = stack.back();
long long sum = 0;
// 计算n2 + n3 + ... + ny
// 修正索引范围:从 stack.size()-y 到 stack.size()-1-1
for(int i=stack.size()-y; i<stack.size()-1; i++){
sum += stack[i];
}
if(n1 == sum){
// 满足条件,出栈y个元素
for(int i=0; i<y; i++) stack.pop_back();
// 入栈新的元素m=2*n1
stack.push_back(2 * n1);
replaced = true;
break; // 进行一次替换后,重新检查
}
}
if(!replaced) break; // 没有替换则退出
}
}
// 输出栈中元素,从栈顶到栈底
for(int i = stack.size()-1; i >=0; i--){
if(i != stack.size()-1) cout << " ";
cout << stack[i];
}
return 0;
}
python
def main():
# 读取整行输入
line = input()
# 使用空格分割输入
numbers = list(map(int, line.split()))
stack = [] # 使用列表模拟栈
for num in numbers:
stack.append(num) # 入栈
# 检查是否需要替换
while True:
replaced = False
# y从2到当前栈大小
for y in range(2, len(stack) + 1):
n1 = stack[-1]
sum_value = sum(stack[-y:-1]) # 计算n2 + n3 + ... + ny
if n1 == sum_value:
# 满足条件,出栈y个元素
del stack[-y:] # 出栈y个元素
# 入栈新的元素m=2*n1
stack.append(2 * n1)
replaced = True
break # 进行一次替换后,重新检查
if not replaced:
break # 没有替换则退出
# 输出栈中元素,从栈顶到栈底
print(" ".join(map(str, reversed(stack))))
if __name__ == "__main__":
main()
java
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取整行输入
String line = scanner.nextLine();
String[] numStrs = line.split(" ");
List<Long> stack = new ArrayList<>(); // 使用 ArrayList 模拟栈
// 将输入的数字依次入栈
for (String numStr : numStrs) {
long num = Long.parseLong(numStr);
stack.add(num); // 入栈
// 检查是否需要替换
while (true) {
boolean replaced = false;
// y 从 2 到当前栈大小
for (int y = 2; y <= stack.size(); y++) {
long n1 = stack.get(stack.size() - 1); // 栈顶元素
long sum = 0;
// 计算 n2 + n3 + ... + ny
for (int i = stack.size() - y; i < stack.size() - 1; i++) {
sum += stack.get(i);
}
if (n1 == sum) {
// 满足条件,出栈 y 个元素
for (int i = 0; i < y; i++) {
stack.remove(stack.size() - 1); // 出栈
}
// 入栈新的元素 m = 2 * n1
stack.add(2 * n1);
replaced = true;
break; // 进行一次替换后,重新检查
}
}
if (!replaced) {
break; // 没有替换则退出
}
}
}
// 输出栈中元素,从栈顶到栈底
for (int i = stack.size() - 1; i >= 0; i--) {
if (i != stack.size() - 1) {
System.out.print(" ");
}
System.out.print(stack.get(i));
}
scanner.close(); // 关闭扫描器
}
}
题目内容
向一个空栈中依次存入正整数,假设入栈元素 n(1<=n<=231−1)按顺序依次为 nx…n4、n3、n2、n1, 每当元素入栈时,如果 n1=n2+…+ny(y 的范围[2,x], 1<=x<=1000),则 n1 ~ ny 全部元素出栈,重新入栈新元素 m(m=2∗n1)。
如:依次向栈存入 6、 1、 2、 3, 当存入 6、 1、 2 时,栈底至栈顶依次为[6、1、2];
当存入 3 时, 3=2+1, 3、2、1 全部出栈,重新入栈元素 6(6=2∗3),此时栈中有元素 6;
因为 6=6,所以两个 6 全部出栈,存入 12,最终栈中只剩一个元素 12。
输入描述
使用单个空格隔开的正整数的字符串,如”5 6 7 8″, 左边的数字先入栈,输入的正整数个数为 x, 1<=x<=1000。
输出描述
最终栈中存留的元素值,元素值使用空格隔开,如”8 7 6 5″, 栈顶数字在左边。
样例1
输入
5 10 20 50 85 1
输出
1 170
说明
5+10+20+50=85, 输入 85 时, 5、10、20、50、85 全部出栈,入栈 170,最终依次出栈的数字为 1 和 170。
样例2
输入
6 7 8 13 9
输出
9 13 8 7 6
样例3
输入
1 2 5 7 9 1 2 2
输出
4 1 9 14 1