问题描述: 在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。 要求: 1.设计一个算法,使其时间复杂度为 O(n),其中 n是班级的人数。 2.尽量减少额外空间的使用,以体现你的算法优化能力。
约束条件: 1 ≤ cards.length ≤ 1001 。0≤ cards[i] ≤ 1000 班级人数为奇数。 除了一个数字卡片只出现一次外,其余每个数字卡片都恰好出现两次。
解析: 这个问题要求我们找到一个数组中唯一出现一次的数字,其余数字都恰好出现两次。这是一个典型的异或操作问题,因为异或运算有如下特性: 任何数与0进行异或运算,结果都是其本身(a ^ 0 = a)。 任何数与其自身进行异或运算,结果是0(a ^ a = 0)。 异或运算满足交换律和结合律,即a ^ b ^ c = a ^ (b ^ c)。 利用这些性质,我们可以设计一个时间复杂度为O(n)、空间复杂度为O(1)的算法来解决这个问题。 具体步骤如下: 初始化一个变量unique_number为0。 遍历输入数组,对每个元素执行异或运算,并更新unique_number。 由于所有成对的数字在异或运算后都会抵消(变为0),最终unique_number中存储的就是那个唯一出现一次的数字。
图解 假设输入数组为[1, 1, 2, 2, 3, 3, 4, 5, 5],我们逐步进行异或运算的过程如下: 1.初始:unique_number = 0 2.unique_number ^= 1 -> unique_number = 1 3.unique_number ^= 1 -> unique_number = 0(抵消) 4.unique_number ^= 2 -> unique_number = 2 5.unique_number ^= 2 -> unique_number = 0(抵消) 6.unique_number ^= 3 -> unique_number = 3 7.unique_number ^= 3 -> unique_number = 0(抵消) 8.unique_number ^= 4 -> unique_number = 4 9.unique_number ^= 5 -> unique_number = 9(注意这里是二进制异或,不是加法) 10.unique_number ^= 5 -> unique_number = 4(再次抵消) 最终,unique_number的值为4,这就是唯一出现一次的数字。
代码详解
第1行定义了函数solution,接受一个列表inp作为参数。
第2行初始化unique_number为0。
第3-4行遍历列表中的每个数字,并将其与unique_number进行异或运算。
第5行返回最终的unique_number,它就是唯一一个没有配对的数字。
第7-13行是测试用例,用于验证函数的正确性。
通过这种方法,我们可以高效地找到数组中唯一出现一次的数字,而不需要额外的空间来存储数据,且时间复杂度为O(n)。