题目链接:两个链表的第一个公共结点
思路:如果两个链表有公共结点,则第一个公共结点以及之后的所有结点都是重合的,即至少它们的尾结点是重合的。因为两个链表长度不一定相等,所以同步遍历时不能保证两个链表同时到达尾结点。假设一个链表比另一个多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