牛客网高频算法题系列-BM10-两个链表的第一个公共结点

题目描述

输入两个无环的单向链表,找出它们的第一个公共结点,如果没有公共节点则返回空。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

原题目见:BM10 两个链表的第一个公共结点

解法一:双重循环

使用双重循环遍历2个链表,简单粗暴,不过效率稍低。

解法二:双指针法

使用2个指针l1和l2分别从链表一和链表二的头结点遍历,遍历到尾部后,再分别从链表二和链表一遍历,如果两个链表有公共交点,则l1和l2一定会在交点处相遇,否则,l1和l2分别遍历完两个链表后都是null,没有公共结点。

代码

  1. public class Bm010 {
  2. /**
  3. * 方法一:双重循环
  4. *
  5. * @param pHead1 链表一
  6. * @param pHead2 链表二
  7. * @return
  8. */
  9. public static ListNode findFirstCommonNode(ListNode pHead1, ListNode pHead2) {
  10. if (pHead1 == null || pHead2 == null) {
  11. return null;
  12. }
  13. ListNode node1 = pHead1;
  14. // 外层循环遍历链表一的结点
  15. while (node1 != null) {
  16. ListNode node2 = pHead2;
  17. // 内层循环遍历链表二的结点
  18. while (node2 != null) {
  19. if (node2 == node1) {
  20. return node1;
  21. }
  22. node2 = node2.next;
  23. }
  24. node1 = node1.next;
  25. }
  26. return null;
  27. }
  28. /**
  29. * 双指针法
  30. *
  31. * @param pHead1
  32. * @param pHead2
  33. * @return
  34. */
  35. public static ListNode findFirstCommonNode2(ListNode pHead1, ListNode pHead2) {
  36. // l1和l2分别从链表一和链表二的头结点遍历,遍历到尾部后,再分别从链表二和链表一遍历
  37. ListNode l1 = pHead1, l2 = pHead2;
  38. while (l1 != l2) {
  39. l1 = (l1 == null) ? pHead2 : l1.next;
  40. l2 = (l2 == null) ? pHead1 : l2.next;
  41. }
  42. // 如果两个链表有公共交点,则l1和l2一定会在交点处相遇,此时l1就是公共结点
  43. // 否则,l1和l2分别遍历完两个链表后都是null,没有公共结点,返回null
  44. return l1;
  45. }
  46. public static void main(String[] args) {
  47. ListNode pHead1 = ListNode.testCase2();
  48. System.out.println("链表一为");
  49. ListNode.print(pHead1);
  50. ListNode pHead2 = ListNode.testCase1();
  51. pHead2.next.next.next = pHead1.next.next;
  52. System.out.println("链表二为");
  53. ListNode.print(pHead2);
  54. ListNode.print(findFirstCommonNode(pHead1, pHead2));
  55. ListNode.print(findFirstCommonNode2(pHead1, pHead2));
  56. }
  57. }

牛客网高频算法题系列-BM10-两个链表的第一个公共结点 - 图1
牛客网高频算法题系列-BM10-两个链表的第一个公共结点 - 图2
相信坚持的力量!