二叉搜索树中的众数

题目描述

力扣链接🔗

二叉搜索树中的众数 - 图1

代码分析

暴力法

将树作为一个普通树。

遍历二叉搜索树为一个数组,再将数组进行遍历即可,次数使用hashmap统计频率即可。

  1. 这个树都遍历了,用map统计频率
  2. 把统计的出来的出现频率(即map中的value)排个序
  3. 取前面高频的元素
  1. /**
  2. * 暴力法(遍历成数组即可)
  3. *
  4. * @param root
  5. * @return
  6. */
  7. public int[] findMode(TreeNode root) {
  8. traversal(root);
  9. for (int i = 0; i < res.size(); i++) {
  10. map.put(res.get(i), map.getOrDefault(res.get(i), 0) + 1);
  11. }
  12. for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
  13. if (entry.getValue() >= max) {
  14. max = entry.getValue();
  15. }
  16. }
  17. for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
  18. if (entry.getValue() == max) {
  19. temp.add(entry.getKey());
  20. }
  21. }
  22. int[] ints = new int[temp.size()];
  23. for (int i = 0; i < temp.size(); i++) {
  24. ints[i] = temp.get(i);
  25. }
  26. return ints;
  27. }
  28. int max = Integer.MIN_VALUE;
  29. Map<Integer, Integer> map = new HashMap<>();
  30. List<Integer> res = new ArrayList<>();
  31. List<Integer> temp = new ArrayList<>();
  32. public TreeNode traversal(TreeNode root) {
  33. if (root == null) {
  34. return null;
  35. }
  36. if (root.left != null) traversal(root.left);
  37. res.add(root.val);
  38. if (root.right != null) traversal(root.right);
  39. return root;
  40. }

递归法

既然是搜索树,它中序遍历就是有序的

二叉搜索树中的众数 - 图2

二叉搜索树的递归时的常用方法就是中序遍历,定义一个前节点和当前节点来处理。

由于二叉搜索树是有顺序的,所以通过前节点和当前节点来判断值是否相等,相等则频率加一,由于众数不止一个,需要定义一个最大频率来记录众数出现的次数,当后面的数都等于最大频率时,也将结果记录进去,但是注意:如果后面有比最大频率更大的数时,需要将出现频率赋值给最大频率,同时需要将记录的结果清空,再重新记录。

  1. /**
  2. * 递归法(根据二叉树的性质)
  3. *
  4. * @param root
  5. * @return
  6. */
  7. public int[] findMode(TreeNode root) {
  8. searchBST(root);
  9. int[] ints = new int[res.size()];
  10. for (int i = 0; i < res.size(); i++) {
  11. ints[i] = res.get(i);
  12. }
  13. return ints;
  14. }
  15. TreeNode pre;
  16. int maxCount; // 最大频率
  17. int count; // 统计频率
  18. List<Integer> res = new ArrayList<>();
  19. public TreeNode searchBST(TreeNode root) {
  20. if (root == null) {
  21. return null;
  22. }
  23. searchBST(root.left); // 左
  24. if (pre == null) {
  25. count = 1; // 第一个节点
  26. } else if (pre.val == root.val) {
  27. count++; // 当当前节点和上一个节点相同,频率加一
  28. } else {
  29. count = 1; // 此时不相同,重新统计
  30. }
  31. pre = root; // 移动到下一个节点
  32. if (count == maxCount) { // 此时频率等于最大频率
  33. res.add(root.val);
  34. }
  35. if (count > maxCount) {
  36. maxCount = count;
  37. res.clear(); // 此时最大的频率改变,要清空集合里的所有元素
  38. res.add(root.val);// 重新赋值
  39. }
  40. searchBST(root.right); //右
  41. return root;
  42. }
  43. }

迭代法

迭代法处理逻辑递归法一致,只需要将中序迭代法的模板修改即可。

  1. TreeNode pre;
  2. TreeNode cur;
  3. int maxCount; // 最大频率
  4. int count; // 统计频率
  5. List<Integer> res = new ArrayList<>();
  6. /**
  7. * 迭代法(中序遍历)
  8. *
  9. * @param root
  10. * @return
  11. */
  12. public int[] findMode(TreeNode root) {
  13. Stack<TreeNode> stack = new Stack();
  14. cur = root;
  15. pre = null;
  16. while (cur != null || !stack.isEmpty()) {
  17. if (cur != null) {
  18. stack.push(cur);
  19. cur = cur.left;
  20. } else {
  21. cur = stack.pop();
  22. if (pre == null) {
  23. count = 1;
  24. } else if (pre.val == cur.val) {
  25. count++;
  26. } else {
  27. count = 1;
  28. }
  29. if (count == maxCount) {
  30. res.add(cur.val);
  31. }
  32. if (count > maxCount) {
  33. maxCount = count;
  34. res.clear();
  35. res.add(cur.val);
  36. }
  37. pre = cur; // 移动节点
  38. cur = cur.right; // 遍历右边
  39. }
  40. }
  41. int[] ints = new int[res.size()];
  42. for (int i = 0; i < res.size(); i++) {
  43. ints[i] = res.get(i);
  44. }
  45. return ints;
  46. }