快慢指針


做LeetCode碰到兩個快慢指針運用的題目,記錄一下,當然這個東西應用的地方肯定不止下面這兩個了,以后要是碰到就再更新

快慢指針:

這里快慢實際是指他們移動的步數,一個一次移動多個位置(一般二),一個移動一個

 

1,判斷鏈表里是否存在環

題目描述:

給定一個鏈表,判斷鏈表中是否有環。

為了表示給定鏈表中的環,我們使用整數 pos 來表示鏈表尾連接到鏈表中的位置(索引從 0 開始)。 如果 pos 是 -1,則在該鏈表中沒有環。

思路:快指針和慢指針同時往鏈表后面移動,如果快指針到達NULL,說明鏈表以NULL為結尾,沒有環。如果快指針追上慢指針(即兩個相等),則表示有環。

代碼:

/**
 * Definition for singly-linked list.
 * class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public boolean hasCycle(ListNode head) {
         if (head==null) {
            return false;
        }
        ListNode slow = head;
        ListNode fast = head;
        while(fast!=null&&fast.next!=null) {
            slow = slow.next;
            fast = fast.next.next;
            if (fast==slow) {
                return true;
            }
        }
        return false;
    }
}
View Code

 

二,一個排序鏈表里找到中位數

這里其實就是倍數關系了,假設把快慢指針比作一條道路上的車,快車的速度是慢車的兩倍,同時出發,那么快車到達終點的時候慢車就在這條路的中間位置!

但是到鏈表里就得注意元素個數奇偶的問題,奇數直接返回slow,偶數的話,返回slow和slow下一個數的和除2

代碼:

package com.mine.leetcode;

import java.util.List;

public class Solution141 {
    public int getMidElement(ListNode head) {
        ListNode fast = head;
        ListNode slow = head;
        while(fast!=null&&slow!=null) {
            //System.out.println("-"+fast.val);
            if(fast.next==null)
                return slow.val;
            else if(fast.next!=null&&fast.next.next==null)
                return (slow.val+slow.next.val)/2;
            else {
                fast = fast.next.next;
                slow = slow.next;
            }
        }
        return 666;
    }
    public static ListNode generateListByArray(int[] nums) {
        ListNode head = new ListNode(0);
        ListNode temp = head;
        for(int i = 0;i < nums.length;i++) {
            temp.next = new ListNode(nums[i]);
            temp = temp.next;
        }
        return head.next;
    }
    
    public static void main(String[] args) {
        int[] nums = {1,2,3,4,5,6,7};
        System.out.println(new Solution141().getMidElement(generateListByArray(nums)));
    }
}
View Code

 

三,輸出鏈表的倒數第K個節點

也是跟上面差不多的原理,第一個指針從鏈表的頭指針開始遍歷向前走k-1步,第二個指針保持不動;從第K步開始,第二個指針也開始從鏈表的頭指針開始遍歷。由於兩個指針的距離保持在k-1,當第一個指針到達鏈表的尾節點時候,第二個指針正好是倒數第K個節點

代碼:

package com.mine.leetcode;

import java.util.List;

public class Solution141 {
    // 查找單鏈表中倒數第K個結點  
    public ListNode GetKthNode(ListNode pHead, int k) // 函數名前面的R代表反向  
    {  
        if(k == 0 || pHead == null) // 這里k的計數是從1開始的,若k為0或鏈表為空返回NULL  
            return null;  
      
        ListNode pAhead = pHead;  
        ListNode pBehind = pHead;  
            for(int i=0;i<k-1;i++){  
               pAhead=pAhead.next;  
               if(pAhead==null)  return null;//當鏈表長度小於k時候,返回Null  
            }  
        while(pAhead.next != null)  // 前后兩個指針一起向前走,直到前面的指針指向最后一個結點  
        {  
            pBehind = pBehind.next;  
            pAhead = pAhead.next;  
        }  
        return pBehind;  // 后面的指針所指結點就是倒數第k個結點  
    }  

    public static void main(String[] args) {
        int[] nums = {1,2,3,4,5,6,7};
        System.out.println(new Solution141().GetKthNode(generateListByArray(nums), 2).val);
    }
}
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM