DRW Online Assessment 全解析 | 真题拆解·备考策略

1,465Times read

DRW 是全球最顶尖的自营交易公司之一,其招聘以数学密度高、淘汰率高著称。不同于一般投行的行为题筛选,DRW 的 OA 直接把概率论、Markov Chain、期权定价和图论算法砸到你面前,限时作答,没有退路。本文整合 Programhelp 平台上多位真实候选人的一手反馈,深度拆解 DRW Online Assessment 的考察逻辑与完整面试流程,帮你在这条竞争最激烈的量化赛道上,提前建立压倒性的优势。

DRW Online Assessment 全解析 | 真题拆解·备考策略

DRW 招募时间线

Step 01 网申

在 DRW 官网提交申请,约 1 周内收到 OA 邀请。部分岗位支持内推(Employee Referral),可加快流程。建议简历突出数学竞赛、编程项目或量化研究经历。

Step 02 OA

  • Quant 方向:6 道数学/统计题,约 45 分钟,限时完成,题目含线性代数、概率论、Markov Chain 等。据候选人反馈,有 1 道题目故意设计成无解,考察候选人面对不确定性的心态。
  • Dev 方向:Codility 平台,3 道编程题(Easy + Medium + Hard),覆盖字符串处理、贪心算法、图论匹配,约 2 小时。

完成窗口通常为 72 小时,建议选择在安静、网络稳定的环境下完整作答。

Step 03 Phone Screen

约 30 分钟,主要聊背景动机(为什么 DRW?为什么 Quant?)及简单的心算测试。节奏相对轻松,但要准备好清晰的 motivation statement。

Step 04 Technical Interview

由 Junior Quant Trader 或研究员主持,约 45 分钟。考察概率统计、期望值计算、Market Making 逻辑,以及正态分布、置信区间等基础题。Quant Researcher 岗还会涉及 ML 模型问题。

Step 05 Superday

现场赴芝加哥(或 Zoom)进行,Day 1 下午报到 + 交流,Day 2 全天面试。涵盖数据分析任务、Trading Game(扑克/骰子博弈)、背靠背技术面与行为面试。DRW 强调 Day 1 的社交活动对最终决策同样重要,不建议缺席。

DRW / Codility 6 道真题分享

题目 1:游戏生命值计算

题目描述

想象一个电子游戏,玩家操控角色闯过多个关卡。角色的初始生命值为 initialHealth,生命值会随着关卡进程发生变化。

给定一个整数数组 deltas,表示每一关的生命值变化。第 i 关(从 0 开始计数)会让角色当前的生命值变化 deltas[i]

规则:

  • 当角色的生命值变为小于 0 时,会立即被设置为 0。
  • 当角色的生命值变为大于 100 时,会立即被设置为 100。

你的任务是:计算并返回角色闯过所有关卡后的最终生命值。

解题思路

直接模拟即可:

  1. 初始化 currentHealth = initialHealth
  2. 遍历 deltas 数组,每次更新 currentHealth += deltas[i]
  3. 每次更新后,将 currentHealth 限制在 [0, 100] 之间
  4. 遍历结束后返回 currentHealth

Java 实现

public class Solution {
    public int solution(int initialHealth, int[] deltas) {
        int current = initialHealth;
        for (int delta : deltas) {
            current += delta;
            if (current < 0) current = 0;
            if (current > 100) current = 100;
        }
        return current;
    }
}

题目 2:匹配子数组模式

题目描述

给定一个整数数组 numbers 和一个表示比较模式的数组 pattern,找出 numbers 中有多少个子数组与给定的 pattern 匹配。

pattern 数组中只包含以下整数:

  • pattern[i] = 1:对应位置的数字比前一个数字
  • pattern[i] = 0:对应位置的数字与前一个数字相等
  • pattern[i] = -1:对应位置的数字比前一个数字

题目保证 numbers.length > pattern.length

解题思路

暴力匹配即可(满足题目时间复杂度要求):

  1. 子数组的长度必须为 pattern.length + 1
  2. 遍历所有可能的起始位置 i,检查从 i 开始的子数组是否匹配 pattern
  3. 统计匹配的子数组数量

Java 实现

public class Solution {
    public int solution(int[] numbers, int[] pattern) {
        int count = 0;
        int m = pattern.length;
        int n = numbers.length;
        
        for (int i = 0; i <= n - m; i++) {
            boolean match = true;
            for (int j = 0; j < m; j++) {
                int curr = numbers[i + j + 1];
                int prev = numbers[i + j];
                if (pattern[j] == 1 && curr <= prev) match = false;
                else if (pattern[j] == 0 && curr != prev) match = false;
                else if (pattern[j] == -1 && curr >= prev) match = false;
            }
            if (match) count++;
        }
        return count;
    }
}

题目 3:矩阵绘制字母 Y

题目描述

给定一个 n × n 的正方形矩阵(n 为奇数),矩阵中只包含数字 012。你可以将任意格子的数字改为 012

目标是计算出在矩阵中画出字母 Y 所需的最少修改次数。

字母 Y 的定义:

  1. 构成 Y 的所有数字都相等:左上到中心的对角线、右上到中心的对角线、从中心垂直向下的所有格子。
  2. 所有不构成 Y 的格子数字都相等,且与构成 Y 的数字不同。

解题思路

枚举所有 6 种可能的颜色组合,计算每种组合需要修改的格子数,取最小值:

  • Y=0, 背景=1 / Y=0, 背景=2
  • Y=1, 背景=0 / Y=1, 背景=2
  • Y=2, 背景=0 / Y=2, 背景=1

