BAT 經典演算法筆試題 —— 逆轉單向連結串列
不善言談的優秀程式設計師在面試中往往是要吃鉅虧的,你沒有辦法透過說話來輕易證明自己的實力。不論是大廠還是小廠,大部分面試官都不具備優秀的面試能力,它們也只能透過三言兩語觀察一下面試者的表面工夫。老錢就是這樣吃了很多虧的程式設計師,不喜歡準備面試,不喜歡吹噓虛假的不存在的經驗和能力,甚至連網上的筆試題都懶得做,因為在實際工作中這些鳥題根本一點都用不上。
但是這並不是什麼值得驕傲的真誠,面試不做準備是對目標企業的不尊重,也是個人性格上自大的一種表現。雖然所有的面試官都希望面試者是真實的無虛假的不做表面文章的,但是這樣的人真的站在你面前時,幾乎所有的面試官往往又都看不上。
那如何在儘量少做表面功夫的基礎上讓面試官能夠看上你?其中的方法之一就是展現平時個人優秀的作品和實現程式碼,但是這需要時間需要實打實的功夫,能夠有機會作出優秀個人作品的人並不多見,大多數人都在忙碌的工作中耗盡了所有的時間。那還有一個方法就是在筆試階段大顯身手,讓自己優秀的程式碼能力躍然紙上,讓面試官瞬間對你產生不一樣的感覺。
不要被筆試階段那些演算法題給吼到了,在你眼裡似乎它們是為程式天才們準備的。其實大多數公司的筆試題也是來源於網上,那些被無數人做爛的題目。你被題目搞暈了而別人沒有,那是因為別人已經做過這道題了,而不是智商所致。
就拿今天我要講的演算法題 —— 逆轉單向連結串列,它是一個非常簡單的題目,但是如果你是第一次見到這道題,將它完完整整沒有 bug 的寫出來是著實需要費一番功夫的。期望在那短短的筆試題環節就輕鬆搞定這道題,那真是非常有演算法天賦的人才能做到的事。難道大廠裡面的程式設計師個個都是天才,鬼才相信。天才總是極少數的,多數都是像老錢這樣的庸才。
好,言歸正傳,下面我們開始講解今天的演算法題 —— 逆轉單向連結串列。首先這是一個單向的連結串列,不同於 Java 裡面的 LinkedList,它是雙向的連結串列。連結串列中每個節點之間透過 next 指標串接起來,會有一個連結串列頭和連結串列尾指標 hold 住整個連結串列。逆轉的任務就是將 head -> a -> b -> c -> d <- tail 變成 head -> d -> c -> b -> a <- tail。
連結串列結構表示
class Node<T> {
T value;
Node<T> next;
Node(T value) {
this.value = value;
}
}
class ReverseLinkedList<T> {
Node<T> head, tail;
}
連結串列構造器
我們需要將所有的元素一個一個的使用 next 指標串接起來,連結串列的頭尾節點要用 head 和 tail 變數把持住。加入新元素時,需要調整尾部節點的 next 指標,指向新加入的元素節點。
class ReverseLinkedList<T> {
private Node<T> head, tail;
public ReverseLinkedList(T... values) {
for (T value : values) {
if (tail == null) {
// 第一個節點
head = tail = new Node<>(value);
} else {
// 後面的節點往連結串列尾部追加
Node<T> oldTail = tail;
oldTail.next = tail = new Node<>(value);
}
}
}
}
ReverseLinkedList<Integer> l = new ReverseLinkedList<>(1,2,3,4,5,6);
連結串列內容呈現
我們需要提供一個連結串列的輸出方法,以便快速對比逆轉後連結串列的內容是否正確
class ReverseLinkedList<T> {
private Node<T> head, tail;
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('[');
Node<T> cur = head;
while (cur != null) {
sb.append(cur.value);
cur = cur.next;
if (cur != null) {
sb.append(',');
}
}
sb.append(']');
return sb.toString();
}
}
迭代逆轉演算法
迴圈調整 next 指標是最容易想到的方法,但是要將指標精確地逆轉正確其實並不容易。下面程式碼中的迴圈部分很短,但是卻很精緻,使用了三個臨時區域性變數 cur、next 和 nextnext,稍有不慎就會出錯。
當我寫完下面這段程式碼時,雖然可以正常執行出期望的結果,但是總當心哪裡會有遺漏,是不是什麼地方少了個 if else,這就是編寫演算法程式碼時常見的心理狀態。
class ReverseLinkedList<T> {
private Node<T> head, tail
public ReverseLinkedList<T> reverseByLoop() {
// 空連結串列或者單元素都無需處理
if (head == tail) {
return this;
}
Node<T> cur = head;
Node<T> next = cur.next;
while (next != null) {
Node<T> nextnext = next.next;
next.next = cur;
cur = next;
next = nextnext;
}
tail = head;
tail.next = null;
head = cur;
return this;
}
}
遞迴逆轉演算法
使用遞迴的思想來解決這個問題也是一個很好的主意,只不過當連結串列特別長時,呼叫棧會很深,連結串列長到一定程度就會丟擲臭名昭著的異常 StackOverflowException。
class ReverseLinkedList<T> {
private Node<T> head, tail
public ReverseLinkedList<T> reverseByRecursive() {
Node<T> oldTail = tail;
tail = reverseFrom(head);
tail.next = null;
head = oldTail;
return this;
}
private Node<T> reverseFrom(Node<T> from) {
if (from == tail) {
return from;
}
Node<T> end = reverseFrom(from.next);
end.next = from;
return from;
}
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31561269/viewspace-2557209/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- c語言單向連結串列逆轉實現方法C語言
- C/C++筆試經典——連結串列倒序C++筆試
- 資料結構與演算法——連結串列 Linked List(單連結串列、雙向連結串列、單向環形連結串列-Josephu 問題)資料結構演算法
- BAT 經典演算法筆試題 —— 磁碟多路歸併排序BAT演算法筆試排序
- BAT 經典演算法筆試題: 映象二叉樹BAT演算法筆試二叉樹
- 單連結串列逆置遞迴演算法遞迴演算法
- 結構與演算法(03):單向連結串列和雙向連結串列演算法
- 連結串列經典示例
- 演算法入門題:如何反轉一個單向連結串列?演算法
- [演算法總結] 17 題搞定 BAT 面試——連結串列題演算法BAT面試
- 演算法搜狗筆試題連結串列合併演算法筆試
- 棧_單向連結串列
- 資料結構連結串列筆試題資料結構筆試
- 資料結構--陣列、單向連結串列、雙向連結串列資料結構陣列
- 演算法題:反轉一個單連結串列&判斷連結串列是否有環演算法
- 單向迴圈連結串列
- 佇列_單向連結串列佇列
- 連結串列-雙向連結串列
- 經典演算法題每日演練——第二十五題 塊狀連結串列演算法
- JavaScript經典筆試題JavaScript筆試
- 連結串列面試題(二)---連結串列逆序(連結串列反轉)面試題
- 每日演算法隨筆:反轉連結串列演算法
- go 實現單向連結串列Go
- C語言之單向連結串列C語言
- 單向連結串列介面設計
- 演算法與資料結構-連結串列((linked-list)-Java實現單向連結串列演算法資料結構Java
- 資料結構之連結串列與陣列(2):單向連結串列上的簡單操作問題資料結構陣列
- 資料結構和演算法——Go實現單連結串列並且反轉單連結串列資料結構演算法Go
- 【資料結構與演算法學習】線性表(順序表、單連結串列、雙向連結串列、迴圈連結串列)資料結構演算法
- 筆記--連結串列演算法筆記演算法
- 單向迴圈連結串列大綱
- 畫江湖之資料結構【第一話:連結串列】單向連結串列資料結構
- 畫江湖之資料結構 [第一話:連結串列] 單向連結串列資料結構
- 雙向連結串列
- BAT經典面試題彙總BAT面試題
- 單向迴圈連結串列的介面程式
- 單向迴圈連結串列的實現
- Go語言經典筆試題Go筆試