六月集训(第15天)—深度优先搜索

深度优先搜索

1. 508. 出现次数最多的子树元素和

    思路:
        (1) 先序遍历一遍二叉树,统计出每个结点对应的子树元素和
        (2) 将最大的元素和放入答案数组。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    struct Ans{
        int val;
        int cnt;
    };

    vector<int> ans;
    int dfs(TreeNode *root) {
        if (root->left == nullptr && root->right == nullptr) {
            ans.push_back(root->val);
            return root->val;
        }
        if (root->left != nullptr) root->val += dfs(root->left);
        if (root->right != nullptr) root->val += dfs(root->right);
        ans.push_back(root->val);
        return root->val;
    } 
public:
    vector<int> findFrequentTreeSum(TreeNode* root) {
        dfs(root);  // 将每个结点对应的元素和求出,放在数组ans中
        int cnt2 = 1;
        vector<Ans> cnt;

        sort(ans.begin(), ans.end());   /* 对ans排序,保证相同的数排在一起 */
        int ans_size = ans.size();
        if (ans_size == 1) return {ans[0]}; // 特判只有一个元素的情况
        for (int i = 1; i < ans_size; ++i) {    /* 统计每个元素和出现的次数,并将元素和和其出现次数打包,放入cnt中 */
            if (ans[i] != ans[i - 1]) {
                cnt.push_back({ans[i - 1], cnt2});
                cnt2 = 1;
            } else {
                cnt2++;
            }
            if (i == ans_size - 1) cnt.push_back({ans[i], cnt2});
        }
        sort(cnt.begin(), cnt.end(), [&](const Ans &a, const Ans &b) {  /* 对cnt降序排列,与最大cnt相同的元素和即为答案 */
            return a.cnt > b.cnt;
        });
        ans.clear();
        int cnt_size = cnt.size();
        ans.push_back(cnt[0].val);
        for (int i = 1; i < cnt_size; ++i) {
            if (cnt[i].cnt == cnt[i - 1].cnt) ans.push_back(cnt[i].val);
            else break;
        }
        return ans;
    }
};

上面自己写的有些冗余,对C++的容器使用不够熟悉,下面用unordered_map改写一下

看上去可以简洁一些,利用unordered_map可以减少一些转换的处理工作。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    unordered_map<int, int> cnt;
    int dfs(TreeNode *root) {
        if (root == nullptr) return 0;
        int sum = root->val;    // 不改变原来的二叉树
        sum += dfs(root->left);
        sum += dfs(root->right);
        cnt[sum]++;
        return sum;
    }
public:
    vector<int> findFrequentTreeSum(TreeNode* root) {
        cnt.clear();
        vector<vector<int>> ans;
        vector<int> ret;
        dfs(root);
        for (auto iter = cnt.begin(); iter != cnt.end(); iter++) {  /* 将子树元素和与其出现次数打包 */
            ans.push_back({iter->first, iter->second});
        }
        sort(ans.begin(), ans.end(), [&](const vector<int> &a, const vector<int> &b) {  /* 将子树元素和按照出现次数升序排列 */
            return a[1] > b[1];
        });
        int ans_size = ans.size();
        ret.push_back(ans[0][0]);
        for (int i = 1; i < ans_size; ++i) {
            if (ans[i][1] != ans[i - 1][1]) break;
            else ret.push_back(ans[i][0]);
        }
        return ret;
    }
};

2. 1600. 王位继承顺序

    思路:
        本题按照题意模拟即可,主要是需要自己设计数据结构来存储各种关系。发现自己在这方面的能力还很欠缺。

struct Tree{
    string name;
    bool isDead;
    vector<Tree*> childList;

    Tree() {
        name = "";
        isDead = false;
        childList.clear();
    }
};

class ThroneInheritance {
    unordered_map<string, Tree*> hash;
    Tree *root;
public:
    Tree *new_node(const string &name) {
        Tree *node = new Tree();
        node->name = name;
        hash[name] = node;
        return node;
    }

    ThroneInheritance(string kingName) {
        root = new_node(kingName);
    }
    
    void birth(string parentName, string childName) {
        Tree *node = hash[parentName];
        node->childList.push_back(new_node(childName));
    }
    
    void death(string name) {
        hash[name]->isDead = true;
    }

    void dfs(Tree *node, vector<string> &ret) {
        if (node == nullptr) return ;
        if (!node->isDead) ret.push_back(node->name);
        int childList_size = node->childList.size();
        for (int i = 0; i < childList_size; ++i) {
            dfs(node->childList[i], ret);
        }
    }
    
    vector<string> getInheritanceOrder() {
        vector<string> ret;
        dfs(root, ret);
        return ret;
    }
};

/**
 * Your ThroneInheritance object will be instantiated and called as such:
 * ThroneInheritance* obj = new ThroneInheritance(kingName);
 * obj->birth(parentName,childName);
 * obj->death(name);
 * vector<string> param_3 = obj->getInheritanceOrder();
 */

3. 1026. 节点与其祖先之间的最大差值

    思路:
        遍历树,到达每个结点时都携带着其祖先结点中的最大值maxx和最小值minn,该结点对应的答案就是其值与minn和maxx做差的绝对值的最大值。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    int ans = 0;
    void dfs(TreeNode *root, int minn, int maxx) {
        if (root == nullptr) return ;
        ans = max(ans, max(abs(root->val - minn), abs(root->val - maxx)));
        minn = min(minn, root->val);
        maxx = max(maxx, root->val);
        dfs(root->left, minn, maxx);
        dfs(root->right, minn, maxx);
    }
public:
    int maxAncestorDiff(TreeNode* root) {
        dfs(root, root->val, root->val);
        return ans;
    }
};

4. 655. 输出二叉树

    思路:
        通过观察样例可知,每层的宽度是$2^{depth} - 1$
         (1) 通过一次遍历获取树的深度depth
         (2) 利用depth求出每层的宽度$width = 2^{depth} - 1$
         (3) 开出大小为depth * width的数组,先用空串“”填充
         (4) 递归左右区间,将每个结点对应的值填入ret数组

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    int quick_pow(int base, int k) {    /* 快速幂 */
        int ans = 1;
        while (k) {
            if (k & 1) ans = ans * base;
            k >>= 1;
            base *= base;
        }
        return ans;
    }

    int dfs(TreeNode *root) {   /* 获取树的深度 */
        if (root == nullptr) return 0;
        int l = dfs(root->left);
        int r = dfs(root->right);
        return l > r ? l + 1 : r + 1;
    }

    void get_ans(TreeNode *root, int l, int r, int depth, vector<vector<string>> &ret) {    /* 递归生成ret结果 */
        if (root == nullptr) return ;
        int mid = l + ((r - l) >> 1);
        ret[depth][mid] = to_string(root->val);
        get_ans(root->left, l, mid - 1, depth + 1, ret);
        get_ans(root->right, mid + 1, r, depth + 1, ret);
    }
public:
    vector<vector<string>> printTree(TreeNode* root) {
        int depth = dfs(root);
        int width = quick_pow(2, depth) - 1;
        vector<vector<string>> ret(depth, vector<string>(width, ""));
        get_ans(root, 0, width, 0, ret);
        return ret;
    }
};
posted @ 2022-06-15 17:17  番茄元  阅读(34)  评论(0)    收藏  举报