Python技术迷

堂弟 45岁,今年被裁员了,赔偿金18万,被裁后他找了半年的工作,都嫌弃他年龄大,工资比以前少大半,不够养家~

刚看到个贴子,说一位45岁的堂弟被裁了,拿了18万赔偿,半年求职处处碰壁,现在想着把家里凑的40万干点小生意。嗯…这事儿挺现实的。

Image

我看了看网友的回复,有说“年龄歧视没办法”,也有鼓励他创业的。但我觉得吧,创业这东西,不能因为找不到工作就当成退路。

换个角度想,小生意就像摆摊卖煎饼,看着简单,其实每个环节都要本事,40万真不算多,亏起来比下雨还快。

在我看来,关键不是靠不靠谱,而是他有没有准备好。做什么?懂不懂?能不能扛得住?如果只是为了脱困而冲动创业,那风险比被裁还大。现在哪怕找份收入少点的工作,先稳住现金流,再慢慢摸索方向,也比把老本全压上要稳。

不过话说回来,人到中年确实不容易,能重新站起来就值得鼓励。【备注:文末可领最新资料】

面试题:在二叉树中增加一行

在公司加班到十一点多,脑子已经有点浆糊了,结果群里有人丢过来一道题:“在二叉树中增加一行”,还点名说要用 Python 写。我一看,这不是面试常考的那道嘛,干脆顺手给你也讲一遍,顺便当复习。

一、题目到底在干嘛?

先把问题说人话一点:

给你一棵二叉树 root,一个整数 val 和一个深度 depth。 要求是在「第 depth 层」插入一整行节点,每个新节点的值都是 val。

规则是这样的:

  • 原来在第 depth 层的那些节点,要整体“下沉”到新加的这一层下面。

  • 更具体点:

    • 原来的 node.left 变成新左节点的 left
    • 原来的 node.right 变成新右节点的 right
    • 然后把新建的这两个节点挂回到 node.left / node.right
    • 对于每个在第 depth-1 层的节点 node:

还有一个特殊情况:

  • 如果 depth == 1,那就要在整棵树的最上面加一行,也就是说新建一个值为 val 的节点,把原来的 root 当成它的左子树,新节点变成新的根。

示意一下(非常粗糙的那种):

原来:

   1
  / \
 2   3

如果 val = 9,depth = 2,插完变成:

     1
    / \
   9   9
  /     \
 2       3

左边那颗旧子树挂到新 9 的 left,右边那颗挂到新 9 的 right。

二、怎么找“插在哪一层”?

思路其实挺直接的,关键点只有一个:把所有“在 depth-1 层的节点”找出来,然后在它们下面插新行。

所以整体可以拆成两步:

  1. 如果 depth == 1:特殊处理,直接新建根节点。
  2. 否则:找到所有在 depth-1 层的节点,对每个节点做一次“左右各插一个”的操作。

那怎么找 depth-1 层呢?常规有两种写法:

  • BFS(层序遍历):一层一层往下走,数层数,走到 depth-1 就停。
  • DFS(递归):递归参数带当前层数,当层数 == depth-1 时处理当前节点。

两种都可以,我个人平时写题更偏向 BFS,因为“按层操作”的题用队列写起来比较直观,不容易绕晕。

三、用 BFS 写一版(队列层序遍历)

核心操作就是“走到 depth-1 层,然后对这一层所有节点动手”。

先假设我们有一个标准的二叉树节点定义:

# 二叉树节点定义(跟常见题目一样)
classTreeNode:
def__init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right

正式代码:

from collections import deque

classSolution:
defaddOneRow(self, root: TreeNode, val: int, depth: int) -> TreeNode:
# 特殊情况:在第 1 层加一行 => 新根节点
if depth == 1:
            new_root = TreeNode(val)
            new_root.left = root
return new_root

# 普通情况:用 BFS 找到第 depth-1 层
        queue = deque()
        queue.append(root)
        current_depth = 1

# 先走到 depth-1 层
while queue and current_depth < depth - 1:
            level_size = len(queue)
for _ in range(level_size):
                node = queue.popleft()
if node.left:
                    queue.append(node.left)
if node.right:
                    queue.append(node.right)
            current_depth += 1

# 此时 queue 里面就是所有 depth-1 层的节点
while queue:
            node = queue.popleft()

# 先保存旧的左右子树
            old_left = node.left
            old_right = node.right

# 建新的左节点和右节点
            node.left = TreeNode(val)
            node.right = TreeNode(val)

# 把原来的子树挂到新节点下面
            node.left.left = old_left
            node.right.right = old_right

return root

你可以顺着逻辑走一遍:

  • depth == 1:直接把旧 root 挂到新节点左边,返回新根,OK。

  • depth > 1:

    • 把原来的左右子树备份一下,
    • 新建两个节点挂在左右,
    • 再把刚刚备份的左右子树接到新节点下面。
    • while 那一段是“往下走层数”,走到 current_depth == depth-1 停。

    • 停的时候,队列里全是 “这一层” 的节点。

    • 对每个节点:

    • 其他层完全不动。

时间复杂度: 整棵树最多访问一次,所以是 O(N),N 为节点数。

空间复杂度: 队列最多装一层的节点,最坏情况接近 O(N),平均也是 O(N)。

四、要不要用 DFS?

顺便提一句 DFS 的写法,大概就是:

  • 定义一个递归函数 dfs(node, current_depth)
  • 当 current_depth == depth-1 时,对 node 做同样的“插左右”操作
  • 否则就递归 node.left 和 node.right

意思一样,只是写法风格不同。给你个参考代码(不用也行,看个思路):

classSolutionDFS:
defaddOneRow(self, root: TreeNode, val: int, depth: int) -> TreeNode:
if depth == 1:
            new_root = TreeNode(val)
            new_root.left = root
return new_root

defdfs(node, current_depth):
ifnot node:
return
if current_depth == depth - 1:
                old_left = node.left
                old_right = node.right
                node.left = TreeNode(val)
                node.right = TreeNode(val)
                node.left.left = old_left
                node.right.right = old_right
else:
                dfs(node.left, current_depth + 1)
                dfs(node.right, current_depth + 1)

        dfs(root, 1)
return root

这版就更“递归党友好”一点,看个人习惯。

五、一些小坑顺便提一下

随便提醒几个容易脑抽的点:

  • depth == 1 一定要单独处理,否则你会发现根本没机会往上插一层。
  • 修改左右指针的时候,一定要先把旧的 left/right 保存下来,不然直接覆盖掉就找不回了。
  • 不管 BFS 还是 DFS,别忘了空节点的判断,不然容易空指针。

整体来说,这道题逻辑不复杂,就是“按层操作 + 特殊的 depth=1”,多写几遍就很顺手了。

差不多就这样,我去泡杯咖啡压压惊,你要是想顺带练习下“构造二叉树 + 打印层序”那一套,也可以跟我说,我可以顺便给你拼一份完整的测试脚手架。

-END-

我为大家打造了一份RPA教程,完全免费:songshuhezi.com/rpa.html

🔥虎哥私藏精品🔥

虎哥作为一名老码农,整理了全网最全《python高级架构师资料合集》,总量高达650GB