寻找单独的数
1.问题描述
在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。
要求:
设计一个算法,使其时间复杂度为 O(n),其中 n 是班级的人数。
尽量减少额外空间的使用,以体现你的算法优化能力。
2.解决思路:
O(n)的时间复杂度,基本上就是一层循环语句的复杂度。也就是我们需要在最多一层循环语句里面,找到出现一次的数据。
可以维护一个键值对作为哈希表(映射)。key为当前卡片的数字,value为当前卡片出现的次数。我们找出次数为1,就是找出value为1的key。
2.1哈希表解法:
用ES6提供的Map数据结构去存储映射关系:
function solution(cards: number[]): number {
// Edit your code here
// 维护一个键值对Map,key为数字,value为出现的字数
const map = new Map<number,number>();
cards.forEach(card => {
const count = map.get(card) || 0;
map.set(card,count+1);
})
for (const [card,count] of map) {
if (count === 1) return card;
}
return -1;
}
function main() {
// Add your test cases here
console.log(solution([1, 1, 2, 2, 3, 3, 4, 5, 5]) === 4);
console.log(solution([0, 1, 0, 1, 2]) === 2);
}
main();
用Object也可以实现:
function solution(cards: number[]): number {
// Edit your code here
// 维护一个键值对Map,key为数字,value为出现的字数
const record:Record<number,number> = {};
cards.forEach(card => {
const count = record[card] || 0;
record[count] = count+1;
})
for (const key in record) {
if (record[key] === 1) {
return Number(key);
}
}
return -1;
}
function main() {
// Add your test cases here
console.log(solution([1, 1, 2, 2, 3, 3, 4, 5, 5]) === 4);
console.log(solution([0, 1, 0, 1, 2]) === 2);
}
main();
2.2异或操作(XOR)
利用异或(XOR)操作的特性。异或操作有一个非常有用的性质:对于任何整数 x
,x ^ x = 0
,并且 x ^ 0 = x
。这意味着如果我们对数组中的所有元素进行异或操作,所有出现两次的数字会相互抵消,最终剩下的就是只出现一次的数字。
在JavaScript中,异或(XOR)操作是一种位运算符,用符号
^
表示。它对两个操作数的每一位执行逻辑异或操作:如果两个相应的二进制位不同,则结果为1;如果相同,则结果为0。异或的基本用法
给定两个整数A和B,它们之间的异或操作可以写作
A ^ B
。例如:
5 ^ 3
的计算过程如下:
5 的二进制表示是
101
3 的二进制表示是
011
对应位置进行异或运算得到
110
,即十进制的6。
所以,通过异或的方式,相同的数字会被抵消,最终剩下符合题目要求的数字。
function solution(cards: number[]): number {
return cards.reduce((total,current) => total^current,0)
}
function main() {
// Add your test cases here
console.log(solution([1, 1, 2, 2, 3, 3, 4, 5, 5]) === 4);
console.log(solution([0, 1, 0, 1, 2]) === 2);
}
main();