判断单链表有环的三种方法

判断链表是否有环的三种方法 

1. 在节点ListNode中增加一个域,用于记录此节点是否已经被访问,如下ListNode中被注释掉代码。此方法简单,能找出环开始的节点,但是增加了链表的开销。如果链表非常大 则需要十分大的内存来保存此域。

2. 使用链表逆序的方法。从头结点开始一直将链表逆序,头结点的next域为空。如果有环的话链表逆序必定会回到头节点而终止。这种做法同样简单,确保O(n)时间终止算法。但是修改了链表结构。原链表已经被改变。但是不能找出环开始的节点

3. 使用两个变量赛跑,一个变量走两步/次,一个变量走一步/次。 如果有环则两个变量必定会相逢,其中快的变量比慢的变量多走一圈。此算法 如果链表的环非常大 则需要较大的遍历时间。此算法同时也能找出环开始的地方

 

  class ListNode {
      int val;
      ListNode next;
// Boolean visited=false;  
     ListNode(int x) {
          val = x;
         next = null;
      }
  }

方法一、 

 public class Solution {
    public boolean hasCycle(ListNode head) {
      if (head == null || head.next == null)
			return false;
	while(head!=null){
		if(head.visited==false)
		   head.visited=true;
		else
		   return true;  //同时第一个vistited为true的节点即为环开始的节点。
		head=head.next;
	}
	return false;
    }
}

 

方法二、 

public class Solution {
 public boolean hasCycle(ListNode head) {
      if (head == null || head.next == null)
			return false;


		ListNode p = head;
		ListNode q = head.next;
		ListNode k = head.next.next;


		while (k != null) {
			if (p == k || k == head)
				return true;

			if (p == head)
				p.next = null;

			q.next = p;

			p = q;
			q = k;
			k = k.next;
		}
		return false;
    }
}
			return false;


		ListNode p = head;
		ListNode q = head.next;
		ListNode k = head.next.next;


		while (k != null) {
			if (p == k || k == head)
				return true;


			if (p == head)
				p.next = null;


			q.next = p;


			p = q;
			q = k;
			k = k.next;
		}
		return false;
    }
}


方法三、 

/*找出环开始的节点证明:设链表长度为N(每个节点访问一次) 链表头到达环开始节点长度为 s ,环的大小为S因为 快节点比慢节点多跑一圈 到达相遇节点, 设n为循环的次数。 所以有 2*n-n=S =》 n=S,即到达相遇节点的时候慢节点相当于刚好走了一个环的大小。所以慢节点走完链表N剩下的节点为N-S。而从头节点到环开始的距离s =N-S。所以从头结点开始和慢节点同时再走N-S步即能在环开始的地方相遇。*/

public class Solution {
    public ListNode detectCycle(ListNode head) {
        
		ListNode meetNode = fineNode(head);

		if (meetNode == null)   //有相遇的节点就说明有环,没有就没有环
			return null;

    while (meetNode != head) {
			head = head.next;
			meetNode = meetNode.next;
		}

		return meetNode;
    }
    
    public static ListNode fineNode(ListNode head) {
		if (head == null)
			return null;

		ListNode fast = head;
		ListNode slow = head;

		while (fast != null && fast.next != null) {   //两个变量赛跑,找出相遇的节点
			fast = fast.next.next;
			slow = slow.next;
			if (fast == slow) {
				return slow;
			}
		}
		return null;
	}
}
 
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值