六月集训(第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;
}
};
东方欲晓,莫道君行早。

浙公网安备 33010602011771号