leetcode树之二叉树寻路

1104、二叉树寻路

在一棵无限的二叉树上,每个节点都有两个子节点,树中的节点 逐行 依次按 “之” 字形进行标记。

如下图所示,在奇数行(即,第一行、第三行、第五行……)中,按从左到右的顺序进行标记;

而偶数行(即,第二行、第四行、第六行……)中,按从右到左的顺序进行标记。

给你树上某一个节点的标号 label,请你返回从根节点到该标号为 label 节点的路径,该路径是由途经的节点标号所组成的。

示例1:

输入:label = 14
输出:[1,3,4,14]

示例2:

输入:label = 26
输出:[1,2,6,10,26]

思路:

递归求上一层的结点值,

  • 对于偶数层来说,由于是逆序,所以该节点原本的值应该是 最小值 + (最大值 - 当前值),也就是计算当前值和最大值得距离,然后累加到最小值上,那么上一层的值在这个基础上除以2即可
  • 对于奇数层来说,该层的顺序是顺序的,也就是这个值没有问题,那么上层原本的值应该是该值除以2,但是上层肯定是逆序的,所以上层的值应该是上层最小值 + (上层最大值 - 上层本应该的值)
class Solution:
  	# 获取当前label所在层数
    def getDep(self, label):
        dep = 0
        while label:
            label = label // 2
            dep += 1
        return dep
    def pathInZigZagTree(self, label: int) -> List[int]:
        self.ans = []
        def dfs(label):
            self.ans.insert(0, label)
            dep = self.getDep(label)
            if dep <= 1: return
            # 分别针对奇数列和偶数列求上层的值进行递归
            if dep % 2 == 0:
                maxLabel = (1 << dep) - 1
                minLabel = 1 << (dep - 1)
                preLabel = (minLabel + maxLabel - label) // 2
            else:
                preLabel = label // 2
                dep -= 1
                maxLabel = (1 << dep) - 1
                minLabel = 1 << (dep - 1)
                preLabel = minLabel + maxLabel - preLabel
            dfs(preLabel)
        dfs(label)
        return self.ans
1372、二叉树中的最长交错路径

给你一棵以 root 为根的二叉树,二叉树中的交错路径定义如下:

  • 选择二叉树中 任意 节点和一个方向(左或者右)。
  • 如果前进方向为右,那么移动到当前节点的的右子节点,否则移动到它的左子节点。
  • 改变前进方向:左变右或者右变左。
  • 重复第二步和第三步,直到你在树中无法继续移动。

交错路径的长度定义为:访问过的节点数目 - 1(单个节点的路径长度为 0 )。

请你返回给定树中最长 交错路径 的长度。

示例1:

输入:root = [1,null,1,1,1,null,null,1,1,null,1,null,null,null,1,null,1]
输出:3

示例2:

输入:root = [1,1,1,null,1,null,null,1,1,null,1]
输出:4

示例3:

输入:root = [1]
输出:0

思路:

第一想到的是递归,根据上一步的前进方向确定下一步的前进方向

class Solution:
    def longestZigZag(self, root: TreeNode) -> int:
      	# 用于存放最大交错长度
        self.maxLen = 0
        def dfs(root, isLeft=True, length=0):
            if not root: return
            self.maxLen = max(self.maxLen, length)
            # 如果上一步是向左,那么这一步应该向右,所以应该是左节点向右移动,然后length + 1
            # 这里还需要从右节点重新开始规划路径
            # 同理如果上一步是向右,这一步应该向左,并且向右重新规划路径
            if isLeft:
                dfs(root.left, False, length + 1)
                dfs(root.right, True, 0)
            else:
                dfs(root.right, True, length + 1)
                dfs(root.left, False, 0)
        # 从父节点的左右子节点出发,分别计算交错长度
        dfs(root) and dfs(root, False)
        return self.maxLen

使用BFS来遍历树,这个时候由于用bool值只能表示一个方向,否则其中一个方向数据会丢失,这里使用父节点和子节点的关系来表示方向。同时不停的更新节点向左走和向右走的交错长度。

class Solution:
    def longestZigZag(self, root: TreeNode) -> int:
      	# 队列中存放父节点和当前结点,用来表示上一步的前进方向
        queue = [(None, root)]
        # l存放的是向左走到该节点的交错长度,r是向右走到该节点的交错长度
        l = collections.defaultdict(int)
        r = collections.defaultdict(int)
        while queue:
            parent, node = queue.pop(0)
            if parent:
              	# 分别记录该节点向左走和向右走的交错长度,如果这一步是向左走,那么上一步应该是向右走,所以取r里的值
                if parent.left == node:
                    l[node] = r[parent] + 1
                else:
                    r[node] = l[parent] + 1
            if node.left:
                queue.append((node, node.left))
            if node.right:
                queue.append((node, node.right))
        # 计算最长的交错路径,这里加上0,避免整个数组长度为0,导致报错
        return max([0] + [v for v in l.values()] + [v for v in r.values()])
1457、二叉树中的伪回文路径

给你一棵二叉树,每个节点的值为 1 到 9 。我们称二叉树中的一条路径是 「伪回文」的,当它满足:路径经过的所有节点值的排列中,存在一个回文序列。

请你返回从根到叶子节点的所有路径中 伪回文 路径的数目。

示例1:

输入:root = [2,3,1,3,1,null,1]
输出:2 

示例2:

输入:root = [2,1,1,1,3,null,null,null,null,null,1]
输出:1 

示例3:

输入:root = [9]
输出:1

思路:

有回文路径,说明该路径中节点值为奇数的至多只能有一个,所以当遇到叶子结点时,统计该路径中奇数值的个数即可。

class Solution:
    def __init__(self):
        self.cache = collections.defaultdict(int)
        self.pathCount = 0

    def check(self):
        count = 0
        print(self.cache)
        for key, value in self.cache.items():
            if value % 2:
                count += 1
        self.pathCount += count <= 1

    def pseudoPalindromicPaths (self, root: TreeNode) -> int:
        def dfs(root):
            if not root: return 0
            # 统计节点出现的次数
            self.cache[root.val] += 1
            # 叶子结点进行奇数节点统计
            if not root.left and not root.right:
                self.check()
            dfs(root.left)
            dfs(root.right)
            # 路径遍历完之后,将该节点统计值删除
            self.cache[root.val] -= 1

        dfs(root)
        return self.pathCount
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

溪语流沙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值