zoukankan      html  css  js  c++  java
  • 剑指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;
        }
    }
    

      

  • 相关阅读:
    数组中出现次数超过一半的数字
    Trie字典树算法
    字符串匹配算法 之 基于DFA(确定性有限自动机)
    实现栈最小元素的min函数
    有关有环链表的问题
    浅谈C中的malloc和free
    undefined reference to 'pthread_create'问题解决
    用两个栈实现队列
    resf规范
    单例模式
  • 原文地址:https://www.cnblogs.com/zhaohuan1996/p/9081611.html
Copyright © 2011-2022 走看看