← 返回博客列表
Microsoft

🚨 Microsoft 2026 Codility OA 真题流出!110 分钟 2 道题,为何看似简单却挂了一大片?

2026-01-24

最近,Microsoft 的 Codility OA 正在大量发放中。

很多同学看到题目后的第一反应是:"稳了,这不就是 DP/贪心 吗?"

千万别大意。

如果你只把它当成普通的算法题写,哪怕 Bug Free,大概率也只能拿个 Rej。

我们 oavoservice 团队第一时间拿到了真题,发现这里面埋了无数个 Engineering Judgment(工程判断力) 的深坑。

🔍 为什么 Microsoft Codility 的题"阴"?

Microsoft 不像 Google/Meta 那样喜欢出 LeetCode Hard,但它有个更恶心的特点:

题目描述很长,业务场景复杂
需要自己处理输入输出
边界条件极其刁钻
DP 状态定义稍有偏差,全盘皆输

而且 Codility 平台的特点是:

这种"盲打"模式,对心态的考验极大。

昨天我们有个 UIUC 的学员,第一题写了 40 分钟,提交后发现只过了 60%,当场就慌了。如果不是我们的 Senior 导师实时在语音里稳住他:"别急,这是 DP 状态转移出了问题,重新定义状态!",他大概率第二题都写不完。

最后结果?110分钟,2道题,全部 All Passed。 稳稳拿下面试门票。

今天把这套热乎的真题拆解一下,告诉你们坑都在哪。

💻 真题一:多米诺骨牌序列(Domino Sequence)

🔍 题目核心

给定长度为 2*N 的数组 A,表示 N 个多米诺骨牌。每个骨牌由两个数字组成:

正确的多米诺序列:相邻骨牌的接触部分数字必须相同。

题目要求:最少需要移除多少个骨牌,使剩余骨牌形成正确序列?

限制

示例解析

Example 1:

A = [2, 4, 1, 3, 4, 6, 2, 4, 1, 6]
骨牌:(2,4), (1,3), (4,6), (2,4), (1,6)

答案:3

🤯 为什么这题挂了一大片?

绝大多数人看到这题,第一反应是:

❌ "这不就是最长连续子序列吗?"
❌ "用贪心,能连就连!"
❌ "暴力枚举所有可能!"

然后越写越乱,最后发现根本处理不了:

  1. 如何定义"可连接"?
  2. 如何处理多个可能的起点?
  3. 如何保证找到全局最优解?

✅ 正确的工程思维

这是一个**「最长递增子序列」的变种 + DP」**问题。

关键洞察

这不是"贪心",而是"动态规划"!

💣 隐形坑点

坑点 1:数组索引转换

# 错误写法
left = A[i]  # ❌ 这是什么?

# 正确写法
left = A[2*i]      # 第 i 个骨牌的左边
right = A[2*i + 1]  # 第 i 个骨牌的右边

坑点 2:边界条件

坑点 3:DP 初始化

🎯 满分实现(Python)

def solution(A):
    if len(A) == 0:
        return 0
    
    n = len(A) // 2
    if n == 1:
        return 0
    
    # 构建骨牌列表
    dominoes = []
    for i in range(n):
        left = A[2 * i]
        right = A[2 * i + 1]
        dominoes.append((left, right))
    
    # DP: dp[i] 表示以第 i 个骨牌结尾的最长序列长度
    dp = [1] * n
    
    for i in range(1, n):
        for j in range(i):
            # 如果第 j 个骨牌的右边等于第 i 个骨牌的左边
            if dominoes[j][1] == dominoes[i][0]:
                dp[i] = max(dp[i], dp[j] + 1)
    
    # 最长序列的长度
    max_keep = max(dp)
    
    # 需要移除的数量
    return n - max_keep

⚡️ 时间复杂度优化

上面的解法是 O(n²),对于 N=50,000 可能会 TLE。

优化思路:用 HashMap 记录每个右值对应的最长序列

def solution(A):
    if len(A) == 0:
        return 0
    
    n = len(A) // 2
    if n == 1:
        return 0
    
    # HashMap: right_value -> max_length
    max_len = {}
    overall_max = 1
    
    for i in range(n):
        left = A[2 * i]
        right = A[2 * i + 1]
        
        # 查找能连接到当前骨牌左边的最长序列
        current_len = max_len.get(left, 0) + 1
        
        # 更新以 right 结尾的最长序列
        max_len[right] = max(max_len.get(right, 0), current_len)
        
        overall_max = max(overall_max, current_len)
    
    return n - overall_max

时间复杂度:O(n)
空间复杂度:O(1) (因为骨牌数字只有 1-6)

🔢 真题二:三个非相邻元素的最大和(Maximum Sum of Three Non-Adjacent Elements)

🔍 题目核心

给定整数数组 A,选择恰好 3 个非相邻元素,使其和最大。

