刚看到个贴子,说一姑娘吐槽:程序员老公被优化,三个月没找到工作,现在去送快递,一个月四五千,她嫌他摆烂,动了离婚的念头。

打开网易新闻 查看精彩图片

我觉得这事吧,得把“暂时跌落”和“彻底废了”分清。收入从两万掉到四千,谁都会崩溃一下,可去送快递说明他至少没躺平。真要说问题,也是这三个月怎么过的,是在想办法转型,还是只会抱怨。

婚姻就是一起扛风险,你只认高薪不认人,那谁敢在人生低谷暴露真面目?

我的看法是,先跟老公摊开聊,定个时间表和计划,比如转岗、考证、换行都行。要是真看不到一点行动,再谈去留也不迟。日子难一点可以,别先把心散了。

算法题: 拆分二叉搜索树

昨晚十一点多我还在公司楼下吹风…就是那种脑子已经关机了,手机还在叮叮叮,群里小李突然甩我一句:哥,算法题“拆分二叉搜索树”咋写啊,我明天面试要讲思路…我当时就想笑,你说这题看着像“树”,其实更像线上拆流量,按阈值把请求分两拨,一拨走快路径,一拨去慢队列,对吧,都是“分流”。

先把题意用人话说一下哈:给你一棵 BST(左小右大那个),再给个值 V,让你把树拆成两棵:第一棵全是 <= V 的节点,第二棵全是 > V 的节点,而且原来的相对结构尽量保留(别把节点值重新插一遍那种,太费劲也不优雅)。

我当时在便利店门口掏出电脑,想法很直:BST 的性质太香了,你站在一个节点 x 上——

  • 如果 x.val <= V ,那 x 肯定属于左边那棵(<=V 的树),问题只会出在它的右子树:右边可能混着 <=V>V ,得继续拆。拆完以后,把“右子树里 <=V 的那部分”接回 x.right ,而“右子树里 >V 的那部分”就当成第二棵树的根返回。

  • 反过来如果 x.val > V ,那 x 应该去右边那棵(>V 的树),麻烦在它的左子树:左边也可能混着两类,拆完后把“左子树里 >V 的那部分”接回 x.left ,剩下的 <=V 那部分就返回给第一棵。

就这么递归一层一层拆,特别像你在网关里按阈值把链路切两段…说着说着我发现老板在催我回去开会,行,代码我贴这儿,你拿去讲,别背稿,讲逻辑就行。

from __future__ import annotations
from dataclasses import dataclass
from typing import Optional, Tuple, List

@dataclass
classTreeNode:
val: int
left: Optional["TreeNode"] = None
right: Optional["TreeNode"] = None

defsplit_bst(root: Optional[TreeNode], V: int) -> Tuple[Optional[TreeNode], Optional[TreeNode]]:
"""
返回 (small, big)
small: 所有节点 val <= V
big: 所有节点 val > V
两棵树都保持 BST 结构,且尽量复用原节点(不新建节点)。
"""
if root isNone:
returnNone, None

if root.val <= V:
# root 属于 small,继续拆右子树
small_right, big = split_bst(root.right, V)
root.right = small_right
return root, big
else:
# root 属于 big,继续拆左子树
small, big_left = split_bst(root.left, V)
root.left = big_left
return small, root

复杂度这块你别说太“学院派”,就说一句就够:每个节点最多被摸一次,时间 O(n),递归栈最坏 O(h),h 是树高,退化链表就 O(n),平衡点就 O(log n)。面试官要是追问“为啥不重建节点”,你就说线上工程里能复用对象就复用,减少分配、减少 GC 抖动,思路更工程化一点…嗯差不多。