算法系列, 继续日进一卒~ 之前文章传送门:
- 《温故知新 —— Sliding Window》
- 《辛辣天塞!滑动窗口之【和的最大值】&【最大值集合】》
- 《keep move!滑动窗口中位数与滑动魔方》
- 《好的,BFS,又学废了!》
- 《好的,DFS,也学废了!》
- 《从 DFS 到回溯法,再看 N 皇后问题》
- 《回溯法解决【电话号码的字母组合】问题》
本篇将带来双指针算法经典题目之:接雨水问题;
题目:
给定
n
个非负整数表示每个宽度为1
的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 示例 2: 输入:height = [4,2,0,3,2,5] 输出:9
解题思路:
解法 1 :暴力解法
直接按照题目的描述进行,对于数组中的每一个元素,我们找出下雨后水能达到的最高位置,等于两边最大高度较小值减去当前高度的值。
如果i是2 左边的最大值是索引为1的位置,这个位置值是1;右边最大值是3,当前这个位置能够存储多少水,是由短的一边决定的;对于i为3的位置来说,算上当前的索引位置的高度左边的最大值是2。
右边的最大值是还是3,此时左右两边的最小值是2 当前索引处的高度,也是2 这样一来 ans 就是0。说明索引为3的位置不能存储雨水
JS 实现如下:
/** * @param {number[]} height * @return {number} */ var trap = function (height) { let res = 0; for (let i = 0; i < height.length; i++) { let max_letf = 0; let max_right = 0; // 以当前curr 这个位置为基准,找出左边的边界的最大值 找出右边边界的最大值 for (let j = i; j >= 0; j--) { max_letf = Math.max(max_letf, height[j]) } for (let j = i; j < height.length; j++) { max_right = Math.max(max_right, height[j]) } res += Math.min(max_letf, max_right) - height[i] } return res };
解法 2 :双指针
当左边最大挡板<右边最大挡板,左边向前挺近,最终值加上当前左最大挡板-当前左指针所指值(相当于左边只要不超过右边,右边最大挡板稳定兜底,左边无脑挺近累加)大于则反之;
JS 实现:
/** * @param {number[]} height * @return {number} */ var trap = function(height) { let end = 0 let l = 0, r=height.length -1 let maxl = 0,maxr=0 while(l < r){ maxl = Math.max(height[l],maxl) maxr = Math.max(height[r],maxr) if(maxl < maxr){ end += maxl - height[l] l++ }else{ end += maxr - height[r] r-- } } return end };
时间复杂度:O(n);双指针,YYDS!
有木有觉得双指针和滑动窗口很像?后续还会带来更多关于双指针的探究~~
OK,以上就是本篇分享~ 撰文不易,点赞鼓励👍👍👍
我是掘金安东尼,公众号同名,日拱一卒、日掘一金,再会~