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
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Test Result

clipboard.png

clipboard.png


xufeng
8 声望3 粉丝

有多少人工就有多少智能