[Go] LeetCode第三天|203.移除链表元素 707.设计链表 206.反转链表
203.移除链表元素
题目链接: https://leetcode.cn/problems/remove-linked-list-elements/
关键词:单链表
解法
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func removeElements(head *ListNode, val int) *ListNode {
dummyHead := &ListNode{} //虚拟头结点,有利于操作一致性,不用单独考虑第一个结点和最后一个结点的删除问题
dummyHead.Next = head
cur := dummyHead
for cur!= nil && cur.Next != nil {
if cur.Next.Val == val {
cur.Next = cur.Next.Next
} else {
cur = cur.Next
}
}
return dummyHead.Next //此处不能为head,因为当所有的结点都要移除时,只会修改dummuHead.Next,head和之后结点并未受影响
}
707.设计链表
题目链接: https://leetcode.cn/problems/design-linked-list/
关键词:链表
解法
注意:题目的下标 index 和数组一样,从0开始
type MyLinkedList struct {
dummyHead *SingleNode
Size int
}
type SingleNode struct {
Val int
Next *SingleNode
}
func Constructor() MyLinkedList {
//初始化哑结点
newNode := &SingleNode{
Val: -1,
Next: nil,
}
return MyLinkedList{
dummyHead: newNode,
Size: 0,
}
}
func (this *MyLinkedList) Get(index int) int {
//判断是否非法
if index < 0 || index >= this.Size { //注意此处为>=
return -1
}
//获取头结点
cur := this.dummyHead.Next
for i := 0; i < index; i++ { //循环index次
cur = cur.Next
}
return cur.Val
}
func (this *MyLinkedList) AddAtHead(val int) {
newNode := &SingleNode{
Val: val,
Next: this.dummyHead.Next,
}
this.dummyHead.Next = newNode
this.Size++
}
func (this *MyLinkedList) AddAtTail(val int) {
newNode := &SingleNode{
Val: val,
}
tail := this.dummyHead
for tail.Next != nil {
tail = tail.Next
}
tail.Next = newNode
this.Size++
}
func (this *MyLinkedList) AddAtIndex(index int, val int) {
newNode := &SingleNode{
Val: val,
}
if index < this.Size {
cur := this.dummyHead //设置当前节点为虚拟头节点
for i := 0; i < index; i++ {
cur = cur.Next // 遍历至index的前一个节点
}
newNode.Next = cur.Next
cur.Next = newNode
this.Size++
} else if index == this.Size {
cur := this.dummyHead
for i := 0; i < index; i++ {
cur = cur.Next
}
cur.Next = newNode
this.Size++
}
}
func (this *MyLinkedList) DeleteAtIndex(index int) {
if index < 0 || index >= this.Size {
return
}
pre := this.dummyHead
for ; index > 0; index-- { //会循环index次。从哑结点(可以看作index=-1)开始走,即走到会走到下标为index-1的结点
pre = pre.Next
}
t := pre.Next
pre.Next = t.Next
t.Next = nil
this.Size--
}
/**
* 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.反转链表
题目链接: https://leetcode.cn/problems/reverse-linked-list/
关键词:单链表
解法一:新建List
相当于头插法,新建List浪费了空间
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseList(head *ListNode) *ListNode {
dummyHead := &ListNode{
Next: head,
}
newListNode := &ListNode{
Next: nil,
}
for dummyHead.Next != nil{
cur := dummyHead.Next
dummyHead.Next = dummyHead.Next.Next //这行代码与下行代码一定不能颠倒顺序
cur.Next = newListNode.Next
newListNode.Next = cur
}
return newListNode.Next
}
解法二:双指针 1.0
直接将相邻之间的结点指向反向,无需额外开辟空间
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseList(head *ListNode) *ListNode {
if head == nil {
return nil
}
if head.Next == nil {
return head
}
pre := head
cur := head.Next
temp := &ListNode{}
for cur.Next != nil {
temp = cur.Next
cur.Next = pre
pre = cur
cur = temp
}
cur.Next = pre
head.Next = nil
return cur
}
解法三:双指针 2.0
将 pre 设置为指向 *ListNode 类型的空指针,相当于虚拟头结点的作用,统一操作
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func reverseList(head *ListNode) *ListNode {
var pre *ListNode = nil
cur := head
for cur != nil {
temp := cur.Next
cur.Next = pre
pre = cur
cur = temp
}
return pre
}