Description
Given a binary search tree (BST) with duplicates, find all the mode(s) (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).
My solution
// 全部存储的笨办法, 没有利用二叉搜索树的特点.
class Solution {
public:
vector<int> findMode(TreeNode *root) {
vector<int> res;
if(!root) return res;
unordered_map<int, int> mp;
stack<TreeNode *> s;
s.push(root);
while (!s.empty()) {
root = s.top();
s.pop();
++mp[root->val];
if (root->right) s.push(root->right);
if (root->left) s.push(root->left);
}
int maxcnt = 0;
for (auto mmp:mp) {
maxcnt = max(mmp.second, maxcnt);
}
for (auto mmp:mp) {
if (mmp.second == maxcnt) res.push_back(mmp.first);
}
return res;
}
};
Discuss
Obviously, it is very easy to get modes from a sorted array since all duplicates are consecutive. An in-order traversal of BST gives exactly a sorted sequence.
public class Solution {
public int[] findMode(TreeNode root) {
inorder(root);
modes = new int[modeCount];
modeCount = 0;
currCount = 0;
inorder(root);
return modes;
}
private int currVal;
private int currCount = 0;
private int maxCount = 0;
private int modeCount = 0;
private int[] modes;
private void handleValue(int val) {
if (val != currVal) {
currVal = val;
currCount = 0;
}
currCount++;
if (currCount > maxCount) {
maxCount = currCount;
modeCount = 1;
} else if (currCount == maxCount) {
if (modes != null)
modes[modeCount] = currVal;
modeCount++;
}
}
private void inorder(TreeNode root) {
if (root == null) return;
inorder(root.left);
handleValue(root.val);
inorder(root.right);
}
}
二叉树遍历问题
犹记上次去网易有道面试, 二叉树中序非递归没写出来的尴尬, 下面总结一波:
void visit(TreeNode *root) {
cout << root->val << " ";
}
递归
- 因为前中后的遍历是按照递归思想定义的, 所以递归的方式实现起来很easy, 并且相差不大.
### pre order
void preorder(TreeNode* root){
if(!root) return;
visit(root);
preorder(root->left);
preorder(root->right);
}
### in order
void inorder(TreeNode* root){
if(!root) return;
inorder(root->left);
visit(root);
inorder(root->right);
}
### post order
void postorder(TreeNode* root){
if(!root) return;
postorder(root->left);
postorder(root->right);
visit(root);
}
非递归
非递归实现起来, 从pre->in->post 一个比一个难...
pre order
- 和递归形式接近的方式
void preorder_likedigui(TreeNode *root) {
if (!root) return;
stack<TreeNode *> s;
s.push(root);
while (!s.empty()) {
root = s.top();
s.pop();
visit(root);
if (root->right) s.push(root->right);
if (root->left) s.push(root->left);
}
}
- 回溯
void preorder_huisu(TreeNode *root) {
if (!root) return;
stack<TreeNode *> s;
while (root || !s.empty()) {
if (root) {
visit(root);
s.push(root);
root = root->left;
} else {
root = s.top();
s.pop();
root = root->right;
}
}
}
in order
- 回溯
void inorder_huisu(TreeNode *root) {
if (!root) return;
stack<TreeNode *> s;
while (root || !s.empty()){
if(root){
s.push(root);
root=root->left;
}else{
root=s.top();
s.pop();
visit(root);
root=root->right;
}
}
}
post order
- 简易但是需要额外空间的方式
void postorder_huisu_extrastack(TreeNode *root) {
if (!root) return;
stack<TreeNode *> s, sextra;
s.push(root);
while (!s.empty()) {
root = s.top();
s.pop();
//visit(root);
sextra.push(root);
if (root->right) s.push(root->right);
if (root->left) s.push(root->left);
}
while(!sextra.empty()){
visit(sextra.top());
sextra.pop();
}
}
- 回溯 | 更复杂一些的方法(递归转非递归看来没有很容易的通用方式..)
void postorder_huisu(TreeNode *root) {
if (!root) return;
stack<TreeNode *> s;
TreeNode *lastVist = NULL;
while (root || !s.empty()) {
if (root) {
s.push(root);
root = root->left;
} else {
root = s.top();
if (root->right && lastVist != root->right) {
root = root->right;
} else {
s.pop();
visit(root);
lastVist = root;
root = NULL;
}
}
}
}
- *回溯另一种常见写法
回溯的方法还有常见的另一种写法,区别在于left->left->left..时使用while一次性到底, 我上面的代码是利用外层while, 两种方式都挺直观. 如下:
// 非递归后序遍历
public static void postorderTraversal(TreeNode root) {
Stack<TreeNode> treeNodeStack = new Stack<TreeNode>();
TreeNode node = root;
TreeNode lastVisit = root;
while (node != null || !treeNodeStack.isEmpty()) {
while (node != null) {
treeNodeStack.push(node);
node = node.left;
}
//查看当前栈顶元素
node = treeNodeStack.peek();
//如果其右子树也为空,或者右子树已经访问
//则可以直接输出当前节点的值
if (node.right == null || node.right == lastVisit) {
System.out.print(node.val + " ");
treeNodeStack.pop();
lastVisit = node;
node = null;
} else {
//否则,继续遍历右子树
node = node.right;
}
}
}
作者:jjs4500
链接:http://www.jianshu.com/p/456af5480cee
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。