题目描述1:数组中只出现一次的数字
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。空间复杂度O(1)时间复杂度O(n)。
思路: 一个整型数组只有一个数字出现一次 其他出现2次 考虑异或全部得到唯一的这个数字。
同理,将问题分组成2组,每组保证有一个出现1次的数,且每组中其他数都出现2次。
考虑通过数某一位是否为1的特征进行分组。
思路: 一个整型数组只有一个数字出现一次 其他出现2次 考虑异或全部得到唯一的这个数字。
同理,将问题分组成2组,每组保证有一个出现1次的数,且每组中其他数都出现2次。
考虑通过数某一位是否为1的特征进行分组。
class Solution { public: bool FindBit1(int num,int pos){ num=num>>pos; return (num&1); } void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) { if(data.empty()) return; //数组内异或 获得异或结果seed 其二进制表示一定含有不只1个1 int seed = 0; for(int i=0;i<data.size();i++){ seed ^= data[i]; } //找到seed二进制中1的位置(从右到左移动次数) int FindIndexOf1 = 0; while(FindIndexOf1<8*sizeof(int)&&((seed&1)==0)){ seed = seed>>1; FindIndexOf1++; //记录移动次数 } //分成两组,分别异或 *num1=0,*num2=0; for(int i=0;i<data.size();i++) { if(FindBit1(data[i],FindIndexOf1)) *num1 ^= data[i]; else *num2 ^= data[i]; } } };
题目描述2:数组中唯一只出现一次的数字
题目:在一个数组中除了一个数字只出现一次之外,其他数字都出现了三次。请 找出那个吃出现一次的数字。
思路:出现3次的多个数和唯一出现1次的数 他们的二进制位对应相加的数被3整除 则目标数该位是0否则是1
// 面试题56(二):数组中唯一只出现一次的数字 // 题目:在一个数组中除了一个数字只出现一次之外,其他数字都出现了三次。请 // 找出那个吃出现一次的数字。 #include <cstdio> #include <exception> #include<stdexcept> #include<iostream> #include<string.h> //思路:出现3次的多个数和唯一出现1次的数 他们的二进制位对应相加的数被3整除 则目标数该位是0否则是1 int FindNumberAppearingOnce(int numbers[], int length) { std::logic_error error("Invalid"); if(!numbers||length<=0) throw std::exception(error); int bitSum[32]={0}; //遍历整型数组 对二进制的每一位进行计算 累计数组中每个数在32位二进制中当前位的和 for(int i=0;i<length;i++){ int bitMask = 1; //32位二进制 每一位求值累加 for(int j =31;j>=0;j--){ int bit = numbers[i]&bitMask; if(bit!=0) bitSum[j] += 1; //bit可能是大于0的任何数 bitMask = bitMask<<1; } } //计算32位数组中每一位是否能被3整除 int result = 0; for(int j=0;j<32;j++){ result = result<<1; //在遇到第一个被3整除的非零数时先移位一次 保证有效移位数比总位数少1 result += bitSum[j]%3; } return result; }