深度优先搜索 DFS
1.简介:
顾名思义,深度优先就是先一个一个向下访问,直接访问到最底下的一个节点,再一个一个退回来访问分支上的节点。
具体实现是通过递归来完成的。
顺序如下:
2.实现
深度优先搜索主要是通过不断递归,进而对树的各个成员进行访问。
递归模板:
/**
* Definition for a binary tree node.
* struct tree {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
void DFS(struct tree *root, int p1, int p2...){
//第一部分:递归终止条件
/*示例:*/ if(root->left == NULL)
{
return ;
}
//第二部分:该层需要进行的操作
process(......);
//第三部分递归到下一层
DFS(root->left, p1, p2,......); //递归到左子树
DFS(root->right, p2, p3,.....); //递归到右子树
}
3. 刷题 刷题 刷题 !!!
1. 第一题 LeetCode 104
leetcode 第104号题目:二叉树的最大深度
即:给定一棵二叉树,返回其最大深度(本题题解可直接套用递归模板)
int maxDepth(struct TreeNode* root){
int S1, S2;
if(!root) //终止条件
return 0;
S1 = 1 + maxDepth(root->left);
S2 = 1 + maxDepth(root->right);
return S1 > S2 ? S1 :S2;
}
本题最符合以下规则:
- 递归终止条件。
- 递归进入下一层
2. 第二题 LeetCode 897
递增顺序查找树(中序遍历)
原题复述:给定一棵二叉树,要求将这个二叉树,按照中序遍历的方式重新排列成只有右子树的一棵新树。
void DFS(struct TreeNode* root, struct TreeNode** newroot){
if(!root)
return ;
DFS(root->left,newroot);
root->left = NULL;
(*newroot)->right = root;
(*newroot) = root;
DFS(root->right, newroot);
}
struct TreeNode* increasingBST(struct TreeNode* root){
struct TreeNode ans = {};
struct TreeNode** cur = &ans;
DFS(root, &cur);
return ans.right;
}
思路描述:
- 创建一个新指针,作为新创建的树的根节点。
- 通过深度优先将最底下的的数字找出
- 再用一个新指针指向这个。
注意:
- 因为不是重新创建一棵树,而是在原有基础上改变树的指向,所以需要“ root ->left = NULL”
- (*newroot) = root; 目的是将新指针移向新指向的节点。
3.第三题
叶子相似的树
两棵树,比较两棵树的叶子是否相同,如果相同返回true,不同返回false
void dfs(struct TreeNode* root, int* path, int *size ){
if(root->left == NULL && root->right == NULL){
path[(*size)++] = root->val;
return ;
}
if(root->left) dfs(root->left, path, size);
if(root->right) dfs(root->right, path, size);
}
bool leafSimilar(struct TreeNode* root1, struct TreeNode* root2){
int path [400], path2[400];
int size1 = 0, size2 = 0;
dfs(root1, path, &size1);
dfs(root2, path2, &size2);
if(size1 != size2) return false;
for(int i = 0;i < size1;i++)
if(path[i] != path2[i]) return false;
return true;
}
思路:递归然后判断该节点是否为叶子节点,若为叶子节点则记录入数组当中,在返回判断两个数组是否完全一样。
4. 第四题
图像渲染
题目简易概述:
给定一个二维数组,指定将一个元素改变,使在该二维数组中与指定元素能上下左右连成一片的相同颜色全部改变。如图:
递归主要代码:
void apply_color(int** image, int imageSize, int* imageColSize, int sr, int sc, int newColor,int oldColor){
//递归推出条件
if(sc < 0 || sc >= *imageColSize)
return;
if(sr < 0 || sr >= imageSize)
return;
//递归执行层
if(image[sr][sc] == oldColor ){
image[sr][sc] = newColor;
apply_color(image, imageSize, imageColSize, sr - 1, sc, newColor, oldColor); //向左慢慢渲染
apply_color(image, imageSize, imageColSize, sr + 1, sc, newColor, oldColor); //向右慢慢渲染
apply_color(image, imageSize, imageColSize, sr, sc - 1, newColor, oldColor); //向上慢慢渲染
apply_color(image, imageSize, imageColSize, sr, sc + 1, newColor, oldColor); //向下慢慢渲染
}
return;
}
代码分析:
传入参数说明:
image 传入的二维数组
imageSize 传入数组的横向长度
imageColSize 传入数组的纵向长度
sr 目标的X轴坐标
sc 目标的Y轴坐标
newColor/oldColor 新旧颜色
在重点理解递归的这四句话:
apply_color(image, imageSize, imageColSize, sr - 1, sc, newColor, oldColor);
apply_color(image, imageSize, imageColSize, sr + 1, sc, newColor, oldColor);
apply_color(image, imageSize, imageColSize, sr, sc - 1, newColor, oldColor);
apply_color(image, imageSize, imageColSize, sr, sc + 1, newColor, oldColor);
递归运作流程:
5.第五题
int max_root(struct TreeNode* root){
if(!root)
return 0;
int hl = 0, hr = 0;
hl = 1 + max_root(root->left);
hr = 1 + max_root(root->right);
return (hl > hr ? hl:hr);
}
bool isBalanced(struct TreeNode* root){
if(!root)
return true;
int sl = 0, sr = 0;
sl = max_root(root->left);
sr = max_root(root->right);
if(sl - sr > 1||sr - sl > 1)
return false;
return isBalanced(root->left) && isBalanced(root->right);
}
重点: 最后一步
return isBalanced(root->left) && isBalanced(root->right);
作用 :遍历每一个节点的左右子树高度,然后进行比较。
3. 总结
- 求节点深度
S1 = 1 + maxDepth(root->left);
递归结果S1就是左子树的最大深度。
- 只寻找最末尾的节点可通过这个条件进行判断
root->left == NULL && root->right == NULL
即没有左右子树就代表为最末尾的节点 。
- 图像渲染这个题(!!!!!)
- 平衡二叉树这个题(!!!!)