数据结构1-2. 链表中的双指针
经典问题:判断一个链表是否有环。
可以使用哈希表来解决该问题,即将链表每个结点的指针存入哈希表,出现重复的地址即说明链表中存在环。
python代码如下 时间复杂度O(N) 空间复杂度O(N)
def hasCycle(head): cur = head if cur is None: return False hash1 = set() hash1.add(cur) while cur.next is not None: cur = cur.next if cur in hash1: return True hash1.add(cur) return False
但是,使用双指针是一个更加有效的方案,通过设定步长不同的两个快慢指针,对链表进行遍历,会有以下两种情况:
- 如果没有环,快指针将停在链表的末尾
- 如果有环,快指针会与慢指针相遇
比较安全的选择是慢指针每次走一步,快指针每次走两步,快指针比慢指针每次多一步,这样对于长度为M的链表,在经过M次迭代后,快指针一定能与慢指针相遇。
python代码如下 时间复杂度O(N) 空间复杂度O(1)
class Solution(object): def hasCycle(head): """ :type head: ListNode :rtype: bool """ slow = head fast = head while fast is not None and fast.next is not None and fast.next.next is not None: slow = slow.next fast = fast.next.next if slow == fast: return True return False
如果问题限制结点数量,甚至可以循环,当超过结点数量时说明有环 0 0
问题2:如果链表存在环,找到入环的结点
同理,哈希表会很简单,但是空间复杂度是O(N),python代码如下
def hasCycle(head): cur = head if cur is None: return False hash1 = set() hash1.add(cur) while cur.next is not None: cur = cur.next if cur in hash1: return cur hash1.add(cur) return False
也可用快慢指针来实现找入环的结点,如图所示

对于上图所示的链表,慢指针每次走一步,走过的距离为 D + S1 ,快指针每次走两步,走过的距离为 n * (S1 + S2) + D,快指针走的路程为慢指针的2倍,则有
2 * (D + S1) = n * (S1 + S2) + D
整理得 D = ( n - 1) * ( s1 + s2 ) + s2
即起始点到入环点得距离与首次相遇点绕环 ( n - 1 ) 圈后再回到入环点得距离相同。
双指针找入环点:快慢指针找到环内首次相遇点后,从起始点和首次相遇点每次前进一,再次相遇的点就是入环点。
python代码如下
def findInputCycle(head): slow = head fast = head while fast is not None and fast.next is not None and fast.next.next is not None: slow = slow.next fast = fast.next.next if slow == fast: con = fast slow = head while con != slow: slow = slow.next con = con.next return con return None

浙公网安备 33010602011771号