1、题目描述
2、解题思路
光看题目还是懵懵懂懂,不如我把一个二叉树倒着过来看:
我们可以看出一个规律:对于任意一个节点,它的右结点变为左子节点的左子节点,它自己变为它左子节点的右子结点。
我们知道,对于一个节点来说,关心的是它的左右子结点,至于它的父节点是谁可以递归求解。
因此,我们需要对每一个节点的左子节点进行重新设置左右节点。
定义 DFS 函数,输入一个子树的根节点,返回的是该子树已经上下翻转后的新二叉树的根节点。
因此,DFS 函数的流程如下:
1、确定翻转后的新二叉树的根节点 head。如果,node 为叶子节点且 head 为空,则 node 成为新的头结点,head = node;
2、node 为 null,return;
3、node 不是叶子节点也不为 null,则先递归把 node 的左右子树翻转好,得到新的左右子节点,然后把新右子节点变为 node 新左子节点的左子节点,node 自己变为新左子节点的右子节点,最后 node 的左右子结点置空,即不再是原来左右子结点的父节点了。
3、解题代码
// Java实现
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
// 处理之后的根节点
TreeNode head;
public TreeNode upsideDownBinaryTree(TreeNode root) {
if (root == null) {
return null;
}
dfs(root); // 对 root 进行上下翻转
return head;
}
public TreeNode dfs(TreeNode node) {
if (node == null) {
return null;
}
if (node.left == null && node.right == null) {
if (head == null) {
// 最左边的节点即为实际的根节点
head = node;
}
return node;
}
TreeNode left = dfs(node.left);
TreeNode right = dfs(node.right);
if (left != null) {
// 左孩子的左子树为当前的右节点
left.left = right;
// 左孩子的右子树为当前父节点
left.right = node;
}
// 清空的当前父节点的左右子树
node.right = null;
node.left = null;
return node;
}
}
// c实现
/**
* Definition for a binary tree node.
*/
struct TreeNode {
int val;
struct TreeNode *left;
struct TreeNode *right;
};
struct TreeNode *newHead = NULL;
struct TreeNode *dfs(struct TreeNode *node)
{
if(node == NULL) return NULL;
// 1.叶子节点的处理
if(node -> left == NULL && node -> right == NULL)
{
if(newHead == NULL)
{
newHead = node;
}
return node;
}
// 2.非叶子节点的处理
// 2.1 先把左右子树进行上下翻转(如果存在的话)
struct TreeNode *newLeft = dfs(node -> left);
struct TreeNode *newRight = dfs(node -> right);
if(newLeft != NULL)
{
// 2.2 node 的新右子结点变为新左子节点的左子节点
newLeft -> left = newRight;
// 2.3 node 成为新左子节点的右子节点
newLeft -> right = node;
}
node -> left = NULL;
node -> right = NULL;
return node;
}
struct TreeNode *upsideDownBinaryTree(struct TreeNode *root)
{
if(root == NULL) return NULL;
dfs(root);
/** LeetCode的测试用例是使用一个main函数
* 因此,每次调用upsideDownBinaryTree函数在返回之前应该把全局变量newHead置空
* 否则,upsideDownBinaryTree会成为一次性函数,因为newHead只有第一次调用的时候不为空
**/
struct TreeNode *ans = newHead;
newHead = NULL;
return ans;
}