乐于分享
好东西不私藏

第一批要求上门卸载小龙虾(OpenClaw)的人已经出现了..

第一批要求上门卸载小龙虾(OpenClaw)的人已经出现了..

卸载 OpenClaw

最近最火的全民性话题,除了石油,就是 OpenClaw(小龙虾)。

而 OpenClaw 里最大的话题,就是上门安装,前天我们 聊了,腾讯方面组织了现场免费安装,在工作日引来了上千人到场,而美团则联手了联想百应,推出了费用高达 395/695 的上门服务。

但这两家大厂,其实都不是最早推出上门服务的,最早推出的,其实是一些"民间"玩家。

根据地区不同,上门安装费用从 100~1000 不等。

但这两天,这些最早提供上门安装服务的猎金者,又有了新的热门生意,就是「上门卸载 OpenClaw」

是的,你没听错,这种钱,ta 们不仅能挣,甚至还能挣两遍 🤣🤣🤣

这 OpenClaw 之所以在大众里,要得快,去得快,对应回来,无非就是"跟风"和"风险"。

大家听说装了 OpenClaw 是智能安装助手,上门安装都要大几百的,一旦看到有免费安装机会,或者有通俗易懂的教程,马上就装了,生怕享受完了。

但对于当中原理和风险,毫不知晓,不少人直接就是拿自己的主力机去安装了。

这几天,随着各类官号频繁提示风险,以及一些"OpenClaw 自动给人发红包"的鬼故事持续发酵,不少人产生了卸载需求 🤣🤣

根据我对网上"对 OpenClaw 祛魅"的人的总结,无非是如下几类:

  1. 带着对 OpenClaw 的期待来下载,没过两天,发现自己根本没有什么任务可以交给 OpenClaw 做
  2. 吃过 OpenClaw 风险的亏,例如被错删资料,乱搞系统,错发邮件
  3. 还没正式大面积使用 OpenClaw,但其实被最近的各类风险提示和鬼故事吓到了,尤其是目前 OpenClaw 还跑在了主力机上面

后两者,是付费卸载的主力用户。

299,上门卸载,包售后一个月,干净无残留:

集体养虾,又集体杀虾,而且这都是本周发生的,世界真魔幻。

题目描述

平台:LeetCode

题号:310

树是一个无向图,其中任何两个顶点只通过一条路径连接。

换句话说,一个任何没有简单环路的连通图都是一棵树。

给你一棵包含  个节点的树,标记为  到  。给定数字  和一个有  条无向边的 edges 列表(每一个边都是一对标签),其中  表示树中节点  和  之间存在一条无向边。

可选择树中任何一个节点作为根。当选择节点  作为根节点时,设结果树的高度为  。在所有可能的树中,具有最小高度的树(即,min(h))被称为 最小高度树 。

请你找到所有的 「最小高度树」 并按 「任意顺序」 返回它们的根节点标签列表。

树的 「高度」 是指根节点和叶子节点之间最长向下路径上边的数量。

示例 1:

输入:n = 4, edges = [[1,0],[1,2],[1,3]]输出:[1]解释:如图所示,当根是标签为 1 的节点时,树的高度是 1 ,这是唯一的最小高度树。

示例 2:

输入:n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]输出:[3,4]

提示:

  • 所有  互不相同
  • 给定的输入保证是一棵树,并且不会有重复的边

树形 DP

这是一道树形 DP 模板题。

当确定以某个点为根节点时,整棵树的形态唯一固定,不妨以编号为  的节点作为根节点进行分析。

假设当前处理到的节点为 u,其是从父节点 fa 遍历而来,且将要遍历的子节点为 j

即树的形态如图所示(一些可能有的出边用虚线表示):

「树形 DP 问题通常将问题根据「方向」进行划分」

对于当前处理到的节点 u 而言,我们根据是否考虑「从 fa 到 u 的出边」将其分为「往上」和「往下」两个方向。

