Preparing For A Software Engineering Interview at Jane Street

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

Preparing for a Software

Engineering interview at Jane


Street
Over the years we’ve done our best to make
our interview processes more transparent to
applicants. While many candidates show up
knowing something about our interviews,
much of the information floating around on
the internet is outdated or wrong.
Hiring is a challenge without easy solutions—after all, we’re trying to evaluate human
beings on multiple dimensions in a contrived environment! What we describe here is
the best balance we’ve found so far between being able to hire excellent people and
not taking too much time—yours or ours. But we know it’s far from perfect. This page
is meant to help interested candidates get a better sense of what to expect in our
Software Engineer interview process.

You can find more detailed information about the evolution of our SWE interview
process on our tech blog, but the most critical bits are here on this page.

Before the interviews


When you submit your application to Jane Street for any role, it’s reviewed by an
actual human. We respond to every application we receive, ideally within a week or
so. Depending on your background we might also suggest you consider another
position. We’ll always be up front with you about what roles you’re being considered
for (or aren’t), so please also let us know what you’re interested in throughout the
process.

If you’ve applied or interviewed before don’t let that stop you from trying again! We
reconsider people all the time—people add to their experiences and our needs often
change as Jane Street grows—so if it didn’t work out a couple of years ago you
might have a better chance this go-around.
The structure of SWE interviews at Jane
Street
There are a few paths you can take to becoming a software engineer at Jane Street,
but they all involve a technical interview that takes place over Zoom, and continue
with later-round interviews that are mostly, if not exclusively, focused on
collaborating on a series of coding problems.

We expect you to write code in a real programming language in these interviews, not
pseudocode. You can use any programming language you’d like, but we strongly
recommend you use the one you’re most familiar with and that best suits the
problem (it’s fine to change your mind as you’re exploring the problem). You should
be comfortable with basic data structures and APIs in your language of choice.

While interviewing, we’re really interested in learning how you work. This means the
journey through the interview is a lot more important than the snapshot of the
solution at the end of it.

So, what do we look for?


From our perspective, the main thing we want to figure out when we interview
someone is: are they someone we want to work with?

To that end, we try to avoid algorithm bingo and puzzles with clever “aha” solutions.
We prefer more open-ended problems that have several plausible angles of attack
and maybe even no single best answer. These problems give us more freedom to
work together and to see how the candidates’ thinking plays out. We are looking for
candidates who engage in clear and productive discussions about the problem at
hand.

That sounds nice enough, but it’s a bit high-level and hand-wavy. So here’s a more
concrete list of suggestions that follow from our overall approach:

• Be nice
• Be clear
• Know your language
• Know what you don’t know
We don’t ask software engineers to do mental math, or math olympiad questions, or
to contemplate logic puzzles. SWE interviews are about programming, plain and
simple. There are other jobs at Jane Street that do care about mental math and logic
puzzles, for good reason. Just not this one. We also don’t award bonus points for
using a functional language like OCaml. Please don’t use OCaml just because you
think it will make us happy. We want to see you at your best, so you should use the
language you’re most comfortable with. If OCaml isn’t your strongest language, then
don’t use it. We don’t go out of our way to hire people who are already familiar with
functional programming. In practice, it’s just not that hard for strong programmers to
pick it up after they start.

What can you do to prepare?


This part is short and sweet. Practice.

We have two resources in particular that boil down both sides of a SWE interview,
ours and yours: a written walkthrough of a question we used to ask candidates, as
well as a mock interview video.

If you haven’t applied for a SWE role at Jane Street yet but feel you’re ready let
us make that easy on you. Fill out a few quick fields, upload your resume, and we’ll
be in touch soon!

What a Jane Street software


engineering interview is like
FEB 28, 2017 | 9 MIN READ

o Share on Facebook

o Share on Twitter

o Share on LinkedIn
By: Sebastian Funk

