Meta de 主要考察简单和聚合查询、分组、排序、CTE、过滤逻辑、时间窗口等。这次面的senior level的,5个sql+5个python题,时间非常紧,一般做3+3比较保险,4+4肯定能进loop面试,分享下前两天的 Meta DE 面经 。
Meta DE 面经:SQL
Q1
- num_copies_not_returned:处于 “good” 状态,且当前借阅还没归还的书本副本数
- pct_renewed:在上面这批副本里,当前这次借阅 renewal_count > 2 的比例,范围 0~100
SELECT
COUNT(*) AS num_copies_not_returned,
CASE
WHEN COUNT(*) = 0 THEN 0
ELSE 100.0 * SUM(CASE WHEN ch.renewal_count > 2 THEN 1 ELSE 0 END) / COUNT(*)
END AS pct_renewed
FROM copies c
JOIN checkouts ch
ON c.copy_id = ch.copy_id
WHERE c.condition = 'good'
AND ch.returned_date IS NULL;
Q2
lifetime_value的定义:一本书被借出的总天数。需要满足约束条件:未归还的借阅记录(returned_date IS NULL)不计入和只考虑拥有超过10个副本的书,找出 lifetime_value 最高的 前3本书。
SELECT
b.book_id,
SUM(ch.returned_date - ch.checkout_date) AS lifetime_value
FROM books b
JOIN copies c ON b.book_id = c.book_id
JOIN checkouts ch ON c.copy_id = ch.copy_id
WHERE ch.returned_date IS NOT NULL
GROUP BY b.book_id
HAVING
(SELECT COUNT(*) FROM copies c2 WHERE c2.book_id = b.book_id) > 10
ORDER BY lifetime_value DESC
LIMIT 3;
Q3
图书馆会员可以预约书籍副本(排队等候借阅),找出预约数量与其邀请人差异最大的那个会员。
SELECT
m.member_id,
m.invited_by_member_id,
ABS(
COUNT(c.copy_id) -
COUNT(ic.copy_id)
) AS diff_num_reserved_copies
FROM members m
LEFT JOIN copies c
ON c.reserved_by_member_id = m.member_id
LEFT JOIN members im
ON im.member_id = m.invited_by_member_id
LEFT JOIN copies ic
ON ic.reserved_by_member_id = im.member_id
GROUP BY
m.member_id,
m.invited_by_member_id
ORDER BY diff_num_reserved_copies DESC, m.member_id
LIMIT 1;
Q4
找在2024年连续两个完整周都借过书的会员,然后从这些人中找出第一周借书数量最多的那个。
WITH member_week_checkouts AS (
SELECT
member_id,
EXTRACT(WEEK FROM checkout_date)::INT AS week_idx,
COUNT(*) AS num_copies
FROM checkouts
WHERE EXTRACT(YEAR FROM checkout_date) = 2024
AND EXTRACT(WEEK FROM checkout_date) BETWEEN 1 AND 52
GROUP BY
member_id,
EXTRACT(WEEK FROM checkout_date)
),
consecutive_weeks AS (
SELECT
w1.member_id,
w1.week_idx AS first_week_index,
w1.num_copies AS first_week_num_copies
FROM member_week_checkouts w1
JOIN member_week_checkouts w2
ON w1.member_id = w2.member_id
AND w2.week_idx = w1.week_idx + 1
)
SELECT
member_id,
first_week_index,
first_week_num_copies
FROM consecutive_weeks
ORDER BY first_week_num_copies DESC, member_id, first_week_index
LIMIT 1;
Meta DE 面经:Code
Q1
最多选 3 本书,每本书必须来自不同 category,每本书有 (category, points),求最大总分
def get_max_score(books):
# 每个category保留最高分
best = {}
for category, score in books:
if category not in best or score > best[category]:
best[category] = score
# 取所有category的最高分
scores = sorted(best.values(), reverse=True)
# 最多取3个
return sum(scores[:3])
Q2
图书馆每次借书或还书都会产生一条日志,日志包含书的ID和操作类型(借出/归还)。验证日志序列是否合法,遇到以下两种非法情况返回 False。
from dataclasses import dataclass
@dataclass
class LogEntry:
book_id: int
is_checkout: bool # True = checkout, False = return
def are_log_entries_valid(log_entries):
checked_out = set()
for entry in log_entries:
book_id = entry.book_id
if entry.is_checkout:
# checkout
if book_id in checked_out:
return False
checked_out.add(book_id)
else:
# return
if book_id not in checked_out:
return False
checked_out.remove(book_id)
return True
Q3
图书馆有4个分馆(A/B/C/D),某些分馆关闭时,员工会去备用分馆或在家工作。给定一组关闭的分馆,返回每个开放分馆的实际员工总数。
以A为例:”A”: {“A”: 80, “B”: 10, “C”: 15, “D”: 5}
- A馆共有80人
- 如果A关闭:10人去B,15人去C,5人去D,剩余50人在家(80-10-15-5=50,不计入任何馆)
def get_num_employees(location_employees: dict[str, dict[str, int]],
closed_locations: set[str]) -> dict[str, int]:
result = {}
# 先给所有未关闭办公室初始化为 0
for loc in location_employees:
if loc not in closed_locations:
result[loc] = 0
# 遍历每个“员工原属办公室”
for src, dist in location_employees.items():
if src in closed_locations:
# src 关闭:员工分流到其他未关闭办公室
for dst, cnt in dist.items():
if dst != src and dst not in closed_locations:
result[dst] += cnt
else:
# src 未关闭:本办公室员工仍在原办公室上班
result[src] += dist[src]
return result
Q4
从 original_name 中删掉若干字母,能否得到 new_name?如果能,返回删掉了多少个字母;不能则返回 -1。忽略空格和大小写,new_name必须是original_name的子序列。
def get_num_letters(original_name: str, new_name: str) -> int:
# 忽略大小写 + 去掉空格
original = original_name.replace(" ", "").lower()
new = new_name.replace(" ", "").lower()
i = 0
j = 0
# 双指针检查 subsequence
while i < len(original) and j < len(new):
if original[i] == new[j]:
j += 1
i += 1
# 如果 new 没完全匹配
if j != len(new):
return -1
# 删除字符数
return len(original) - len(new)
总体都还可以,就是一小时内,时间非常的紧张,刚开始没多问直接开始SQL环节,总共做了4+4个问题,给的提示很到位了,也做完了,面试官还是非常肯定学生的能力的,Meta最近的SDE面的多,DS的也没问题,搞不定的。
整场面试下来可以发现,Meta 的题更多的考基础,时间非常有限,一般很难完成4个sql+4个code。如果你也担心在 Meta 或其他大厂面试中遇到类似情况,不如了解一下我们的 VO远程助攻服务 ,目前已经帮助数百名学员顺利拿下 offer,让面试不再慌乱,思路清晰,成功率大大提升。