利用快慢指针解决中间值问题,单向链表是否有环问题以及有环链表入口问题。

利用快慢指针解决中间值问题,单向链表是否有环问题以及有环链表入口问题

1. 中间值问题;
2. 单向链表是否有环问题;
3. 有环链表入口问题;

快慢指针: 快慢指针指的是定义两个指针,这两个指针的移动速度一快一慢,以此来制造出自己想要的差值,这个差值可以让我们找到链表是哪个相应的结点,已满情况下,快指针的移动步长为慢指针的两倍。

中间值问题:
当快指针走到尾部的时候,慢指针恰恰走到中间的位置;
在这里插入图片描述代码如下:

public class FastSlowTest {
    public static void main(String[] args) {
        Node<String> first = new Node<>("aa", null);
        Node<String> second = new Node<>("bb", null);
        Node<String> third = new Node<>("cc", null);
        Node<String> fourth = new Node<>("dd", null);//
        Node<String> fifth = new Node<>("ee", null);
        Node<String> sixth = new Node<>("ff", null);
        Node<String> seventh = new Node<>("gg", null);


        //完成结点之间的指向
        first.next = second;
        second.next = third;
        third.next = fourth;
        fourth.next = fifth;
        fifth.next = sixth;
        sixth.next = seventh;
        

     //查找中间值,在查找中间值的问题的时候需要把产生环去掉
        String mid = getMid(first);
        System.out.println("中间值为:"+mid);
    }
    /**
     * 查找中间值问题
     *      * @param first 链表的首结点
     *      * @return  链表的中间结点的值
     */
    public static String getMid(Node<String> first){
        //定义两个指针
       Node<String> fast = first;//快指针,是slow指针的二倍速度
       Node<String> slow = first;//慢指针

        //使用两个指针遍历链表,当快指针指向的结点没有下一个结点,就可以结束了
        while (fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
        }
        return slow.item;
    }
    //结点类
    public static class Node<T>{
        //存储数据
       T item;
        //下一个结点
        Node next;

        //构造函数
        Node(T item,Node next){
            this.item = item;
            this.next = next;
        }
    }
}

单向链表是否有环问题
使用快慢指针的思想,还是把链表比作一条跑道,链表中有环,那么这条跑道就是一条圆环跑道,在一条圆环跑道中,两个人有速度差,那么迟早两个人会相遇,只要相遇就说明有环。
在这里插入图片描述代码入下:

package cn.itcast.demo.day02.Demo02;

public class FastSlowTest {
    public static void main(String[] args) {
        Node<String> first = new Node<>("aa", null);
        Node<String> second = new Node<>("bb", null);
        Node<String> third = new Node<>("cc", null);
        Node<String> fourth = new Node<>("dd", null);//
        Node<String> fifth = new Node<>("ee", null);
        Node<String> sixth = new Node<>("ff", null);
        Node<String> seventh = new Node<>("gg", null);


        //完成结点之间的指向
        first.next = second;
        second.next = third;
        third.next = fourth;
        fourth.next = fifth;
        fifth.next = sixth;
        sixth.next = seventh;
        //产生环
        seventh.next = third;
    
        //判断是否有环
        boolean circle = isCircle(first);
        System.out.println("first链表中是否有环:"+circle);


    }
     /* 判断链表中是否有环
     * @param first 链表首结点
     * @return true为有环,false为无环
     */
    public static boolean isCircle(Node<String> first){
        //定义快慢指针
        Node<String> fast = first;
        Node<String> slow = first;

        //遍历链表,如果快慢指针指向了同一个结点,则证明有环
        while (fast != null && fast.next != null){
            fast = fast.next.next;
            slow = slow.next;
            if(fast.equals(slow)){
                return true;
            }
        }
        return false;
    }
    //结点类
    public static class Node<T>{
        //存储数据
       T item;
        //下一个结点
        Node next;

        //构造函数
        Node(T item,Node next){
            this.item = item;
            this.next = next;
        }
    }
}

有环链表入口问题
理论:当快慢指针相遇时候,我们可以判断到链表中有环,这时重新设定一个新指针指向链表的起点,且步长与慢指针一样为1,则慢指针与“新”指针相遇的地方就是环的入口。
在这里插入图片描述代码实现入下:

package cn.itcast.demo.day02.Demo02;

public class FastSlowTest {
    public static void main(String[] args) {
        Node<String> first = new Node<>("aa", null);
        Node<String> second = new Node<>("bb", null);
        Node<String> third = new Node<>("cc", null);
        Node<String> fourth = new Node<>("dd", null);//
        Node<String> fifth = new Node<>("ee", null);
        Node<String> sixth = new Node<>("ff", null);
        Node<String> seventh = new Node<>("gg", null);


        //完成结点之间的指向
        first.next = second;
        second.next = third;
        third.next = fourth;
        fourth.next = fifth;
        fifth.next = sixth;
        sixth.next = seventh;
        //产生环
        seventh.next = third;

        Node entrance = getEntrance(first);
        System.out.println("first链表中环的入口元素为:"+entrance.item);

    }
    /**
     * 查找有环链表中环的入口结点
     * @param first 链表首结点
     * @return 环的入口结点
     */
    public static Node getEntrance(Node<String> first){
        //定义快慢指针
        Node<String> fast = first;
        Node<String> slow = first;
        Node<String> temp = null;

        //遍历链表,先找到环(快慢指针相遇),准备一个临时指针,指向链表的首结点
        //继续遍历,知道慢指针和临时指针相遇,那么相遇是所指向的结点就是环的入口
        while (fast != null && fast.next != null){
            //变换快慢指针
            fast = fast.next.next;
            slow = slow.next;

            //判断快慢指针是否相遇
            if(fast.equals(slow)){
                temp = first;
                continue;
            }

            //让临时结点变换
            if(temp != null){
                temp = temp.next;
                //判断临时指针是否和慢指针重合
                if(temp.equals(slow)){
                    break;
                }
            }
        }
        return temp;
    }
    public static class Node<T>{
        //存储数据
       T item;
        //下一个结点
        Node next;

        //构造函数
        Node(T item,Node next){
            this.item = item;
            this.next = next;
        }
    }
}
发布了22 篇原创文章 · 获赞 21 · 访问量 1386

猜你喜欢

转载自blog.csdn.net/qq_43751200/article/details/104593193
今日推荐