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("非法参数异常");
    
    ​    }
    
    }
    
  • 相关阅读:
    令人抓狂的redis和rediscluster Python驱动包的安装
    基于Docker的Consul集群实现服务发现
    应用中引入缓存层后,缓存和持久化层数据一致性的思考
    Redis中几个简单的概念:缓存穿透/击穿/雪崩,别再被吓唬了
    Redis Cluster 自动化安装,扩容和缩容
    mysql 8.0 忘记root密码后重置
    MySQL 8.0部分弃用的参数整理
    MySQL Online DDL与DML并发阻塞关系总结
    MySQL Error Log 文件丢失导致The server quit without updating PID file启动失败的场景
    MySQL删除大表时潜在的问题(drop table,truncate table)
  • 原文地址:https://www.cnblogs.com/cosefy/p/13070500.html
Copyright © 2011-2022 走看看