算法训练1-day10-栈与队列

48 阅读2分钟

今天是栈与队列

  1. 150. 逆波兰表达式求值

使用一个栈保存数字,遇到算术符就进行计算,然后将结果加入栈。

AC代码:

class Solution {
public:
    int evalRPN(vector<string>& tokens) {
        stack<int> numbers;
        for (string token : tokens) {
            if (token == "-" || token == "+" || token == "*" || token == "/") {
                Calculate(numbers, token);
            } else {
                numbers.push(stoi(token));
            }
        }

        return numbers.top();
    }

    void Calculate(stack<int>& numbers, string token) {
        int right = numbers.top();
        numbers.pop();
        int left = numbers.top();
        numbers.pop();
        if (token == "-") {
            numbers.push(left - right);
        } else if (token == "+") {
            numbers.push(left + right);
        } else if (token == "*") {
            numbers.push(left * right);
        } else {
            numbers.push(left / right);
        }
    }
};
  1. 239. 滑动窗口最大值

AC代码:

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        vector<int> ans(nums.size() - k + 1);
        deque<int> windowMaxNums;
        for (int i = 0; i < k; ++i) {
            //记录窗口最大值
            //从左往右,当加入nums[i]时,查看双端队列的后面,将所有小于nuns[i]的值全部弹出
            //直到遇到大于等于nums[i]的值
            //此时队列里保存的值依次递减,队头就是最大值
            //如[1,3,-1]加入队列后为[3,-1]
            //然后1移出,-3加入,队列变为[3,-1,-3]
            //然后3要移出,发现等于队列头,先移出,然后5加入,将-1,-3全部弹出,再加入5队列变为[5]
            while (!windowMaxNums.empty() && windowMaxNums.back() < nums[i]) {
                windowMaxNums.pop_back();
            }
            windowMaxNums.push_back(nums[i]);
        }

        ans[0] = windowMaxNums.front();
        for (int i = k; i < nums.size(); ++i) {
            if (nums[i - k] == windowMaxNums.front()) {
                windowMaxNums.pop_front();
            }

            while (!windowMaxNums.empty() && windowMaxNums.back() < nums[i]) {
                windowMaxNums.pop_back();
            }
            windowMaxNums.push_back(nums[i]);
            ans[i - k + 1] = windowMaxNums.front();
        }

        return ans;
    }
};
  1. 347. 前 K 个高频元素

AC代码:

class Solution {
public:
    class Comparer {
    public:
        bool operator()(pair<int, int> a, pair<int, int> b) {
	        //注意c++中返回true表示第二个元素应该排在前面
	        //所以 a.second > b.second表示当比较a和b时,b小于a则b在前面
            return a.second > b.second;
        }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> numsMap;
        // 小根堆
        priority_queue < pair<int, int>, vector<pair<int, int>>, Comparer> p;
        vector<int> ans(k);

        //统计频率,O(n)
        for (int num : nums) {
            numsMap[num]++;
        }

        //获取频率前k高的数,
        //遍历numsMap,最坏情况nums的所有数不同,O(n)
        //建堆,大小为k,插入删除都是log(k)
        //因此为O(nlogk)
        for (auto& item : numsMap) {
            if (p.size() < k) {
                p.push(item);
            } else {
                if (item.second > p.top().second) {
                    p.pop();
                    p.push(item);
                }
            }
        }

        int i = 0;
        while(!p.empty()){
            auto item = p.top();
            p.pop();
            ans[i++] = item.first;
        }

        return ans;
    }
};