[Algorithm] Two pointers | Sliding Window

Two Pointers

收縮型 One Input, Opposite Ends (相反的兩端:[left → … ← right])

left 和 right 兩個 pointer
為 opposite ends (相反的兩端;起始於起點和終點,並越來越靠近)

Template

def fn(arr):
  ans = 0
  left, right = 0, len(arr) - 1

  while left < right:
    # do some logic here with left and right
        
    if CONDITION:
      left += 1
    else:
      right -= 1
    
  return ans

例題

平行型 Two Inputs, Exhaust Both (消耗兩者:[i → … ] [j → … ])

Template

def fn(arr1, arr2):
  i = j = ans = 0
  while i < len(arr1) and j < len(arr2):
    # do some logic here
    if CONDITION:
      i += 1
    else:
      j += 1
    
  while i < len(arr1):
    # do logic
    i += 1
    
  while j < len(arr2):
    # do logic
    j += 1
    
  return ans

例題

滑動型 Sliding Window ([left → … right → … ])

要訣

每當 sliding window 變動時,從零計算(重要資訊的)總體狀態 (O(n2))
從 sliding window 變動的左右邊界範圍計算差距
再得以併用舊的總體狀態,得知新的總體狀態 (O(n))

思考
  1. 合法構築 sliding window w 的條件
    (在 sliding window 不合法時,調整 left 使 sliding window 回到合法狀態)
  2. 如何遵循上述要訣並從 sliding window 中獲得目標解答的方法 f(w)
    return best([f(w) for w in all_sliding_windows])

Template

sliding_window := arr[left:right + 1]

left := left pointer of sliding window (start of sliding window)
length := length of slide window = right – left + 1
right := right pointer of sliding window (end of sliding window) = left + length – 1

curr := f(current_sliding_window)
ans := best([f(w) for w in all_sliding_window])

def fn(arr):
  ans = left = curr = 0
  for right in range(len(arr)):
    # do logic here to add arr[right] to curr

    while WINDOW_CONDITION_BROKEN:
      # remove arr[left] from curr
      left += 1

    # update ans
    
  return ans
使用例
優化 Sliding Window 作例 (當 sliding window 不合法時調整 left)

例題

Fast & Slow Pointer|Floyd’s Cycle Detection AlgorithmHare & Tortoise Algorithm

\begin{align}
F &:= \text{length of nodes before cycle} \\
C &:= \text{length of nodes in cycle}
\end{align}

將 noncyclic nodes 標記為 –F to -1
將 cycle 裡的 nodes 標記為 0 to  C – 1
node (-F) 為 list 的起點; node 0 則是 Cycle 的起點

1 – a.
hare 的速度是 tortoise 的兩倍
在 iteration F
tortoise 到達 node 0
而 hare 則走了 2F 步到達 node h 
h = F % Ch = FnC F = h + nC

1 – b
再經過 Ch iterations 後
tortoise 位於 node (Ch)
hare 也會在 node (Ch) 和 tortoise 相遇
h + 2(Ch) = 2Ch; (2Ch) % C = Ch

如果這個 list 沒有 cycle,hare 會比 tortoise 先到達終點

2.
將 tortoise 移回 node (-F),hare 留在 node (Ch
並將兩者的速度皆設定為 1 
則再經過 F iterations 後
tortoise 的位置會在 Cycle 的起點 node 0
※ –F + F = 0
hare的位置也會在 Cycle 的起點 node 0
※ (Ch) + F = (Ch) + (h + nC) = (n + 1)C; ((n + 1)C) % C = 0

由以上的步驟,我們可以藉此確定起點的位置

例題

Last Updated on 2023/09/10 by A1go

目錄
Bitnami