上午九點五十分,林晨坐在t廠大樓三十二層的一間小型會議室里。
會議室不大,約十平米,一張長方形會議桌,四把椅子,牆上掛著白板。窗戶朝東,晨光透過百葉窗在地板上投下斑駁的光影。空氣里有淡淡的消毒水味和咖啡香——典型的互聯網公司氣味。
林晨提前二十分鐘到達。前台核對信息後,一位年輕的hR實習生將他領到這里,遞上一瓶礦泉水,禮貌地說面試官馬上就到。
他打開筆記本電腦,連接電源,再次檢查網絡。視頻面試鏈接已經發到郵箱,但他被通知第一輪是現場面試。也好,面對面更能展現狀態。
九點五十五分,門被推開。
進來的是個三十出頭的男性,短發,戴黑框眼鏡,穿著深灰色t恤,胸口印著t廠的logo。他手里拿著ipad和一支筆,步伐輕快。
“林晨是吧?我是王磊,AI平台部的算法工程師,今天由我來做技術一面”。他伸出手,笑容溫和但透著專業感。
林晨起身握手︰“王老師好,我是林晨”。
“坐坐,別客氣”。王磊在對面坐下,打開ipad,“簡歷我看過了,十年跨境電商經驗,最近半年自學AI,還做了個量化投資系統”?
“是的”。林晨點頭,心里快速調整狀態——甦婉說得對,不是接受考核,是展示價值。
“那我們直接開始吧”。王磊推了推眼鏡,“先做兩道算法題,可以嗎”?
“沒問題”。
王磊在ipad上操作幾下,將屏幕轉向林晨。是t廠內部的在線編程平台界面,題目已經加載。
第一題︰尋找旋轉排序數組中的最小值 II
題目描述︰假設一個按升序排列的數組在某個未知點上進行了旋轉(例如,數組 [0,1,2,4,5,6,7] 可能變成 [4,5,6,7,0,1,2])。數組中可能包含重復元素。請編寫一個函數,找出其中最小的元素。
難度標簽︰hard。
林晨掃了一眼題目。這是二分查找的變種,經典難題。他曾在Leetcode上刷過類似的題,但包含重復元素會增加復雜度。
“可以用這個平台寫,也可以在白板上寫思路”。王磊說。
“我直接寫代碼吧”。林晨將筆記本電腦轉向自己,打開編程界面。
手指落在鍵盤上時,他深吸一口氣。這半年,他刷了超過三百道算法題,從Easy到hard,從數組到圖論。失業的壓力轉化為刷題的動力,常常一天八小時坐在電腦前,直到眼楮發酸。
此刻,那些深夜的堅持開始兌現。
他先寫下函數簽名,然後快速分析︰因為有重復元素,當 nums[mid] == nums[right] 時,無法判斷最小值在左側還是右側,此時只能將右指針減一。時間復雜度最壞會退化到o(n),但平均仍是o(log n)。
指尖在鍵盤上飛舞︰
def findmin(nums):
left, right = 0, len(nums) - 1
while left < right:
mid = left + (right - left) // 2
if nums[mid] > nums[right]:
left = mid + 1
elif nums[mid] < nums[right]:
right = mid
else: # nums[mid] == nums[right]
right -= 1
return nums[left]
寫完,他檢查了一遍邊界條件,點擊運行。
測試用例通過。
“Ac了”。王磊看著ipad上的反饋,點點頭,“時間三分十二秒,很快。能解釋一下為什麼 nums[mid] == nums[right] 時要 right -= 1 嗎”?
林晨轉向白板,畫了一個數組示意圖︰“比如 [3,3,1,3],初始時 left=0, right=3, mid=1。nums[1]=3, nums[3]=3,相等。此時我們無法判斷最小值在左邊還是右邊,但可以確定的是,去掉最右邊的元素不會丟掉最小值,因為 nums[right] 和 nums[mid] 相等,所以可以安全地將 right 減一”。
“正確”。王磊在ipad上做了記錄,“下一題”。
第二題︰接雨水 II
題目描述︰給定一個 m x n 的矩陣,其中的值均為正整數,代表二維高度圖。請計算這個形狀可以接多少雨水。
難度標簽︰hard。
二維接雨水,比一維難得多。林晨記得這道題要用最小堆(優先隊列)加bFS的思路。他從邊界開始,將最低的柱子作為“水桶”的短板,向內推進。
思路清晰後,他再次開始編碼。這次花了些時間,約八分鐘。
import heapq
def trapRainwater(heightmap):
if not heightmap:
return 0
m, n = len(heightmap), len(heightmap[0])
if m < 3 or n < 3:
return 0
visited = [[False] * n for _ in range(m)]
heap = []
# 將邊界加入堆
for i in range(m):
heapq.heappush(heap, (heightmap[i][0], i, 0))
heapq.heappush(heap, (heightmap[i][n-1], i, n-1))
visited[i][0] = visited[i][n-1] = true
for j in range(1, n-1):
heapq.heappush(heap, (heightmap[0][j], 0, j))
heapq.heappush(heap, (heightmap[m-1][j], m-1, j))
visited[0][j] = visited[m-1][j] = true
directions = [(0,1),(0,-1),(1,0),(-1,0)]
water = 0
while heap:
height, x, y = heapq.heappop(heap)
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < m and 0 <= ny < n and not visited[nx][ny]:
visited[nx][ny] = true
# 如果相鄰格子比當前邊界矮,可以接水
water += max(0, height - heightmap[nx][ny])
# 新邊界的高度是 max(當前邊界高度, 相鄰格子高度)
heapq.heappush(heap, (max(height, heightmap[nx][ny]), nx, ny))
return water
運行,再次Ac。
王磊看著結果,沉默了幾秒。然後他抬起頭,笑容更明顯了些︰“兩道hard題,全部一次Ac,而且時間控制得很好。林先生,你的算法功底比很多科班出身的候選人還要扎實”。
“謝謝”。林晨松了口氣,但不敢放松——他知道,算法只是門檻,真正的重點在後面。
果然,王磊將ipad放到一邊,身體前傾︰“那我們聊聊項目吧。你簡歷上寫的這個‘智能量化投資系統’,我挺感興趣的。一個做了十年跨境電商的人,怎麼想到做這個”?
林晨知道,展示價值的時刻到了。
他打開自己帶來的筆記本電腦,調出系統的架構圖︰“其實邏輯是相通的。跨境電商要做庫存預測、價格優化、用戶行為分析,本質也是數據驅動決策。我失業後開始學AI,就想能不能把機器學習用在投資上”。
他切換到系統界面——這是他自己開發的web端,簡潔的深色主題,左側是菜單欄,中間是K線圖和策略信號。
“系統分為幾個模塊”。林晨開始講解,“數據層,我從多個數據源獲取A股、基金、期貨、外匯的實時和歷史數據,用pySpark做清洗和預處理。特征工程部分,我提取了上百個技術指標,包括均線、mAcd、RSI、布林帶,還有一些自己設計的因子”。
王磊認真听著,偶爾點頭。
“模型層,我用了集成學習。基礎模型包括LStm、GRU這些時序模型,還有xGboost和LightGbm。但不是簡單堆疊,我設計了一個元學習器,動態評估每個子模型在不同市場狀態下的表現,分配權重”。
“怎麼評估市場狀態”?王磊問。
“我用無監督學習做了聚類”。林晨切換到另一張圖,“根據波動率、成交量、行業輪動速度等維度,把市場分為震蕩市、單邊上漲、單邊下跌、高波動四種狀態。每種狀態下,不同策略的有效性差異很大”。
“有意思”。王磊眼楮亮了,“那風控呢”?
“三層風控”。林晨點開風控模塊,“第一層,策略層面,每個策略都有最大回撤閾值,觸發就暫停。第二層,賬戶層面,單日虧損超過2%或周虧損超過5%,全倉降杠桿。第三層,人工干預接口,我可以隨時手動平倉”。
他頓了頓,補充道︰“系統運行半年,累計收益率86%,最大回撤7.2%”。
王磊挑了挑眉︰“實盤”?
“實盤”。林晨點頭,“我用的是自己的錢。代碼可以騙人,但賬戶淨值不會”。
這句話讓王磊笑了︰“說得對。那你在開發過程中遇到的最大技術挑戰是什麼”?
林晨想了想︰“數據一致性。金融市場數據來源多,格式不一,還有停牌、除權除息、合約換月這些特殊情況。我花了大量時間構建數據管道,確保輸入模型的數據是干淨、連續、可復現的。另外就是實盤交易時的延遲和滑點問題,我接入了券商ApI,但中小券商的接口穩定性一般,需要做重試和容錯”。
兩人就這樣聊了四十多分鐘。從模型細節到工程實現,從投資理念到技術選型。王磊問得很細,有時甚至會追問某個參數為什麼設成0.3而不是0.25。林晨一一作答,有些地方他承認還在優化,但思路是清晰的。
十點五十分,王磊看了眼時間︰“差不多了。我這邊技術評估沒問題,算法和項目都超出預期。接下來會有二面,應該是我們總監陳博士親自面,他可能會問得更深,尤其是AI底層的一些東西”。
“謝謝王老師”。林晨起身。
“別客氣”。王磊也站起來,再次握手,“說實話,你這個轉型案例挺勵志的。期待和你做同事”。
走出會議室時,林晨感覺腳步輕快了許多。
走廊里人來人往,年輕的程序員們端著咖啡匆匆走過,討論著模型訓練和線上問題。陽光透過落地窗灑進來,整個樓層明亮而充滿活力。
他走到窗邊,望向樓下。深南大道車流如織,遠處騰訊大廈的玻璃幕牆反射著耀眼光芒。這座城市的脈搏,他曾經以為自己已經脫節,但現在,他又一次站在了核心地帶的建築里,用代碼證明了自己的價值。
手機震動,是甦婉發來的微信︰“面試怎麼樣”?
林晨打字回復︰“一面過了,聊得很好。面試官說期待做同事”。
幾乎秒回︰“太好了!我就知道你可以!樂樂說晚上要吃大餐慶祝”!
看著屏幕上的字,林晨嘴角揚起。他想起昨晚甦婉說的話——你不是在求職,是在尋找能發揮價值的平台。
也許,t廠就是這個平台。
但下一關,是陳博士。
林晨听說過這位技術總監的名聲︰嚴謹、深刻、喜歡追問本質。他會問什麼?會如何看待一個半路出家的AI工程師?
電梯下行時,林晨看著樓層數字跳動,心里那個問題逐漸清晰︰
當一位追求算法極限的科學家,遇見一個用代碼解決實際問題的工程師,會踫撞出怎樣的火花?
他不知道答案。
但他已經準備好了。