常見鏈表面試題

來源:互聯網
上載者:User

簡單LinkedList 的java代碼實現:

public class LinkedListNode {public int value;public LinkedListNode next;public LinkedListNode(int value) {this.value = value;this.next = null;}}
public class LinkedList {public LinkedListNode head;/*add an element to the tail*/public void add(int v) {if (head == null) {this.head = new LinkedListNode(v);} else {LinkedListNode node = head;while (node.next != null) {node = node.next;}node.next = new LinkedListNode(v);}}/*remove the element that appear first*/public void removeFirst(int v) {/* if to be removed is head node */if (head.value == v) {head = head.next;return;}/* iterate to the end and remove target node */LinkedListNode node = head;while (node.next != null) {if (node.next.value == v) {node.next = node.next.next;return;}node = node.next;}}public void print() {LinkedListNode node = head;while (node != null) {System.out.print(node.value + " ");node = node.next;}System.out.println();}}

1. Write code to remove duplicated element from an unsorted linked list. 從無序鏈表中重複資料刪除元素

來源 Cracking the Code Interview (2nd Edition) Ch2 Q1.

【解答】:題目已經明確說明是無序列表,對這類面試題,一般最差的複雜度是 O(NlogN),也就是需要一次排序過程,所以給出的答案最好要優於O(NlogN)。

方法一:除去重複元素,首先想到利用hash。將List迭代一遍,每拿出一個元素,放到hashtable裡,並判斷是否重複,如果重複則從List中刪除該元素。這個演算法的時間複雜度是O(N),但需要O(N)的空間建立hashtable去存放元素。

java代碼:http://pastebin.com/UiqMVxdL  這裡的linkedlist使用的是java.util.*中的LinkedList。實際面試中往往需要自己實現一個linkedlist。

 public static void removeDuplicate(List<Integer> l){2.                Hashtable table = new Hashtable();3.                for(Iterator<Integer> iter = l.iterator();iter.hasNext();){4.                        Integer i = iter.next();5.                        if(table.containsKey(i)){6.                                iter.remove();7.                        }else{8.                                table.put(i, true);9.                        }10.                }11.        }

 

方法二:利用runner pointer. 這個技巧也是解答LinkedList Problem的重要技巧之一。迭代當前鏈表,每次迭代利用一個runner去訪問之後的元素,重複資料刪除元素。算是naive approach,時間複雜度O(N^2),空間複雜度O(1)。面試中最先可能想到的應該是這種解答,然後可以最佳化到第一種方法。

2. Implement am algorithm to find the kth to last element of a singly linked list. 尋找單項鏈表中,距最後一個元素距離為K的元素。

來源 Cracking the Code Interview (2nd Edition) Ch2 Q2.

【解答】:方法一:如果知道鏈表的長度N,答案就是從第(N-K)個元素。當然這題也就沒有意義了。

方法二:利用chaser-runner。首先讓runner先移動K位,這時候chaser從鏈表頭部開始,和runner同時以相同的速度迭代鏈表,當runner到達鏈表尾部,chaser恰好距離最後一個元素K的距離。時間複雜度O(N), 空間複雜度O(1)。

java代碼:http://pastebin.com/MQczDMvT 這裡用到的LinkedList是本文開始時定義的data structure.

 public static LinkedListNode kth2Last(LinkedList list, int k) {2.                LinkedListNode chaser = list.head;3.                LinkedListNode runner = list.head;4. 5.                int i = 0;6.                7.                while (i < k) {8.                        /*the list must have at least k+1 elements*/9.                        if (runner == null) {10.                                return null;11.                        }12.                        runner = runner.next;13.                        i++;14.                }15.                16.                /*if the list has exactly k elements*/17.                if(runner == null){18.                        return null;19.                }20.                21.                22.                /*begin chasing*/23.                while(runner.next!=null){24.                        chaser = chaser.next;25.                        runner = runner.next;26.                }27.                return chaser;28.        }

 

3. Given a circular linked list, implement an algorithm which returns the node at the beginning of the loop. 尋找有環鏈表環的頭部。

來源 Cracking the Code Interview (2nd Edition) Ch2 Q6.

【解答】: 這個題算是經典面試題之一,和Binary Tree的BFS遍曆一樣,都屬於看上去滿有水平,實際並沒有太多難度的題目,如果遇到了不會做人品可是敗成啥樣了!?

