题目理解
题目描述了一个特定的场景:在一个班级中,每位同学都拿到了一张卡片,卡片上有一个整数。除了一个数字之外,所有的数字都恰好出现了两次。现在需要找出那个独特数字是什么。
同时,题目给出了两个明确的要求:
设计一个算法,时间复杂度为O(n),其中n是班级的人数。
尽量减少额外空间的使用,以体现算法的优化能力。
算法设计
考虑到题目的特殊要求,我们可以采用位运算的思想来解决这个问题。位运算在处理整数和判断某些特定位是否设置时非常高效,且不需要额外的空间(除了存储结果的变量外)。
具体算法如下:
初始化一个变量unique_num为0,用于存储最终的结果。
遍历班级中每位同学的卡片数字:
对于每个数字,我们将其与unique_num进行异或运算,并将结果存回unique_num中。
异或运算的性质是:如果两个数字相同,则异或结果为0;如果两个数字不同,则异或结果为非0值(且这个非0值是两个数字中唯一的那个,在二进制表示上不同的位)。
由于除了一个数字之外,其他数字都恰好出现了两次,所以这些成对的数字在异或运算中会相互抵消(即异或两次同一个数字会回到初始状态0)。
因此,遍历结束后,unique_num中存储的就是那个独特数字。
测试样例
由于题目没有给出具体的测试样例,这里我们可以自己构造一个来验证算法的正确性。
例如,假设班级中有5位同学,他们手中的卡片数字分别是:1, 2, 3, 2, 1。那么,根据算法,我们应该能够得到独特数字是3。
具体计算过程如下:
初始时,unique_num = 0。
遍历第一个数字1,unique_num = 0 ^ 1 = 1。
遍历第二个数字2,unique_num = 1 ^ 2 = 3。
遍历第三个数字3,unique_num = 3 ^ 3 = 0(但这里我们不会回到0,因为3不是成对出现的数字)。然而,由于后续还有数字,我们继续计算。
遍历第四个数字2(已经出现过一次),unique_num = 0 ^ 2 = 2(但注意,这里的0是上一步异或3的结果,实际上在连续异或中,我们可以忽略中间结果,直接看最终异或结果)。然而,同样地,由于后续还有数字,且2是成对出现的,我们继续计算。
遍历第五个数字1(已经出现过一次),unique_num = 2 ^ 1 = 3。此时,我们得到了最终结果3,这就是那个独特数字。
当然,在实际计算中,我们不会每次都回到0再开始异或,而是直接连续异或所有数字。上面的计算过程只是为了解释异或运算的性质和算法的工作原理。
综上所述,该算法满足题目要求的时间复杂度和空间复杂度,且能够有效地找出那个独特数字。 public class Main { public static int solution(int[] inp) { // Edit your code here int[] a = new int[1001];//标记数组 int i = 0; int sum = 0; for(i = 0;i < inp.length;i++) { if(a[inp[i]] == 0){ a[inp[i]] = 1;sum += inp[i]; } else{ sum -= inp[i]; } } return sum; }
public static void main(String[] args) {
// Add your test cases here
int[] inp = {0,1,0,1,2};
System.out.println(solution(inp));
//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);
}
}