找单独的数-题目解析| 豆包MarsCode AI刷题

71 阅读4分钟

题目解析

问题描述

在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。

解题思路

问题理解

题目要求在一个整数数组中找到唯一一个出现一次的数字,而其他数字都恰好出现两次。我们需要设计一个时间复杂度为 O(n) 的算法,并且尽量减少额外空间的使用。

数据结构选择

由于题目要求尽量减少额外空间的使用,并且时间复杂度为 O(n),我们可以考虑使用位运算来解决这个问题。具体来说,使用异或运算(XOR)是一个非常合适的选择。

算法步骤

1、异或运算的性质: 任何数与自身异或的结果是 0(即 a ^ a = 0)。

任何数与 0 异或的结果是它本身(即 a ^ 0 = a)。

异或运算满足交换律和结合律,即 a ^ b ^ a = (a ^ a) ^ b = 0 ^ b = b

2、算法实现: 初始化一个变量 uniquenumber 为 0。

遍历数组中的每一个元素,将 uniquenumber 与当前元素进行异或运算。

由于异或运算的性质,所有出现两次的数字会相互抵消,最终 uniquenumber 中剩下的就是唯一出现一次的数字。

代码详解

public class Main {
    public static int solution(int[] inp) {
        int uniquenumber = 0;
        for (int num : inp) {
            uniquenumber ^= num;  // 使用异或运算来找到唯一出现一次的数字
        }
        return uniquenumber;
    }

    public static void main(String[] args) {
        System.out.println(solution(new int[]{1, 1, 2, 2, 3, 3, 4, 5, 5}) == 4);
        System.out.println(solution(new int[]{0, 1, 0, 1, 2}) == 2);
    }
}

代码解释

1、初始化 uniquenumber

int uniquenumber = 0;

2、遍历数组并进行异或运算:

for (int num : inp) {
    uniquenumber ^= num;
}

遍历数组中的每一个元素,将 uniquenumber 与当前元素进行异或运算。由于异或运算的性质,所有出现两次的数字会相互抵消,最终 uniquenumber 中剩下的就是唯一出现一次的数字。 3、返回结果:

return uniquenumber;

测试样例

1、样例1:cards = [1, 1, 2, 2, 3, 3, 4, 5, 5]

异或运算过程:0 ^ 1 ^ 1 ^ 2 ^ 2 ^ 3 ^ 3 ^ 4 ^ 5 ^ 5 = 4

输出:4

2、样例2:cards = [0, 1, 0, 1, 2]

异或运算过程:0 ^ 0 ^ 1 ^ 1 ^ 2 = 2

输出:2

3、样例3:cards = [7, 3, 3, 7, 10]

异或运算过程:0 ^ 7 ^ 3 ^ 3 ^ 7 ^ 10 = 10

输出:10

总结

在这个问题中,我们面对的是一个寻找数组中唯一出现一次的数字的挑战,而数组中其他所有数字都恰好出现两次。这个问题不仅考验了我们对数据结构和算法的理解,还要求我们能够巧妙地运用数学中的异或运算来解决实际问题。

首先,我们深入理解了问题的本质,明确了目标是找到那个唯一的数字。随后,通过对异或运算性质的深刻把握,我们意识到这个运算能够完美地满足问题的需求。异或运算的交换律和结合律使得我们能够将所有出现两次的数字相互抵消,从而留下唯一的那个数字。

在算法实现上,我们采用了简洁而高效的遍历方法,对每个元素进行异或运算。这种方法不仅时间复杂度低,而且空间复杂度也极低,完全符合题目的要求。

此外,我们还通过详细的代码解释和测试样例,展示了算法的具体执行过程和正确性。这不仅有助于我们验证算法的正确性,还能够帮助其他读者更好地理解和应用这个算法。

总的来说,这个问题不仅锻炼了我们的问题解决能力,还让我们深刻体会到了异或运算的巧妙和实用。在未来的学习和工作中,我们应该继续挖掘和运用这些数学工具,以更高效、更优雅地解决各种问题。同时,我们也应该注重算法的优化和空间的利用,以在资源有限的情况下取得更好的性能。