1803.统计异或值在范围内的数对有多少
链接:1803.统计异或值在范围内的数对有多少
难度:Hard
标签:位运算、字典树、数组
简介:给你一个整数数组 nums (下标 从 0 开始 计数)以及两个整数:low 和 high ,请返回 漂亮数对 的数目。
题解 1 - cpp
- 编辑时间:2023-01-05
- 执行用时:432ms
- 内存消耗:132.2MB
- 编程语言:cpp
- 解法介绍:字典树,按位遍历,对于当前点找和 target 前缀一样,当前位小的数量。
#include <vector>
#include <numeric>
#include <iostream>
#include <unordered_map>
// bestlyg
#define X first
#define Y second
#define lb(x) ((x) & (-x))
#define mem(a,b) memset(a,b,sizeof(a))
#define debug freopen("input","r",stdin)
#define PII pair<int,int>
#ifdef DEBUG
#define log(frm, args...) {    printf(frm, ##args);}
#else
#define log(frm, args...)
#endif
typedef long long ll;
using namespace std;
class UnionFind {
public:
    int n;
    vector<int> data, cnt;
    UnionFind(int n): n(n), data(vector<int>(n, 0)), cnt(vector<int>(n, 1)) {
        iota(data.begin(), data.end(), 0);
    }
    int size(int v) { return cnt[find(v)]; }
    int find(int v) {
        if (data[v] == v) return v;
        return data[v] = find(data[v]);
    }
    void uni(int v1, int v2) {
        int p1 = find(v1), p2 = find(v2);
        if (p1 != p2) {
            cnt[p1] += cnt[p2];
            data[p2] = p1;
        }
    }
    bool same(int v1, int v2) { return find(v1) == find(v2); }
};
int pos2Idx(int x, int y, int size) { return x * size + y; }
void idx2Pos(int idx, int size, int &x, int &y) { x = idx / size; y = idx % size; }
vector<vector<int>> dirs = { {0, 1}, {0, -1}, {1, 0}, {-1, 0}};
// START
const int MAX = 14;
struct TrieNode {
    int sum, val;
    TrieNode *children[2];
    TrieNode(int val): sum(0), val(val) { children[0] = children[1] = nullptr; }
    ~TrieNode() {
        delete children[0];
        delete children[1];
    }
};
struct Trie {
    TrieNode *root;
    Trie(): root(new TrieNode(0)) {}
    void add(int num) {
        TrieNode *p = root;
        for (int i = MAX; i >= 0; i--) {
            int tag = (num >> i) & 1;
            TrieNode *next = p->children[tag];
            if (next == nullptr) next = p->children[tag] = new TrieNode(tag);
            p = next;
            p->sum += 1;
        }
    }
    int get(int num, int x) {
        TrieNode *p = root;
        int sum = 0;
        for (int i = MAX; i >= 0; i--) {
            int tag = (num >> i) & 1;
            if ((x >> i) & 1) {
                if (p->children[tag] != nullptr) sum += p->children[tag]->sum;
                if (p->children[tag ^ 1] == nullptr) return sum;
                p = p->children[tag ^ 1];
            } else {
                if (p->children[tag] == nullptr) return sum;
                p = p->children[tag];
            }
        }
        sum += p->sum;
        return sum;
    }
    ~Trie() {
        log("~trie
");
        delete root;
    }
};
class Solution {
public:
    int comp(vector<int> &nums, int num) {
        Trie trie;
        int ans = 0;
        for (int i = 1; i < nums.size(); i++) {
            trie.add(nums[i - 1]);
            ans += trie.get(nums[i], num);
        }
        return ans;
    }
    int countPairs(vector<int>& nums, int low, int high) {
        return comp(nums, high) - comp(nums, low - 1);
    }
};
// END
#ifdef LOCAL
int main() {
    Solution s;
    // vector<int> nums = {1,4,2,7};
    // int low = 2;
    // int high = 6;
    vector<int> nums = {9,8,4,2,1};
    int low = 5;
    int high = 14;
    cout << s.countPairs(nums, low, high) << endl;
    return 0;
}
#endif
题解 2 - rust
- 编辑时间:2023-01-05
- 执行用时:132ms
- 内存消耗:4.6MB
- 编程语言:rust
- 解法介绍:同上。
pub use std::{cell::RefCell, rc::Rc};
const MAX: i32 = 14;
struct TrieNode {
    sum: i32,
    children: [Option<Rc<RefCell<TrieNode>>>; 2],
}
impl TrieNode {
    fn new() -> TrieNode {
        TrieNode {
            sum: 0,
            children: [None, None],
        }
    }
}
struct Trie {
    root: Option<Rc<RefCell<TrieNode>>>,
}
impl Trie {
    fn new() -> Trie {
        Trie {
            root: Some(Rc::new(RefCell::new(TrieNode::new()))),
        }
    }
    fn add(&self, num: i32) {
        let mut p = self.root.clone().unwrap();
        let mut i = MAX;
        while i >= 0 {
            let tag = ((num >> i) & 1) as usize;
            let mut next: Option<Rc<RefCell<TrieNode>>> = None;
            if p.as_ref().borrow().children[tag].is_none() {
                let node = Rc::new(RefCell::new(TrieNode::new()));
                p.borrow_mut().children[tag] = Some(node.clone());
                next = Some(node.clone());
            } else {
                let node = p.as_ref().borrow().children[tag].clone();
                next = node
            }
            p = next.unwrap();
            p.borrow_mut().sum += 1;
            i -= 1;
        }
    }
    fn get(&self, num: i32, x: i32) -> i32 {
        let mut p = self.root.clone().unwrap();
        let mut sum = 0;
        let mut i = MAX;
        while i >= 0 {
            let tag = ((num >> i) & 1) as usize;
            if ((x >> i) & 1) == 1 {
                if p.as_ref().borrow().children[tag].is_some() {
                    let child = p.as_ref().borrow().children[tag].clone();
                    sum += child.unwrap().as_ref().borrow().sum;
                }
                if p.as_ref().borrow().children[tag ^ 1].is_none() {
                    return sum;
                }
                let next = p.as_ref().borrow().children[tag ^ 1].clone();
                p = next.unwrap();
            } else {
                if p.as_ref().borrow().children[tag].is_none() {
                    return sum;
                }
                let next = p.as_ref().borrow().children[tag].clone();
                p = next.unwrap();
            }
            i -= 1;
        }
        sum += p.as_ref().borrow().sum;
        sum
    }
}
impl Solution {
    fn comp(nums: &Vec<i32>, num: i32) -> i32 {
        let trie = Trie::new();
        let mut ans = 0;
        for i in 1..nums.len() {
            trie.add(nums[i - 1]);
            ans += trie.get(nums[i], num);
        }
        ans
    }
    pub fn count_pairs(nums: Vec<i32>, low: i32, high: i32) -> i32 {;
        Solution::comp(&nums, high) - Solution::comp(&nums, low - 1)
    }
}
题解 3 - typescript
- 编辑时间:2023-01-05
- 执行用时:7316ms
- 内存消耗:47.1MB
- 编程语言:typescript
- 解法介绍:暴力模拟。
function countPairs(nums: number[], low: number, high: number): number {
  const n = nums.length;
  let ans = 0;
  for (let i = 0; i < n; i++) {
    for (let j = i + 1; j < n; j++) {
      const v = nums[i] ^ nums[j];
      if (v >= low && v <= high) ans++;
    }
  }
  return ans;
}
题解 4 - rust
- 编辑时间:2023-01-05
- 执行用时:436ms
- 内存消耗:2.2MB
- 编程语言:rust
- 解法介绍:暴力。
impl Solution {
    pub fn count_pairs(nums: Vec<i32>, low: i32, high: i32) -> i32 {
        let mut ans = 0;
        for i in 0..nums.len() {
            for j in i + 1..nums.len() {
                let val = nums[i] ^ nums[j];
                if val >= low && val <= high {
                    ans += 1;
                }
            }
        }
        ans
    }
}