返回

解码 LeetCode:从 136 题了解只出现一次的数字背后的妙法

IOS

探索算法世界:破解 LeetCode 136 题「只出现一次的数字」

算法在编程中的重要性

在计算机编程的浩瀚世界中,算法扮演着至关重要的角色。它犹如一张蓝图,指引着程序的执行方向,决定着程序的运行效率。对于程序员而言,掌握算法的精髓至关重要,它能帮助我们编写出高效、健壮的代码。

LeetCode:算法学习的殿堂

作为全球知名的算法学习平台,LeetCode 汇聚了众多优质算法题,吸引了无数程序员前来挑战。其中,136 题「只出现一次的数字」备受关注。在这篇文章中,我们将跟随算法达人顾毅的脚步,从 Swift 视角纵览算法世界,洞悉编程精髓,共同揭秘只出现一次的数字背后的妙法。

一、题目背景

在给定一个非空整数数组中,除了某个元素只出现一次外,其余每个元素均出现两次。找出那个只出现一次的元素。

示例:

  • 输入: [2,2,1]

  • 输出: 1

  • 输入: [4,1,2,1,2]

  • 输出: 4

  • 输入: [1]

  • 输出: 1

二、算法思路

解决此题的关键在于充分利用数组中数字出现的次数特点,即除了某个元素只出现一次外,其余每个元素均出现两次。基于此,我们可以使用位运算来解决此题。

位运算的基本原理

  • 按位与运算(&):当两个二进制位均为 1 时,结果为 1,否则为 0。
  • 按位或运算(|):当两个二进制位中至少有一个为 1 时,结果为 1,否则为 0。
  • 按位异或运算(^):当两个二进制位不同时,结果为 1,否则为 0。

算法步骤

  1. 将数组中的所有元素进行按位异或运算。由于相同数字异或的结果为 0,因此最终结果将是只出现一次的元素。

  2. 将上一步的结果与数组中的每个元素进行按位与运算。由于相同数字与自身按位与的结果为自身,因此最终结果将是只出现一次的元素。

func singleNumber(_ nums: [Int]) -> Int {
    var result = 0
    for num in nums {
        result ^= num
    }
    return result
}

三、算法分析

  • 时间复杂度: O(n),其中 n 为数组的长度。由于算法只需要遍历数组一次,因此时间复杂度为 O(n)。

  • 空间复杂度: O(1),因为算法不需要使用额外的空间。

四、代码实现

// 给定一个非空整数数组,除了某个元素只出现一次外,其余每个元素均出现两次。找出那个只出现一次的元素。
// 你的算法应该具有线性时间复杂度。你能不使用额外空间来实现吗?

func singleNumber(_ nums: [Int]) -> Int {
    var result = 0
    for num in nums {
        result ^= num
    }
    return result
}

// 测试用例
let nums1 = [2,2,1]
let nums2 = [4,1,2,1,2]
let nums3 = [1]

print(singleNumber(nums1)) // 输出:1
print(singleNumber(nums2)) // 输出:4
print(singleNumber(nums3)) // 输出:1

五、结语

通过对 LeetCode 136 题「只出现一次的数字」的分析和讲解,我们不仅学习了算法的基本原理和实现方法,也锻炼了编程思维和解决问题的能力。希望今天的分享对大家有所帮助,也希望大家能够继续关注顾毅的 Swift 算法题题解,一起探索算法世界的奥秘。

常见问题解答

  1. 如何理解按位异或运算?
    按位异或运算的本质是比较两个二进制位的不同性。当两个二进制位不同时,结果为 1,否则为 0。

  2. 为什么异或相同数字的结果为 0?
    因为任何数字与自身异或的结果都是 0。例如,1010 ^ 1010 = 0000。

  3. 为什么与相同数字的结果为自身?
    因为任何数字与自身按位与的结果都是自身。例如,1010 & 1010 = 1010。

  4. 该算法的时间复杂度是多少?
    O(n),其中 n 为数组的长度。

  5. 该算法的空间复杂度是多少?
    O(1),因为算法不需要使用额外的空间。