引言
在计算机编程中,面对数组中只有一个元素出现一次,其他元素均出现两次的问题,我们面临着如何高效解决的挑战。本文将介绍两种基于不同思路的线性时间复杂度算法,用于解决这一问题,分别是基于排序和基于位运算的算法。
题目
给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
方法一:基于排序的算法
思路解析
既然是只有一个数只出现一次 其他数字都是两次,我第一时间想到的是奇偶,因此也就想着是否有什么规律,于是就举例排列了一下:
如果我们将绿色矩形看作是那个唯一数 从上面简图可以发现(排序后):
数组的长度一定是奇数
唯一数一定排在奇数位
而且再多思考 就会发现 如果该奇数位不等于他后面的数 那么他一定就是唯一数了
算法步骤
- 对输入数组进行排序。
- 遍历排序后的数组,检查每一个元素是否和后面的元素相同,若不同,则当前元素即为唯一出现一次的元素。
- 如果遍历完数组仍未找到唯一的元素,说明最后一个元素是唯一的。
代码实现
时间复杂度为 O(nlogn),空间复杂度为O(n);
var singleNumber = function(nums) {
nums.sort((a, b) => a - b);
for (let i = 0; i < nums.length - 1; i += 2) {
if (nums[i] !== nums[i + 1]) return nums[i];
}
return nums[nums.length - 1]; // 如果没有找到,则最后一个元素是唯一的
};
方法二:基于位运算的算法
异或操作有以下性质:
- 任何数和 0 做异或运算,结果仍然是原来的数,即 a ^ 0 = a。
- 任何数和其自身做异或运算,结果是 0,即 a ^ a = 0。
- 异或运算满足交换律和结合律,即 a ^ b ^ a = (a ^ a) ^ b = 0 ^ b = b。
思路解析
我们知道了异或操作的特性,就可以利用异或运算找出只出现一次的元素。
算法步骤
- 遍历数组,对所有元素进行异或运算。
- 最终的结果即为唯一出现一次的元素。
代码实现
时间复杂度为 O(n),空间复杂度为 O(1)。
var singleNumber = function(nums) {
let result = 0;
for (let num of nums) {
result ^= num;
}
return result;
};
总结
看见一些前辈说 如果第一想法不是用异或的思路,那么就是算法有所欠缺了,很惭愧,鄙人刚看见题目还是不能想到异或操作的思路,可见算法还是太少了,持之以恒或许才能找到算法的感觉吧 加油