題目描述
輸入兩個鏈表,找出它們的第一個公共結點。git
# -*- coding: utf-8 -*- # @Time : 2019-07-12 22:20 # @Author : Jayce Wong # @ProjectName : job # @FileName : findFirstCommonNode.py # @Blog : https://blog.51cto.com/jayce1111 # @Github : https://github.com/SysuJayce class ListNode: def __init__(self, x): self.val = x self.next = None class Solution: """ 兩個單向鏈表的第一個公共節點,若是存在這樣的公共節點,那麼這兩個鏈表從該節點開始剩餘的節點都是 同樣的。 解法1: 對於第一個鏈表,遍歷其全部節點,在掃描到第x個節點的時候,從第二個鏈表中遍歷全部節點,若是存在 一個和節點x同樣的節點,那麼節點x就是第一個公共節點。 這種解法的時間複雜度爲O(n^2) 解法2: 前面說到若是兩個單向鏈表存在公共節點,那麼從第一個公共節點開始到最後一個節點都是公共節點。 所以,若是咱們能從兩個鏈表的末尾節點開始遍歷,找到最後一個相同的節點,那麼這個節點就是第一個 公共節點。可是這個單向鏈表不支持反向遍歷,所以咱們能夠利用棧的性質,維護兩個輔助棧,分別保存 兩個鏈表的節點,而後每次比較這兩個輔助棧的棧頂元素。最後咱們就能在O(n)的時間複雜度內解決問題。 解法3: 雖然解法2的時間複雜度已經很優了,可是仍須要用到輔助空間,其實藉助快慢指針的思想,咱們能夠避免 這樣的額外空間開銷。先計算兩個鏈表的長度,而後先移動長鏈表的指針,使得長短鏈表的指針距離各自的 末尾有相同的距離,而後開始同時移動兩個指針,直到出現兩指針指向的節點相同爲止,那麼這個相同節點 就是第一個公共節點。 """ def FindFirstCommonNode(self, pHead1, pHead2): # 記錄兩個鏈表的長度 len1 = len2 = 0 pNode1 = pHead1 pNode2 = pHead2 while pNode1: pNode1 = pNode1.next len1 += 1 while pNode2: pNode2 = pNode2.next len2 += 1 # 肯定哪一個鏈表是長鏈表,哪一個鏈表是短鏈表 if len1 > len2: pLong = pHead1 pShort = pHead2 else: pLong = pHead2 pShort = pHead1 # 調整長鏈表的指針,使得長短鏈表距離各自末尾節點距離相同 diff = abs(len1 - len2) for i in range(diff): pLong = pLong.next # 同時移動長短鏈表指針,當出現第一個相同節點(即第一個公共節點)的時候,返回這個節點 while pLong: if pLong == pShort: return pLong pLong = pLong.next pShort = pShort.next # 若是不存在公共節點,返回空指針 return None