1. 程式人生 > 其它 >單鏈表環相關問題

單鏈表環相關問題

技術標籤:演算法單鏈表連結串列演算法leetcodejava

1、判斷是否有環

https://leetcode-cn.com/problems/linked-list-cycle/

思路,快慢指標,快指標先於慢指標入環,然後相遇

public boolean hasCycle(ListNode head) {
         ListNode fast,slow;
       fast = slow = head;
       while (slow!=null && fast.next!=null){
           slow = slow.next;
           fast = fast.next.next;
           if(slow == null || fast == null) return false;
           if(slow == fast) return true;
       }
       return false;
    }

2、獲取環的入口節點

https://leetcode-cn.com/problems/linked-list-cycle-ii/

推導公式:

2*S = s+n*r
s = n*r
a + x = s = n*r
a + x = (n-1)*r + r = (n-1)*r + (L-a)
a= (n-1)*r + (L-a -x)

程式碼:

public static ListNode detectCycle(ListNode head) {
        ListNode fast, slow;
        fast = slow = head;
        while (slow!=null && fast.next!=null){
            slow = slow.next;
            fast = fast.next.next;
            if(slow == null || fast == null) return null;
            if(slow == fast) break;
        }
        if(slow == null || fast.next == null) return null;
        while (head != slow){
            head = head.next;
            slow = slow.next;
        }
        return head;
    }

3.得到環的節點數

    public int getCircleSize(ListNode head){
        ListNode fast,slow;
        fast = slow = head;
        while (slow!=null && fast.next!=null){
            slow = slow.next;
            fast = fast.next.next;
            if(slow ==null || fast == null) return 0;
            if(slow == fast) break;
        }
        if(slow == null || fast.next == null) return 0;
        ListNode temp = slow.next;
        int count = 1;
        while (temp != slow){
            temp = temp.next;
            count++;
        }
        return count;
    }

4 得到單鏈表長度

public int getLinkListSize(ListNode head){
        ListNode fast,slow;
        fast = slow = head;
        int count = 0;
        boolean isCircle = false;
        while (slow!=null && fast.next!=null){
            count++;
            slow = slow.next;
            fast = fast.next.next;
            if(slow ==null || fast == null){
                isCircle = false;
                break;
            }
            if(slow == fast) {
                isCircle = true;
                break;
            }
        }
        if(isCircle){ //如果是環,連結串列節點個數 應該是 到環入口節點數 + 環的節點數
            ListNode p = head;
            ListNode q= slow;
            int startCount = 0; //連結串列起點到 環入口節點數(不包含環入口節點)
            while (p != q){
                startCount++;
                p = p.next;
                q = q.next;

            }
            ListNode temp = slow.next;
            int circleCount = 1; //環節點數
            while (temp != slow){
                temp = temp.next;
                circleCount++;
            }
            return startCount + circleCount;
        }else{
            while (slow!=null){
                count++;
                slow = slow.next;
            }
            return count;
        }
    }