输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
数据范围:
要求:空间复杂度
,时间复杂度 )
要求:空间复杂度
例如,输入{1,2,3},{4,5},{6,7}时,两个无环的单向链表的结构如下图所示:
可以看到它们的第一个公共结点的结点值为6,所以返回结点值为6的结点。
输入分为是3段,第一段是第一个链表的非公共部分,第二段是第二个链表的非公共部分,第三段是第一个链表和第二个链表的公共部分。 后台会将这3个参数组装为两个链表,并将这两个链表对应的头节点传入到函数FindFirstCommonNode里面,用户得到的输入只有pHead1和pHead2。
返回传入的pHead1和pHead2的第一个公共结点,后台会打印以该节点为头节点的链表。
{1,2,3},{4,5},{6,7}{6,7}第一个参数{1,2,3}代表是第一个链表非公共部分,第二个参数{4,5}代表是第二个链表非公共部分,最后的{6,7}表示的是2个链表的公共部分
这3个参数最后在后台会组装成为2个两个无环的单链表,且是有公共节点的 {1},{2,3},{}{}2个链表没有公共节点 ,返回null,后台打印{} public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if (pHead1 == null || pHead2 == null){
return null;
}
ListNode commonNodeFinal = null;
ListNode flagNode = pHead2;
while (flagNode != null){
if (pHead1.val == flagNode.val){
if (pHead1.next != null && flagNode.next!=null && pHead1.next.val == flagNode.next.val) {
commonNodeFinal = pHead1;
break;
}else {
if (pHead1.next == null && flagNode.next == null){
commonNodeFinal = pHead1;
break;
}
}
}
flagNode = flagNode.next;
}
if (commonNodeFinal == null && pHead1.next != null){
commonNodeFinal = FindFirstCommonNode(pHead1.next, pHead2);
}
return commonNodeFinal;
}
遍历递归一个个对比就解决了
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
Set<ListNode> set = new HashSet<>(); // 存链表节点
while (pHead1 != null) {
set.add(pHead1);
pHead1 = pHead1.next;
}
while (pHead2 != null) {
if (set.contains(pHead2)) break; // 第一个相同的即所求
else {
set.add(pHead1);
pHead2 = pHead2.next;
}
}
return pHead2;
}
} import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
// 左程云老师讲过这道题。分别测量两条链表的长度length1和length2,计算二者的差值diff
// 先让较长链表走diff个结点,然后二者同时一次走一个结点,相遇的结点就是第一个公共节点
// 算法的时间复杂度O(N),额外空间复杂度O(1)
// 1.分别遍历一遍链表,得到总共有几个结点
if (pHead1 == null) {
return null;
}
if (pHead2 == null) {
return null;
}
// 确保两个链表都至少有一个结点
int length1 = 0;
int length2 = 0;
ListNode cur = pHead1;
while (cur != null) {
length1++;
cur = cur.next;
}
cur = pHead2;
while (cur != null) {
length2++;
cur = cur.next;
}
// 2.找到较长的链表并计算差值
ListNode longListHead = length1 >= length2 ? pHead1 : pHead2;
ListNode shortListHead = length1 >= length2 ? pHead2 : pHead1;
int diff = Math.abs(length1 - length2);
// 3.先让较长链表走diff个结点,然后二者同时一次走一个结点,相遇的结点就是第一个公共节点
ListNode longListCur = longListHead;
ListNode shortListCur = shortListHead;
while(diff > 0) {
longListCur = longListCur.next;
diff--;
}
// 4.此时,令longListCur和shortListCur同时一次往前走一个结点,直到它们相遇
while (longListCur != shortListCur) {
longListCur = longListCur.next;
shortListCur = shortListCur.next;
}
// 5.返回相遇的结点,就是第一个公共结点
return longListCur;
}
}
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
//先保留两个头结点
ListNode p1 = pHead1;
ListNode p2 = pHead2;
while (pHead1 != pHead2) {
if (pHead1 == null) { //遍历到了尾部,遍历另一个链表
pHead1 = p2;
} else {
pHead1 = pHead1.next;
}
if (pHead2 == null) { //遍历到了尾部,遍历另一个链表
pHead2 = p1;
} else {
pHead2 = pHead2.next;
}
}
return pHead1;
}
} public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode node1 = pHead1;
ListNode node2 = pHead2;
while(node1 != node2){
if(node1 == null){
node1 = pHead2;
}
else{
node1 = node1.next;
}
if(node2 == null){
node2 = pHead1;
}
else{
node2 = node2.next;
}
}
return node1;
} import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if (pHead1 == null || pHead2 == null) {
return null;
}
if (pHead1.next == pHead2.next) {
return pHead1.next;
}
// if (pHead1 == null && pHead2 != null) {
// return pHead2;
// }
// if (pHead2 == null && pHead1 != null) {
// return pHead1;
// }
ListNode p1 = pHead1;
ListNode p2 = pHead2;
int len1 = 0, len2 = 0;
while (p1 != null) {
len1++;
p1 = p1.next;
}
while (p2 != null) {
len2++;
p2 = p2.next;
}
ListNode frist = len1 > len2 ? pHead1 : pHead2;
ListNode slow = frist == pHead1 ? pHead2 : pHead1;
int k = Math.abs(len1 - len2);
System.out.println(k);
for (int i = 0; i < k; i++) {
frist = frist.next;
}
while (slow != frist) {
frist = frist.next;
slow = slow.next;
}
return frist;
}
} public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
ListNode p1 = pHead1;
ListNode p2 = pHead2;
while (true) {
if (p1 == p2) return p1;
p1 = (p1 == null) ? pHead2 : p1.next;
p2 = (p2 == null) ? pHead1 : p2.next;
}
}
} public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if (pHead1 == null || pHead2 == null) {
return null;
}
if (pHead1 == pHead2) return pHead1;
int n1 = 0;
int n2 = 0;
ListNode h1 = pHead1;
ListNode h2 = pHead2;
while (pHead1.next != null || pHead2.next != null) {
if (pHead1.next != null && pHead2.next != null) {
pHead1 = pHead1.next;
pHead2 = pHead2.next;
if (pHead1 == pHead2) return pHead1;
} else if (pHead1.next == null) {
pHead2 = pHead2.next;
n2++;
} else {
pHead1 = pHead1.next;
n1++;
}
}
if (pHead1 != pHead2) return null;
if (n1 > 0) {
while (h1.next != null) {
if (n1 > 0) {
h1 = h1.next;
n1--;
} else {
h1 = h1.next;
h2 = h2.next;
}
if (h1 == h2) return h1;
}
} else if (n2 > 0) {
while (h2.next != null) {
if (n2 > 0) {
h2 = h2.next;
n2--;
} else {
h1 = h1.next;
h2 = h2.next;
}
if (h1 == h2) return h1;
}
}
return null;
}
思路感觉差不多,大神的代码更简洁
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
//两个链表的相遇,走完自己走别人
ListNode cur1=pHead1;
ListNode cur2=pHead2;
while(cur1!=cur2){//直到找到公共节点
if(cur1!=null) {
cur1=cur1.next;
}else{
cur1=pHead2;
}
if(cur2!=null){
cur2=cur2.next;
}else{
cur2=pHead1;
}
}
return cur1;
} import java.util.*;
/*
public class ListNode {
int val;
ListNode next = null;
ListNode(int val) {
this.val = val;
}
}*/
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
if (pHead1 == null || pHead2 == null) {
return null;
}
//2、计算链表的长度
int lenA = 0;
int lenB = 0;
ListNode curA = pHead1;
ListNode curB = pHead2;
while (curA != null) {
lenA++;
curA = curA.next;
}
while (curB != null) {
lenB++;
curB = curB.next;
}
curA = pHead1;
curB = pHead2;
int len = lenA - lenB;
if (len > 0) {
while (len-- > 0) {
curA = curA.next;
}
} else {
len = -len;
while (len-- > 0) {
curB = curB.next;
}
}
while (curA != null) {
if (curA == curB) {
return curA;
}
curA = curA.next;
curB = curB.next;
}
return null;
}
}
import java.util.Set;
import java.util.HashSet;
public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
// 使用 HashSet 去重的解法
Set<ListNode> nodes = new HashSet<>();
ListNode tmp = pHead1;
while (tmp!=null && nodes.add(tmp)) {
tmp = tmp.next;
}
tmp = pHead2;
while (tmp!=null && nodes.add(tmp)) {
tmp = tmp.next;
}
return tmp;
}
} 第二种就是获得两个链表的长度,较长的链表从差值处开始遍历,较短的链表从头开始遍历,每次向后移动时比较是否为公共节点 public class Solution {
public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
// 遍历两个链表,求节点差异,然后比较可能的公共节点是否一致
if (pHead1==null || pHead2==null) {
return null;
}
// 获取两个链表的节点数量
int len1 = 0;
int len2 = 0;
ListNode tmp1 = pHead1;
ListNode tmp2 = pHead2;
while (tmp1 != null) {
++len1;
tmp1 = tmp1.next;
}
while (tmp2 != null) {
++len2;
tmp2 = tmp2.next;
}
tmp1 = pHead1;
tmp2 = pHead2;
// 节点多的链表向前移动
if (len1 > len2) {
for (int i=0; i<len1-len2; ++i) {
tmp1 = tmp1.next;
}
} else {
for (int i=0; i<len2-len1; ++i) {
tmp2 = tmp2.next;
}
}
// 移动至链表尾,发现一致的返回
while (tmp1 != null) {
if (tmp1 == tmp2) {
return tmp1;
}
tmp1 = tmp1.next;
tmp2 = tmp2.next;
}
return null; // 美哟公共节点
}
}
/* 找出2个链表的长度,然后让长的先走两个链表的长度差,然后再一起走 (因为2个链表用公共的尾部) */ class Solution { public: ListNode* FindFirstCommonNode( ListNode *pHead1, ListNode *pHead2) { int len1 = findListLenth(pHead1); int len2 = findListLenth(pHead2); if(len1 > len2){ pHead1 = walkStep(pHead1,len1 - len2); }else{ pHead2 = walkStep(pHead2,len2 - len1); } while(pHead1 != NULL){ if(pHead1 == pHead2) return pHead1; pHead1 = pHead1->next; pHead2 = pHead2->next; } return NULL; } int findListLenth(ListNode *pHead1){ if(pHead1 == NULL) return 0; int sum = 1; while(pHead1 = pHead1->next) sum++; return sum; } ListNode* walkStep(ListNode *pHead1, int step){ while(step--){ pHead1 = pHead1->next; } return pHead1; } };