题目
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1] 输出: 1
示例 2:
输入: [4,1,2,1,2] 输出: 4
题解一:双循环
思路很简单,就是两个for循环,查找记录每个数出现的次数.这个耗时很高,大概197ms.
class Solution {
public int singleNumber(int[] nums) {
int len = nums.length;
for(int i=0;i<len;i++){
int flag = 0;
for(int j=0;j<len;j++){
if(nums[i]==nums[j]){
flag++;
}
}
if(flag==1) return nums[i];
}
return -1;
}
}
题解二:排序后两两比较
这是我第一个想到的方法,需要注意的就是首尾巴两个数需要单独拿出来判断一下.
class Solution {
public int singleNumber(int[] nums) {
int c=0;
Arrays.sort(nums);
if(nums.length==1){return nums[0];}
if(nums.length>=2){
if(nums[1]!=nums[0]){
return nums[0];
}
if(nums[nums.length-1]!=nums[nums.length-2]){
return nums[nums.length-1];
}
}
for(int i=1;i<nums.length-1;i++)
{
if((nums[i]!=nums[i+1])&&(nums[i]!=nums[i-1])){
c=nums[i];
break;
}
}
return c;
}
}
题解三:哈希
本人刚开始从leetcode上刷题,解题的时候老是想不到哈希,惭愧啊.
这个解法就是把数组中的元素当做map的key,往map中塞值之前先查询一下有没有,记录一下出现次数作为value.
需要注意的一点就是count的类型必须为Integer,如果是int编译会不通过.
class Solution {
public int singleNumber(int[] nums) {
Map<Integer,Integer> map = new HashMap();
for(Integer i: nums){
Integer count = map.get(i);
count = count == null? 1:++count;
map.put(i,count);
}
for(Integer i : map.keySet()){
if(map.get(i) == 1){
return i;
}
}
return -1; //出错返回-1
}
}
题解四:异或运算
这个解法打死我我也想不到,虽然是科班出身,但是学的东西早就还给老师了.对与或非的位运算更是忘的干干净净,下面先简单复习一下什么是异或运算.
如果我们对 0 和二进制位做 XOR 运算,得到的仍然是这个二进制位
a⊕0=a
如果我们对相同的二进制位做 XOR 运算,返回的结果是 0
a⊕a=0
XOR 满足交换律和结合律
a⊕b⊕a=(a⊕a)⊕b=0⊕b=b
所以我们只需要将所有的数进行 XOR 操作,得到那个唯一的数字。
class Solution {
public int singleNumber(int[] nums) {
int ans = nums[0];
if (nums.length > 1) {
for (int i = 1; i < nums.length; i++) {
ans = ans ^ nums[i];
}
}
return ans;
}
}