做完這道題的那個下午,我盯著測試用例發了好一會兒呆。
輸入是 [5,2,13,3,8],輸出變成 [13,8]。
被刪掉的 5、2、3,全都有一個共同點——它們右側存在一個比自己更大的數。
這道 LeetCode 第 2487 號題的任務很直白:給定一個單鏈表的頭節點,移除所有滿足“右側任意位置存在更大節點值”這一條件的節點,最后返回修改后的鏈表。
![]()
用題目給的例子來拆解,你會立刻理解它在干什么。
鏈表 5 → 2 → 13 → 3 → 8。
節點 13 位于 5 和 2 的右側,因此 5 和 2 必須移除。
節點 8 位于 3 的右側,因此 3 必須移除。
最終留下來的,只有 13 和 8。
這個規則的殘酷之處在于:一個節點能不能活下來,看的不是自己有多強,而是它身后有沒有更強的存在。一旦某個右側節點值更大,它就連帶被清除出場。
解題思路里最精彩的一步,是先把這個單向鏈表翻轉過來。
翻轉之后,原本復雜的“向后看”直接變成了“向前看”——你只需要從翻轉后的頭節點開始,維護一個當前遇到的最大值,凡是遇到比它小的節點,統統跳過;遇到更大的,就更新最大值并保留該節點。
遍歷完成后,再把處理好的鏈表翻轉一次,恢復到原本的順序。
代碼實現里定義了一個名為 reverList 的輔助函數,用于執行鏈表翻轉。主函數 removeNodes 的流程是三步走:
第一步,翻轉原鏈表,得到 reversList;
第二步,用 maxNode 和 prevNode 配合 currNode 遍歷翻轉后的鏈表,執行上述的“保留歷史最大值”過濾邏輯;
第三步,將過濾結果再次翻轉,作為最終答案返回。
這個過濾邏輯的 while 循環寫得極其克制:當 maxNode 的值大于 currNode 的值時,currNode 直接跳到下一個節點;否則,就把 maxNode 更新為 currNode,把 prevNode 的 next 指向 currNode,然后 prevNode 和 currNode 各自前進。
循環結束后,把 prevNode 的 next 設為 null,干凈收尾。
這道題真正讓我興奮的地方,不在于它考了鏈表反轉——那是基礎操作。它巧妙在那層“往前看”的思維翻轉:很多看起來需要反復回頭才能解決的問題,一旦你調轉方向,復雜度就當場降級。
2487 號題不會是你做過最難的鏈表題,但它很可能成為你面試時最想拿出來聊五分鐘的那一道。
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.