在Go語言中,你可以使用迭代方法來反轉一個單連結串列。這種方法只需要O(1)的額外空間。首先,我們需要定義連結串列的資料結構:
type ListNode struct {
Val int
Next *ListNode
}
然後,我們可以使用以下程式碼來反轉一個連結串列:
func reverseList(head *ListNode) *ListNode {
var prev *ListNode
curr := head
for curr != nil {
nextTemp := curr.Next //儲存下一個節點
curr.Next = prev //反轉連結
prev = curr //後移
curr = nextTemp //後移
}
return prev
}
這個函數會迭代連結串列的每個節點,並改變當前節點的Next指標以指向它的前一個元素。由於我們需要在更改指標之前儲存下一個節點,所以我們需要在更改指標之前將當前節點的Next指標儲存到臨時變數中。
在更改指標後,我們將當前節點和下一個節點向後移動,因此我們可以在O(1)的空間中反轉連結串列。這個函數的時間複雜度是O(n),因為它需要遍歷連結串列的每個節點。
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
func reverseList(head *ListNode) *ListNode {
var prev *ListNode
current := head
for current != nil {
nextTemp := current.Next
current.Next = prev
prev = current
current = nextTemp
}
return prev
}
func main() {
// 建立連結串列:1 -> 2 -> 3 -> 4 -> 5
head := &ListNode{Val: 1}
head.Next = &ListNode{Val: 2}
head.Next.Next = &ListNode{Val: 3}
head.Next.Next.Next = &ListNode{Val: 4}
head.Next.Next.Next.Next = &ListNode{Val: 5}
// 逆轉連結串列
newHead := reverseList(head)
// 列印逆轉後的連結串列:5 -> 4 -> 3 -> 2 -> 1
current := newHead
for current != nil {
fmt.Printf("%d -> ", current.Val)
current = current.Next
}
fmt.Println("nil")
}
以下是一個使用go語言實現對單連結串列進行逆轉的O(n)時間非遞迴過程:
package main
import "fmt"
// 定義連結串列節點結構體
type ListNode struct {
Val int
Next *ListNode
}
// 定義連結串列類
class List {
constructor() {}
reverseList(head: *ListNode) -> *ListNode {
var prev *ListNode = head
var current *ListNode = head.Next
while current != nil {
var next *ListNode = current.Next
current.Next = prev
prev = current
current = next
}
head.Next = prev
return head
}
}
// 測試
var list = new List()
list.add(1)
list.add(2)
list.add(3)
list.add(4)
list.add(5)
fmt.Println("原連結串列:")
printList(list.head)
list.reverseList(&list.head)
fmt.Println("逆轉後的連結串列:")
printList(list.head)
其中,List
是連結串列類,reverseList
是反轉連結串列的方法。在reverseList
方法中,我們使用兩個指標prev
和current
分別指向連結串列的頭節點和當前節點,然後遍歷整個連結串列,每次將當前節點的下一個節點賦值給當前節點,並將當前節點的指標指向前一個節點,最後返回頭節點即可。
package main
import (
"fmt"
)
type ListNode struct {
Val int
Next *ListNode
}
func reverseList(head *ListNode) *ListNode {
var prev *ListNode
current := head
for current != nil {
nextTemp := current.Next
current.Next = prev
prev = current
current = nextTemp
}
return prev
}
func printList(head *ListNode) {
for head != nil {
fmt.Print(head.Val, "->")
head = head.Next
}
fmt.Println("nil")
}
func main() {
head := &ListNode{Val: 1, Next: &ListNode{Val: 2, Next: &ListNode{Val: 3, Next: &ListNode{Val: 4, Next: &ListNode{Val: 5, Next: nil}}}}}
fmt.Println("Original list:")
printList(head)
reversedHead := reverseList(head)
fmt.Println("Reversed list:")
printList(reversedHead)
}
這個程式首先定義了一個 ListNode
結構體,用於表示連結串列的節點。reverseList
函數接受一個連結串列的頭節點作為引數,並返回逆轉後的連結串列的頭節點。
在 reverseList
函數中,我們使用了一個前置節點 prev
,初始值為 nil
。我們從連結串列的頭節點開始,遍歷連結串列的每個節點。對於每個節點,我們儲存其下一個節點(nextTemp
),然後將當前節點的前置節點設定為 prev
,將當前節點設定為下一個節點,繼續遍歷。當遍歷到連結串列的尾部時,current
和 nextTemp
都為 nil
,此時我們將 prev
作為連結串列的新頭節點返回。
printList
函數用於列印連結串列。我們在 main
函數中建立了一個範例連結串列,然後呼叫 reverseList
函數對其進行逆轉,並列印原始連結串列和逆轉後的連結串列。
以下是使用Go語言實現的非遞迴方法,用於逆轉一個含n個元素的單連結串列:
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
func reverseList(head *ListNode) *ListNode {
prev := nil
curr := head
for curr != nil {
next := curr.Next
curr.Next = prev
prev = curr
curr = next
}
return prev
}
func main() {
head := &ListNode{Val: 1}
head.Next = &ListNode{Val: 2}
head.Next.Next = &ListNode{Val: 3}
head.Next.Next.Next = &ListNode{Val: 4}
head.Next.Next.Next.Next = &ListNode{Val: 5}
fmt.Println("Original List:")
for curr := head; curr != nil; curr = curr.Next {
fmt.Printf("%d ", curr.Val)
}
newHead := reverseList(head)
fmt.Println("\nReversed List:")
for curr := newHead; curr != nil; curr = curr.Next {
fmt.Printf("%d ", curr.Val)
}
}
在這個程式中,我們使用三個指標:prev,curr和next。prev指標初始化為nil,curr指標初始化為連結串列的頭節點。然後,我們進入一個迴圈,該回圈在curr不為nil時繼續執行。在每次迭代中,我們都做以下操作:
1.將next指標設定為curr的下一個節點。
2.將curr的next指標設定為prev。
3.將prev和curr向前移動一位。
當我們完成迴圈時,prev指標將指向逆轉後的連結串列的頭節點。我們返回prev指標,這就是逆轉後的連結串列的頭節點。
注意,這個程式使用了常數大小的額外空間。
以下是使用 Go 語言實現 O(n) 時間複雜度的非遞迴方式逆轉單連結串列的程式碼:
func reverseList(head *ListNode) *ListNode {
var prev *ListNode = nil
var curr *ListNode = head
for curr != nil {
next := curr.Next
curr.Next = prev
prev = curr
curr = next
}
return prev
}
該程式碼中,我們使用了三個指標,分別是 prev
、curr
和 next
。其中,prev
指向當前節點的前一個節點,curr
指向當前節點,next
指向當前節點的下一個節點。我們從頭節點開始遍歷連結串列,每次將當前節點的 next
指標指向 prev
,然後更新 prev
和 curr
的值,繼續遍歷下一個節點。最後返回 prev
即可。
由於我們只需要常數級別的額外空間,因此空間複雜度為 O(1)。時間複雜度為 O(n),因為我們需要遍歷整個連結串列一次。
下面是一個使用Go語言實現對單連結串列逆轉的非遞迴過程,時間複雜度為O(n):
package main
import "fmt"
type ListNode struct {
Val int
Next *ListNode
}
func reverseList(head *ListNode) *ListNode {
var prev *ListNode
current := head
for current != nil {
next := current.Next
current.Next = prev
prev = current
current = next
}
return prev
}
func displayList(head *ListNode) {
current := head
for current != nil {
fmt.Printf("%d ", current.Val)
current = current.Next
}
fmt.Println()
}
func main() {
// 建立一個範例連結串列 1 -> 2 -> 3 -> 4 -> 5
head := &ListNode{Val: 1}
node2 := &ListNode{Val: 2}
node3 := &ListNode{Val: 3}
node4 := &ListNode{Val: 4}
node5 := &ListNode{Val: 5}
head.Next = node2
node2.Next = node3
node3.Next = node4
node4.Next = node5
fmt.Println("原連結串列:")
displayList(head)
reversedHead := reverseList(head)
fmt.Println("逆轉後的連結串列:")
displayList(reversedHead)
}
這段程式碼定義了一個ListNode
結構體來表示單連結串列節點,然後實現了reverseList
函數來對單連結串列進行逆轉。過程中使用了三個指標:prev
用於表示當前節點的前一個節點,current
用於表示當前節點,next
用於儲存下一個節點。我們對每個節點進行處理,將當前節點的下一個節點指向前一個節點,然後更新prev
、current
和next
指標。最後返回逆轉後的連結串列的頭節點。
在main
函數中,建立了一個範例連結串列,並呼叫reverseList
函數對其進行逆轉。最後呼叫displayList
函數來列印原連結串列和逆轉後連結串列的值,以驗證結果。
這個過程的空間複雜度為O(1),除了儲存連結串列本身所需的空間外,只使用了固定大小的三個指標。