小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
【说明】
算法应该具有线性时间复杂度。 不使用额外空间来实现
-
示例 1:
输入: [2,2,1]
输出: 1
-
示例 2:
输入: [4,1,2,1,2]
输出: 4
来源:LeetCode
原则:先暴力,后方法优化
【暴力法】
// java
class Solution {
public int singleNumber(int[] nums) {
// 判断数组是否只有一个元素
if(nums.length == 1){
return nums[0];
}
// 对数组进行排序
Arrays.sort(nums);
// 判断排序后的前两个数字是否不同
if(nums[0]!=nums[1]){
return nums[0];
}
int len = nums.length;
// 判断排序后最后两个数字是否不同
if(nums[len-1] !=nums[len-2]){
return nums[len-1];
}
int res = 0 ;
// 判断中间部分的数字与两边的数字是否都不相同
for(int i = 1;i<len-1;i++){
if(nums[i]!=nums[i-1] && nums[i]!=nums[i+1]){
res = nums[i];
break;
}
}
return res;
}
}
【位运算】
使用异或运算,不同为1,相同为0。
0与任意数n取异或的结果仍为n,所以最后就只剩一个数。
异或满足以下规律:
- 1、归零率:
n ^ n = 0 - 2、恒等率:
n ^ 0 = n - 3、交换律:
n ^ m = m ^ n - 4、结合率:
n ^ m ^ i = n ^ (m^i) = (n^m) ^ i - 5、自反:
n ^ m ^ n = m - 6、由
x = y ^ z ^ w 可以推出 w = x ^ y ^ z
// java
class Solution {
public int singleNumber(int[] nums) {
int res = 0 ;
// 可以先进行排序,排序后,利用结合率
// 相同的异或为0 ,
// 最后 0 与单独的数异或,结果还是那个数
for(int i = 0 ; i< nums.length ; i++){
// 0 与 nums[i] 异或的结果仍为nums[i]
// nums[i] 与 nums[i+1] 取异或,
// 若相同,则 res = 0 ;
// 若不同,则 res = 1 ;
res = res ^ nums[i];
}
// 返回单独的数
return res;
}
}