← 返回博客列表
Amazon

Amazon Intern VO Round 1 真题:统计好友及二度好友最常用标签 Top X(图遍历 + 频次统计)

2026-03-18

Amazon Intern VO · Social Graph Tag Frequency

Amazon Intern VO Round 1 真题:统计好友及二度好友最常用标签 Top X

本题来自 Amazon 2026 Intern Virtual Onsite Round 1,考察图遍历(BFS)、哈希表频次统计与堆(Heap)的综合运用,是社交网络场景下的经典 Top-K 问题。


题目描述

Imagine you have a Twitter-style social network. Each user has a list of friends, and each user has posted some posts. Each post can carry multiple tags.

Your task:

Given a user_id and an integer X, return the Top X most frequent tags used across all posts by:

  1. The user's direct friends (1-hop)
  2. The user's friends-of-friends (2-hop)

注意:不统计用户本人的标签。如果同一个人通过多条路径可达,其标签只计一次。

示例

用户 user_0 的朋友:A, B
  A 的帖子标签:["sports", "fun"]
  B 的帖子标签:["news",   "sports"]
  A 的朋友:C
    C 的帖子标签:["travel", "sports"]

X = 2

聚合后标签频次:
  sports : 3
  fun    : 1
  news   : 1
  travel : 1

Top 2 输出 → ["sports", "fun"]  (fun/news/travel 频次相同时按字典序或题意处理)

解题思路

整体三步走:

步骤 操作 数据结构
1 BFS 遍历 1~2 跳好友,收集所有用户 ID deque + visited set
2 遍历这些用户的所有帖子标签,统计频次 HashMap (Counter)
3 取频次最高的 Top X 个标签 排序 或 min-heap

为什么用 BFS 而非 DFS?

为什么用 min-heap 而非全排序?


完整 Python 代码

from collections import deque, Counter
import heapq
from typing import List, Dict

def top_tags_friends_and_fof(
    user_id: str,
    friends: Dict[str, List[str]],   # user -> list of friend IDs
    posts: Dict[str, List[List[str]]],# user -> list of posts, each post is list of tags
    X: int
) -> List[str]:
    """
    返回 user_id 的 1-hop + 2-hop 好友帖子中频次最高的 Top X 标签。
    """
    # --- Step 1: BFS 收集 1~2 hop 好友 ---
    visited = {user_id}   # 排除自身
    collected = set()     # 需要统计标签的用户集合
    queue = deque()

    # 加入 1-hop 好友
    for friend in friends.get(user_id, []):
        if friend not in visited:
            visited.add(friend)
            collected.add(friend)
            queue.append(friend)

    # 从 1-hop 扩展到 2-hop
    while queue:
        curr = queue.popleft()
        for fof in friends.get(curr, []):
            if fof not in visited:
                visited.add(fof)
                collected.add(fof)
                # 不再继续扩展(只到 2 hop)

    # --- Step 2: 统计标签频次 ---
    tag_count: Counter = Counter()
    for uid in collected:
        for post_tags in posts.get(uid, []):
            tag_count.update(post_tags)

    if not tag_count:
        return []

    # --- Step 3: 取 Top X ---
    # 方法 A:直接排序(简洁)
    top_x = [tag for tag, _ in tag_count.most_common(X)]
    return top_x


def top_tags_heap(tag_count: Counter, X: int) -> List[str]:
    """
    方法 B:min-heap,O(n log X),X << n 时更优。
    """
    heap = []  # (count, tag)
    for tag, cnt in tag_count.items():
        heapq.heappush(heap, (cnt, tag))
        if len(heap) > X:
            heapq.heappop(heap)
    # heap 中剩余 X 个,按频次降序输出
    result = [tag for cnt, tag in sorted(heap, reverse=True)]
    return result

测试用例

