找单独的数

82 阅读3分钟

在一个班级中,每位同学手上都有一张写有整数的卡片。除了一个数字之外,其他所有数字都出现了两次。我们的任务是找到这个只出现一次的数字。

思路分析:

为了在 O(n)  的时间复杂度内解决问题,并且尽量减少额外空间的使用,我们可以采用位运算中的 异或(XOR)  操作。

为什么选择异或操作?

  • 性质1:任何数与0异或结果为其本身,即 a ⊕ 0 = a
  • 性质2:任何数与其自身异或结果为0,即 a ⊕ a = 0
  • 性质3:异或运算满足交换律和结合律。

基于上述性质,如果我们将所有数字进行异或操作,那么成对出现的数字会相互抵消(因为 a ⊕ a = 0),最后剩下的就是那个只出现一次的数字。

代码详解:

cpp
复制代码
#include <vector>

int findUniqueNumber(const std::vector<int>& numbers) {
    int uniqueNumber = 0;
    for (const int& num : numbers) {
        uniqueNumber ^= num; // 逐个进行异或操作
    }
    return uniqueNumber;
}

代码解释:

  • 第3行:  定义函数 findUniqueNumber,接受一个整数向量 numbers

  • 第4行:  初始化变量 uniqueNumber 为0,用于存储最终结果。

  • 第5-7行:  遍历 numbers 中的每个数字,依次进行异或操作。

    • 异或操作过程:

      • 首先,uniqueNumber 与第一个数字异或。
      • 然后,将结果与下一个数字异或。
      • 如此循环,直到遍历完整个数组。
  • 第8行:  返回最终的 uniqueNumber,即只出现一次的数字。

示例运行:

假设 numbers = [2, 3, 5, 4, 5, 3, 4]

  • 初始 uniqueNumber = 0

  • 异或过程:

    • uniqueNumber = 0 ⊕ 2 = 2
    • uniqueNumber = 2 ⊕ 3 = 1
    • uniqueNumber = 1 ⊕ 5 = 4
    • uniqueNumber = 4 ⊕ 4 = 0
    • uniqueNumber = 0 ⊕ 5 = 5
    • uniqueNumber = 5 ⊕ 3 = 6
    • uniqueNumber = 6 ⊕ 4 = 2
  • 最终,uniqueNumber = 2,即只出现一次的数字是2。


知识总结:

  • 异或运算(XOR):  是一种常见的位运算操作,广泛应用于算法优化中,尤其是在处理成对出现的数据时。

  • 时间复杂度分析:

    • 遍历数组:  O(n)
    • 异或操作:  O(1) 时间完成
    • 总体复杂度:  O(n)
  • 空间复杂度分析:

    • 额外空间:  我们只使用了一个整数变量 uniqueNumber,因此空间复杂度为 O(1)

学习建议:

  • 理解位运算:  掌握位运算的基本性质,如与、或、异或、取反等,对于解决类似问题非常有帮助。
  • 优化思维:  在解决问题时,优先考虑时间和空间复杂度,寻找既高效又简洁的算法。
  • 多练习经典算法:  多做一些包含位运算的经典题目,加深对其应用场景的理解。

学习计划:

  1. 巩固基础:  复习位运算的基本概念和性质,确保理解异或操作的特点。
  2. 实践应用:  利用豆包MarsCode AI刷题功能,搜索并练习更多涉及位运算的题目,如只出现一次的数字系列问题。
  3. 总结归纳:  在刷题过程中,记录不同题目的解题思路和技巧,形成自己的知识体系。
  4. 错题回顾:  定期复习做错的题目,分析错误原因,避免类似错误再次发生。

工具运用:

  • 豆包MarsCode AI刷题功能:  利用AI提供的实时反馈和解析,及时纠正错误理解,提升学习效率。
  • 结合其他资源:  如算法书籍、在线课程和技术博客,获取不同的解题思路和技巧。
  • 交流分享:  参与算法讨论社区,与他人分享心得,互相学习,共同进步。

结语:

通过这道题目,我们不仅学会了如何利用异或操作高效地找到只出现一次的数字,还深化了对位运算的理解。希望我的解析和学习心得能对大家有所帮助。学习算法贵在坚持和积累,愿我们都能在算法的道路上不断精进!