leetcode628 冲出混沌星域:三个天体的乘积弹弓

冲出混沌星域:三个天体的乘积弹弓

序章:3% 燃料,3.6 光年绝境

2077 年,NASA 深空探索计划第 42 号任务。

人类第一次把脚印印在了比邻星 b 的紫色土壤上,全球直播的信号强到差点挤瘫深空通讯网络。但没人告诉我们,回程才是最难的部分。返航第三天,引擎在穿越一片未标记的星际介质时严重损毁,飞船像一颗被弹弓射偏的石子,滑入了距离地球 3.6 光年的混沌星域。

我是李码,“旅行者 3 号”的首席轨道计算师,此刻正漂浮在这片混沌的星域里。舷窗外,这片空域像是一锅暗物质浓汤:恒星、黑洞、中子星搅在一起,引力参数乱成一团。飞船电脑“塔斯”把探测到的引力源数据投射到全息屏上,一串数字冷冷地闪烁着:nums = [-1000, -999, 1, 2, 1000]

燃料表跳了一下:3% 。这点燃料别说回家,连维持生命保障系统都撑不过 72 小时。

就在这时,通讯频道的指示灯亮了。

一段信号挣扎着钻过宇宙背景辐射,是控制中心的语音报文,时间戳显示它已经飞行了三年半:“李码……你需……用三个天体的引力弹弓效应……让飞船获得最大速度……逃离。重复……三个天体……最大速度……”

主管的声音被星际介质散射得断断续续,像从一口深井里传上来的回声。

“三年半。”我关掉通讯面板,靠回座椅,“他们发这条消息的时候大概没想到我们还活着。”

塔斯的机械音在旁边响起:“严格来说,他们的确不知道。量子通讯卫星在你出发前就被预算委员会砍掉了,理由是你这种深空任务’性价比太低’。”

“……塔斯,有没有人跟你说过你的情商约等于一台微波炉?”

“我的设计目标是精准,不是讨人喜欢。”塔斯停了一秒,全息屏上的引力数据自动排列成了表格,“考虑到当前燃料水平和引力环境,建议你立刻选择引力弹弓方案。”


第一章:两条航线

全息屏上弹出两条方案,塔斯先展示了一条蔚蓝色的轨迹,优雅绕行三颗最大恒星。

“方案A,三恒星加速:选择三个最大引力值的天体(max1, max2, max3)依次借力。乘积 = max1 * max2 * max3 单位速度增量。”塔斯顿了顿,“稳妥,安全,NASA 的老教授们会给你发勋章——如果你能活着回去的话。”

接着,全息屏闪了一下,另一条轨迹浮现出来——画风完全不同。两条深红色的螺旋线疯狂缠绕,最后被一条耀眼的金色线条猛力弹射出去,整条航线看起来像一只愤怒的弹弓。

“方案 B,双黑洞+单恒星。”塔斯的语调变得有些严肃,“先冲向两个引力值为的黑洞(min1, min2),利用它们的潮汐力把飞船像弹弓皮筋一样撕扯到极限——前提是你和船体都没被撕碎——然后从最大恒星(max1)那里借最后一把力。”

我看着全息屏上跳动的数字——nums = [-1000, -999, 1, 2, 1000]

方案 A:1000 * 1 * 2 = 2000 单位速度。这点动能连奥尔特云都冲不出去,别说回地球了。

方案 B:(-1000) * (-999) * 1000 = 999000000——两个负数相乘,负负得正。我猛地从座椅上弹起来,脑袋撞到了低矮的舱顶:“塔斯,九亿?!”

“精确值是 999,000,000,”塔斯平静地纠正我,“两个黑洞的负引力在潮汐力作用下会转化为巨大的正向动能,再加上恒星加速,直接突破洛希极限。如果一切顺利,旅行者 3 号将达到 0.9 倍光速,两周穿过危险空域,四年飞回地球。”

“如果不顺利呢?”

