1. 程式人生 > >劍指Offer 兩個鏈表的第一個公共結點

劍指Offer 兩個鏈表的第一個公共結點

color code wal get www ret 時間復雜度 common 相同

  題目鏈接:兩個鏈表的第一個公共結點

  思路:如果兩個鏈表有公共結點,則第一個公共結點以及之後的所有結點都是重合的,即至少它們的尾結點是重合的。因為兩個鏈表長度不一定相等,所以同步遍歷時不能保證兩個鏈表同時到達尾結點。假設一個鏈表比另一個多k個結點,先在長的鏈表上遍歷k個結點即尾部對齊,再同步遍歷,保證同時到達尾結點,即同時到達第一個公共結點。也就是說,同步遍歷時第一個相同結點就是第一個公共結點。

  步驟:

  1 如果兩個鏈表至少有一個是空,則返回null。

  2 分別獲取兩個鏈表的長度len1和len2。

  3 通過比較兩個鏈表的長度來獲取長度差k,並使長鏈表遍歷k個結點。

  4 通過同步遍歷來查找第一個公共結點,如果查找到公共結點,則返回該結點。

  5 返回null。

  時間復雜度:O(len1+len2)。

  Java代碼:

 1 /*
 2 public class ListNode {
 3     int val;
 4     ListNode next = null;
 5 
 6     ListNode(int val) {
 7         this.val = val;
 8     }
 9 }*/
10 public class Solution {
11     public ListNode FindFirstCommonNode(ListNode list1, ListNode list2) {
12
// 如果兩個鏈表至少有一個是空,則返回null 13 if (list1 == null || list2 == null) { 14 return null; 15 } 16 17 // 分別獲取兩個鏈表的長度len1和len2 18 int len1 = getListLength(list1); 19 int len2 = getListLength(list2); 20 21 // 通過比較兩個鏈表的長度來獲取長度差k,並使長鏈表遍歷k個結點
22 if (len1 > len2) { 23 list1 = walkSteps(list1, len1 - len2); 24 } else { 25 list2 = walkSteps(list2, len2 - len1); 26 } 27 28 // 通過同步遍歷來查找第一個公共結點,如果查找到公共結點,則返回該結點 29 while (list1 != null) { 30 if (list1 == list2) { 31 return list1; 32 } 33 34 list1 = list1.next; 35 list2 = list2.next; 36 } 37 38 // 返回null 39 return null; 40 } 41 42 // 獲取鏈表長度 43 private int getListLength(ListNode list) { 44 int len = 1; 45 while (list.next != null) { 46 list = list.next; 47 len++; 48 } 49 50 return len; 51 } 52 53 // 獲取當前結點走了k步之後的結點 54 private ListNode walkSteps(ListNode list, int k) { 55 while (k-- > 0) { 56 list = list.next; 57 } 58 59 return list; 60 } 61 }

  參考資料

  [編程題]兩個鏈表的第一個公共結點

  《2017年數據結構聯考復習指導》P46-47

劍指Offer 兩個鏈表的第一個公共結點