目录
一、用两个栈实现队列

插入正常让元素进入第一个栈
删除,先让栈一所有元素进入栈二,取完栈二top,删除,剩余push回栈一,保证后续又插入新元素的队列顺序性
class Solution
{
public:
void push(int node) {
stack1.push(node);
}
int pop() {
while(!stack1.empty())
{
stack2.push(stack1.top());
stack1.pop();
}
int ret=stack2.top();
stack2.pop();
while(!stack2.empty())
{
stack1.push(stack2.top());
stack2.pop();
}
return ret;
}
private:
stack<int> stack1;
stack<int> stack2;
};
二、包含min函数的栈


双栈,一个栈正常操作,另一个栈只有插入元素更小的时候才入栈(错误,插入元素等于的时候也要入栈)
#include <climits>
#include <stack>
class Solution {
stack<int> s1,s2;
public:
void push(int value) {
s1.push(value);
//注意是>=不是>,等于也要push进,因为存在多个最小值
//s1:2 2 2 2,s2:2,pop一次后s2就为空了,此时min是2,但min函数出错
if(s2.empty()||s2.top()>=value)s2.push(value);
// or
// if(s2.empty()||s2.top()>value)
// s2.push(value);
// else
// s2.push(s2.top());
}
void pop() {
if(s1.top()==s2.top())s2.pop();
s1.pop();
}
int top() {
return s1.top();
}
int min() {
return s2.top();
}
};
三、有效括号序列


#include <stack>
class Solution {
stack<int> st;
public:
bool isValid(string s) {
int n=s.size();
for(int i=0;i<n;++i)
{
if(s[i]=='['||s[i]=='('||s[i]=='{')
st.push(s[i]);
else
{
if(st.empty())return false;
if(s[i]==']'&&st.top()=='[')st.pop();
else if(s[i]==')'&&st.top()=='(')st.pop();
else if(s[i]=='}'&&st.top()=='{')st.pop();
else return false;
}
}
return st.empty()?true:false;
}
};
四、滑动窗口的最大值


法一:暴力
窗口大小大于数组大小的时候返回空
#include <climits>
class Solution {
public:
vector<int> maxInWindows(vector<int>& num, int size) {
vector<int> ret;
if(size<=num.size()&&size!=0)
{
for(int i=0;i<=num.size()-size;++i)
{
int MaxNum=INT_MIN;
for(int j=i;j<i+size;++j)
{
if(num[j]>MaxNum)MaxNum=num[j];
}
ret.push_back(MaxNum);
}
}
return ret;
}
};
法二:双端队列
队列中维护该区间内部,元素大小从大到小排列的元素下标,为什么是下标因为后面滑动窗口的时候,如果队头元素下标不在这个区级内了,就要一直pop_front。对于新加入的元素,如果它始终大于(while)队尾,就一直删队尾,最终在合适位置push,如此就保证了双端队列中始终维护着在这个区间内部的 元素大小从大到小排列的 对应的从小到大排列的下标。(力竭了〒▽〒)
#include <climits>
#include <deque>
#include <vector>
class Solution {
public:
vector<int> maxInWindows(vector<int>& num, int size) {
vector<int> ret;
if(size<=num.size()&&size!=0)
{
//dq存储下标
deque<int> dq;
//先处理一个窗口
for(int i=0;i<size;++i)
{
while(!dq.empty()&&num[dq.back()]<num[i])
dq.pop_back();
dq.push_back(i);
}
//滑动窗口,i为新区间的末尾元素下标
for(int i=size;i<num.size();++i)
{
ret.push_back(num[dq.front()]);
//不在区间内的元素删掉
//i-size+1是新的区间的第一个元素下标
while(!dq.empty()&&dq.front()<i-size+1)
dq.pop_front();
//加入新元素,维护dq的方法同上
while(!dq.empty()&&num[dq.back()]<num[i])
dq.pop_back();
dq.push_back(i);
}
//最后一个窗口维护完,元素还没入ret
ret.push_back(num[dq.front()]);
}
return ret;
}
};
五、最小的k个数

