两个单链表相交的一系列问题(offer收割)

题目

给定两个链表的头结点,返回它们相交的第一个节点,如果不相交,则返回null。注意:两个链表都可能含有环。

要求

时间复杂度O(N),空间复杂度O(1)。

代码

package com.iqiyi;

import org.junit.Assert;
import org.junit.Test;

public class Code2_11 {
	public static class Node{
		int data;
		Node next;
		Node(int data){
			this.data=data;
		}
	}
	
	public static Node getLoopNode(Node node){
		if(node==null||node.next==null||node.next.next==null)
			return null;
		Node slow=node.next;
		Node fast=node.next.next;
		while(slow!=fast){
			if(fast.next==null||fast.next.next==null)
				return null;
			slow=slow.next;
			fast=fast.next.next;
		}
		fast=node;
		while(fast!=slow){
			fast=fast.next;
			slow=slow.next;
		}
		return fast;
	}
	
	public static Node getNoLoop(Node head1,Node head2){
		Node temp1=head1;
		int length1=0;
		while(temp1.next!=null){
			temp1=temp1.next;
			length1++;
		}
		Node temp2=head2;
		int length2=0;
		while(temp2.next!=null){
			temp2=temp2.next;
			length2++;
		}
		if(temp1!=temp2)
			return null;
		Node c1=null;
		Node c2=null;
		int d=0;
		if(length1>length2){
			c1=head1;
			c2=head2;
			d=length1-length2;
		}
		else{
			c1=head2;
			c2=head1;
			d=length2-length1;
		}
		while(d>0){
			c1=c1.next;
			d--;
		}
		while(c1!=c2){
			c1=c1.next;
			c2=c2.next;
		}
		return c1;
	}
	
	public static Node getBothLoop(Node head1,Node loop1,Node head2,Node loop2){
		if(loop1==loop2){
			Node temp1=head1;
			int length1=0;
			while(temp1.next!=loop1){
				temp1=temp1.next;
				length1++;
			}
			Node temp2=head2;
			int length2=0;
			while(temp2.next!=loop2){
				temp2=temp2.next;
				length2++;
			}
			Node c1=null;
			Node c2=null;
			int d=0;
			if(length1>length2){
				c1=head1;
				c2=head2;
				d=length1-length2;
			}
			else{
				c1=head2;
				c2=head1;
				d=length2-length1;
			}
			while(d>0){
				c1=c1.next;
				d--;
			}
			while(c1!=c2){
				c1=c1.next;
				c2=c2.next;
			}
			return c1;
		}
		else{
			while(loop1.next!=loop1){
				if(loop1==loop2)
					return loop1;
				loop1=loop1.next;
			}
			return null;
		}
	}
	
	public static Node getIntersectantNode(Node head1,Node head2){
		if(head1==null||head2==null)
			return null;
		Node loop1=getLoopNode(head1);
		Node loop2=getLoopNode(head2);
		if(loop1==null&&loop2==null)
			return getNoLoop(head1, head2);
		if(loop1!=null&&loop2!=null)
			return getBothLoop(head1, loop1, head2, loop2);
		return null;
	}
	
	@Test
	public void test1(){
		Node node0=new Node(1);
		Node node1=new Node(2);
		Node node2=new Node(3);
		Node node3=new Node(4);
		Node node4=new Node(5);
		Node node5=new Node(6);
		Node node6=new Node(7);
		Node node7=new Node(8);
		node0.next=node1;
		node1.next=node2;
		node2.next=node3;
		node3.next=node4;
		node4.next=node5;
		node5.next=node6;
		node6.next=node7;
		node7.next=node3;
		
		Node node8=new Node(11);
		Node node9=new Node(10);
		Node node10=new Node(9);
		node8.next=node9;
		node9.next=node10;
		node10.next=node2;
		
		Node ans=getIntersectantNode(node0, node8);
		Assert.assertNotNull(ans);
		Assert.assertTrue(ans.data==3);
	}

}
复制代码

转载于:https://juejin.im/post/5c4001b5f265da615d72e39f

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值