Are you thinking about applying to Jane Street for a software engineering role? Or
already have a phone interview scheduled but unsure what to expect? Read on as we
walk through an example phone interview with you.
We want to give you some insight into what a typical Jane Street phone interview looks
like and give you a chance to prepare. We’re going to take a look at a question we call
“Memo” which we used to ask regularly (but of course don’t ask anymore so no need to
memorize anything on this page!). As such this post is meant to be a specific case
analysis. If you haven’t yet seen it, we recommend reading this blog post for a general
overview what we are looking for in candidates.
Getting started

To allow us to work on the question together, we’ll use a shared online editor. We’ll
provide you with the link to use (either before hand or during the interview).

We expect you to write code in a real programming language in the interview, not
pseudo-code. You can use any programming language you’d like, but we strongly
recommend you use the one you’re most familiar with and will let you solve the
problem in the best way (it’s fine to change your mind as you’re exploring the
problem!). You should be comfortable with basic data structures and APIs in the
language of your choice.

Note, there are no bonus points for using a functional language like OCaml. Please don’t
use OCaml just because you think it will make us happy. We want to see you at your
best, so you should use the language you’re most comfortable with. If OCaml isn’t your
strongest language, then don’t use it.

If during the interview you realize you have seen a question before, then please let us
know and we can do a different question. As you’ll see in this post, knowing a question
in advance greatly reduces what we can learn about you!

Part 1 – Basic coding

Have you heard about memoization? Can you carefully describe what it is? If you
haven’t heard about it, don’t worry. We’ll bring you up to speed. (A good introduction is
on Wikipedia.)
Now let’s say there is a function f of type int -> int whose output only depends on
the input. f is very expensive to compute. We’d like you to write a memoized version of
this function, i.e. another function g of the same type, that returns the same values –
g(x) = f(x) for all x – but only does the expensive computation once for each input
value.
A typical first solution we’re looking for at this stage uses a hash-table to store
calculated results. A possible solution in OCaml might be:

let memo f =
let results = Hashtbl.create 256 in
(fun input ->
match Hashtbl.find results input with
| None ->
let result = f input in
Hashtbl.add results ~key:input ~data:result;
result
| Some result -> result)
(As I said above, you’re not required or expected to write in OCaml but in this blog post I’m
going to follow my own advice and use the language I’m most familiar with, which is
OCaml. You might also object that this does a test-and-set without a lock, so can’t possibly
be thread-safe. Nice spot! For the purpose of this question let’s ignore re-entry to focus on
the core ideas.)
Whichever APIs or data structures you end up using for your solution: you should be
prepared to talk about how they work and what the complexity of various operations is.

Part 2 – Reasoning about and improving your code

Can you think of any issues we could run into when using the function from part 1? For
example, let’s say we run your function in production and notice our application
performs significantly worse than before. Quite the opposite from what we hoped
memoization would do! Can you see what the problem might be?

The big problem is memory usage. Our application might call f with lots of different
inputs and each result will be stored in the hashtable forever – a memory leak! Can you
come up with some ideas to improve upon this?
A reasonable approach to control the memory usage is to bound the size of the hash-
table and to evict things from it in a FIFO fashion. What trade-offs does FIFO have
versus other eviction schemes? How could you modify your memo function to
implement FIFO? Let’s aim for O(1) complexity when evicting from the cache.

There are a few different ways to do this. A good solution keeps a separate queue: when
adding a new result to your hashtable, if the size grows beyond the bound, then
dequeue from the queue and remove that element from the hashtable.

Besides being able to write code to do this, we look for how you communicate your
thoughts on the problem and ideas to improve it. We don’t necessarily expect every
candidate to immediately jump to the O(1) solution, but we’re interested in the process
of talking through this problem and what you can come up with.

Part 3 – Going further

As you probably realize, FIFO can be very inefficient in some use-cases. Let’s say we
want to do LRU (least recently used) instead. We still want the implementation to be as
efficient as possible. How can you implement this?
Once more, there are multiple ways to do this. The easiest solution stores timestamps
with each value in the hashtable and linearly scans through the table when evicting.
This is O(n). It’s possible to improve to O(log n) using a min-heap or even to O(1) using
a doubly-linked list.

