[代码随想录]Day03-链表part01

题目:203. 移除链表节点

思路:

20210316095619221

做链表首先最好有个虚拟头指针,这样做删除添加操作的时候可以统一操作否则还得特判。

要删除一个元素x:

  1. 进行的操作只有一步:把x前面节点的Next改为x.Next
  2. 然后要进行操作的节点有x以及x的前一个节点,因此我们至少需要x的前一个节点的位置的控制权。
  3. 迭代规则是:
    1. 如果删除了元素,直接把cur改为cur.Next即可
    2. 如果没有删除元素,把pre指针改为cur的位置,cur改为cur.Next

代码:

双指针迭代

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func removeElements(head *ListNode, val int) *ListNode {
    res := new(ListNode)
    res.Next = head  // 虚拟头指针
    pre, cur := res, res.Next 
    for cur != nil {
        if cur.Val == val {
            cur = cur.Next
            pre.Next = cur
        } else {
            pre = cur
            cur = cur.Next
        }
    }
    return res.Next
}

参考:

代码随想录

题目:707. 设计链表

思路:

究极整合题,核心内容就是如何使用这个虚拟头节点,值得推敲的一道题(毕竟把很多内容全用了)。

代码:

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
type MyLinkedList struct {
    head *ListNode
    size int // 记录长度
}

func Constructor() MyLinkedList {
    return MyLinkedList{&ListNode{},0}
}


func (this *MyLinkedList) Get(index int) int {
    if index <0 || index >= this.size {
        return -1
    }
    cur := this.head // 虚拟头
    for i := 0; i <= index; i++ { 
        cur = cur.Next
    }
    return cur.Val
}


func (this *MyLinkedList) AddAtHead(val int)  {
    this.AddAtIndex(0, val) // 直接使用现成的插入
}


func (this *MyLinkedList) AddAtTail(val int)  {
    this.AddAtIndex(this.size, val) // 直接使用现成的插入
}


func (this *MyLinkedList) AddAtIndex(index int, val int)  {
    if index > this.size {
        return
    }
    if index < 0 {
        index = 0
    }
    this.size++
    cur := this.head
    for i:=0; i < index; i++ {
        cur = cur.Next
    }
    tmp := &ListNode{val,cur.Next}
    cur.Next = tmp
}


func (this *MyLinkedList) DeleteAtIndex(index int)  {
    if index < 0 || index >= this.size {
        return
    }
    this.size--
    cur := this.head
        for i:=0; i < index; i++ {
        cur = cur.Next
    }
    cur.Next = cur.Next.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. 反转链表

思路:

说是双指针其实有三个只是由其中一个能直接得到。

三个指针l、r、t分别代表前一个节点,当前节点,以及下一个节点,那么翻转的步骤如下:

  1. 让当前节点指向前一个节点r.Next = l
  2. 把上一个节点更新为当前节点l = r
  3. 把当前节点更新为下一个节点r = t

需要注意的几个问题:

  1. 要把第一个节点的next改为nil
  2. 结束时r == nil,因此我们返回的是上一个节点l而不是当前节点r

代码:

双指针

/**
 * 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 {
        tmp := cur.Next // 右
        cur.Next = pre
        pre = cur
        cur = tmp
    }
    return pre
}

参考:

代码随想录

补充:

new出来的就不是nil了,这里翻转完成之后最左边的元素要指向nil,因此使用虚拟头的话会产生不必要的错误!当然根本不需要虚拟头,因为不会从头遍历。

posted @   WtcSky  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示