难度: Medium
教学过程中,教练示范一次,学员跟做三次。该过程被混乱剪辑后,记录于数组 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
难度: Medium
教学过程中,教练示范一次,学员跟做三次。该过程被混乱剪辑后,记录于数组 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
运行时间: 240 ms
内存: 15.7 MB
class Solution: def trainingPlan(self, actions: List[int]) -> int: ones,twos = 0,0 for action in actions: ones = ones^action&~twos twos = twos^action&~ones return ones
题解利用位操作来统计每个人员编号出现的次数。通过两个变量`ones`和`twos`,分别记录每个位出现1次和2次的情况。代码通过遍历`actions`数组,对每一个元素进行位操作更新`ones`和`twos`。整体思路是使用位运算模拟三进制计数,其中`ones`表示出现一次,`twos`表示出现两次,最终任何出现三次的位会被重置为0。因此,只出现一次的教练编号将保留在`ones`中。
时间复杂度: O(n)
空间复杂度: O(1)
class Solution: def trainingPlan(self, actions: List[int]) -> int: ones, twos = 0, 0 # 初始化两个计数器,ones和twos for action in actions: ones = ones ^ action & ~twos # 更新ones,加入新的action,排除twos中已有的 twos = twos ^ action & ~ones # 更新twos,加入新的action,排除ones中更新后的 return ones # 返回只出现一次的教练编号
位操作在处理频率统计时提供了一种更为高效和节省空间的方式。在该题目中,每个人的编号可能重复出现多次,使用位操作可以有效地模拟三进制计数(出现1次、2次、重置为0)。通过位操作,我们可以仅使用固定的几个整数变量(在本题中是`ones`和`twos`)来记录状态,相比使用哈希表,这种方法大幅减少内存消耗,并可能在某些情况下提高计算速度。此外,位操作直接在底层操作二进制位,提高了处理效率。
在这种方法中,`ones`和`twos`变量用于跟踪每个数字出现的次数。具体来说,`ones`记录了某个数字出现一次的位,而`twos`记录了某个数字出现两次的位。逻辑如下: 1. 当一个新的数字出现时,我们首先检查它是否已经在`ones`中记录过(即之前出现过一次),如果是,我们将其加入到`twos`中(表示现在出现了两次)。 2. 如果一个数字已经在`twos`中(即之前出现过两次),那么再次出现将使该数字出现次数达到三次,根据题目要求,我们需要将其计数重置为0,即从`ones`和`twos`中移除。 3. 使用位操作,我们可以有效地同时更新`ones`和`twos`,确保每个数字的出现次数能够准确计数。当循环结束后,`ones`中存储的即为只出现一次的教练编号。
`~twos`是对`twos`变量进行位取反操作,这意味着它将`twos`中所有的1变为0,所有的0变为1。在表达式`ones = ones ^ action & ~twos`中,`~twos`起到了一个过滤器的作用,确保只有当某个数字没有在`twos`中记录(即没有出现过两次)时,这个数字才会被考虑加入到`ones`中。这是为了保证当一个数字出现第三次时,它能够从`ones`和`twos`中正确地被清除,避免错误地统计出现次数。