程序员老鬼

年薪60万华为小领导爆料:在华为是个小领导,带20个外包,天天催他们干活,甚至通宵改 BUG,自己啥都没干,一直摘果子。。

刚看到个贴子,说有个华为年薪60万的小领导吐槽:自己带着二十个外包天天催活、催通宵改BUG,结果自己几乎啥都没干,全在摘果子,心里过意不去。

Image

从我的角度看,领导本来就不是干活最多的那个人,他的价值在于把活推进去、把资源协调好、把团队顶住压力。就像打游戏,你是队长,不一定输出最高,但你得指挥、得扛锅。网友说他“摘果子”,但职场本来就是按角色分工来分收益的,不是按谁敲键盘次数来算。

不过话说回来,如果他真觉得良心不安,那多为团队争点资源、多让大家少熬几个通宵,这才比较实际。光自责没用,还容易显矫情。

职场里谁的活都不轻松,各司其职、把团队带好,比“我是不是干得最多”重要多了。【备注:文末可领最新资料】

面试题:除法求值

下面就聊聊这道很典型、但又挺适合讲故事的题——「除法求值」(Evaluate Division),顺便用 Java 写一版好理解的解法。

大概意思是这样:

给你一堆“等式”和它们的结果,比如:

  • a / b = 2.0
  • b / c = 3.0

然后又给你很多问句:

  • a / c = ?
  • c / a = ?
  • x / y = ? …

如果能通过前面的等式推出来,就算出结果;推不出来,就返回 -1.0。

上面这个例子里:

  • a / c = (a / b) * (b / c) = 2.0 * 3.0 = 6.0
  • c / a = 1 / (a / c) = 1 / 6.0
  • 如果出现从来没见过的变量,比如 a / x,肯定是 -1.0。

用人脑看很简单,但要写代码就得想个统一的模型。

把等式看成一张“带权图”

最自然的想法: 每个变量(a、b、c…)当成图里的一个“点”,每个等式当成一条“有方向、有权重”的边。

比如有 a / b = 2.0,我们就建两条边:

  • a -> b 权重 2.0
  • b -> a 权重 1 / 2.0

再有 b / c = 3.0,就多两条边:

  • b -> c 权重 3.0
  • c -> b 权重 1 / 3.0

这样如果要算 a / c,其实就是在图里找一条从 a 到 c 的路径:

  • a -> b -> c

沿途把权重乘起来:2.0 * 3.0 = 6.0。

所以问题就变成了:

在一张带权有向图里,求“起点到终点”的路径乘积,如果走不到,就返回 -1。

图有了,那怎么找路径?DFS / BFS 都行,这里用 DFS 讲起来比较顺。

用 DFS 解“除法求值”

大致步骤:

  1. 建图用 Map<String, Map<String, Double>> graph 存边。

  • graph.get("a").get("b") = 2.0 表示 a -> b 权重为 2.0。
  • 处理查询对每个查询 x / y:

    • 如果 x 或 y 根本不在图里,直接返回 -1.0。
    • 如果 x.equals(y),且这个点存在,返回 1.0。
    • 否则,从 x 开始 DFS 找到 y,一路乘积累积结果。
  • DFS 细节写个递归函数 dfs(cur, target, acc, visited):

    逻辑是:

    • 没访问过就继续 DFS:dfs(next, target, acc * weight(cur->next), visited)
    • 谁先找到就返回谁;都找不到就返回 -1.0。
    • 如果 cur 就是 target,返回 acc。

    • 否则遍历 cur 的所有邻居 next:

    • cur:当前节点
    • target:目标节点
    • acc:从起点到当前节点的乘积
    • visited:防止死循环(比如 a->b, b->a 这种环)

    下面这段代码就是完整写法,尽量写得直白一点:

    import java.util.*;

    publicclassEvaluateDivision{

    publicdouble[] calcEquation(List<List<String>> equations, double[] values,
                                     List<List<String>> queries) {
    // 1. 建图:a / b = k  => a->b:k, b->a:1/k
            Map<String, Map<String, Double>> graph = new HashMap<>();

    for (int i = 0; i < equations.size(); i++) {
                List<String> eq = equations.get(i);
                String a = eq.get(0);
                String b = eq.get(1);
    double k = values[i];

                graph.putIfAbsent(a, new HashMap<>());
                graph.putIfAbsent(b, new HashMap<>());

                graph.get(a).put(b, k);
                graph.get(b).put(a, 1.0 / k);
            }

    double[] ans = newdouble[queries.size()];

    // 2. 处理每一个查询
    for (int i = 0; i < queries.size(); i++) {
                List<String> q = queries.get(i);
                String x = q.get(0);
                String y = q.get(1);

    if (!graph.containsKey(x) || !graph.containsKey(y)) {
    // 没见过的变量,肯定算不出来
                    ans[i] = -1.0;
                } elseif (x.equals(y)) {
    // 自己除自己 = 1
                    ans[i] = 1.0;
                } else {
                    Set<String> visited = new HashSet<>();
                    ans[i] = dfs(graph, x, y, 1.0, visited);
                }
            }

    return ans;
        }

    // 从 cur 出发,到 target,当前乘积是 acc
    privatedoubledfs(Map<String, Map<String, Double>> graph,
                           String cur, String target,
    double acc, Set<String> visited)
    {
    if (cur.equals(target)) {
    return acc;
            }
            visited.add(cur);

            Map<String, Double> neighbors = graph.get(cur);
    for (Map.Entry<String, Double> entry : neighbors.entrySet()) {
                String next = entry.getKey();
    double weight = entry.getValue();
    if (visited.contains(next)) {
    continue;
                }
    double res = dfs(graph, next, target, acc * weight, visited);
    if (res != -1.0) {
    // 找到了就一路返回
    return res;
                }
            }
    // 这条路走不通
    return -1.0;
        }

    // 简单测一下
    publicstaticvoidmain(String[] args){
            EvaluateDivision solver = new EvaluateDivision();

            List<List<String>> equations = Arrays.asList(
                    Arrays.asList("a", "b"),
                    Arrays.asList("b", "c")
            );
    double[] values = {2.0, 3.0};
            List<List<String>> queries = Arrays.asList(
                    Arrays.asList("a", "c"),
                    Arrays.asList("c", "a"),
                    Arrays.asList("a", "e"),
                    Arrays.asList("a", "a")
            );

    double[] res = solver.calcEquation(equations, values, queries);
            System.out.println(Arrays.toString(res));
    // 输出大致是:[6.0, 0.166..., -1.0, 1.0]
        }
    }

    简单回顾下整个流程(不搞那种特别抽象的总结):

    • 把“除法关系”变成一张图,边上放比例。

    • 查询的时候就是:在图里找一条路,从起点走到终点,一路把边的权值乘起来。

    • 走不到就 -1.0。

    • DFS 写起来不复杂,注意:

      • 变量可能不存在;
      • 图可能有环,记得 visited;
      • 自除情况返回 1.0。

    这题思路一旦和“带权图 + 路径乘积”对上号,后面基本就是体力活了。你可以再试着把 DFS 换成 BFS,或者用并查集带权重写一版,对图论和并查集的理解都会更清晰。

    -END-

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

    最后给大家分享一份不错的副业资料,点击下方公众号,回复关键字: 副业 领取,也可以链接我领取,微信:hls404