数组中唯一只出现一次的数字
Posted 穿过雾的阴霾
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数组中唯一只出现一次的数字相关的知识,希望对你有一定的参考价值。
思路
如果一个数字出现 3 次,那么它的二进制表示的每一位也出现三次,如果把所有出现三次的数字的二进制表示的每一位都分别加起来,那么每一位的和都能被 3 整除
cnt[32]
数组存储每一位 1 出现的次数- 遍历数组中所有数,将其二进制表示记录在
cnt
数组里 - 遍历
cnt
数组,根据cnt[i]
能否被 3 整除,推断出答案的二进制的第 i 位是 0 还是 1
复杂度分析
时间复杂度 O(32n)
,空间复杂度用到了长度为 32 的辅助数组,O(1)
代码
class Solution
public:
int findNumberAppearingOnce(vector<int>& nums)
int cnt[35];//cnt[i]记录二进制第i位1的个数
memset(cnt,0,sizeof cnt);
for(auto num:nums)
for (int i = 0; i < 32; i ++ )
if(num>>i&1) cnt[i]++;
int res=0;
for (int i = 0; i < 32; i ++ )
if(cnt[i]%3)//res二进制第i位为1
res+=1<<i;
return res;
;
《剑指Offer——数组中只出现一次的两个数字,数组中唯一只出现一次的数字》代码
数组中只出现一次的两个数字,数组中唯一只出现一次的数字
前言
//============================================================================
// 《剑指Offer——数组中只出现一次的两个数字,数组中唯一只出现一次的数字》代码
//============================================================================
// 题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序
// 找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
//============================================================================
// 题目:在一个数组中除了一个数字只出现一次之外,其他数字都出现了三次。请
// 找出那个吃出现一次的数字。
//============================================================================
一、示例
1.数组中只出现一次的两个数字,
/*========================================================
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。
请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
=======================================================*/
2.数组中唯一只出现一次的数字
/*=====================================================
在一个数组 nums 中除一个数字只出现一次之外,
其他数字都出现了三次。请找出那个只出现一次的数字。
示例 1:
输入:nums = [3,4,3,3]
输出:4
示例 2:
输入:nums = [9,1,7,9,7,9,7]
输出:1
======================================================*/
二、代码解析
1.新建.cpp文件
代码如下(示例):
//============================================================================
// 《剑指Offer——数组中只出现一次的两个数字,数组中唯一只出现一次的数字》代码
//============================================================================
// 题目:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序
// 找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
//============================================================================
// 题目:在一个数组中除了一个数字只出现一次之外,其他数字都出现了三次。请
// 找出那个吃出现一次的数字。
//============================================================================
#include <iostream>
#include<vector>
#include<unordered_map>
using namespace std;
/*========================================================
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。
请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
=======================================================*/
/*法一-----哈希表*/
vector<int> singleNumbers(vector<int>& nums)
{
vector<int> result;
unordered_map<int, int> map;
for (int num : nums)
{
map[num]++;
}
for (auto item : map)
{
if (item.second == 1)
{
result.push_back(item.first);
}
}
return result;
}
/*法二-----异或运算*/
// 找到num从右边数起第一个是1的位
unsigned int FindFirstBitIs1(int num)
{
int indexBit = 0;
while (((num & 1) == 0) && (indexBit < 8 * sizeof(int)))
{
num = num >> 1;
++indexBit;
}
return indexBit;
}
// 判断数字num的第indexBit位是不是1
bool IsBit1(int num, unsigned int indexBit)
{
num = num >> indexBit;
return (num & 1);
}
void FindNumsAppearOnce(int data[], int length, int* num1, int* num2)
{
if (data == nullptr || length < 2)
return;
int resultExclusiveOR = 0;
for (int i = 0; i < length; ++i)
resultExclusiveOR ^= data[i];
unsigned int indexOf1 = FindFirstBitIs1(resultExclusiveOR);
*num1 = *num2 = 0;
for (int j = 0; j < length; ++j)
{
if (IsBit1(data[j], indexOf1))
*num1 ^= data[j];
else
*num2 ^= data[j];
}
}
/*=====================================================
在一个数组 nums 中除一个数字只出现一次之外,
其他数字都出现了三次。请找出那个只出现一次的数字。
示例 1:
输入:nums = [3,4,3,3]
输出:4
示例 2:
输入:nums = [9,1,7,9,7,9,7]
输出:1
======================================================*/
/*法一---嘻哈表*/
int singleNumber(vector<int>& nums)
{
unordered_map<int, int> map;
for (int num : nums)
{
map[num]++;
}
for (auto item : map)
{
if (item.second == 1)
{
return item.first;
}
}
return 0;
}
/*法二--位运算*/
int FindNumberAppearingOnce(vector<int>& nums)
{
if (nums.empty())
{
return 0;
}
int bitSum[32] = { 0 };
for (int i = 0; i < nums.size(); ++i)
{ //3,4,3,3
long bitMask = 1;
for (int j = 31; j >= 0; --j)
{
int bit = nums[i] & bitMask; //bit=1
if (bit != 0)
{
bitSum[j] += 1; //bitSum[31]=1,
}
bitMask = bitMask << 1; //bitMask=2
}
}
int result = 0;
for (int i = 0; i < 32; ++i)
{
result <<= 1;
result += bitSum[i] % 3;
}
return result;
}
int main()
{
vector<int> nums = { 1,1,1,2,3,3,3 };
vector<int> nums1 = { 1,1,2,5,3,3 };
int data[] = { 1,1,2,5,3,3 };
cout << "数组中只出现一次的两个数字" << endl;
vector<int> result = singleNumbers(nums1);
int value1, value2;
FindNumsAppearOnce(data,6,&value1,&value2);
cout << "法一--->嘻哈表--->" << result[0] << " " << result[1] << endl;
cout << "法二--->异或运算--->" << value1 << " " << value2 << endl;
cout << "数组中唯一只出现一次的数字" << endl;
cout << "法一--->嘻哈表--->" << singleNumber(nums) << endl;
cout << "法二--->位运算--->" << FindNumberAppearingOnce(nums) << endl;
return 0;
}
三,测试
以上是关于数组中唯一只出现一次的数字的主要内容,如果未能解决你的问题,请参考以下文章
《剑指offer》第五十六题II:数组中唯一只出现一次的数字