首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Swift 实现:寻找单链表相交节点

Swift 实现:寻找单链表相交节点

原创
作者头像
Swift社区
发布2024-12-31 15:48:50
发布2024-12-31 15:48:50
1680
举报
文章被收录于专栏:Swift社区Swift社区

摘要

本篇文章将分享如何通过 Swift 编写程序,找到两个单链表相交的起始节点。我们将分析问题,提供清晰的题解代码,并通过示例测试验证结果。同时,文章会详细剖析代码逻辑,评估其时间复杂度和空间复杂度,助力开发者掌握高效算法的实现技巧。

描述

编写一个程序,找到两个单链表相交的起始节点。

如下面的两个链表:

在节点 c1 开始相交。

示例 1:

输入:intersectVal = 8, listA = 4,1,8,4,5, listB = 5,0,1,8,4,5, skipA = 2, skipB = 3

输出:Reference of the node with value = 8

输入解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 4,1,8,4,5,链表 B 为 5,0,1,8,4,5。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

示例 2:

输入:intersectVal = 2, listA = 0,9,1,2,4, listB = 3,2,4, skipA = 3, skipB = 1

输出:Reference of the node with value = 2

输入解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各自的表头开始算起,链表 A 为 0,9,1,2,4,链表 B 为 3,2,4。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

示例 3:

输入:intersectVal = 0, listA = 2,6,4, listB = 1,5, skipA = 3, skipB = 2

输出:null

输入解释:从各自的表头开始算起,链表 A 为 2,6,4,链表 B 为 1,5。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。

解释:这两个链表不相交,因此返回 null。

注意:

  • 如果两个链表没有交点,返回 null.
  • 在返回结果后,两个链表仍须保持原有的结构。
  • 可假定整个链表结构中没有循环。
  • 程序尽量满足 O(n) 时间复杂度,且仅用 O(1) 内存。

题解答案

以下为 Swift 的题解实现:

代码语言:swift
复制
class ListNode {
    var val: Int
    var next: ListNode?

    init(_ val: Int) {
        self.val = val
        self.next = nil
    }
}

class Solution {
    func getIntersectionNode(_ headA: ListNode?, _ headB: ListNode?) -> ListNode? {
        guard headA != nil && headB != nil else { return nil }
        
        var pointerA = headA
        var pointerB = headB
        
        while pointerA !== pointerB {
            pointerA = pointerA == nil ? headB : pointerA?.next
            pointerB = pointerB == nil ? headA : pointerB?.next
        }
        
        return pointerA
    }
}

题解代码分析

  1. 基本思路undefined使用双指针法解决问题:
    • 两个指针分别从 headAheadB 开始,依次遍历链表。
    • 如果指针到达链表尾部,则切换到另一个链表的头部继续遍历。
    • 当两个指针相遇时,即为链表的相交节点;若无相交节点,则最终返回 nil
  2. 关键逻辑
    • 双指针在遍历链表时,总会同时进入交点或结束(无交点时均为 nil)。
    • 通过两次遍历,确保指针在长度不同的链表上补齐长度差异。
  3. 核心代码解析
    • pointerA = pointerA == nil ? headB : pointerA?.nextundefined当 pointerA 到达链表 A 的末尾时,切换到链表 B 的头部,反之亦然。

示例测试及结果

代码语言:swift
复制
// 示例链表创建
let common = ListNode(8)
common.next = ListNode(4)
common.next?.next = ListNode(5)

let listA = ListNode(4)
listA.next = ListNode(1)
listA.next?.next = common

let listB = ListNode(5)
listB.next = ListNode(0)
listB.next?.next = ListNode(1)
listB.next?.next?.next = common

// 测试用例
let solution = Solution()
if let intersection = solution.getIntersectionNode(listA, listB) {
    print("Intersection Node Value: \(intersection.val)") // 输出:8
} else {
    print("No Intersection")
}

输出结果:

代码语言:txt
复制
Intersection Node Value: 8

时间复杂度

  • 分析:undefined每个指针最多遍历两个链表的总长度,时间复杂度为 (O(m + n)),其中 (m) 和 (n) 分别为链表 A 和链表 B 的长度。

空间复杂度

  • 分析:undefined仅使用了两个指针,额外空间复杂度为 (O(1))。

总结

通过双指针法,成功实现了寻找链表相交节点的高效算法。其优势在于时间复杂度 (O(n))、空间复杂度 (O(1)) 的表现。实际应用中,该方法具有较高的通用性,非常适合处理单链表相关问题。

未来可以进一步扩展到其他链表问题,例如检测链表环、合并链表等。希望本篇文章能帮助大家更好地理解和掌握链表算法的核心技巧!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 摘要
  • 描述
  • 题解答案
  • 题解代码分析
  • 示例测试及结果
  • 时间复杂度
  • 空间复杂度
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档