题目

给定一个不含有重复值的数组arr,找到每一个i位置左边和右边离i位置最近且值比arr[i]小的位置。返回所有位置相应的信息。

类似题目:132模板https://leetcode-cn.com/problems/132-pattern/

image.png
-1表示不存在。
要求:时间复杂度:O(n)

解答

单调栈:指栈内元素都是严格单调递增或者单调递减的。
如果有新元素入栈,栈调整过程中会破坏所有单调性的栈顶元素出栈,并且出栈的元素不会再次入栈。
由于每个元素只有一次入栈和出栈的操作,所以单调栈的维护时间复杂度是O(n)。

单调栈的性质:

  • 单调栈里的元素具有单调性;
  • 递减栈(从栈顶到栈底递减)中可以找到元素左右两侧比自身大的第一个元素
  • 同理,递增栈有相似的性质

本题实现O(n^2)很简单,每个位置分别向左向右遍历。

思考:如果优化,做到时间复杂度O(n)。

代码

  1. def getNearlessNoRepeat(arr):
  2. ans = [None] * len(arr)
  3. stack = []
  4. for i in range(len(arr)):
  5. while stack and arr[stack[-1]] > arr[i]:
  6. popIndex = stack.pop()
  7. if len(stack) == 0:
  8. leftLessIndex = -1
  9. else:
  10. leftLessIndex = stack[-1]
  11. ans[popIndex] = (leftLessIndex, i)
  12. stack.append(i)
  13. while len(stack) > 0:
  14. popIndex = stack.pop()
  15. if len(stack) == 0:
  16. leftLessIndex = -1
  17. else:
  18. leftLessIndex = stack[-1]
  19. ans[popIndex] = (leftLessIndex, -1)
  20. return ans
  21. arr = [3, 4, 1, 5, 6, 2, 7]
  22. print(getNearlessNoRepeat(arr))