leetcode-160- 相交链表(intersection of two linked list)-java

题目及测试

package pid160;
/*   相交链表

编写一个程序,找到两个单链表相交的起始节点。

 

例如,下面的两个链表:

A:          a1 → a2
                   ↘
                     c1 → c2 → c3
                   ↗            
B:     b1 → b2 → b3

在节点 c1 开始相交。

 

注意:

    如果两个链表没有交点,返回 null.
    在返回结果后,两个链表仍须保持原有的结构。
    可假定整个链表结构中没有循环。
    程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

 

致谢:
特别感谢 @stellari 添加此问题并创建所有测试用例。



*/
public class main {
	
public static void main(String[] args) {
		ListNode c=new ListNode(0);
		c.next=new ListNode(-1);
		
		LinkList a=new LinkList(1);
		a.addLast(2);
		a.addLast(3);
		a.first.next.next.next=c;
		a.printList();
		//test(a.first);
		
		LinkList b=new LinkList(5);
		b.addLast(6);
		b.addLast(4);
		b.addLast(2);
		b.first.next.next.next.next=c;
		b.printList();
		test(a.first,b.first);		
		/*
		LinkList c=new LinkList(1);
		c.addLast(2);
		c.addLast(2);
		c.addLast(1);
		c.printList();
		//test(c.first);
		
		
		LinkList d=new LinkList(1);
		d.addLast(2);
		d.addLast(3);
		
		c.printList();		
		d.printList();
		test(c.first,d.first);*/
	}
		 
	private static void test(ListNode ito,ListNode ito2) {
		Solution solution = new Solution();
		ListNode rtn;
		long begin = System.currentTimeMillis();
		System.out.println();
		//开始时打印数组
		
		rtn=solution.getIntersectionNode(ito,ito2);//执行程序
		long end = System.currentTimeMillis();	
		System.out.println("rtn=");
		rtn.printNodeToEnd();
		
		//System.out.println(":rtn" );
		//System.out.print(rtn);
		System.out.println();
		System.out.println("耗时:" + (end - begin) + "ms");
		System.out.println("-------------------");
	}

}

解法1(成功,2ms,超快)

首先有一点非常重要,相交节点后的所有节点 (包括相交节点) 都是两个链表共享的。

我们将两个链表的右端对齐,长度较大的链表 的左端的 多出来的节点 肯定不是相交节点,所以我们不考虑左端的这一部分的节点

使用双指针算法,先遍历一遍两个链表的长度,再将两个指针指向两个链表头部,移动长的链表的指针,指向相同距离的位置,再两个指针一起走,如果指针相遇,则得到相同节点

package pid160;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if(headA==null||headB==null){
    	return null;
    }
    int lengthA=0;
    int lengthB=0;
    ListNode now=headA;
    while(now!=null){
    	lengthA++;
    	now=now.next;
    }
    now=headB;
    while(now!=null){
    	lengthB++;
    	now=now.next;
    }
    ListNode nowA=headA;
    ListNode nowB=headB;
    if(lengthA>lengthB){
    	for(int i=0;i<lengthA-lengthB;i++){
    		nowA=nowA.next;
    	}
    }
    if(lengthA<lengthB){
    	for(int i=0;i<lengthB-lengthA;i++){
    		nowB=nowB.next;
    	}
    }
    ListNode result=null;
    while(true){
    	if(nowA==nowB){
    		result=nowA;
    		break;
    	}
    	if(nowA==null||nowB==null){
    		break;
    	}
    	nowA=nowA.next;
    	nowB=nowB.next;    	
    }   	
	return result;
    }
}

解法2(别人的)

其实思路和解法1一样,都是双指针,等指针在两个链表的相同位置后,开始比较

我们需要做的事情是,让两个链表从同距离末尾同等距离的位置开始遍历。这个位置只能是较短链表的头结点位置。
为此,我们必须消除两个链表的长度差

指针 pA 指向 A 链表,指针 pB 指向 B 链表,依次往后遍历
如果 pA 到了末尾,则 pA = headB 继续遍历
如果 pB 到了末尾,则 pB = headA 继续遍历
比较长的链表指针指向较短链表head时,长度差就消除了
如此,只需要将最短链表遍历两次即可找到位置

 

即假设有长度A和B,A长,

双指针从A跑完,pA跑了长度A,到B的headB

pB从B跑,B跑完跑了B,再到A的headA,跑了A-B,

此时pA在B的headB,pB在A的A-B处,是相同的位置。

 

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (headA == null || headB == null) return null;
    ListNode pA = headA, pB = headB;
    while (pA != pB) {
        pA = pA == null ? headB : pA.next;
        pB = pB == null ? headA : pB.next;
    }
    return pA;
}

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值