【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)
136. Single Number
Given a non-empty array of integers, every element appears twice except for one. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
Example 1:
Input: [2,2,1]
Output: 1
Example 2:
Input: [4,1,2,1,2]
Output: 4
//问题:某个数出现一次,其他数出现两次,找出这个数(要求O(n),O(1))
/*方法一:异或,一个数异或同一个数两次,还是那个数
a^0=a,a^a =0
分析:O(n), O(1)(若用哈希表,空间复杂度为O(n))
*/
class Solution
{
public:
int singleNumber(vector<int>& nums)
{
int result = 0;
for(int a:nums)
{
result ^= a;
}
return result;
}
};
//方法二:利用哈希表构建map,统计各数出现的次数,如果次数为2去掉该key,最后只剩下为单数的key
//分析:O(n), O(n) (时间效率也差于前一个)
#include <unordered_map>
class Solution
{
public:
int singleNumber(vector<int>& nums)
{
unordered_map<int,int> dict;
for(int num:nums)//统计元素出现的次数
{
if(++dict[num] == 2) dict.erase(num); //如果出现过,则去除
}
return dict.begin()->first; //返回单数的key
}
};
137. Single Number II
Given a non-empty array of integers, every element appears three times except for one, which appears exactly once. Find that single one.
Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
Example 1:
Input: [2,2,3,2]
Output: 3
Example 2:
Input: [0,1,0,1,0,1,99]
Output: 99
//问题:某个数出现一次,其他数出现三次,找出这个数(要求O(n),O(1))(具有一般性,某个数出现一次,其他数出现基5次、7次...均可以用这种方法)
//方法:用一个32位大小的数组存储所有数各个比特位的和(不进行进位),
//如果每位的和对3取余就能得到那个只出现一次的数在该位上的数字
//O(n),O(1)(由于为常数大小空间32,故可以看做O(1),若用哈希表则为O(n))
class Solution
{
public:
int singleNumber(vector<int>& nums)
{
int bitSum[32] = {0}; //比特位累加和统计表
for(int i = 0; i<nums.size(); i++) //遍历数组
{
int bitMask = 1;
for(int j = 0; j<=31; j++)
{
if((nums[i] & bitMask) != 0) bitSum[j] += 1; //若第j位为1则进行累加
bitMask <<= 1; //产生下一位的mask(注意这里的<<=运算符)
}
}
int result = 0;
for(int j = 31; j >= 0; j--) //从高位往低位开始扫描
{
result <<= 1;
result += bitSum[j]%3;
}
return result;
}
};
260. Single Number III
Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.
Example:
Input: [1,2,1,3,2,5]
Output: [3,5]
Note:
-
The order of the result is not important. So in the above example, [5, 3] is also correct.
-
Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?
/*
问题:有两个数出现一次,其他数出现两次,找出这两个数(要求O(n),O(1))
方法:
(1)所有数异或,相同数异或得0,所以最后结果相当于对这两个数异或,由于不相同,必有某一比特位为1
(2)按此位是否为1将数组分为两个子数组,则这两个数被分到不同子数组里,这样将问题转化为一个数组中只有一个数出现一次,其他数出现两次的子问题。
*/
class Solution
{
public:
vector<int> singleNumber(vector<int>& nums)
{
int xor_value = 0;
for(int num:nums) xor_value ^= num; //得到所有数的异或值
vector<int> result = {0,0}; //构造结果向量
for(int num:nums) //分成两个子数组分别进行异或
{
if((num&bit_mask) == 0) //注意:这里一定要打括号,因为==的优先级大于按位与&运算符
{
result[0] ^= num; //如果该位为1,相与之后为mask,否则为0
}
else result[1] ^= num;
}
return result;
}
};