输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)
数据范围:
要求:空间复杂度 ,时间复杂度
要求:空间复杂度 ,时间复杂度
例如,输入{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,后台打印{}
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; // 美哟公共节点 } }