製造焦慮:打破幻覺
最近衝了 Uber 2026 OA,平台依舊是 CodeSignal,題量 4 道題,70 分鐘完成。
說實話,這次題目對於有一定基礎的同學來說,熟悉度很高,我自己花了 22 分鐘就全部做完。四題裡有兩個題幾乎是白送的,看一眼就能寫出來,完全沒有難度。
為了幫助大家提前練手,我把每道題的思路和做法都整理出來了。
Uber 2026 OA 面試概覽
| 項目 | 詳情 |
|---|---|
| 平台 | CodeSignal |
| 題量 | 4 道 |
| 時間 | 70 分鐘 |
| 難度 | 中等偏上,但部分題目熟悉即可快速完成 |
考察點
- 二進位運算與位操作
- 堆疊與單調堆疊技巧
- 子陣列與排列判斷
- 字串操作與交換匹配邏輯
總體來說,Uber OA 更看重邏輯清晰度、思路正確性和實現速度,演算法難度不是很大,但細節處理容易出錯。
Q1: Minimum Operations to Reduce Binary Number to Zero
🔍 題目描述
給定一個正整數 n,每次操作可以加或減 2^i(i ≥ 0),求將 n 變為 0 的最少操作次數。
📝 解題思路
- 將問題看作二進位處理
- 從低位到高位處理每一位,同時維護進位
- 當前位值 = 原位值 + 進位
- 若值為 1:可以直接減法消掉,操作數 +1,或者加法產生進位
- 若值為 2(位 1 + 進位 1):直接進位,不增加操作
- 累加操作數
- 最終進位為 0 時結束
💡 關鍵洞察
- 二進位中連續的 1 可以透過「加 1 進位」然後「減 1」來優化操作數
- 例如:
111(7) → 加 1 變成1000(8) → 減 8,共 2 次操作 - 而直接減:
111→ 減 4 → 減 2 → 減 1,需要 3 次操作
🧑💻 程式碼實現
def min_operations_to_zero(n: int) -> int:
"""
Uber OA 真題:二進位數變為 0 的最少操作次數
Args:
n: 正整數
Returns:
int: 最少操作次數
"""
operations = 0
carry = 0
while n > 0 or carry > 0:
# 當前位的值 = 原位值 + 進位
current_bit = (n & 1) + carry
if current_bit == 1:
# 值為 1:需要一次操作(加或減)
# 貪心:如果下一位也是 1,選擇加法(產生進位,可能合併連續 1)
next_bit = (n >> 1) & 1
if next_bit == 1:
# 加法:產生進位
carry = 1
else:
# 減法:不產生進位
carry = 0
operations += 1
elif current_bit == 2:
# 值為 2:直接進位,不增加操作
carry = 1
else:
# 值為 0:無需操作
carry = 0
n >>= 1
return operations
# 測試用例
print(min_operations_to_zero(7)) # 7 = 111 -> +1 = 1000 -> -8 = 0, 答案: 2
print(min_operations_to_zero(5)) # 5 = 101 -> -4 = 1 -> -1 = 0, 答案: 2
print(min_operations_to_zero(1)) # 1 = 1 -> -1 = 0, 答案: 1
print(min_operations_to_zero(15)) # 15 = 1111 -> +1 = 10000 -> -16 = 0, 答案: 2
print(min_operations_to_zero(10)) # 10 = 1010 -> -8 = 2 -> -2 = 0, 答案: 2
⚠️ 小技巧
- 二進位位處理題最關鍵是進位維護
- 一定要從低位向高位遍歷,否則操作數計算會出錯
- 可以畫出二進位位圖快速理解操作邏輯
Q2: Discounted Price Sum
🔍 題目描述
每個物品售價 = 原價 − 右邊第一個 ≤ 當前價格的物品的價格(若無則按原價出售)。
求總售價及按原價出售物品的索引。
📝 解題思路
- 從右向左遍歷物品
- 使用單調遞增堆疊尋找右邊第一個 ≤ 當前價格的物品
- 堆疊空 ⇒ 原價出售,記錄索引
- 堆疊非空 ⇒ 售價 = 原價 − 堆疊頂價格
- 累加總售價
- 輸出總售價及原價出售的物品索引(升序)
🧑💻 程式碼實現
def discounted_price_sum(prices: list) -> tuple:
"""
Uber OA 真題:折扣價格總和
Args:
prices: 物品原價列表
Returns:
tuple: (總售價, 原價出售的索引列表)
"""
n = len(prices)
total = 0
full_price_indices = []
stack = [] # 單調遞增堆疊,存儲 (價格, 索引)
# 從右向左遍歷
for i in range(n - 1, -1, -1):
current_price = prices[i]
# 彈出所有大於當前價格的元素
while stack and stack[-1][0] > current_price:
stack.pop()
if not stack:
# 堆疊空:原價出售
total += current_price
full_price_indices.append(i)
else:
# 堆疊非空:折扣價 = 原價 - 右邊第一個 ≤ 當前價格的物品價格
discount_price = current_price - stack[-1][0]
total += discount_price
# 當前元素入堆疊
stack.append((current_price, i))
# 索引升序排列
full_price_indices.sort()
return total, full_price_indices
# 測試用例
prices1 = [8, 4, 6, 2, 3]
print(discounted_price_sum(prices1))
# 分析:
# i=4: 3, 堆疊空, 原價 3
# i=3: 2, 堆疊空, 原價 2
# i=2: 6, 堆疊頂 2 ≤ 6, 售價 6-2=4
# i=1: 4, 堆疊頂 2 ≤ 4, 售價 4-2=2
# i=0: 8, 堆疊頂 4 ≤ 8, 售價 8-4=4
# 總價: 4+2+4+2+3 = 15, 原價索引: [3, 4]
prices2 = [5, 1, 4, 2]
print(discounted_price_sum(prices2))
⚠️ 小技巧
- 單調堆疊是處理「右邊第一個符合條件元素」的經典工具
- 這類題核心是順序和堆疊狀態維護
- 輸出索引前注意排序,否則可能 WA
Q3: Balanced Subarray
🔍 題目描述
對於每個 k(1 ~ n),判斷是否存在一個子陣列恰好是 1 ~ k 的排列。
📝 解題思路
- 先記錄每個數字在排列中的位置
pos[value] - 從
k = 1開始,維護包含數字1 ~ k的最小位置區間[L, R]L = min(pos[1..k])R = max(pos[1..k])
- 如果
R − L + 1 == k,則k是 balanced- 區間長度恰好等於 k,且值域為 1 ~ k,必為排列
- 否則不是 balanced
🧑💻 程式碼實現
def balanced_subarray(arr: list) -> list:
"""
Uber OA 真題:判斷 1~k 是否存在 balanced 子陣列
Args:
arr: 1~n 的排列
Returns:
list: 長度為 n 的布林陣列,result[i] 表示 k=i+1 是否 balanced
"""
n = len(arr)
# 記錄每個數字的位置(1-indexed value -> 0-indexed position)
pos = [0] * (n + 1)
for i, val in enumerate(arr):
pos[val] = i
result = []
min_pos = float('inf')
max_pos = float('-inf')
for k in range(1, n + 1):
# 更新包含 1~k 的區間範圍
min_pos = min(min_pos, pos[k])
max_pos = max(max_pos, pos[k])
# 判斷區間長度是否恰好為 k
interval_len = max_pos - min_pos + 1
if interval_len == k:
result.append(True)
else:
result.append(False)
return result
# 測試用例
arr1 = [3, 1, 2, 5, 4]
print(balanced_subarray(arr1))
# k=1: pos[1]=1, 區間[1,1], len=1 ✓
# k=2: pos[2]=2, 區間[1,2], len=2 ✓
# k=3: pos[3]=0, 區間[0,2], len=3 ✓
# k=4: pos[4]=4, 區間[0,4], len=5 ≠ 4 ✗
# k=5: pos[5]=3, 區間[0,4], len=5 ✓
# 輸出: [True, True, True, False, True]
arr2 = [2, 1, 4, 3]
print(balanced_subarray(arr2))
# k=1: pos[1]=1, 區間[1,1], len=1 ✓
# k=2: pos[2]=0, 區間[0,1], len=2 ✓
# k=3: pos[3]=3, 區間[0,3], len=4 ≠ 3 ✗
# k=4: pos[4]=2, 區間[0,3], len=4 ✓
# 輸出: [True, True, False, True]
⚠️ 小技巧
- 關鍵是記錄數字位置,並維護區間最小值和最大值
- 可以在遍歷中累積更新 min/max,無需重複掃描
- 這種題非常適合用陣列 + 索引映射實現,時間複雜度 O(n)
Q4: Maximum Pairs by Swapping Digits
🔍 題目描述
兩個數字若可透過最多兩次交換某些位置的數字變成彼此(含相等),算作一對。求總對數。
📝 解題思路
- 長度不同 ⇒ 不可能配對
- 長度相同:
- 將數字轉為字串並排序字元
- 若排序後相同 ⇒ 可透過若干次交換變成彼此(計數)
- 若排序後不同:
- 統計不同位置的字元
- 若不同位置數 ≤ 4 且字元可兩兩匹配 ⇒ 可兩次交換
- 實現步驟:
- 先按長度分組
- 組內用雜湊表統計排序串頻次計算相等對數
- 對不等情況檢查是否符合兩次交換條件
🧑💻 程式碼實現
from collections import defaultdict
def max_pairs_by_swapping(nums: list) -> int:
"""
Uber OA 真題:最多兩次交換配對數
Args:
nums: 數字列表
Returns:
int: 可配對的總對數
"""
# 按長度分組
length_groups = defaultdict(list)
for num in nums:
s = str(num)
length_groups[len(s)].append(s)
total_pairs = 0
for length, group in length_groups.items():
n = len(group)
# 統計排序後相同的字串(可透過交換變成彼此)
sorted_count = defaultdict(int)
for s in group:
sorted_s = ''.join(sorted(s))
sorted_count[sorted_s] += 1
# 計算同排序串的配對數:C(count, 2) = count * (count - 1) / 2
for count in sorted_count.values():
total_pairs += count * (count - 1) // 2
return total_pairs
def can_match_with_two_swaps(s1: str, s2: str) -> bool:
"""
檢查兩個字串是否可以透過最多兩次交換變成彼此
"""
if len(s1) != len(s2):
return False
# 找出不同位置
diff_positions = []
for i in range(len(s1)):
if s1[i] != s2[i]:
diff_positions.append(i)
# 0 個不同:已相等
if len(diff_positions) == 0:
return True
# 2 個不同:一次交換
if len(diff_positions) == 2:
i, j = diff_positions
return s1[i] == s2[j] and s1[j] == s2[i]
# 4 個不同:兩次交換(需要檢查字元是否匹配)
if len(diff_positions) == 4:
chars1 = [s1[i] for i in diff_positions]
chars2 = [s2[i] for i in diff_positions]
return sorted(chars1) == sorted(chars2)
return False
# 更精確的版本(考慮不同位置的交換)
def max_pairs_precise(nums: list) -> int:
"""
精確版本:檢查每對是否可透過最多兩次交換配對
"""
n = len(nums)
pairs = 0
for i in range(n):
for j in range(i + 1, n):
s1, s2 = str(nums[i]), str(nums[j])
if can_match_with_two_swaps(s1, s2):
pairs += 1
return pairs
# 測試用例
nums1 = [123, 321, 132, 456]
print(max_pairs_by_swapping(nums1)) # 123, 321, 132 可互相配對,共 3 對
nums2 = [111, 111, 111]
print(max_pairs_by_swapping(nums2)) # 3 個相同,C(3,2) = 3 對
nums3 = [12, 21, 34, 43, 56]
print(max_pairs_by_swapping(nums3)) # (12,21), (34,43) = 2 對
⚠️ 小技巧
- 排序字串可以快速判斷是否可能透過交換變成彼此
- 不同位置 ≤ 4 是關鍵判斷條件
- 雜湊表分組統計可以大幅減少時間複雜度
複雜度分析
| 題目 | 時間複雜度 | 空間複雜度 |
|---|---|---|
| Q1: Binary to Zero | O(log n) | O(1) |
| Q2: Discounted Price | O(n) | O(n) |
| Q3: Balanced Subarray | O(n) | O(n) |
| Q4: Max Pairs | O(n² × L) 或 O(n × L log L) | O(n × L) |
其中 L = 數字的最大位數
🔥 為什麼大多數人會掛?
| 常見錯誤 | 正確做法 |
|---|---|
| Q1 忘記處理進位 | 維護 carry 變數 |
| Q1 從高位開始處理 | 必須從低位向高位遍歷 |
| Q2 單調堆疊方向錯誤 | 從右向左遍歷 |
| Q2 索引沒排序 | 輸出前升序排列 |
| Q3 重複掃描求 min/max | 累積更新 min_pos, max_pos |
| Q4 只考慮相等情況 | 還要考慮 2 次和 4 次不同位置 |
FAQ | Uber 2026 OA 常見問題
Q1: Uber 2026 OA 有幾道題?難度如何?
Uber 2026 OA 一共有 4 道題,題型包括二進位加減最少操作數、單調堆疊折扣售價、子陣列排列判斷和數字最多交換匹配對數。難度偏中等偏上,但大部分題型屬於常見模板題型,只要熟悉 CodeSignal 平台和 Python 解題思路,通常可以快速完成。
Q2: 完成 Uber 2026 OA 大概需要多長時間?
根據實戰經驗,如果熟悉題型,四題可以在 20–30 分鐘內完成全部操作。我自己整套題花了 22 分鐘就一次過,透過合理規劃題目順序和使用 Python 模板程式碼,可以顯著節省時間。
Q3: Uber 2026 OA 有哪些考察重點?
主要考察以下能力:
- 二進位位運算和進位處理
- 單調堆疊應用和折扣售價計算邏輯
- 子陣列排列判斷和區間最小/最大位置維護
- 字串數字匹配與最多兩次交換邏輯
此外,還會考察邊界條件處理、演算法複雜度理解和程式碼實現能力。
Q4: Python 在 Uber OA 中有哪些優勢?
Python 語法簡潔,內建資料結構(如字典、列表、集合)和函數(如 min, max, sorted)非常適合處理 OA 題目邏輯,尤其是:
- 二進位位操作和進位模擬
- 單調堆疊或堆疊操作
- 索引映射和子陣列判斷
- 字串轉換和雜湊統計
合理使用 Python 模板程式碼,可以提高完成速度和正確率。
Q5: 有沒有快速通過 Uber OA 的經驗技巧?
經驗總結如下:
- 熟悉題型模板:二進位位處理、單調堆疊、區間判斷、字元交換匹配
- 先理清邏輯再寫程式碼:畫草稿或用小樣例測試
- 時間分配合理:先做熟悉題,難題留最後
- 邊界條件複盤:尤其是交易次數、進位、索引長度、字元匹配
- 模板程式碼複用:提前準備好函數/工具方法,可直接呼叫
Q6: Uber OA 的題目會重複嗎?
根據實戰經驗,CodeSignal 平台上的題目類型重複率較高,尤其是類似二進位操作、單調堆疊和子陣列排列的經典模板題型。提前練習這些題型,理解通用解法和邊界處理方法,可以大幅提高 AC 準確率。
📞 oavoservice 服務
別再浪費時間!Uber / TikTok / Stripe OA 快速通關指南。
很多同學其實不是不會寫,而是 OA 時間壓力太大、容易在細節上翻車。
針對這種情況,我們提供成熟的大廠 OA 支援方案:
- ✅ OA代寫:CodeSignal / HackerRank / 牛客網 滿分保障
- ✅ 筆試協助:高頻題型快速處理
- ✅ 遠程無痕操作:過程無痕、執行穩定
- ✅ 目標:幫助你在關鍵 OA 環節一次到位,減少不必要的消耗
👉 立即添加微信:Coding0201
不要讓 4 道 OA 題,毀掉你的 Uber Offer。
本文由 oavoservice 團隊原創,轉載請註明出處。