做决定的时候,谁心里没盘算着找个“天花板”级别的解法呢?找路要最快,存硬盘要最省,敲代码最好连眉头都不皱一下。但现实嘛。你非要死盯一个指标硬磕,别的方面立马跟着崩盘。我最近重翻克努特那本《计算机程序设计艺术:基本算法》,发现这老爷子翻来覆去就捣鼓一个理儿:算法这玩意儿,压根就没打算追求什么绝对的最优。说白了,它就是在预算、时间、算力全被卡得死死的条件下,硬生生抠出来的一个“差不多能跑”的平衡点。这事儿大概就是这么个意思。别较真。
道理其实挺直白。你要非在数学题里死磕绝对最优,计算量分分钟指数级爆炸;可落到真枪实弹的物理世界,那套“完美解”基本是个伪命题。书里拿二分查找和线性查找做了个对照。假设你手里有十万条乱七八糟的数据,线性查找只能老老实实挨个儿翻,二分查找呢,理论上只要走大约17次(log2(100000))就能定位。听着挺唬人是吧?但克努特马上给你兜头浇盆冷水:二分查找有个铁律,数据必须先排好序。为了维持这点秩序,你往里插条新数据、删条旧数据,光是挪动和排序的开销就能把你累趴。要是你这表天天增删改,二分查找那点速度优势,早被底层维护成本吞得连渣都不剩。我觉得吧。别光盯着某一步跑得快不快。得把前后账本摊开算。没有哪招是孤立的快,只有整体算下来划不划算。
这种“算总账”的套路,在工程圈里简直太常见了。我见过太多团队为了死磕所谓的“代码洁癖”,一头扎进过度设计的坑里出不来。架构师天天憋着劲重构底层,非要搞什么零冗余、理论上的最优时间复杂度,结果呢?项目一拖再拖,隔壁竞品早就把市场窗口捂热了。反倒是一些懂得在“赶紧上线验证”和“以后慢慢维护”之间敢踩刹车的团队,反而活得久。克努特当年打磨第三版的时候,硬是往里塞了数十项基础技术,还把那些干巴巴的数学预备知识重新捋了一遍。说实话,这操作本身就透着股向现实低头的无奈:理论模型画得再圆,也得给工程实践让道。他写这本书,真不是冲着发纯数学论文去的,就是教人怎么在泥地里踩实步子,一步步往前铺路。
这套逻辑在资源紧巴巴的地方,确实好使。但你要直接把它生搬硬套到个人成长或者搞创作上,我敢打赌,立马水土不服。算法算账,靠的是时间、空间、内存这些能称斤论两的硬指标。可人的精力、情绪、灵感,哪样能拿尺子量准?你非要用“性价比”去盘算一次周末的深度阅读,或者拿“投入产出比”去规划一段长期关系,算法那套框架绝对会直接卡壳。因为有些东西的价值,偏偏就长在那些“不划算”的冗余和看似瞎折腾的过程里。我觉得克努特这套框架确实够冷,它默认你的目标是铁板一块、边界清清楚楚。可现实里,人自己的目标本来就在晃悠,权衡的尺子自然也就跟着飘了。未必所有事都能这么算。
我倒觉得,真正让人头秃的,压根不是找不到最优解,而是咱们总习惯把“做取舍”直接等同于“认怂放弃”。书里拎出来的链表和数组,压根没谁绝对碾压谁,全看场合。链表放弃了随机访问的快,换来了动态插入的活络;数组死磕连续内存,博的就是那个缓存命中率。它们说白了,都在自己的地盘里把活儿干到了极致。人做选择其实也一个德行。认下“这玩意儿不够完美”,真不是给自己找台阶降标准,而是把手里那点力气,从幻想里的全能神身上拽下来,掰开揉碎地拿去解决眼下的具体问题。
所以下回再为“选A还是选B”抓耳挠腮的时候,不如换个问法:我愿意为哪个结果,硬扛什么代价。算法这东西从来不画大饼承诺奇迹,它只管把不确定性老老实实塞进已知的框框里。把限制看明白,认了这堆权衡,剩下的全交给动手去干。能在条条框框里蹚出条路的,从来不是脑子转得最快的,而是心里最清楚自己在掂量什么的明白人。未必什么事儿都得算到小数点后两位,有时候,认了不完美,反而能走得更稳。