题意整理
- 给定一个数组。
- 求数组中只出现一次的数。
方法一(哈希表)
1.解题思路
记录数组中每一个数出现的次数,并将数组中的数作为键,出现次数作为值添加到哈希表中,然后遍历哈希表,当某个键对应的值为1时,直接返回对应的键,即找到了只出现一次的数。
动图展示:
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param arr int一维数组 * @param k int * @return int */ public int foundOnceNumber (int[] arr, int k) { //新建map,用于计数 Map<Integer,Integer> map=new HashMap<>(); //将数组中所有元素出现次数添加到map for(int a:arr){ map.put(a,map.getOrDefault(a,0)+1); } //如果键为1,说明只出现了一次,直接返回 for(Integer key:map.keySet()){ if(map.get(key)==1){ return key; } } return -1; } }
3.复杂度分析
- 时间复杂度:两次循环都是线性遍历,执行次数不超过n,所以时间复杂度是 。
- 空间复杂度:需要额外大小为n的哈希表,所以空间复杂度为 。
方法二(位运算)
1.解题思路
- 首先创建一个bit数组,用于记录二进制位的变化。
- 然后遍历bit数组,将原数组中元素对应bit位的1添加到bit数组,如果某个数出现k次,那么对k取余之后,对应bit位就会变成0,所以剩下的bit位一定是只出现一次的那个数的。
- 最后从高位往低位依次还原只出现1次的那个数。
2.代码实现
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param arr int一维数组 * @param k int * @return int */ public int foundOnceNumber (int[] arr, int k) { //计算每一个数的bit位 int[] bit=new int[32]; //遍历每一个bit位 for(int i=0;i<32;i++){ //如果某个数出现k次,bit位累加之后就会变为k for(int a:arr){ bit[i]+=((a>>i)&1); } //取余后只剩下出现一次那个数的bit位 bit[i]%=k; } int res=0; //从高位往低位依次还原只出现1次的那个数 for(int i=31;i>=0;i--){ res=(res<<1)|bit[i]; } return res; } }
3.复杂度分析
- 时间复杂度:第一层循环固定32次,第二层n次,总共需要循环 次,所以时间复杂度是 。
- 空间复杂度:需要额外常数级别(大小为32)的bit数组,所以空间复杂度为 。