维护大根堆数量为k即可
#include <queue>
#include <vector>
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int>& input, int k) {
vector<int> ret;
if(k==0)return ret;
priority_queue<int> heap;
for(auto&x:input)
{
if(heap.size()<k)heap.push(x);
//始终维护大根堆大小为k
else
{
if(x<heap.top())
{
heap.pop();
heap.push(x);
}
}
}
while(k--)
{
ret.push_back(heap.top());
heap.pop();
}
return ret;
}
};
六*、寻找第k大

分治题怎么到这来了???
#include <cstdlib>
#include <vector>
class Solution {
public:
int findKth(vector<int>& a, int n, int K) {
if(n==0)return 0;
srand(time(NULL));
return qsort(a,0,n-1,K);
}
int qsort(vector<int>&nums,int left,int right,int K)
{
if(left==right)return nums[left];
int key=getRandomKey(nums, left, right);
int lt=left-1,rt=right+1,i=left;
//注意不是i<=right
while(i<rt)
{
//递增,注意i的更新规则
//[0,lt]:<key [lt+1,i-1]:==key [i,rt-1]:未处理 [rt,right]:>key
//>key的时候i不往后++,因为此时换来的来自未处理区域
if(nums[i]<key)swap(nums[i++],nums[++lt]);
else if(nums[i]==key)++i;
else swap(nums[i],nums[--rt]);
}
//[left,lt] [lt+1,rt-1] [rt,right]
int c=right-rt+1,b=rt-lt-1;
if(c>=K)return qsort(nums, rt, right, K);
else if(b+c>=K)return key;
else return qsort(nums, left, lt, K-c-b);
}
int getRandomKey(vector<int>&nums,int left,int right)
{
return nums[rand()%(right-left+1)+left];
}
};
七*、数据流中的中位数

维护一个大根堆,一个小根堆,始终维护堆的数量相等,或者只相差1
最后取二者top相加除以2(详解见我的这篇文章:基础算法:优先级队列-优快云博客)

#include <queue>
class Solution {
priority_queue<int> Bigheap;//大根堆存储前一半小的
priority_queue<int,vector<int>,greater<int>> Smallheap;//小根堆存储后一半大的
public:
void Insert(int num) {
//最终大根堆size-1=小根堆size
if(Bigheap.size()==Smallheap.size())
{
//先判断空,空也直接插入,但是取不到top会报段错误
if(Bigheap.empty()||num<Bigheap.top())Bigheap.push(num);
else
{
Smallheap.push(num);
Bigheap.push(Smallheap.top());
Smallheap.pop();
}
}
//大根堆size比小根堆size大1
//最终size相等
else
{
//因为是大根堆先插入,我们先判断新插入的会不会比大根堆先插入的更小
//更小就把数字迁到小根堆
if(num<Bigheap.top())
{
Bigheap.push(num);
Smallheap.push(Bigheap.top());
Bigheap.pop();
}
else Smallheap.push(num);
}
}
double GetMedian() {
if(Bigheap.size()>Smallheap.size())return Bigheap.top()*1.0;
else return (Bigheap.top()+Smallheap.top())/2.0;
}
};
八*、表达式求值

直接看官方的解法吧

#include<cctype>
#include <vector>
class Solution {
public:
//第二个下标方便处理()内部内容,出递归后更新下标位置
vector<int> function(string s,int index)
{
stack<int> st;
int num=0,i=index;
char op='+';
for(;i<s.length();++i)
{
//如果是数字,处理这一层的数字
if(isdigit(s[i]))
{
num=num*10+s[i]-'0';
//如果还没到达末尾,跳过后续的入栈
if(i!=s.length()-1)continue;
}
//如果是左括号,进入递归,将括号内结果当作一个整体
if(s[i]=='(')
{
vector<int> res=function(s, i+1);
num=res[0];
i=res[1];
if(i!=s.length()-1)continue;
}
//入栈
switch (op) {
case '+':
st.push(num);
break;
case '-':
st.push(-num);
break;
case '*':
int tmp=st.top();
st.pop();
st.push(tmp*num);
break;
}
//当前数字处理完毕,num置零
num=0;
//结束左括号进入的递归
if(s[i]==')')break;
//运行到这就说明s[i]是符号,这一层的符号是s[i]
else op=s[i];
}
int sum=0;
while(!st.empty())
{
sum+=st.top();
st.pop();
}
return vector<int> {sum,i};
}
int solve(string s) {
return function(s,0)[0];
}
};
完。
1189



被折叠的 条评论
为什么被折叠?



