整数数组 sockets
记录了一个袜子礼盒的颜色分布情况,其中 sockets[i]
表示该袜子的颜色编号。礼盒中除了一款撞色搭配的袜子,每种颜色的袜子均有两只。请设计一个程序,在时间复杂度 O(n),空间复杂度O(1) 内找到这双撞色搭配袜子的两个颜色编号。
示例 1:
输入:sockets = [4, 5, 2, 4, 6, 6]
输出:[2,5] 或 [5,2]
LCR 177. 撞色搭配 - 力扣(LeetCode)
空间复杂度O(1),不能再用哈希表了,时间复杂度O(n),要求一次遍历就把这对找出来。
先来看这么一个题目:
给你一个 非空 整数数组 nums
,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
java
class Solution {
public int singleNumber(int[] nums) {
int result = 0;
for(int i = 0; i < nums.length; i++){
result = result ^ nums[i];
}
return result;
}
}
我们发现用位运算可以很好地解决这类题目
我们再来看这个题目,肯定还是用位运算,只不过当所有的数两两抵消之后,我们会留下这一对数。如何把这一对数提取出来放进数组呢。

java
class Solution {
public int[] sockCollocation(int[] sockets) {
int x = 0, y = 0, n = 0, m = 1;
for(int num : sockets) // 1. 遍历异或
n ^= num;
while((n & m) == 0) // 2. 循环左移,计算 m
m <<= 1;
for(int num: sockets) { // 3. 遍历 sockets 分组
if((num & m) != 0) x ^= num; // 4. 当 num & m != 0
else y ^= num; // 4. 当 num & m == 0
}
return new int[] {x, y}; // 5. 返回出现一次的数字
}
}
思路就是,先找到一个异或运算,然后这两个异或运算的结果中的二进制,如果有一个位为1,那么这两个数的这一位肯定不相同。一个为1,一个为0,那么我们就拿这个位去遍历数组,数组中这个元素等于1就跟x走,等于0就跟y走,最后返回即可。
拓展:
教学过程中,教练示范一次,学员跟做三次。该过程被混乱剪辑后,记录于数组 actions
,其中 actions[i]
表示做出该动作的人员编号。请返回教练的编号。
示例 1:
输入:actions = [5, 7, 5, 5]
输出:7
示例 2:
输入:actions = [12, 1, 6, 12, 6, 12, 6]
输出:1
提示:
1 <= actions.length <= 10000
1 <= actions[i] < 2^31
LCR 178. 训练计划 VI - 力扣(LeetCode)

java
class Solution {
public int trainingPlan(int[] actions) {
int[] counts = new int[32];
for(int action : actions) {
for(int i = 0; i < 32; i++) {
counts[i] += action & 1; // 更新第 i 位 1 的个数之和
action >>= 1; // 第 i 位 --> 第 i 位
}
}
int res = 0, m = 3;
for(int i = 31; i >= 0; i--) {
res <<= 1;
res |= counts[i] % m; // 恢复第 i 位
}
return res;
}
}
第三题太恶心了,想不出来,留个参考吧。