• 剑指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;
        }
    }
    

      

  • 相关阅读:
    那些年,学swift踩过的坑
    JAVA经BigDecimal圆角的解决方案及注意事项
    Jquery简介选择的
    Oracle性能优化顺序表名称来选择最有效的学习笔记
    jQuery Validate插入 reomte使用详细的说明
    公钥私人 ssh避password登陆
    Telnet,SSH1,SSH2,Telnet/SSL,Rlogin,Serial,TAPI,RAW
    mysqlbackup 还原特定的表
    OpenJDK 阅读源代码 Java 实现字节流输入类
    Android Application Thread CPU GC Operatiing and OOM Question 0603-随手笔记
  • 原文地址:https://www.cnblogs.com/zhaohuan1996/p/9081611.html
Copyright © 2020-2023  润新知