链表的快慢指针

快慢指针应用

 

1.求链表的中间结点

(1)最开始slow与fast都指向链表的第 1 个有效结点

(2)fast的移动步长为slow的两倍:slow移动一格,fast移动两格

(3)当fast移动到最后一个结点时,slow移动到中间位置

(4)当链表有效节点个数为偶数:中间结点是第 length / 2 个

 

2.单链表是否有环

(1)最开始slow与fast都指向链表的第 1 个有效结点

(2)fast的移动步长为slow的两倍:slow移动一格,fast移动两格;先移动,后检测

(3)单链表无环:快慢指针不可能相遇,快指针到达链表结尾,返回false

(4)单链表有环:快指针先进入环,一直循环运动,直到慢指针进入循环且两指针相遇,返回true

 

3.求有环链表的入口

(1)判断到链表是否有环,此时快慢指针相遇

(2)重新设定一个指针 temp 指向链表的第 1 个有效结点,步长与慢指针一样为1

(3)同时移动慢指针、指针 temp,直到两者相遇,慢指针与指针 temp 相遇的地方就是环的入口

 

代码实现

注:单向链表实现快慢指针应用

class Node {//该节点省略data域
    public int no;
    public Node next;

    public Node(int no) {
        if (no >= 0) {//要求no要大于0
            this.no = no;
        }
    }

    @Override
    public String toString() {
        return "Node{" +
                "no=" + no +
                '}';
    }
}

public class SingleLinkedList {//单向链表
    public Node head = new Node(0);//头节点,不包含数据

    //求链表的中间节点
    public Node getMid() {
        if (head.next == null) {
            return null;
        }
        Node fast = head.next;
        Node slow = head.next;
        while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow;
    }

    //判断链表是否有环
    public boolean isCircle() {
        if (head.next == null) {
            return false;
        }
        Node fast = head.next;
        Node slow = head.next;
        while (fast.next != null && fast.next.next != null) {
            fast = fast.next.next;
            slow = slow.next;
            if (fast.equals(slow)) {//快慢指针指向了同一个结点,证明有环
                return true;
            }
        }
        return false;//快指针到链表尾,证明无环
    }

    //求链表的环入口
    public Node getEntrance() {
        if (head.next == null) {
            return null;
        }
        Node fast = head.next;
        Node slow = head.next;
        Node temp = null;
        while (fast.next != null && fast.next.next != null) {//先判断链表是否有环
            fast = fast.next.next;
            slow = slow.next;
            if (fast.equals(slow)) {
                temp = head.next;
                break;
            }
        }
        //若存在环:temp = null;若不存在环:temp != null
        while (!slow.equals(temp) && temp != null) {
            temp = temp.next;
            slow = slow.next;
        }
        return temp;
    }

    public void add(Node node) {//节点加入链表尾
        Node temp = head;
        while (true) {
            if (temp.no == node.no) {//该编号节点已存在
                return;
            } else if (temp.next == null) {
                break;
            }
            temp = temp.next;
        }
        temp.next = node;
    }
}

 

posted @   半条咸鱼  阅读(105)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 没有源码,如何修改代码逻辑?
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
点击右上角即可分享
微信分享提示