单调栈
具体题目
- leetcode 84. 柱状图中最大的矩形
- leetcode 42. 接雨水
算法用途
可以在O(N)时间内找到一组数中的每一个数最近的小于它的数。
比如3,5,6,4,1,8
5左边第一个小于它的数是3
6左边第一个小于它的数是5
4左边第一个小于它的数是3
1左边第一个小于它的数没有
8左边第一个小于它的数是1
单调栈算法可以在O(N)时间内求出答案 3,5,3,null,1
算法描述
算法思想
单调栈在遍历过程中不断压入符合单调性的元素,如果有一个元素X能破坏单调栈内的单调性,则从单调栈中弹出若干元素。弹出这些元素后再压入元素X,单调栈内能维持单调性。一般弹出元素的过程就是执行动作的过程。
算法原理
如果j0<j1 并且num[j0]>num[j1],那么对于任意一个后面的数num[i],(i>j1)。小于num[i]的数一定不会是num[j0],(如果num[j1]小于num[i],那么答案可能为num[j1]。j1比j0更接近i。如果num[j1]>num[i],那么num[j0]也一定大于num[i],而我们要找的是第一个小于num[i]的数,所以这种情况下num[j0]一定不是我们寻找的数)
算法步骤
从左向右遍历。遍历过程中维护一个栈,栈记录的是数组的引索。
遍历到第0个数:3。 由于栈空,引索0压栈。 意味着在3左边比3小的数不存在。
遍历到第1个数:5。 由于5比栈顶引索对应的数字3大,引索1压栈。 意味着在5左边比5小的数是3。
遍历到第2个数:6。 由于6比栈顶引索对应的数字5大,引索2压栈。 意味着在6左边比6小的数是5。
遍历到第3个数:4。 由于4比栈顶引索对应的数字6小,引索2出栈; 由于4比栈顶引索对应的数字5小,引索1出栈。 由于4比栈顶引索对应的数字3大, 引索3压栈。意味着在4左边比4小的数是3。而且由于4的存在,比他它的数5和6不会成为后面遍历的数的答案。
……
这样,就找到了每个数左边比这个数小的数是哪个了。由于每个数最多进栈1次,出栈1次。所以遍历整个数组只需要O(n)的时间。
算法感想
该算法动态地判断不会成为结果的数,从而减少检索量。