第十三天
今天在知乎上看到一篇文章,关于学习路线以及学习心得的,突然感觉我的学习路线有点偏了,我之前看的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月的目标是下次考试不用花钱。