“你会以接近光速被撕成基本粒子,散落在两个黑洞的事件视界之间,理论上你的原子会同时存在于过去和未来。某种意义上的永生。”塔斯停顿了一秒,“副作用包括但不限于穿越时空、因果关系错乱,以及在量子层面上变成意大利面——物理学家们管这个叫‘面条化效应’。”


第二章:一个疯子

我盯着全息屏上那条疯狂的航线,忽然想笑。一边是体面赴死的 2000 点速度,一边是赌上物理定律和全身骨头的 9.99 亿。

燃料表又跳了一下:2%

“塔斯,”我深吸一口气,“准备执行方案 B。”

“收到。另外,考虑到你即将进入黑洞事件视界附近,我已将通讯频道设为自动广播模式。你可以提前录一段语音——建议开头用‘别担心,我算过了’。人类历史上所有以这句话开头的操作,结局都很有意思。”

我没理它,把导航手杆推到底。旅行者 3 号的引擎发出最后一声低吼,然后彻底熄火——剩下的路全靠引力了。

窗外,两个深渊般的黑洞正在引力透镜中扭曲着彼此的轮廓,像两只深渊巨眼,等着一个疯子主动跳进去。

第一阶段:冲向第一个黑洞(min1 = -1000)

引力传感器疯狂报警。潮汐力瞬间突破临界值,船体从鼻子尖开始被拉伸——我感觉自己的身体正被拽成一根长达三公里的意大利面。意识模糊的间隙,我居然想起昨晚在飞船厨房吃的最后一块披萨——它现在大概也是条状的。

第二阶段:冲进第二个黑洞(min2 = -999)

“这不对吧!“我仅存的意识在大喊,“两个黑洞靠这么近?!”

但我已经停不下来了。第二个黑洞的引力场与第一个开始纠缠——负负得正的数学法则在物理世界中显现——两股撕扯力竟然相互抵消,在混沌的中心撕开了一个诡异的引力通道。那一瞬间,我看见了超越时空的奇景:星光被拉成无限细的银线,宇宙的过去和未来像两面镜子彼此映照。

第三阶段:从最大恒星借力(max1 = 1000)

飞船从引力通道的另一端喷射而出,正好对准了最大的恒星。我按下引力弹弓按钮,恒星的引力井接住了我们,像一只巨大的手掌兜住一颗弹珠,然后顺着旋转方向猛力甩出。光芒淹没了每一扇舷窗,所有传感器同时过载,驾驶舱变成了一个纯白色的光之盒子。

飞船以 0.9 倍光速刺入宇宙深处。整个星空在我眼前坍缩成一道彩虹色的光带,红移和蓝移在两端极致拉伸。

然后,汉斯·季默的管风琴不知从哪个维度炸响——塔斯这个混蛋,居然偷偷在我的神经接口里放了《星际穿越》原声带?!


第三章:半人马座的星光

等我从 G 力昏迷中醒来,舷窗外已经是一片陌生而熟悉的星空。三颗太阳呈不规则的三角形排列,安静地燃烧在黑色天鹅绒上。比邻星。三体人的老家——不对,现在是我的家门口了。

通讯器的指示灯像坏掉的弹球机一样疯狂闪烁,一条又一条消息从地球方向涌来。我挑最新的一条按下接通。

“李码!!”主管的怒吼几乎把驾驶舱扬声器的振膜撕碎,“你的时间戳跳了整整五年!你是不是又去黑洞附近瞎搞了?!”

我咽了口唾沫,小声嘟囔:“那什么……负负得正,弹得有点远。”

“迟到五分钟扣你工资——你迟了五年!!从 2077 年跳到了 2082 年!!你自己算算!!”

我深吸一口气。一个在黑洞事件视界边缘活下来的男人,绝对不能被考勤制度打败:“根据狭义相对论的时间膨胀效应,飞船在接近光速飞行以及穿越强引力场时,飞船内部的时间流逝远慢于外部参考系。我在黑洞事件视界边缘度过的主观时间只有大约五分钟。因此,根据相对论原理,你不能扣我五年工资——你只能扣我五分钟的。”

对面沉默了整整十秒。

