只出现一次的数字-LeetCode算法详细分析
Posted CoseFy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了只出现一次的数字-LeetCode算法详细分析相关的知识,希望对你有一定的参考价值。
题目:只出现一次的数字
给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
说明:
你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例 1:
输入: [2,2,1]
输出: 1
示例 2:
输入: [4,1,2,1,2]
输出: 4
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
/**
* @author cosefy
* @date 2020/6/8
*/
public class SingleNumber {
public static void main(String[] args) {
int[] nums = {24,45,1,24,1};
int num1 = singleNumber_Test1(nums);
int num2= singleNumber_Test2(nums);
int num4= singleNumber_Test4(nums);
System.out.println(num1+" "+num2+" "+num4);
}
}
解法一:哈希表辅助求解
思路:利用哈希表来记录数组中元素出现个数,key值记录数值大小,value记录出现次数,然后遍历哈希表得到出现次数为1的数值
分析:虽然时间复杂度为O(n),但是由于哈希表的添加元素以及哈希表的遍历,时间效率不是很高。
易错点:
-注意一次循环中迭代器不能用两次next方法,否则会出现NoSuchElementException异常
-注意常见错误
思考:
-考虑哈希表本方法是否存在改进的可能
-思考没有辅助空间的解决方法
public static int singleNumber_Test1(int[] nums) {
// char[] n = int[nums.length/2+1];
if(nums.length%2 ==0)
return -1;
HashMap<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
if (!map.containsKey(num))
map.put(num, 1);
else {
Integer integer = map.get(num);
map.put(num, integer + 1);
}
}
Iterator<Integer> it = map.keySet().iterator();//此处也可用增强for循环来遍历
while (it.hasNext()) {
int key = it.next();
//System.out.println("key:" + key + "Value: " + map.get(key));
if(map.get(key)==1)
return key;
}
//此处while循环中若一次循环里用到两次next方法,会抛出NoSuchElementException异常
throw new IllegalArgumentException("不存在单个数值");
}
解法二:列表辅助实现
思路 :将数组中的元素存放到列表中,若存放相同元素,则将该元素移除,最后列表只剩下单个元素。
分析:这里同样借助了辅助空间,空间复杂度为O(n),时间复杂度O(n)
public static int singleNumber_Test2(int[] nums) {
if(nums.length%2 ==0)
return -1;
ArrayList<Integer>list = new ArrayList<>();
for (int num : nums) {
if(!list.contains(num)) {
list.add(num);
}
else {
list.remove(list.indexOf(num));
}
}
return list.get(0);
}
解法三:set辅助实现
思路:利用set元素不重合的特性,将所有不重合元素求和为sum1,数组所有元素求和为sum2,sum1*2-sum2即为单个元素值。
分析:空间复杂度为O(n),时间复杂度为O(n),过程简单
过程较为简单,不再单独书写
解法四:利用异或方法(无需辅助空间)
思路:异或操作的特点是相同元素直接异或为0,而0和任一元素异或得到任一元素自身,并且满足交换律。所以适合本题的解法
分析:时间复杂度为O(n),空间复杂度为O(1)
Javapublic static int singleNumber_Test4(int[] nums){
if(nums.length==1)
return nums[0];
if(nums.length%2==0)
return -1;
int res = nums[0];
for (int i = 1; i < nums.length; i++) {
res = res ^ nums[i];
}
return res;
}
以上是关于只出现一次的数字-LeetCode算法详细分析的主要内容,如果未能解决你的问题,请参考以下文章
数据结构和算法LeetCode,初级算法-5只出现一次的数字