題目
編寫一個程序,找到兩個單鏈表相交的起始節點。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
//此處編寫代碼
}
例如,下面的兩個鏈表:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
在節點 c1 開始相交。
注意:
- 如果兩個鏈表沒有交點,返回 null.
- 在返回結果後,兩個鏈表仍須保持原有的結構。
- 可假定整個鏈表結構中沒有循環。
- 程序儘量滿足 O(n) 時間複雜度,且僅用 O(1) 內存。
題解
思路: 有兩種思路,第一種是先遍歷A鏈表,將最後一個節點的next指向A的頭結點,然後用鏈表判環的方式去找環的起點即兩個鏈表的交叉點,最後要把環斷開還原鏈表。鏈表判環見141. 環形鏈表。
第二種思路是先遍歷兩個鏈表,算出兩鏈表長度的差值N,然後較長鏈表先走N步然後兩鏈表同時向後遍歷,遇上相同節點即爲相交點。
note:注意鏈表爲空的情況。最後兩鏈表一定會交於NULL。
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if (__builtin_expect(!!(!headA || !headB), 0)) return NULL;
int lena = 0, lenb = 0, len;
struct ListNode *p = headA, *q = headB;
while (p != NULL) {
lena++;
p = p->next;
}
while (q) {
lenb++;
q = q->next;
}
p = headA;
q = headB;
if (lena > lenb) {
len = lena - lenb;
while (len--) {
p = p->next;
}
} else {
len = lenb - lena;
while (len--) {
q = q->next;
}
}
while (p != q) {
p = p->next;
q = q->next;
}
return p;
}
ps : 這題代碼寫的好醜