子数组的最小值的贡献

LeetCode907

非常经典的一道题,思想也很经典,核心点在于预处理出当前点为最小值时的辐射范围

int n = nums.size();
vector<int> left(n, -1);
vector<int> right(n, n);
// 维护递增栈
stack<int> stackUp;
for (int i = 0; i < n; ++i) {
  // 栈顶对应值比当前值大,说明栈顶的右侧第一个最小值是i
  while (!stackUp.empty() && nums[stackUp.top()] >= nums[i]) {
    right[stackUp.top()] = i;
    stackUp.pop();
  }
  // 此时如果栈非空,则栈顶值是i左侧的第一个最小值是栈顶
  if (!stackUp.empty()) {
    left[i] = stackUp.top();
  }
  // 更新递增栈
  stackUp.emplace(i);
}

在得到了left和right数组后,可得当前点i的辐射范围是(left[i], right[i]), 注意是左开右开。
当前点i的最终贡献为nums[i] * (i - left[i]) * (right[i] - i)

posted @ 2022-05-24 21:58  miyanyan  阅读(27)  评论(0编辑  收藏  举报