leetcode算法刷题 150, 239, 347

150. 逆波兰表达式求值

示例 1:

输入: ["2", "1", "+", "3", " * "]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:

输入: ["4", "13", "5", "/", "+"]
输出: 6
解释: 该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:

输入: ["10", "6", "9", "3", "+", "-11", " * ", "/", " * ", "17", "+", "5", "+"]

输出: 22

class Solution {
public:
    int evalRPN(vector<string>& tokens) {//使用栈存储操作数及运算的结果,当扫描到运算符时弹出两个操作数,运算完结果再压入栈中
        int a, b;
        stack<int> st;
        for(string s: tokens){
            if(s == "+" || s == "-" || s == "*" || s == "/"){
                a = st.top();
                st.pop();
                b = st.top();
                st.pop();
                if(s == "+")
                    st.push(a+b);
                else if(s == "-")
                    st.push(b-a);
                else if(s == "*")
                    st.push(b*a);
                else if(s == "/")
                    st.push(b/a);
            }
            else
                st.push(stoi(s));
        }
        return st.top();
    }
};

239. 滑动窗口最大值

给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回滑动窗口中的最大值。

进阶:

你能在线性时间复杂度内解决此题吗?

class MyDeque{//
    public:
        deque<int> q;
        void push(int x){//入队前将所有比入队元素小的值全部出队,再将当前值入队
            while(!q.empty() && q.back() < x)
                q.pop_back();
            q.push_back(x);
        }

        void pop(int x){//若当前入队的值与队头元素相等则出队
            if(!q.empty() && q.front() == x)
                q.pop_front();
        }

        int front(){//返回队头元素,即每个区间的最大值
            return q.front();
        }
};
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        MyDeque q;
        vector<int> result;
        for(int i = 0; i < k; ++i)//第一个区间的元素全部入队
            q.push(nums[i]);
        result.push_back(q.front());
        for(int j = k; j < nums.size(); ++j){
            q.pop(nums[j-k]);//将区间最前面的元素出队列
            q.push(nums[j]);//将新区间包括的新元素入队列
            result.push_back(q.front());
        }
        return result;//返回每个区间包括的最大值
    }
};

347.前 K 个高频元素

定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:

输入: nums = [1], k = 1
输出: [1]
提示:

你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
你的算法的时间复杂度必须优于 $O(n \log n)$ , n 是数组的大小。
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
你可以按任意顺序返回答案。

使用优先级队列作为保存前k个高频的数据结构,优先级队列相当于一个堆,在插入这个堆时会自动进行排序。

class Solution {
public:
    class mycomparison{
        public:
            bool operator()(const pair<int, int> &x, const pair<int, int> &y){//定义为小根堆
                return x.second > y.second;
            }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        unordered_map<int, int> mymap;
        for(int i = 0; i < nums.size(); ++i)
            mymap[nums[i]]++;//使用unordered_map统计频次
        priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;
        for(unordered_map<int, int>::iterator it = mymap.begin(); it != mymap.end(); ++it){//迭代map,不断更新小根堆
            pri_que.push(*it);
            if(pri_que.size() > k)//始终保持k大小的堆
                pri_que.pop();
        }
        vector<int> result;
        while(!pri_que.empty()){//统计结果
            result.push_back(pri_que.top().first);
            pri_que.pop();
        }
        return result;
    }
};
posted @ 2025-02-05 10:25  arbiter9  阅读(12)  评论(0)    收藏  举报