算法笔记——双指针

算法笔记——双指针

双指针即使用两个指针对对象进行扫描,一般有快慢指针和左右指针两种,快慢指针指从一侧开始同时向另一侧移动但是移动速度不同,左右指针则是分别从两侧向对方移动

双指针的内容不多,但是使用起来非常灵活,需要多做题体会思路

快慢指针的常见用法

1. 判断链表是否有环

单链表的特点是每个节点只知道下一个节点,所以一个指针的话无法判断链表中是否含有环的。

如果链表中不含环,那么这个指针最终会遇到空指针 null 表示链表到头了,这还好说,可以判断该链表不含环。
但是如果链表中含有环,那么这个指针就会陷入死循环,因为环形数组中没有 null 指针作为尾部节点。

经典解法就是用两个指针,一个每次前进两步,一个每次前进一步。如果不含有环,跑得快的那个指针最终会遇到 null,说明链表不含环;如果含有环,快指针最终会超慢指针一圈,和慢指针相遇,说明链表含有环。

2. 已知链表有环,返回环的起始位置

参考文章
当快慢指针相遇的时候,让其中任何一个指针指向链表头,然后让这两个指针以相同的速度前进,再次相遇时所在的节点位置就是环开始的位置。
在这里插入图片描述

  1. 第一次相遇的时候,假设慢指针slow走了k步,那么快指针一定走了2k步,也就是说slow多走了k步,这k步就是环的长度
  2. 假设相遇点与环的起点的距离为m(橙色曲线所示),那么环的起点与头节点head的距离为k-m。这是因为慢指针走了k步,这k步包含了头节点到环的起点(绿色直线部分),以及环起点到相遇点(橙色部分),而后者的距离为m,那么环的起点与头节点head的距离就为k-m。但因为整个环的长度为k,所以从相遇点继续前进k-m步(绿色曲线部分),也会到达环起点,正好与头节点和环起点的距离是一样的。
  3. 所以我们只需要把快慢指针的任意一个重新指向head,然后两个指针以向相同的速度前进,在走k-m步之后,两个指针必会相遇,而相遇点就是环的起点

3. 寻找链表的中点

类似上面的思路,我们还可以让快指针一次前进两步,慢指针一次前进一步,当快指针到达链表尽头时,慢指针就处于链表的中间位置。

4. 寻找链表的倒数第 k 个元素

我们的思路还是使用快慢指针,让快指针先走 k 步,然后快慢指针开始同速前进。这样当快指针走到链表末尾 null 时,慢指针所在的位置就是倒数第 k 个链表节点(为了简化,假设 k 不会超过链表长度)

5. 滑动窗口

例如:求不含有重复字符的最长子串
用到了滑动窗口的算法,滑动窗⼝的右边界不断的右移,只要没有重复的字符,就持续向右扩大窗口边界。⼀旦出现了重复字符,就需要缩小左边界,直到重复的字符移出了左边界,然后继续移动滑动窗口的右边界。以此类推,每次移动需要计算当前长度,并判断是否需要更新最大长度度,最终最大的值就是题目所求。

参考文章(含代码)

左右指针的常见用法

二分查找

在二分查找中我们分别定义了一个left和一个right来指向对应元素,这也属于左右指针的一种

双指针的用法还有很多,大家可以通过下面的例题继续加深理解

例题

82. 删除排序链表中的重复元素 II
15. 三数之和
844. 比较含退格的字符串
986. 区间列表的交集
11. 盛最多水的容器

猜你喜欢

转载自blog.csdn.net/shn111/article/details/123211014