只出现一次的数字 1,2,3

之前做过好多遍只出现一次的数字,当时学到了通过位运算解决
今天又看到一个 求两个单独的数字,也是通过位运算做到的,太狠了,这些大佬们

思考:
1.比如一组数 只有一个单独存在的数,其他都是两个,那么通过异或运算,剩下的就是这个数
2.现在又来一组数,有两个单独的数字,那么通过异或运算之后的结果,就是这两个数的异或结果
举个例子 一组数 1,2,1,3,2,5 单独的数是3和5
二进制分别是 11,101 他们 异或之后是110 也就是6
这时候看异或后的结果110 1的位置便是他们不相同的位数。
那么 通过这个原则,即可把完整的数组 分为两种情况,分别在两种情况中异或,
剩下的两个数就是要求的结果

赶快去LeetCode找到这个题 260题
本来想用C提交,但是传递三个参数,不太理解第三个参数干嘛的,便用java交了

int* singleNumber(int* nums, int numsSize, int* returnSize){

}
class Solution {
    public int[] singleNumber(int[] nums) {
        int [] res =new int [2];
        int sum=0;
        int q=1;
        for(int i=0;i<nums.length;i++)sum^=nums[i];
        while((q&sum)==0)q<<=1;
        for(int i=0;i<nums.length;i++)
            if((nums[i]&q)!=0)res[0]^=nums[i];
            else res[1]^=nums[i];
        return res;
    }
}

写完之后看了下题解,哇,还有更巧妙的办法。。这里贴上官网的题解

class Solution {
  public int[] singleNumber(int[] nums) {
    int bitmask = 0;
    for (int num : nums) bitmask ^= num;
    int diff = bitmask & (-bitmask);
    int x = 0;
    for (int num : nums) if ((num & diff) != 0) x ^= num;
    return new int[]{x, bitmask^x};
  }
}

-bitmask=(~-bitmask+1);
x&-x 低位往高位走的第一个1

然后继续看LeetCode的137题

这个题是其中一个数出现一次,剩下的出现三次。求出出现一次的数
首先
第一种思路:把所有出现过的数放到一个set里面(可以排除相同的数)然后加起来乘以三
然后减去每一个数,那剩下的那个数再除以一个2,
但是。。。。 所有的数加起来int肯定是放不下的。至于long。算了 我们看下一个算法

第二种思路:位操作
假如例子是
1 2 6 1 1 2 2 3 3 3
1 -> 0 0 1
2 -> 0 1 0
6 -> 1 1 0
1 -> 0 0 1
1 -> 0 0 1
2 -> 0 1 0
2 -> 0 1 0
3 -> 0 1 1
3 -> 0 1 1
3 -> 0 1 1
看最右边的一列 1001100111 有 6 个 1
再往前看一列 0110011111 有 7 个 1
再往前看一列 0010000 有 1 个 1
我们只需要把是 3 的倍数的对应列写 0,不是 3 的倍数的对应列写 1
也就是 1 1 0,也就是 6。
这是因为 如果每一列出现三的倍数,那么,单独的那个数字转换二进制之后在这一列为0,也就是不存在,所以把这一列全部置0,同样 ,如果在之前不为0,就代表存在,置为1,然后输出即为最后正确答案

第三种思路
这种操作遇到原题还行,如果遇不到,我还是用上一种思路吧

class Solution {
    public int singleNumber(int[] nums) {
        int ones = 0, twos = 0;
        for(int num : nums){
            ones = ones ^ num & ~twos;
            twos = twos ^ num & ~ones;
        }
        return ones;
    }
}

这种思路有点不太理解,大体就是
比如状态转移 00》01》11》00
在第三次转移时候变回00
所以可以定义one two,three 三个变量通过位操作模拟,
但是three最后只保存一个状态,完全可以用前两个代替。

发布了11 篇原创文章 · 获赞 1 · 访问量 186

猜你喜欢

转载自blog.csdn.net/z591593455/article/details/104590528