找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

3606

积分

0

好友

478

主题
发表于 昨天 20:28 | 查看: 5| 回复: 0

刚刷到一个吐槽,说有个技术很菜的同事跳槽去了体制内。帖子的观点挺损,但细想又很扎心:像他这样有学历但技术短板明显的人,进体制内反而最能扬长避短,一点儿也不浪费个人优势。

大疆员工爆料称技术菜但学历好的同事去了体制内能避开短处

这种人进了体制内,真就像切换了游戏地图。学历是硬通货,沟通表达也不算差,流程意识也具备。写材料、做对接、组织开会、向上汇报,这些活儿反倒能把他的优势发挥出来。技术短板没人天天拿放大镜盯着看,压力也不再是半夜 On-Call 或者周末紧急上线的玩法。

所以说,有时候真不是个人能力行不行的问题,而是赛道有没有选对。大厂需要的是能落地、能救火、能硬扛事儿的人;而体制内很多岗位要的则是稳重、守规矩、履历体面。

他可能不是“废了”,只是终于从地狱难度切换到了自己最舒服的模式。估计 HR 看完这份吐槽,都得沉默两秒。


面试题:四叉树交集

这道题最容易写错的地方,不在于递归,而在于题目名字本身。

“四叉树交集”这几个字一看,很多人的手速会比脑子快,直接写成 AND 逻辑。但这道题实际的合并逻辑,是求两个黑白矩阵的逻辑 OR 。也就是说,在同一块区域里,只要有一边是 true ,结果就应该是 true

四叉树的节点定义一般长这样:

class Node {
    public boolean val;
    public boolean isLeaf;
    public Node topLeft;
    public Node topRight;
    public Node bottomLeft;
    public Node bottomRight;

    public Node() {}

    public Node(boolean val, boolean isLeaf) {
        this.val = val;
        this.isLeaf = isLeaf;
    }

    public Node(boolean val, boolean isLeaf,
                Node topLeft, Node topRight,
                Node bottomLeft, Node bottomRight) {
        this.val = val;
        this.isLeaf = isLeaf;
        this.topLeft = topLeft;
        this.topRight = topRight;
        this.bottomLeft = bottomLeft;
        this.bottomRight = bottomRight;
    }
}

拿到这题,我一般不急着去拆四个方向,而是先关注叶子节点

因为叶子节点代表的是一整块完整的矩形区域,而不仅仅是一个网格。如果这个地方的判断顺序搞错了,代码就会多出许多毫无意义的递归调用。

比如,左边是一棵 true 的叶子节点:

node1: isLeaf = true, val = true
node2: 随便是什么

那合并后的结果,一定是一棵 true 的叶子节点。

这片区域已经全是 1 了,再和谁做 OR 运算结果都还是 1。后面的结构不用看,也不该去看。

反之,如果某一边是 false 叶子,那它对 OR 运算没有任何贡献,直接返回另一棵树的结构就行。

思路清晰后,代码可以这样组织:

class Solution {

    public Node intersect(Node a, Node b) {
        if (a == null) return b;
        if (b == null) return a;

        if (a.isLeaf) {
            return a.val ? new Node(true, true) : cloneTree(b);
        }

        if (b.isLeaf) {
            return b.val ? new Node(true, true) : cloneTree(a);
        }

        Node leftTop = intersect(a.topLeft, b.topLeft);
        Node rightTop = intersect(a.topRight, b.topRight);
        Node leftBottom = intersect(a.bottomLeft, b.bottomLeft);
        Node rightBottom = intersect(a.bottomRight, b.bottomRight);

        if (canMerge(leftTop, rightTop, leftBottom, rightBottom)) {
            return new Node(leftTop.val, true);
        }

        return new Node(false, false, leftTop, rightTop, leftBottom, rightBottom);
    }

    private boolean canMerge(Node a, Node b, Node c, Node d) {
        return a.isLeaf && b.isLeaf && c.isLeaf && d.isLeaf
                && a.val == b.val
                && b.val == c.val
                && c.val == d.val;
    }

    private Node cloneTree(Node node) {
        if (node == null) return null;

        if (node.isLeaf) {
            return new Node(node.val, true);
        }

        return new Node(
                node.val,
                false,
                cloneTree(node.topLeft),
                cloneTree(node.topRight),
                cloneTree(node.bottomLeft),
                cloneTree(node.bottomRight)
        );
    }
}

这段代码里我加了个 cloneTree 辅助方法。这不是必须的,但我个人编码时更倾向于这么做。

有些算法题解会直接返回原节点的引用,提交到 LeetCode 上当然也能通过。但如果后续还有其他逻辑需要修改这棵树,共用了原树引用就很容易出现脏数据。在纯粹的算法题里可能无所谓,但在工程代码里,我一般不会偷这个懒。

这题真正的流程就四步,顺序千万不能乱:

  1. 先看 true 叶子:直接吞掉另一棵树,游戏结束。
  2. 再看 false 叶子:忽略它,直接把后续处理交给另一棵树。
  3. 两边都不是叶子:递归处理四个子区域。
  4. 递归回来后,检查四个子节点能否压缩成一个叶子节点。

最后这个压缩步骤非常关键。

试想一下,如果四个子区域最终全是 true,但你不做合并,结果虽然在逻辑上正确,可树的结构却不够简洁。四叉树的核心意义,就在于将连续相同值的区域压缩成一块,否则它就直接退化成了普通的网格结构,失去了数据结构本身的价值。

这题看着像是在考树的操作,实际上,它考的是两个核心逻辑判断:叶子节点能否提前终结递归,以及递归结果能否重新合并。只要处理这两个点的顺序不乱,代码结构就不会散架。

在准备面试求职时,这一类题目不仅能考察递归的熟练度,更能看出候选人对数据结构本质的理解程度。如果你也有类似的解题心得,不妨常来云栈社区和我们一起聊聊,那里聚集了很多热爱深挖技术细节的极客。




上一篇:接手老旧项目,真想一把推倒重写?聊聊程序员的执念与现实
下一篇:微软发布Majorana 2量子芯片:比特可靠性提升千倍,商业化目标提速至2029
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-6-4 03:01 , Processed in 0.888505 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表