剑指56:数组中只出现一次的数字——异或——位运算

  • 2022-07-15 12:13:21

题目描述1:数组中只出现一次的数字

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。空间复杂度O(1)时间复杂度O(n)。

思路: 一个整型数组只有一个数字出现一次 其他出现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;
} 


猜你喜欢