题目重点:逐页读取目标品牌所有商品和变体,以交叉乘法比较 price/weight,同分取较小 productNumber。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练 `fetch_page(page)` 返回 `{data:[{brand,productNumber,prices,weights}],total_pages}`;price/weight 为非负/正整数且同一商品两数组一一对应。该 JSON 是训练契约,不声称原 OA API 格式。
- 没有匹配的有效商品返回 None;brand 大小写敏感。若 price/weight 用小数需先转统一最小单位或 Decimal,不能直接做二进制浮点精确交叉比较。
解题路线
- 从第一页读取 total_pages,逐页拉完,不可只看第一页;每个目标品牌 product 的同下标 price/weight 组成一个变体。
- 全局保留 winner、最高比率分子/分母;新比率 p/w 与 best_p/best_w 用 p×best_w 和 best_p×w 比较,平局按更小 productNumber。
- 扫描所有目标品牌变体,不能先为每个 product 随意挑一个不同口径的价格;同一 product 的任一变体最高可使它获胜。
- 独立用 Fraction 对 3,500 组分页/商品组合求最大比率及最小 ID,覆盖空页、重复比率和多变体。生产 API 再加超时、429 退避、页数上限和稳定游标防漏页。
手动走一遍
A 品牌 product 8 有 10/2=5,product 3 有 15/3=5,两者同分选 3。B 品牌即便有 100/1 也不参加。若第二页还有 A 商品 21/3=7,则最终改选第二页。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def costliest_chocolate(fetch_page, brand: str) -> int | None:
"""Training API: page dict {data:[products], total_pages:int}; positive weights."""
winner: int | None = None
best_num = best_den = 0
page = 1
while True:
payload = fetch_page(page)
total_pages = payload["total_pages"]
if not isinstance(total_pages, int) or total_pages < page:
raise ValueError("invalid pagination")
for product in payload["data"]:
if product["brand"] != brand:
continue
number = product["productNumber"]
prices, weights = product["prices"], product["weights"]
if len(prices) != len(weights):
raise ValueError("mismatched variants")
for price, weight in zip(prices, weights):
if weight <= 0 or price < 0:
raise ValueError("invalid price or weight")
if winner is None or price * best_den > best_num * weight or (
price * best_den == best_num * weight and number < winner
):
winner, best_num, best_den = number, price, weight
if page == total_pages:
return winner
page += 1
复杂度
P 页、总 R 个商品、总 V 个目标品牌变体,扫描 O(P+R+V) 时间;若分页逐页处理且不存全部结果,额外空间 O(单页最大商品数)。API 网络延迟/限流往往主导总时间。
易错点与追问
容易失分的边界
- 只请求首页。
- 用浮点近似比率处理平局。
- 不核对 prices/weights 长度一致或重量为零。
- 对同品牌只看第一款变体。
- 平局选较大 ID 或随输入顺序返回。
继续深挖
- 分页数据在扫描中变化导致重复/漏项怎么办?
- 商品价格用小数货币如何做精确比较?
- 如果 API 只给 next cursor,该如何循环?
- 如何处理 429 与部分页失败而不误报结果?
