设计键

在以前的问题中,键的选择相对简单。不幸的是,有时你必须考虑在使用哈希表时设计合适的键

实际上,设计关键是在原始信息和哈希映射使用的实际键之间建立映射关系。设计键时,需要保证:

  1. 属于同一组的所有值都将映射到同一组中。
  2. 需要分成不同组的值不会映射到同一组。

设计键的模板

  1. 当字符串 / 数组中每个元素的顺序不重要时,可以使用排序后的字符串 / 数组作为键。
    设计键 - 图1
  2. 如果只关心每个值的偏移量,通常是第一个值的偏移量,则可以使用偏移量作为键。
    设计键 - 图2
  3. 在树中,你有时可能会希望直接使用 TreeNode 作为键。 但在大多数情况下,采用子树的序列化表述可能是一个更好的主意。
    设计键 - 图3
  4. 在矩阵中,你可能希望使用行索引列索引作为键。
  5. 在数独中,可以将行索引和列索引组合来标识此元素属于哪个
    设计键 - 图4
  6. 有时,在矩阵中,您可能希望将值聚合在同一对角线中。
    设计键 - 图5

字母异位词分组

详细见Map中,此处使用了第一种设计键的方法。

有效的数独

题目描述

力扣链接🔗

设计键 - 图6

题目分析

此处使用了设计键的第五种建议。将行和列用hashMap数组来判断,九宫格设计键的时候,使用列和行的组合来设计。

代码

  1. class Solution {
  2. public boolean isValidSudoku(char[][] board) {
  3. // 创建列和行和9宫格对应的map映射
  4. HashMap<Integer, Integer>[] rows = new HashMap[9];
  5. HashMap<Integer, Integer>[] lines = new HashMap[9];
  6. HashMap<Integer, Integer>[] boxs = new HashMap[9];
  7. // 为行,列,9宫格中添加hash映射来判断是否有相同的数字(初始化)
  8. for (int i = 0; i < 9; i++) {
  9. rows[i] = new HashMap<Integer, Integer>();
  10. lines[i] = new HashMap<Integer, Integer>();
  11. boxs[i] = new HashMap<Integer, Integer>();
  12. }
  13. // 遍历判断数独
  14. for (int i = 0; i < 9; i++) {
  15. for (int j = 0; j < 9; j++) {
  16. if (board[i][j] != '.') {
  17. int value = (int) board[i][j];
  18. rows[i].put(value, rows[i].getOrDefault(value, 0) + 1);
  19. lines[j].put(value, lines[j].getOrDefault(value, 0) + 1);
  20. // 为9宫格中的索引
  21. int index = (i / 3) * 3 + j / 3;
  22. boxs[index].put(value, boxs[index].getOrDefault(value, 0) + 1);
  23. // 判断是否存在
  24. if (rows[i].get(value) > 1 || lines[j].get(value) > 1 || boxs[index].get(value) > 1) {
  25. return false;
  26. }
  27. }
  28. }
  29. }
  30. return true;
  31. }
  32. }

寻找重复子树

题目描述

力扣链接🔗

设计键 - 图7

题目分析

采用子树的序列化表述作为键。

代码

  1. /**
  2. * Definition for a binary tree node.
  3. * public class TreeNode {
  4. * int val;
  5. * TreeNode left;
  6. * TreeNode right;
  7. * TreeNode() {}
  8. * TreeNode(int val) { this.val = val; }
  9. * TreeNode(int val, TreeNode left, TreeNode right) {
  10. * this.val = val;
  11. * this.left = left;
  12. * this.right = right;
  13. * }
  14. * }
  15. */
  16. class Solution {
  17. ArrayList<TreeNode> ans = new ArrayList<>();
  18. HashMap<String, Integer> map = new HashMap<>();
  19. public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
  20. serial(root);
  21. return ans;
  22. }
  23. public String serial(TreeNode treeNode) {
  24. if (treeNode == null) {
  25. return "#";
  26. }
  27. // 递归遍历树,每遍历一个节点,就会将树的结构序列化
  28. String string = treeNode.val +","+ serial(treeNode.left) +","+ serial(treeNode.right);
  29. // 将序列化后的字符串保存在map中
  30. map.put(string,map.getOrDefault(string,0) + 1);
  31. if (map.get(string) == 2) {
  32. ans.add(treeNode);
  33. }
  34. return string;
  35. }
  36. }