GitHub地址
题目:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例:
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
代码:
我一开始的思路是将数组进行排序,排序之后只要确保中间的数和前一个数,后一个数都不相等,这样这个数就肯定是只出现了一次的,因为第一个数没有前一个数,最后一个数也没有后一个说,所以这两个位置的数单独处理,这样就有了下面的代码,只击败了40%的LeetCode小伙伴。
public class SingleNumber {
public static int singleNumber(int[] nums) {
if (nums != null && nums.length == 1) {
return nums[0];
}
Arrays.sort(nums);
int i;
for (i = 1; i < nums.length - 1; i++) {
if ((i - 1) == 0) {
if (nums[i] != nums[i - 1]) {
i--;
break;
} else {
continue;
}
}
if ((i + 1) == nums.length - 1) {
if (nums[i + 1] != nums[i]) {
i++;
break;
} else {
continue;
}
}
if (nums[i - 1] != nums[i] && nums[i] != nums[i + 1])
break;
}
return nums[i];
}
public static void main(String[] args) {
int[] nums = {1, 2, 1, 2,4};
System.out.println(singleNumber2(nums));
}
最快的算法是下面的,大佬写的。
public static int singleNumber(int[] nums) {
int ans = 0;
for (int num : nums) {
ans ^= num;
}
return ans;
}
一开始的时候没有看太懂这个 ^= 符号,其实这个就和 += 是一个道理,即 ans = ans ^ num,即代码可以改成下面的
public static int singleNumber(int[] nums) {
int ans = 0;
for (int num : nums) {
ans = ans ^ num;
}
return ans;
}
这个地方用到的是异或运算符 ^,需要知道两点这个算法就可以理解了
- a ^ 0 = a
- a ^ a = 0
即任何一个数异或0都等于这个数,任何一个数异或自身都等于0.
下面是异或运算图解:
所以针对于这一题就很容易发现,两个相同的数异或结果为0,只有只出现一次的数字与 ans = 0 异或。