JavaScript從反轉數組到鏈表反轉

鏈表反轉以前我已經寫過相關的文章了,可是如今去看下以前寫過的文章,感受太過於簡短,只是貼出了代碼,並無把核心的東西講出來。趁着週末,仍是把這道簡單的題從新梳理一下。javascript

如何反轉一個數組?

衆所周知,JavaScript的數組提供了不少有用的操做數組的方法,其中Array.prototype.reverse方法就能夠將數組裏面的數字反轉。用reverse這個函數反轉數組很簡單,這裏看下代碼如何操做:前端

let array = [1, 2, 3, 4, 5]
array.reverse()     // [5, 4, 3, 2, 1]
複製代碼

這樣的代碼很簡單,可是咱們依舊不知道是怎麼反轉的。下面來看下一種常見的思路————頭尾交換,以下圖:
數組長度爲3:java

  • 1
  • 2
  • 3
  • 3
  • 2
  • 1

數組長度爲4:算法

  • 1
  • 2
  • 3
  • 4
  • 4
  • 2
  • 3
  • 1
  • 4
  • 3
  • 2
  • 1
數組長度爲5:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 5
  • 2
  • 3
  • 4
  • 1
  • 5
  • 4
  • 3
  • 2
  • 1

因此長度爲 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的討論看到這種思路————局部反轉構成總體反轉 啥意思呢?好比說:函數

  • 1
  • 2
  • 3
  • 4
  • 2
  • 1
  • 3
  • 4
  • 3
  • 2
  • 1
  • 4
  • 4
  • 3
  • 2
  • 1
根據上面過程的啓發,咱們很容易能夠獲得以下的代碼:
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老師的前端補習班」關注個人微信公衆號,那麼就能夠第一時間收到個人最新文章。

相關文章
相關標籤/搜索