难度:困难。
标签:字典树。
使用字典树将数组中二进制字符串存储起来,每个节点都要存放该子树存储的数字个数。
使用
s
e
a
r
c
h
(
a
,
r
i
g
h
t
)
search(a, right)
search(a,right)查找与a异或小于right的数的个数。
正确解法:
class TrieNode{
public:
int num;
TrieNode* children[2] = {NULL};
TrieNode(){
num = 0;
}
};
class Trie{
public:
TrieNode* root;
Trie(){
root = new TrieNode();
}
void insert(string s){
TrieNode* cur = root;
for(int i = 0; i < s.length(); i++){
int c = s[i] - '0';
if(cur->children[c] == NULL){
cur->children[c] = new TrieNode();
}
cur->children[c]->num += 1;
cur = cur->children[c];
}
}
int search(string now, string high){
TrieNode* cur = root;
int res = 0;
for(int i = 0; i < now.length(); i++){
int now_c = now[i] - '0';
int high_c = high[i] - '0';
if(high_c){
// 与now_c相同,异或结果为0,比high小,全部加入结果并剪枝
if(cur->children[now_c] != NULL)res += cur->children[now_c]->num;
// 若不存在与now_c不同的值,则返回
if(now_c == 0){
if(cur->children[1] == NULL)return res;
cur = cur->children[1];
}
else{
if(cur->children[0] == NULL)return res;
cur = cur->children[0];
}
}
else{
// high_c为0,只能向异或结果为0的分支走
if(cur->children[now_c] == NULL)return res;
cur = cur->children[now_c];
}
}
// 若遍历到叶节点,需要加上叶节点
res += cur->num;
return res;
}
};
class Solution {
int max_n = 15;
string intTobin(int n, int max_n){
string s = "";
while(n){
s.insert(s.begin(), char(n % 2 + '0'));
n = n / 2;
}
int m = s.length();
for(int i = 0; i < max_n - m; i++)s.insert(s.begin(), '0');
return s;
}
public:
int countPairs(vector<int>& nums, int low, int high) {
Trie* tree = new Trie();
string left = intTobin(low - 1, max_n);
string right = intTobin(high, max_n);
int res = 0;
for(int i = 0; i < nums.size(); i++){
string s = intTobin(nums[i], max_n);
tree->insert(s);
res += tree->search(s, right) - tree->search(s, left);
}
return res;
}
};
参考:https://leetcode-cn.com/problems/count-pairs-with-xor-in-a-range/solution/dai-zhu-shi-de-cppzi-dian-shu-by-liu-xin-thli/
结果: