Saturday, May 11th, 2019 · 13 min read
Based on an informal talk I delivered for the AP Computer Science class at my high school about studying computer science in college and searching for an internship.
I’m currently sitting somewhere above Nebraska, halfway to San Francisco on the way to a twelve-week internship at Google’s Mountain View headquarters. It’s been a little over a week after I returned from my first year as a computer science student at the University of Michigan, last Thursday.
It’s surreal — sure, that I’m leaving as soon as I get back home — but also that as a freshman, I was fortunate enough to get a gig at such a big company. Luck was definitely a big part of it, but there were a few things I did that I think helped me land it which I wanted to document here as well — so hopefully your Twitter location will say “SFO” next summer, too!
I just finished my first year at the University of Michigan, where I took Introductory Data Structures, EECS 280, and Discrete Math, MATH 465 (I skipped Intro to Programming, EECS 183, by completing Michigan’s diagnostic project). Although some of my more advanced CS friends took the subsequent Data Structures and Algorithms course, EECS 281, which is generally taken during one’s sophomore year, I wasn’t able to since discrete math was an enforced prerequisite.
I started applying to companies in September. I applied to:
Airbnb, Amazon, Atlassian, Braintree, Coinbase, Facebook, Facebook again (freshman program), Flexport, GitHub, Google, Google again (freshman program), Hudl, Jet, Microsoft, Microsoft again (freshman program), Mozilla, Robinhood, Spotify, Strava, Uber, and a few other places I can’t remember via AngelList and Y Combinator’s Work at a Startup
From what I saw at the Michigan Engineering career fair when I visited, most recruiters seemed pretty averse to freshmen — resumes of first-years generally look the same, and who’s to say if we actually have any skills barely eight weeks into college? It definitely showed in my application results: I was either rejected or ghosted by every company I applied to.
That is, except for Google — but interestingly, it wasn’t because of my resume.
Earlier in the year, I was trying to make a bot to buy Supreme faster, since I always ended up getting cartjacked. I was Googling for solutions, and ended up searching for ”headless chrome” — a tool used by web developers to automate actions in the Google Chrome browser. Suddenly, a message popped up in the results page: “You’re speaking our language. Up for a challenge?“. I clicked “I want to play” and was redirected to a Linux-terminal looking webpage, where I was given a programming question and three days to solve it.
More piqued by the website itself than by the question offered, I did some research, and it turned out that the popup was a “secret” Google recruiting tool called Foobar.
It’s been around since at least 2014, and at this point it’s a bit of an open secret — in fact, I found multiple solutions to the questions on GitHub. Nonetheless, there was no point in not doing them myself (I was doubtful of my ability to finesse my way onto a job if I was genuinely unqualified), and I liked them anyway — I’m a big fan of Project Euler questions, which provide a similar challenge and which I’d been doing since my junior year of high school.
After a few weeks of work, I had solved six questions, each more difficult than the last, and at this point, the site offered to send my information to a recruiter. While I had already applied online, I figured it wouldn’t hurt to put my name in again. Nothing had come out of my job search yet anyway.
Happily, a week later, I got some fruitful news: an email from Google asking me to complete a 45-minute coding assessment (commonly referred to as the “coding screen”) to verify my performance on Foobar. It consisted of two questions, one of which was an easier warm-up and a second, harder one — similar to the Foobar questions — which took the majority of my time. I was working right down to the last second — I found and fixed a critical bug with less than a minute to go — and wasn’t sure how I did, but by then all I could do was wait.
And wait I did — I completed the coding screen in mid-November, and didn’t hear back until mid-December, when I received an email from my newly assigned recruiter.
Hope you’re doing well! I wanted to circle back with you today regarding my previous email. Were you still hoping to pursue a Software Engineering Internship at Google?
I’m hoping to get you started with our process as soon as possible however if I do not hear back in 2 business days, I will need to withdraw your application at this time. If you wish to move forward, please the requested information as soon as possible!
Copied in the email body was another email postmarked around Thanksgiving, two weeks earlier — which I didn’t remember receiving and couldn’t seem to find anywhere in my inbox — about scheduling an interview. Anxious, I quickly figured out a few dates and responded.
In retrospect, this worked out really well. Since I didn’t respond for so long, the only available interview dates were after winter break — which was great, since at the time it was right around finals for fall semester. I don’t think I would’ve been able to adequately prepare for an interview before break had I received the first email and responded then.
With that close call out of the way, it was time to start studying. I had heard from other CS majors that you needed to know EECS 281 — data structures and algorithms — to get an internship, so I now had my winter break — three weeks — to teach myself as much of the curriculum as I could.
With my minimal “formal” computer science background, here’s what I used to prepare:
After I returned home for break, the first resource I used to prepare was the HackerRank videos. They were easy to consume and didn’t require much concentrated thought, so it was a good way to ease into things. Once I was done, I read the chapters of Cracking the Coding Interview which reviewed the concepts in the videos to ensure I’d remember the content for at least a few weeks.
Next, I read through the Big O chapter of CTCI (twice, in fact) and did the end-of-chapter exercises (there was a Big O exercise that I got wrong when I was going through the exercises on my own at first that I answered correctly on my interview — so it’s an important chapter!). I then watched the lectures of MIT OpenCourseWare’s 6.006: Introduction to Algorithms at double speed and used the Introduction to Algorithms textbook as a reference implementation for breadth-first and depth-first search, which I then translated from pseudocode to C++ (note: BFS and DFS are key algorithms — you’ll learn in the 6.006 videos that they have applications not only in search but in pathfinding and calculating dependencies, too).
For more direct practice, I did 13 Leetcode questions (they take a while!), starting from easy and then graduating into medium — and I probably would have done more if I had the time. I focused on dynamic programming, but I would recommend that you focus on what you personally find difficult (and to figure out you have trouble with, try a wide variety of questions!). I also did two practice interviews on Pramp, where I was matched up with another person who wanted to prep and we alternated roles as interviewer and interviewee. Finally, I had coffee with two alumni from my high school who already had tech jobs and had interviewed before, and they graciously gave me great tips for the process (e.g. which chapters of Cracking the Coding Interview to focus on) and ran through interview questions with me.
All in all, for learning the requisite data structures and algorithms knowledge, I found the HackerRank videos and Cracking the Coding Interview content the most helpful resources, followed by Leetcode. I also want to emphasize the importance of Pramp — while many people can solve coding questions, Pramp helped me practice communicating my process while coming up with a solution. The MIT stuff was good for reference and extra intuition, but not as helpful for the more basic, necessary knowlege.
It was a busy winter break, and pretty soon I had my interview: a 45-minute phone call with a current software engineer while I coded on a Google doc.
As scheduled, on January 3rd, I got a call from 650-253-0000 (my phone said “Mountain View, CA”, so I knew it was it). After a brief introduction and clarification (“yes, this is Nathan”), we dived right into the technical question. It wasn’t anything too out of the ordinary (another way to think about it: my time on Leetcode was well spent). I did what I had taught myself to do, making sure to think out loud and keeping in mind the optimization techniques I’d learned through my study of data structures, like memoization and using hash tables, as I coded. It was on a Google doc without compiler warnings or code highlighting (which was okay, since correct syntax is not as important as your process and general ideas).
I was responsible for leading most of the interview, but my interviewer would chime in every once in a while to ask a question (“what’s the computational complexity of this loop?”). The problem took me all of the allotted 45 minutes, which I’m told is normal — most interviewers will ask a question that can be extended in stages (e.g. “ok, you’ve finished the basic functionality, now handle integer inputs greater than
INT_MAX”) to fill up the time. Afterwards, there was a brief 5-minute behavioral question about working in teams (I’m told this is new, as usually Google software engineer interviews are purely technical), and then the interview ended.
The interview was followed by a period of uneasy waiting, and I was unsure whether my intense study would amount to anything. Finally, twenty-seven days later, I got an email from my recruiter: I had passed the interview! Unfortunately, the way the Google internship process works is that once you pass the interview you are placed in a pool of interns that managers (“intern hosts”) then choose from — if you don’t get picked, you don’t get an internship. If you do get picked, you have an informal follow-up interview with the potential host, and if both parties are still interested, an offer is drafted. I filled out a survey saying what I was interested in working on and what specific skills I had, and waited some more. Nothing was guaranteed yet.
By now, it was February, almost five months after I had started applying to internships. I had no other leads. Positions were filling up, and I began thinking about alternative summer options.
One week passed, and then another — nothing. One chilly Michigan afternoon, I was grabbing a snack in the dining hall, scrolling through Twitter on my phone. It chimed and I wondered whether an assignment had just been graded. A notification peeked down from the top of my screen. It was an email from Google!
I finally had another interested host. I read the project description, and it was a backend job, which I was much more excited about learning about. Later that week, I hopped on a brief call with my potential summer manager to learn more.
Four days later, I got the news: the call went well. My recruiter drafted an offer, and on March 12th, almost six months after I began my search, I had a job.
It’s May now, and I land in San Francisco in about thirty minutes. My Twitter location? Soon to be “SFO.”
Thank you to my fellow Wissahickon alumni Mayank Makwana, Alycia Lee, and Sam Kessler for their help during the process!
I write about college, mathematics, code, and startups. Subscribe to get my latest essays by email.