Python技术迷

某大厂员工吐槽:领导给我介绍私活,让我赚了65万,结果领导却要30万介绍费,我犹豫了,于是骗领导说只赚了48万,愿意给18万!我太机灵了!

刚刷到这个帖子,我第一反应就是,哥们你这不是机灵,你这是把职场整成二手交易平台了。

领导给你牵个私活,张口就要30万介绍费,这吃相也太猛了,饭还没上桌,账单先拍脸上。

Image

更逗的是楼主也没怂,立马把65万改口成48万,还主动报价18万,那个小算盘隔着屏幕都听见响了。你说他坏吧,也谈不上,主要是这事从头到尾就没一个人按正常路子来。一个敢介绍,一个敢接,一个敢要价,一个敢砍价,整得跟地下经纪人接头似的。最搞笑的是,楼主最后还来一句“我太机灵了”,给我看笑了,这哪是机灵,这明明是黑吃黑没吃明白。


算法题:火柴拼正方形

这题第一眼看着像回溯,真写起来,很多人会把搜索树写炸。

给一堆火柴,问你能不能拼成正方形。别急着 dfs 往里冲,我一般先做两件事:总长度不对,直接滚;单根火柴比边长还长,也别算了。这种题最烦的不是“不会”,而是明明方向对,结果重复状态太多,跑得像没刹车。

正方形四条边,设总长度是 s,那每条边必须是 target = s // 4。问题就变成:把这些火柴分到 4 个桶里,每个桶最后都正好等于 target。

这里有个很土但很好使的优化:先排序,长的先放。因为大数更容易把错误路线提前撞出来,剪枝更狠。另一个常见剪枝是:如果当前边和前一条边长度一样,就没必要重复试,状态完全重复。

代码我习惯这么写,干净一点:

from typing import List

classSolution:
defmakesquare(self, matchsticks: List[int]) -> bool:
if len(matchsticks) < 4:
returnFalse

        total = sum(matchsticks)
if total % 4 != 0:
returnFalse

        target = total // 4
        matchsticks.sort(reverse=True)

if matchsticks[0] > target:
returnFalse

        edges = [0, 0, 0, 0]

defdfs(i: int) -> bool:
if i == len(matchsticks):
return edges[0] == edges[1] == edges[2] == target

            cur = matchsticks[i]

for k in range(4):
if edges[k] + cur > target:
continue

if k > 0and edges[k] == edges[k - 1]:
continue

                edges[k] += cur
if dfs(i + 1):
returnTrue
                edges[k] -= cur

returnFalse

return dfs(0)

这段代码的判断顺序我比较在意。

先卡总和,再卡最大值,再倒序排序,然后才进递归。很多写法喜欢一上来就搜,逻辑上没错,但这种题数据一大,性能就开始难看。尤其你不做“相同边状态跳过”这个剪枝,四个桶来回试,实际上在做大量重复劳动。

拿 matchsticks = [1,1,2,2,2] 试一下,总和是 8,每条边 2。排序后是 [2,2,2,1,1]。前三根 2 直接各占一条边,后面两个 1 拼成最后一条边,正好能成。

再比如 [3,3,3,3,4],总和虽然是 16,看起来挺像那么回事,但最大值 4,边长也是 4,剩下四个 3 根本凑不出另外三条 4,这种回溯很快也会失败。

这题本质上不是“拼正方形”,就是个四桶装载问题。题不难,麻烦的是你得知道哪里该早点停,哪里不能重复试。同样是回溯,剪枝顺序不对,代码味道就不一样。