輸入一個鏈表的頭節點,從尾到頭反過來返回每個節點的值(用數組返回)。示例:
輸入:head = [1,3,2]
輸出:[2,3,1]
鏈式存儲結構的便利在于增加、刪除節點,但如果我們要訪問某個節點的數據我們需要從頭結點開始一個一個的遍歷。
題目中要求我們要將鏈表的從尾到頭的打印,我們可以借助于棧的結構FILO(First In Last Out)的特性來完成反向輸出,算法構建一個O(n)大小的棧來存放從頭到尾遍歷后的結點,遍歷一次鏈表一次將數據存放到棧中,完成后將棧中數據依次出棧,順序剛好就是鏈表從尾到頭的順序。
這里給出所需要用到的數據結構:
// 單鏈表結點
public class ListNode {
public var val: Int
public var next: ListNode?
public init(_ val: Int) {
self.val = val
self.next = nil
}
}
// 使用數組實現的棧
public struct Stack<T> {
fileprivate var array = [T]()
public var isEmpty: Bool {
return array.isEmpty
}
public var count: Int {
return array.count
}
public mutating func push(_ element: T){
array.append(element)
}
public mutating func pop() -> T? {
return array.popLast()
}
public var top: T? {
array.last
}
}
棧的算法實現:
// 棧的實現
func reversePrint(_ head: ListNode?) -> [Int] {
if head == nil {
return []
}
var head = head
var stack = Stack<Int>()
while head != nil {
stack.push(head!.val)
head = head?.next
}
var array = [Int]()
while !stack.isEmpty {
array.append(stack.pop()!)
}
return array
}
因遞歸的本質就是一個棧的結構。上面用了棧結構來實現算法,那么自然可以聯想到遞歸的方式。如下代碼
// 遞歸實現
var array = [Int]()
func reversePrint(_ head: ListNode?) -> [Int] {
guard let h = head else { return []}
if h.next != nil {
reversePrint(h.next)
}
array.append(h.val)
return array
}