更多PAT甲级题解--acking-you.gtihub.io

最易理解的Stack实现方式,没有树状数组,没有堆!

题目

OJ平台

题目分析

  • 关键就是要我们实现以下这个操作:

PeekMedian -- return the median value of all the elements in the stack. With N elements, the median value is defined to be the (N/2)-th smallest element if N is even, or ((N+1)/2)-th if N is odd. 作用是返回栈中第 N/2 小的元素。

  • 我们可能很快就会想到排序,然后用STL中的栈来实现,一旦需要排序的时候(PeekMedian操作)就直接sort,然后提交后你会发现----它超时了!😂

好吧,我不偷懒了,自己想想怎么实现这一一个栈,我是用的最朴素的方式实现,通过在栈中多加一个数组实现对元素的排序(这个过程由于是每次入栈和出栈进行排序,所以完全可以用二分找到位置进行插入和删除某个元素),后面看到很多大佬,不是用堆就是用树状数组,太强了,我还达不到这样的高度啊🤦‍♂️

  • 以下是我实现的效率(根大佬们的树状数组还是没得比🤣

代码详解

栈的数据结构实现

这里使用的二分是STL自带的,当然你也可以自己写个二分,这样的话,代码长度会变长🤦‍♂️

//@实现一个栈,用两个数组实现。
struct Stack {
    int *nums;                 //用作栈空间
    int *sort_nums;            //将栈元素排序后的情况
    int length;                //栈的长度
    int capcity;               //栈的最大容量

    Stack(int cap) : nums(nullptr), length(0), capcity(cap), sort_nums(nullptr) {
        nums = new int[capcity];
        sort_nums = new int[capcity];
    }

//@关键在于push和pop操作的处理
    void push(int val) {
        if (!isEmpty()) {
            int pos = upper_bound(sort_nums, sort_nums + length, val) - sort_nums;
            for (int i = length; i > pos; i--) {
                sort_nums[i] = sort_nums[i - 1];
            }
            sort_nums[pos] = val;
        } else {
            sort_nums[length] = val;
        }
        nums[length] = val;
        length++;;
    }

    void pop() {
        if (!isEmpty()) {
            int pos = upper_bound(sort_nums, sort_nums + length, nums[length - 1]) - sort_nums;
            for (int i = pos - 1; i < length; i++) {
                sort_nums[i] = sort_nums[i + 1];
            }
        } else {
            cout << "Invalid" << endl;
            return;
        }
        length--;
        cout << nums[length] << endl;
        return;
    }

    void peekMed() {
        if (isEmpty()) {
            cout << "Invalid" << endl;
        } else {
            cout << sort_nums[(length - 1) / 2] << endl;
        }
    }

    bool isEmpty() {
        return length == 0;
    }
} St(100002);

输入数据和问题解决处理

void solve(const string &s) {//根据字符串的第二个字符进行分类操作
    if (s[1] == 'u') {
        int v;
        cin >> v;
        St.push(v);
    } else if (s[1] == 'o') {
        St.pop();
    } else {
        St.peekMed();
    }
}

void Input() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> N;
    int n = N;
    string s;
    while (n--) {
        cin >> s;
        solve(s);
    }
}

整合代码进行提交

应该是最易理解的实现方式了吧!

#include <bits/stdc++.h>

using namespace std;
int N;                         //输入的操作数
//@实现一个栈,用两个数组实现。
struct Stack {
    int *nums;                 //用作栈空间
    int *sort_nums;            //将栈元素排序后的情况
    int length;                //栈的长度
    int capcity;               //栈的最大容量

    Stack(int cap) : nums(nullptr), length(0), capcity(cap), sort_nums(nullptr) {
        nums = new int[capcity];
        sort_nums = new int[capcity];
    }

//@关键在于push和pop操作的处理
    void push(int val) {
        if (!isEmpty()) {
            int pos = upper_bound(sort_nums, sort_nums + length, val) - sort_nums;
            for (int i = length; i > pos; i--) {
                sort_nums[i] = sort_nums[i - 1];
            }
            sort_nums[pos] = val;
        } else {
            sort_nums[length] = val;
        }
        nums[length] = val;
        length++;;
    }

    void pop() {
        if (!isEmpty()) {
            int pos = upper_bound(sort_nums, sort_nums + length, nums[length - 1]) - sort_nums;
            for (int i = pos - 1; i < length; i++) {
                sort_nums[i] = sort_nums[i + 1];
            }
        } else {
            cout << "Invalid" << endl;
            return;
        }
        length--;
        cout << nums[length] << endl;
        return;
    }

    void peekMed() {
        if (isEmpty()) {
            cout << "Invalid" << endl;
        } else {
            cout << sort_nums[(length - 1) / 2] << endl;
        }
    }

    bool isEmpty() {
        return length == 0;
    }
} St(100002);


void solve(const string &s) {//根据字符串的第二个字符进行分类操作
    if (s[1] == 'u') {
        int v;
        cin >> v;
        St.push(v);
    } else if (s[1] == 'o') {
        St.pop();
    } else {
        St.peekMed();
    }
}

void Input() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> N;
    int n = N;
    string s;
    while (n--) {
        cin >> s;
        solve(s);
    }
}

int main() {
    Input();
    return 0;
}