单向链表的闭环判断


单向链表,只能访问next元素,如何判断是否存在环?

 

最简单的方案,不考虑空间复杂度,我们会想到使用一个Set来保存集合,用来记录已经访问过的元素

/**
     * 最简单的算法,但需要的空间比较高,一个Set集合
     * @param link
     * @param <T>
     * @return
     */
    public static <T>  boolean containsCircle1(Link<T> link) {
        if(link == null){
            return false;
        }
        T value = link.getValue();
        Set<T> values = new HashSet<T>();
        values.add(value);
        while ((link = link.getNext()) != null){
            if(link == null){
                return false;
            }
            value = link.getValue();
            if (values.contains(value)) {
                return true;
            }
        }
        return false;
    }

 

 

这会浪费O(n)的空间,效率低下,如果链表长度过长,占用的空间会非常大,考虑一下有无其他简便的方法?

 

使用两个指针,分别以不同的速度向前遍历,一个以单个元素为步长,另一个以两个元素为步长,如果两个元素步长的指针追上了后面的指针,这便证明该链表中存在环。这样,只需要额外的两个空间,空间复杂度为O(1)

 

/**
     * 使用两个指针,一个以速度1前进,另一个以速度2前进,如果存在闭环,则必定会出现交叉碰面
     * @param link
     * @param <T>
     * @return
     */
    public static <T> boolean containsCircle2(Link<T> link) {
        if (link == null || link.getNext() == null) {
            return false;
        }
        Link<T> first = link;
        Link<T> second = link.getNext();
        while (second != null && second.getNext() != null && second.getNext().getNext() != null) {
            first = first.getNext();
            second = second.getNext().getNext();
            if (first.getValue() == second.getValue()) {
                return true;
            }
        }
        return false;
    }

 

 

 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值