题目:
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字,要求:时间复杂度为O(n),空间复杂度O(1)
测试样例:
输入:
8
{2,4,3,6,3,2,5,5}
输出:
4,6
解法:
使用异或解决问题:一个数异或自己等于0,异或其他数 != 0,如果是一个数字,那么一趟遍历数组异或之后的结果就是我们要的;而现在是2个数据,那么我们需要仔细考虑怎样将两个数字分开:
首先:将所有的数进行异或,得到一个结果不等于0的数字,因此这个结果数字在二进制位上必定最少有一位为1(因为那2个数不一样),我们从该结果的右边开始选择一个为1的位,记为第n位(这一位为1,那么就意味着第一个数的此位置上为1 ,第二个数此位置上肯定为0,或者反之,不然不可能异或 != 0);那么根据这一位的特性,将数组元素分成两个子数组,第一个子数组的每个数字的第n位为1,而第二个子数组中每个数字的第n位都是0;由于我们分组的标准是数字中的某一位是0还是1,那么出现了两次的数字肯定被分到了同一个数组;然后分别对这两部分进行再次异或得到两个数;
代码实现
//查找整数number最右边是1的位 int findFistBitIs1(int number) { int index = 0; while (((index & 1) == 0) && index <= sizeof(int) * 8) { number >>= 1; ++ index; } return index; } //测试number的从右边数第indexBit位是否为1 int isBit1OnIndex(int number, int indexBit) { int testNumber = 1 << indexBit; return (number & testNumber); } int main() { freopen("input.txt","r",stdin); int n; cin >> n; int *array = new int[n]; for (int i = 0; i < n; ++i) { cin >> array[i]; } int testNumber = 0; for (int i = 0; i < n; ++i) { testNumber ^= array[i]; } int indexOf1 = findFistBitIs1(testNumber); int ans1,ans2; ans1 = ans2 = 0; for (int i = 0; i < n; ++i) { if (isBit1OnIndex(array[i],indexOf1)) { ans1 ^= array[i]; } else { ans2 ^= array[i]; } } cout << ans1 << " " << ans2 << endl; delete []array; }
时间: 2024-10-04 23:04:20