136.只出现一次的数字(简单)
题目
给你一个 非空 整数数组 nums
,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。
示例 1 :
输入:nums = [2,2,1] 输出:1
示例 2 :
输入:nums = [4,1,2,1,2] 输出:4
示例 3 :
输入:nums = [1] 输出:1
提示:
1 <= nums.length <= 3 * 104
-3 * 104 <= nums[i] <= 3 * 104
- 除了某个元素只出现一次以外,其余每个元素均出现两次。
分析
由于题目中明确表明,除了一个数字只出现了一次之外,其他数字都出现了两次,可以使用异或运算,每两个相同的数字异或后都变为零,只剩最后只出现一次的数字,与0异或后仍然为自己。
源代码
class Solution {
public:
int singleNumber(vector<int>& nums) {
int val=0;
for(auto e:nums)
{
val ^=e;
}
return val;
}
};
137.只出现一次的数字II(中等)
题目
给你一个整数数组 nums
,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。
示例 1:
输入:nums = [2,2,3,2] 输出:3
示例 2:
输入:nums = [0,1,0,1,0,1,99] 输出:99
提示:
1 <= nums.length <= 3 * 104
-231 <= nums[i] <= 231 - 1
nums
中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次
分析
以第一组为例:nums = [2,2,3,2],首先判断每一位是0还是1,采取与移位1进行与运算,将每一个数字的每一位出现了多少个1,加在一次,这时可能出现两种情况
只有三个相同的数字出现该位,则该位和为3N,该位也出现了那个特别的数字,则该位和为3N+1
0010
0010
0011
0010
---------------------
0041
然后对每一位进行余三操作,如果余数为1,则单独一个的数该位为1,否则该为为0,这个地方困扰我的问题是如何将这些余数变为一个数字,即如何在对应位置1,采取与1进行移位或运算
源代码
class Solution {
public:
int singleNumber(vector<int>& nums) {
int BitsArray[32]={0};
for(auto e:nums)
{
for(size_t i=0;i<32;i++)
{
if(e&(1<<i))
{
BitsArray[i]++;
}
}
}
int val=0;
for(size_t j=0;j<32;j++)
{
if(BitsArray[j]%3==1)
{
val|=(1<<j);
}
}
return val;
}
};
260.只出现一次的数字III(中等)
题目
给你一个整数数组 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]
提示:
2 <= nums.length <= 3 * 104
-231 <= nums[i] <= 231 - 1
- 除两个只出现一次的整数外,
nums
中的其他数字都出现两次
分析
可以先将他们全部异或,那么结果就是只出现一次的那两个数字的异或的结果,然后想办法将它们分开。
以这个举例:nums = [1,2,1,3,2,5],那么结果应该是3和5的异或
0011
0101
-------------
0110
由结果可知,哪一位为1,则说明该为这两个数字不一样,可用这个来区分它们,将这些数分为两组,例如,红色这位为1,则该位两个数字一个为1,一个为0,分为两组之后,就成了136的问题了,除了该数其他数都出现两次
例如该位为1的有:2 3 2
该位为0的有:1 5 1
源代码
class Solution {
public:
vector<int> singleNumber(vector<int>& nums) {
int val=0,j=0;
for(auto e:nums)
{
val^=e;
}
for(auto e:nums)
{
for(j=0;j<32;j++)
{
if(val&(1<<j))
{
break;
}
}
}
int num1=0,num2=0;
for(auto e:nums)
{
if(e&(1<<j))
{
num1^=e;
}
else
{
num2^=e;
}
}
vector<int> v;
v.push_back(num1);
v.push_back(num2);
return v;
}
};
小结
这次练习加深了我对位运算符的认识,当要从两两相同的数中找不同的那个可以用异或运算,如何定位某一位是0还是1也可以采用与1移位与的运算,将某一位置1或0可以采用与1移位或的运算。