-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathIntersectionNodeOfTwoLinkedLists.java
163 lines (151 loc) · 3.89 KB
/
IntersectionNodeOfTwoLinkedLists.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
package io.ziheng.codinginterviews;
import java.util.HashSet;
import java.util.Set;
/**
* 单链表节点
*/
class ListNode {
public int val;
public ListNode next;
public ListNode(int val) {
this.val = val;
this.next = null;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
/**
* 剑指 Offer 面试题 52:两个链表的第一个公共节点
*
* 题目描述:
* 输入两个链表,找出它们的第一个公共节点。
*
* 知识点:["链表"]
*/
public class IntersectionNodeOfTwoLinkedLists {
/**
* 剑指 Offer 面试题 52:两个链表的第一个公共节点
*
* @param pHeadA
* @param pHeadB
* @return ListNode
*/
public ListNode findFirstIntersectionNode(ListNode pHeadA, ListNode pHeadB) {
if (pHeadA == null || pHeadB == null) {
return null;
}
// 暴力法
// return findFirstIntersectionNodeBruteForce(pHeadA, pHeadB);
// 哈希表法
// return findFirstIntersectionNodeHashing(pHeadA, pHeadB);
// 双指针法
return findFirstIntersectionNodeTwoPointer(pHeadA, pHeadB);
}
/**
* 双指针法
* 让长链表先走过两链表长度差的步长,再进行节点重合判断。
*
* 时间复杂度:O(n)
* 空间复杂度:O(n)
*
* @param pHeadA
* @param pHeadB
* @return ListNode
*/
private ListNode findFirstIntersectionNodeTwoPointer(
ListNode pHeadA, ListNode pHeadB) {
int lenA = findLength(pHeadA);
int lenB = findLength(pHeadB);
ListNode pA = pHeadA;
ListNode pB = pHeadB;
if (lenA > lenB) {
int diff = lenA - lenB;
for (int i = 0; i < diff; i++) {
pA = pA.next;
}
} else {
int diff = lenB - lenA;
for (int i = 0; i < diff; i++) {
pB = pB.next;
}
}
while (pA != null) {
if (pA == pB) {
return pA;
}
pA = pA.next;
pB = pB.next;
}
return null;
}
private int findLength(ListNode head) {
int cnt = 0;
ListNode currentNode = head;
while (currentNode != null) {
cnt++;
currentNode = currentNode.next;
}
return cnt;
}
/**
* 哈希表法
*
* 时间复杂度:O(n + m)
* 空间复杂度:O(n)
*
* @param pHeadA
* @param pHeadB
* @return ListNode
*/
private ListNode findFirstIntersectionNodeHashing(
ListNode pHeadA, ListNode pHeadB) {
Set<ListNode> aSet = new HashSet<>();
ListNode currentNode = pHeadA;
while (currentNode != null) {
aSet.add(currentNode);
currentNode = currentNode.next;
}
currentNode = pHeadB;
while (currentNode != null) {
if (aSet.contains(currentNode)) {
return currentNode;
}
currentNode = currentNode.next;
}
return null;
}
/**
* 暴力法
*
* 时间复杂度:O(n * m)
* 空间复杂度:O(1)
*
* @param pHeadA
* @param pHeadB
* @return ListNode
*/
private ListNode findFirstIntersectionNodeBruteForce(
ListNode pHeadA, ListNode pHeadB) {
ListNode pA = pHeadA;
while (pA != null) {
if (hasNode(pA, pHeadB)) {
return pA;
}
pA = pA.next;
}
return null;
}
private boolean hasNode(ListNode node, ListNode head) {
ListNode currentNode = head;
while (currentNode != null) {
if (node == currentNode) {
return true;
}
currentNode = currentNode.next;
}
return false;
}
}
/* EOF */