leetcode200题之扫尾部分(三)

1. 基本的计算器

题目地址:https://leetcode-cn.com/problems/basic-calculator-ii/

字符串转为整数实现:

string s = "458";

int n = 0;
for (int i = 0; i < s.size(); i++) {
    char c = s[i];
    n = 10 * n + (c - '0');
}
// n 现在就等于 458

如果是数字,连续读取到 num
如果不是数字,就是遇到了下一个符号,之前的数字和符号就要存进栈中,遇到乘除法,拿出前一个数字做对应运算即可。

 

class Solution {
public:
    int calculate(string s) {
        stack <int> t;
        int res = 0, n = 0;
        char sign = '+';
        for(int i = 0; i < s.size(); ++i)
        {
            if(s[i] >= '0')  
                n = n * 10 + (s[i] - '0');     //如果是数字,就继续进位
            if(s[i] < '0' && s[i] != ' ' || i == s.size()-1)                
            {    //当遇见新的符号或者是最后一位数字时,进行上一个符号的计算并将结果入栈
                int pre;
                switch(sign)
                {
                    case '+':
                        t.push(n);
                        break;
                    case '-':
                        t.push(-n);
                        break;
                    case '*':
                        pre = t.top();
                        t.pop();
                        t.push(pre * n);
                        break;
                    case '/':
                        pre = t.top();
                        t.pop();
                        t.push(pre / n);
                        break;
                }
                sign = s[i];
                n = 0;              //上个符号的计算结束,符号更新,数字清0
            }
        }
        while(!t.empty())           //统计计算结果
        {
            res += t.top();
            t.pop();
        }
        return res;
    }
};

2.递增的三元子序列

方法一:

首先,新建两个变量 small 和 mid ,分别用来保存题目要我们求的长度为 3 的递增子序列的最小值和中间值。

接着,我们遍历数组,每遇到一个数字,我们将它和 small 和 mid 相比,若小于等于 small ,则替换 small;否则,若small<nums[i]<= mid,则替换 mid;否则,若大于 mid,则说明我们找到了长度为 3 的递增数组!

class Solution {
public:
    bool increasingTriplet(vector<int>& nums) {
        int len=nums.size();
        if(len<3)  return false;
        int small=INT_MAX, mid=INT_MAX;
        for(auto num:nums){
            if(num<=small){
                small=num;
            }
            else if(num<=mid){
                mid=num;
            }
            else if(num>mid){
                return true;
            }
        }
        return false;
    }
};

方法二:定义两个数组forward[i]和backward[i],forward[i]从前向后遍历,保存[0, i]之间最小元素值,backward[i]从后向前遍历,保存[i, size - 1]间最大元素值。然后从前向后遍历,如果找到一个数满足forward[i] < nums[i] < backward[i],则表示三元子序列存在。  (空间复杂度O(n))

比如:
nums[i]: 8 3 5 1 6
forwa[i]: 8 3 3 1 1
backw[i]:8 6 6 6 6

class Solution {
public:
    bool increasingTriplet(vector<int>& nums) {
        int len=nums.size();
        if(len<3)  return false;
        vector<int> f(len,nums[0]);
        vector<int> b(len,nums.back());
        for(int i=1; i<len; i++){
            f[i]=min(f[i-1],nums[i]);
        }
        for(int i=len-2; i>=0; i--){
            b[i]=max(b[i+1],nums[i]);
        }
        for(int i=0; i<len; i++){
            if(f[i]<nums[i] && nums[i]<b[i]){
                return true;
            }
        }
        return false;
    }
};

3.LRU缓存机制

方法:哈希表+双向链表

范例:可以想象手机后台程序。

/* 缓存容量为 2 */
LRUCache cache = new LRUCache(2);
// 你可以把 cache 理解成一个队列
// 假设左边是队头,右边是队尾
// 最近使用的排在队头,久未使用的排在队尾
// 圆括号表示键值对 (key, val)

