给出一个整型数组,其中除了两个数字只出现一次之外,其他的数字都出现了两次。请找出这两个只出现一次的数字。要求时间复杂度是 O(n) ,空间复杂度是 O(1) 。请简述思路。
public class yuhuo { public static void main(String[] args) { int[] a= {1,2,1,4,5,7,5,4};//手动定义数组 int[] b=soulution(a);//传回结果数组 for(int arr:b){ System.out.println(arr); } } public static int[] soulution (int[] a) { int m=0; for(int arr:a ) m^=arr;//求的所有数异或结果 int k=0;//记录最低位出现1的位置 while((m&1)==0){//利用若m最低位为1时,m&1=1,最低位为0时,m&1=0,来判定最低位的位置 m=m>>1 ; k++; } int[] b={0,0}; for(int arr:a){ if(((arr>>k)&1)==1)//异或计算求其中一个值 b[0]^=arr; else b[1]^=arr;//异或计算求其中另一个值 } return b; } }
/** 使用位运算 先将所有数字异或后的结果保存在X中,接下来找到X最低位(从右向左数第一个)的1,这里假设X最低位的1的位于第k位; 以第k位是否为1将所有数字分成两类,因为是二进制,所以第k位只有两种情况。由此,将所有数字分成了两类。可以确定(其实我也不懂为什么),两个出现一次的数字分别处于两类之中,也就是说,两个出现一次的数字不会全部属于同一类。 按照“一个只出现一次的数字(其余数字出现两次)”的思路将两类中的数字分别全部异或,分别得到两类中只出现一次的数字,就是结果。 **/ vector<int> getOnce(vector<int> arr){ vector<int> res; if(arr.size() == 0) return res; int num1, num2; num1 = num2 = 0; int xorAllRes = 0; for(auto iter = arr.begin(); iter != arr.end(); ++iter){ xorAllRes ^= *iter; } int k = 0; while((xorAllRes & 1) == 0) ++k; //找到抑或结果最低位的1的位置,记录为k for(auto iter = arr.begin(); iter != arr.end(); ++iter){ if(((*iter >> k) & 1) == 1){ //第k位为1,则为第"1"类,与num1异或 num1 ^= *iter; }else{ //否则,属于第二类,与num2异或 num2 ^= *iter; } } res.push_back(num1); res.push_back(num2); return res; }
class Solution { vector<int> onlyones(vector<int>nums) { int count = 0; int i = 0; int cur=nums[i]; vector<int>res; while (i<nums.size()) { if (nums[i] == cur) { count++; if (count == 2) { cur = nums[++i]; count = 1; } i++; } else { res.push_back(cur); cur = nums[i++]; count = 1; } } return res; } };