137. 只出现一次的数字 II
思路
开辟一个32容量数组, 然后逐位计算个数 然后 % 3
public int singleNumber(int[] nums) {
int[] bitTag = new int[32];
for (int nm : nums) {
// 对每个数 计算bit位的值
for (int i = 0; i < 32; i++) {
bitTag[i] += nm & 1;
nm >>= 1;
}
}
int ans = 0;
for (int i = 0; i < 32; i++) {
// 要先移位, 否则最后一个后多移位一次
ans <<= 1;
ans |= bitTag[31 - i] % 3;
}
return ans;
}
260. 只出现一次的数字 III
思路
偶数个相同的数互相异或是0
两个不同的数异或必定有一位是不同的, 所以 从低位到高位开始判断哪位是1
因为其他的数都是偶数个, 那么根据这个来分为两组 进行互相异或
public int[] singleNumber(int[] nums) {
int[] ans = new int[2];
int temp = 0;
for (int nm : nums) {
temp ^= nm;
}
int i = 0;
// 寻找分割点
while ((temp & 1) == 0) {
i++;
temp >>= 1;
}
for (int nm : nums) {
if ((nm & (1 << i)) == 0) {
ans[0] ^= nm;
continue;
}
ans[1] ^= nm;
}
return ans;
}
421. 数组中两个数的最大异或值
思路
两个数异或值最大 那么就尽可能的让异或后的位数1足够多
构造一个前缀树 进行遍历寻找
在遍历的时候, 如果当前位是1, 那么就寻找0的前缀树路径
//节点
static class Node {
Node one = null;
Node zero = null;
}
// 构建前序树
public static void BuildTree(Node root, int num) {
int value = 0;
for (int i = 31; i >= 0; i--) {
value = (num >> i) & 1;
if (value == 1) {
if (root.one == null) {
root.one = new Node();
}
root = root.one;
} else {
if (root.zero == null) {
root.zero = new Node();
}
root = root.zero;
}
}
}
public int findMaximumXOR(int[] nums) {
Node root = new Node();
for (int nm : nums) {
BuildTree(root, nm);
}
int max = 0;
int tempNum;
int bitValue;
Node temp;
// 遍历每个数
for (int nm : nums) {
tempNum = 0;
temp = root;
for (int i = 31; i >= 0; i--) {
bitValue = (nm >> i) & 1;
// bit是1的时候, 就寻找 Node是0的 因为要异或和最大
if (bitValue == 1) {
if (temp.zero != null) {
temp = temp.zero;
tempNum |= 1 << i;
} else {
temp = temp.one;
}
} else {
if (temp.one != null) {
temp = temp.one;
tempNum |= 1 << i;
} else {
temp = temp.zero;
}
}
}
max = Math.max(max, tempNum);
}
return max;
}
318.最大单词长度乘积
思路
对每个字母计算后的位序进行 或 1 处理
如果两个String 每个字母都不同的话, 那么 进行 & 必定等于0
那么满足条件 计算长度积
public int maxProduct(String[] words) {
int[] bitNums = new int[words.length];
for (int i = 0; i < words.length; i++) {
for (int j = 0; j < words[i].length(); j++) {
// 对每个str的每个单词进行移位处理
bitNums[i] |= 1 << (words[i].charAt(j) - 'a');
}
}
int max = 0;
for (int i = 0; i < words.length; i++) {
for (int j = 1; j < words.length; j++) {
// 两个没有任何单词相同的进行 & 运算就是0
if ((bitNums[i] & bitNums[j]) == 0) {
max = Math.max(max, words[i].length() * words[j].length());
}
}
}
return max;
}
338. 比特位计数
/**
方法1:
递归: 偶数的1的个数和这个数/2是相同的, 例如 1000(8) == 100(4)
奇数的1的个数是上一个数+1, 101(5) = 100(4) + 1
*/
public int[] countBits(int num) {
int[] result = new int[num + 1];
int[] bk = new int[num + 1];
for (int i = 0; i <= num; i++) {
result[i] = getCount(i, bk);
}
return result;
}
public int getCount(int num, int[] bk) {
if (num == 0) return 0;
if (bk[num] != 0) return bk[num];
int result = 0;
if (num % 2 == 0) {
result = getCount(num / 2, bk);
} else {
result = getCount(num - 1, bk) + 1;
}
bk[num] = result;
return result;
}
/*
方法2: 计算每个数的1,并且用备忘录加速*/
public int[] countBits(int num) {
int[] result = new int[num + 1];
int[] bk = new int[num + 1];
for (int i = 0; i <= num; i++) {
result[i] = getCount(i, bk);
}
return result;
}
public int getCount(int num, int[] bk) {
int count = 0;
int temp = num;
while (temp > 0) {
// 备忘录加速
if (bk[temp] != 0) {
count = bk[temp] + count;
bk[num] = count;
return count;
}
if ((temp & 1) > 0) {
count++;
}
temp >>>= 1;
}
bk[num] = count;
return count;
}