實戰(zhàn))
校招季又到了每年這時候總有一堆同學在后臺問我要各家大廠的編程題匯總。今年正好整理電腦文件時翻到了2020年平安科技技術崗校招的部分編程題筆記當時我完整參加了平安科技的校招流程筆試、技術面、HR面一路走下來積累了不少一手資料。今年把這些題目重新梳理了一遍結合當年的解題思路、踩過的坑和一些復盤心得整理成一篇可以直接拿來備戰(zhàn)的參考。無論你是準備投平安科技還是想了解金融科技方向的技術考察重點這篇都值得花幾分鐘讀完。先說下平安科技筆試的總體感受它和互聯網大廠字節(jié)、阿里那種的筆試風格有明顯的區(qū)別。平安作為金融科技公司技術筆試更看重邏輯嚴密性、代碼規(guī)范性和對邊界條件的把控而不是純粹比拼算法競賽技巧。題目以中檔難度為主很少出現超級hard的偏題怪題但會在看似簡單的題目里埋一些細節(jié)陷阱這點我在后面的題目拆解中會詳細說。1. 2020年平安科技校招編程題的整體風格分析1.1 題型分布與考察方向平安科技2020屆校招技術崗的編程題整體分為兩大類一類是純算法題占總分的絕大部分比重另一類是場景應用題會和實際業(yè)務結合考察代碼落地能力。字符串/數組操作這類題占比最高大概能到40%左右題目本身不難但非常考驗代碼的嚴謹性比如指針越界、空指針、字符編碼處理等。數據結構應用重點考察棧、隊列、哈希表、鏈表二叉樹也會涉及但樹這塊不會太深基本停留在遍歷和基礎性質判斷層面。動態(tài)規(guī)劃/貪心算法這類題有固定套路平安的出題特點是不繞彎子狀態(tài)轉移方程比較直接關鍵看你能不能快速識別出題型并寫出干凈的轉移邏輯。多線程/并發(fā)場景這是平安區(qū)別于其他互聯網公司的一個特色考點。因為業(yè)務系統(tǒng)涉及交易、風控等場景對并發(fā)編程的考察不是死記API而是給一個實際業(yè)務場景讓你實現線程安全的代碼。數據庫SQL題技術崗筆試偶爾會出現一道SQL場景題考察基本查詢、聯表、聚合難度不大但要求寫出的SQL能正確應對邊界查詢條件。我手里整理的這批題目主要覆蓋前四類。原題的具體描述經過這三年已經有了不少流傳版本我按自己記憶中比較接近原意的描述重新整理并配上完整的解題思路和實現代碼。1.2 難度梯度與選拔邏輯把平安的編程題整體過一遍你會發(fā)現它的難度分布是一個典型的金字塔結構從基礎到進階層層遞進?;A題占比約50%通常是一道字符串處理或簡單模擬題例如反轉字符串、統(tǒng)計字符頻率、數組去重。這類題主要篩掉完全沒準備過的裸考選手只要刷過50道LeetCode簡單題就能穩(wěn)拿。但這類題也不是無腦拿分的我在整理時發(fā)現平安特別喜歡在基礎題上設置“隱藏條件”比如要求不使用額外空間、要求時間復雜度O(n)、要求原地修改等這些附加約束才是區(qū)分度的關鍵。拔高題占比約30%涉及哈希表、單調棧、雙指針等經典技巧或者是動態(tài)規(guī)劃的入門級別。這類題需要你形成條件反射式的解題直覺看到題目就能快速定位到對應的數據結構或算法模型。壓軸題占比約20%通常是一道多線程并發(fā)場景題或者一道綜合性較強的應用模擬題。這類題沒有標準答案判分看重的是你的代碼風格、線程安全處理、以及異常邊界處理是否到位。坦白講我看到很多同學在這類題上直接空著其實是很可惜的。即使不能完全跑通把線程安全、鎖、并發(fā)控制的思路寫出來面試官也會給一部分步驟分。2. 編程題逐題拆解與解題思路2.1 字符串壓縮考察頻率最高的基礎題這道題是平安筆試的高頻題出題形式很經典給定一個字符串將連續(xù)重復的字符壓縮成“字符重復次數”的形式。例如輸入aaabbc輸出a3b2c1。如果壓縮后的字符串長度不小于原字符串則返回原字符串。很多人在這道題上丟分不是因為不會寫而是因為邊界條件處理不到位。我先給一份相對完整的參考實現def compress_string(s: str) - str: if not s: return res [] count 1 for i in range(1, len(s)): if s[i] s[i - 1]: count 1 else: res.append(s[i - 1] str(count)) count 1 # 處理最后一組字符 res.append(s[-1] str(count)) compressed .join(res) return compressed if len(compressed) len(s) else s這段代碼的核心思路是用一次線性掃描統(tǒng)計相鄰相同字符的數量維護一個count變量每當字符變化時就把前一個字符及其次數寫入結果。最后別忘了處理末尾字符這是一個非常典型的遺漏點。再看剛才提到的兩個陷阱空字符串的情況。很多人上來就res.append(s[0])空字符串直接越界報錯。壓縮后長度不小于原字符串時需要返回原串。這說明題目要求的是“無損壓縮”如果不能縮短則不壓縮這是業(yè)務系統(tǒng)中常見的邏輯——避免無效轉換。我在面試復盤時和幾個一起進面試的同學交流過這道題最大的問題其實是很多人忘了加上最后那行return compressed if len(compressed) len(s) else s。去掉這行代碼在細節(jié)測試用例上就會出錯。這種“簡單題里暗藏玄機”的出題風格幾乎貫穿平安技術筆試的全程。2.2 股票買賣最佳時機動態(tài)規(guī)劃基礎型第二類高頻題是股票買賣類問題。2020年考的是最簡單的一個版本給定一個數組第i個元素是第i天的股票價格只允許完成一筆交易買入一次、賣出一次設計算法獲得最大利潤。這題最直觀的思路是雙重循環(huán)枚舉買入日和賣出日但時間復雜度是O(n^2)在數據規(guī)模大時會超時。務實的做法是動態(tài)規(guī)劃或者一次遍歷維護最小值。參考代碼如下def max_profit(prices) - int: if not prices or len(prices) 2: return 0 min_price prices[0] max_profit 0 for price in prices[1:]: if price min_price: min_price price else: max_profit max(max_profit, price - min_price) return max_profit核心思路是遍歷價格數組時不斷更新歷史最低價min_price同時計算當前價格與歷史最低價的差值更新最大利潤。這里的隱含邏輯是要獲得最大收益一定是在最低點買入、在之后的某一天賣出所以只要跟蹤最低點就能確保每一步的收益計算都是基于最優(yōu)買入時機。這道題值得注意的點是題目明確說“只允許完成一筆交易”所以不需要考慮多次買賣的疊加。有些同學會條件反射地去套“累加所有上升段”的解法——那是無窮次交易版本的思路在2020年的題目中會直接算錯。我在筆試時也差點踩了這個坑讀題的時候把“一筆交易”四個字圈出來是這類題最有效的防錯方式。2.3 鏈表反轉數據結構基礎真題鏈表的考察在平安筆試中頻率不算低因為它能同時考察指針操作和邊界控制能力。2020年的題目是經典的“反轉單鏈表”給定一個單鏈表的頭節(jié)點將其反轉返回新鏈表的頭節(jié)點。這道題的標準解法有兩種迭代法和遞歸法。筆試時我建議用迭代法因為遞歸法需要理解遞歸棧的展開過程在線上筆試那種緊張環(huán)境下容易寫錯而且遞歸深度過深還會造成棧溢出。迭代法參考代碼class ListNode: def __init__(self, val0, nextNone): self.val val self.next next def reverse_list(head: ListNode) - ListNode: prev None curr head while curr: next_node curr.next # 先保存下一個節(jié)點 curr.next prev # 反轉指針 prev curr # 移動prev curr next_node # 移動curr return prev這里容易出錯的點有兩個第一在while循環(huán)中第一步必須是next_node curr.next否則一旦執(zhí)行curr.next prev原鏈表的下一個節(jié)點就丟失了。第二循環(huán)結束后prev指向的是新鏈表的頭節(jié)點而head此時指向的是原鏈表的尾節(jié)點即新鏈表的尾如果返回head就全錯了。在實際筆試中這類題通常會給完整的鏈表定義和輸入格式。我建議在寫代碼前先在草稿紙上畫一下鏈表的指針變化圖三個節(jié)點就夠把每一步prev、curr、next_node的指向關系畫清楚寫起代碼來會順暢很多。這是我在多次模擬筆試后總結出來的經驗比空想指針的變化要高效得多。2.4 多線程交替打印平安的特色考題接下來這道題就有點平安特色了。題目要求創(chuàng)建兩個線程一個線程負責打印奇數另一個線程負責打印偶數兩個線程交替輸出1到100的數字。這道題在互聯網大廠筆試中不算常見但在金融科技公司的筆試中出現的頻率不低因為交易系統(tǒng)、賬務系統(tǒng)中有大量類似的并發(fā)協作場景。核心考點是線程通信和同步考察你是否能熟練使用鎖或信號量控制線程的執(zhí)行順序。參考實現Python版本import threading def print_odd(): for i in range(1, 101, 2): lock_even.acquire() print(i) lock_odd.release() def print_even(): for i in range(2, 101, 2): lock_odd.acquire() print(i) lock_even.release() lock_odd threading.Lock() lock_even threading.Lock() lock_even.acquire() # 初始讓偶數線程等待 t1 threading.Thread(targetprint_odd) t2 threading.Thread(targetprint_even) t1.start() t2.start() t1.join() t2.join()這個實現的核心思想是使用兩把鎖交替獲取和釋放形成嚴格的執(zhí)行順序。初始狀態(tài)讓偶數線程的鎖處于占用狀態(tài)確保奇數線程先執(zhí)行。每打印一個數后釋放對方的鎖同時阻塞自己的鎖這樣線程之間就形成了交替執(zhí)行的節(jié)奏。這個方案的關鍵在于兩把鎖的初始狀態(tài)設置很多人在這個細節(jié)上出錯導致程序死鎖或者順序錯亂。我當年在筆試時就在草稿紙上仔細推演了每個線程在每一步的鎖狀態(tài)變化確保沒有死鎖風險后才落筆。另外如果筆試環(huán)境支持Java語言用wait()和notify()實現也是常見的做法。但要注意wait()必須在同步代碼塊中調用否則會拋IllegalMonitorStateException。我在幫一個師弟review代碼時就看到過這個錯誤他以為只要調了wait()線程就會自動讓出鎖完全沒有意識到同步塊的前提條件。這種小錯誤在筆試中很致命因為判卷系統(tǒng)會直接把代碼跑掛。2.5 兩個數組的交集哈希表經典應用題這是一道非常典型的哈希表應用題平安也喜歡在筆試中考察這類數據結構的基礎應用。題目描述是給定兩個數組編寫一個函數來計算它們的交集輸出結果中每個元素出現的次數應與元素在兩個數組中出現的次數一致。參考實現from collections import Counter def intersect(nums1, nums2): if not nums1 or not nums2: return [] counter1 Counter(nums1) result [] for num in nums2: if counter1.get(num, 0) 0: result.append(num) counter1[num] - 1 return result思路很簡單先用哈希表統(tǒng)計第一個數組中每個元素出現的次數再遍歷第二個數組每遇到一個在哈希表中還有余量的元素就加入結果并將計數減一。這樣可以正確處理重復元素的情況。這道題的進階版本是如果數組已經有序如何優(yōu)化空間復雜度那就用雙指針解法兩個指針分別指向兩個數組的開頭比較當前元素大小相等則加入結果不相等則移動較小元素所在的指針。這個解法的時間復雜度是O(nm)空間復雜度O(1)在筆試中如果能把這兩種解法都寫出來會是一個非常加分的展示。我在復盤時注意到平安的面試官比較欣賞“能給出多種解法并分析取舍”的候選人這比只寫一種能跑的解法要立體得多。2.6 從上到下打印二叉樹BFS層序遍歷二叉樹層次遍歷是校招筆試中的常青樹平安2020年也考了一道變種題從上到下按層打印二叉樹同一層的節(jié)點按從左到右的順序打印每一層打印到一行。這道題的本質就是二叉樹的廣度優(yōu)先搜索BFS最通用的框架是用隊列輔助實現。代碼框架如下from collections import deque def level_order(root): if not root: return [] result [] queue deque([root]) while queue: level_size len(queue) level_nodes [] for _ in range(level_size): node queue.popleft() level_nodes.append(node.val) if node.left: queue.append(node.left) if node.right: queue.append(node.right) result.append(level_nodes) return result這里的關鍵技巧在于每輪循環(huán)開始時先用level_size len(queue)鎖定當前層的節(jié)點數。因為在遍歷過程中隊列中會不斷加入下一層的節(jié)點如果不提前鎖定層大小就無法區(qū)分當前層和下一層輸出的結果就會變成一維數組而不是分層的二維數組。我見過不少同學在筆試時寫出無法正確分層的版本原因就是沒有理解level_size的作用。其實這個技巧在LeetCode 102題中有非常詳細的推導過程刷過這道題的人基本都能順利寫出來。所以我在總結中經常對學弟學妹說算法題的復習不在于數量而在于把每個基礎題型的框架吃透這樣遇到變形題才能快速遷移。3. 完整實操線上筆試流程與代碼提交技巧3.1 平安的筆試環(huán)境與平臺操作要點2020年平安科技的線上筆試用的是第三方在線評測平臺整體體驗和??途W、LeetCode的在線評測非常類似。筆試時間大概90分鐘題量在3到5道之間每道題的分值不同。編程語言選擇平臺支持C、Java、Python等主流語言。如果沒特別說明我建議優(yōu)先選Python因為代碼量更少、調試更快尤其在處理字符串和數組這類題目時Python的內置方法能節(jié)省大量時間。代碼補全方式筆試平臺的代碼編輯器通常不提供自動補全而且縮進有時候會出問題。建議提前在本地IDE把所有題目的代碼框架寫好然后復制到筆試平臺。復制粘貼后一定要重新檢查一遍縮進和括號避免格式問題導致的低級錯誤。輸入輸出格式平安的筆試平臺采用的是標準輸入輸出模式。換句話說判卷系統(tǒng)不會調用你的函數而是把你的程序當作獨立進程運行從標準輸入讀取測試數據從標準輸出讀取結果。這個和LeetCode的“函數補全”模式完全不同。很多第一次接觸這種模式的同學會在這里吃大虧在本地調試好好的代碼一提交就是“格式錯誤”。一個典型的例子是輸入一個整數數組平臺可能是用空格分隔的一行字符串。你需要在程序里手動處理input()讀入的字符串用split()轉換成列表而不能直接假設系統(tǒng)已經幫你處理好了數據結構。我當時總結了一個標準的輸入讀取模板import sys def main(): data sys.stdin.read().strip().split() if not data: return # 根據題目要求解析例如第一個數是數組長度 n int(data[0]) arr list(map(int, data[1:1n])) # 業(yè)務邏輯... print(result) if __name__ __main__: main()使用sys.stdin.read()一次性讀入所有內容再統(tǒng)一用split()切分能避免多行輸入時input()的麻煩。這個模板我后來在多次筆試中反復使用省了不少時間。建議準備參加筆試的同學把這類標準輸入輸出的模板背熟這屬于考前性價比最高的準備工作。3.2 一個完整題目的全流程調試記錄以股票買賣這道題為例我完整演示一下筆試時的做題流程和調試思路。第一步先讀題圈出關鍵限制條件。題目給了數組長度范圍假設是1 prices.length 10^5。這意味著算法的時間復雜度必須控制在O(n)或者O(nlogn)級別O(n^2)的暴力解法一定會超時。第二步在草稿紙上推導思路。為什么可以用一次遍歷完成核心在于我們只需要知道到當前天為止的歷史最低價以及當前價格減去歷史最低價所得到的潛在收益。這些信息可以在一次遍歷中持續(xù)維護不需要回頭去枚舉每一天的買入價。第三步寫出代碼框架后用題目給的示例數據做一次人工推演。prices [7, 1, 5, 3, 6, 4]初始化min_price 7max_profit 0。遍歷到1小于min_price更新min_price 1。遍歷到55 - 1 4更新max_profit 4。遍歷到33 - 1 2小于4不更新。遍歷到66 - 1 5更新max_profit 5。遍歷到44 - 1 3小于5不更新。輸出結果為5和預期一致。這一步人工走查非常管用能提前發(fā)現邏輯錯誤避免提交后反復試錯浪費時間。第四步考慮到邊界情況。數組只有1個元素時沒有合法的買賣操作應該返回0??諗到M也返回0。這些情況在代碼中都有對應的處理邏輯。第五步點擊提交查看評測結果。如果有失敗的測試用例平臺通常會返回錯誤類型和部分測試數據。我在筆試時遇到過一次因為沒處理空數組導致IndexError的情況當時就是根據評測反饋快速定位并修復的。整體來說有了清晰的做題流程3道編程題中至少能穩(wěn)拿2道題的全部分數另外一道壓軸題能寫出框架就能拿部分分數整體筆試通過基本沒有太大懸念。3.3 文本輸出格式的細節(jié)技巧還有一個非常容易被忽視的細節(jié)輸出格式。很多在線判題系統(tǒng)對輸出格式的檢查是“非對即錯”的多一個空格、少一個換行都可能導致Wrong Answer。我見過最典型的案例是要求輸出“每個數字占一行”結果有同學把所有數字用空格連接成一行輸出導致全錯?;蛘咭筝敵鼋Y果末尾不能有多余空格結果用了 .join(map(str, arr))導致最后一組數據后多了一個空格同樣被判錯。這里分享一個穩(wěn)妥的輸出格式方案需要輸出一個數組時優(yōu)先使用print( .join(map(str, result)))這樣能確保元素之間只有一個空格且末尾沒有多余空格。如果需要每個元素占一行用print(\n.join(map(str, result)))。如果需要輸出列表直接用print(result)也是可以的但要注意??突蛸惔a這類平臺的Python版本可能不完全一致直接打印列表時使用的分隔符可能有差異。保險起見還是手動處理格式更穩(wěn)妥。我在幫助學弟學妹們復盤筆試的時候發(fā)現輸出格式導致的失分率出奇的高幾乎每兩個人里就有一個人因為格式問題丟過分。這個細節(jié)雖然在學校的大作業(yè)里不扣分但在線上筆試中就是實打實的扣分點需要在考前就形成正確的輸出習慣。4. 常見問題與備考建議速查4.1 編程題高頻問題排查記錄我根據自己的筆試經驗和多次復盤整理了下面這張高頻問題速查表覆蓋了大多數同學在在線筆試中遇到的典型坑。問題類型典型表現排查思路與解決方案輸入解析錯誤ValueError或IndexError確認是用sys.stdin.read()還是input()明確輸入是否包含多行、是否有空行輸出格式不符提示Wrong Answer但本地正確檢查結尾是否有空格、是否缺少換行、每行輸出值是否用對分隔符空值/邊界值未處理傳入空數組時崩潰寫代碼前先明確邊界條件給函數入口加if not ...的保護判斷遞歸棧溢出大數據量時RecursionError優(yōu)先用迭代解法避免使用遞歸遍歷大數組或大深度樹結構哈希表修改沖突RuntimeError: dictionary changed size during iteration遍歷哈希表時不要直接增刪元素先收集需要操作的key循環(huán)結束后再統(tǒng)一處理Python縮進錯亂粘貼后運行報IndentationError寫完代碼后全選格式化或者從本地復制時使用空格縮進而非Tab這張表我在每次考前都會讓自己過一遍。尤其是“哈希表遍歷時修改”這個坑在校招筆試的查重、頻率統(tǒng)計類題目中特別常見。很多場景下你需要遍歷哈希表并刪除某些不滿足條件的鍵值對直接刪會拋異常正確做法是先記錄需要刪除的鍵遍歷結束后再統(tǒng)一刪除。4.2 平安科技筆試的真實時間分配策略90分鐘做3到5道題時間看起來還算充裕但如果前面某道題卡住了后面就會很被動。我的建議是拿到卷子后先把所有題目從頭到尾讀一遍給每道題標注難度等級和預估時間然后從最簡單的題目開始做。具體的時間分配策略是前10分鐘通讀所有題目標注哪些是必拿分的簡單題哪些是需要思考的中等題哪些是最后攻堅的壓軸題。60到70分鐘集中精力做簡單題和中等題。簡單題一次通過率要爭取100%中等題如果一次寫不出完整解法先把思路寫清楚再把核心代碼寫出來拿到大部分測試用例的分數。剩下10到20分鐘攻壓軸題。即使寫不出完整版本也要把題目中涉及的線程安全思路、鎖模型、異常處理框架寫出來讓判卷人看到你有完整的工程思維。還有一個實際經驗如果某道題卡了15分鐘還沒思路果斷跳過先把后面能拿的分拿上。在線筆試是分測試點給分的一道題全錯和完全沒做的區(qū)別不大但后面簡單題的全分卻是實實在在的。我見過太多同學在壓軸題上死活憋不出來結果前面的簡單題代碼都來不及寫完最后總分一塌糊涂。4.3 針對平安校招方向的筆試備考建議結合平安科技的業(yè)務方向金融科技、保險科技、智慧城市等在備考時除了常規(guī)刷題我建議額外關注以下幾個方向字符串處理的編碼規(guī)范金融系統(tǒng)中有大量賬號、身份證號、手機號等敏感數據的處理和脫敏筆試中的字符串題往往就是這些業(yè)務場景的簡化版。注意字符編碼問題Python3中字符串默認是Unicode但在某些在線平臺中可能需要對中文字符做額外處理。線程安全與并發(fā)控制平安的核心系統(tǒng)對并發(fā)安全要求極高筆試中出現多線程交替打印、模擬轉賬等題目并非偶然。建議熟練掌握Lock、RLock、Semaphore、Condition等并發(fā)原語并能解釋它們之間的區(qū)別和適用場景。數據庫基礎有些崗位的筆試會加入SQL題尤其是后端開發(fā)、數據開發(fā)方向。基本的JOIN、GROUP BY、HAVING、子查詢是必須掌握的建議把常見的查詢場景寫一遍。業(yè)務場景邏輯題平安筆試中也出現過類似“根據交易流水判斷是否存在異常交易”的簡化場景題這類題目本質是模擬題關鍵在于設計清晰的數據結構和邏輯流程。不要急于寫代碼先在草稿紙上畫清楚狀態(tài)流轉再轉換成代碼。時間規(guī)劃上如果還有一個月準備前兩周按模板刷LeetCode高頻題字符串、數組、哈希表、DP入門、二叉樹遍歷第三周開始做模擬筆試嚴格按照90分鐘時限在??突蛸惔a平臺進行訓練最后一周重點復習自己容易出錯的知識點和題目類型。5. 2020年壓軸題深挖多線程并發(fā)協作的完整思路延伸5.1 從交替打印擴展到生產者消費者模型前面提到多線程交替打印是一道很有平安特色的題但在實際判卷中這道題經常會出現一個加強版在交替打印的基礎上要求實現一個生產者-消費者模型生產者線程產生數據放入緩沖區(qū)消費者線程從緩沖區(qū)取出數據進行處理要求緩沖區(qū)滿時生產者等待緩沖區(qū)空時消費者等待。這個模型本質上是操作系統(tǒng)課程中的經典同步問題但在筆試中用代碼實現時很多人會卡在“條件變量”的使用上。Python中推薦使用threading.Condition來實現等待和通知機制參考實現如下import threading import time import random class ProducerConsumer: def __init__(self, capacity10): self.buffer [] self.capacity capacity self.cond threading.Condition() def produce(self, item): with self.cond: while len(self.buffer) self.capacity: print(緩沖區(qū)滿生產者等待...) self.cond.wait() self.buffer.append(item) print(f生產了 {item}緩沖區(qū)大小: {len(self.buffer)}) self.cond.notify_all() def consume(self): with self.cond: while not self.buffer: print(緩沖區(qū)空消費者等待...) self.cond.wait() item self.buffer.pop(0) print(f消費了 {item}緩沖區(qū)大小: {len(self.buffer)}) self.cond.notify_all() return item pc ProducerConsumer(capacity5) def producer_worker(): for i in range(10): pc.produce(i) time.sleep(random.random() * 0.1) def consumer_worker(): for _ in range(10): pc.consume() time.sleep(random.random() * 0.1) t1 threading.Thread(targetproducer_worker) t2 threading.Thread(targetconsumer_worker) t1.start() t2.start() t1.join() t2.join()這里面有兩個非常容易出錯的細節(jié)第一while len(self.buffer) self.capacity中必須使用while循環(huán)而不是if。原因是當多個生產者線程同時被喚醒時可能出現“虛假喚醒”或“競爭性喚醒”即使一個線程被喚醒條件仍可能不滿足。使用while循環(huán)能在每次被喚醒后重新檢查條件確保安全性。第二notify_all()和notify()的選擇。如果只有一個生產者和一個消費者用notify()就足夠了。但如果存在多個生產者和多個消費者用notify()可能只會喚醒同類線程導致信號丟失所以更穩(wěn)妥的做法是使用notify_all()。如果筆試中遇到這類題我建議先明確你的設計目標是單生產者單消費者還是多生產者多消費者。不同場景下的最佳實現方式是不同的這也能體現你對并發(fā)模型的理解深度而不只是背了一個模板。5.2 線程安全與死鎖預防的筆試要點平安的并發(fā)編程題通常不會直接問“什么是死鎖”而是會給你一個存在死鎖隱患的代碼片段讓你找出問題并修復。這是我整理2020年筆試反饋時發(fā)現的一個集中考點。死鎖產生的四個必要條件是互斥、持有并等待、不可剝奪、循環(huán)等待。筆試中讓你修復死鎖最常見的解法是破壞“循環(huán)等待”條件即所有線程按相同的順序獲取鎖。舉個例子如果線程A持有鎖1去申請鎖2而線程B持有鎖2去申請鎖1就會產生死鎖。修復方案很直接強制所有線程先申請鎖1再申請鎖2徹底消除循環(huán)等待。在筆試中如果你發(fā)現題目給出的多線程代碼可能存在死鎖風險一定要在答案中明確指出問題所在并給出修復方案這比單純跑通代碼更讓判卷人認可。因為判卷人看的不僅是你寫代碼的能力更是你識別并發(fā)風險的能力。另外在實際線上筆試環(huán)境中多線程代碼的評測結果可能不是實時的、確定的。線程調度的不確定性導致即使代碼邏輯完全正確輸出順序也未必和預期完全一致。所以這類題目的判分通常是以“關鍵輸出是否按順序出現”作為依據而非嚴格逐字符匹配。我在練習時就會故意運行多次確認每次運行結果都和預期一致才敢提交。5.3 并發(fā)場景題在面試中的追問方向順帶提一句如果筆試中出現了多線程題面試時面試官大概率會圍繞它追問。常見的問題包括Lock和RLock的區(qū)別是什么什么時候用RLockCondition的wait()在調用前為什么要持有鎖如果生產者的速度遠大于消費者的速度怎么優(yōu)化使用queue.Queue和自己實現的條件變量有什么區(qū)別這些問題如果只是背答案容易露餡建議自己在本地多寫幾個并發(fā)小例子把Lock、RLock、Condition、Semaphore、queue.Queue都實際用一遍觀察它們的行為差異。紙上得來終覺淺并發(fā)這塊必須親手跑代碼才能形成真正的理解。6. 從筆試題目看平安的用人標準與復習優(yōu)先級6.1 編程題背后的考察邏輯把平安2020年的編程題放在一起看能清晰地感受到這家公司在技術校招上的考察標準重視基礎強調規(guī)范關注業(yè)務場景?;A優(yōu)先沒有太多偏題怪題大部分題目是LeetCode中檔難度及以下說明平安更想招算法基礎扎實的候選人而不是刷題機器。規(guī)范至上從字符串壓縮的邊界條件到鏈表反轉的指針細節(jié)再到多線程代碼的死鎖風險處處在考察代碼規(guī)范性和細節(jié)把控能力。這個和金融行業(yè)對代碼質量的高要求是吻合的。場景驅動多線程并發(fā)題、數據統(tǒng)計題的出題背景基本都能在平安的業(yè)務系統(tǒng)中找到對應的影子這說明筆試不是單純考算法而是希望候選人能具備將技術應用到實際業(yè)務場景的基本素養(yǎng)。我當時準備校招時刷了大約200道LeetCode題核心刷了三遍第一遍按類型刷建立知識體系第二遍按難度刷提升手感第三遍只刷高頻題和自己錯過的題鞏固薄弱環(huán)節(jié)。對于平安這個級別的公司這套方法完全夠用。6.2 高效刷題的正確姿勢說到刷題方法我見過太多無效刷題的案例最常見的就是“看題五分鐘看答案兩小時”看的時候覺得都懂了合上答案自己寫又卡殼。這種刷法對校招筆試基本沒有幫助。正確做法是給自己定一個規(guī)則每道題至少獨立思考20分鐘如果沒有思路允許看題解但看完題解后必須合上答案自己從頭到尾把代碼寫一遍。寫完后再對比答案看思路是否一致、代碼是否有優(yōu)化空間。通過這樣的“反饋式刷題”才能把一道題真正內化。同時建議建立自己的錯題本記錄每道題的錯誤原因。比如“數組指針越界”“沒有處理空輸入”“遞歸忘記寫終止條件”等??记胺e題本比刷新題更高效因為重復踩同一個坑才是筆試失分的主要來源。6.3 關于2025年Python一級編程題的延伸思考最后聊一個有意思的題外話。這段時間在查資料時看到“python2025.3一級編程題題目及答案”這個熱搜詞說明Python編程基礎考核的熱度在持續(xù)上升。雖然“一級編程題”通常面向的是Python初學者和青少年等級考試但其中考察的基本功——變量類型、條件判斷、循環(huán)、列表操作、字符串方法——恰恰是校招筆試中最核心的底層能力。別覺得一級考題簡單就不屑一顧我見過不少校招生在筆試里寫出if a 1:這種低級語法錯誤。把基礎打牢其實是最被低估的競爭力。如果時間充裕與其反復刷高難度題不如把Python基礎語法、常用內置方法、標準庫中最常見的模塊過一遍。我在2020年筆試時就因為在itertools模塊上比較熟悉寫一道排列組合題時直接用itertools.permutations節(jié)省了大量時間。備考編程題這件事講究的是“以終為始”。你要想清楚筆試考的是什么再倒推自己需要掌握什么。平安這類金融科技公司的筆試不是要和ACM選手比“快”而是和業(yè)務系統(tǒng)的要求比“穩(wěn)”。能寫對、寫規(guī)范、寫清楚比能寫出花來更重要。從我自己的經歷來看平安科技的2020年校招編程題整體難度適中認真準備一兩個月完全有能力通過。希望這篇整理能幫你少走一些彎路。如果有具體題目想深入討論歡迎在評論區(qū)交流我盡量抽出時間回復。