cache.put(1, 1);
// cache = [(1, 1)]
cache.put(2, 2);
// cache = [(2, 2), (1, 1)]
cache.get(1);       // 返回 1
// cache = [(1, 1), (2, 2)]
// 解释:因为最近访问了键 1,所以提前至队头
// 返回键 1 对应的值 1
cache.put(3, 3);
// cache = [(3, 3), (1, 1)]
// 解释:缓存容量已满,需要删除内容空出位置
// 优先删除久未使用的数据,也就是队尾的数据
// 然后把新的数据插入队头
cache.get(2);       // 返回 -1 (未找到)
// cache = [(3, 3), (1, 1)]
// 解释:cache 中不存在键为 2 的数据
cache.put(1, 4);    
// cache = [(1, 4), (3, 3)]
// 解释:键 1 已存在,把原始值 1 覆盖为 4
// 不要忘了也要将键值对提前到队头
struct Node{
    int key;
    int value;
    Node* pre, * next;
    Node():key(0),value(0),pre(nullptr), next(nullptr){}
    Node(int _key, int _value):key(_key),value(_value),pre(nullptr), next(nullptr){}
};
class LRUCache {
public:
    Node* head;
    Node* tail;
    unordered_map<int, Node*> mp;
    int size;
    int capacity;
    LRUCache(int _capacity):capacity(_capacity),size(0) {
        head=new Node();  //伪头部(头哨兵)
        tail=new Node();  //伪尾部(尾哨兵)
        head->next=tail;
        tail->pre=head;
    }
    
    int get(int key) {
        if(!mp.count(key)){
            return -1;
        }
        //如果key存在
        Node* node=mp[key]; //1.通过哈希表定位
        moveToHead(node);   //2.移到头部
        return node->value;   //返回get要的node的值
    }
    
    void put(int key, int value) {
        //key不存在,加入
        if(!mp.count(key)){
            Node* node=new Node(key,value);  //1.new一个Node
            mp[key]=node;                    //2.将Node加入哈希表
            addToHead(node);                 //3.加入头部
            ++size;                          //4.size+1
            if(size>capacity){
                Node* removed=removeTail();   //超出容量,删除双向链表尾节点
                mp.erase(removed->key);       //删除哈希表中对应的项
                delete removed;
                --size;
            }
        }
        //key值存在,value需要更新
        else{
            Node* node=mp[key];   //1.通过哈希表定位
            node->value=value;    //2.更新value值
            moveToHead(node);     //3.移到头部
        }
    }
    void addToHead(Node* node){
        node->pre=head;
        node->next=head->next;
        head->next->pre=node;
        head->next=node;
    }
    void removeNode(Node* node){
        node->pre->next=node->next;
        node->next->pre=node->pre;
    }
    void moveToHead(Node* node){
        removeNode(node);
        addToHead(node);
    }
    Node* removeTail(){
        Node* node=tail->pre;
        removeNode(node);
        return node;
    }
};
/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache* obj = new LRUCache(capacity);
 * int param_1 = obj->get(key);
 * obj->put(key,value);
 */

4. 最小栈

两个栈:

数据栈:常规操作即可,

“最小”栈:如果新元素<=数据栈栈顶元素或者最小栈为空,则也要push进最小栈(维持一个降序)

                 等价于遍历stack所有元素,把升序的数字都删除掉,留下一个从栈底到栈顶降序的栈。

class MinStack {
private:
    stack<int> stk;
    stack<int> min_stk;
public:
    /** initialize your data structure here. */
    MinStack() {
        
    }
    
    void push(int x) {
        stk.push(x);
        if(min_stk.empty() || x<=min_stk.top()){
            min_stk.push(x);
        }
    }
    
    void pop() {
        if(stk.top()==min_stk.top()){
            min_stk.pop();
        }
        stk.pop();
    }
    
    int top() {
        return stk.top();
    }
    
    int getMin() {
        return min_stk.top();
    }
};

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack* obj = new MinStack();
 * obj->push(x);
 * obj->pop();
 * int param_3 = obj->top();
 * int param_4 = obj->getMin();
 */

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值