Art and photos by Summer Gray
Implementing the
LHC on a Whiteboard
How to survive
coding interviews
of all shapes and sizes
Slide 2
Slide 2 text
Why Coding Interviews?
Slide 3
Slide 3 text
No content
Slide 4
Slide 4 text
This Mismatch…
❖ Is keeping programmers from getting jobs
❖ Is likely due to a lack of interview training (especially
compared to the other training we do in our industry)
❖ Is fixable
Slide 5
Slide 5 text
What Is a Coding Interview?
❖ Take homes
❖ With or without time limits
❖ Technical interviews
❖ “Pairing”
❖ The dreaded whiteboard
❖ Auditions
Slide 6
Slide 6 text
What Do I Know About This?
❖ I work for NoRedInk
❖ We get a lot of applicants
❖ Roughly 75% of the candidates fail our “take home”
❖ Around 30% of the rest fail their first technical interview
❖ I see a lot of what doesn’t work
Slide 7
Slide 7 text
We’re hiring
It’s In My Interest To
Improve How You Do
The better candidates do,
the faster we hire and
the less I interview
Slide 8
Slide 8 text
What This Talk Is Not?
❖ Guaranteed
❖ A moral judgement
❖ All-knowing
❖ Respectful of your time
Slide 9
Slide 9 text
How Can You Prepare?
Slide 10
Slide 10 text
Study
❖ Interviews commonly focus on a certain subset of
programming knowledge
❖ This probably isn’t knowledge that you use daily
❖ Ensuring it’s fresh in your brain can help
Slide 11
Slide 11 text
Concepts Data Structures Algorithms
Big O Notation Hash Tables Binary Search
Dynamic Programming/
Memoization
Trees/Tries/Graphs
Bread-First Search/
Depth-First Search
Recursion Linked Lists
Merge Sort/
Quicksort
Bit Manipulation Heaps
Stacks and Queues
Slide 12
Slide 12 text
Concepts Data Structures Algorithms
Big O Notation Hash Tables Binary Search
Dynamic Programming/
Memoization
Trees/Tries/Graphs
Bread-First Search/
Depth-First Search
Recursion Linked Lists
Merge Sort/
Quicksort
Bit Manipulation Heaps
Stacks and Queues
Slide 13
Slide 13 text
http://bigocheatsheet.com/
Slide 14
Slide 14 text
Big O Notation
❖ A metric used to describe an upper bound on algorithm
efficiency
❖ Can be used for time or space
❖ Drops constants and non-dominant terms
❖ Adds independent work; multiplies dependent work
❖ Not just an academic curiosity! It can help you solve
problems faster and easier!
Slide 15
Slide 15 text
def sum_and_product(nums)
{ sum: nums.inject(0, :+),
product: nums.inject(1, :*) }
end
p sum_and_product(1..10)
Slide 16
Slide 16 text
def sum_and_product(nums)
{ sum: nums.inject(0, :+),
product: nums.inject(1, :*) }
end
p sum_and_product(1..10)
O(n)
Slide 17
Slide 17 text
def sum_and_product(nums)
{ sum: nums.inject(0, :+),
product: nums.inject(1, :*) }
end
p sum_and_product(1..10)
O(n)
Slide 18
Slide 18 text
module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
end
p Fib.recursive(10)
Slide 19
Slide 19 text
module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
end
p Fib.recursive(10)
O(2n)
Slide 20
Slide 20 text
module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
end
p Fib.recursive(10)
O(branchesdepth)
O(2n)
Slide 21
Slide 21 text
def shared_count(a, b)
sorted = b.sort
a.count { |i|
sorted.bsearch { |j| j >= i } == i
}
end
p shared_count(
[35, 55, 13, 49, 40, 59, 27],
[39, 40, 60, 17, 55, 58, 35]
)
Slide 22
Slide 22 text
def shared_count(a, b)
sorted = b.sort
a.count { |i|
sorted.bsearch { |j| j >= i } == i
}
end
p shared_count(
[35, 55, 13, 49, 40, 59, 27],
[39, 40, 60, 17, 55, 58, 35]
)
O(b log b + a log b)
Slide 23
Slide 23 text
def shared_count(a, b)
sorted = b.sort
a.count { |i|
sorted.bsearch { |j| j >= i } == i
}
end
p shared_count(
[35, 55, 13, 49, 40, 59, 27],
[39, 40, 60, 17, 55, 58, 35]
)
O(b log b + a log b)
Slide 24
Slide 24 text
def shared_count(a, b)
sorted = b.sort
a.count { |i|
sorted.bsearch { |j| j >= i } == i
}
end
p shared_count(
[35, 55, 13, 49, 40, 59, 27],
[39, 40, 60, 17, 55, 58, 35]
)
O(b log b + a log b)
Slide 25
Slide 25 text
A: 13, 27, 35, 40, 49, 55, 59
B: 17, 35, 39, 40, 55, 58, 60
Given two sorted arrays, find the elements
in common. The arrays are the same length
and each has all distinct elements.
Slide 26
Slide 26 text
A Brute Force Solution
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
shared = a.select { |n| b.include?(n) }
p shared
Slide 27
Slide 27 text
A Brute Force Solution
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
shared = a.select { |n| b.include?(n) }
p shared
Slide 28
Slide 28 text
Bungling Towards Ideal
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
i = 0
shared = b.each_with_object([ ]) do |n, array|
while i < a.size && a[i] < n
i += 1
end
array << n if a[i] == n
end
p shared
Slide 29
Slide 29 text
Bungling Towards Ideal
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
i = 0
shared = b.each_with_object([ ]) do |n, array|
while i < a.size && a[i] < n
i += 1
end
array << n if a[i] == n
end
p shared
Slide 30
Slide 30 text
Bungling Towards Ideal
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
i = 0
shared = b.each_with_object([ ]) do |n, array|
while i < a.size && a[i] < n
i += 1
end
array << n if a[i] == n
end
p shared
Slide 31
Slide 31 text
Straightforward Linear
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
c = b.each_with_object({ }) do |n, hash|
hash[n] = true
end
shared = a.select { |n| c.include?(n) }
p shared
Slide 32
Slide 32 text
Straightforward Linear
a = [13, 27, 35, 40, 49, 55, 59]
b = [17, 35, 39, 40, 55, 58, 60]
c = b.each_with_object({ }) do |n, hash|
hash[n] = true
end
shared = a.select { |n| c.include?(n) }
p shared
Slide 33
Slide 33 text
Ruby Can Sometimes Help
❖ Minitest::Benchmark supports:
❖ assert_performance_constant()
❖ assert_performance_exponential()
❖ assert_performance_linear()
❖ assert_performance_logarithmic()
❖ assert_performance_power()
Slide 34
Slide 34 text
Analyzing Algorithms
module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
def memoized(i)
cache = Hash.new { |hash, n| hash[n] = n < 2 ? n : hash[n - 2] + hash[n - 1] }
cache[i]
end
def dynamic(i)
return i if i < 2
a, b = 0, 1
(i - 2).times do a, b = b, a + b end
a + b
end
end
Slide 35
Slide 35 text
Analyzing Algorithms
module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
def memoized(i)
cache = Hash.new { |hash, n| hash[n] = n < 2 ? n : hash[n - 2] + hash[n - 1] }
cache[i]
end
def dynamic(i)
return i if i < 2
a, b = 0, 1
(i - 2).times do a, b = b, a + b end
a + b
end
end
Slide 36
Slide 36 text
Analyzing Algorithms
module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
def memoized(i)
cache = Hash.new { |hash, n| hash[n] = n < 2 ? n : hash[n - 2] + hash[n - 1] }
cache[i]
end
def dynamic(i)
return i if i < 2
a, b = 0, 1
(i - 2).times do a, b = b, a + b end
a + b
end
end
Slide 37
Slide 37 text
Analyzing Algorithms
module Fib
module_function
def recursive(i)
return i if i < 2
recursive(i - 2) + recursive(i - 1)
end
def memoized(i)
cache = Hash.new { |hash, n| hash[n] = n < 2 ? n : hash[n - 2] + hash[n - 1] }
cache[i]
end
def dynamic(i)
return i if i < 2
a, b = 0, 1
(i - 2).times do a, b = b, a + b end
a + b
end
end
Slide 38
Slide 38 text
Almost Helpful
require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibRecursiveBench < Minitest::Benchmark
def self.bench_range
[1, 3, 30]
end
def bench_recursive_fib
assert_performance_exponential do |n|
Fib.recursive(n)
end
end
end
Slide 39
Slide 39 text
Almost Helpful
require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibRecursiveBench < Minitest::Benchmark
def self.bench_range
[1, 3, 30]
end
def bench_recursive_fib
assert_performance_exponential do |n|
Fib.recursive(n)
end
end
end
Slide 40
Slide 40 text
Almost Helpful
require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibRecursiveBench < Minitest::Benchmark
def self.bench_range
[1, 3, 30]
end
def bench_recursive_fib
assert_performance_exponential do |n|
Fib.recursive(n)
end
end
end
Slide 41
Slide 41 text
More Helpful
require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibMemoizedBench < Minitest::Benchmark
def self.bench_range
bench_exp(1, 1_000)
end
def bench_memoized_fib
assert_performance_linear do |n|
Fib.memoized(n)
end
end
end
Slide 42
Slide 42 text
More Helpful
require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibMemoizedBench < Minitest::Benchmark
def self.bench_range
bench_exp(1, 1_000)
end
def bench_memoized_fib
assert_performance_linear do |n|
Fib.memoized(n)
end
end
end
Slide 43
Slide 43 text
More Helpful
require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibMemoizedBench < Minitest::Benchmark
def self.bench_range
bench_exp(1, 1_000)
end
def bench_memoized_fib
assert_performance_linear do |n|
Fib.memoized(n)
end
end
end
Slide 44
Slide 44 text
The Most Helpful
require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibDynamicBench < Minitest::Benchmark
def bench_dynamic_fib
assert_performance_linear do |n|
Fib.dynamic(n)
end
end
end
Slide 45
Slide 45 text
The Most Helpful
require "minitest/autorun"
require "minitest/benchmark"
require_relative "fib"
class FibDynamicBench < Minitest::Benchmark
def bench_dynamic_fib
assert_performance_linear do |n|
Fib.dynamic(n)
end
end
end
Slide 46
Slide 46 text
The classic “Nine Balls” interview brainteaser
You have nine balls. Eight are the same weight and
one is heavier. You are given a balance which tells
you only wether the left side or right side is heavier.
Find the heavy ball in just two uses of the scale.
Slide 47
Slide 47 text
No content
Slide 48
Slide 48 text
No content
Slide 49
Slide 49 text
Practice
❖ Work code challenges
❖ http://exercism.io/
❖ http://rubyquiz.com/
❖ You need to be able to consistently solve Exercism size
problems in one hour
Slide 50
Slide 50 text
More Study and Practice
Slide 51
Slide 51 text
Have Some Open Source
❖ Be able to point to a published gem
❖ It barely matters what it does
❖ The most important details are a strong README, clean
code, tests, and documentation
❖ A small gem is fine
Slide 52
Slide 52 text
What To Do While Coding?
Slide 53
Slide 53 text
Goals
❖ Not the same as normal on the job programming
❖ You need to avoid being seen as a bad hire
❖ If you can avoid major mistakes, you’re ahead
Slide 54
Slide 54 text
Tip #1
Read Carefully
And/or ask as many clarifying questions
as needed
Slide 55
Slide 55 text
Tip #2
Follow Directions
Many candidates do not do this
Slide 56
Slide 56 text
Tip #3
Stop and Think
You don’t have time not to do this
Slide 57
Slide 57 text
No content
Slide 58
Slide 58 text
Tip #4
Think Out Loud
Magic words:
• “My first thought is…”
• “I’m considering the tradeoffs…”
• “I might circle back to this…”
• “I don’t know.”
Slide 59
Slide 59 text
Tip #5
Don’t Make
Offensive Comments
Show that you have personality and
a little bit of humor,
but keep it appropriate
Slide 60
Slide 60 text
Tip #6
Start at the
Hard Part
• Don’t begin by designing objects
• Jump straight to the interesting bit
• Fake input as needed
• Ignore UI completely
Slide 61
Slide 61 text
Tip #7
Test the Core
Pretty much no one tests anything,
so just a little, at the key place, is a win
Slide 62
Slide 62 text
Tip #8
Avoid Dependencies
And don’t recreate them manually
Slide 63
Slide 63 text
Tip #9
Write Less Code
Don’t “gold plate”
Slide 64
Slide 64 text
Tip #10
Ignore “Bonus”
Challenges
Seriously, it’s just not worth it
Slide 65
Slide 65 text
Tip #11
Consider Time
Limits Soft
Submit on time,
but resubmit later if needed
Slide 66
Slide 66 text
Tip #12
Show Off Your
Text Editing Skills
• Know five editing shortcuts
• Make one multiple cursors or macros
Slide 67
Slide 67 text
Maximizing for Success
❖ You probably won’t nail all of my tips every time
❖ That’s fine
❖ Interviews are hard for everyone and everyone makes
mistakes
❖ Hit as many of the points we’ve discussed as you can
❖ Those you get will help