2021-10-12

第十三天

今天在知乎上看到一篇文章,关于学习路线以及学习心得的,突然感觉我的学习路线有点偏了,我之前看的Cpppp和国外一个版本的算法数据与结构Cpp描述,作者说这两本书不适合自己进行学习,用来当辞典还是不错的,哪里不会的可以去查一下。。。
只能说我学习比较全面吧,那本书800页,我看了大概300页,基本语法结构肯定都看了,但是其中还是有不少晦涩难懂的地方,看了那篇文章,突然觉得部分东西也不是很有必要了。开始今日的学习。

1.栈练习题

先回顾以下栈这个东西,基本上就这一个特点就是先进后出。
那什么样的题目可以用栈来处理呢?拥有最近相关性的题目。使用栈来处理的习题类型基本上就是这一类。

有效的括号
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
示例 1:
输入:s = “()”
输出:true

示例 2:
输入:s = “()[]{}”
输出:true

示例 3:
输入:s = “(]”
输出:false

示例 4:
输入:s = “([)]”
输出:false

示例 5:
输入:s = “{[]}”
输出:true
这个题目是判断左右括号是否能闭合,是否是有效括号。
class Solution {

public:
    bool isValid(string s) {
        unordered_map<char,int> m{{'(',1},{'[',2},{'{',3},
                                {')',4},{']',5},{'}',6}};
        stack<char> st;
        bool istrue=true;
        for(char c:s){
            int flag=m[c];
            if(flag>=1&&flag<=3) st.push(c);
            else if(!st.empty()&&m[st.top()]==flag-3) st.pop();
            else {istrue=false;break;}
        }
        if(!st.empty()) istrue=false;
        return istrue;
    }
};

利用了哈希表和栈的特性,哈希表就好像python里面的pd.DataFrame(),值都是一一对应的,这里简单的看了一下,也不算难的。
先把对应的符号和序号都存到哈希表里面,因为这个题目是针对于最近的符号,所以有最近相关性,我们必须先把最里面的符号找出来才能判断是不是都是有效的符号。
从最里面开始,找到相同的,就把他们都移除掉,最后如果是空的就证明都是有效的符号。把左边的括号存到栈里面去,因为只能最近的即和最上面的值进行比较,所以如果找到了就掉最上面的值,最后得到空就完成。
注意一点,如果里面没有左括号的话也是会得不出正确答案的,所以第三个else的作用就出来了。

最小栈
设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

push(x) —— 将元素 x 推入栈中。
pop() —— 删除栈顶的元素。
top() —— 获取栈顶元素。
getMin() —— 检索栈中的最小元素。

输入:
[“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.

class MinStack {
public:
    stack<int> data;
    stack<int> min_stack;
    MinStack() {
        min_stack.push(INT_MAX);
    }
    
    void push(int val) {
        data.push(val);
        min_stack.push(min(min_stack.top(), val));
    }
    
    void pop() {
        data.pop();
        min_stack.pop();
    }
    
    int top() {
        return data.top();
    }
    
    int getMin() {
        return min_stack.top();
    }
};

就是按照要求,按照顺序去做,一开始跑没过去,注意pop那一栏的不要忘了min_stack也要pop去掉栈顶元素。这个好像是只要符合他的输出就行。

柱状图面积
这个不贴图了

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();
        int ans = 0;
        // 枚举左边界
        for (int left = 0; left < n; ++left) {
            int minHeight = INT_MAX;
            // 枚举右边界
            for (int right = left; right < n; ++right) {
                // 确定高度
                minHeight = min(minHeight, heights[right]);
                // 计算面积
                ans = max(ans, (right - left + 1) * minHeight);
            }
        }
        return ans;
    }
};

不出所料,暴力直接溢出;

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int n = heights.size();
        int ans = 0;
        for (int mid = 0; mid < n; ++mid) {
            // 枚举高
            int height = heights[mid];
            int left = mid, right = mid;
            // 确定左右边界
            while (left - 1 >= 0 && heights[left - 1] >= height) {
                --left;
            }
            while (right + 1 < n && heights[right + 1] >= height) {
                ++right;
            }
            // 计算面积
            ans = max(ans, (right - left + 1) * height);
        }
        return ans;
    }
};

第二种溢出,但是确实是可以解决的。
第一种是从第一根柱子开始,宽度确定的情况下,寻找最小的高。
第二种也是从第一根开始,在高度确定的情况下,寻找最大的宽。

#include <iostream>
#include <vector>
#include <stack>

using namespace std;


class Solution {
public:
    int largestRectangleArea(vector<int> &heights) {
        unsigned long size = heights.size();
        if (size == 1) {
            return heights[0];
        }
        int res = 0;
        stack<int> stk;
        for (int i = 0; i < size; ++i) {
            while (!stk.empty() && heights[stk.top()] > heights[i]) {
                int length = heights[stk.top()];
                stk.pop();
                int weight = i;
                if (!stk.empty()) {
                    weight = i - stk.top() - 1;
                }
                res = max(res, length * weight);
            }
            stk.push(i);
        }
        while (!stk.empty()) {
            int length = heights[stk.top()];
            stk.pop();
            int weight = size;
            if (!stk.empty()) {
                weight = size - stk.top() - 1;
            }
            res = max(res, length * weight);
        }
        return res;
    }
};

栈的解法,就离谱哦,这个建议去官网看解析,真的。

今日结束,其实今天应该多看几道题目或者多学点东西的。
上午在装系统,下午游客,半晌回来以后才开始学,因为觉得自己学的不是很好,有点吃力,所以这个时间段也看了一些有有经验的帖子,换了本书看,只是看网课感觉还是不够的,搞到了电子版的大话数据结构,买了一本详细一点的c++描述数据结构与算法,特别是大话数据结构,觉得写的还真不错,确实还挺适合自学的。
进度堪忧只能说,要不然就等下年三月份把,12月的目标是下次考试不用花钱。

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值