两个单链表相交的一系列问题


//两个单链表相交的一系列问题
public class TwoInterList{
	
	//链表节点的定义
	public static class Node{

		public int value;
		public Node next;

		public Node(int data)
		{
			this.value=data;
		}
	}
  
   //返回两个链表相交的第一个节点(只有两种情况(1)两个链表都无环相交 (2)两个链表都有环相交)
	public static Node getIntersectNode(Node head1,Node head2)
	{
		if(head1==null||head2==null)
		{
			return null;
		}
		Node loop1=getLoop(head1);
		Node loop2=getLoop(head2);
        
        //两个都没有环
		if(loop1==null&&loop2==null)
		{
			return noLoop(head1,head2);
		}
		//两个都有环
		if(loop1!=null&&loop2!=null)
		{
			return bothLoop(head1,loop1,head2,loop2);

		}
		return null;

	}

	//问题一、检验一个链表是否有环,并且返回链表的环的第一个节点
	public static Node getLoop(Node head)
	{

		if(head==null||head.next==null||head.next.next==null)
		{
			return null;
		}
		//此种解法只对1->2->3->1情况下成立
		/**
		Node p=head;
		while(p.next!=null)
		{
            p=p.next;
            if(p==head)
            {
            	return head;

            }
		}
		*/
		Node n1=head.next;    // n1->slow  (一步一步走)
		Node n2=head.next.next; //n2->fast (两步两步走)
		while(n1!=n2)
		{
			if(n2.next==null||n2.next.next==null)
			{
				return null;
			}
			n2=n2.next.next;
			n1=n1.next;
		}
		n2=head; //n2 再次指向head
		while(n1!=n2)
		{
			n1=n1.next;
			n2=n2.next;
		}
		return n1;
	}
   //问题二、检验两个无环链表是否相交,并且返回两个链表相交的第一个节点
	public static Node noLoop(Node head1,Node head2)
	{
           if(head1==null||head2==null)
            {

            	return null;
            }

            Node cur1=head1;
            Node cur2=head2;
            int n=0;

            while(cur1.next!=null)
            {
            	++n;
            	cur1=cur1.next;
            }
            while(cur2.next!=null)
            {
            	--n;
            	cur2=cur2.next;
            }
            //到达最后一个节点如果不相等的话,证明不相交
            if(cur1!=cur2)
            {
           
             return null;
            }
            cur1=n>0?head1:head2; //选取较长的链表
            cur2=cur1==head1?head2:head1; //选取较短的链表

            n=Math.abs(n);
            //较长的链表的链表先走n步
            while(n!=0)
            {
            	--n;
            	cur1=cur1.next;

            }
            while(cur1!=cur2)
            {
            	cur1=cur1.next;
            	cur2=cur2.next;
            }
            return cur1;

	}
	//问题三:判断两个有环链表是否相交,相交则返回第一个相交节点
	public static Node bothLoop(Node head1,Node loop1,Node head2,Node loop2)
	{

		Node cur1=null;
		Node cur2=null;

		if(loop1==loop2)
		{
           cur1=head1;
           cur2=head2;
           int n=0;
           while(cur1!=loop1)
           {
           	n++;
           	cur1=cur1.next;
           }

            while(cur2!=loop2)
           {
           	n--;
           	cur2=cur2.next;
           }
           cur1=n>0?head1:head2;
           cur2=cur1==head1?head2:head1;
           n=Math.abs(n);
           while(n!=0)
           {
           	n--;
           	cur1=cur1.next;
           }
           while(cur1!=cur2)
           {
           	cur1=cur1.next;
           	cur2=cur2.next;
           }
           return cur1;
		}else{

			cur1=loop1.next;
			while(cur1!=loop1)
			{
				if(cur1!=loop2)
				{
                  return loop1;
				}
				cur1=cur1.next;
			}
			return null;
		}
		
	}

	public static void main(String[] args)
	{
	   //System.out.println("Hello");

		Node node=new Node(1);
		node.next=new Node(2);
		node.next.next=new Node(3);
		node.next.next.next=node.next;
     
        Node mode=new Node(1);
		mode.next=new Node(2);
		mode.next.next=new Node(3);
		mode.next.next.next=new Node(4);
		mode.next.next.next.next=mode.next;
       System.out.println(getIntersectNode(node,mode).value);

	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值