#P3066. 计算堆栈中的剩余数字(100分)
          
                        
                                    
                      
        
              - 
          
          
                      1000ms
            
          
                      Tried: 95
            Accepted: 49
            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