這篇是我參加 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 助攻這些。