链表 - 160. 相交链表(C#和C实现)
题目描述
编写一个程序,找到两个单链表相交的起始节点。
示例:
A: a1 → a2
↘
c1 → c2 → c3
↗
B: b1 → b2 → b3
在节点 c1
开始相交。
解题思路
- 遍历两个链表,得到它们的长度分别为
lenA
和lenB
。 - 如果链表 A 的长度大于链表 B 的长度,将链表 A 的指针向前移动
lenA - lenB
步。 - 如果链表 B 的长度大于链表 A 的长度,将链表 B 的指针向前移动
lenB - lenA
步。 - 同时遍历两个链表,找到相交的节点,返回该节点。
C#代码实现
public ListNode GetIntersectionNode(ListNode headA, ListNode headB) {
// 获取链表A的长度
int lenA = GetListLength(headA);
// 获取链表B的长度
int lenB = GetListLength(headB);
// 将链表A和链表B的长度相等
while (lenA > lenB) {
// 将链表A的指针指向下一个节点
headA = headA.next;
// 将链表A的长度减1
lenA--;
}
while (lenB > lenA) {
// 将链表B的指针指向下一个节点
headB = headB.next;
// 将链表B的长度减1
lenB--;
}
// 遍历链表A和链表B,当指针指向同一个节点时,返回该节点
while (headA != headB) {
// 将链表A的指针指向下一个节点
headA = headA.next;
// 将链表B的指针指向下一个节点
headB = headB.next;
}
// 返回链表A的指针
return headA;
}
private int GetListLength(ListNode head) {
// 初始化链表长度
int length = 0;
// 遍历链表,将链表长度加1
while (head != null) {
length++;
head = head.next;
}
// 返回链表长度
return length;
}
C代码实现
struct ListNode* getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
// 获取链表A的长度
int lenA = getListLength(headA);
// 获取链表B的长度
int lenB = getListLength(headB);
// 将链表A的指针移动到与链表B等长
while (lenA > lenB) {
headA = headA->next;
lenA--;
}
// 将链表B的指针移动到与链表A等长
while (lenB > lenA) {
headB = headB->next;
lenB--;
}
// 同时移动指针,直到相遇
while (headA != headB) {
headA = headA->next;
headB = headB->next;
}
return headA;
}
// 获取链表长度
int getListLength(struct ListNode* head) {
// 初始化长度
int length = 0;
// 遍历链表
while (head != NULL) {
// 长度加1
length++;
// 指针指向下一个节点
head = head->next;
}
// 返回链表长度
return length;
}
时间复杂度和空间复杂度
- 时间复杂度:O(m + n),其中 m 和 n 分别是两个链表的长度。遍历两个链表一次,然后遍历相交的节点一次。
- 空间复杂度:O(1)。除了常数级别的变量,算法的空间复杂度是常数级别的
参与点评
读者朋友们,如果您在阅读过程中,对文章的质量、易理解性有任何建议,欢迎在评论区指出,我会认真改进。