程序员老鬼

辛辛苦苦攒了300万,辞职全职投资,全仓买入ETH,亏掉60%只剩120万了,怎么办?不想上班,还能继续躺平吗?

这哪是躺平啊,这是把床搬到火山口上了。

辛辛苦苦攒了300万,辞职不干了,想着全职投资,结果一把全仓ETH,亏到只剩120万。说真的,这事最扎心的不是亏钱,是他还在问“还能不能继续躺平”。

投资本来就有波动,全仓一个币,还没工资现金流兜底,这不叫自由职业,叫裸奔。

Image

不想上班我能理解,谁爱上班啊。但躺平也得有躺平的本钱。300万的时候可能还有点余地,120万再继续硬扛,心态先崩。每天盯盘,涨了幻想回本,跌了怀疑人生,比上班还累。

这时候最该想的不是“怎么翻盘”,而是先别让自己再被市场教育一遍。打工人看完血压都上来了,真的。

面试题:访问所有节点的最短路径

这题第一眼别去想什么最短路模板,也别急着 Floyd。 “访问所有节点”这几个字很容易把人带偏,以为要找一条真的路径。其实代码里要抓的是两个东西:人现在在哪个点,已经踩过哪些点。

题目是:给你一个无向图,从任意节点出发,可以重复走边,问最少走多少步,能把所有节点都访问到。

我一般看到这种“所有节点 + 最短步数”,会先怀疑状态压缩 BFS。因为普通 BFS 只记录当前节点不够,比如都走到 3 号节点,一个路径访问过 0、1、3,另一个路径访问过 2、3,这俩状态完全不是一回事。

状态写成这样:

int state = 1 << node;

比如有 4 个节点,1011 表示访问过 0、1、3。

队列里不能只放节点,要放:

当前位置 node
访问状态 mask
当前步数 step

所有节点都访问过时,mask 应该等于:

int finish = (1 << n) - 1;

这里有个小细节,起点不是固定的。题目允许从任意节点出发,所以 BFS 初始化时,要把所有节点都塞进去。这个地方少写一步,结果就会绕远。

完整代码我一般这么写,别搞太复杂:

import java.util.*;

classSolution{
publicintshortestPathLength(int[][] graph){
int n = graph.length;
if (n <= 1) return0;

int finish = (1 << n) - 1;
boolean[][] seen = newboolean[n][1 << n];
        ArrayDeque<int[]> queue = new ArrayDeque<>();

for (int i = 0; i < n; i++) {
int mask = 1 << i;
            queue.offer(newint[]{i, mask, 0});
            seen[i][mask] = true;
        }

while (!queue.isEmpty()) {
int[] cur = queue.poll();
int node = cur[0];
int mask = cur[1];
int step = cur[2];

for (int next : graph[node]) {
int nextMask = mask | (1 << next);

if (nextMask == finish) {
return step + 1;
                }

if (seen[next][nextMask]) {
continue;
                }

                seen[next][nextMask] = true;
                queue.offer(newint[]{next, nextMask, step + 1});
            }
        }

return -1;
    }
}

这段代码里最关键的是 seen[next][nextMask]。 不是防止某个节点重复访问,而是防止“同一个节点 + 同一份访问记录”重复进队列。

举个很小的图:

graph = [[1,2,3],[0],[0],[0]]

从 0 出发未必最优,因为你要访问三个叶子节点,来回折返。BFS 把 0、1、2、3 都作为起点一起推进,谁先凑齐全部节点,谁就是最短答案。

这题的节点数通常不大,否则状态压缩直接炸。复杂度大概是:

节点数 n
状态数 2^n
总状态 n * 2^n

所以时间复杂度可以看成 O(n * 2^n + 边数 * 2^n),面试里说到这个程度够了。

我不太建议这题上来写 DFS 回溯。回溯会把“路径”枚举得很热闹,但你很难保证第一次找到的就是最短。BFS 的优势就在这里:一步一步往外扩,第一次访问到全集状态,步数肯定最短。

这题真正考的不是图论多深,而是你能不能把“走到哪个点”和“已经访问过哪些点”绑成一个状态。绑住了,剩下就是 BFS。