import java.util.*;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
HashMap<Integer,Integer> map = new HashMap<>();
for(int i = 0; i < array.length; i++){
if(!map.containsKey(array[i])){
map.put(array[i] , i);
}else{
map.remove(array[i]);
}
}
Object[] a = map.keySet().toArray();
num1[0] = (int) a[0];
num2[0] = (int) a[1];
}
} import java.util.*;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if (array == null) {
return;
}
HashSet<Integer> set = new HashSet<>();
for (Integer num : array) {
if (set.contains(num)){
set.remove(num);
}else {
set.add(num);
}
}
int i = 0;
for (Integer a: set) {
if (i == 0){
num1[0] = a;
}else {
num2[0] = a;
}
i++;
}
}
} import java.util.*;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
HashMap<Integer,Integer> map=new HashMap<>();
for(int i: array){
if(!map.containsKey(i)){
map.put(i,1);
}else{
map.put(i, map.get(i)+1);
}
}
int[] ans=new int[2];
int cnt=0;
for(int i:array){
if(map.get(i)==1){
ans[cnt]=i;
cnt++;
}
}
num1[0]=ans[0];
num2[0]=ans[1];
}
}
位异或
import java.util.*;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int eor=0;
for(int i=0;i<array.length;i++){
eor=eor^array[i];
}
int rightOne=eor&(~eor+1);
for(int i=0;i<array.length;i++){
if((array[i]&rightOne)!=0){
num1[0]=num1[0]^ array[i]; //num1[0]初始为0
}
}
num2[0]=eor^num1[0];
}
}
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
Arrays.sort(array);
for(int i=0;i<array.length;i++){
if(i+1<array.length && array[i]==array[i+1]){
i++;
}else if(num1[0]==0){
num1[0]=array[i];
}else{
num2[0]=array[i];
}
}
} //num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int xor1 = 0;
for (int i = 0; i < array.length; i++) {
xor1 = xor1 ^ array[i];
}
// 在xor1中找到第一个不同的位对数据进行分类,分类为两个队列对数据进行异或求和找到我们想要的结果
int index = 1;
while ((index & xor1) == 0)
index = index << 1;// 左移
int result1 = 0;
int result2 = 0;
// 根据index的位数进行分组
for (int i = 0; i < array.length; i++) {
if ((index & array[i]) == 0)
result1 = result1 ^ array[i];
else
result2 = result2 ^ array[i];
}
num1[0] = result1;
num2[0] = result2;
}
} //num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if(array == null || array.length == 0)
return;
// 先异或一次取得结果为两个不同数得异或结果,两个相同数异或等于0了
int length = array.length;
int first = 0;
for(int i = 0 ; i < length ; i++){
first ^= array[i];
}
// 取first中最低位的1,可以使用lowbit
// 这种操作会返回最后一个1及其后面所有零,如lowbit(0011 1000) = 0000 1000
int lowbit = first & -first;
// 根据lowbit分组即可,分组时直接加入异或
int a = 0;
int b = 0;
for(int i = 0 ; i < length ; i++){
if((array[i] & lowbit) == 0){
a ^= array[i];
}else{
b ^= array[i];
}
}
// 最终因为相同的数被分到了同一数组,同的两个数被分到了不同数组
// 因此最终a和b数值即为所求结果
num1[0] = a;
num2[0] = b;
return;
}
} public class Solution {
/**
题目描述
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
题解:
因为题目提示了用位运算: 位运算中异或的性质:两个相同数字异或=0,一个数和0异或还是它本身。
1. 将array 的全部元素进行 异或, 如果结果temp为 0 ,表示不存在两个不同的数字,直接退出;否则进入下一步
2. 找出 temp 的最右边的 1 所在的位置,因为异或操作“相同为0,不同为1”,如果该位置index 为 1 表示,不同的两个数字再该位置上不同;
3. 根据 index 把 array 分成两个子数字, 其中任一个子数组有且仅有一个单一的数字,所以直接与 num1[0]/ num2[0] 进行异或,
最终的异或结果是该单一的数字(以为成对的元素已经异或为0)
*/
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int temp = 0;
for (int i = 0; i < array.length; i++) {
temp ^= array[i];
}
// 存储 temp 的最右边的 1 所在的位置
int index = 0;
while ((temp & 1) == 0) {
index++;
// >> 带进位右移
temp = temp >> 1;
}
// 根据 index 可以把 array 分为两个部分,每个部分均有一个单一的数字
num1[0] = num2[0] = 0;
for (int i = 0; i < array.length; i++) {
// array[i] >> index) & 1 : 求 array[i] 数字的第 index 位的数字是1 还是 0, 以此为array 的分割条件
if (((array[i] >> index) & 1) == 1) {
num1[0] ^= array[i];
}else {
num2[0] ^= array[i];
}
}
}
} import java.util.HashSet;
import java.util.Iterator;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
HashSet<Integer> result = new HashSet<>();
for(int i = 0; i < array.length; i++){
if(result.contains(array[i])){
result.remove(array[i]);
continue;
}
result.add(array[i]);
}
Iterator<Integer> iterator = result.iterator();
while(iterator.hasNext()){
num1[0] = iterator.next();
num2[0] = iterator.next();
}
}
} import java.util.*;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
// 一个数第一次遇到存入 set,第二次遇到将该数从 set 中删除,最后剩下的两个就是只出现一次的
TreeSet<Integer> set = new TreeSet<>();
for(Integer x : array) {
if(!set.contains(x)) {
set.add(x);
} else {
set.remove(x);
}
}
num1[0] = set.pollFirst();
num2[0] = set.pollFirst();
}
} //num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int[] arr = new int[128];
for (int i=0;i<array.length;i++) {
if (arr[array[i]]==0) {
arr[array[i]] = 1;
} else {
arr[array[i]] = 2;
}
}
boolean flag = false;
for (int i=0;i<arr.length;i++) {
if (arr[i]==1) {
if (!flag) {
num1[0] = i;
flag = true;
} else {
num2[0] = i;
break;
}
}
}
}
} import java.util.HashMap;
import java.util.Set;
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
HashMap<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);
}
}
int count = 0;
Set<Integer> keySet = hashMap.keySet();
for (int key : keySet) {
if (hashMap.get(key) == 1) {
if (count == 0) {
num1[0] = key;
count++;
} else if (count == 1){
num2[0] = key;
} else {
break;
}
}
}
}
}
/*思路:先排序,那么相同的两个数必定是挨着的;
判断第一个数,若和第二个不相等,第一个肯定没有重复的;
判断最后一个数,若和倒数第二个不相等,最后一个肯定没有重复的;
再循环判断第二个数到倒数第二个数,若每个数和前后两个数都不同,那么是没有重复的;
*/
import java.util.*;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
Arrays.sort(array);//排序,从小到大
int[] temp=new int[2];//用于存放num1[0],num2[0]两个不重复的数
int k=0;
//判断第一个数是否有重复
if(array[0]!=array[1]){
temp[k]=array[0];
k++;
}
//判断最后一个数是否有重复
if(array[array.length-1]!=array[array.length-2]){
temp[k]=array[array.length-1];
k++;
}
//判断第二个到倒数第二个数是否有重复
for(int i=1;i<array.length-1;i++){
if ((array[i]!=array[i-1])&&(array[i]!=array[i+1])) {
temp[k]=array[i];
k++;
}
}
num1[0]=temp[0];
num2[0]=temp[1];
System.out.println(num1[0]+" "+num2[0]);
}
} public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
HashSet<Integer> s = new HashSet<>();
for(int var:array){
if(s.contains(var)) s.remove(var);
else s.add(var);
}
Iterator it = s.iterator();
num1[0] = (int)it.next();
num2[0] = (int)it.next();
}
} 思路二、利用异或运算很厉害!!!!具体操作流程:
因为如果a==b a^b = 0 0^c = c
异或是同0异1!!!
因此其余数据都是重复的,我们从头到尾异或,最后的结果就是这两个不同的数据的异或结果。
然后我们再找出异或结果中的1(代表两个数据在这个位上不同,也就是一个是1一个是0)那么接着我们再按照这个将数据分为两组,一组是在该位是1一组是在该位是0,那么在进行一次全体异或,就可以得出两个数据了!!!!!!!!!!
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int result=0;
for(int var:array) result^=var;
int flag = 1;
//从右往左找到第一个1,也就是两个位数不同的位
while((result&flag)==0) flag<<=1;
for(int var:array) {
if((var&flag)==0) num1[0]^=var;
else num2[0]^=var;
}
} import java.util.*;
//num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
/**
*
* 对于题目中说除了两个单个数字外,其他的都出现偶数次。我们需要从这句话入手,寻求更优的解决思路。
*
* 我们知道,位运算中异或的性质是:两个相同数字异或=0,不相同的话肯定不为0,一个数和0异或还是它本身。
*
* 这个题目的突破口在哪里?题目为什么要强调有一个数字出现一次,其他的出现两次?我们想到了异或运算的性质:
* 任何一个数字异或它自己都等于0 。也就是说,如果我们从头到尾依次异或数组中的每一个数字,
* 那么最终的结果刚好是那个只出现一次的数字,因为那些出现两次的数字全部在异或中抵消掉了(异或运算的交换律,可以参考博客:
* https://blog.csdn.net/luzhensmart/article/details/107586619)。
*
* 有了上面简单问题的解决方案之后,我们回到原始的问题。如果能够把原数组分为两个子数组。
* 在每个子数组中,包含一个只出现一次的数字,而其它数字都出现两次。如果能够这样拆分原数组,
* 按照前面的办法就是分别求出这两个只出现一次的数字了。
*
* 我们还是从头到尾依次异或数组中的每一个数字,那么最终得到的结果就是两个只出现一次的数字的异或结果。
* 因为其它数字都出现了两次,在异或中全部抵消掉了。由于这两个数字肯定不一样,那么这个异或结果肯定不为0 ,
* 也就是说在这个结果数字的二进制表示中至少就有一位为1 。
*
* 我们在结果数字中找到第一个为1 的位的位置,记为第N 位。现在我们以第N 位是不是1 为标准把原数组中的数字分成两个子数组,
* 第一个子数组中每个数字的第N 位都为1 ,而第二个子数组的每个数字的第N 位都为0 。
*
* 现在我们已经把原数组分成了两个子数组,每个子数组都包含一个只出现一次的数字,而其它数字都出现了两次。
* 因此到此为止,所有的问题我们都已经解决。
*/
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if(array == null ||array.length <= 1){
num1[0] = 0;
num2[0] = 0;
return;
}
//异或运算结果
int xorResult = 0;
for(int i=0;i<array.length;i++){
xorResult ^= array[i];
}
/**
* int 4字节 32bit 最高位为正负数代表 计算二进制结果xorResult从左到右的顺序 第一个位置为1的位置
* 从左开始找到这个异或结果第一个为1的索引
*/
int index = 0;
while((xorResult&1)==0 && index < 32){
xorResult = xorResult >> 1;
index++;
}
//以这个索引处是否为1作为判定标准,就将两个不同的数分离开了
//下面就是分两批不停地疑惑,就会得到这两个不同的数
for(int j=0;j<array.length;j++){
//这样就可以分别找到index处为1的独特解以及为0的独特解
if(targetIndexIs1(array[j],index)){
num1[0] ^= array[j];
}else{
num2[0] ^= array[j];
}
}
}
/**
* 判断num的index(从左往右看)是否为1
*/
public boolean targetIndexIs1(int target,int index){
target = target >> index;
if((target&1) == 1){
return true;
}else{
return false;
}
}
} import java.util.HashMap;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
if( array == null || array.length <=1) return;
HashMap<Integer, Integer> map = new HashMap<>();
for(int i=0; i< array.length ; i++){
if(map.containsKey(array[i])){
map.put(array[i], 1);
}else{
map.put(array[i], null);
}
}
boolean flag = true;
for(Integer key : map.keySet()){
if(map.get(key) == null){
if(flag){
num1[0]= key;
flag = false;
}else{
num2[0]= key;
}
}
}
}
}
/num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
int ret = 0;
for (int i : array) {
ret ^= i;
}
//取出某一位上不同
num1[0] = 0;
num2[0] = 0;
ret &= (-ret);
for (int i : array) {
if ((ret & i) == 0) {
num1[0] ^= i;
} else {
num2[0] ^= i;
}
}
}
} //num1,num2分别为长度为1的数组。传出参数
//将num1[0],num2[0]设置为返回结果
import java.util.Arrays;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
Arrays.sort(array);//先对数组排序
if(array[0]!=array[1]) {//对第一个数单独判断
num1[0] = array[0];
for (int i = 1; i < array.length-1; i++) {
//因为要判断当前索引是否和前后数字相等,所以 i < array.length-1
if(array[i]!=array[i-1] && array[i]!=array[i+1]) {
num2[0] = array[i];
}
}
}else {//else后表示第一个数是重复的,继续寻找
int index = 0;
for (int i = 1; i < array.length-1; i++) {
if(array[i]!=array[i-1] && array[i]!=array[i+1]) {
num1[0] = array[i];
index = i;//记录第一次的找到的索引,然后break
break;
}
}
for (int i = index+1; i < array.length-1; i++) {
if(array[i]!=array[i-1] && array[i]!=array[i+1]) {
num2[0] = array[i];
}
}
//循环条件 i < array.length-1,因此不会遍历到最后一个数
//如果循环完没有找到第2个数,那么最后一个数就是第二个数,单独判断一下。
if(array[array.length-2]!=array[array.length-1])
num2[0] = array[array.length-1];
}
}
} //暴力解法:直接将数字排序,相同的两个数必然相邻,遍历时跨度为2,遇到相邻两数不一致时,取出该数,跨度为1继续遍历
import java.util.*;
public class Solution {
public void FindNumsAppearOnce(int [] array,int num1[] , int num2[]) {
Arrays.sort(array);
int j = 0;
int[] arr = new int[2];
for(int i=0;i<array.length-1;i+=2){
if(array[i]!=array[i+1]){
arr[j++]=array[i];
i--;
if(j==2) break;
}
}
//如果第二个数在最后面,则上述的遍历将会跳过这个数
if(array[array.length-1]!=array[array.length-2]){
arr[1]=array[array.length-1];
}
num1[0] = arr[0];
num2[0] = arr[1];
}
}
class Solution { public: void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) { if(data.size()<2) return ; int size=data.size(); int temp=data[0]; for(int i=1;i<size;i++) temp=temp^data[i]; if(temp==0) return ; int index=0; while((temp&1)==0){ temp=temp>>1; ++index; } *num1=*num2=0; for(int i=0;i<size;i++) { if(IsBit(data[i],index)) *num1^=data[i]; else *num2^=data[i]; } } bool IsBit(int num,int index) { num=num>>index; return (num&1); } };可以用位运算实现,如果将所有所有数字相异或,则最后的结果肯定是那两个只出现一次的数字异或的结果,所以根据异或的结果1所在的最低位,把数字分成两半,每一半里都还有只出现一次的数据和成对出现的数据
这样继续对每一半相异或则可以分别求出两个只出现一次的数字