目录
判定字符是否唯一
题目解析
算法原理
解法一 :用int hash[26]哈希表去遍历整个字符串,如果谋个字符出现的次数 > 1次,那么返回true,否则返回false
时间复杂度:O(N) 遍历一遍数组
空间复杂度:O(N) 开了一个哈希表
解法二 :用位图的思想,因为字符不超过32个
位图的下标是0到31
0表示字符未出现过,1表示这个字符已经出现过一次了
鸽巢原理的优化:
只要字符的长度超过了26表示一定出现了重复字符
代码
cpp
class Solution
{
public:
bool isUnique(string astr)
{
// 哈希表
// int hash[128] = {0};
// for(int i = 0;i < astr.size();++i)
// hash[astr[i]]++;
// for(int i = 0;i < astr.size();++i)
// {
// if(hash[astr[i]] != 1) return false;
// }
// return true;
// 位图 + 优化(鸽巢原理)
int n = astr.size();
if(n > 26) return false;// 优化
// 位图
int bitMap = 0;
for(auto ch : astr)
{
int i = ch - 'a';
// 判断字符是否重复
if((bitMap >> i)&1) return false;
// 否则将字符加入到位图中
bitMap |= (1 << i);
}
return true;
}
};
丢失的数字
题目解析
算法原理
代码
cpp
class Solution
{
public:
int missingNumber(vector<int>& nums)
{
// 位运算
// 时间O(N) 空间O(1)
int ret = 0;
for(auto x : nums) ret ^= x;
for(int i = 0;i <= nums.size();++i)
ret ^= i;
return ret;
int sum = 0;
vector<int> v(nums.size()+1);
for(int i = 0;i < nums.size() + 1;++i)
{
v[i] = i;
sum ^= v[i];
}
for(int i = 0;i < nums.size();++i)
{
sum ^= nums[i];
}
return sum;
// 哈希表
// 时间O(N) 空间O(N)
int n = nums.size();
int hash[10000] = {0};
for(int i = 0;i < n;++i) hash[nums[i]]++;
for(int i = 0;i <= n;++i)
{
if(hash[i] == 0) return i;
}
return -1;
// 高斯求和
// 时间O(N) 空间O(1)
int sum = 0;
int n = nums.size();
// 全部的和
int k = (0+n)*(n+1) / 2;
for (int i = 0; i < n; ++i)
sum += nums[i];// 数组中的和
return k - sum;// 缺失的数
}
};
两整数之和
题目解析
算法原理
a^b表示无进位加法
a&b,表示保留进位
(a&b)<< 1,表示进位
a^b 再和(a&b) << 1 异或(无进位相加后再循环上面的步骤直到进位为0就是答案)
代码
cpp
class Solution
{
public:
// <*>
int getSum(int a, int b)
{
// int sum = 0;
// while(b != 0)
// {
// int tmp = a & b;
// a = a ^ b;
// b = tmp << 1;
// }
// return a;
while(b != 0)
{
int x = a ^ b;
unsigned int tmp =(unsigned int)(a & b) << 1;
a = x;
b = tmp;
}
return a;
}
};
只出现一次的数字 II
题目解析
算法原理
把所有数第0位的比特位的值相加然后%3,有三个相同的数,得到的最终结果是唯一的那个数的比特位
代码
cpp
class Solution
{
public:
// <*>
int singleNumber(vector<int>& nums)
{
int ret = 0;
for(int i = 0;i < 32;++i)// 0 ~ 31
{
int sum = 0;// 记录所有数当前位,比特位的和
for(auto x : nums)
if((x >> i)&1 == 1) sum++;
sum %= 3;// 得到唯一出现数当前比特位的值1或0
if(sum == 1) ret |= (1 << i); // 当前位,比特位放入结果中
}
return ret;
}
};
消失的两个数字
题目解析
算法原理
不是缺失了两个数字吗,那么全部数异或起来就是a^b的值,tmp = a ^ b,tmp肯定不等于0,那么肯定他们两有一个比特位上的数字是不同的,0或1,就找是0还是1就可以区分它们了
代码
cpp
class Solution
{
public:
vector<int> missingTwo(vector<int>& nums)
{
// int n = nums.size();
// vector<int> ret;
// int hash[30001] = {0};
// for(int i = 0;i < n;++i)
// hash[nums[i]]++;
// for(int i = 1;i <= n+2;++i)
// if(hash[i] != 1) ret.push_back(i);
// return ret;
// 1. 得到缺失的两个数异或的值
int tmp = 0;
for(auto x:nums) tmp ^= x;
for(int i = 1;i <= nums.size() + 2;++i) tmp ^= i;
// 2. 找出缺失的位置tmp != 0,必然至少一个数的位置上是0^1
int k = 0;
while(1)
{
if(((tmp >> k)&1)== 1) break;
else k++;
}
// 3. 根据比特位上是0还是1可以分开两个数
int a = 0,b = 0;
for(auto x : nums)
{
if(((x >> k)&1) == 1) a ^= x;
else b ^= x;
}
for(int i = 1;i <= nums.size() + 2;++i)
{
if(((i >> k)&1) == 1) a ^= i;
else b ^= i;
}
return {a,b};
}
};
恭喜你看到这里了,那就祝你题题AC ! ! !