链表算法(2)

25-09-19 反转链表、两数之和
25-09-20 两两交换链表中的节点
昨天和今天在准备速写带画教学内容,学习进度放缓…
相关链接:代码随想录 |> 206.反转链表|24. 两两交换链表中的节点|1. 两数之和

# 206.反转链表

206. 反转链表

简单

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

img

>输入:head = [1,2,3,4,5]
>输出:[5,4,3,2,1]

示例 2:

img

>输入:head = [1,2]
>输出:[2,1]

示例 3:

>输入:head = []
>输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?

# 双指针法

写的时候犯了个小错误,由于基础不牢,不知道怎么直接给 prev nil,然后直接写了 prev := &ListNode{} 再赋值成 nil ,然后这个节点被丢弃掉,等待 GC 回收。多了一次无意义的分配。

应该是: var prev *ListNode

含义:声明了一个指针,初始状态是「空指针」,不指向任何元素。

这证明我对结构体的传递还不熟悉。

大致过程:

prev = nil

cur = head

tmp = cur.Next // tmp 存储下一个节点,防止指针反向后丢失

cur.Next = prev // 指针反向

以上就是一次反向的过程,遍历的条件是

for cur != nil {
    
}

如下图所示:

image-20250919211706978

image-20250919211721024


多次操作后…到达最后一次

当 cur == tail 时是最后一次迭代,接着 cur = nil ,不进循环,tmp 也是 nil。此时 return prev 就是反转后的链表

image-20250919211924684

代码

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func reverseList(head *ListNode) *ListNode {
    // prev := &ListNode{}
    // prev = nil
    var prev *ListNode
    cur := head

    for cur != nil {
        tmp := cur.Next // 存储下一个节点/nil
        cur.Next = prev // 反转指向
        // 向后移动
        prev = cur
        cur = tmp
    }
    return prev
}

# 24. 两两交换链表中的节点

24. 两两交换链表中的节点

中等

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

示例 1:

img

>输入:head = [1,2,3,4]
>输出:[2,1,4,3]

示例 2:

>输入:head = []
>输出:[]

示例 3:

>输入:head = [1]
>输出:[1]

提示:

  • 链表中节点的数目在范围 [0, 100]
  • 0 <= Node.val <= 100

# 虚拟头结点

一定要画图

image-20250920174456760

image-20250920174517629

image-20250920174532533

设一个虚拟头结点指向 head ,然后按照上图的步骤操作。注意这里需要设一个 tmp 存一下节点1。

同时需要注意循环条件。

当链表节点数为偶数时,cur.Next != nil (空链表时也满足);

当链表节点数为奇数时,cur.Next.Next != nil

写循环条件时,cur.Next != nil 应该写在 cur.Next.Next != nil 前面,否则可能会操作空指针。

for cur.Next != nil && cur.Next.Next != nil {
}

完整代码

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func swapPairs(head *ListNode) *ListNode {
    DummyHead := &ListNode{Next: head}
    cur := DummyHead

    for cur.Next != nil && cur.Next.Next != nil {
        tmp := cur.Next
        cur.Next = tmp.Next
        tmp.Next = cur.Next.Next
        cur.Next.Next = tmp

        // 移动 cur
        cur = cur.Next.Next
    }
    return DummyHead.Next
}
归档 友链
arrow_up
theme