置頂

我的 VPython 教學文件 (HackMD 版本)

VPython 教學文件目錄 安裝及測試 基本語法 等速度直線運動 自由落下 終端速度 水平抛射 使用For迴圈計算水平抛射資料 斜向抛射 圓周運動 簡諧運動 單擺 木塊彈簧系統分離 重力及簡諧 行星運動 相疊木塊 雙重簡諧運動 一維彈性碰撞 ...

熱門文章

2026年8月31日 星期一

LeetCode 解題筆記:2058. Find the Minimum and Maximum Number of Nodes Between Critical Points

作者:王一哲
日期:2026年8月31日


LeetCode 題目連結:2058. Find the Minimum and Maximum Number of Nodes Between Critical Points

解題想法


中等難度題。題目一個鏈結串列的開頭節點 $head$,如果鏈結串列之中某個節點的值同時大於前、後節點的值,或是同時小於前、後節點的值,這樣的節點稱為關鍵點 (critical point),鏈結串列頭、尾的節點不會是關鍵點。題目要回傳兩個關鍵點的最小與最大距離,如果只有1個或沒有關鍵點,無法取距離,回傳 $[-1, -1]$。

可以先建立一個節點 $pre$ 指向 $head$,另一個走訪用的虛擬節點 $dummy$ 指向 $head.next$,再用一個 while 迴圈走訪所有的節點,如果還有 $dummy.next$ 繼續執行。再建一個陣列 $pos$ 儲存關鍵點的位置,用變數 $imin$ 儲存最小的距離,$step$ 儲存目前的節點與 $head$ 的距離。每次執行 while 迴圈時,先檢查這個節點的值是否同時大於 $pre$ 或 $dummy.next$ 的值,或是同時小於 $pre$ 或 $dummy.next$ 的值,如果 $pos$ 已經有資料,檢查 $step - pos[-1]$ 是否是新的最小值,再將 $step$ 加入 $pos$。如果最後 $pos$ 長度小於 2,回傳 $[-1, -1]$;反之,回傳 $[imin, pos[-1] - pos[0]]$。

Python 程式碼


Runtime: 65 ms, beats 90.43%. Memory: 63.25 MB, beats 23.68%.
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def nodesBetweenCriticalPoints(self, head: Optional[ListNode]) -> List[int]:
        pre = head  # 前一個節點,先指向 head
        dummy = head.next  # 走訪用的虛擬節點,先指向 head.next
        step = 0  # 目前節點與 head 的距離
        pos = []  # 關鍵節點與 head 的距離
        imin = float('inf')  # 最矩距離
        while dummy.next:  # 如果有 dummy.next 繼續執行
            step += 1
            # 檢查 dummy 是否同時比前、後節點小或同時比前、後節點大
            if (pre.val > dummy.val and dummy.next.val > dummy.val) or (pre.val < dummy.val and dummy.next.val < dummy.val):
                if pos: imin = min(imin, step - pos[-1])  # 如果 pos 已經有資料,更新 imin
                pos.append(step)  # 加入 step
            pre = dummy  # pre 指向現在的 dummy
            dummy = dummy.next  # dummy 指向下一格
        
        # 如果關鍵節點不到 2 個,無法取距離,回傳 [-1, -1]
        if len(pos) < 2:
            return [-1, -1]
        else:  # 可以找距離,最遠距離為 pos 兩端
            return [imin, pos[-1] - pos[0]]


C++ 程式碼


Runtime: 6 ms, beats 36.54%. Memory: 128.34 MB, beats 39.79%.
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    vector<int> nodesBetweenCriticalPoints(ListNode* head) {
        ListNode* pre = head;  // 前一個節點,先指向 head
        ListNode* dummy = head->next;  // 走訪用的虛擬節點,先指向 head.next
        int step = 0, imin = 100000;  // 目前節點與 head 的距離,關鍵節點最短距離
        vector<int> pos;  // 關鍵節點與 head 的距離
        while(dummy->next != nullptr) {  // 如果有 dummy->next 繼續執行
            step++;
            // 檢查 dummy 是否同時比前、後節點小或同時比前、後節點大
            if ((pre->val > dummy->val && dummy->next->val > dummy->val) || 
                (pre->val < dummy->val && dummy->next->val < dummy->val)) {
                if (!pos.empty() && step - pos.back() < imin) {  // 如果 pos 已經有資料
                    imin = step - pos.back();
                }
                pos.push_back(step);  // 加入 step
            }
            pre = dummy;  // pre 指向現在的 dummy
            dummy = dummy->next;  // dummy 指向下一格
        }
        
        // 輸出答案
        int m = (int)pos.size();
        if (m < 2) {  // 如果關鍵節點不到 2 個,無法取距離,回傳 {-1, -1}
            return {-1, -1};
        } else {  // 可以找距離,最遠距離為 pos 兩端
            return {imin, pos[m-1] - pos[0]};
        }
    }
};


沒有留言:

張貼留言