面試:從尾到頭打印鏈表

題目:從尾到頭打印鏈表node

要求:輸入一個鏈表的頭節點,從尾到頭反過來返回每一個節點的值(用數組返回)。數組

示例:數據結構

`app

輸入:head = [1,3,2]函數

輸出:[2,3,1]性能

`spa

限制:code

0 <= 鏈表長度="" <="10000 cdn

題解1:遞歸法

由於是從尾到頭返回每個節點的值,因此很容易想到若是從最後的節點將值放入數組中,而後再往前逐步將數據放入數組,最後回到頭節點返回便可,能夠想到遞歸就能輕鬆作到,只要注意遞歸函數的結束條件便可。blog

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
    if head == nil {
        return nil
    }

    return appendData(head)
}

func appendData(head *ListNode) []int {
    if head.Next != nil{
        list := appendData(head.Next)
        list = append(list, head.Val)
        return list
    }

    return []int{head.Val}
}複製代碼

天然而然,效率不會很高~

file

反思了一下,其實遞歸還能夠再簡短一點

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
    if head == nil {
        return []int{}
    }

    return append(reversePrint(head.Next), head.Val)
}複製代碼

結果以下:

file

題解2:反轉鏈表

想了一下,這樣不行啊,耗時這麼長,試試不用遞歸吧~

而後就想,若是我反轉鏈表呢,再生成數組返回,這樣也能夠實現吧?

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
    if head == nil {
        return nil
    }

    var newHead *ListNode
    res := []int{}
    for head != nil {
        node := head.Next
        head.Next = newHead
        newHead = head
        head = node
    }

    for newHead != nil {
        res = append(res, newHead.Val)
        newHead = newHead.Next
    }

    return res
}複製代碼

結果以下:

file

解法3:反轉數組

反轉鏈表再獲取數值,能夠是能夠,會不會有點多餘?還不如直接順序獲取值放到數組,再反轉結果呢~

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
    if head == nil {
        return nil
    }

    res := []int{}
    for head != nil {
        res = append(res, head.Val)
        head = head.Next
    }

    for i, j := 0, len(res)-1; i < j; {
        res[i], res[j] = res[j], res[i]
        i++
        j--
    }

    return res
}複製代碼

至此,結果有了很大的提高:

file

解法4:棧

這個反轉數組仍是感受好奇怪,有沒有更好的方法呢?把先讀到的放最後,最後的在最前面,棧不就是這樣的數據結構嗎?

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
import "container/list"

func reversePrint(head *ListNode) []int {
    if head == nil {
        return nil
    }

    res := list.New()
    for head != nil {
        res.PushFront(head.Val)
        head = head.Next
    }

    ret := []int{}
    for e := res.Front(); e != nil; e = e.Next() {
        ret = append(ret, e.Value.(int))
    }

    return ret
}複製代碼

三下五除二,搞定!來看當作果:

file

解法5:遍歷兩次

其實到棧,我覺得這題就這樣了,然而......

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reversePrint(head *ListNode) []int {
    if head == nil {
        return nil
    }

    count := 0
    newHead := head
    for head != nil {
        count++
        head = head.Next
    }

    res := make([]int, count)
    i := 0
    for newHead != nil {
        res[count-i-1] = newHead.Val
        i++
        newHead = newHead.Next 
    }

    return res
}複製代碼

臥槽!!!質的提高,既省去自動擴容的性能,也能提升處理速度:

file

歡迎關注公衆號:若魚治水,文章會首發在公衆號,也可備註加我備註進羣進技術交流羣~

相關文章
相關標籤/搜索