鏈表反轉以前我已經寫過相關的文章了,可是如今去看下以前寫過的文章,感受太過於簡短,只是貼出了代碼,並無把核心的東西講出來。趁着週末,仍是把這道簡單的題從新梳理一下。javascript
衆所周知,JavaScript的數組提供了不少有用的操做數組的方法,其中Array.prototype.reverse
方法就能夠將數組裏面的數字反轉。用reverse
這個函數反轉數組很簡單,這裏看下代碼如何操做:前端
let array = [1, 2, 3, 4, 5]
array.reverse() // [5, 4, 3, 2, 1]
複製代碼
這樣的代碼很簡單,可是咱們依舊不知道是怎麼反轉的。下面來看下一種常見的思路————頭尾交換,以下圖:
數組長度爲3:java
數組長度爲4:算法
因此長度爲 n的數組須要交換 n / 2 + 1 次,由此咱們能夠得出下面的代碼:數組
let array = [1, 2, 3, 4, 5]
for(let i = 0; i < array.length / 2; i ++){
[array[i], array[array.length - i - 1]] = [array[array.length - i - 1], array[i]]
}
console.log(array) // [5, 4, 3, 2, 1]
複製代碼
什麼是鏈表?個人理解是一個長度爲n,沒法經過下標來遍歷,只能經過當前節點來訪問下一個節點的鏈式結構。 那麼廢話很少說,先來構造一個簡單的鏈表:微信
//節點構造函數
function Node(val){
this.val = val
this.next = null
}
//定義鏈表
function List(array){
this.head = null
let i = 0,temp = null
while(i < array.length){
if( i === 0){
this.head = new Node(array[i])
temp = this.head
}else{
let newNode = new Node(array[i])
temp.next = newNode
temp = temp.next
}
i++
}
}
//遍歷鏈表
function traverseList(listHead){
while(listHead){
console.log(listHead.val)
listHead = listHead.next
}
}
複製代碼
以上是一個鏈表的簡單實現,不懂的朋友能夠翻看一下數據結構與算法 接下來劃重點:鏈表只能由當前節點訪問下一個節點,沒法經過下標來訪問鏈表元素
一開始沒有想到辦法,後來我用了一種比較奇葩的方法————將鏈表的值存進數組,反轉數組之後再從新賦值,代碼以下:數據結構
/** * @param {ListNode} head * @return {ListNode} */
var reverseList = function (head) {
let temp = head,
result = []
while (temp != null) {
result.push(temp.val)
temp = temp.next
}
temp = head, i = 0
result.reverse()
while (temp != null) {
temp.val = result[i++]
temp = temp.next
}
return head
};
複製代碼
可是這顯然沒有利用到鏈表的特性————即由當前結點訪問下一個節點。後來我在LeetCode的討論看到這種思路————局部反轉構成總體反轉 啥意思呢?好比說:函數
var reverseList = function (head) {
let pre = null
while (head) {
next = head.next
head.next = pre
pre = head
head = next
}
return pre
};
複製代碼
思路是否是很簡單呢?這樣簡單的思路當時我卻沒有想到...反思ing......ui
從數組的反轉到鏈表的反轉,咱們能夠得出一個結論:思惟不能僵化(逃,貌似很普通的一個算法————反轉,能夠有不少種作法。路過的朋友若是還知道其餘算法,還請多多指教this
掃描下方的二維碼或搜索「tony老師的前端補習班」關注個人微信公衆號,那麼就能夠第一時間收到個人最新文章。