剑指offer--两个链表的第一个公共结点

/**
 * 输入两个链表,找出它们的第一个公共结点
 */
package javabasic.nowcoder;

import java.util.HashMap;
import java.util.Map;

public class Main40 {
	
	

	/*分析:两个单链表如果存在第一个公共结点,则后续结点一定都公共,
	因为结点里包含next指针,如果第一个公共结点相同,则next必然相同,
	所以第一个公共结点后链表合并。
	 
	    思路1:设表1长度n,表2长度m,暴力法嵌套遍历两个链表需要O(mn)的时间复杂度,
	 
	    可以采用hash的思想将其中一个转存为哈希表结构,这样建哈希表时间O(m),
	 
	    而遍历链表时间O(n),而遍历时查找哈希表的时间为O(1),因此复杂度降为O(m+n),
	 
	    但需要辅助空间。(这种哈希优化的策略是种一般性的思路,谨记!)
	 
	    */
	public ListNode FindFirstCommonNodeI(ListNode pHead1, ListNode pHead2) {
		if(pHead1==null||pHead2==null)return null;
		ListNode p = pHead1;
		ListNode q = pHead2;
		Map<ListNode,Integer> record = new HashMap<ListNode,Integer>();
		while(p!=null) {
			record.put(p, null);
			p=p.next;
		}
		while(q!=null) {
			if(record.containsKey(q)) {
				return q;
			}
			q = q.next;
		}
		return null;
	}
	
	/*
	 
	    思路2:开始遍历两遍链表获取两个表的长度,比较长度让长的一个先走差值个步长,
	 
	    再两个一起走。(快慢指针思想,也是链表问题的一般性思路)
	 
	*/
	public ListNode FindFirstCommonNodeII(ListNode pHead1, ListNode pHead2) {
		if(pHead1==null||pHead2==null)return null;
		ListNode p = pHead1;
		ListNode q = pHead2;
		int length1 = getLength(p);
		int length2 = getLength(q);
		//如果链表1的长度大于链表2的长度
		if(length1>=length2) {
			int len = length1-length2;
			//先遍历链表1,遍历的长度就是两链表的长度差
			while(len>0) {
				p=p.next;
				len--;
			}
		}else if(length1<length2) {
			//如果链表2的长度大于链表1的长度
			int len = length2-length1;
			//先遍历链表2,遍历的长度就是两链表的长度差
			while(len>0) {
				q=q.next;
				len--;
			}
		}
		//开始齐头并进,直到找到第一个公共结点
		while(p!=q) {
			p=p.next;
			q=q.next;
		}
		return p;
	}
	
	
	
	//求指定链表的长度
	private int getLength(ListNode q) {
		int length = 0;
		ListNode current = q;
		while(current!=null) {
			length++;
			current=current.next;
		}
		return length;
	}

	/**
	     * 思路:如果有公共节点,1)若两个链表长度相等,那么遍历一遍后,在某个时刻,p1 == p2
	     *                   2)若两个链表长度不相等,那么短的那个链表的指针pn(也就是p1或p2)
	     *                     必先为null,那么这时再另pn = 链表头节点。经过一段时间后,
	     *                     则一定会出现p1 == p2。
	     *      如果没有公共节点:这种情况可以看成是公共节点为null,顾不用再考虑。
	     */
	public ListNode FindFirstCommonNodeIII(ListNode pHead1, ListNode pHead2) {
		if(pHead1==null||pHead2==null)return null;
		ListNode p = pHead1;
		ListNode q = pHead2;
		while(p!=q) {
			if(p!=null) {
				p=p.next;
			}
			if(q!=null) {
				q=q.next;
			}
			if(p!=q) {
				if(p==null) {
					p=pHead1;
				}
				if(q==null) {
					q=pHead2;
				}
			}
		}
		return p;
    }
}

  

posted @ 2018-05-24 10:47  dreamy_java  阅读(329)  评论(0编辑  收藏  举报