【力扣刷题实战】只出现一次的数字III
大家好,我是小卡皮巴拉
文章目录
目录
力扣题目:只出现一次的数字III
题目描述
解题思路
问题理解
算法选择
具体思路
解题要点
完整代码(C++)
兄弟们共勉 !!!
每篇前言
博客主页:小卡皮巴拉
咱的口号:🌹小比特,大梦想🌹
作者请求:由于博主水平有限,难免会有错误和不准之处,我也非常渴望知道这些错误,恳请大佬们批评斧正。
力扣题目:只出现一次的数字III
原题链接:260. 只出现一次的数字 III - 力扣(LeetCode)
题目描述
给你一个整数数组 nums
,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。
你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。
示例 1:
输入:nums = [1,2,1,3,2,5] 输出:[3,5] 解释:[5, 3] 也是有效的答案。
示例 2:
输入:nums = [-1,0] 输出:[-1,0]
示例 3:
输入:nums = [0,1] 输出:[1,0]
解题思路
问题理解
本题要求在给定的整数数组 nums
中找出恰好只出现一次的两个元素,数组里其余元素都出现两次。需要设计一个时间复杂度为线性(O(n))且仅使用常量额外空间(O(1))的算法来解决此问题,最后按任意顺序返回这两个只出现一次的元素。
算法选择
采用位运算的方法。位运算的异或操作能高效地处理元素出现次数的问题,结合异或操作的特性和对结果的进一步处理,可以找出只出现一次的两个元素。
具体思路
-
计算所有元素的异或结果:
-
初始化一个变量
xor_all
为 0。 -
遍历数组
nums
,将每个元素e
与xor_all
进行异或操作,即xor_all ^= e
。由于相同元素异或结果为 0,所以最终xor_all
的值是那两个只出现一次的元素的异或结果。
-
-
找出异或结果中某一位为 1 的位:
-
通过
unsigned int diff_bit = static_cast<unsigned int>(xor_all) & static_cast<unsigned int>(-static_cast<unsigned int>(xor_all));
找出xor_all
中最右边为 1 的位。这一位为 1 意味着那两个只出现一次的元素在该位上不同。
-
-
根据该位将数组元素分组并分别异或:
-
初始化两个变量
num1
和num2
为 0。 -
再次遍历数组
nums
,对于每个元素e
,检查其在diff_bit
位上的值:-
如果
e & static_cast<int>(diff_bit)
为真,说明e
在该位上为 1,将其与num1
进行异或操作,即num1 ^= e
。 -
否则,说明
e
在该位上为 0,将其与num2
进行异或操作,即num2 ^= e
。
-
-
这样分组后,相同的元素会被分到同一组,经过异或操作后会相互抵消,最终
num1
和num2
分别是那两个只出现一次的元素。
-
-
返回结果:
-
返回包含
num1
和num2
的向量{num1, num2}
。
-
解题要点
-
异或操作的特性运用:利用异或操作
a ^ a = 0
和a ^ 0 = a
的特性,通过对所有元素异或得到两个只出现一次元素的异或结果。 -
找出不同位:通过
xor_all
与-xor_all
进行按位与操作,找出两个只出现一次元素不同的某一位,以此作为分组的依据。 -
分组异或:根据找出的不同位将数组元素分组并分别异或,最终得到两个只出现一次的元素。
完整代码(C++)
class Solution {
public:
std::vector<int> singleNumber(std::vector<int>& nums)
{
int xor_all = 0;
// 遍历数组,将所有元素进行异或操作,得到两个只出现一次元素的异或结果
for(auto e : nums)
{
xor_all ^= e;
}
// 找出 xor_all 中最右边为 1 的位,该位表明两个只出现一次的元素在该位不同
unsigned int diff_bit = static_cast<unsigned int>(xor_all) &
static_cast<unsigned int>(-static_cast<unsigned int>(xor_all));
int num1 = 0, num2 = 0;
// 根据 diff_bit 位将数组元素分组并分别异或
for(auto e : nums)
{
if(e & static_cast<int>(diff_bit)) num1 ^= e;
else num2 ^= e;
}
return {num1, num2};
}
};
兄弟们共勉 !!!
码字不易,求个三连
抱拳了兄弟们!