Day03 链表

65 阅读2分钟

概念

刷题

203 移除链表元素

leetcode.cn/problems/re…

使用tmp中间值,记录被删除的元素指针,将上一链表元素指针指向tmp的next指针,就可以删除一个链表元素

需要注意,头节点等于被删除元素的值,被删除元素在末尾,被删除元素是相邻节点的情况

image.png

707 设计链表 (重做)

image.png

这道题目需要重新做一下 没有使用虚拟头节点


package main

type Node struct {
   Val int
   Next *Node
}

type MyLinkedList struct {
   Size int
   Head *Node
}


func Constructor() MyLinkedList {
   return MyLinkedList{0, nil}
}


func (this *MyLinkedList) Get(index int) int {
   if index >= this.Size {
      return -1
   }
   result := this.Head
   for i:=0;i<index;i++ {
      result = result.Next
   }
   return result.Val
}


func (this *MyLinkedList) AddAtHead(val int)  {
   this.Size += 1
   newheader := &Node{val, nil}
   newheader.Next = this.Head
   this.Head = newheader
}


func (this *MyLinkedList) AddAtTail(val int)  {
   this.Size += 1
   newtailer := &Node{val, nil}
   if this.Size == 1 {
      this.Head = newtailer
      return
   }
   tmp := this.Head
   for tmp.Next != nil {
      tmp = tmp.Next
   }
   tmp.Next = newtailer
}


func (this *MyLinkedList) AddAtIndex(index int, val int)  {
   if index <= this.Size {
      this.Size += 1
      newnode := &Node{val, nil}
      tmp := this.Head
      if index == 0 {
         this.Head = newnode
         newnode.Next = tmp
         return
      }

      for i:=1; i<index; i++ {
         tmp = tmp.Next
      }
      next := tmp.Next
      tmp.Next = newnode
      newnode.Next = next
   }
}


func (this *MyLinkedList) DeleteAtIndex(index int)  {
   if index < this.Size {
      tmp := this.Head
      this.Size -= 1
      if index == 0 {
         this.Head = tmp.Next
         return
      }
      for i:=1;i<index;i++ {
         tmp = tmp.Next
      }
      rm := tmp.Next
      tmp.Next = rm.Next

   }
}


/**
 * 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);
 */

206 反转链表

image.png

双指针解法:

原链表 image.png

反转列表后,链表的最后一个节点 data0 的next指针指向nil,故我们使用虚拟头节点,使用一个nil节点指向data0(头节点)

image.png

设置 pre,cur两个指针,分别指向nil,data0。反转pre 和 cur两个节点 (cur指向pre)

image.png

pre和cur分别向右移一个节点,再反转pre和cur两个节点,直到cur指向nil,停止移动。

image.png 最后返回pre,pre是反转后的链表的头节点

代码


package main

type ListNode struct {
   Val  int
   Next *ListNode
}

func reverseList(head *ListNode) *ListNode {
   // 虚拟头节点
   var pre *ListNode = nil
   cur := head

   for cur != nil {
      tmp := cur.Next
      cur.Next = pre
      pre = cur
      cur = tmp
   }
   return pre
}

总结

虚拟头节点的巧用

-   **是否要添加虚拟头结点** :  
    虚拟头结点的主要目的是为了避免对头结点的特殊处理;这个处理就指的是修改操作。所以可以这样:涉及到对链表修改(如插入,删除,移动)的,都加个dummy,只是遍历取点就可以不用加