博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[LeetCode] Find Mode in Binary Search Tree 找二分搜索数的众数
阅读量:6074 次
发布时间:2019-06-20

本文共 4099 字,大约阅读时间需要 13 分钟。

 

Given a binary search tree (BST) with duplicates, find all the  (the most frequently occurred element) in the given BST.

Assume a BST is defined as follows:

  • The left subtree of a node contains only nodes with keys less than or equal to the node's key.
  • The right subtree of a node contains only nodes with keys greater than or equal to the node's key.
  • Both the left and right subtrees must also be binary search trees.

 

For example:

Given BST [1,null,2,2],

1    \     2    /   2

 

return [2].

Note: If a tree has more than one mode, you can return them in any order.

Follow up: Could you do that without using any extra space? (Assume that the implicit stack space incurred due to recursion does not count).

 

这道题让我们求二分搜索树中的众数,这里定义的二分搜索树中左根右结点之间的关系是小于等于的,有些题目中是严格小于的,所以一定要看清题目要求。所谓的众数就是出现最多次的数字,可以有多个,那么这道题比较直接点思路就是利用一个哈希表来记录数字和其出现次数之前的映射,然后维护一个变量mx来记录当前最多的次数值,这样在遍历完树之后,根据这个mx值就能把对应的元素找出来。那么用这种方法的话就不需要用到二分搜索树的性质了,随意一种遍历方式都可以,下面我们来看递归的中序遍历的解法如下:

 

解法一:

class Solution {public:    vector
findMode(TreeNode* root) { vector
res; int mx = 0; unordered_map
m; inorder(root, m, mx); for (auto a : m) { if (a.second == mx) { res.push_back(a.first); } } return res; } void inorder(TreeNode* node, unordered_map
& m, int& mx) { if (!node) return; inorder(node->left, m, mx); mx = max(mx, ++m[node->val]); inorder(node->right, m, mx); }};

 

下面这种解法是上面方法的迭代形式,也是用的中序遍历的方法,有兴趣的童鞋可以实现其他的遍历方法:

 

解法二:

class Solution {public:    vector
findMode(TreeNode* root) { if (!root) return {}; vector
res; TreeNode *p = root; stack
s; unordered_map
m; int mx = 0; while (!s.empty() || p) { while (p) { s.push(p); p = p->left; } p = s.top(); s.pop(); mx = max(mx, ++m[p->val]); p = p->right; } for (auto a : m) { if (a.second == mx) { res.push_back(a.first); } } return res; }};

 

题目中的follow up说了让我们不用除了递归中的隐含栈之外的额外空间,那么我们就不能用哈希表了,不过这也不难,由于是二分搜索树,那么我们中序遍历出来的结果就是有序的,这样我们只要比较前后两个元素是否相等,就等统计出现某个元素出现的次数,因为相同的元素肯定是都在一起的。我们需要一个结点变量pre来记录上一个遍历到的结点,然后mx还是记录最大的次数,cnt来计数当前元素出现的个数,我们在中序遍历的时候,如果pre不为空,说明当前不是第一个结点,我们和之前一个结点值比较,如果相等,cnt自增1,如果不等,cnt重置1。如果此时cnt大于了mx,那么我们清空结果res,并把当前结点值加入结果res,如果cnt等于mx,那我们直接将当前结点值加入结果res,然后mx赋值为cnt。最后我们要把pre更新为当前结点,参见代码如下:

 

解法三:

class Solution {public:    vector
findMode(TreeNode* root) { vector
res; int mx = 0, cnt = 1; TreeNode *pre = NULL; inorder(root, pre, cnt, mx, res); return res; } void inorder(TreeNode* node, TreeNode*& pre, int& cnt, int& mx, vector
& res) { if (!node) return; inorder(node->left, pre, cnt, mx, res); if (pre) { cnt = (node->val == pre->val) ? cnt + 1 : 1; } if (cnt >= mx) { if (cnt > mx) res.clear(); res.push_back(node->val); mx = cnt; } pre = node; inorder(node->right, pre, cnt, mx, res); }};

 

下面这种方法是上面解法的迭代写法,思路基本相同,可以参考上面的讲解,参见代码如下:

 

解法四:

class Solution {public:    vector
findMode(TreeNode* root) { if (!root) return {}; vector
res; TreeNode *p = root, *pre = NULL; stack
s; int mx = 0, cnt = 1;; while (!s.empty() || p) { while (p) { s.push(p); p = p->left; } p = s.top(); s.pop(); if (pre) { cnt = (p->val == pre->val) ? cnt + 1 : 1; } if (cnt >= mx) { if (cnt > mx) res.clear(); res.push_back(p->val); mx = cnt; } pre = p; p = p->right; } return res; }};

 

类似题目:

 

参考资料:

 

转载地址:http://jtngx.baihongyu.com/

你可能感兴趣的文章
解决eclipse之ADT与SDK版本不一致问题
查看>>
jQuery 属性操作
查看>>
小甜点,RecyclerView 之 ItemDecoration 讲解及高级特性实践
查看>>
387. 字符串中的第一个唯一字符
查看>>
(转)ORA-01245错误 (2013-04-13 18:37:01)
查看>>
shiro笔记-AuthenticatingRealm和AuthorizingRealm关系
查看>>
内联网
查看>>
从键盘上连续录入一批整数,比较并输出其中的最大值和最小值,当输入数字0时结束循环...
查看>>
mysql中触发器如何监听本身并且改变本身的字段?
查看>>
VBA 高级筛选
查看>>
设置应用图标badge(徽章)
查看>>
洛谷P4891 序列
查看>>
省选前做题记录
查看>>
批量替换行首
查看>>
jenkins对接gitlab和git
查看>>
MANIFEST.MF中的MF是什么意思
查看>>
归并排序与递归
查看>>
CVE-2018-0802漏洞利用
查看>>
根据业务压力测试
查看>>
点分治——树上路径统计
查看>>