在这个问题中,我们需要在一个整数数组中找到唯一一个出现一次的数字。数组中的其他数字都恰好出现两次。这个问题的一个关键点是,我们需要在时间复杂度为 O(n) 的情况下解决,并且尽量减少额外空间的使用。
数据结构的选择
由于题目要求时间复杂度为 O(n),并且尽量减少额外空间的使用,我们可以考虑使用位操作来解决这个问题。具体来说,异或(XOR)操作是一个非常合适的选择,因为它具有以下特性:
- x ^ x = 0:任何数与自身异或的结果为 0。
- x ^ 0 = x:任何数与 0 异或的结果为该数本身。
- 异或操作满足交换律和结合律:这意味着我们可以任意顺序对数组中的元素进行异或操作,结果不会受到影响。
算法步骤
- 初始化一个变量
result为 0:这个变量将用于存储最终的结果。 - 遍历数组中的每一个元素:对每个元素进行异或操作,并将结果存储在
result中。 - 返回
result:遍历结束后,result中存储的就是唯一一个出现一次的数字。
详细解释
-
初始化
result为 0:因为任何数与 0 异或的结果还是该数本身,所以初始化为 0 不会影响最终结果。 -
遍历数组中的每个元素:
- 对于数组中的每个元素
card,我们执行result ^= card。 - 由于异或操作的特性,成对出现的数字会相互抵消,最终剩下的就是单独的那个数字。
- 对于数组中的每个元素
-
返回
result:遍历结束后,result中存储的就是唯一一个出现一次的数字。
为什么选择异或操作
异或操作在这里非常合适,因为它不仅满足题目要求的时间复杂度 O(n),而且不需要额外的空间。异或操作的特性使得我们可以在一次遍历中完成所有计算,并且不需要额外的数据结构来存储中间结果。
进一步思考
虽然异或操作已经很好地解决了这个问题,但我们还可以进一步思考是否有其他方法可以解决这个问题。例如,我们可以考虑使用哈希表来记录每个数字的出现次数,但这会增加额外的空间复杂度。因此,异或操作仍然是最佳选择。
总结
通过使用异或操作,我们可以在 O(n) 的时间复杂度内找到数组中唯一一个出现一次的数字,并且不需要额外的空间。这种方法不仅高效,而且简洁,完美地满足了题目的要求。public class Main { public static int solution(int[] cards) { int result = 0; for (int card : cards) { result ^= card; // 对所有元素进行异或操作 } return result; }
public static void main(String[] args) {
// Add your test cases here
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);
}
}