目录
[题目四:只出现一次的数字 II(Medium)](#题目四:只出现一次的数字 II(Medium))
题目一:判断字符是否唯一(Easy)
题目链接
- LeetCode 面试题 01.01 :判定字符是否唯一
解题思路(位图法)
鸽巢原理优化 :如果字符串长度超过 26(小写字母总数),则必定有重复字符,直接返回
false。位图思想:
使用一个 32 位的整数
bitMap作为"哈希表",每一位代表一个小写字母(0 表示未出现,1 表示已出现)。遍历字符串每个字符
ch,计算其偏移量i = ch - 'a'。检查
bitMap的第i位是否为 1:
若为 1,说明字符已出现,返回
false。否则,将第
i位置为 1(通过bitMap |= 1 << i)。遍历结束未发现重复,返回
true。
Java代码实现
java
class Solution {
public boolean isUnique(String astr) {
// 鸽巢原理优化
if (astr.length() > 26) return false;
int bitMap = 0;
for (int i = 0; i < astr.length(); i++) {
int x = astr.charAt(i) - 'a';
// 判断字符是否已出现
if (((bitMap >> x) & 1) == 1) {
return false;
}
// 将字符加入位图
bitMap |= (1 << x);
}
return true;
}
}
题目二:丢失的数字(Easy)
题目链接
- LeetCode 268 :丢失的数字
解题思路(位运算---异或消消乐)
异或运算性质:
任何数与 0 异或等于其本身:
a ^ 0 = a相同数异或结果为 0:
a ^ a = 0异或满足交换律和结合律
算法步骤:
初始化
ret = 0。遍历数组
nums,将每个数与ret异或。再遍历
[0, n](n为数组长度),将每个数与ret异或。最终
ret即为缺失的数字(因为出现两次的数都抵消了,缺失的数只出现一次)。
Java代码实现
java
class Solution {
public int missingNumber(int[] nums) {
int ret = 0;
// 异或数组中的所有数
for (int x : nums) {
ret ^= x;
}
// 异或 [0, n] 的所有数
for (int i = 0; i <= nums.length; i++) {
ret ^= i;
}
return ret;
}
}
题目三:两整数之和(Medium)
题目链接
- LeetCode 371 :两整数之和
解题思路(位运算模拟加法)
异或运算 :
a ^ b得到无进位加法的结果。与运算 :
(a & b) << 1得到进位。循环处理:
将无进位加法结果赋给
a,进位赋给b。重复直到进位
b为 0,此时a即为最终和。注意:Java 中负数用补码表示,位运算同样适用。
Java代码实现
java
class Solution {
public int getSum(int a, int b) {
while (b != 0) {
int x = a ^ b; // 无进位相加
int carry = (a & b) << 1; // 计算进位
a = x;
b = carry;
}
return a;
}
}
题目四:只出现一次的数字 II(Medium)
题目链接
- LeetCode 137 :只出现一次的数字 II
解题思路(比特位计数)
位运算统计:
由于其他数字都出现了三次,我们可以统计每个比特位上 1 出现的次数。
对每一位的计数结果取模 3,得到的结果就是只出现一次的数字在该位上的值(0 或 1)。
算法步骤:
初始化
ret = 0。遍历 32 个比特位(int 有 32 位):
统计数组中所有数字在该位上 1 的个数
sum。如果
sum % 3 == 1,说明只出现一次的数字在该位上是 1,将ret的该位置为 1。最终
ret即为所求。
Java代码实现
java
class Solution {
public int singleNumber(int[] nums) {
int ret = 0;
// 遍历32个比特位
for (int i = 0; i < 32; i++) {
int sum = 0;
// 统计第i位上1的个数
for (int x : nums) {
if (((x >> i) & 1) == 1) {
sum++;
}
}
sum %= 3;
if (sum == 1) {
ret |= (1 << i); // 设置ret的第i位为1
}
}
return ret;
}
}