非相邻定义:三个元素的索引必须满足任意两个索引的差 > 1。

限制

示例解析

Example 1:

A = [8, -4, -7, -5, -5, -4, 8, 8]

答案:12

Example 2:

A = [-2, -8, 1, 5, -8, 4, 7, 6]

答案:15

Example 3(负数情况):

A = [-3, 0, -6, -7, -9, -5, -2, -6]

答案:-9

🤯 隐形杀招:为什么 90% 的人会挂?

看似简单的题目,实际上有三个致命陷阱

陷阱 1:暴力枚举会 TLE

# ❌ 这样写必挂
max_sum = float('-inf')
for i in range(n):
    for j in range(i+2, n):
        for k in range(j+2, n):
            max_sum = max(max_sum, A[i] + A[j] + A[k])

时间复杂度:O(n³),对于 N=100,000 必然超时

陷阱 2:贪心选 3 个最大值会错

# ❌ 错误思路
sorted_indices = sorted(range(n), key=lambda i: A[i], reverse=True)
# 然后试图找 3 个不相邻的?

反例:

A = [10, 1, 1, 1, 1, 1, 9, 1, 1, 1, 1, 1, 8]

贪心在有负数时完全失效!

陷阱 3:DP 状态定义不清晰

很多人想用 DP,但不知道状态怎么定义:

# ❌ 错误状态
dp[i] = "前 i 个元素的最大和"  # 选了几个?

✅ 正确的工程思维:枚举中间元素 + 预处理

核心洞察

固定中间元素,问题变简单!

  1. 枚举第二个元素的位置 j(中间那个)
  2. [0, j-2] 中找最大值(第一个元素)
  3. [j+2, n-1] 中找最大值(第三个元素)

关键优化:预处理前缀/后缀最大值

💣 最容易翻车的地方

边界条件:

负数处理:

🎯 满分实现(Python)

def solution(A):
    n = len(A)
    
    # 边界检查
    if n < 5:
        return float('-inf')  # 不可能有解
    
    # 预处理:prefix_max[i] 表示 [0, i] 的最大值
    prefix_max = [float('-inf')] * n
    prefix_max[0] = A[0]
    for i in range(1, n):
        prefix_max[i] = max(prefix_max[i-1], A[i])
    
    # 预处理:suffix_max[i] 表示 [i, n-1] 的最大值
    suffix_max = [float('-inf')] * n
    suffix_max[n-1] = A[n-1]
    for i in range(n-2, -1, -1):
        suffix_max[i] = max(suffix_max[i+1], A[i])
    
    # 枚举中间元素
    max_sum = float('-inf')
    for j in range(2, n-2):
        # 第一个元素从 [0, j-2] 中选
        first = prefix_max[j-2]
        # 第三个元素从 [j+2, n-1] 中选
        third = suffix_max[j+2]
        
        current_sum = first + A[j] + third
        max_sum = max(max_sum, current_sum)
    
    return max_sum

时间复杂度:O(n)
空间复杂度:O(n)

⚡️ 空间优化版本

如果面试官追问"能否 O(1) 空间":

def solution(A):
    n = len(A)
    if n < 5:
        return float('-inf')
    
    max_sum = float('-inf')
    
    for j in range(2, n-2):
        # 实时计算左边最大值
        left_max = max(A[0:j-1])
        # 实时计算右边最大值
        right_max = max(A[j+2:])
        
        max_sum = max(max_sum, left_max + A[j] + right_max)
    
    return max_sum

但这样会退化到 O(n²),不推荐!面试时先问清楚 trade-off。

💡 说句现实的:Microsoft Codility OA,真的不适合裸考

Microsoft SDE 的 TC(北美):

New Grad:$160k – $180k
SDE II:$200k – $250k

而 Codility OA 的残酷现实是:

输入输出需要自己处理
没有交互式调试
一个边界条件错误 = 全挂
一次机会,可能等半年

我们在 oavoservice 做的事情,其实很简单:

你写代码
有人盯状态定义
有人盯边界条件
有人盯时间复杂度
在你要 TLE / 写歪之前,直接叫停

不是你不行,是一个人上场风险太高。

🚀 oavoservice:你的满分通关专家

面对 Microsoft 这种 工程量大、细节层层递进 的 Codility OA,你需要的不只是一份答案,而是一个专业的 技术团队 支持。

我们提供:

Codility 平台全覆盖:熟悉平台特性,规避隐藏陷阱
代码符合工业级标准:Production-Level Code,不是刷题风格
实时语音助攻:OA 进行时,资深工程师实时指导
满分保障:不过不收费,我们对自己的实力有信心

不要让一道 DP 状态转移、一个边界条件,卡住你通往 $200k Offer 的路。

We consistently provide professional online assessment services for major tech companies like Microsoft, Google, and Amazon, guaranteeing perfect scores.

👉 立即添加微信:Coding0201

锁定你的 Microsoft 面试机会!