LeetCode.206-转链表(Swift)

83 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情 。如果哪里写的不对,请大家评论批评。

希望往后的日子,可以每天坚持一个算法

题目

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

例子1

image.png

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

例子2

image.png
输入: head = [1,2]
输出: [2,1]

例子3

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

分析

1、这是一个链表,只能从head开始。 2、想要反转就需要把0.next=nil,1.next=0 3、需要一个节点变量记录当前的位置,当需要0.next=nil之前,还需要记录1的位置,必须先记录再断开。 4、还需一个节点来记录已经反转的部分链表

图解

  1. 首先画出一个链表,用cur来记录当前的节点 链表反转.drawio (2).png
  2. 然后使用next来临时记录下一个节点next = cur.next(当cur断开之后,临时当做头节点使用)
  3. 这时候cur就可以断开链表了,反转后他是最后一位,所以 cur.next = nil

这里要注意,一会 cur.next = nil有变化

  1. 这时候我们需要pre来保存着已经反转的链表,作为反转之后链表的头结点,下一步就可以处理后面的节点了,cur就变成了cur = next
  2. 这时候我们完成了第一个节点的拆分 链表反转.drawio (3).png
  3. 下面拆分第二个节点,来看看怎么操作
  4. 几乎重复2-5步骤,这个时候cur指向了2,next继续记录下一个节点next = cur.next(当cur断开之后,临时当做头节点使用)
  5. 这时候cur就可以断开链表了,下一步需要去组装反转之后的链表

注意的点来了,这时候cur指向的是2,需求是2.next -> 1所以cur.next = pre

问题来了,我们大概率需要循环2-5的过程,第一步1的时候 cur.next = nil和第二部的cur.next = pre的不一样,怎么办?

你是不是发现,第一步的时候pre实际上是nil的,那么实际想第一步也可以cur.next = pre

  1. 之后依然需要pre来保存着已经反转的链表,作为反转之后链表的头结点,下一步就可以处理后面的节点了,cur就变成了cur = next 链表反转.drawio (5).png
  2. 这时候我们完成了第一个节点的拆分
  3. 之后就按照2-5一直循环下去,一直到cur == nil

链表反转.drawio (6).png

代码

class Solution {
    func reverseList(_ head: ListNode?) -> ListNode? {
        // 链表是否成立
        if head == nil || head?.next == nil {
            return head
        }
        // 反转之后链表的头结点
        var pre : ListNode? 
        // 当前节点的位置
        var cur : ListNode? = head
        // 临时记录下一个节点,作为临时的头节点
        var next : ListNode? 
    
        // 如果当前节点不为nil,一直循环下去
        while cur != nil {
            // 使用临时节点,记录下一个节点,保证前面节点断开不会丢失
            next = cur?.next
            // 当前节点的next指向,已经反转链表的头节点
            cur?.next = pre
            // 当前节点就成为了,已反转链表的头节点
            pre = cur
            // 当前节点向后移位
            cur = next
        }
        // 返回已反转链表的头节点
        return pre!
    }
}