iOS算法刷题之链表

242 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情

链表.png

链表也是常被问到的题型,比如说环形链表、相交链表、合并链表、链表的中间结点、反转链表、回文链表等。使用到的技术会有虚拟头节点、双指针、递归等。

虚拟头节点

虚拟头节点,也就是“dymmy”节点。在有些题中,如果不适用“dymmy”虚拟节点,代码会复杂很多,而有了“dummy”节点这个占位符,可以避免处理空指针的情况,降低代码的复杂性。 虚拟头节点举例: 21. 合并两个有序链表

题解:创建一个虚拟头节点dumy,并保存虚拟头节点为head,当n1和n2都不为空时,遍历n1和n2接入到dumy中。剩下的不为空的n1或n2直接接入到dumy后面,最终返回head.next

class Solution {
    func mergeTwoLists(_ list1: ListNode?, _ list2: ListNode?) -> ListNode? {
        var dumy: ListNode? = ListNode(-1)
        var head = dumy
        
        var n1 = list1
        var n2 = list2
        
        while n1 != nil && n2 != nil {
            if n1!.val < n2!.val {
                dumy?.next = n1
                n1 = n1!.next
            }else {
                dumy?.next = n2
                n2 = n2!.next
            }
            dumy = dumy?.next
        }

        if n1 != nil {
            dumy?.next = n1
        }

        if n2 != nil {
            dumy?.next = n2
        }

        return head!.next
    }
}

其他虚拟头节点的题:剑指Offer 18. 删除链表的节点

双指针

链表是内存不连续的,遍历的话只能从头开始一直遍历,使用双指针技巧可以减少遍历的复杂度。 双指针举例: 141. 环形链表

题解:创建两个指针slow和fast,slow每次走一步,fast每次走两步。当slow不为空fast不为空并且slow=fast,返回true。否则返回false。

class Solution {
    func hasCycle(_ head: ListNode?) -> Bool {
        if head == nil || head!.next == nil {
            return false
        }
        var slow = head
        var fast = head?.next
        while slow != nil && fast != nil {
            if slow === fast {
                return true
            }
            slow = slow?.next
            fast = fast?.next?.next
        }
        return false
    }
}

其他双指针经典题:23. 合并K个升序链表142. 环形链表 II876. 链表的中间结点19. 删除链表的倒数第N个结点160. 相交链表

递归

链表不光有迭代的特性,还有递归的特性,递归在很多题型当中都会用到,对于递归算法,最重要的就是明确递归函数的定义。 递归题举例: 206. 反转链表

题解:last是反转完成的链表,也就是最后一个节点。现在的head.next到last都反转完成,现在需要把head也反转一下,所以head.next.next指向head,head.next指向nil,这样就反转完成了。递归的basecase是当head为nil或者head.next为nil直接返回head。

class Solution {
    func reverseList(_ head: ListNode?) -> ListNode? {
        if head == nil || head?.next == nil {
            return head
        }
        var last = reverseList(head?.next)
        head?.next?.next = head
        head?.next = nil
        return last
    }
}

其他递归经典题:92. 反转链表 II25. K个一组翻转链表148. 排序链表

总结

链表的题也要多刷,也是属于基础结构,比较好培养算法思想。 其他链表题还有:234. 回文链表