2025.1.18学习记录1

一,代码随想录leetcode150逆波兰表达式求值

看答案后的解题思路:首先先建立一个栈s1,然后用一个for循环对tokens数组进行遍历。如果遍历到数字,就让其入栈,如果遍历到的是符号,首先先定义num1和num2来接收栈最顶端的两个元素,然后让这两个元素出栈,完成对应的加减乘除运算后再让其入栈即可。在遍历结束时容器内只剩余一个元素,这个元素即为逆波兰表达式最终结果。获取其栈顶元素并返回即可。

class Solution {
public:
    bool isNumber(string s){
        if(s.empty())return false;
        if(s[0]=='-'||s[0]=='+'){
            if(s.size()==1)return false;
            else{
                s=s.substr(1);
            }
        }
        for(char c:s){
            if(!isdigit(c))return false;
        }
        return true;
    }
    int evalRPN(vector<string>& tokens) {
        stack<long long> s1;
        for(int i=0;i<tokens.size();i++){
            if(isNumber(tokens[i]))s1.push(stoll(tokens[i]));
            else{
                long long num1=0,num2=0;
                num1=s1.top();s1.pop();
                num2=s1.top();s1.pop();
                if(tokens[i]=="+")s1.push(num1+num2);
                if(tokens[i]=="-")s1.push(num2-num1);
                if(tokens[i]=="*")s1.push(num1*num2);
                if(tokens[i]=="/")s1.push(num2/num1);
            }
        }
        return s1.top();
    }
};

 小结:

本题目需要注意的有以下几点:

1,对于一个字符串是否为数字的判断:首先判断该字符串是否为空,如果是空的直接返回false。然后判断第一位,如果是符号并且字符串长度为1则也返回false。如果长度不是1,用s=s.substr(1)函数来将字符串取下标为1及以后的部分。然后对新的字符串进行遍历,用isdigit函数判断是否是数字,如果有一项不是数字就直接返回false,全部遍历完成后返回true,说明这个字符串是数字。其实本题目也可以判断符号来巧妙地避开这个,会方便一些。

2,因为定义的栈是int类型,但是将一个判断结果为数字的字符串入栈前要先进行类型转换。转换用sto来进行。

  1. std::stoi

    • 功能:将字符串转换为 int 类型。
    • 用法
       

      cpp

      std::string str = "123"; int num = std::stoi(str); // num = 123

  2. std::stol

    • 功能:将字符串转换为 long 类型。
    • 用法
       

      cpp

      std::string str = "123456"; long num = std::stol(str); // num = 123456

  3. std::stoll

    • 功能:将字符串转换为 long long 类型。
    • 用法
       

      cpp

      std::string str = "1234567890123"; long long num = std::stoll(str); // num = 1234567890123

  4. std::stof

    • 功能:将字符串转换为 float 类型。
    • 用法
       

      cpp

      std::string str = "123.45"; float num = std::stof(str); // num = 123.45f

  5. std::stod

    • 功能:将字符串转换为 double 类型。
    • 用法
       

      cpp

      std::string str = "123.456"; double num = std::stod(str); // num = 123.456

  6. std::stold

    • 功能:将字符串转换为 long double 类型。
    • 用法
       

      cpp

      std::string str = "123.4567890123456789"; long double num = std::stold(str); // num = 123.4567890123456789

二,代码随想录leetcode239滑动窗口最大值

看答案之后的解题思路:这个题目的核心思路是定义一个自己的数据结构,如果窗口每滑动一次,就进行一次入,出,取最大值的操作即可。下面来解释三个函数的思路:首先先定义一个deque(双端队列)pop:如果函数不为空,并且函数在字符串遍历的过程中要删去的数值等于当前队列中的front就让front的元素出队,否则说明要删去的元素在push过程中已经删去了,无需进行额外操作。push:如果函数不为空并且当前队列队尾的元素小于要入队的元素,就让队尾元素出队,最后让该元素入队,这样做可以保证队头元素始终是最大的元素。getmax:直接取对头元素即可。

class Solution {
private:
    class MyQue{
    public:
        deque<int> que;
        void pop(int value){
            if(que.empty()==false&&que.front()==value)
            que.pop_front();
        }
        void push(int value){
            while(que.empty()==false&&que.back()<value){
                que.pop_back();
            }
            que.push_back(value);
        }
        int getmax(){
            return que.front();
        }
    };
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        MyQue que;
        vector<int> result;
        for(int i=0;i<k;i++){
            que.push(nums[i]);
        }
        result.push_back(que.getmax());
        for(int i=k;i<nums.size();i++){
            que.push(nums[i]);
            que.pop(nums[i-k]);
            result.push_back(que.getmax());
        }
        return result;
    }
};

 小结:本题需要注意以下几点:

1,deque双端队列在c++中的相关函数:

  1. 构造函数

    • deque<T>:默认构造函数,创建一个空的 deque
    • deque(size_type count, const T& value):创建一个包含 count 个元素,每个元素初始化为 value 的 deque
  2. 基本操作

    • push_back(const T& value):在双端队列的末尾插入一个元素。
    • push_front(const T& value):在双端队列的开头插入一个元素。
    • pop_back():删除双端队列的末尾元素。
    • pop_front():删除双端队列的开头元素。
  3. 访问元素

    • at(size_type pos):返回指定位置的元素,检查边界并抛出异常。
    • operator[](size_type pos):返回指定位置的元素,不检查边界。
    • front():返回第一个元素的引用。
    • back():返回最后一个元素的引用。
  4. 容量操作

    • size():返回 deque 中的元素数量。
    • empty():检查 deque 是否为空。
    • resize(size_type count):调整 deque 的大小,若新的大小大于当前大小,则追加默认值。
    • clear():移除所有元素。
  5. 迭代器

    • begin():返回指向第一个元素的迭代器。
    • end():返回指向最后一个元素后一个位置的迭代器。
    • cbegin()cend():返回常量迭代器以进行只读访问。
  6. 其他操作

    • insert(iterator pos, const T& value):在指定位置插入元素。
    • erase(iterator pos):删除指定位置的元素。
    • swap(deque& other):交换两个 deque 的内容。

