leetcode208.实现Trie

1. 思路

Trie 树(又叫「前缀树」或「字典树」)是一种用于快速查询「某个字符串/字符前缀」是否存在的数据结构。
其核心是使用「边」来代表有无字符,使用「点」来记录是否为「单词结尾」以及「其后续字符串的字符是什么」。
image.png

2. 代码

  1. public class Trie{
  2. class TrieNode{
  3. boolean end;
  4. TrieNode[] children = new TrieNode[26];
  5. }
  6. TrieNode root;
  7. public Trie(){
  8. root = new TrieNode();
  9. }
  10. public void insert(String s){
  11. TrieNode p = root;
  12. for(char c:s.toCharArray()){
  13. int index = c-'a';
  14. if(p.children[index]==null){
  15. p.children[index] = new TrieNode();
  16. }
  17. p = p.children[index];
  18. }
  19. p.end = true;
  20. }
  21. public boolean search(String s){
  22. TrieNode p = root;
  23. for(char c:s.toCharArray()){
  24. int index = c-'a';
  25. if(p.children[index]==null){
  26. return false;
  27. }
  28. p = p.children[index];
  29. }
  30. return p.end;
  31. }
  32. public boolean startsWith(String s){
  33. TrieNode p = root;
  34. for(char c:s.toCharArray()){
  35. int index = c-'a';
  36. if(p.children[index]==null){
  37. return false;
  38. }
  39. p = p.children[index];
  40. }
  41. return true;
  42. }
  43. }

leetcode421. 数组中两个数的最大异或值

1. 思路

要求得数组nums 中的「最大异或结果」,假定 nums[i] 与 nums[j] 异或可以取得最终结果。由于异或计算「每位相互独立」(又称为不进位加法),同时具有「相同值异或结果为 0,不同值异或结果为 1」的特性。
因此对于 nums[j] 而言,可以从其二进制表示中的最高位开始往低位找,尽量让每一位的异或结果为 1,这样找到的 nums[i] 与 nums[j] 的异或结果才是最大的。
具体的,我们需要先将 nums 中下标范围为 [0, j]的数(二进制表示)加入Trie 中,然后每次贪心的匹配每一位(优先匹配与之不同的二进制位)。

2. 代码

  1. class Solution {
  2. class Node {
  3. Node[] ns = new Node[2];
  4. }
  5. Node root = new Node();
  6. void add(int x) {
  7. Node p = root;i
  8. for (int i = 31; i >= 0; i--) {
  9. int u = (x >> i) & 1;
  10. if (p.ns[u] == null) p.ns[u] = new Node();
  11. p = p.ns[u];
  12. }
  13. }
  14. int getVal(int x) {
  15. int ans = 0;
  16. Node p = root;
  17. for (int i = 31; i >= 0; i--) {
  18. int a = (x >> i) & 1, b = 1 - a;
  19. if (p.ns[b] != null) {
  20. ans |= (b << i);
  21. p = p.ns[b];
  22. } else {
  23. ans |= (a << i);
  24. p = p.ns[a];
  25. }
  26. }
  27. return ans;
  28. }
  29. public int findMaximumXOR(int[] nums) {
  30. int ans = 0;
  31. for (int i : nums) {
  32. add(i);
  33. int j = getVal(i);
  34. ans = Math.max(ans, i ^ j);
  35. }
  36. return ans;
  37. }
  38. }

leetcode1707.与数组中元素中的最大异或值

1. 思路

具体的,我们可以按照下面的逻辑进行处理:

  1. 对 nums 进行「从小到大」进行排序,对 queries 的第二维进行「从小到大」排序(排序前先将询问原本的下标映射关系存下来)。
  2. 按照排序顺序处理所有的 queries[i]:
    • 在回答每个询问前,将小于等于 queries[i][1] 的数值存入 TrieTrie。由于我们已经事先对 nums 进行排序,因此这个过程只需要维护一个在 nums 上有往右移动的指针即可。
    • 然后利用贪心思路,查询每个 queries[i][0] 所能找到的最大值是多少,计算异或和(此过程与 421. 数组中两个数的最大异或值 一致)。
    • 找到当前询问在原询问序列的下标,将答案存入。

      2. 代码

      ```java import java.util.Arrays; import java.util.HashMap;

public class MaximizeXor { class Node{ Node[] child = new Node[2]; } Node root = new Node(); void add(int x){ Node p = root; for(int i=31;i>=0;i—){ int u=(x>>i)&1; if(p.child[u]==null) p.child[u] = new Node(); p = p.child[u]; } }

int getVal(int x){
    int ans = 0;
    Node p=root;
    for(int i=31;i>=0;i--){
        int a=(x>>i)&1,b=1-a;
        if(p.child[b]!=null){
            p=p.child[b];
            ans=ans|(b<<i);
        }else {
            p=p.child[a];
            ans=ans|(a<<i);
        }
    }
    return ans^x;
}
public int[] maximizeXor(int[] nums, int[][] queries) {
    int m=nums.length,n= queries.length;
    HashMap<int[],Integer> map = new HashMap<>();
    for(int i=0;i<n;i++){
        map.put(queries[i],i);
    }
    Arrays.sort(nums);
    Arrays.sort(queries,(a,b)->a[1]-b[1]);
    int[] ans = new int[n];
    int loc = 0;
    for(int[] q:queries){
        int x=q[0],limit=q[1];
        while (loc<m&&nums[loc]<=limit){
            add(nums[loc++]);
        }
        if(loc==0){
            ans[map.get(q)]=-1;
        }else {
            ans[map.get(q)] = getVal(x);
        }
    }
    return ans;
}

}

```