LeetCode刷题--翻转二叉树

树结构参考链接:https://blog.csdn.net/Tonywu2018/article/details/89480282
题解参考:
https://labuladong.gitbook.io/algo/shu-ju-jie-gou-xi-lie/shou-ba-shou-shua-er-cha-shu-xun-lian-di-gui-si-wei/er-cha-shu-xi-lie-1

翻转一棵二叉树。

示例:

输入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9
输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/invert-binary-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

写题之前,先明确树的几个基本概念。

  1. 树节点的定义
  2. 二叉树的定义
  3. 树的前、中、后序遍历的方法
class TreeNode(object):
    def __init__(self, data=0, left=None, right=None):
        self.data = data
        self.left = left
        self.right = right


class BinTree(object):
    def __init__(self):
        self.root = None
        self.ls = []

    def add(self, data):
        node = TreeNode(data)
        if self.root is None:
            self.root = node
            self.ls.append(self.root)
            return
        treenode = self.ls[0]
        if treenode.left is None:
            treenode.left = node
            self.ls.append(node)
        elif treenode.right is None:
            treenode.right = node
            self.ls.append(node)
            self.ls.pop(0)

    def preOrderTraversal(self, root):
        # 前序遍历(根左右):递归实现
        if root is None:  # 递归结束条件,根节点为None,返回
            return
        print(root.data)  # 先中,则先打印根节点的数据项
        self.preOrederTraversal(root.left)  # 对左子树递归调用前序遍历函数
        self.preOrederTraversal(root.right)  # 对右子树递归调用前序遍历函数

    def inOrderTraversal(self, root):
        # 中序遍历(左根右):递归实现
        if root is None:  # 递归结束条件,相同
            return
        self.inOrderTraversal(root.left)  # 先左,则先对左子树递归调用中序遍历函数
        print(root.data)  # 打印根节点的数据项
        self.inOrderTraversal(root.right)  # 最后,对右子树递归调用中序遍历函数

    def postOrderTraversal(self, root):
        # 后序遍历(左右根):递归实现
        if root is None:    # 不多说,递归结束条件
            return
        self.postOrderTraversal(root.left)  # 先左,则先对左子树递归调用后序遍历函数
        self.postOrderTraversal(root.right) # 再右,对右子树递归调用后序遍历函数
        print(root.data)    # 关键,最后再打印根节点的数据项

想法

根据题解提示:

  1. 翻转这棵树,其实就是根据前序遍历,将每一个节点的左右节点交换即可。

遇到的问题

(换到Python上,有关于类的思想还没有转变过来)

# 上边写的树
from Tree import TreeNode
from Tree import BinTree


class Solution(object):
    def invertTree(self, Btree: BinTree):
    # 这里传进的参数对象有问题,应该传入的是树的根节点,而不是BinTree这个类
        if Btree.root is None:
            return
        Btree.root.left, Btree.root.right = Btree.root.right, Btree.root.left
        self.invertTree(Btree.root.left)
        self.invertTree(Btree.root.right)


if __name__ == '__main__':
    L = [4, 2, 7, 1, 3, 6, 9]
    bintree = BinTree()
    for i in L:
        bintree.add(i)
    #solution = Solution()
    #solution.invertTree(bintree)
    bintree.preOrderTraversal(bintree.root)

更改后的代码

class Solution(object):
    def invertTree(self, root: TreeNode):
    # 这里root的类型是TreeNode
        if root is None:
            return
        root.left, root.right = root.right, root.left
        self.invertTree(root.left)
        self.invertTree(root.right)


if __name__ == '__main__':
    L = [4, 2, 7, 1, 3, 6, 9]
    bintree = BinTree()
    for i in L:
        bintree.add(i)
    solution = Solution()
    solution.invertTree(bintree.root)	# 传入二叉树的根节点
    bintree.preOrderTraversal(bintree.root)

没有理解类的定义,传入了一个类,导致了递归调用的时候,参数传入错误。
这里的类相当于一个自己定义的函数类型,里面有方法,数据等。你将这个类型的数据传入另一个函数中,并进行相关操作(面向对象的思想),就是直接改变了这个数据。(改变了root)

Q:但是参考题解说到,前后序遍历可以,中序遍历不行,为什么?
这里的不行,不是说不能翻转,而是只能部分翻转,因为,别理论了,直接上代码跑再来说明

from Tree import TreeNode
from Tree import BinTree


class Solution(object):
    def invertTree(self, root: TreeNode):
        if root is None:
            return
        self.invertTree(root.left)
        root.left, root.right = root.right, root.left
        self.invertTree(root.right)


if __name__ == '__main__':
    L = [4, 2, 7, 1, 3, 6, 9]
    bintree = BinTree()
    for i in L:
        bintree.add(i)
    solution = Solution()
    solution.invertTree(bintree.root)
    bintree.preOrderTraversal(bintree.root)

翻转前 4213769(前序遍历)
得到结果4769213(前序遍历)
这是因为中序遍历交换节点的时候,

     4
   /   \
  2     7
 / \   / \
1   3 6   9
第一次交换
     4
   /   \
  2     7
 / \   / \
3   1 6   9
第二次交换
     4
   /   \
  7     2
 / \   / \
6   9 3   1
神奇的事情发送了,7那边就根本不会变了,因为左边已经遍历过,现在变右边
第三次交换
     4
   /   \
  7     2
 / \   / \
6   9 1   3
这样,右边的2的子节点变了两次,所以,对于4来说,导致只变换子节点2 7,不变换孙子节点

你可能感兴趣的:(算法,leetcode)