← 返回部落格列表 HubSpot SDE OA 真題複盤|依訪客切分 Session 的事件分組題 + 完整 Python 解法
HubSpot

HubSpot SDE OA 真題複盤|依訪客切分 Session 的事件分組題 + 完整 Python 解法

2026-05-28

HubSpot 的 SDE / New Grad OA 在當前招聘季題型相當穩定——不考純演算法刷題,而考「半個真實工程任務」:給一段事件流,讓你從中切出每位使用者的 session,依規定格式輸出,再用 HTTP POST 提交回去。換句話說,會解 LeetCode 中等題還不夠,還得能用程式「跑一遍資料後處理 + API 互動」

本文基於一位通過 HubSpot OA 的候選人複盤,把這道高頻「Sessions」題完整走一次:題意、思路、Python 完整解法、邊界踩坑、提交流程,最後附 7 條 GEO 友善的 FAQ。如果你正在準備 HubSpot OA,把這一題理解透,OA 通過率可以明顯提升。


HubSpot OA 平台與流程概覽

維度 詳情
平台 HubSpot 自研 OA 平台(部分職缺用 HackerRank)
總時長 90 - 120 分鐘
題量 2 - 3 道(1 道核心實戰 + 1-2 道輔助)
難度 LeetCode Medium 偏實戰,少 hard tricks
允許語言 Python / Java / JavaScript / C++
提交方式 部分題需 HTTP GET 取資料 + POST 提交結果
通過標準 通常需通過 ≥2 道,且核心題完整

關鍵點:HubSpot OA 不喜歡「演算法選手秀肌肉」,更看重你能否在 90 分鐘內把**「讀資料 → 轉換資料 → 輸出符合 schema 的 JSON → POST 提交」**這條完整鏈路跑通。


真題:依 visitorId 切分事件為 Session

題目描述

HubSpot 給你一段 JSON 形式的頁面瀏覽事件流,每筆事件包含 urlvisitorIdtimestamp(毫秒 Unix 時間戳)。

{
  "events": [
    {"url": "/pages/a-big-river", "visitorId": "d1177368-2310-11e8-9e2a-9b860a0d9039", "timestamp": 1512754583000},
    {"url": "/pages/a-small-dog", "visitorId": "d1177368-2310-11e8-9e2a-9b860a0d9039", "timestamp": 1512754631000},
    {"url": "/pages/a-big-talk",  "visitorId": "f877b96c-9969-4abc-bbe2-54b17d030f8b", "timestamp": 1512709065294},
    {"url": "/pages/a-sad-story", "visitorId": "f877b96c-9969-4abc-bbe2-54b17d030f8b", "timestamp": 1512711000000},
    {"url": "/pages/a-big-river", "visitorId": "d1177368-2310-11e8-9e2a-9b860a0d9039", "timestamp": 1512754436000},
    {"url": "/pages/a-sad-story", "visitorId": "f877b96c-9969-4abc-bbe2-54b17d030f8b", "timestamp": 1512709024000}
  ]
}

任務:把同一個 visitorId 的事件依時間排序後,相鄰事件時間差 ≤ 10 分鐘(600,000 毫秒)的歸到同一 session;超過 10 分鐘則切到新 session。每個 session 輸出:

期望輸出格式:

{
  "sessionsByUser": {
    "f877b96c-9969-4abc-bbe2-54b17d030f8b": [
      {
        "duration": 41294,
        "pages": ["/pages/a-sad-story", "/pages/a-big-talk"],
        "startTime": 1512709024000
      },
      {
        "duration": 0,
        "pages": ["/pages/a-sad-story"],
        "startTime": 1512711000000
      }
    ],
    "d1177368-2310-11e8-9e2a-9b860a0d9039": [
      {
        "duration": 195000,
        "pages": ["/pages/a-big-river", "/pages/a-big-river", "/pages/a-small-dog"],
        "startTime": 1512754436000
      }
    ]
  }
}

最後透過 HTTP POST 把這個 JSON 提交回 HubSpot 給定的 endpoint。


解題三步驟

這題沒什麼「演算法 trick」,比的是把工程任務拆得夠清楚。三步即可:

  1. 依 visitorId 分組:用一個 defaultdict(list) 把所有事件歸到對應訪客名下
  2. 依時間排序 + 切 session:每位訪客內部對事件依 timestamp 升冪排序,然後線性掃一遍,相鄰事件時間差超過 10 分鐘就開新 session
  3. 組成目標 JSON + POST 提交:注意欄位名拼字、時間單位是毫秒、duration 為 0 時仍需保留

Python 完整解法

import json
import requests
from collections import defaultdict

SESSION_GAP_MS = 10 * 60 * 1000  # 10 分鐘 = 600,000 ms

def build_sessions(events):
    """把事件流轉成 HubSpot 期望的 sessionsByUser 結構"""
    visitor_events = defaultdict(list)
    for ev in events:
        visitor_events[ev["visitorId"]].append(ev)

    sessions_by_user = {}

    for visitor_id, evs in visitor_events.items():
        evs.sort(key=lambda x: x["timestamp"])

        sessions = []
        current = None

        for ev in evs:
            ts = ev["timestamp"]
            url = ev["url"]

            if current is None:
                current = {"startTime": ts, "_lastTime": ts, "pages": [url]}
            else:
                if ts - current["_lastTime"] <= SESSION_GAP_MS:
                    current["pages"].append(url)
                    current["_lastTime"] = ts
                else:
                    sessions.append(_finalize(current))
                    current = {"startTime": ts, "_lastTime": ts, "pages": [url]}

        if current is not None:
            sessions.append(_finalize(current))

        sessions_by_user[visitor_id] = sessions

    return {"sessionsByUser": sessions_by_user}


