美文网首页
Floyd循环检测算法 快慢指针的三个例子

Floyd循环检测算法 快慢指针的三个例子

作者: 饱饱抓住了灵感 | 来源:发表于2023-11-27 22:09 被阅读0次

算法概述

Floyd循环检测算法,也被称为龟兔赛跑算法,或者快慢指针,是一种可以在链表或数组等线性结构中使用的技术。

此技术通过同时使用两个指针,一个快指针和一个慢指针来遍历一个数据结构。通常来说,快指针每次移动两个节点,而慢指针每次只移动一个节点

它的主要优点是它可以在单次遍历中解决以上的问题,从而使得算法效率高。

在使用快慢指针时,通常需要注意的是可能出现的边界条件,例如链表为空或只有一个或两个节点的情况。

三个例子

1. 找到链表的中点

首先创建两个指针,slowPtrfastPtr,都初始化为头节点。

然后,只要fastPtrfastPtr.next不为null,就将fastPtr向前移动两个节点,slowPtr向前移动一个节点。

fastPtr无法再前进时,slowPtr将位于链表的中点。

Java实现:

class Node {
    int data;
    Node next;
  
    Node(int data) {
        this.data = data;
        next = null;
    }
}

public Node findMiddle(Node head) {
    Node slowPtr = head;
    Node fastPtr = head;
  
    if (head != null) {
        while (fastPtr != null && fastPtr.next != null) {
            fastPtr = fastPtr.next.next;
            slowPtr = slowPtr.next;
        }
    }
  
    return slowPtr;
}
2. 检测链表中是否有环

首先创建两个指针,slowfastslow指针每次移动一个节点,fast指针每次移动两个节点。

如果在某个时刻,slowfast指向同一节点,那么链表中存在环。

如果fast指针到达链表的末尾(即fastfast.next为null),那么链表中不存在环。

Java实现:

class Node {
    int data;
    Node next;

    Node(int data) {
        this.data = data;
        next = null;
    }
}

public boolean hasCycle(Node head) {
    if (head == null) {
        return false;
    }

    Node slow = head;
    Node fast = head.next;

    while (slow != fast) {
        if (fast == null || fast.next == null) {
            return false;
        }
        slow = slow.next;
        fast = fast.next.next;
    }

    return true;
}
3. 找到两个链表的交叉点

找到两个链表交叉点通常包括3个步骤:

  1. 我们将遍历两个链表以确定他们的长度及是否相交。
  2. 我们将使两个指针同时从两个链表的头部开始,但是较长的那个链表的指针会先移动“长度差”的步数。
  3. 两个指针将同时移动,当他们相遇时,那个点就是链表的交叉点。

Java实现:

  static class ListNode {
        int data;
        ListNode next;

        ListNode(int data) {
            this.data = data;
            next = null;
        }
    }

    public ListNode getIntersectionListNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }

        ListNode p1 = headA;
        ListNode p2 = headB;

        int length1 = 1;
        int length2 = 1;

        // 两个指针移动到尾部
        while (p1.next != null) {
            p1 = p1.next;
            length1++;
        }
        while (p2.next != null) {
            p2 = p2.next;
            length2++;
        }

        // 如果尾部不同, 则无交叉点
        if (p1 != p2) return null;

        // 将两个指针移动到头部
        p1 = headA;
        p2 = headB;

        // 较长的指针先走一段
        int diff = length1 - length2;
        if (diff > 0) {
            for (int i = 0; i < diff; i++) {
                p1 = p1.next;
            }
        } else if (diff < 0) {
            for (int i = diff; i < 0; i++) {
                p2 = p2.next;
            }
        }

        // 两个指针同时移动, 直到他们相遇
        while (p1 != p2) {
            p1 = p1.next;
            p2 = p2.next;
        }

        return p1;
    }

相关文章

  • 判断单链表环的快慢指针法

    快慢指针法 算法步骤 初始化快慢指针 循环处理,快指针走两步,慢指针走一步,直到发现环或者到达链表结尾 伪代码 环...

  • 判环算法以及链表常见算法题

    由于涉及到Floyd判环算法,故先简单阐述一下Floyd判环算法原理。Floyd判环算法算法原理:设置两个指针同时...

  • LeetCode进阶977-双指针

    概要 双指针是一种比较常见的算法思想,在循环遍历数组时经常会用到。双指针主要有两种算法技巧:1、快慢指针(例如已发...

  • 转载 闲聊判圈算法

    转载 闲聊判圈算法floyd(Floyd cycle detection) 问题:如何检测一个链表是否有环,...

  • 【刷题方法总结】快慢指针法

    1. 快慢指针法方法详解 在外网中,该方法又称为“Floyd’s Cycle-Finding Algorithm”...

  • 基础算法解决相对应问题思路(二)

    回顾基础算法定义一个链表 1. 如何证明给定的链表是否包含循环?如何找到循环的头节点? 思路: 还是利用快慢指针解...

  • 循环链表:快慢指针

    解决方案1:循环链表遍历放入数组,然后循环看节点是否存在于数组中,比较简单,就不实现了解决方案2:快慢指针

  • 142. Linked List Cycle II

    我们要保证快慢指针相遇时的迭代次数相同,于是快慢指针应该时从相同的位置出发,但是循环跳出的条件时相等,于是将快慢指...

  • 快慢指针的算法应用

    快慢指针主要解决的问题: 寻找/删除第K个节点; 有关链表环问题解法:寻找/删除第K个节点。 问题一: 给定任意一...

  • 快慢指针的应用

    快慢指针 快慢指针中的快慢指的是移动的步长,快慢分别指的是快指针每次移动两步,满指针每次移动一步 快慢指针的应用 ...

网友评论

      本文标题:Floyd循环检测算法 快慢指针的三个例子

      本文链接:https://www.haomeiwen.com/subject/msdtgdtx.html