程序员老鬼

大厂加班强度表汇总,网友:有点准。。

刚刷到一个网友吐槽大厂加班强度的图表,密密麻麻写着各大厂的“加班到几点”,不少人看了直呼太准了

Image

我觉得这事吧,说到底反映的是职场的性价比问题。

图上那些强度高的公司,薪资确实也不低,问题是很多人只看到“名声响+工资高”,没想到“代价”也成正比。

不过话说回来,大厂的加班文化也不是一天形成的。有时不是你一个人想“躺”,是你不躺别人也躺不了。从这个角度看,不是员工“卷”,而是整个系统在推人去卷。

总的来说,选择哪种强度、拿多少薪资,都是自己的权衡,但千万别被光鲜外表蒙了眼。能撑住的拼,撑不住的换,人生这场职场副本,总得玩得明白点。【备注:文末可领最新资料】

算法题:编码最短长度的字符串

这个“编码最短长度的字符串”的题,说白了其实就是典型的最小覆盖问题,也有点像字符串压缩的升级版,但这玩意儿坑多得一批。很多面试题里会绕来绕去,其实核心就俩字:状态压缩 + 记忆化搜索,或者高级一点就直接上动态规划。

题意通常是这样的:你有一堆字符串(比如 ["catg","ctaagt","gcta","ttca","atgcatc"]),你要找一个最短的字符串,把这些子串都包含进去(每个子串只能用一次),并且尽量“无缝衔接”它们。听起来是不是像极了某些大厂面试官的“奇葩需求”?😂

这玩意儿其实跟旅行商问题(TSP)非常像,你可以把每个字符串看作一个城市,两两之间计算“重叠”部分,转化成图,然后搞一把“最短路径”把这些字符串串起来。思路确实清晰,但实现起来嘛,稍微不注意就内存爆炸💥

上干货,直接上代码(Java写的):

publicclassShortestSuperstring{
public String shortestSuperstring(String[] words){
int n = words.length;
int[][] overlap = newint[n][n];

// 预处理:计算重叠长度
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (i != j) {
int m = Math.min(words[i].length(), words[j].length());
for (int k = m; k >= 0; k--) {
if (words[i].endsWith(words[j].substring(0, k))) {
                            overlap[i][j] = k;
break;
                        }
                    }
                }
            }
        }

// dp[mask][i] 表示访问了mask中所有单词,以i结尾的最短superstring长度
int[][] dp = newint[1 << n][n];
int[][] path = newint[1 << n][n]; // 记录路径
for (int[] row : dp) Arrays.fill(row, Integer.MAX_VALUE / 2);

for (int i = 0; i < n; i++) {
            dp[1 << i][i] = words[i].length();
        }

for (int mask = 1; mask < (1 << n); mask++) {
for (int u = 0; u < n; u++) {
if ((mask & (1 << u)) == 0) continue;
for (int v = 0; v < n; v++) {
if ((mask & (1 << v)) != 0) continue;
int nextMask = mask | (1 << v);
int val = dp[mask][u] + words[v].length() - overlap[u][v];
if (val < dp[nextMask][v]) {
                        dp[nextMask][v] = val;
                        path[nextMask][v] = u;
                    }
                }
            }
        }

// 最小长度字符串的最后一个单词索引
int min = Integer.MAX_VALUE;
int last = -1;
int finalMask = (1 << n) - 1;
for (int i = 0; i < n; i++) {
if (dp[finalMask][i] < min) {
                min = dp[finalMask][i];
                last = i;
            }
        }

// 回溯构造路径
        List<Integer> res = new ArrayList<>();
int mask = finalMask;
while (mask > 0) {
            res.add(last);
int temp = mask;
            mask ^= (1 << last);
            last = path[temp][last];
        }
        Collections.reverse(res);

// 拼接字符串
        StringBuilder sb = new StringBuilder(words[res.get(0)]);
for (int i = 1; i < res.size(); i++) {
int o = overlap[res.get(i - 1)][res.get(i)];
            sb.append(words[res.get(i)].substring(o));
        }
return sb.toString();
    }
}

讲真,这个写法不复杂,但坑点不少,比如状态压缩的 mask 操作、路径回溯,以及拼接的时候的重叠计算,一不小心就会写成个“变异版贪吃蛇”。

这个题让我想起当年实习的时候,接了个需求是做日志压缩。当时天真地以为“用个zip不就完了?”。结果需求是“要能按字段合并相邻重复数据”,听起来就像“压缩字符串”+“不丢信息”。最后我也是拿状态转移表+滑窗搞了一晚上的逻辑,第二天早上起来发现测试同事说跑了4小时还没结束...内存直接吃爆😂

所以说,别小看这些看起来像“面试套路题”的玩意儿,它们真的是有实战意义的——尤其是那种复杂数据合并、压缩、去重之类的需求,这种动态规划+图论混合策略真的能救命

最后,我为大家打造了一份deepseek的入门到精通教程,完全免费:https://www.songshuhezi.com/deepseek

-END-

最后给大家分享一份不错的副业资料,感兴趣的同学可以链接我,微信:hls404 找我领取。