数据结构之链表面试题汇总(三)判断单链表是否有环、取出环的起始点、得到有环链表中环的长度

title: 数据结构之链表面试题汇总(三)判断单链表是否有环、取出环的起始点、得到有环链表中环的长度
date: 2016-08-18 9:14:00
categories: 数据结构

版权声明:本站采用开放的[知识共享署名-非商业性使用-相同方式共享 许可协议]进行许可

所有文章出现的代码,将会出现在我的github中,名字可以根据类全名来找,我在github中的文件夹也会加目录备注。


判断单链表是否有环

思路:

  • 首先判断链表是否为空,为空抛异常
  • 利用”双指针“方法:
    • 一个指针每次移动一个节点,另外一个指针每次移动两个节点,如果第一个指针所对应的节点等于第二个指针所对应的节点,那么这个链表有环
    • 在这里需要注意传入来链表的节点数

图解:

代码实现:

public static boolean hasLoopReturnBoolean(Node head) {
    Node first = head;
    Node second = head;
    // if the head is null return exception
    if (head == null || head.getNext() == null)
        return false;
    // move first on step backward and the second move twice at once
    // if the condition of the judgement without the second.getNext()!=null
    // when it reach the tail it will raise the NPE
    while (second != null && second.getNext() != null) {
        first = first.getNext();
        second = second.getNext().getNext();
        // if first=second return true
        if (first == second)
            return true;
    }
    // else false
    return false;
}

测试代码:有环

public class ReverseLinkedListTest {

    public static void main(String[] args) {
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        node1.setNext(node2);
        node2.setNext(node3);
        node3.setNext(node4);
        node4.setNext(node5);
        node5.setNext(node3);

        System.out.println(HasLoop.hasLoopReturnBoolean(node1));
    }

}

运行结果:

测试代码:无环:即把第五个节点的设置下一个节点的代码注释掉

public class ReverseLinkedListTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        node1.setNext(node2);
        node2.setNext(node3);
        node3.setNext(node4);
        node4.setNext(node5);
        // node5.setNext(node3);

        System.out.println(HasLoop.hasLoopReturnBoolean(node1));
    }

}

运行结果:

有环单链表中,得到环的起始点

思路:

可以借助上一题中判断是否有环的方法,在循环中判断first=second的时候,如果相等,直接返回first或者second即可。

代码实现:

public static Node hasLoopReturnNode(Node head) {
    Node first = head;
    Node second = head;
    // if the head is null return exception
    if (head == null || head.getNext() == null)
        return null;
    // move first on step backward and the second move twice at once
    // if the condition of the judgement without the second.getNext()!=null
    // when it reach the tail it will raise the NPE
    while (second != null && second.getNext() != null) {
        first = first.getNext();
        second = second.getNext().getNext();
        // if first=second return true
        if (first == second)
            return first;
    }
    // else without loop
    return null;
}

测试代码:有环

public class ReverseLinkedListTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        node1.setNext(node2);
        node2.setNext(node3);
        node3.setNext(node4);
        node4.setNext(node5);
        node5.setNext(node3);

        System.out.println(HasLoop.hasLoopReturnNode(node1).getRecord());
    }

}

运行结果:

无环测试代码:

public class ReverseLinkedListTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        node1.setNext(node2);
        node2.setNext(node3);
        node3.setNext(node4);
        node4.setNext(node5);
        // node5.setNext(node3);

        System.out.println(HasLoop.hasLoopReturnNode(node1).getRecord());
    }

}

运行结果:

如果没有环,返回的是null,如果要读取里面的数据,就会抛空指针异常

得到有环链表中环的长度

思路:

  • 继续继承判断链表是否有环的方法,只不过在判断的时候,把一个链表的头节点传到函数中
  • 首先获取该链表的环开始的节点
  • 再定义两个变量来记录返回节点信息,即环开始的节点
  • 一个留作备用,另外一个用来比较
  • 再定义一个变量来记录环的长度
  • 循环是死循环,因为有环链表永远到不了头
  • 通过判断现在的节点是否等于环开始节点来跳出循环,并且返回环长度

代码实现:

public static int getCycleLength(Node head) {
        // define the variable to record the length
        int length = 0;
        // judge the list has the loop or not
        Node loop = hasLoopReturnNode(head);
        // juege the head is null,
        if (loop == null)
            // true return 0
            return length;
        // while the head=current the return the length
        Node flat = loop;
        Node current = loop;
        while (current != null) {
            current = current.getNext();
            length++;
            if (current == flat) {
                return length;
            }
        }
        return length;
    }

测试代码:有环

public class ReverseLinkedListTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        node1.setNext(node2);
        node2.setNext(node3);
        node3.setNext(node4);
        node4.setNext(node5);
        node5.setNext(node3);

        System.out.println(HasLoop.getCycleLength(node1));
    }

}

运行结果:

测试代码:无环:

public class ReverseLinkedListTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        Node node1 = new Node(1);
        Node node2 = new Node(2);
        Node node3 = new Node(3);
        Node node4 = new Node(4);
        Node node5 = new Node(5);
        node1.setNext(node2);
        node2.setNext(node3);
        node3.setNext(node4);
        node4.setNext(node5);
        // node5.setNext(node3);

        System.out.println(HasLoop.getCycleLength(node1));
    }

}

运行结果:


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值