Index LeetCode
堆,大顶堆priority_queue
栈,先进后出结构,在c++中用stack来表示;
队列,先进先出结构,在c++中用queue来表示
BM42.用两个栈实现队列(232.用栈实现队列)[easy]
输入:["MyQueue","push","push","peek","pop","empty"] , [[],[1],[2],[],[],[],[]]
输出:[null, null, null, 1, 1, false]
解释:
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.pop(); // return 1, queue is [2]
双栈法
stack<int> stk1, stk2;
void push(int x){
stk1.push(x);
}
int pop(){
int res=-1;
if(stk1.empty()) return res;
while(!stk1.empty()){
stk2.push(stk1.top());
skt1.pop();
}
res=stk2.top();
stk2.pop();
while(!stk2.empty()){
stk1.push(stk2.top());
stk2.pop();
}
return res;
}
BM43.包含min函数的栈(剑指Offer30.包含min函数的栈)[easy]
说明:定义栈的数据结构,请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中,调用 min、push 及 pop 的时间复杂度都是 O(1)
双栈法
stack<int> s1,s2;
void push(int x){
s1.push(x);
if(s2.empty() || s2.top() > x){
s2.push(x);
}else{
s2.push(s2.top());
}
}
void pop(){
s1.pop();
s2.pop();
}
int top(){
return s1.top();
}
int min(){
return s2.top();
}
BM44.有效括号序列(20.有效的括号)[easy]
输入:s="()[]{}", s="([)]"
输出:ture, false
bool isVaild(string s){
stack<char> stk;
for(char c:s){
if(stk.empty() || c=='(' || c=='[' || c=='{'){
stk.push(c);
}else if(stk.top()=='(' && c==')' || stk.top()=='[' && c==']' || stk.top=='{' && c=='}'){
stk.pop();
}else{
return false;
}
}
return stk.empty();
}
BM45.滑动窗口的最大值(239.滑动窗口的最大值)[hard]
输入:nums=[1,3,-1,-3,5,3,6,7],k=3
输出:[3,3,5,5,6,7]
滑动窗口的位置 最大值
[1 3 -1] -3 5 3 6 7 : 3
1 [3 -1 -3] 5 3 6 7 : 3
1 3 [-1 -3 5] 3 6 7 : 5
1 3 -1 [-3 5 3] 6 7 : 5
1 3 -1 -3 [5 3 6] 7 : 6
1 3 -1 -3 5 [3 6 7] : 7
说明:双端队列,队列头只保存最大的元素的下标
vector<int> maxSlidingWindow(vector<int>& nums, int k){
vector<int> res;
deque<int> dq;
for(int i=0; i<nums.size(); i++){
if(!dq.empty() && dq.front() == i-k){ //窗口右移,删除队列左端元素
dq.pop_front(); //双端队列左边为front()
}
while(!dq.empty() && nums[dq.back()] < nums[i]){ //保持队列中front为最大值
dq.pop_back();
}
dq.push_back(i);
if(i >= k-1){ //保存滑动窗口的最大值
res.push_back(nums[dq.front()]);
}
}
return res;
}
BM46.最小的K个数(剑指Offer40.最小的K个数)[medium]
输入:nums=[3,2,1],k=2; nums=[0,1,2,1],k=1
输出:[1,2]或[2,1]; [0]
快排或priority_queue(优先队列、大顶堆)
//大顶堆 优先队列 priority_queue()
vector<int> getLeastNumbers(vector<int>& arr, int k){
vector<int> res;
priority_queue<int> pri;
for(int i=0; i<arr.size(); i++){
pri.push(arr[i]);
if(pri.size() >= k){
pri.pop(); //最大值先出
}
}
while(!pri.empty()){
res.push_back(pri.top());
pri.pop();
}
return res;
}
//快排
vector<int> getLeastNumbers(vector<int>& arr, int k){
vector<int> res;
qucik_sort(arr, 0, arr.size()-1);
for(int i=0; i<k; i++) res.push_back(arr[i]);
return res;
}
void quick_sort(vector<int>& arr, int start, int end){
if(start >= end) return;
int left=start, right=end, key=arr[left];
while(left < right){
while(left<right && arr[right] >= key){
right--;
}
nums[left]=nums[right];
while(left<right && arr[left] <= key){
left++;
}
nums[right]=nums[left];
}
arr[left]=key;
quick_sort(arr, start ,right);
quck_sort(arr, right+1, end);
}
BM47.寻找第K大(215.数组中的第K个最大元素)[medium]
输入:nums=[3,2,1,5,6,4],k=2
输出:5
“二分”+快排,即快速选择
int findKthLargest(vector<int>& nums, int k){
int left=0, right=nums.size()-1, target=nums.size()-k;
while(left < right){
int ret=quick_sort(nums, left, right); //一分为二的有序下标
if(ret == target) return nums[ret];
else if(ret < tagrt) left=ret+1;
else right=ret-1;
}
return nums[left];
}
int quick_sort(vector<int>& nums, int left, int right){
int key=nums[left];
while(left < right){
while(left<right && nums[right]>=key){
right--;
}
nums[left]=nums[right];
while(left<right && nums[left]<=key){
left++;
}
nums[right]=nums[left];
}
nums[left]=key;
return left;
}
BM48.数据流中的中位数(剑指Offer41.数据流中的中位数)[hard]
输入:[5,2,3,4,1,6,7,0,8]
输出:"5.00 3.50 3.00 3.50 3.00 3.50 4.00 3.50 4.00 "
说明:如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。数据流里面不断吐出的是5,2,3...,则得到的平均数分别为5,(5+2)/2,3...
插入排序 或者 大小顶堆
//插入排序,有序插入,时间复杂度O(n)
vector<int> vec;
void addNum(int num){
if(vec.empty()){
vec.push_back(num);
}else{
int i=0;
for(; i<vec.size(); i++){
if(num <= vec[i]) break; //当num小于vec[i]
}
vec.insert(vev.begin()+i, num); //在i位置前插入num
}
}
double findMedian(){
int n=vec.size();
if(n%2){ //奇数
return (double)vec[n/2];
}else{
double a=vec[n/2];
double b=vec[n/2-1];
return (a+b)/2;
}
}
//大小顶堆
priority_queue<int> min; //大顶堆,元素数值较小
priority_queue<int, vector<int>, greater<int>> max; //小顶堆,元素值较大
void Insert(int num){
min.push(num);
max.push(min.top()); //将较小部分的最大值取出,送入较大的部分
min.pop();
if(min.size() < max.size()){ //平衡两个堆的数量
min.push(max.top());
max.pop();
}
}
double GetMedian(){
if(min.size() > max.size()){ //奇数
return (double)min.top();
}else{
return ((double)min.top()+(double)max.top())/2; //偶数
}
}
BM49.表达式求值(227.基本计算器III)[medium]
输入:"(2*(3-4))*5"
输出:-10
说明:请写一个整数计算器,支持加减乘三种运算和括号。
栈+递归
vector<int> function(string s, int index){
stack<int> stk;
int num=0;
char op='+';
int i;
for(i=index; i<s.length(); i++){
//数字转换成int数字
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 '+': //加减号先入栈
stk.push(num);
break;
case '-':
stk.push(-num);
break;
case '*': //优先计算乘号
int temp=stk.top();
stk.pop();
stk.push(temp*num);
break;
}
num=0;
if(s[i] == ')')
break;
else
op=s[i];
}
int sum=0;
while(!stk.empty()){ //栈中元素相加
sum+=stk.top()
stk.pop();
}
return vector<int> {sum, i};
}
int solve(string s){
return function(s, 0)[0];
}