滑动窗口

function f(s: string): number {
  let l = 0, ans = 0;
  const freq = new Map<string, number>();
  for (let r = 0; r < s.length; r++) {
    freq.set(s[r], (freq.get(s[r]) ?? 0) + 1);
    while (/*窗口不合法*/ false) {
      freq.set(s[l], freq.get(s[l])! - 1);
      if (freq.get(s[l]) === 0) freq.delete(s[l]);
      l++;
    }
    ans = Math.max(ans, r - l + 1);
  }
  return ans;
}

二分(左边界)

function lowerBound(a: number[], x: number): number {
  let l = 0, r = a.length; // [l, r)
  while (l < r) {
    const m = (l + r) >> 1;
    if (a[m] < x) l = m + 1; else r = m;
  }
  return l;
}

BFS(矩阵/图)

function bfs(grid: number[][]): number {
  const m = grid.length, n = grid[0].length;
  const q: [number, number][] = [];
  const seen = Array.from({length: m}, () => Array(n).fill(false));
  q.push([0,0]); seen[0][0] = true;
  let steps = 0;
  while (q.length) {
    for (let sz = q.length; sz > 0; sz--) {
      const [x,y] = q.shift()!;
      if (/*到达目标*/ false) return steps;
      for (const [dx,dy] of [[1,0],[-1,0],[0,1],[0,-1]]) {
        const nx = x + dx, ny = y + dy;
        if (nx>=0 && ny>=0 && nx<m && ny<n && !seen[nx][ny]) {
          seen[nx][ny] = true; q.push([nx,ny]);
        }
      }
    }
    steps++;
  }
  return -1;
}

单调栈

function nextGreater(a: number[]): number[] {
  const n = a.length, ans = Array(n).fill(-1), st: number[] = [];
  for (let i = 0; i < n; i++) {
    while (st.length && a[i] > a[st.at(-1)!]) {
      const j = st.pop()!; ans[j] = a[i];
    }
    st.push(i);
  }
  return ans;
}