leetcode 探索 鏈表 設計鏈表

題目

設計鏈表的實現。您可以選擇使用單鏈表或雙鏈表。單鏈表中的節點應該具有兩個屬性:val 和 next。val 是當前節點的值,next 是指向下一個節點的指針/引用。如果要使用雙向鏈表,則還需要一個屬性 prev 以指示鏈表中的上一個節點。假設鏈表中的所有節點都是 0-index 的。

在鏈表類中實現這些功能:
get(index):獲取鏈表中第 index 個節點的值。如果索引無效,則返回-1。
addAtHead(val):在鏈表的第一個元素之前添加一個值爲 val 的節點。插入後,新節點將成爲鏈表的第一個節點。
addAtTail(val):將值爲 val 的節點追加到鏈表的最後一個元素。
addAtIndex(index,val):在鏈表中的第 index 個節點之前添加值爲 val 的節點。如果 index 等於鏈表的長度,則該節點將附加到鏈表的末尾。如果 index 大於鏈表長度,則不會插入節點。如果index小於0,則在頭部插入節點。
deleteAtIndex(index):如果索引 index 有效,則刪除鏈表中的第 index 個節點。

示例:

MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1,2); //鏈表變爲1-> 2-> 3
linkedList.get(1); //返回2
linkedList.deleteAtIndex(1); //現在鏈表是1-> 3
linkedList.get(1); //返回3

提示:

所有val值都在 [1, 1000] 之內。
操作次數將在 [1, 1000] 之內。
請不要使用內置的 LinkedList 庫。

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/design-linked-list

分析

leecode將要實現的方法已經給出來了,我們只要挨個實現就好了。需要定義一個元素Node,然後MyLinkedList只放入Head和Size,Head是Node類型。我們去實現Get的時候,除了判斷邊界條件,還要幾個要注意的地方。

  • 注意指針指向的位置,這裏i < index + 1, 這樣才能遍歷到index的位置。
  • 注意添加頭指針的時候,是要把Head.Next 指向新節點。
  • 注意插入節點的時候,在AddAtIndex裏,遍歷的時候,要注意的是遍歷到index的前一個節點,這樣我們才能把新節點插入到這前一個節點後目標位置。
  • 總的來說,就是要考慮每一個方法,針對空鏈表,添加頭部,添加尾部,刪除尾節點等是否有問題。

鏈表的設計,要注意的點非常多,邊界條件的檢查。所以最好是,每一次操作之後,打印出鏈表看看,插入或者刪除的順序是否正確。

解法

type MyLinkedList struct {
    Head *Node
    Size int
}

type Node struct {
    Val int
    Next *Node
}


/** Initialize your data structure here. */
func Constructor() MyLinkedList {
    return MyLinkedList{
        Head: &Node{},
        Size: 0,
    }
}


/** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
func (this *MyLinkedList) Get(index int) int {
    if index < 0 || index >= this.Size {
        return -1
    }
    // fmt.Printf("get size: %d, index:%d\n", this.Size, index)
    cur := this.Head
    // i=0 時候,需要返回的是head.Next.
    for i:=0; i < index+1 ; i++ {
        cur = cur.Next
    }
    
    return cur.Val
}


/** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */
func (this *MyLinkedList) AddAtHead(val int)  {
    newNode := &Node{
        Val: val,
        Next: this.Head.Next,
    }
    this.Head.Next = newNode // 這裏要注意,是head next 指向新節點
    this.Size++
    
    // this.Print("addAtHead")
}


/** Append a node of value val to the last element of the linked list. */
func (this *MyLinkedList) AddAtTail(val int)  {
    if this.Size == 0 {
        this.AddAtHead(val)
        return
    }
    
    pred := this.Head
    for pred.Next != nil {
        pred = pred.Next
    }
    pred.Next = &Node{
        Val:val,
    }
    this.Size++
    // this.Print("addAtTail")
}


/** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
func (this *MyLinkedList) AddAtIndex(index int, val int)  {
    // index 大於長度,不會被插入
    if index > this.Size {
        return
    }
    
    // index 小於等於0,插入到頭部
    if index <= 0 {
        this.AddAtHead(val)
        return
    }
    
    // index 等於長度,插入到尾部
    if index == this.Size {
        this.AddAtTail(val)
        return
    }
    
    pred := this.Head
    // fmt.Printf("head:%v, index:%d\n", pred, index)
    // 這應該是停在index的前一個節點
    for i:=0; i < index; i++ {
        pred = pred.Next
    }
    newNode := &Node{
        Val: val,
        Next: pred.Next,
    }
    pred.Next = newNode
    this.Size++
    
    // this.Print("addAtIndex")
}


/** Delete the index-th node in the linked list, if the index is valid. */
func (this *MyLinkedList) DeleteAtIndex(index int)  {
    if index < 0 || index >= this.Size {
        return
    }
    
    pred := this.Head
    // i 會停在index的前一個位置,如果i是0,能刪除嗎?
    for i:=0; i < index; i++ {
        pred = pred.Next
    }
    
    pred.Next = pred.Next.Next
    this.Size--  
    // this.Print("deleteAt")

}

func (this *MyLinkedList)Print(msg string){
    fmt.Printf("%s: [", msg)
    cur := this.Head
    for cur!=nil {
        fmt.Printf("%v\t", cur.Val)
        cur = cur.Next
    }
    fmt.Println("]")
}

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * obj := Constructor();
 * param_1 := obj.Get(index);
 * obj.AddAtHead(val);
 * obj.AddAtTail(val);
 * obj.AddAtIndex(index,val);
 * obj.DeleteAtIndex(index);
 */
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章