Side-note: implementing the most efficient solution One way to get to O(1) is to
maintain a doubly linked list and make the values in the hash-table point to
elements in that list. Then when looking up a cached value in the hash-table, you
can slice it out of its current position in the list and put it at the top in O(1). You
maintain a separate pointer to the bottom of the doubly linked list to evict in O(1).
Few candidates come up with the doubly-linked list immediately, so don’t worry if this
is not something you thought of straight away. While we might ask you to implement
parts of your solution, this part is intended as a discussion and test your ideas for
improving complexity. We’ll guide you to the right level of abstraction, so you don’t have
to worry too much about which details to include.

We also have various other extensions for this question that make it possible to keep
going further as far as time allows.

What we look for

Again, for a good overview see this post.


While interviewing, we try to evaluate how well you would fit in our work environment
by collaboratively solving a problem. This means the journey through the interview is a
lot more important than the snapshot of the solution at the end of it. We are more
interested in seeing how you approach a difficult problem than just capturing a boolean
flag whether you can come up with the solution.

As a concrete example, we might prefer a candidate that wrote careful and clear code,
communicated well and had good insights and ideas along the way, but didn’t get as far
through the problem compared to another candidate that immediately solved every
part but was sloppy and hard to follow.

This makes it impossible to give a rigid set of requirements of what needs to be


achieved during the interview. Nevertheless, to give you some rough guidelines:

Every successful candidate should achieve a bug-free solution for part 1 relatively
quickly. If some of part 1 sounds unfamiliar to you, it might be better to hold off
applying to give yourself more time to prepare.
Most candidates that we pass also complete part 2 fully in the time of the interview.
Strong candidates finish part 3 with a complete solution, but not finishing this part
doesn’t mean that you will be rejected! As said above, it’s what happens during the
interview that really counts, not the result at the end.

Sharing questions afterwards

We are interested in seeing you approach a difficult problem and walk through the
process of deriving a solution with you. If you already know the question in advance
(either by finding it online, or by talking to friends who have previously applied), it
reduces the efficacy of the interview: We now only get to test if you can write code for a
problem you’ve already understood and solved, which is a small subset of things we are
interested in learning about. For example, if you’ve read through this post, we wouldn’t
learn much from asking you Memo!
Thus we would like to ask you not to share the interview question with anybody else (in
person or online).

What happens next

We usually try to get back to you about the outcome of the interview within one week.
During busy periods this might take a bit longer, but not hearing from us after 10 days is
unexpected and you should definitely poke us.

If the interview went well, we invite you to come to one of our offices (New York,
London or Hong Kong) for a day of onsite interviews. These proceed in much the same
way as the phone interview – all questions are technical.

Ready to apply?

If you read this post and feel ready to apply, then simply go here. We have a very
straightforward application process – all we need is your resume or CV. If you already
have an offer from another firm and are worried about timing please let us know early
in your process! You can also read our thoughts and experiences with exploding offers,
something we don’t do but know many other companies use as a recruitment tool. We
look forward to speaking with you!
Sebastian Funk joined Jane Street in 2014 after graduating in Computer Science from the University of
Cambridge and has been primarily working in the Trading Systems group. He is a proud former member of a
Funk band incidentally named after him.

#INTERVIEWING
Interviewing At Jane Street
OCT 24, 2014 | 9 MIN READ

o Share on Facebook

o Share on Twitter

o Share on LinkedIn
By: David Powers

Software Engineering Interviews at Jane Street


Welcome to our version of the “Technical Interviews at insert your company
here” post. This topic has been covered by a lot of people already, so I’m going to do my
best to not repeat all of the copious advice already out there.
Interviewing, for both the interviewers and the interviewee is just plain old hard work.
We spend a lot of time working on the process, and we know that you have spent years
working on your skillset.

