版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/majichen95/article/details/83820697
请写一个程序,找到两个单链表最开始的交叉节点。
样例
下列两个链表:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
在节点 c1 开始交叉。
挑战
需满足 O(n) 时间复杂度,且仅用 O(1) 内存。
注意事项
- 如果两个链表没有交叉,返回
null
。 - 在返回结果后,两个链表仍须保持原有的结构。
- 可假定整个链表结构中没有循环。
解题思路:
时间:O(2 * (LenA + LenB)) = O(LenA + LenB)
空间:O(1)
算法:
- 分别测量两个链表的长度;
- 通过长度比较,令两个链表的头指针都指向 距离末尾节点距离相同 并且 距离最远的地方。其实就是让两个指针指向离交叉点距离相同的位置;
- 一起挪动两个指针,知道他们指向同一个节点;
- 返回任意一个指针指向的节点。
/**
* Definition for ListNode
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
/**
* @param headA: the first list
* @param headB: the second list
* @return: a ListNode
*/
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
// write your code here
if(headA == null || headB == null)
return null;
int lenA = measureLength(headA);
int lenB = measureLength(headB);
ListNode nodeA = headA;
ListNode nodeB = headB;
//根据两者长度定比较起始点,使得从起始点开始两者长度一致
while(lenA < lenB){
lenB--;
nodeB = nodeB.next;
}
while(lenA > lenB){
lenA--;
nodeA = nodeA.next;
}
//按顺序比较节点
while(nodeA != nodeB){
nodeA = nodeA.next;
nodeB = nodeB.next;
}
return nodeA;
}
private int measureLength(ListNode head){
int len = 0;
ListNode node = head;
while(node != null){
len++;
node = node.next;
}
return len;
}
}