算法题讲解:找单独的数(简单题1) | 豆包MarsCode AI刷题

128 阅读5分钟

今天为大家详细讲一道基础的算法题,本文主要是介绍解题的一种具体思路,帮助大家学会怎么高效的刷题。

问题描述

在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。要求算法的时间复杂度为 O(n)O(n),其中 nn 是班级的人数,并且尽量减少额外空间的使用,以体现你的算法优化能力。

做题思路

1. 问题分析

在这个问题中,我们需要在一个数组中找到唯一一个出现一次的数字,而其他数字都恰好出现两次。直接遍历数组并统计每个数字的出现次数会增加时间和空间复杂度,不符合题目要求。因此,我们需要寻找一种更高效的方法来解决这个问题。

2. 关键点

  • 异或运算(XOR) :异或运算是位运算的一种,具有以下重要性质:

    • a⊕a=0a⊕a=0:任何数与自身异或结果为0。
    • a⊕0=aa⊕0=a:任何数与0异或结果为自身。
    • 异或运算满足交换律和结合律,即 a⊕b⊕a=ba⊕b⊕a=b。

这些性质使得异或运算非常适合用于解决这类问题。通过遍历数组,将所有数字进行异或运算,相同的数字会相互抵消,最终剩下的结果就是那个唯一的数字。

3. 解决方案

  • 初始化:定义一个变量 result,初始值为0。
  • 遍历数组:对于数组中的每个数字,将其与 result 进行异或运算。
  • 返回结果:最终 result 中存储的就是那个唯一的数字。

做题方式

  1. 初始化结果变量

    • 定义一个变量 result,初始值为0。这个变量将用于存储最终的结果。
  2. 遍历数组

    • 使用增强型 for 循环遍历数组中的每个元素 num,并将 numresult 进行异或运算。异或运算的结果会保存回 result
  3. 返回结果

    • 遍历完成后,result 中存储的就是那个唯一的数字,返回 result

详细代码讲解

public class Main {
    public static int solution(int[] inp) {
        int result = 0;
        for (int num : inp) {
            result ^= num; // 使用异或运算
        }

        return result;
    }

    public static void main(String[] args) {
        // 测试用例
        System.out.println(solution(new int[]{1, 1, 2, 2, 3, 3, 4, 5, 5}) == 4); // true
        System.out.println(solution(new int[]{0, 1, 0, 1, 2}) == 2); // true
        System.out.println(solution(new int[]{7, 3, 3, 7, 10}) == 10); // true
    }
}

代码解析

  1. 方法定义

    • public static int solution(int[] inp):定义一个静态方法 solution,接收一个整数数组 inp 作为参数,返回一个整数。
  2. 初始化结果变量

    • int result = 0;:初始化一个变量 result,初始值为0。这个变量将用于存储最终的结果。
  3. 遍历数组

    • for (int num : inp) { result ^= num; }:使用增强型 for 循环遍历数组中的每个元素 num,并将 numresult 进行异或运算。异或运算的结果会保存回 result

    • 异或运算的解释

      • 假设数组为 [1, 1, 2, 2, 3, 3, 4, 5, 5],初始时 result = 0
      • 第一次遍历:result = 0 ^ 1 = 1
      • 第二次遍历:result = 1 ^ 1 = 0
      • 第三次遍历:result = 0 ^ 2 = 2
      • 第四次遍历:result = 2 ^ 2 = 0
      • 第五次遍历:result = 0 ^ 3 = 3
      • 第六次遍历:result = 3 ^ 3 = 0
      • 第七次遍历:result = 0 ^ 4 = 4
      • 第八次遍历:result = 4 ^ 5 = 1
      • 第九次遍历:result = 1 ^ 5 = 4
    • 最终 result 的值为4,即数组中唯一一个出现一次的数字。

  4. 返回结果

    • return result;:遍历完成后,result 中存储的就是那个唯一的数字,返回 result
  5. 测试用例

    • System.out.println(solution(new int[]{1, 1, 2, 2, 3, 3, 4, 5, 5}) == 4);:测试用例1,输出 true 表示结果正确。
    • System.out.println(solution(new int[]{0, 1, 0, 1, 2}) == 2);:测试用例2,输出 true 表示结果正确。
    • System.out.println(solution(new int[]{7, 3, 3, 7, 10}) == 10);:测试用例3,输出 true 表示结果正确。

代码优化

  1. 时间复杂度

    • 该算法的时间复杂度为 O(n)O(n),因为我们需要遍历整个数组一次。
  2. 空间复杂度

    • 该算法的空间复杂度为 O(1)O(1),因为我们只使用了一个额外的变量 result 来存储中间结果。

总结

通过使用异或运算,我们可以在 O(n)O(n) 时间复杂度和 O(1)O(1) 空间复杂度内找到数组中唯一一个出现一次的数字。这种方法不仅高效,而且简洁,非常适合解决这类问题。在做题过程中,我们可以常用右侧的ai功能,为我们提供思路,一道简单题思考五分钟左右依然毫无思路,就不要再浪费时间了,让ai给一些思路,刷题会更快。

扩展思考

  1. 多于一个唯一数字的情况

    • 如果数组中有多于一个唯一数字,如何找到所有的唯一数字?
    • 一种方法是使用哈希表来记录每个数字的出现次数,然后再遍历哈希表找到出现次数为1的数字。但这会增加空间复杂度。
  2. 扩展到多个数组

    • 如果有多个数组,每个数组中都有一个唯一数字,如何高效地找到所有数组中的唯一数字?
    • 可以考虑将所有数组合并成一个大数组,然后使用上述方法找到唯一数字。
  3. 实际应用

    • 这种方法在数据处理和算法竞赛中非常常见,尤其是在需要高效处理大量数据的情况下。
    • 例如,在数据库查询优化中,可以利用类似的思想来快速找到唯一键值。

希望这些扩展思考能帮助你更深入地理解这个问题,并激发你在算法领域的探索兴趣。如果你有更多的问题或想法,欢迎随时交流!