兩個鏈表的第一個公共結點


題目描述
輸入兩個鏈表,找出它們的第一個公共結點。

節點類:

public class ListNode {
	int val;
	ListNode next = null;

	ListNode(int val) {
		this.val = val;
	}
}

分析
首先要理解什么是公共節點,並不是兩個節點的值相同就是公共節點。
而是在第一鏈表和第二鏈表中都存在一個節點,該節點往后的子鏈表在兩個鏈表中是相同的。

如下圖中鏈表6 - 7就是兩個鏈表的公共鏈表,而節點6就是第一個公共節點。
在這里插入圖片描述

方法一
最直觀就是暴力法,在第一鏈表上順序遍歷每個節點,每遍歷到一個節點,就在第二個鏈表上順序遍歷每個節點。如果在第二個鏈表上有一個節點和第一個鏈表上的節點一樣,則說明兩個鏈表在這個節點上重合,但是這種方法的復雜度為O( m n m * n )(第一個鏈表長度為m,第二個鏈表的長度為n)

方法二
如果兩個鏈表存在公共節點,那么公共節點出現在兩個鏈表的尾部。如果我們從兩個鏈表的尾部開始往前比較,那么最后一個相同的節點就是我們要找的節點。但是這兩個鏈表是單向的,要實現尾節點最先比較,我們可以借助兩個輔助棧。分別將兩個鏈表的節點放入兩個棧中,這樣棧頂就是兩個鏈表的尾節點,比較兩個棧頂節點是否相同,如果相同,將棧頂彈出比較下一個棧頂,直到找到最后一個相同的棧頂。時間復雜度O(m + n)。

    public ListNode FindFirstCommonNode(ListNode pHead1, ListNode pHead2) {
    	
    	if(pHead1 == null || pHead2 == null) {
    		return null;
    	}
    	Stack<ListNode> pStack1 = new Stack<ListNode>();
    	Stack<ListNode> pStack2 = new Stack<ListNode>();
    	while(pHead1 != null) {
    		pStack1.add(pHead1);
    		pHead1 = pHead1.next;
    	}
    	while(pHead2 != null) {
    		pStack2.add(pHead2);
    		pHead2 = pHead2.next;
    	}
    	ListNode temp = null;
    	while(!pStack1.isEmpty() && !pStack2.isEmpty()) {
    		ListNode pH1 = pStack1.pop();
    		ListNode pH2 = pStack2.pop();
    		if(pH1.val == pH2.val) {
    			temp = pH1;		
    		}
    		else {
    			break;
    		}
    	}
    	return temp;

    }

方法三
先獲得兩個鏈表的長度,然后在較長的鏈表上先走若干步(兩鏈表長度之差),接着同時在兩個鏈表上遍歷,找到的第一個相同的節點就是他們的第一個公共節點。時間復雜度O(m + n)。

    public ListNode FindFirstCommonNode_2(ListNode pHead1, ListNode pHead2) {
    	if(pHead1 == null || pHead2 == null) {
    		return null;
    	}
    	
    	int pHead1Length = getListLength(pHead1);
    	int pHead2Length = getListLength(pHead2);
    	
    	int gap = pHead1Length - pHead2Length;
    	ListNode tempList1 = pHead1;
    	ListNode tempList2 = pHead2;
    	
    	if(pHead2Length > pHead1Length) {
    		tempList1 = pHead2;
    		tempList2 = pHead1;
    		gap = pHead2Length - pHead1Length;
    	}
    	
    	for (int i = 0; i < gap; i++) {
    		tempList1 = tempList1.next;
		}
    	
    	while((tempList1 != null) && (tempList2 != null) && (tempList1.val != tempList2.val)) {
    		tempList1 = tempList1.next;
    		tempList2 = tempList2.next;
    	}
    	
    	return tempList1;

    }
    
    public int getListLength(ListNode list) {
    	int number = 0;
    	while(list != null) {
    		++number;
    		list = list.next;
    	}
    	return number;
    }

方法四
很玄學的代碼。。。
用兩個指針掃描”兩個鏈表“,最終兩個指針到達 null 或者到達公共結點。

    public ListNode FindFirstCommonNode_3(ListNode pHead1, ListNode pHead2) {
    	if(pHead1 == null || pHead2 == null) {
    		return null;
    	}
    	ListNode temp1 = pHead1;
    	ListNode temp2 = pHead2;
    	while(temp1 != temp2) {
    		temp1 = (temp1 == null ? pHead2 : temp1.next);
    		
    		temp2 = (temp2 == null ? pHead1 : temp2.next);
    		System.out.println(pHead1.val);
    	}
    	
    	return temp1;
    }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM