leetcode136.只出现一次的数字
题目描述:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
思路:异或运算
对于异或运算有以下特性:
- a ^ a = 0
- a ^ 0 = a
已知非空数组中,只有某个元素出现了一次,其余的元素均出现了两次。所以,我们可以从头让每个元素依次进行异或运算,一直遍历到最后一个元素,异或的结果就是那个只出现一次的元素。代码如下:
class Solution {
public int singleNumber(int[] nums) {
int res = 0;
for(int i = 0; i < nums.length; ++i){
res ^= nums[i];
}
return res;
}
}
时间复杂度:O(N)
额外空间复杂度:O(1)
代码执行结果:
leetcode 137.只出现一次的数字ii
题目描述:
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,3,2]
输出: 3
示例 2:
输入: [0,1,0,1,0,1,99]
输出: 99
思路:位运算
对于题目的示例:
[2,2,3,2]
转换为二进制后:
10
10
11
10
每一位上对1的个数进行统计,如果能整除3,那么返回结果的那一位则为0;如果不能整除3,那么返回结果的那一位则为1:
10
10
11
10
第一位的和为1,第二位的和为4,都不能整除3,所以结果为:
11
返回的结果转换为十进制后,也正好为只出现一次的那个元素
代码如下:
class Solution {
public int singleNumber(int[] nums) {
int res = 0;
for(int i = 0;i < 32;i++){
int temp = 0;
for(int num : nums){
temp += (num >>> i) & 1;
}
if(temp % 3 != 0){
res |= (1 << i);
}
}
return res;
}
}
时间复杂度:O(N)
额外空间复杂度:O(1)
代码执行结果: