1. 程式人生 > 實用技巧 >二叉樹的眾數問題

二叉樹的眾數問題

如果給定一棵二叉樹,要找到二叉樹中的所有眾數(出現頻率最高的元素)。

一、普通二叉樹的眾數

要統計出現的次數,一般使用到的是map中的unordered_map,因為不需要有序,也不需要有重複的元素,其key值一般是元素的值,value一般是元素出現的次數,這個只要遍歷一遍二叉樹就能得到unordered_map了;

關鍵是遍歷得到它之後怎樣做處理:

1 得到的map裡放的是key(元素)和value(元素出現的個數),是按照二叉樹遍歷的順序放進去的,如果不是二叉搜尋樹的中序遍歷,那就是無序的,要在這個無序的map中找到出現頻率最高的key(元素),也就是找到value值最大的所有元素,以下我總結幾種方法,其實懂的人可能覺得很簡單,因為我對於map的迭代操作不熟練,所以用來記錄一下,勿怪。

  (1)我們新建立一個vector<pair<int, int>>,用map初始化它,然後我們需要先遍歷一遍這個vector,找到value的最大值,再遍歷一遍,找到這個value對應的所有元素放進結果集中。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 
*/ class Solution { private: void searchBST(TreeNode* root, unordered_map<int, int>& map) { if (root == nullptr) return; map[root->val]++; searchBST(root->left, map); searchBST(root->right, map); return; } public: vector
<int> findMode(TreeNode* root) { //統計出現次數的一般用map來統計,將統計完的map轉換成vector<pair<int, int>> ,利用其特點給頻率進行sort排序,第一個肯定是最大的頻率,檢查後面還有沒有跟這個頻率一樣的頻率,記錄到結果集中 unordered_map<int, int> map;//key:元素 value:出現頻率 vector<int> result; if (root == nullptr) return result; searchBST(root, map);//得到的map是統計每個節點值出現的次數 /*****************程式碼的區別在這裡*******************/ vector<pair<int, int>> vec(map.begin(), map.end()); int maxValue = INT_MIN;//記錄value的最大值 for (int i=0; i<vec.size(); i++) { maxValue = max(maxValue, vec[i].second); } //以上得到了value的最大值 for (int i=0; i<vec.size(); i++) { if(vec[i].second == maxValue) result.push_back(vec[i].first); } return result; } };

  (2)直接用map迭代器進行迭代

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
private:
    void searchBST(TreeNode* root, unordered_map<int, int>& map) {
        if (root == nullptr)
            return;
        map[root->val]++;
        searchBST(root->left, map);
        searchBST(root->right, map);
        return;
    }
public:
    vector<int> findMode(TreeNode* root) {
        //統計出現次數的一般用map來統計,將統計完的map轉換成vector<pair<int, int>> ,利用其特點給頻率進行sort排序,第一個肯定是最大的頻率,檢查後面還有沒有跟這個頻率一樣的頻率,記錄到結果集中
        unordered_map<int, int> map;//key:元素 value:出現頻率
        vector<int> result;
        if (root == nullptr)
            return result;
        searchBST(root, map);//得到的map是統計每個節點值出現的次數
        
        /*****************程式碼的區別在這裡*******************/
        unordered_map<int, int>::iterator it;//建立一個迭代器
        int maxValue = INT_MIN;//記錄value的最大值
        for (it = map.begin(); it != map.end(); it++) {
            maxValue = max(maxValue, (*it).second);
        }
        //以上得到了value的最大值
        for (it = map.begin(); it != map.end(); it++) {
            if((*it).second == maxValue)
                result.push_back((*it).first);
        }

        return result;
    }
};

2 得到的map是key 和 value一一對應的,我們可以建立vector<pair<int, int>>來將map複製過來,然後對這個vector進行sort排序,按照value從大到小的順序排序,排序好之後,value最大也就是出現次數最多的元素肯定排在前面,遍歷一次,將他們加入結果集即可。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
private:
    void searchBST(TreeNode* root, unordered_map<int, int>& map) {
        if (root == nullptr)
            return;
        map[root->val]++;
        searchBST(root->left, map);
        searchBST(root->right, map);
        return;
    }
    bool static cmp(const pair<int, int>& a, const pair<int, int>& b) {
        return a.second > b.second;
    }
public:
    vector<int> findMode(TreeNode* root) {
        //統計出現次數的一般用map來統計,將統計完的map轉換成vector<pair<int, int>> ,利用其特點給頻率進行sort排序,第一個肯定是最大的頻率,檢查後面還有沒有跟這個頻率一樣的頻率,記錄到結果集中
        unordered_map<int, int> map;//key:元素 value:出現頻率
        vector<int> result;
        if (root == nullptr)
            return result;
        searchBST(root, map);//得到的map是統計每個節點值出現的次數
        vector<pair<int, int>> vec(map.begin(), map.end());
        sort(vec.begin(), vec.end(), cmp);
        result.push_back(vec[0].first);
        for (int i=1; i<vec.size(); i++) {
            if(vec[i].second == vec[0].second)
                result.push_back(vec[i].first);
            else
                break;
        }
        return result;
    }
};

二、求二叉搜尋樹中的所有眾數

二叉搜尋樹也是普通的二叉樹,當前可以按照普通二叉樹的思路和方法求解,但是二叉搜尋樹具有 中序遍歷 有序的特性,應用這個特性,能找到更高效的方法。

可以通過一次遍歷得到結果,需要pre指標來記錄前一個節點,需要count來統計頻率,需要maxCount來表示最大頻率,還需要一個結果集在存放結果。因為是全部遍歷,所以遞迴函式不需要返回值

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
private:
    vector<int> result;//結果集
    int count = 0;//統計頻率
    int maxCount = 0;//最大頻率
    TreeNode* pre = nullptr;//記錄前一個節點,與當前節點進行比較
    void searchBST(TreeNode* root) {
        if (root == nullptr)
            return;
        searchBST(root->left);//
        if (pre == nullptr)
            count = 1;//說明是第一個節點
        else if (pre->val == root->val)
            count++;
        else
            count = 1;//如果前一個跟當前不相等,清空count頻率計數器
        pre = root;
        if (count == maxCount) {
            result.push_back(root->val);
        }
        if (count > maxCount) {//如果不是最大頻率,就要清空result結果集,將更大的放進去
            maxCount = count;
            result.clear();
            result.push_back(root->val);
        }
        searchBST(root->right);//
        return;
    }
public:
    vector<int> findMode(TreeNode* root) {
        //二叉搜尋樹的中序遍歷相當於一個有序陣列,在一個有序陣列中找出所有的眾數,一次遍歷就能解決
        result.clear();
        searchBST(root);
        return result;
    }
};