通常状况下,遍历数组(或者字符串)操做,都是采用单指针从前日后或者从后往前依次访问数组(或者字符串)中的元素。 而对于如下状况,只采用单指针处理,则会徒增时间复杂度和空间复杂度:前端
例如:找到两个数使得它们相加之和等于目标数,采用单指针处理,则须要嵌套循环,使得时间复杂度增加为 O(n^2);算法
再例如:翻转数组,采用单指针处理,则须要额外内存空间,使得空间复杂度增加为 O(n);数组
利用双指针技巧则能够优化上述解决方案:markdown
第一个例子:能够先对采用数组进行排序预处理,再建立先后指针向中间遍历,遍历的时间复杂度为 O(n),总体时间复杂度主要取决于排序算法,一般为 O(nlogn);app
第二个列子:一个指针负责遍历,另一个指针负责交换元素,从而使得空间复杂度为 O(1);函数
双指针没有复杂的定义,总结起来主要处理两类问题:oop
将嵌套循环转化为单循环问题;post
经过指针记录状态,从而优化空间复杂度;学习
下面的实战分析会让你感觉双指针的威力。优化
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。函数应该返回这两个下标值 index1和index2,其中index1 必须小于 index2。
这道题目采用单指针的作法只能经过嵌套循环枚举全部两数之和的方法来解决,时间复杂度为 O(n^2)。
恰巧本题中的数组已是有序数组,那么直接建立先后指针:
若是两数以后大于 target,尾指针向前移动;
若是两数之和小于 target,头指针向后移动;
上述代码利用双指针技巧成功地将时间复杂度下降为 O(n)。
const twoSum = (numbers, target) => {
const max = numbers.length
let start = 0
let end = max -1
while(start< end) {
const sum = numbers[start] + numbers[end]
if(sum === target)
{
return [start, end]
}
if(sum > target){
end --
continue
}
if(sum < target) {
start++
continue
}
}
}
// 这个文章里的两数之和是第一篇文章的升级版
// 时间复杂度:O(n)
// 空间复杂度: O(1) 比map 更加的高级
复制代码
给定一个排序数组,你须要在 原地 删除重复出现的元素,使得每一个元素只出现一次,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成。
示例 1:给定数组 nums = [1,1,2],函数应该返回新的长度 2, 而且原数组 nums 的前两个元素被修改成 1, 2。
你不须要考虑数组中超出新长度后面的元素。
示例 2:给定 nums = [0,0,1,1,1,2,2,3,3,4],函数应该返回新的长度 5, 而且原数组 nums 的前五个元素被修改成 0, 1, 2, 3, 4。
说明:
为何返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
解题思路: 使用快慢指针来记录遍历的坐标。开始时这两个指针都指向第一个数字,若是两个指针指的数字相同,则快指针向前走一步。若是不一样,则两个指针都向前走一步,当快指针走完整个数组后,慢指针当前的坐标加 1 就是数组中不一样数字的个数。
const removeDuplicates = nums => {
const max = nums.length
if (max === 1) {
return nums
}
let slow = 0
for (let fast = 1; fast < max; fast++) {
if (nums[fast] !== nums[slow]) {
slow++
nums[slow] = nums[fast]
}
}
return slow + 1;
}
// 时间复杂度:O(n)
// 空间复杂度:O(1)
复制代码
刷题打卡次日,选择双指针,学习了提高代码效率的重要手段之一:前一次优化后的哈希map解法就是采用了空间换时间的方法。 可是双指针能够更加优化,可是前提是数组必须为有序的,今天又刷了力扣的第26题,一块儿加油哇~
若是你以为这篇内容对你挺有有帮助的话: 点赞支持下吧,让更多的人也能看到这篇内容(收藏不点赞,都是耍流氓 -_-)关注公众号给npy的前端秘籍,咱们一块儿学习一块儿进步。 以为不错的话,也能够阅读其余文章(感谢朋友的鼓励与支持🌹🌹🌹)
参考: 双指针技巧Easy篇