Even so, sometimes all that hard work doesn’t work out - even with a great candidate -
just due to the the awkwardness of the interview process itself: time is short, the
questions are weirdly artificial, and of course people get nervous. Programming for an
audience on a whiteboard, a web browser, or even just on a computer that isn’t yours is
a bit like playing the guitar with mittens on. It can put even an accomplished person off
their game.

Missing out on good people makes us sad.

That’s what this post is for. By talking a bit about what we’re looking for, the ways
people do poorly, and how we think you might be able to prepare we hope we’ll reduce
the mitten handicap - at least a bit.

What Do We Look For?

From our perspective, the main thing we want to figure out when we interview
someone is: are they someone we want to work with?
That probably seems obvious and maybe even trite, but it’s a point that can easily get
lost once an interview is underway. We think of our interviews as little simulations of
what it’s like to work with the candidate; and while it may seem like the interview is all
about solving the problem, it’s really not. We’re much more interested in learning
about how you work.

We are looking for candidates who engage in clear and productive discussions about the
problem at hand. Ideally they quickly find the right technical level for the discussion -
not too abstract and not too detailed. They cleanly describe the most important
considerations, and lay out a good plan for dealing with them. Where there are tradeoffs
they note them and explain which side they took and why. They ask thoughtful
questions about parts of the problem that are unclear. Overall they show tenacity and
and curiosity; they want to engage with the problem and with the people they are
working with.

We model our interviews in a way that allows us to simulate, as best we can in an hour,
what it’s like to work with someone. That means we don’t particularly value seeing
someone write union-find in 15 lines, or care if a candidate knows exactly how an AVL
tree is written (though we do care about understanding tree balance at a higher level).
Those kinds of things can be found on the internet.

To that end, we try to avoid algorithm bingo and puzzles with clever “aha” solutions. We
prefer more open-ended problems that have several plausible angles of attack and
maybe even no single best answer. They give us more freedom to work together and to
see how the candidates’ thinking plays out.

That sounds nice enough, but it’s a bit high-level and hand-wavy. So here’s a more
concrete list of suggestions that follow from our overall approach.

Be nice
The smartest, most technically clever person in the world won’t get hired at Jane Street
if they aren’t courteous and pleasant to talk to. Most problems at Jane Street are solved
with a lot of collaboration and discussion, and the solutions often take days or weeks to
work out, incorporating ideas from many many people. The tenor and quality of those
discussions is an essential part of getting to the right answer.
Be clear
And by clear, we mean simple and to the point. Use words and examples that get the
core idea across to the widest technical audience possible.

Avoid showy, highly technical or deeply obscure terms of art, especially if you don’t fully
understand them. In the best case we’ll likely just ask exactly what you meant by
“hylomorphism”, which wastes precious time. In the worst case it will become clear that
you should have said “metamorphism” instead, which is just embarrassing for everyone
involved.

Know what you don’t know


Naturally we like it when candidates are good at solving the problems we put in front of
them. But just as important - perhaps more important - is their ability to reason about
their own level of understanding.

In other words, we really like people who can admit when they’re unsure and speak
confidently when they have the basis to do so. Be willing to say, “I don’t know” rather
than guessing. Tell us when you are fairly confident but still a little bit uncertain. Get
used to talking about not just the problem but also your own confidence in individual
assumptions and statements.

Know your language


Code is a wonderful language for communicating complex ideas. It provides a concise
and unambiguous way of expressing them. But, like any foreign language, it takes a lot
of time and practice to get really comfortable. We need you to be comfortable with it
because we communicate ideas in code a lot.

Now, comfortable doesn’t mean that you need to have memorized the spec for a
language (assuming it even has one beyond the reference implementation). It means
that you should be able to read and write code in your language of choice without
constant access to reference materials for common things, such as:

o Standard control structures (loops/if-then/etc.)


o Function, module, class, type, etc. definitions
o Common data types like arrays, lists, hash tables/maps/dictionaries
o Exceptions and other error handling techniques
o Reasonable code organization
That especially means you shouldn’t pick a language because you think it will make us
happy.