首先第一問一般是判斷該鏈表有沒有環,接著問如果有環的話,找出環開始的節點。

如果判斷是否有環?--Same technique as the last question. We can use
runner pointer
to detect if there is a loop. 記得以前在學校裡跑1500米的時候,我經常被人套圈…類似的,如果一個鏈表有環,並且進入環以後,將一直在環裡走下去,慢的總是會被快的趕上,套圈。所以我們用兩個指標,一個slow runner,一個fast runner,每次slow走1個,fast走2個,如果在某個時刻slow == fast指標,則證明有環。

如何判斷環的開始是哪個節點?-- 這個問題也很容易想通。當兩個指標第一次相遇的時候,他們距離環的開始節點還有K個元素,而這K個元素是進入環之前那段鏈表元素的個數。怎麼證明呢?設想兩個runner同時從某個環的同一個點出發,快的runner以2倍於慢的runner速度前進,它們第一次重合一定還是在這個出發點的位置,以後每一次相遇也一定是在這個出發點的位置。So,設想現在進入環前的那一段K個節點,是環的一部分,離環真正的開始節點距離為K,那麼兩個runner同時出發,第一次碰撞必然還是在距離環開始節點K的位置。所以,第一次碰撞時,隨便將任意一個runner回到鏈表頭部,此時兩個runner以同一速度前進,當他們再次相遇的節點,就是環的開始節點。

java代碼:http://pastebin.com/p35Cwgzv

 

 public static LinkedListNode findBegin(LinkedList list){2.                LinkedListNode slow = list.head;3.                LinkedListNode fast = list.head;4.                5.                /*find the first meeting point*/6.                while(fast!=null){7.                        fast = fast.next.next;8.                        slow = slow.next;9.                        if(fast == slow){10.                                break;11.                        }12.                }13.                14.                /*check if there do have a loop*/15.                if(fast == null){16.                        return null;17.                }18.                19.                slow = list.head;20.                21.                /*find the beginning of the loop*/22.                while(slow!=fast){23.                        slow = slow.next;24.                        fast = fast.next;25.                }26.                return fast;27.        }

 

4. Implement a function to check if a linked list is a palindrome. 判斷鏈表是不是迴文鏈表。

來源 Cracking the Code Interview (2nd Edition) Ch2 Q7.

【解答】:經典面試題了。迴文就是 0-->1-->2-->1-->0 奇數個節點, 或者 0-->1-->2-->2-->1-->0 偶數個節點。

方法一:很自然的想法就是把鏈表反轉,然後對比反轉以後的鏈表和原鏈表的節點值,並且只要比較反轉鏈表和原鏈表一辦的元素就可以。

方法二:利用runner pointer。很多的題目都可以利用這個方法來解決。Runner pointer和遞迴是解決鏈表問題最常用的兩個方法。

定義兩個指標,slow runner和fast runner,fast以2倍於slow的速度向鏈表尾部移動。如有奇數個節點:當fast到達鏈表尾部時,slow恰好到達鏈表中間。如有偶數個節點:fast第一次為null時,slow恰好完成了一半節點的訪問。把slow訪問過的節點元素值壓入一個stack裡。此後slow繼續向鏈表尾部訪問,同時stack裡的元素開始出棧(奇數個元素的情況下要跳過中間元素),比較兩個元素值,一旦出現不等,則不是迴文,否則是。該解法的時間複雜度是O(N),因為需要一次迭代,同時需要O(N)的空間用作stack來存放鏈表元素。

java代碼 http://pastebin.com/wZ54iSmq  這裡的List是本文開始定義的資料結構。

 

1.        public static boolean isPalindrome(LinkedList list){2.                LinkedListNode slow = list.head;3.                LinkedListNode fast = list.head;4.                5.                Stack<Integer> stack = new Stack<Integer>();6.                while(fast!=null&&fast.next!=null){7.                        stack.push(slow.value);8.                        slow = slow.next;9.                        fast = fast.next.next;10.                }11.                12.                /*if the length of list is odd*/13.                if(fast!=null){14.                        slow = slow.next;15.                }16.                17.                /*compare elements all the way to the end*/18.                while(slow!=null){19.                        if(slow.value!=stack.pop().intValue()){20.                                return false;21.                        }22.                        slow = slow.next;23.                }24.                return true;25.        }

 

轉載:http://blog.csdn.net/tanglinghui/article/details/7618142

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.