题目重点:节点有parent/children/price,遍历完整共同祖先链寻找最小价格。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 有限parent树,身份比较不能用price代替;祖先包含本人。
- 并列取B向上遇到的第一个,即共同祖先里更近者;异树无共同祖先返回None。
解题路线
- 把A到根的所有节点身份放set,再B到根扫描,遇共同节点比较price;不要遇第一个共同节点就返回,它只是LCA。
- parent循环拒绝。已知同根树的共同祖先为LCA到根整条链,若查询多可先LCA再用路径最小值结构。
- 只读parent不需要遍历所有children;hA/hB决定基线成本。对象可能有重复价格,set使用id确保不会把不同节点同价误认。
手动走一遍
LCA价格20、其父价格3、根价格8,答案父而非LCA;若A就是B的祖先,仍要比较A及其所有祖先价格。异根即使价格都3也无共同节点。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def cheapest(a,b):
# Nodes expose parent and price; identities and prices are distinct concepts.
ancestors=set();u=a
while u is not None:
if id(u) in ancestors:raise ValueError("parent cycle")
ancestors.add(id(u));u=u.parent
best=None;seen=set();u=b
while u is not None:
if id(u) in seen:raise ValueError("parent cycle")
seen.add(id(u))
if id(u) in ancestors and (best is None or u.price<best.price):best=u
u=u.parent
return best
复杂度
O(hA+hB)时间、O(hA+hB)防环/祖先空间;静态多query可binary lifting加价格min索引O(nlogn)预处理,query O(logn)。
易错点与追问
容易失分的边界
- cheapest与lowest两种目标独立。
- 为优化先找LCA后只返回其price,没有查更高祖先。
继续深挖
- 价格动态更新,怎样用HLD/segment tree查询LCA到根最小?
- 严格祖先不含本人时,A/B父子情形答案怎样改变?
