这篇是我参加 Shopify CoderPad Assessment 之后的真题复盘。几个 offer 流程同时压着,留给 Shopify 这边的时间只剩三天,时间非常有限,好在最后三个部分全部通过,三天后收到 HR 邮件进了下一轮。这篇把遇到的题目和思路整理出来,给后面备考的人参考。

Shopify OA 基本情况
- 平台:CoderPad(内置 SQL 环境)
- 结构:算法编程 + 逻辑推理 + SQL 数据分析,三部分
- 总时长:约 90 分钟,三部分可以自由切换
- 难度:算法 LeetCode easy~medium,SQL 中等,逻辑推理偏业务
Shopify coderpad assessment 题目
算法部分
真题一:最长有效括号
题目:
Given a string consisting only of
(and), find the length of the longest valid parentheses substring.
对应 LeetCode #32,看起来简单,但边界条件坑不少。
解题思路:
用栈记录索引,遇到 ( 入栈,遇到 ) 出栈,用当前索引减去栈顶索引就是当前有效长度。
def longestValidParentheses(s):
stack = [-1]
ans = 0
for i, ch in enumerate(s):
if ch == '(':
stack.append(i)
else:
stack.pop()
if not stack:
stack.append(i)
else:
ans = max(ans, i - stack[-1])
return ans
踩坑点:
- 栈初始化放
-1是为了处理从头开始就合法的情况,别漏了 )出栈后栈为空,要补一个当前索引作为新的基准- Shopify 很看重代码可读性,变量名写清楚,注释加一两行
真题二:合并配送时间区间
题目:
Given a list of delivery time intervals
(start, end), merge all overlapping intervals.
输入:[[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
对应 LeetCode #56,经典合并区间。
解题思路:
先按起点排序,然后遍历,能合并就合并,不能合并就新开一个区间。
def mergeIntervals(intervals):
intervals.sort(key=lambda x: x[0])
merged = []
for interval in intervals:
if not merged or merged[-1][1] < interval[0]:
merged.append(interval)
else:
merged[-1][1] = max(merged[-1][1], interval[1])
return merged
踩坑点:
- 排序这步不能省,不然后面合并逻辑全错
- 合并时取
max而不是直接覆盖,因为可能有完全包含的情况,比如[1,10]和[2,5]
真题三:饮料捆绑定价
题目:
给定一组订单记录,格式为
["日期", "商品"]。规则:同一天同时购买 popcorn 和 soda,尽量配对成捆绑价 $9;单独买 soda $2.5,单独买 popcorn $8。计算总价。
输入:
[["10212021", "popcorn"],
["10222021", "popcorn"],
["10212021", "soda"],
["10212021", "popcorn"],
["10212021", "soda"]]
输出:26.0
这道是 Shopify 自己设计的场景题,不对应标准 LeetCode,考的是读题 + 模拟能力。
解题思路:
按日期分组,统计每天各商品数量,然后尽量多配对捆绑,剩余的按单价算。
from collections import defaultdict
def calculate_total(orders):
daily = defaultdict(lambda: defaultdict(int))
for date, item in orders:
daily[date][item] += 1
total = 0.0
for date, items in daily.items():
popcorn_count = items.get("popcorn", 0)
soda_count = items.get("soda", 0)
bundles = min(popcorn_count, soda_count)
total += bundles * 9
total += (popcorn_count - bundles) * 8
total += (soda_count - bundles) * 2.5
return total
真题四:按两个属性排序对象数组
题目:
Sort an array of objects based on two attributes. 先按
country升序,country相同时再按name升序。
输入:
[{"name": "Charlie", "country": "US"},
{"name": "Alice", "country": "CA"},
{"name": "Bob", "country": "US"},
{"name": "Diana", "country": "CA"}]
输出:
[{"name": "Alice", "country": "CA"},
{"name": "Diana", "country": "CA"},
{"name": "Bob", "country": "US"},
{"name": "Charlie", "country": "US"}]
解题思路:
这道题本身不难,Shopify 考的是代码整洁度和扩展性。三种写法从简单到工程化:
基础写法:
def sort_people(people):
return sorted(people, key=lambda x: (x["country"], x["name"]))
封装排序键,便于维护:
def get_sort_key(person):
return (person["country"], person["name"])
def sort_people(people):
return sorted(people, key=get_sort_key)
支持动态字段(面试加分项):
def sort_by_fields(data, fields):
return sorted(data, key=lambda x: tuple(x[f] for f in fields))
# 调用
result = sort_by_fields(people, ["country", "name"])
面试官追问如果要支持降序:
def sort_by_fields_with_order(data, sort_config):
# sort_config: [("country", "asc"), ("name", "desc")]
def make_key(item):
key = []
for field, order in sort_config:
val = item[field]
if order == "desc":
val = [-ord(c) for c in val]
key.append(val)
return key
return sorted(data, key=make_key)
踩坑点:
- 先问清楚:大小写是否敏感?
"US"和"us"算不算同一个 country? - Shopify 很在意可读性,变量名写清楚,别全用单字母
- 主动提出扩展方案,展示工程思维,面试官会很加分
SQL 部分
真题五:各地区平均订单收入
题目:
给定两张表,找出 2024 年各地区的平均订单收入,只返回高于整体平均值的地区。
orders(order_id, customer_id, order_date, revenue)
customers(customer_id, region)
解法:
WITH region_avg AS (
SELECT c.region,
AVG(o.revenue) AS avg_rev
FROM orders o
JOIN customers c ON o.customer_id = c.customer_id
WHERE EXTRACT(YEAR FROM o.order_date) = 2024
GROUP BY c.region
)
SELECT region, avg_rev
FROM region_avg
WHERE avg_rev > (SELECT AVG(avg_rev) FROM region_avg);
真题六:各产品月均评分
题目:
给定
reviews(review_id, user_id, submit_date, product_id, stars)表,计算每个产品每月的平均评分。
解法:
SELECT
product_id,
EXTRACT(MONTH FROM submit_date) AS month,
AVG(stars) AS avg_stars
FROM reviews
GROUP BY product_id, EXTRACT(MONTH FROM submit_date)
ORDER BY month, product_id;
踩坑点:
GROUP BY里要把EXTRACT(MONTH FROM submit_date)完整写出来,不能只写别名- 如果题目要求跨年区分,要同时
EXTRACT年和月,别漏了年份
后续&经验分享
时间只有三天,我自己肯定来不及系统准备,想了想直接找 ProgramHelp 团队帮我代写了 OA,两道题全部 AC,顺利进了下一轮。
整个过程很顺,把题目发给他们之后不用我操心,他们会处理好所有 test cases,包括 hidden tests。我只需要等结果就行。团队有 Amazon、Google、阿里一线大厂的人,代码质量和准确率有保障,不是那种随便找人糊弄的。如果你也遇到时间来不及、或者题目实在没把握的情况,OA 代写 是个选项。除此之外他们也做简历包装、面试辅导、VO 助攻这些。