• 求链表的相交节点


    题目:给定两个可能成环的单链表,头结点head1 head2.

    请实现一函数,如果两个链表相交,请返回相交的一个节点,如果不相交,返回null.

    我们了解一下求链表成环节点的题目.----->给定链表的头结点,返回链表的成环节点,没有返回null.

    首先这道题目分别有两种做法,一种是空间复杂度为O(N)的一种

    1. public static Node LoopNode1(Node head){
    2. if(head==null){
    3. return head;
    4. }
    5. Set set = new HashSet<>();
    6. while(head!=null){
    7. if(set.contains(head)){
    8. return head;
    9. }else{
    10. set.add(head);
    11. head = head.next;
    12. }
    13. }
    14. return null;
    15. }

    首先使用Set 如果集合内存在当前节点,那么就返回,如果不存在就放进集合内.

    因为如果是有环链表的成环节点早晚会遍历到.但是如果是无环链表就会遍历到null.

    同时我们还有空间复杂度为O(1) 的方法

    1. public static Node LoopNode(Node head){
    2. if(head==null || head.next==null || head.next.next==null){
    3. return null;
    4. }
    5. Node slow = head.next;
    6. Node fast = head.next.next;
    7. while(slow!=fast){
    8. if(fast.next==null || fast.next.next==null){
    9. return null;
    10. }
    11. slow = slow.next;
    12. fast = fast.next.next;
    13. }
    14. fast = head;
    15. while(slow!=fast){
    16. slow = slow.next;
    17. fast = fast.next;
    18. }
    19. return slow;
    20. }

    如果首先如果链表能够成环,那么一个快指针和一个满足指针肯定能在环内碰见.

    证明就先省略.

    那么两个链表是否成环就有多种情况,假设head1 的入环节点为loop1 ,head2的入环节点就是loop2.

    那么第一种情况:

    loop1==null && loop2==null

    这种情况下有两种情况:

    在不成环的情况下:两链表是否相交的的判断:两条链表上是否有相同的节点.

    空间复制度为O(N).

    1. private static Node intersertNode1(Node head1,Node head2){
    2. Set set = new HashSet<>();
    3. while(head1!=null){
    4. set.add(head1);
    5. head1 = head1.next;
    6. }
    7. while(head2!=null){
    8. if(set.contains(head2)){
    9. return head2;
    10. }else{
    11. head2 = head2.next;
    12. }
    13. }
    14. return null;
    15. }

    这个方法就是先将其中一个链表的全部都放在集合中.另外的一个链表从头开始遍历.第一个存在链表的节点就是相交的节点.

    空间复制度为O(1)

    1. private static Node inersertNode(Node head1,Node head2){
    2. Node cur1 = head1;
    3. int N = 0;
    4. while(cur1.next!=null){
    5. N++;
    6. cur1 = cur1.next;
    7. }
    8. Node cur2 = head2;
    9. while(cur2.next!=null){
    10. N--;
    11. cur2 = cur2.next;
    12. }
    13. if(cur1!=cur2){
    14. return null;
    15. }
    16. cur1 = N > 0 ? head1 : head2;
    17. cur2 = cur1==head1 ? head2 : head1;
    18. N = Math.abs(N);
    19. while(N!=0){
    20. N--;
    21. cur1 = cur1.next;
    22. }
    23. while(cur1!=cur2){
    24. cur1 = cur1.next;
    25. cur2 = cur2.next;
    26. }
    27. return cur1;
    28. }

    这种方法的方法就是先记录各个链表的长度,然后让长链表先走差值步,然后再同时走,直到走到其中相同的节点就是相交节点.当我们记录完链表的长度后我们能判断最后一个节点.如果最后一个节点不相同就代表不是最后一个节点.

    第二种情况:

    loop1==null ^ loop2==null

    当链表一个成环,另外一个不成环就只有一种情况.

     

    当只有这种情况才能符合一个入环节点为空,另外一个入环节点不为空.

    这种情况就直接返回null

    第三种情况:

    loop1 != null && loop2 !=null

    这种情况下需要我们分析

    当loop1==loop2 的情况下那么就是

    当loop1 != loop2  

     

    1. public static Node bothLoop(Node head1,Node loop1,Node head2,Node loop2){
    2. Node cur1 = head1;
    3. Node cur2 = head2;
    4. if(loop1==loop2){
    5. int N = 0;
    6. while(cur1!=loop1){
    7. cur1 = cur1.next;
    8. N++;
    9. }
    10. while(cur2!=loop1){
    11. cur2 = cur2.next;
    12. N--;
    13. }
    14. cur1 = N > 0 ? head1 : head2;
    15. cur2 = cur1==head1 ? head2 : head1;
    16. N = Math.abs(N);
    17. while(N!=0){
    18. cur1 = cur1.next;
    19. }
    20. while(cur1!=cur2){
    21. cur1 = cur1.next;
    22. cur2 = cur2.next;
    23. }
    24. return cur1;
    25. }else{
    26. cur1 = loop1.next;
    27. while(cur1!=loop1){
    28. if(cur1==loop2){
    29. return loop2;
    30. }
    31. cur1 = cur1.next;
    32. }
    33. return null;
    34. }
    35. }

    所以我们的总的函数就是

    1. public static Node getInersertNode(Node head1,Node head2){
    2. if(head1==null ^ head2==null){
    3. return null;
    4. }
    5. Node loop1 = LoopNode(head1);
    6. Node loop2 = LoopNode(head2);
    7. if(loop1==null && loop2==null){
    8. return inersertNode(loop1,loop2);
    9. }else if(loop1==null ^ loop2==null){
    10. return null;
    11. }else{
    12. return bothLoop(head1,loop1,head2,loop2);
    13. }
    14. }
    15. private static Node LoopNode(Node head){
    16. if(head==null || head.next==null || head.next.next==null){
    17. return null;
    18. }
    19. Node slow = head.next;
    20. Node fast = head.next.next;
    21. while(slow!=fast){
    22. if(fast.next==null || fast.next.next==null){
    23. return null;
    24. }
    25. slow = slow.next;
    26. fast = fast.next.next;
    27. }
    28. fast = head;
    29. while(slow!=fast){
    30. slow = slow.next;
    31. fast = fast.next;
    32. }
    33. return slow;
    34. }
    35. private static Node inersertNode(Node head1,Node head2){
    36. Node cur1 = head1;
    37. int N = 0;
    38. while(cur1.next!=null){
    39. N++;
    40. cur1 = cur1.next;
    41. }
    42. Node cur2 = head2;
    43. while(cur2.next!=null){
    44. N--;
    45. cur2 = cur2.next;
    46. }
    47. if(cur1!=cur2){
    48. return null;
    49. }
    50. cur1 = N > 0 ? head1 : head2;
    51. cur2 = cur1==head1 ? head2 : head1;
    52. N = Math.abs(N);
    53. while(N!=0){
    54. N--;
    55. cur1 = cur1.next;
    56. }
    57. while(cur1!=cur2){
    58. cur1 = cur1.next;
    59. cur2 = cur2.next;
    60. }
    61. return cur1;
    62. }
    63. private static Node bothLoop(Node head1,Node loop1,Node head2,Node loop2){
    64. Node cur1 = head1;
    65. Node cur2 = head2;
    66. if(loop1==loop2){
    67. int N = 0;
    68. while(cur1!=loop1){
    69. cur1 = cur1.next;
    70. N++;
    71. }
    72. while(cur2!=loop1){
    73. cur2 = cur2.next;
    74. N--;
    75. }
    76. cur1 = N > 0 ? head1 : head2;
    77. cur2 = cur1==head1 ? head2 : head1;
    78. N = Math.abs(N);
    79. while(N!=0){
    80. cur1 = cur1.next;
    81. }
    82. while(cur1!=cur2){
    83. cur1 = cur1.next;
    84. cur2 = cur2.next;
    85. }
    86. return cur1;
    87. }else{
    88. cur1 = loop1.next;
    89. while(cur1!=loop1){
    90. if(cur1==loop2){
    91. return loop2;
    92. }
    93. cur1 = cur1.next;
    94. }
    95. return null;
    96. }
    97. }

  • 相关阅读:
    Spring Boot 国际化 i18n
    Go语言的GoFrame+Vue+ElementUI开源框架推荐
    SpringBoot程序预装载数据
    Elasticsearch索引分片的数量及大小分配策略
    WRF模式行业应用问题解析
    Mac安装brew及前端环境「亲测有效」
    接口相关注解组合
    MySQL 空间碎片详解
    前后端跨域
    Nacos使用实践
  • 原文地址:https://blog.csdn.net/weixin_61652218/article/details/126751737