zoukankan      html  css  js  c++  java
  • 链表 相交结点与环问题

    基本问题:

    1.两个链表中的第一个公共结点

    [解题思路]

    a.先求得两个链表的长度,得到链表长度差d

    b.根据链表长度差,首先让长链表的指针先走d-1步,之后两个指针一起走,发现相同结点时就是公共结点

        int len1 = 0, len2 = 0;
            ListNode p1 = head1, p2 = head2;
            while (p1 != null) {
                len1++;
                p1 = p1.next;
            }
    
            while (p2 != null) {
                len2++;
                p2 = p2.next;
            }
            
            ListNode listLong = null, listShort = null;
            int lenDiff = 0; 
            if(len1 > len2){
                listLong = head1;
                listShort = head2;
                lenDiff = len1 - len2;
            } else {
                listLong = head2;
                listShort = head1;
                lenDiff = len2 - len1;
            }
            
            for(int i = 0; i < lenDiff; i++){
                listLong = listLong.next;
            }
            
            while(listLong != null && listShort != null && (listLong != listShort)){
                listLong = listLong.next;
                listShort = listShort.next;
            }
    
            return listLong;

    2.如何判断一个链表中是否存在环

     [解题思路]

    和上题类似,维护两个指针,一个指针每次走1步,另一个指针每次走2步,如果快指针追上了慢指针,则链表中存在环

     1 public static boolean checkCircle2(ListNode head) {
     2         if (head == null) {
     3             return false;
     4         }
     5 
     6         ListNode fast = head, slow = head;
     7         while (fast != null && fast.next != null) {
     8             slow = slow.next;
     9             fast = fast.next.next;
    10             if(slow == fast){
    11                 break;
    12             }
    13         }
    14         return !(fast == null || fast.next == null);
    15     }

     

    扩展问题:

    1.求问题2中环的入口点

     如明确知晓链表中存在环,则在环中将链表拆开,则就变成上面的问题1,找到入口结点之后恢复链表

     1 public static ListNode findPortal(ListNode head) {
     2         if (head == null) {
     3             return null;
     4         }
     5 
     6         ListNode fast = head, slow = head;
     7         ListNode head2 = null, tail = null;
     8         while (fast != null && fast.next != null) {
     9             slow = slow.next;
    10             fast = fast.next.next;
    11             // meet in circle, break the circle
    12             if (slow == fast) {
    13                 head2 = fast.next;
    14                 tail = fast;
    15                 fast.next = null;
    16                 break;
    17             }
    18         }
    19 
    20         ListNode result = findCommonNode(head, head2);
    21         tail.next = head2;
    22 
    23         return result;
    24     }
    25 
    26     private static ListNode findCommonNode(ListNode head1, ListNode head2) {
    27         if (head1 == null || head2 == null) {
    28             return null;
    29         }
    30         int len1 = 0, len2 = 0;
    31         ListNode p1 = head1, p2 = head2;
    32         while (p1 != null) {
    33             len1++;
    34             p1 = p1.next;
    35         }
    36 
    37         while (p2 != null) {
    38             len2++;
    39             p2 = p2.next;
    40         }
    41         
    42         ListNode listLong = null, listShort = null;
    43         int lenDiff = 0; 
    44         if(len1 > len2){
    45             listLong = head1;
    46             listShort = head2;
    47             lenDiff = len1 - len2;
    48         } else {
    49             listLong = head2;
    50             listShort = head1;
    51             lenDiff = len2 - len1;
    52         }
    53         
    54         for(int i = 0; i < lenDiff; i++){
    55             listLong = listLong.next;
    56         }
    57         
    58         while(listLong != null && listShort != null && (listLong != listShort)){
    59             listLong = listLong.next;
    60             listShort = listShort.next;
    61         }
    62 
    63         return listLong;
    64     }

     这题还有另外的解题思路:http://www.cppblog.com/humanchao/archive/2012/11/12/47357.html

    假设两个指针相遇时slow指针走了s步,则fast指针走了2s步(因为慢指针走一步,快指针走两步)

    此时fast指针可能绕环走了n圈(n >= 0), 则有2s = s + nr; ==> s = nr;

    设链表起点到环的入口点距离为a,环入口点到两指针相遇点距离为x.==>s = a + x;

    ==>a + x = nr;

    ==>a + x = (n-1)r + r

    ==>a + x = (n-1)r + L - a

    ==>a = (n-1)r + L - x -a;

    则我们在发现fast指针和slow指针相遇时,另外使用两个指针,分别指向链表头结点和相遇结点,同时开始走,则他们相遇结点就是

    环的入口结点

     1 public static ListNode findPortal2(ListNode head) {
     2         if (head == null) {
     3             return null;
     4         }
     5         
     6         ListNode fast = head, slow = head;
     7         while(fast != null && fast.next != null){
     8             fast = fast.next.next;
     9             slow = slow.next;
    10             if(fast == slow){
    11                 break;
    12             }
    13         }
    14         
    15         if(fast == null || fast.next == null){
    16             return null;
    17         }
    18         
    19         ListNode p = head;
    20         while(p != fast){
    21             p = p.next;
    22             fast = fast.next;
    23         }
    24         return p;
    25     }

    链表其他问题:

    1.求链表倒数第k个结点

    2.求链表的中间结点,如链表中结点总数为奇数,返回中间结点;如为偶数,返回中间两个结点的任意一个

    问题来源:

    http://www.cnblogs.com/sooner/p/3277886.html

  • 相关阅读:
    android用户界面之WebView教程实例汇总
    android用户界面之TabHost教程实例汇总
    手把手教你写android项目@第一期项目——身份证查询创新(项目总结)
    android用户界面之GridView教程实例汇总
    android学习从模仿开始 —— 模仿UI 导航帖
    Android 实现书籍翻页效果
    android用户界面之Widget教程实例汇总
    如何安装webdriver chrome浏览器支持
    Seleniumwebdriver系列教程(15)————使用已存在的profile启动firefox
    ruby设计模式之【观察者】模式1————简单的观察者模式
  • 原文地址:https://www.cnblogs.com/feiling/p/3319087.html
Copyright © 2011-2022 走看看