问题描述:一个整形数组中除了两个数字只出现一次外,其它的数字都出现了两次,获取这两个数字。
思路1:
1) 任何一个数字和自己本身做异或操作的结果都为0,任何一个数字和0做异或操作的结果都为数字本身。
2) 将所有的元素一起做异或操作
3) 异或操作的结果的二进制表示中,按照从右往左的顺序,找到第一个1出现的位置x
4 )将数组中的元素分为两类:
1> 第一类:从右边开始数第x位上的数字为1的元素
2> 第二类:从右边开始数第x位上的数字为0的元素
5)分别对两类元素做异或操作,异或操作的结果即只出现一次的两个元素。
/**
* 一个整形数组,除了两个数字只出现一次以外,其他都出现了两次,找到这两个数字
* @param array
* @return
*/
public static int[] findNumApperOnce(int[] array) {
int tmp = 0;
for(int i = 0;i < array.length;i++) {
tmp ^= array[i]; //得到的是数组中那两个不同元素异或的结果
}
int x = 0;
//判断两个数异或结果的二进制数从右往左数第几位是1
while((tmp & 1) == 0 && x <= 32) {
tmp >>= 1;
x++;
}
int a = 0,b = 0;
for(int i = 0;i < array.length;i++) {
if(isOne(array[i],x)) {
a ^= array[i]; //将二进制数从右往左数的第x位为1的一组数异或,得到一个结果
}else {
b ^= array[i]; //将二进制数从右往左数的第x位为0的一组数异或,得到一个结果
}
}
return new int[] {a,b}; //返回的这两个数,就是数组中两个只出现一次的元素
}
/**
* 判断当前数组元素的第index位是否为0
* @param number
* @param index
* @return
*/
public static boolean isOne(int number,int index) {
number = number >> index;
if((number & 1) != 0) {
return true;
}else {
return false;
}
}
思路2:
1)定义一HashMap的集合(键表示出现的数字,值表示数字出现的次数),遍历数组,一次往集合中添加元素,记录出现次数。
2)定义一个ArrayList集合,遍历HashMap集合,把只出现一次的元素添加到ArrayList集合中
3)遍历读取ArrayList集合即可(数组中只出现一次的元素有0~n个,都可以拿这种方法)
/**
* 一个整形数组,除了两个数字只出现一次以外,其他都出现了两次,找到这两个数字
* @param array
* @return
*/
public static int[] findNumber(int[] array) {
Map<Integer,Integer> hashMap = new HashMap<>();
for(int i = 0;i < array.length;i++) {
if(! hashMap.containsKey(array[i])) {
hashMap.put(array[i],1); //第一次添加,每个元素都只出现一次
}else {
hashMap.put(array[i],hashMap.get(array[i])+1); //后面添加再遇到这个元素,出现次数+1
}
}
ArrayList<Integer> arrayList = new ArrayList<>();
Iterator<Map.Entry<Integer,Integer>> iterator = hashMap.entrySet().iterator();
while(iterator.hasNext()) {
Map.Entry<Integer,Integer> next = iterator.next();
Integer key = next.getKey();
Integer value = next.getValue();
if(value == 1) { //元素只出现一次
arrayList.add(key);
}
}
Iterator<Integer> iterator1 = arrayList.iterator();
int[] array1 = new int[2];
int i = 0;
while(iterator1.hasNext()) {
Integer next = iterator1.next();
array1[i] = next;
i++;
}
return array1;
}
这个题的简单变种是:一组数据中,只有一个元素出现了一次,其他元素均出现了偶数次
思路
- 任何一个数字和自己本身做异或操作的结果都为0,任何一个数字和0做异或操作的结果都为数字本身。
- 将所有的元素一起做异或操作,得到的结果就是那个只出现一次的元素
/**
* 一组数据中,只有一个元素出现了一次,其他元素均出现了偶数次,找到这个元素
* @param array
* @return
*/
public static int[] findNumber1(int[] array) {
if(array == null || array.length == 0) {
return null;
}
int tmp = 0;
for(int i = 0;i < array.length;i++) {
tmp ^= array[i];
}
return tmp;
}