Java 实现

public class Solution {
    public int solution(int[][] matrix) {
        int n = matrix.length;
        int center = n / 2;
        boolean[][] isY = new boolean[n][n];
        
        // 标记Y的位置
        for (int i = 0; i < center; i++) {
            isY[i][i] = true;
            isY[i][n - 1 - i] = true;
        }
        for (int i = center; i < n; i++) {
            isY[i][center] = true;
        }
        
        int[][] pairs = {{0,1}, {0,2}, {1,0}, {1,2}, {2,0}, {2,1}};
        int minChanges = Integer.MAX_VALUE;
        
        for (int[] pair : pairs) {
            int yColor = pair[0];
            int bgColor = pair[1];
            int changes = 0;
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    if (isY[i][j]) {
                        if (matrix[i][j] != yColor) changes++;
                    } else {
                        if (matrix[i][j] != bgColor) changes++;
                    }
                }
            }
            minChanges = Math.min(minChanges, changes);
        }
        return minChanges;
    }
}

题目 4:数字翻转配对

题目描述

定义 flipDigits 函数:将整数的数字顺序反转,并去掉结果中的所有前导零。

例如:flipDigits(5070) = 705flipDigits(800) = 8

给定一个非负整数数组 arr,计算满足以下条件的数对 (i, j) 的数量:

  • i ≤ j
  • arr[i] + flipDigits(arr[j]) = arr[j] + flipDigits(arr[i])

解题思路

对等式变形:arr[i] - flipDigits(arr[i]) = arr[j] - flipDigits(arr[j])

因此,我们只需要统计每个 (x - flipDigits(x)) 值出现的次数,再用组合数计算即可。

Java 实现

import java.util.*;

public class Solution {
    public long solution(int[] arr) {
        Map<Long, Long> countMap = new HashMap<>();
        for (int x : arr) {
            long key = x - flipDigits(x);
            countMap.put(key, countMap.getOrDefault(key, 0L) + 1);
        }
        
        long total = 0;
        for (long cnt : countMap.values()) {
            total += cnt * (cnt + 1) / 2;
        }
        return total;
    }
    
    private long flipDigits(int x) {
        long res = 0;
        while (x > 0) {
            res = res * 10 + (x % 10);
            x /= 10;
        }
        return res;
    }
}

题目 5:构造每个字母出现奇数次的字符串

题目描述

编写一个函数,给定整数 N,返回一个由 N 个小写字母(a-z)组成的字符串,要求每个出现过的字母的出现次数都是奇数。

解题思路

  • N 是奇数时:直接用 N'a' 即可('a' 出现奇数次)。
  • N 是偶数时:用 (N-1)'a' 和 1 个 'b' 即可(两个字母都出现奇数次)。

Python 实现

def solution(N):
    if N % 2 == 1:
        return 'a' * N
    else:
        return 'a' * (N - 1) + 'b'

题目 6:最小交换次数使两个数字差最小

题目描述

给定两个数字字符串 ST,可以交换对应位置上的数字,目标是让两个数的差的绝对值尽可能小,求最小交换次数。

解题思路

动态规划:逐位处理,维护三种状态的最小交换次数:

  • dp[0]:当前两个数前缀完全相等
  • dp[1]:当前 S 前缀比 T 前缀大
  • dp[2]:当前 S 前缀比 T 前缀小

Java 实现

public class Solution {
    public int solution(String S, String T) {
        int n = S.length();
        int[] dp = new int[]{0, n + 1, n + 1};
        
        for (int i = 0; i < n; i++) {
            char s = S.charAt(i);
            char t = T.charAt(i);
            int[] next = new int[]{n + 1, n + 1, n + 1};
            
            // 不交换
            updateNext(next, dp, s, t, 0);
            // 交换
            updateNext(next, dp, t, s, 1);
            
            dp = next;
        }
        return Math.min(dp[0], Math.min(dp[1], dp[2]));
    }
    
    private void updateNext(int[] next, int[] dp, char a, char b, int cost) {
        int aVal = a - '0';
        int bVal = b - '0';
        
        if (dp[0] != Integer.MAX_VALUE) {
            if (aVal > bVal) next[1] = Math.min(next[1], dp[0] + cost);
            else if (aVal < bVal) next[2] = Math.min(next[2], dp[0] + cost);
            else next[0] = Math.min(next[0], dp[0] + cost);
        }
        if (dp[1] != Integer.MAX_VALUE) next[1] = Math.min(next[1], dp[1] + cost);
        if (dp[2] != Integer.MAX_VALUE) next[2] = Math.min(next[2], dp[2] + cost);
    }
}

推荐备考资源

  • Tradermath.org:心算与概率题库
  • A Practical Guide to Quant Finance Interviews(绿皮书)
  • LeetCode / Codility:Dev Track 必备
  • Kaggle:Python 数据分析练习
  • DRW 官方备考指南

额外推荐: 如果你想系统提升 OA 通过率和面试表现,强烈建议了解 Programhelp。他们的学长提供专业的 OA 实战辅助 、真题预测、代码优化以及高强度模拟面试,能帮你快速补齐弱点,显著提高备考效率。

有需要的同学可以直接联系 Programhelp 详谈,他们会根据你的情况给出针对性方案。

author avatar
Jory Wang Amazon资深软件开发工程师
Amazon 资深工程师,专注 基础设施核心系统研发,在系统可扩展性、可靠性及成本优化方面具备丰富实战经验。 目前聚焦 FAANG SDE 面试辅导,一年内助力 30+ 位候选人成功斩获 L5 / L6 Offer。
End of text
 0