leetcode-160- 相交連結串列(intersection of two linked list)-java
阿新 • • 發佈:2018-11-19
題目及測試
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; } }
網上還有兩種解法,都不太好
有以下幾種思路:
(1)暴力破解,遍歷連結串列A的所有節點,並且對於每個節點,都與連結串列B中的所有節點比較,退出條件是在B中找到第一個相等的節點。時間複雜度O(lengthA*lengthB),空間複雜度O(1)。
(2)雜湊表。遍歷連結串列A,並且將節點儲存到雜湊表中。接著遍歷連結串列B,對於B中的每個節點,查詢雜湊表,如果在雜湊表中找到了,說明是交集開始的那個節點。時間複雜度O(lengthA+lengthB),空間複雜度O(lengthA)或O(lengthB)。