博客园  :: 首页  :: 新随笔  :: 管理

4.堆/栈/队列

Posted on 2021-03-29 21:37  wsg_blog  阅读(87)  评论(0编辑  收藏  举报

Index LeetCode

堆,大顶堆priority_queue min、小顶堆,priority_queue<int, vector, greater> max;
栈,先进后出结构,在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];
}