LeetCode每日一题——撞色搭配

撞色搭配OJ链接:LCR 177. 撞色搭配 - 力扣(LeetCode)

题目:

思路: 

这跟找单身狗的题目很相似,但是本题的条件会更苛刻点,有时间复杂度和空间复杂度的要求。那么我们就不能通过排序+双指针的方法进行查找。而是通过我们的操作符中的位操作符和移位操作符进行查找。

首先我们要知道什么是位操作符和移位操作符:

位操作符和移位操作符有:

位操作符
&  //按位与
|  //按位或
^  //按位异或
~  //按位取反

移位操作符
<< //左移操作符
>> //右移操作符

注:他们的操作数必须是整数。

本题我们需要用到的位操作符只有&和^所以我只介绍这两个,其它的位操作符大家有兴趣的可以自行去了解。

1.&(按位与)

特点 :对应比特位均为1结果才为1。

例如:

int a=2;int b=5;求a&b的值。

操作符都是按位进行计算的,所以我们需要将其转化位二进制数字。

a=2的二进制为0010

b=5的二进制位0101

a&b=0000(二进制)=0(十进制)

2.^(按位异或)

特点:相同为0,相异为1;

例如:

int a=2;int b=5;求a^b的值。

a=2的二进制为0010

b=5的二进制位0101

a^b=1111(二进制)=15(十进制)

3.<<(左移操作符)

特点:左边抛弃,右边补0

例如:

int a=2;int b=a<<1;

a=2的二进制为0010

a<<1=0100(二进制)=4(十进制)

4.>>(右移操作符)

特点:分两种:

1. 逻辑右移:左边用0填充,右边丢弃
2. 算术右移:左边用原该值的符号位填充,右边丢弃

例如:

int a=2;int b=a>>1;

a=2的二进制为0010

a>>1=0001(二进制)=1(十进制)

知道了操作符如何使用那么我们就可以开始分析题目了。

大致思路:通过0对自身依次异或,将两个单独的数的异或后的结果找出,再通过结果将两个单独数分离开来得到两组数,再通过0对自身依次异或,最后得到的两个结果就是我们需要的数

例如 1 1 2 2 3 4

1.通过0对自身依次异或,得到的就是两个单独数异或的结果,即 1^1^2^2^3^4 = 3^4 = 7 = 0111

2.找到异或后结果的二进制序列,找出为1的位数(如果为1,则说明两个单独数在这个位不相同,可凭此将两个数分离),我们可以发现在第二位和第三都是1,其实取哪一位都可以,目的是分离这两个数,这里我们取第二位

3.找到位数后,将按其他数的这个位数是否为1,还是为0分离,这就形成了两组数,各带一个单独数。
分离的两组数为 1 1 4和2 2 3

4.对这两组数通过0对自身依次异或,就可以得到我们需要的两个数。

代码实现:
int* sockCollocation(int* sockets, int socketsSize, int* returnSize) 
{
    int*ret=(int*)malloc(sizeof(int)*2);//开辟存放不同颜色袜子的编号的数组
    ret[0]=0;//初始化变量
    ret[1]=0;
    int temp=0;
    for(int i=0;i<socketsSize;i++)//求出两个不同颜色袜子的异或值
    {
        temp^=sockets[i];
    }
    int k=1;
    int count=0;
    while((temp&k)==0)//算出二进制哪一位开始是不同的(k左移或者temp右移)
    {
        temp>>=1;
        count++;//计算移动次数
    }
    for(int i=0;i<socketsSize;i++)
    {
        if((sockets[i]>>count)&1==1)
        {
            ret[0]^=sockets[i];
        }
        else
        {
            ret[1]^=sockets[i];
        }
    }
    *returnSize=2;
    return ret;
}

运行结果:

 

PS:看到这里了,码字不易,给个一键三连鼓励一下吧!有不足或者错误之处欢迎在评论区指出! 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值