🔗 🟡 2058. Find the Minimum and Maximum Number of Nodes Between Critical Points 1311

tags: Weekly Contest 265 鏈結串列(Linked List)

題意

鏈結串列(Linked List) 中, 臨界點(critical point) 被定義為 局部最大值(local maxima)局部最小值(local minima)

  • 如果當前節點的值嚴格大於前一個節點和下一個節點,則該節點是 局部最大值(local maxima)
  • 如果當前節點的值嚴格小於前一個節點和下一個節點,則該節點是 局部最小值(local minima)
  • 但需要注意的是,一個節點只有在存在前一個節點和下一個節點的情況下,才可能是 局部最大值/最小值

給定一個 鏈結串列(Linked List) 的頭節點 head\text{head},返回一個長度為2的陣列 [minDistance,maxDistance][\text{minDistance}, \text{maxDistance}],其中 minDistance\text{minDistance} 是任意兩個不同臨界點之間的最小距離,maxDistance\text{maxDistance} 是任意兩個不同臨界點之間的最大距離。如果臨界點少於2個,則返回 [1,1][-1, -1]

思路:維護第一個和最後一個臨界點的索引

根據題意,我們需要計算臨界點之間的 minDistance\text{minDistance}mn=maxDistancemn = \text{maxDistance} 。而 maxDistance\text{maxDistance} 就是第一個和最後一個臨界點之間的距離;而 minDistance\text{minDistance} 則是任意兩個不同臨界點之間距離的最小距離。因此,我們只需要維護第一個臨界點的索引 first\text{first} 和最後一個臨界點的索引 last\text{last} 即可。

idxidx 表示當前節點的索引、preprecurcur 分別指向前一個節點和當前節點。初始化 first\text{first}last\text{last}1-1mnmn 為正無窮大。遍歷鏈結串列,若當前節點為臨界點:

  • 如果是第一個臨界點,更新 firstfirst 為當前索引。
  • 否則更新 mn=min(mn,idxlast)mn = \min(mn, \text{idx} - \text{last})
  • 然後更新 lastlast 為當前索引。

遍歷結束後,若找到了至少兩個臨界點,則返回 [mn,lastfirst][\text{mn}, \text{last} - \text{first}];否則返回 [1,1][-1, -1]

複雜度分析

  • 時間複雜度:O(n)\mathcal{O}(n),其中 nn 為鏈結串列的長度。
  • 空間複雜度:O(1)\mathcal{O}(1)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution:
def nodesBetweenCriticalPoints(self, head: Optional[ListNode]) -> List[int]:
pre, cur = None, head
first = last = -1
mn = float('inf') # min distance
idx = 0
while cur and cur.next:
if pre is not None and (pre.val < cur.val > cur.next.val or pre.val > cur.val < cur.next.val):
if first == -1:
first = idx
else:
mn = min(mn, idx - last)
last = idx
pre, cur = cur, cur.next
idx += 1
return [mn, last - first] if mn != float('inf') else [-1, -1]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
vector<int> nodesBetweenCriticalPoints(ListNode* head) {
ListNode *pre = nullptr, *cur = head;
int first = -1, last = -1;
int mn = INT_MAX; // min distance
int idx = 0;
while (cur && cur->next) {
if (pre != nullptr && (pre->val < cur->val && cur->val > cur->next->val || pre->val > cur->val && cur->val < cur->next->val)) {
if (first == -1) first = idx;
else mn = min(mn, idx - last);
last = idx;
}
pre = cur;
cur = cur->next;
idx++;
}
return mn != INT_MAX ? vector<int>{mn, last - first} : vector<int>{-1, -1};
}
};

寫在最後

Cover photo is remixed from @吃肥皂泡泡, thanks for their work!