← 返回博客列表
DoorDash

DoorDash VO 面试题:最近同轴城市(Closest Straight City|哈希表 + 排序 + 二分)

2025-11-23

# DoorDash VO 面试题:最近同轴城市(Closest Straight City|哈希表 + 排序 + 二分)

oavoservice 原创复盘:重点在“如何把候选缩到常数个”,以及 tie-break 的实现细节。

题目(改写版)

给定 n 个城市坐标:(x[i], y[i]),以及 q 个查询城市名。

对每个查询城市 c

思路核心

如果每次查询都扫一遍 n,会变成 O(nq)

优化:

对查询城市,只需要在两条有序列表里找它的相邻前驱/后继,最多比较 4 个候选。

数据结构

复杂度

Python 参考实现

from bisect import bisect_left
from collections import defaultdict


def closest_straight_city(names, xs, ys, queries):
    pos = {}
    x_map = defaultdict(list)
    y_map = defaultdict(list)

    for name, x, y in zip(names, xs, ys):
        pos[name] = (x, y)
        x_map[x].append((y, name))
        y_map[y].append((x, name))

    for x in x_map:
        x_map[x].sort()  # (y, name)
    for y in y_map:
        y_map[y].sort()  # (x, name)

    def pick_best(candidates, x0, y0):
        best = None
        best_dist = None
        for name, x, y in candidates:
            dist = abs(x - x0) + abs(y - y0)
            if best is None or dist < best_dist or (dist == best_dist and name < best):
                best = name
                best_dist = dist
        return best

    ans = []
    for q in queries:
        if q not in pos:
            ans.append("NONE")
            continue

        x0, y0 = pos[q]
        candidates = []

        # 同 x:在按 y 排序列表里找邻居
        lst = x_map.get(x0, [])
        i = bisect_left(lst, (y0, q))
        for j in (i - 1, i + 1):
            if 0 <= j < len(lst):
                y, name = lst[j]
                if name != q:
                    candidates.append((name, x0, y))

        # 同 y:在按 x 排序列表里找邻居
        lst = y_map.get(y0, [])
        i = bisect_left(lst, (x0, q))
        for j in (i - 1, i + 1):
            if 0 <= j < len(lst):
                x, name = lst[j]
                if name != q:
                    candidates.append((name, x, y0))

        best = pick_best(candidates, x0, y0)
        ans.append(best if best is not None else "NONE")

    return ans

常见坑


如果你在准备 DoorDash VO,这题在面试里常被用来考你是否能把“全局扫描”改造成“索引 + 邻居候选”。oavoservice 会重点训练这种“把候选缩到常数个”的套路。


需要面试真题? 立刻联系微信 Coding0201,获得真题