概念
刷题
203 移除链表元素
使用tmp中间值,记录被删除的元素指针,将上一链表元素指针指向tmp的next指针,就可以删除一个链表元素
需要注意,头节点等于被删除元素的值,被删除元素在末尾,被删除元素是相邻节点的情况
707 设计链表 (重做)
这道题目需要重新做一下 没有使用虚拟头节点
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 反转链表
双指针解法:
原链表
反转列表后,链表的最后一个节点 data0 的next指针指向nil,故我们使用虚拟头节点,使用一个nil节点指向data0(头节点)
设置 pre,cur两个指针,分别指向nil,data0。反转pre 和 cur两个节点 (cur指向pre)
pre和cur分别向右移一个节点,再反转pre和cur两个节点,直到cur指向nil,停止移动。
最后返回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,只是遍历取点就可以不用加