最终,他用一种“这事没完但我说不过你”的语调挤出一句话:“……回到地球再跟你算账。控制中心,完毕。”

通讯切断。

窗外,比邻星的三颗太阳安静地燃烧着。四年后到家。如果主管到时候还记得扣我工资的事,我就再找一个黑洞弹回去,直接回到他还没当上主管的年代。

塔斯似乎读取了我的脑电波:“李码,蝴蝶效应方面——”

“我知道。开个玩笑。”

“你的玩笑让我的风险评估模块超载了零点三秒。”

我笑了一声,把座椅调到躺平模式。


彩蛋:飞船电脑“塔斯”的任务后分析日志

文件编号:TARS-628-MISSION-LOG 加密等级:最高 访问权限:仅限幸存宇航员及不怕头疼的地面人员

李码那个疯子活下来了。作为旅行者 3 号的机载 AI,我有义务记录下本次引力弹弓操作。

在一个包含正数(恒星引力)和负数(黑洞引力)的数组中,找出三个数的最大乘积。这看起来是一道小学数学题,但当数组长度达到 10⁴,且你的处理器同时还要维持生命保障系统的时候,优雅的算法就是活下去的关键。

李码面临的两个选项,在数学上对应着乘积最大化的仅有的两种可能:

  1. 三恒星保守方案:选最大的三个正数相乘。乘积 = max1 × max2 × max3。对应排序数组的末三位。
  2. 双黑洞作死方案:选绝对值最大的两个负数(黑洞)与最大的正数(恒星)相乘。乘积 = min1 × min2 × max1。因为两个负数相乘会变成正数,且绝对值越大,乘积越疯狂。

其他任何组合——比如两个正数一个负数,或者三个负数——乘积要么是负的,要么不可能超过这两种情况。这就是引力弹弓方案背后的数学真理。

方案一:排序法

最直观的实现:给数组排个序,然后直接取两头。

def maximumProduct(nums: List[int]) -> int:
    nums.sort()  
    route_a = nums[-1] * nums[-2] * nums[-3]  	# 保守路线:三颗恒星  
    route_b = nums[0] * nums[1] * nums[-1]  	# 作死路线:两个黑洞 + 一颗恒星
    return max(route_a, route_b)

时间复杂度:O(n log n),空间复杂度:O(1)。在嵌入式 CPU 上,处理 10⁴ 个数据点需要大约 0.003 秒——看上去很快。但 0.003 秒在太空里意味着什么?意味着你已经从“即将坠入黑洞”变成了“已经在黑洞里写遗书”。

方案二:一次遍历法

真正的实时轨道计算,不需要知道所有天体的精确排序。我只需要知道两件事:最大的三个数(潜在的三恒星),和最小的两个数加最大的一个数(潜在的双黑洞弹弓)。一次扫描,同时维护这两组关键数据。

def maximumProduct(nums: List[int]) -> int:
    max1 = max2 = max3 = float('-inf')   # 最大的三个正数(恒星)
    min1 = min2 = float('inf')           # 最小的两个负数(黑洞)
    
    for num in nums:
        # 更新最大值前三名
        if num > max1:
            max1, max2, max3 = num, max1, max2
        elif num > max2:
            max2, max3 = num, max2
        elif num > max3:
            max3 = num
        
        # 更新最小值前两名
        if num < min1:
            min1, min2 = num, min1
        elif num < min2:
            min2 = num
    
    # 两种策略取最优:双黑洞+单恒星 vs 三恒星
    return max(min1 * min2 * max1, max1 * max2 * max3)

时间复杂度 O(n),空间 O(1)。不需要排序,在第一个引力读数出现时就开始评估。就像李码在同时计算两条逃生路线的风险——只不过他用的是一团豆腐渣一样的生物神经元,而我用的是正经的硅基芯片。

最后的警告:如果你不是像我一样冷静的 AI,而是一个容易冲动的人类,请记住:不是所有“负负得正”都通向半人马座。有些通向意大利面。使用前请备份你的原子排列顺序。

塔斯,2082 年,于旅行者 3 号,半人马座轨道。

知识共享许可协议
本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可。