2,c++中vector相关函数 

  1. 构造函数

    • vector<T>():默认构造函数,创建一个空的 vector
    • vector(size_type count, const T& value):创建一个包含 count 个元素,所有元素初始化为 value 的 vector
    • vector(const vector& other):拷贝构造函数,创建一个 vector 的副本。
    • vector(vector&& other) noexcept:移动构造函数,移动另一个 vector 的内容。
  2. 基本操作

    • push_back(const T& value):在 vector 的末尾插入一个元素。
    • pop_back():删除 vector 的最后一个元素。
    • insert(iterator pos, const T& value):在指定位置插入元素。
    • erase(iterator pos):删除指定位置的元素。
    • clear():移除所有元素,vector 变为空。
  3. 访问元素

    • at(size_type pos):返回指定位置的元素,检查边界并抛出异常。
    • operator[](size_type pos):返回指定位置的元素,不检查边界。
    • front():返回第一个元素的引用。
    • back():返回最后一个元素的引用。
  4. 容量操作

    • size():返回 vector 中的元素数量。
    • capacity():返回 vector 当前分配的存储空间大小。
    • empty():检查 vector 是否为空。
    • resize(size_type count):调整 vector 的大小。
    • reserve(size_type new_cap):预留空间以容纳至少 new_cap 个元素,避免频繁的内存重新分配。
  5. 迭代器

    • begin():返回指向第一个元素的迭代器。
    • end():返回指向最后一个元素后一个位置的迭代器。
    • cbegin()cend():返回常量迭代器以进行只读访问。
  6. 其他操作

    • swap(vector& other):交换两个 vector 的内容。
    • assign(size_type count, const T& value):用指定的 count 个 value 赋值给 vector

3,代码随想录leetcode347前k个高频元素

看答案之后的解题思路 :统计出现频率前k高的元素,创建一个最大个数不超过k的小顶堆即可。首先先创建一个map,键是数组nums中的元素,值是这些元素出现的次数。通过一个循环,让这些数组中的元素和这些元素出现的次数体现到了map中。然后对map遍历,把所有的pair全部放到小顶堆中,最后建立一个数组,把这些元素倒序放到数组里面即可。

class Solution {
public:
    // 小顶堆
    class mycomparison {
    public:
        bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) {
            return lhs.second > rhs.second;
        }
    };
    vector<int> topKFrequent(vector<int>& nums, int k) {
        // 要统计元素出现频率
        unordered_map<int, int> map; // map<nums[i],对应出现的次数>
        for (int i = 0; i < nums.size(); i++) {
            map[nums[i]]++;
        }

        // 对频率排序
        // 定义一个小顶堆,大小为k
        priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;

        // 用固定大小为k的小顶堆,扫面所有频率的数值
        for (unordered_map<int, int>::iterator it = map.begin(); it != map.end(); it++) {
            pri_que.push(*it);
            if (pri_que.size() > k) { // 如果堆的大小大于了K,则队列弹出,保证堆的大小一直为k
                pri_que.pop();
            }
        }

        // 找出前K个高频元素,因为小顶堆先弹出的是最小的,所以倒序来输出到数组
        vector<int> result(k);
        for (int i = k - 1; i >= 0; i--) {
            result[i] = pri_que.top().first;
            pri_que.pop();
        }
        return result;

    }
};

小结:这题好多代码不会写,后面要学习补上。

1.c++如何定义一个小顶堆:

  先自己写一个比较函数:struct MyComparison { bool operator()(const int& lhs, const int& rhs) { return lhs > rhs; // 比较规则:较大的元素优先级较低 } };再自己写一个定义小顶堆的代码priority_queue<int, vector<int>, MyComparison> minHeap;

2:priority_queue<pair<int, int>, vector<pair<int, int>>, mycomparison> pri_que;代码解释

  • priority_queue:优先队列是一种特殊的队列数据结构,它能让我们按优先级顺序处理元素。
  • pair<int, int>:优先队列中的每个元素是一个整数对(pair),即包含两个整数的组合。
  • vector<pair<int, int>>:这是存储元素的底层容器,使用了一个 vector 来存放 pair<int, int> 类型的元素。
  • mycomparison:这是一个自定义的比较器,用于定义元素的优先级顺序。

3, bool operator()(const pair<int, int>& lhs, const pair<int, int>& rhs) { return lhs.second > rhs.second; }代码解释:

这段代码定义了一个重载的运算符(),该运算符用于比较两个pair<int, int>类型的对象lhsrhs。具体来说,它比较这两个对象的第二个元素(second),并返回一个布尔值:

  • 如果lhs的第二个元素大于rhs的第二个元素,则返回true
  • 否则返回false

这通常用于排序或优先队列中,表示希望根据第二个元素的大小进行排序。

4,为什么不用大顶堆?因为大顶堆根是最大的元素,而且要控制数组元素不超过k,所以必然涉及到元素的移除,移除会移除根,也就是最大的数字,与题目要求不符合,因此用小顶堆。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值