首页 > 代码库 > 【原创】leetCodeOj --- Intersection of Two Linked Lists 解题报告(经典的相交链表找交点)
【原创】leetCodeOj --- Intersection of Two Linked Lists 解题报告(经典的相交链表找交点)
题目地址:
https://oj.leetcode.com/problems/intersection-of-two-linked-lists/
题目内容:
Write a program to find the node at which the intersection of two singly linked lists begins.
For example, the following two linked lists:
A: a1 → a2 ↘ c1 → c2 → c3 ↗ B: b1 → b2 → b3
begin to intersect at node c1.
Notes:
- If the two linked lists have no intersection at all, return
null
. - The linked lists must retain their original structure after the function returns.
- You may assume there are no cycles anywhere in the entire linked structure.
- Your code should preferably run in O(n) time and use only O(1) memory.
方法:
首先,既然是时间复杂度O(n),那么就不能一个一个点那样试;
其次,既然空间复杂度要求O(1),既然就不能用stack或者unordered_map之类的数据结构来找链表交点。
那么,我们需要一个比较酷炫的trick来找交点。
先转化问题:
假设有A、B两条链表相交,请求出交点到A链表头结点的距离。(所谓距离,就是头结点走几次能到)
先看具体求法:
0、计算A链表的长度lenA
1、计算B链表的长度lenB
2、逆转A链表(关键)
3、重新计算B链表的长度newLenB
4、返回result = (newLenB - lenB + lenA - 1) / 2
具体到这道题,还需要把A链表又逆转回来,因为你不能更改链表原来的结构。然后重新读取链表,返回第result个结点就OK了。
那么这具体求法究竟是怎么来的?
自己动手试试就明白了。其实就是算出A链表结点在交点旁边的分布数,画图太麻烦了,如果有时间再补一个,或者谁不理解回复一下我就补
全部代码:
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */class Solution {public: ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) { if (headA == NULL || headB == NULL) return NULL; int addressA; // fin of A. int addressB; // fin of B. int lenA = countLength(headA,&addressA); int lenB = countLength(headB,&addressB); if (addressA != addressB) // if has a intersect return NULL; ListNode *tmpHeadA = (ListNode *)addressA; // to store headA‘s tail for reverse. reverseLink(headA); int newLenB = countLength(headB,&addressB); int toNew = findCount(lenA,lenB,newLenB); reverseLink(tmpHeadA); return findNthNode(headA,toNew); } int findCount(int lenA,int lenB,int newLenB) { int gap = newLenB - lenB; return (gap + lenA - 1) / 2; } ListNode *findNthNode(ListNode *head,int toN) { int count = 0; while (toN != count) { head = head->next; count ++; } return head; } int countLength(ListNode *head,int *fin) { int count = 0; while (head) { *fin = (int)head; head = head->next; count ++; } return count; } void reverseLink(ListNode *head) { ListNode *pre = NULL; ListNode *now = head; ListNode *nxt = head->next; while (1) { now->next = pre; pre = now; now = nxt; if (nxt) nxt = nxt->next; else break; } }};
【原创】leetCodeOj --- Intersection of Two Linked Lists 解题报告(经典的相交链表找交点)