var getIntersectionNode = function(headA, headB) {
let a = headA;
let b = headB;
while (a != b) {
a = a !== null ? a.next : headB;
b = b !== null ? b.next : headA;
}
return a;
};
Java
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//非空判断
if (headA null || headB null) {
return null;
}
ListNode a = headA;
ListNode b = headB;
while (a != b) {
if (a null) {
a = headB;
} else {
a = a.next;
}
if (b null) {
b = headA;
} else {
b = b.next;
}
}
return a;
}
时间复杂度O(m+n)
空间复杂度O(1)
双指针
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
if not headA or not headB:
return None
p = headA
q = headB
while p != q:
p = headB if not p else p.next
q = headA if not q else q.next
return p
C++
执行用时: 40 ms
内存消耗: 14.3 MB
两个链表的第一个公共节点:
所谓公共节点,就是地址相同的两个节点,因此需要使用判断,由于两个链表的长度不定,因此采用循环遍历的方式,创建两个辅助头节点,当链表A遍历完后会转向链表B的头节点,同时链表B遍历完后会转向链表A的头节点,循环一次后,两个辅助头节点必然相同,要么相遇,要么为NULL,返回即可。
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
if not headA or not headB:
return None
p1,p2=headA,headB
while p1!=p2:
if p1:
p1=p1.next
else:
p1=headB
if p2:
p2=p2.next
else:
p2=headA
return p1
”’
1如果两个链表有一个为空,那就没有公共节点,直接返回None
2设立两个指针p1,p2分别指向各自头结点
3如果指向的两个节点不相等的时候,p1不为空,指向下一个,p1如果为空,居然是走p2指向的链表,p2同理
4直到双方相等,也就是p1=p2,返回p1,此时也就是公共节点部分
时间复杂度o(m+n),空间复杂度o(1)
”’
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
// 如果两个链表中有一个链表为null,那就不会有公共节点,返回null
if (headA == null || headB == null) {
return null;
}
/* 如果有公共节点
headA的长度为m,headB的长度为n,公共节点的长度为c,headA的不公共节点长度为a,headB的不公共节点长度为b. 可会出现:a + c = m, b + c = n
都从头节点开始遍历,A = headA, B = headB
第一种可能:a = b,那必然会同时遍历到第一个公共节点。只要A==B,那就是遍历到了第一个公共节点
第二中可能:a != b,因为长度不相等,会有一个链表先遍历到null,此时A=headB,或者B=headA.当A遍历过
a + c + b + 1个节点(遍历过a+b+c次),也就是遍历到headB的第b+1个节点(也就是headB中第一个公共节点)时,B也遍历过 b + c + a + 1个节点(遍历过b+c+a次),也就是遍历到headB的第a+1个节点,此时A=B,遍历到第一个公共节点
没有公共节点
第一种情况:m = n,A和B同时到达链表的尾节点,最后A和B都为null
第二种情况:m != n,A遍历过m + n次达到headB的尾节点null,B遍历过n + m次达到headA的尾节点null
*/
ListNode A = headA, B = headB;
while (A != B) {
A = A != null ? A.next : headB;
B = B != null ? B.next :headA;
}
return A;
}
}
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode A = headA;
ListNode B = headB;
while (A != B){
if (A != null){
A = A.next;
}else{
A = headB;
}
if (B != null){
B = B.next;
}else{
B = headA;
}
}
return A;
}
}
共以下 88 个回答
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
ListNode a = headA,b= headB;
while(a!=b){
if(a!=null){
a = a.next;
}else{
a = headB;
}
if(b!=null){
b = b.next;
}else{
b = headA;
}
}
return a;
}
}加油
时间: O(n+m)
空间: O(1)
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if(headA null || headB null){
return null;
}
ListNode A = headA;
ListNode B = headB;
while(A != B){
A = A null ? headB : A.next;
B = B null ? headA : B.next;
}
return A;
}
}
时间复杂度O(n+m)
空间复杂度O(1)
思路:将两个链表拼在一起,将公共部分对其,然后遍历
时间复杂度:O(n + m)
空间复杂度:O(1)
先对齐,然后找共同点:
c++
class Solution {
public:
ListNode getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode curA=headA;
ListNode* curB=headB; //必须定义,后面要用到原始的数据
int l1=0,l2=0;
while(curA!=NULL){
l1++;
curA=curA->next;
}
while(curB!=NULL){
l2++;
curB=curB->next;
}
};
思路:双指针同时前进,找相同点
时间复杂度:O(n)
空间复杂度:O(1)
代码
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
if (headA null || headB null){
return null;
}
ListNode new1 = headA;
ListNode new2 = headB;
ListNode new3 = headA;
ListNode new4 = headB;
int i = 0;
while (new1 != null){
new1 = new1.next;
i++;
}
int j = 0;
while (new2 != null){
new2 = new2.next;
j++;
}
if (i > j){
for(int a = 0; a < i – j; a++){
new3 = new3.next;
}
}else if(i < j){
for(int a = 0; a < j – i; a++){
new4 = new4.next;
}
}
return abc(new3,new4);
}
}
时间复杂度:O(a+b+c+d)四个链表的遍历总次数 空间复杂度:O(1)
““java
class Solution{
ListNode getIntersectionNode(ListNode headA,ListNode headB){
if(headAnull||headB null) return null;
ListNode A = headA;
ListNode B = headB;
while(A!=B){
A=A null?headB:A.next;
B=Bnull?headA:B.next;
}
return A;
}
}
如果到达最后一个节点,则重新遍历另外一个链表,直到相交
时间复杂度O(n)
空间复杂度O(1)
结果链表,用双指针表示,一个头指针,一个更新指针,
循环比较两个链表,把两个链表中小的值,逐个更新进结果链表,直到其中一个链表为空,则把另外一个链表直接放结果链表后面
时间复杂度O(n)
空间复杂度O(1)
b设置双指针遍历两条链表得到长度
相减,长的链表先走
然后两个指针再同时走
相同是相遇,返回结果
时间复杂度O(A+B), 空间复杂度O(1)
时间复杂度:O(m+n)
空间复杂度:O(1)
python3实现
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
node1, node2 = headA, headB
用 p1 遍历 head A, p2 遍历 headB, 如果 p1等于null ,就去走 p2 走过的路(遍历 head B),如果 p2等于null ,就去走 p1 走过的路(遍历 head A), 此时 p1 和 p2 走了同样的路。如果这两条路上有相交的节点,即 p1等于p2,返回其中任意一个节点,没有则返回 null
Time:O(M+N)
Space:O(1)
time O(n)
memory O(1)
公共节点
解题思路
首先将两个链表的头节点定义指针,指向头节点,两个指针分别往后移动,当他们指向的值是相同的时候停止。
代码
双指针
时间复杂度:O(A + B)。
空间复杂度:O(1)。
两个链表走到底后,交换 走的路程是一样的。
复杂度分析:
时间复杂度: O(A+B)
空间复杂度: O(1)
双指针均走两条链表
双指针
时间复杂度O(m+n)
空间复杂度O(1)
时间复杂度O(m+n)
空间复杂度O(1)
“`C++实现
/**
* 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) {
ListNode* ha = headA;
ListNode* hb = headB;
while (ha != hb) {
ha = ha ? ha->next : headB;
hb = hb ? hb->next : headA;
}
return ha;
}
};
“`
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
}
Java
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//非空判断
if (headA null || headB null) {
return null;
}
ListNode a = headA;
ListNode b = headB;
while (a != b) {
if (a null) {
a = headB;
} else {
a = a.next;
}
if (b null) {
b = headA;
} else {
b = b.next;
}
}
return a;
}
时间复杂度O(m+n)
空间复杂度O(1)
打卡
时间复杂度O(m+n),空间复杂度O(1)
打卡
双指针
时间复杂度是O(m+n)
空间复杂度为 O(1)
太妙了
时间复杂度O(m+n);
空间复杂度O(1);
C++实现 节点数量之差实现 O(n) O(1)
计算插值,直接遍历 O(n) O(1)
时间复杂度O(m+n)
空间复杂度O(1)
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
if (headA NULL || headB NULL) {
return NULL;
}
struct ListNode *l1 = headA;
struct ListNode *l2 = headB;
while (l1 != l2) {
l1 = l1 NULL ? headB : l1->next;
l2 = l2 NULL ? headA : l2->next;
}
return l1;
}
找公共节点,说明两个链表公共节点一样长,先将两个链表弄成一样的长度,然后进行比对
【思路】双指针,两个指针交叉遍历两个链表,两指针重合时即为答案
【复杂度】时间O(m+n),空间O(1)
时间复杂度O(m+n)
空间复杂度O(1)
时间复杂度:O(a+b)
空间复杂度:O(1)
时间复杂度:O(a+b),a、b分别为两链表各自长度
空间复杂度:O(1)
时间复杂度O(m+n),空间复杂度O(1)
先求出链表长度的差值。令长度较长的那个链表先走过这段距离,对齐两个链表之后,同时遍历,就能找到公共节点了
只要走过两个链表长度的差值之后,如果有公共节点同步走一定会相遇
时间:O(m+n)
空间:O(1)
c++
双指针,每个指针指向一个链表的头节点,一个链表遍历完了,指向另一个指针的头节点。如果有公共节点,必然会相遇,否则两个最终都会指向NULL,返回NULL
TC: O(n)
SC: O(1)
唉 不够浪漫
第二圈交换起跑线
“`c#
public ListNode GetIntersectionNode(ListNode headA, ListNode headB) {
if(headA == null || headB == null){
return null;
}
“`
【时间O(m+n),空间O(1)】
第一条视为a+c段,第二条视为b+c段
a+c+b+c=b+c+a+c
相遇在最后一个c段的起点
不相遇则c段起点为空指针
时间复杂度:O(n+m)
空间复杂度:O(1)
1、先判断两个链表是否为空
2、创建两个虚拟节点A、B,指向两个链表头结点
3、在A B不相等的条件下循环(某一个虚拟结点为空则该结点指向另一个链表头结点继续循环,否则指向自己的next结点)
4、(如果有共同结点则返回A或者B即可,没有共同结点会返回空)
时间复杂度:O(m+n)
空间复杂度:O(1)
时间复杂度:O(m + n)
空间复杂度:O(1)
有难度
C++
执行用时: 40 ms
内存消耗: 14.3 MB
两个链表的第一个公共节点:
所谓公共节点,就是地址相同的两个节点,因此需要使用判断,由于两个链表的长度不定,因此采用循环遍历的方式,创建两个辅助头节点,当链表A遍历完后会转向链表B的头节点,同时链表B遍历完后会转向链表A的头节点,循环一次后,两个辅助头节点必然相同,要么相遇,要么为NULL,返回即可。
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
if not headA or not headB:
return None
p1,p2=headA,headB
while p1!=p2:
if p1:
p1=p1.next
else:
p1=headB
if p2:
p2=p2.next
else:
p2=headA
return p1
”’
1如果两个链表有一个为空,那就没有公共节点,直接返回None
2设立两个指针p1,p2分别指向各自头结点
3如果指向的两个节点不相等的时候,p1不为空,指向下一个,p1如果为空,居然是走p2指向的链表,p2同理
4直到双方相等,也就是p1=p2,返回p1,此时也就是公共节点部分
时间复杂度o(m+n),空间复杂度o(1)
”’
时间复杂度:O(m+n) 空间复杂度:O(1)
思路:看了解析
复杂度
1.创建两个指针A和B,分别指向输入链表headA和headB的头节点。
2.使用while循环,只要A和B不相等(即还没有找到交点),就进行以下操作:
(2.1)如果A不为空,将A指针向后移动一位,指向下一个节点。否则,A已经遍历到链表headA的末尾,将A指针重新指向headB的头节点。
(2.2)如果B不为空,将B指针向后移动一位,指向下一个节点。否则,B已经遍历到链表headB的末尾,将B指针重新指向headA的头节点。
3.当A和B相等时,表示找到了交点或者两个链表都遍历完毕(没有交点)。返回A指针即可。
代码:
这道看解析了啊啊啊啊
class Solution {
ListNode getIntersectionNode(ListNode headA, ListNode headB) {
//定义两个头节点
ListNode p1=headA;
ListNode p2=headB;
if(p1null || p2null){
return null;
}
}
“`c++
class Solution {
public:
// 双指针
// 时间复杂度 O(N + M),两个链表节点数和
// 空间复杂度 O(1)
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (headA == nullptr || headB == nullptr) { return nullptr; }
ListNode* pA = headA;
ListNode* pB = headB;
while (pA != pB) {
pA = (pA == nullptr ? headB : pA->next);
pB = (pB == nullptr ? headA : pB->next);
}
return pA;
}
};
“`
思想:先计算两条链表的长度,计算其长度的差lenA-lenB=k,设置快指针在较长链表,慢指针在较短链表,快指针先行k步,然后快慢指针共同前进,遇到相等结点则返回公共节点;若未遇到公共节点,则返回null
时间复杂度:O(m+n) 空间复杂度:O(1)
C++实现
class Solution {
public:
ListNode getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA NULL) return NULL;
if(headB NULL) return NULL;
ListNode curA = headA;
ListNode* curB = headB;
int lenA = 0 , lenB = 0;
while(curA){
lenA++;
curA = curA->next;
}
while(curB){
lenB++;
curB = curB->next;
}
curA = headA;
curB = headB;
if(lenB > lenA){
swap(lenA,lenB);
swap(curA,curB);
}
int gap = lenA – lenB;
while(gap–){
curA = curA->next;
}
while(curA != NULL){
if(curA curB)
return curA;
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
C++
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *a = headA;
ListNode *b = headB;
while(a != b){
a = a != NULL ? a->next : headB;
b = b != NULL ? b->next : headA;
}
return a;
}
};
时间复杂度为O(n);
空间复杂度为O(1);
思想:
虽然两个链表的长度可能不相同,但是二者的总长度是相同的,如果定义的两个遍历链表的指针相遇了,那么则是交点。
思路
代码
c++代码
class Solution {
public:
ListNode getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode p1 = headA, *p2 = headB;
while(p1!=p2){
if(p1!=nullptr) p1 = p1->next;
else p1 = headB;
if(p2!=nullptr) p2 = p2->next;
else p2 = headA;
}
return p1;
}
};
时间复杂度:O(n),空间复杂度:O(1)。
“`c++
// c++实现
/**
* 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 || ! headB)
return nullptr;
ListNode* cur1 = headA;
ListNode* cur2 = headB;
while(cur1 != cur2){
// 设 a 链从头结点到相交节点的距离为 a
// b 链从头节点到相交节点的距离为 b
// 相交节点到终点的距离为 c
// l1 : a+c+b
// l2 : b+c+a
// 相当于在两条链表尾部加了一个 null 节点,
// 则可能有两个相交节点
// 1 有两个相交节点,即null之前有一个,
// 2 有一个即null节点,那么找到的是 null 节点
cur1 = cur1 ? cur1->next : headB;
cur2 = cur2 ? cur2->next : headA;
}
return cur1;
}
};
C++实现
“`C++
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *a=headA,*b=headB;
while(a!=b){
a=a==NULL?headB:a->next;
b=b==NULL?headA:b->next;
}
return a;
}
};
“`
c++实现
ListNode* lA = headA;
ListNode* lB = headB;
int len1 =0,len2=0;
while(lA!=NULL)
{len1++;
lA = lA->next;
java实现
时间复杂度为n1+n2,空间复杂度为1。按照帅地的思路。写了两种方法
c实现
struct ListNode getIntersectionNode(struct ListNode headA, struct ListNode headB)
{ struct ListNode node1 = headA, *node2 = headB;
while (node1 != node2)
{ if (node1)
node1 = node1->next;
else
node1 = headB;
if (node2)
node2 = node2->next;
else
node2 = headA;
}
return node1;
}
时间复杂度:O(m+n),空间复杂度:O(1)。
class Solution{
ListNode getIntersectionNode(ListNode headA,ListNode headB){
if(headAnull)return null;
ListNodeA=headA;
ListNodeB=headB;
while(A!=B){
A=Anull ?headB:A.next;
B=Bnull ?headA:B.next;
}
return A;
}
}
时间复杂度:O(n+m)
空间复杂度:O(1)
这里是Ming打卡:
这里与增删改无关,不需要虚拟头结点
注意循环终止的条件是他们相等(毕竟题目就是求这个)
如果相遇两个结点会走的长度=a+b+n,n为公共部分,如果不相遇会走a+b更长了
两个指针都遍历一遍两个链表,分别为A+B和B+A。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
// 利用两个链表相加路径相同来解决
// 时间复杂度O(m+n); 两个链表长度和
// 空间复杂度O(1);没有辅助空间
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *A = headA,B = headB;
while(A!=B)
{
A = ANULL?headB:A->next;
B = BNULL?headA:B->next;
}
return A;
}
};