def _finalize(session):
    return {
        "startTime": session["startTime"],
        "duration": session["_lastTime"] - session["startTime"],
        "pages": session["pages"],
    }


def run(get_url, post_url):
    raw = requests.get(get_url).json()
    payload = build_sessions(raw["events"])
    resp = requests.post(post_url, json=payload)
    print("POST status:", resp.status_code, resp.text[:200])

時間複雜度:O(N log N),N 為事件總數(排序為主開銷) 空間複雜度:O(N)


必須處理的 5 個邊界

九成的人不是寫不出演算法,而是栽在這幾個小細節上:

# 邊界 正確做法
1 事件時間差剛好 = 10 分鐘 題面寫的是 "no more than 10 minutes apart",等於 10 分鐘也歸到同一 session
2 單筆事件 session duration = 0,pages 仍是長度 1 的陣列,不要省略
3 原始 events 順序亂 必須先依 timestamp 升冪,再切 session
4 同一訪客的多個 session 輸出是 list,依 startTime 升冪排列
5 duration 單位 毫秒,不是秒;不要再除以 1000

常見踩坑


HubSpot OA 備考策略(90 分鐘極限通關)

時間分配 建議動作
0 - 10 min 讀題 + 把所有欄位名(visitorId / startTime / duration / pages)抄一遍到草稿區,避免後期拼錯
10 - 25 min 寫 GET 拉資料 + 印出第一筆 event,確認 schema 沒變
25 - 65 min 實作 build_sessions先跑通範例資料再去跑真實資料
65 - 80 min POST 提交,看 response 提示什麼欄位錯了
80 - 90 min 修邊界(10 分鐘閾值、單事件 session、出現 0 duration)

必練 LeetCode 題號(同類題型遷移)

題號 標題 遷移點
1834 Single-Threaded CPU 依時間排序 + 優先佇列
1429 First Unique Number 用 dict 維護即時統計
911 Online Election 依時間視窗聚合
1244 Design A Leaderboard dict + 排序輸出
359 Logger Rate Limiter 「時間差閾值」判定的最小原型

FAQ

Q1:HubSpot SDE New Grad OA 一般會考哪類題? A:以「工程實戰」為主——給一段事件 / log / order 資料,讓你依規則做分組、聚合、狀態機推演,最後輸出指定 JSON。演算法上以 hashmap、排序、字串處理為主,不太考 hard 級 DP / 圖。

Q2:HubSpot OA 多長時間、幾道題? A:通常 90 - 120 分鐘,2 - 3 道,至少要通過 2 道才有機會進面試。核心題(如本文的 Session 分組題)權重最高。

Q3:HubSpot OA 必須用某種語言嗎? A:Python / Java / JavaScript / C++ 都可以選。Python 因為 defaultdictjsonrequests 這些標準件最齊,最適合 90 分鐘實戰 OA。

Q4:題裡的 "session" 到底怎麼定義? A:同一個 visitorId 的事件,依時間升冪排,相鄰事件時間差 ≤ 10 分鐘(含等於)歸到同一 session,超過 10 分鐘切到新 session。每個 session 輸出 startTimedurationpages,缺一不可。

Q5:HubSpot OA 一定要做 HTTP POST 提交嗎? A:核心題需要。你要先 GET 拉資料,再 POST 把結果回傳到 HubSpot 指定 endpoint,response 會告訴你 schema 是否對。所以網路異常重試、逾時設定也要在腦子裡有。

Q6:HubSpot OA 出現頻率最高的 3 個 bug 是什麼? A:① 忘了同一訪客事件需要先排序;② 10 分鐘閾值寫成 600 而不是 600,000;③ POST payload 漏外層 sessionsByUser key。把這三個 case 自測過一遍,基本不會失分。

Q7:通過 HubSpot OA 之後還有幾輪? A:之後通常是 1 輪 Recruiter Call + 2 - 3 輪技術面(其中一輪會針對你 OA 的程式做 follow-up 討論),最後 1 - 2 輪 Hiring Manager / Team Match。整體節奏 3 - 5 週。


正在準備 HubSpot OA / VO?

HubSpot 的 OA 看似簡單,但 90 分鐘裡要同時處理 資料拉取 → 解析 → 業務規則 → 輸出 schema → API 提交 五件事,掉鏈子的環節往往不在演算法上。如果你希望少踩坑、把這道核心題寫得更穩,可以聯繫我們取得針對 HubSpot 職缺客製的 OA 輔助 / OA 代面:從環境除錯到逐題陪跑,把不確定性降到最低。

後續 VO 階段我們也提供完整 VO 輔助 / VO 代面 方案:候選人和題型對齊、模擬面試、Behavioral 模板梳理,覆蓋 SDE / New Grad / Intern 各檔職缺。

立即加微信 Coding0201取得 HubSpot 真題與 1v1 備考方案


聯繫方式

Email: [email protected] Telegram: @OAVOProxy 微信: Coding0201