if __name__ == "__main__":
    friends_graph = {
        "user_0": ["A", "B"],
        "A":      ["C", "D"],
        "B":      ["D"],
        "C":      [],
        "D":      [],
    }
    posts_data = {
        "A": [["sports", "fun"]],
        "B": [["news", "sports"]],
        "C": [["travel", "sports"]],
        "D": [["tech", "fun"]],
    }

    print(top_tags_friends_and_fof("user_0", friends_graph, posts_data, X=2))
    # 预期: ['sports', 'fun']  (sports=3, fun=2)

    print(top_tags_friends_and_fof("user_0", friends_graph, posts_data, X=3))
    # 预期: ['sports', 'fun', 'news'] 或 ['sports', 'fun', 'travel'] 等(频次相同时不保证顺序)

复杂度分析

阶段 时间复杂度 空间复杂度
BFS 收集好友 O(F + F²),F = 1-hop 好友数 O(F²)
统计标签频次 O(T),T = 所有帖子标签总数 O(U) 不同标签数
取 Top X(排序) O(U log U) O(U)
取 Top X(heap) O(U log X) O(X)
整体 O(F² + T + U log X) O(F² + U)

Follow-up 问题与回答

Q1:如果要支持 3-hop 甚至 K-hop 怎么办?

将 BFS 改为通用 K 层扩展:

def bfs_k_hop(user_id, friends, K):
    visited = {user_id}
    collected = set()
    queue = deque([(user_id, 0)])
    while queue:
        curr, depth = queue.popleft()
        if depth >= K:
            continue
        for nb in friends.get(curr, []):
            if nb not in visited:
                visited.add(nb)
                collected.add(nb)
                queue.append((nb, depth + 1))
    return collected

Q2:如果图是有向图(Twitter follow 关系),该怎么处理?

只需将 friends[curr] 替换为 following[curr](只沿 follow 方向扩展),其余逻辑不变。

Q3:如果用户量达到亿级,如何扩展?

Q4:如果同一用户的标签需要去重(每个标签每人只算一次)?

在统计时改为 set 去重:

for uid in collected:
    user_tags = set()
    for post_tags in posts.get(uid, []):
        user_tags.update(post_tags)
    tag_count.update(user_tags)   # 每人每个标签最多贡献 1

常见错误

错误 后果 正确做法
未用 visited 去重 同一用户标签重复计算,答案错误 BFS 时维护 visited set
user_id 本人加入统计 多统计了自己的标签 初始化 visited = {user_id}
2-hop 节点继续入队扩展 变成 3-hop 甚至无限 BFS 控制层数,2-hop 只收集不再入队
只用排序不提 heap 错过 O(n log X) 优化机会 主动提出 heap 方案并分析复杂度

面试策略

开场澄清(2 分钟)

拿到题目先确认:

思路表达顺序

  1. 先说大框架:BFS → HashMap → Heap
  2. 写代码前举例走一遍(白板或口述)
  3. 写完基本版本后主动优化:提出 heap vs 全排序
  4. 收尾时主动讲复杂度,再提 Follow-up

加分点


相关 LeetCode 题目

题号 题目 关联点
347 Top K Frequent Elements 频次统计 + heap
994 Rotting Oranges BFS 层级遍历
133 Clone Graph 图 BFS/DFS + visited
1091 Shortest Path in Binary Matrix BFS 最短路
692 Top K Frequent Words Top-K 字符串

延伸思考:为什么 Amazon 爱出社交图题?

Amazon 的业务场景中大量涉及图结构:推荐系统(买了 A 的人还买了 B)、商家网络、物流节点等。社交图 Top-K 标签这道题,实质上是推荐系统的简化版——根据用户的社交圈兴趣,推荐最热门的话题标签,与 Amazon Personalize 的底层逻辑一脉相承。

理解这道题,不只是为了应付面试——它能帮你真正理解推荐系统的冷启动问题和协同过滤的直觉基础。


🚀 需要 Amazon Intern VO 辅助?

oavoservice 专注北美大厂 OA/VO 全程辅助,Amazon Intern/NG 是我们的高频服务场景。

立即添加微信:Coding0201

获取:

📱 微信:Coding0201 | 💬 Telegram:@OAVOProxy | 📧 [email protected]