本周记录了一道与DFS相关的题目。
DFS,深度优先搜索,基本思想是搜到底,然后 退一步重新搜,关键是将DFS应用到实际问题里面。如果将DFS用于搜索树,那么,对于一个节点,若它的左子树不为空且没有访问过,则对左子节点进行DFS;若它的右子树不为空且没有访问过,则对其右子节点进行DFS。当然,一道题不可能这么简单让你遍历所有节点,肯定是有一些操作需要去加入。下面是Leetcode上的一道题目。
1.题目描述
The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.
Determine the maximum amount of money the thief can rob tonight without alerting the police.
Example 1:
3
/ \
2 3
\ \
3 1
Maximum amount of money the thief can rob = 3 + 3 + 1 = 7.
Example 2:
3
/ \
4 5
/ \ \
1 3 1
Maximum amount of money the thief can rob = 4 + 5 = 9.
简化题目的意思,即给定一个二叉树,每个节点有对应的值,找出一个路径,满足两个条件:
(1)路径上每个节点的值相加是所有路径中最大的;
(2)路径内不能有相邻的节点。
2.解题思路
给定的是一棵二叉树,每个节点有对应的左右子树。对于根节点root的操作,我们希望采用递归的思想,对左右子树进行计算。在本题中,对于root节点,可以有两种选择,一是取root节点的值,那么此时其左右子树,就不能取左右子节点的值;二是不取root的值,那么此时其左右子树,可以取自身的值也可以不取自身的值。
因此,对于一个节点都会有两个值需要记录,一个是包含自身的路径值,另一个是不包含自身的最大路径值。因此我们可以定义一个有元素的数组,left[2]表示左子树,right[2]表示右子树,res[2]表示要求的root,其中,下标为0表示包含自身的最大路径值,下标为1表示不包含自身的路径值。对于root的计算时:
本题采用的是DFS的思想,都会从路径的叶子节点开始往上计算。因此,在计算每一个父节点之前,子节点的最大路径结果数组已经得到。因此递归计算可以得到最后的结果。在结果数组中,比较res[0]和res[1],取大的值就是结果值。(1)root自身的值 + 左子树不含自身 + 右子树不含自身,即res[0] = left[1] + right[1] + root->val;
(2)root不含自身的值 + 左子树 + 右子树,此时,左子树和右子树可以在含自身的路径值以及不含自身的路径值中选择一个最大的,相加就可以得到 root不含自身时的最大路径值,即res[1] = max(left[0], left[1]) + max(right[0],right[1])。
3.代码展示
int* dfs(TreeNode *root)
{
if (root == NULL){
int * res = new int[2];
res[0] = 0;
res[1] = 0;
return res;
}
int* left = dfs(root->left);
int* right = dfs(root->right);
int* res = new int[2];
res[0] = root->val + left[1] + right[1]; //下标0指的是包含root自己的值
res[1] = max(left[0], left[1]) + max(right[0],right[1]); //下标1指的是不含root自己,那么root的子树可以在含自己和不含自己之间选最大的
return res;
}
int rob(TreeNode* root) {
int* res;
res = new int[2];
res = dfs(root);
if(res[0] > res[1])
return res[0];
return res[1];
}