2~5 TLE求助

P4387 【深基15.习9】验证栈序列

Mandel520 @ 2022-02-10 12:03:00

下面这个是我使用stack并成功AC的程序:

#include<bits/stdc++.h>
using namespace std;

int q, n;  //q:询问次数 n:序列长度
int input_arr[100005];   //入栈序列
int output_arr[100005];  //出栈序列

int main(){
    cin >> q;
    while(q--){
        cin >> n;
        for (int i = 1; i <= n; i++) cin >> input_arr[i];   //入栈序列
        for (int i = 1; i <= n; i++) cin >> output_arr[i];  //出栈序列

        stack<int> s;
        int idx1 = 1;  //表示当前入栈序列匹配的位数
        int idx2 = 1;  //表示当前出栈序列匹配的位数

        while (idx2 <= n){
            while((s.empty()) || (s.top() != output_arr[idx2])){//栈顶和出栈序列不相同则继续入栈
                if(idx1 > n){ //全都入栈了还是不能匹配出栈序列
                    cout << "No" << endl;
                    goto part1;
                }
                s.push(input_arr[idx1]); //入栈
                idx1++;
            }

            while((!s.empty()) && s.top() == output_arr[idx2] && idx2 <= n){//栈顶和出栈序列相同则出栈
                s.pop();  //出栈
                idx2++; 
            }
        }
        cout << "Yes" << endl;
        part1:;
    }
    return 0;
}

下面这个是我手写栈的程序,思路和上面的程序相同, 但是TLE了4个点

#include<stdio.h>
#include<string.h>

typedef struct{       //定义栈
    int Data[100005];   //存储元素的数组
    int topIdx;       //栈顶指针
}Stack;

void InitStack(Stack *s){  // 初始化栈
    s->topIdx = 0;
    memset(s->Data, 0, sizeof(s->Data));        
} 

int Push(Stack *L, int e){     //将元素推入栈中
    if (L->topIdx == 100005 - 1) return 0; //栈已满
    L->Data[L->topIdx++] = e;  //加入栈中
    return e;                  //返回压入的元素
}

int Pop(Stack *L){    //移除栈顶元素
    if (L->topIdx == 0) return 0;
    int val = L->Data[--(L->topIdx)];
    //printf("%d ",val);
    return val;
}

int Top(Stack s){     //返回栈顶元素
    if (s.topIdx == 0) return 0;
    return s.Data[s.topIdx - 1];
}

int isEmpty(Stack s){  //判断栈s是否为空
    if (s.topIdx == 0) return 1;
    return 0;
}

int isFull(Stack s){   //判断栈是否已满
    if (s.topIdx != 100005 -1) return 1;
    return 0;
}

int q, n;  //q:询问次数 n:序列长度
int input_arr[100005];   //入栈序列
int output_arr[100005];  //出栈序列

int main(){
    scanf("%d", &q);
    while(q--){
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) scanf("%d", &input_arr[i]);  //入栈序列
        for (int i = 1; i <= n; i++) scanf("%d", &output_arr[i]); //出栈序列

        Stack s;
        InitStack(&s);
        int idx1 = 1;  //表示当前入栈序列匹配的位数
        int idx2 = 1;  //表示当前出栈序列匹配的位数

        while(idx2 <= n){
            while((isEmpty(s)) || (Top(s) != output_arr[idx2])){//栈顶和出栈序列不相同则继续入栈
                if (idx1 > n){
                    puts("No");
                    goto part1;
                }
                Push(&s, input_arr[idx1]);  //入栈
                idx1++;
            }

            while((!isEmpty(s)) && Top(s) == output_arr[idx2] && idx2 <= n){//栈顶和出栈序列相同则出栈
                Pop(&s);  //出栈
                idx2++;
            }
        }
        puts("Yes");
        part1:;
    }
    return 0;
}

现在我需要指出的是:

(1)这个手写的栈, 之前已经在P1241和P1449两道题中使用过, 所以应该不是手写的栈的问题

(2)下面这个程序中的main()函数和上面的程序中的main()函数几乎完全一致, 因此也不想是main()函数中的问题

(3)讨论区的所有hack样例我全都使用第二个程序测过了, 全都通过. 说明也不是犯了其他人犯过的错误

(4)因为是数组实现的栈, 因此时间复杂度本身是没有问题的

基于以上4点, 我实在想不通第二个程序的问题出在哪, 因此恳求各位大佬帮我看看


by yukimianyan @ 2022-02-10 13:19:21

@Jeremy_Mandel 是您的手写栈实现不好

int Top(Stack s){     //返回栈顶元素
    if (s.topIdx == 0) return 0;
    return s.Data[s.topIdx - 1];
}

int isEmpty(Stack s){  //判断栈s是否为空
    if (s.topIdx == 0) return 1;
    return 0;
}

int isFull(Stack s){   //判断栈是否已满
    if (s.topIdx != 100005 -1) return 1;
    return 0;
}

这些函数传参传的是 Stack s,每次调用都会复制一个新的 Stack ,一共调用 1e5 次,每次复制 1e5 级别的内存,常数爆炸,建议传指针或者引用


by yukimianyan @ 2022-02-10 13:19:50

int Top(Stack &s){     //返回栈顶元素
    if (s.topIdx == 0) return 0;
    return s.Data[s.topIdx - 1];
}

int isEmpty(Stack &s){  //判断栈s是否为空
    if (s.topIdx == 0) return 1;
    return 0;
}

int isFull(Stack &s){   //判断栈是否已满
    if (s.topIdx != 100005 -1) return 1;
    return 0;
}

by Mandel520 @ 2022-02-10 14:45:17

@yukimianyan 谢谢大佬, 大佬太强了, 已经关注大佬了


|