-
题目:
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.
-
分析:
两个链表,如图会从某个位置开始进行重合,求出这个起始交点,需要注意的是:- 没有交点,返回NULL
- 保持原来的结构不变
- 确保没有环
- 时间复杂度为O(n),空间复杂度为O(1)
其中第一条和最后一条注意事项是最重要的,个人觉得这道题虽然在LeetCode上面是easy难度的,但是涉及到的内容还是挺不少的,因为有最后一条注意事项的限制,所以需要结合时间复杂度和空间复杂度来进行算法定制,对于本题,本文一共会列出三种算法来求解,并同时分析算法复杂度和时间复杂度。
-
三种算法的分析:
-
直接法:
遍历链表A,对于每一个遍历的节点都遍历一次链表B,判断是否有节点相同,这种算法是最简单的,但是效率不高
- 时间复杂度:O(n * n)
- 空间复杂度:O(1)
显然是不能满足要求的,时间复杂度不是一个级别的
-
哈希表求解法
先遍历链表A,将链表A的每个节点放入哈希表中,然后遍历链表B,对于每个节点都利用哈希表进行判断,看是否存在相同的节点
- 时间复杂度:O(n)
- 空间复杂度:O(n)
这里时间复杂度是满足了O(n),但是空间复杂度却由于创建了哈希表而变成了O(n)
-
双指针求解法
两个链表的长度是不一样的,但是重叠部分是一样的,也就是说后半部分是一样的,那么就可以将长的链表的前半部分给裁剪了,然后将裁剪后的链表的起始节点作为第一个节,然后同时遍历两个链表进行判断是否相同,所以时间复杂度仅仅为O(n)
- 时间复杂度:O(n)
- 空间复杂度:O(1)
这就是最符合题目的求解方法,从这道题也能看出来算法的重要性,他能够提高空间和时间的效率
-
直接法:
-
代码:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *nodeA = headA;
ListNode *nodeB = headB;
int lengthA = 0;
int lengthB = 0;
while(headA) {
lengthA++;
headA = headA->next;
}
while(headB) {
lengthB++;
headB = headB->next;
}
if (lengthA >= lengthB) {
int difference = lengthA - lengthB;
for (int i = 0; i < difference; i++) {
nodeA = nodeA->next;
}
} else {
int difference = lengthB - lengthA;
for (int i = 0; i < difference; i++) {
nodeB = nodeB->next;
}
}
while(nodeA!=nodeB) {
nodeA = nodeA->next;
nodeB = nodeB->next;
}
return nodeA;
}
网友评论