撞色搭配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.>>(右移操作符)
特点:分两种:
例如:
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:看到这里了,码字不易,给个一键三连鼓励一下吧!有不足或者错误之处欢迎在评论区指出!