stack

2021-06-19

Stack栈,是一种后进先出的数据结构,在进行递归的时候,很适合使用。这里总结了两篇Stack 1, Stack 2

stack,queue属于STL,但不是container,是属于container adapter。可以使用vector,list,deque实现。支持:

Push, pop, top, size, empty, swap.

可以使用其它的容器初始化:

std::stack<int, std::vector<int>> third;
std::stack<int, std::list<int>> third;
  • Monotonic stack
// 42. Trapping Rain Water
// Ref: https://leetcode-cn.com/problems/trapping-rain-water/solution/42-jie-yu-shui-shuang-zhi-zhen-dong-tai-wguic/
int trap(vector<int>& heights) {
  if (heights.empty()) return 0;
  stack<int> record;
  int count = 0;
  for (int i = 0; i < heights.size(); ++i) {
    while (!record.empty() && heights[i] >= heights[record.top()]) {
      const int mid = record.top();
      record.pop();
      if (record.empty()) break;
      const int left = record.top();
      count += (min(heights[left], heights[i]) - heights[mid])*
               (i - left - 1);
    }
    if(record.empty() || heights[record.top()] > heights[i]) {
      record.push(i);
    } 
  }
  return count;
}
  
// 84. Largest Rectangle in Histogram
// Ref: https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/84-zhu-zhuang-tu-zhong-zui-da-de-ju-xing-6cb8/
// https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/bao-li-jie-fa-zhan-by-liweiwei1419/
// https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/xiang-jie-dan-diao-zhan-bi-xu-miao-dong-by-sweetie/
// https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/xiang-jie-dan-diao-zhan-bi-xu-miao-dong-by-sweetie/
// https://leetcode-cn.com/problems/largest-rectangle-in-histogram/solution/xiang-xi-jie-shao-dan-diao-zhan-de-li-jie-he-shi-y/
int largestRectangleArea(vector<int>& heights) {
  stack<int> record;
  int max_area = 0;
  heights.insert(heights.begin(), 0);
  heights.emplace_back(0);
  record.push(0);
  for (int i = 1; i < heights.size(); ++i) {
    while (heights[record.top()] > heights[i]) {
      const int mid = record.top();
      record.pop();
      max_area = max(max_area, (i - record.top() - 1) * heights[mid]);
    }
    record.push(i);
  }
  return max_area;
}

// 85. Maximal Rectangle
// DP + brute force.
// Reference: https://leetcode-cn.com/problems/maximal-rectangle/solution/maximal-rectangle-by-ikaruga-idh2/
int maximalRectangle(vector<vector<char>>& matrix) {
  if (matrix.empty() || matrix[0].empty()) return 0;
  vector<vector<int>> mat(matrix.size() + 1, vector<int>(matrix[0].size() + 1, 0));
  for (int i = 0; i < matrix.size(); ++i) {
    for (int j = 0; j < matrix[0].size(); ++j) {
      mat[i+1][j+1] = 
        matrix[i][j] == '0'? 0:mat[i+1][j] + 1;
    }
  }
  int max_area = 0;
  for (int i = 1; i < mat.size(); ++i) {
    for (int j = 1; j < mat[0].size(); ++j) {
      int min_len = mat[i][j];
      int cur_area = min_len;
      int k = i - 1;
      while (k > 0) {
        if (!mat[k][j]) break;
        min_len = min(min_len, mat[k][j]);
        cur_area = max(cur_area, min_len * (i - k + 1));
        --k;
      }
      max_area = max(max_area, cur_area);
    }
  }
  return max_area;
}
// Monotonic stack.
int maximalRectangle(vector<vector<char>>& matrix) {
  if (matrix.empty() || matrix[0].empty()) return 0;
  vector<int> heights(matrix[0].size() + 2, 0);
  int max_area = 0;
  for (int i = 0; i < matrix.size(); ++i) {
    for (int j = 0; j < matrix[0].size(); ++j) {
      if (matrix[i][j] == '0') {
        heights[j+1] = 0;
      } else {
        ++heights[j+1];
      }
    }
    max_area = max(max_area, MaxHistogramArea(heights));
  }
  return max_area;
}
int MaxHistogramArea(const vector<int>& heights) {
  stack<int> record;
  record.push(heights[0]);
  int max_area = 0;
  for (int i = 1; i < heights.size(); ++i) {
    while (heights[record.top()] > heights[i]) {
      const int mid = record.top();
      record.pop();
      max_area = max(max_area, heights[mid] * (i - record.top() - 1));
    }
    record.push(i);
  }
  return max_area;
}  
  
// 316.

// 402.

// 496.

// 581.

// 739.

// 901.

// 1776. Car Fleet II
// https://leetcode-cn.com/problems/car-fleet-ii/solution/che-dui-ii-si-lu-tui-dao-zhan-de-ying-yo-jqym/
// 这里面最重要的逻辑转换就是如果没法追上右边第一辆的车,那么就是
vector<double> getCollisionTimes(vector<vector<int>>& cars) {
  vector<double> ans(cars.size(), -1.0);
  stack<int> record;
  record.push(cars.size()-1);
  for (int i = cars.size()-2; i >= 0; --i) {
    while (!record.empty()) {
      if (cars[record.top()][1] >= cars[i][1] || 
          ans[record.top()] > 1e-7 && 1.0*(cars[record.top()][0] - cars[i][0]) > 
                (cars[i][1] - cars[record.top()][1])* ans[record.top()]) 
        record.pop();
      else break;  
    }
    if (!record.empty()) {
      ans[i] = 1.0*(cars[record.top()][0] - cars[i][0]) / 
              (cars[i][1] - cars[record.top()][1]);
    }
    record.push(i);
  }
  return ans;
}