假设我们可以通过 DFS 预处理出  数组和  数组:

  •  代表在以  号点为根节点的树中,以 u 节点为子树根节点时,往下的最大高度
  •  代表在以  号点为根节点的树中,以 u 节点为子节点时,往上的最大高度

那么最终以 u 为根节点的最大高度为 

 只需要简单的 DFS 即可处理出来。对于  而言,其同样包含「往上」和「往下」两部分:

  • 对于经过 fa 后接着往上的部分有 
  • 对于经过 fa 后转而往下的部分,我们需要考虑「fa 节点往下的最大值 」是否由 u 节点参与而来进行分情况讨论:
    • 如果  本身不由 u 参与,那么  应当是 fa 节点往下的最大值  而来( 代表加上 fa 到 u 的边)
    • 如果本身 fa 往下的最大值由 u 节点参与,此时应当使用 fa 往下的次大值  来更新 

因此我们需要对  数组进行拆分,拆分为记录「最大值的  数组」和记录「次大值的  数组(注意这里的次大值是非严格的次大值)」,同时使用  数组记录下取得  时 u 的子节点 j 为何值。

实现上,在处理「往上」方向的 DFS 时,为避免对 fa 节点为空的处理,我们可以将「用 fa 来更新 u」调整为「用 u 来更新 j」。

Java 代码:

classSolution{int N = 20010, M = N * 2, idx = 0;int[] he = newint[N], e = newint[M], ne = newint[M];int[] f1 = newint[N], f2 = newint[N], g = newint[N], p = newint[N];voidadd(int a, int b){        e[idx] = b;        ne[idx] = he[a];        he[a] = idx++;    }public List<Integer> findMinHeightTrees(int n, int[][] edges){        Arrays.fill(he, -1);for (int[] e : edges) {int a = e[0], b = e[1];            add(a, b); add(b, a);        }        dfs1(0, -1);        dfs2(0, -1);        List<Integer> ans = new ArrayList<>();int min = n;for (int i = 0; i < n; i++) {int cur = Math.max(f1[i], g[i]);if (cur < min) {                min = cur;                ans.clear();                ans.add(i);            } elseif (cur == min) {                ans.add(i);            }        }return ans;    }intdfs1(int u, int fa){for (int i = he[u]; i != -1; i = ne[i]) {int j = e[i];if (j == fa) continue;int sub = dfs1(j, u) + 1;if (sub > f1[u]) {                f2[u] = f1[u];                f1[u] = sub;                p[u] = j;            } elseif (sub > f2[u]) {                f2[u] = sub;            }        }return f1[u];    }voiddfs2(int u, int fa){for (int i = he[u]; i != -1; i = ne[i]) {int j = e[i];if (j == fa) continue;if (p[u] != j) g[j] = Math.max(g[j], f1[u] + 1);else g[j] = Math.max(g[j], f2[u] + 1);            g[j] = Math.max(g[j], g[u] + 1);            dfs2(j, u);        }    }}
  • 时间复杂度:
  • 空间复杂度:

补充

可能会初次接触「树形 DP」的同学不太理解,这里再补充说明一下。

归根结底,以  u 为根节点的最大深度,必然是下面三种情况之一(往下、往上 和 往上再往下)。

其中对  数组的拆分(变为  和 )以及记录取得  对应的子节点 ,目的都是为了能够正确统计「往上再往下」的情况(统计该情况时,不能考虑从 fa 经过 u 的路径,因此需要记录一个非严格的次大值 )。

最后

巨划算的 LeetCode 会员优惠通道目前仍可用 ~

使用福利优惠通道 leetcode.cn/premium/?promoChannel=acoier,年度会员 有效期额外增加两个月,季度会员 有效期额外增加两周,更有超大额专属 🧧 和实物 🎁 福利每月发放。

我是宫水三叶,每天都会分享算法知识,并和大家聊聊近期的所见所闻

欢迎关注,明天见。