又是一道single number题目,这类题目一般都是依赖位操作,先给出题目:

Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.

Example:

Input:  [1,2,1,3,2,5]
Output: [3,5]
Note:

The order of the result is not important. So in the above example, [5, 3] is also correct.
Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?

这题已经说了,必须是线性的时间复杂度,也就是时间复杂度是O(N),同时空间复杂度被限制为了O(1),也就是hashmap之类的就不能用了,假如用map这种东西,这种题目就没什么意思了。

做过single number这题的人应该知道,那题比较简单,所有数字都是两两出现的,除了一个。由于异或操作满足交换律,所以两个相同数字的异或结果是0,而0与任何数字异或的结果都是那个数字本身,所以最后就剩下那个孤零零的数字了。

这题在single number的基础上增加了复杂度,有2个数字单独出现了,所以全部异或的操作肯定不能使用。假如我们全部异或了,我们得到的结果是那两个孤零零数字异或的结果,好像对这题没啥用。但是仔细想想呢,有了两个数字单独异或的结果,我们至少可以知道,这个结果肯定在某个比特位上不为0,我们以这个比特位为1,其余为0产生一个mask,用这个mask可以知道数字上这个位是否为0。

有这个mask有什么用呢?我们可以知道,假如我们把这个mask和当前数组里所有数字进行异或处理,那么肯定可以分为2组,1组包含某个单独的数字1,另一组包含单独的数字2。有这个就好办了,因为其与在别分割为组的数字们,他们肯定都是和另一个和它相同的数字成对出现的,它的某一位与mask的与结果,肯定和和它相同的数字相同。

所以这个题目又转为了single number这题了,该怎么解不用解释了吧。下面贴一个解法:

vector<int> singleNumber(vector<int>& nums) {
    int xorn = 0;
    for (auto v : nums) {
        xorn ^= v;
    }
    int flag = xorn ^ (xorn & (xorn - 1));
    vector<int> res(2, 0);
    for (auto v : nums) {
        if ((flag & v) == 0) {
            res[0] ^= v;
        } else {
            res[1] ^= v;
        }
    }
    return res;
}
共 0 条回复
暂时没有人回复哦,赶紧抢沙发
发表新回复

作者

sryan
today is a good day