We’d much prefer you use a language that you know well, and can prove your skills
with. Similarly, when picking which features of the language to use pick the ones you
understand best. We’re not going to be impressed with your elegant use of Python
decorators if you don’t really understand what they do.

Write the code you said you would write


We love it when a plan comes together, but it’s extra hard to watch when a good plan
falls apart on execution. Once you discuss a plan of attack with your interviewer do
what you claimed you would do. Don’t change the plan in the middle or drop it in favor
of a better idea without some discussion. You have a very limited amount of time and
executing a decent plan well is better than producing a Frankenstein’s monster of 3
different plans that doesn’t quite come to life.

If you do get partway through and start to lose faith step back and talk about it. Explain
exactly why you are concerned. If there really is a fatal flaw and you’ve seen it we’ll help
you get out of the jam, and we’ll appreciate that you articulated it. If it’s just not quite
perfect we’ll likely encourage you to continue.

Review CS 101
We’ve hired plenty of successful people who didn’t have a traditional college
background in CS and we certainly don’t require a masters or a PhD. That said, we need
you to have a solid working knowledge of core computer science concepts, including:

o Abstraction layers like functions, objects, and modules


o Basic algorithms and data structures, including binary search, sorting, hashing,
breadth/depth first search, hash tables, binary trees and heaps.
o Techniques for estimating CPU and memory costs, including big-O notation.
o Recursion and exhaustive case analysis

So if you can’t for the life of you recall what amortized analysis is and you can’t nimbly
bang out the code for a depth-first search it’s probably worth reviewing some of this
material.

Think about real computers


Depending on your point of view it’s either a sad or beautiful fact that the most elegant
code can only run on top of the giant jangly amalgam of parts and OS glue that is a real
computer. Unfortunately we need programs to actually run so we need people who
understand the inner workings of that behemoth.

This doesn’t mean that we quiz every candidate about deep kernel internals, or the
differences between SDRAM vs SGRAM. But for some jobs in systems development we
do expect a fair amount of detailed knowledge, and in general it’s a big plus if you can
take into account things like cache effects, IO patterns, memory representations, and the
capabilities of real CPUs.

What We Don’t Look For

Lot’s of things. But there are a few things that pop up time and again that people worry
we are looking for that bear mentioning.

We aren’t looking for you to finish. Our questions are often designed to be open ended
enough that even the best people we’ve seen couldn’t answer them fully in the time
allotted. We want to keep the conversation going to learn everything we can, and we
don’t expect that you’ll answer everything 100% perfectly.

We also don’t expect you to give the perfect answer or to deliver bug free code. Coding
in front of people is hard. Coding with a time limit is hard. Coding, in general, is hard.

We don’t ask software engineers to do mental math, or math olympiad questions, or to


contemplate logic puzzles about pirate tigers that only tell the truth despite what you
might have read online. Dev interviews are about programming, plain and simple. That’s
what we are hiring you to do and that’s what we expect you to demonstrate. There are
other jobs at Jane Street that do care about mental math and logic puzzles for good
reasons. Just not this one.

What Can You Do To Prepare?

This part is short and sweet. Practice.

Build something from scratch and on your own in a language you like. Don’t stop short.
Build the whole thing. Make yourself do the parts that are hard for you and don’t accept
half-finished code just because you think you know how you would finish it. Dive deep
into the layers of the libraries and language that you built it upon, and understand how
they work too.
When you think you are done show it to the smartest people you know, get feedback,
tear it down and build it again with what you’ve learned.

Repeat with a new problem.

We are looking for people to build real things with us, and practice really does make
perfect.

David Powers joined Jane Street in 2006 after spending time as a system administrator, directing IT at an
investment bank, and making swords to sell at renaissance faires. He graduated with a degree in mostly
Philosophy from Oberlin College in 1999 with just enough CS to land a job. At Jane Street he's had the chance
to write a lot of software, helped build out an office and data center or two, and has been invested in
recruiting for the past few years.

You might also like