zoukankan      html  css  js  c++  java
  • 判断链表循环-算法详细分析

    题目:判断循环链表

    给定一个链表,判断链表中是否有环。
    为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。
    如果 pos 是 -1,则在该链表中没有环。

    示例 1:

        输入:head = [3,2,0,-4], pos = 1
        输出:true
        解释:链表中有一个环,其尾部连接到第二个节点。
    

    示例 2:

        输入:head = [1,2], pos = 0
        输出:true
        解释:链表中有一个环,其尾部连接到第一个节点。
    

    示例 3:

        输入:head = [1], pos = -1
        输出:false
        解释:链表中没有环
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
    
     * @author cosefy
    
     * @date 2020/6/9
     */
    //创建结点类
    class ListNode {
        int val;
        ListNode next;
       //构造函数
        ListNode(int x) {
            val = x;
            next = null;
        }
       //添加结点的方法,返回的结点是添加后的结点
        public ListNode add(ListNode node) {
            this.next = node;
            return node;
        }
    }
    //主类
    public class HasCycle {
        public static void main(String[] args) {
            List<Integer> list = new ArrayList<>();
            list.add(1);
            list.add(2);
            int pos = 1;
            ListNode head = getLinkedList(list, pos); //调用创建链表方法
            boolean b = hasCycle_Test1(head);    //调用判断链表是否循环的方法
            System.out.println(b);
        }
    
    解法一:双指针法:
    **思路**:利用快慢指针,每次慢指针向后移动一次,快指针移动两次,若链表为循环链表,则快慢指针有相等的情况;若链表不为循环链表
        则快指针会指向null。
    **分析**: 时间复杂度为O(n),运行效率很高
    **易错点**:注意空指针异常的情况,不要直接移动快指针两次,移动之前要判断是否为空。
    
     public static boolean hasCycle_Test1(ListNode head) {
            if(head==null)
                return false;
            ListNode slow_node = head;
            ListNode fast_node = head;
            while(true){
                if(fast_node.next==null )
                    return false;
                if(fast_node.next.next!=null){
                    slow_node=slow_node.next;
                    fast_node=fast_node.next.next;
                }else{
                    return false;
                }
                if(fast_node==slow_node)
                    return true;
            }
        }
    
    //解法二:哈希表
    /*
    思路:粗放结点到哈希表中,若结点尾部为空,说明不循环,若遍历的当前结点和哈希表的存的已有结点相同,则说明循环。
    分析:时间和空间复杂度都为O(n)
    代码不再单独写出
     */
    

    根据列表创建链表,并返回首结点:

     public static ListNode getLinkedList(List<Integer> list, int pos) {
            if(pos+1>list.size()) {
                System.out.println("结点个数"+ list.size()+" 插入结点位置: "+pos);
                throw new IllegalArgumentException("非法参数异常");
            }
            if (list.size() == 0)
                return null;
            ListNode first = new ListNode(list.get(0));
            ListNode cur = first;
            for (int i = 0; i < list.size(); i++) {
                if (i == 0)
                    continue;
                cur = cur.add(new ListNode(list.get(i))); //添加结点
            }
            if (pos != -1)
                cur.next = getLinkedNode(first, pos);  //将尾结点指向指定位置的结点
            return first;
        }
    

    ​ 函数返回指定位置的结点:

        public static ListNode getLinkedNode(ListNode head, int pos) {
    ​        int i = 0;
    ​        while (i < pos) {
    ​            i++;
    ​            head = head.next;
    ​        }
    ​        return head;
    ​        //  throw new IllegalArgumentException("非法参数异常");
    
    ​    }
    
    }
    
  • 相关阅读:
    Constants and Variables
    随想
    C#基础篇之语言和框架介绍
    Python基础19 实例方法 类方法 静态方法 私有变量 私有方法 属性
    Python基础18 实例变量 类变量 构造方法
    Python基础17 嵌套函数 函数类型和Lambda表达式 三大基础函数 filter() map() reduce()
    Python基础16 函数返回值 作用区域 生成器
    Python基础11 List插入,删除,替换和其他常用方法 insert() remove() pop() reverse() copy() clear() index() count()
    Python基础15 函数的定义 使用关键字参数调用 参数默认值 可变参数
    Python基础14 字典的创建修改访问和遍历 popitem() keys() values() items()
  • 原文地址:https://www.cnblogs.com/cosefy/p/13070500.html
Copyright © 2011-2022 走看看