双指针内容总结
双指针是一种重要的算法思想 它可以通过指针的移动去除无效状态 从而简化时间复杂度
双指针问题类型
- 快慢指针
此类问题 通常是设置两个指针i
,j
i
指针负责扫描序列j
指针负责维护某些信息 结束条件为快指针扫描完整个序列 比如 删除数组重复项-2 这里i
负责遍历序列,枚举元素j
负责维护写入的位置 这样 从0
到j-1
便是数组的有效长度 再比如删除链表倒数第n个节点 设置两个指针i
j
开始两张均指向虚拟头节点 之后将j
指针向右移动n
个位置 使两指针距离之间相差n
之后 共同移动 直到i
指针指向nullptr
那j
即为链表倒数第n个元素的前驱 - 首尾指针
此类问题 两个指针通常指向序列的开头和结尾 现根据现有的i
j
组合 计算出一个解 之后 通过问题的性质 来移动指针 消除不可能成为答案的i
j
组合 比如i++
会使得所以左端点为i
的组合均被消去j--
会使得所有以j
右端点的组合被消去 在分析时,可以假设一端指针不动,让另一端指针移动 考虑能否得到最优解 若不能 即移动指针 直到i<j
这样 便大幅较小了复杂度 可以在O(n)
时间内解决问题
比如三数之和 这里我们先将序列进行排序 使得其可以用双指针进行进行简化 从前向后枚举nums[i]
令left
为i+1
right
为len-1
其实就是在i
j
组合内求nums[i]+nums[j]
为一个定值 那当此时的nums[i]+nums[j]
为目标值时 显然i
不动 ,j
向左移动会使值变小j
不动i
向右移会使值变大 均不可能产生解 因此i++,j--
同理 若小于目标值 那应当i++
消除i
和j
的所有组合 应为它们不可能产生解 若大于目标值 即j--
再比如 盛最多水的容器 这个问题 看似直接移动i
或j
都无法消除多余组合 应为高是乱序的,而且面积的计算和横坐标也有关 但问题的关键是高度取决于较小的一方 那高度较高的一方无论如何移动指针 都无法更新最优解 那以较短一方指针为边界的组合均为无效状态 那较短方指针++ 即消除了这些无效组合。