← 返回博客列表
Uber

🚨 Uber 2026 OA 真题全解析:二进制位操作 + 单调栈 + 子数组排列 + 数字交换配对 —— 22 分钟 4 题 AC!

2026-01-20

制造焦虑:打破幻觉

最近冲了 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. 将问题看作二进制处理
  2. 从低位到高位处理每一位,同时维护进位
  3. 当前位值 = 原位值 + 进位
    • 若值为 1:可以直接减法消掉,操作数 +1,或者加法产生进位
    • 若值为 2(位 1 + 进位 1):直接进位,不增加操作
  4. 累加操作数
  5. 最终进位为 0 时结束

💡 关键洞察

🧑‍💻 代码实现

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

🔍 题目描述

每个物品售价 = 原价 − 右边第一个 ≤ 当前价格的物品的价格(若无则按原价出售)。

总售价按原价出售物品的索引

📝 解题思路

  1. 从右向左遍历物品
  2. 使用单调递增栈寻找右边第一个 ≤ 当前价格的物品
  3. 栈空 ⇒ 原价出售,记录索引
  4. 栈非空 ⇒ 售价 = 原价 − 栈顶价格
  5. 累加总售价
  6. 输出总售价及原价出售的物品索引(升序)

🧑‍💻 代码实现

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))

⚠️ 小技巧


Q3: Balanced Subarray

🔍 题目描述

对于每个 k(1 ~ n),判断是否存在一个子数组恰好是 1 ~ k 的排列

📝 解题思路

  1. 先记录每个数字在排列中的位置 pos[value]
  2. k = 1 开始,维护包含数字 1 ~ k 的最小位置区间 [L, R]
    • L = min(pos[1..k])
    • R = max(pos[1..k])
  3. 如果 R − L + 1 == k,则 k 是 balanced
    • 区间长度恰好等于 k,且值域为 1 ~ k,必为排列
  4. 否则不是 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]

⚠️ 小技巧


Q4: Maximum Pairs by Swapping Digits

🔍 题目描述

两个数字若可通过最多两次交换某些位置的数字变成彼此(含相等),算作一对。求总对数

📝 解题思路

  1. 长度不同 ⇒ 不可能配对
  2. 长度相同
    • 将数字转为字符串并排序字符
    • 若排序后相同 ⇒ 可通过若干次交换变成彼此(计数)
    • 若排序后不同
      • 统计不同位置的字符
      • 若不同位置数 ≤ 4 且字符可两两匹配 ⇒ 可两次交换
  3. 实现步骤
    • 先按长度分组
    • 组内用哈希表统计排序串频次计算相等对数
    • 对不等情况检查是否符合两次交换条件

🧑‍💻 代码实现

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 对

⚠️ 小技巧


复杂度分析

题目 时间复杂度 空间复杂度
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 支持方案:


👉 立即添加微信:Coding0201

不要让 4 道 OA 题,毁掉你的 Uber Offer。


本文由 oavoservice 团队原创,转载请注明出处。