Background Info
Status: Senior Software Engineer, BS CS
Position: Senior Software Engineer at a Startup
Location: Europe
Date: May
Intro
I have finally completed my interview journey after several interviews at multiple companies and it is time to give back to the community.
Within the last 8 months, I have completed almost 1,000 problems (approximately 250 Easy, 550 Medium, 200 Hard).
I tried to solve at least 4 problems a day and revise already solved problems. It was hard work, most of the time it was fun, but sometimes it was also very exhausting. I knew that I want to interview at FAANG companies somewhere in the future but didn't really think that I would do it this year - it was more of a spontaneous decision in the end. I haven't had competitive programming experience before but years of professional experience.
My routine:
I was working during my preparation (or rather while I was leetcoding - the decision to interview came up spontaneously). On work days I usually leetcoded from 6am to 8am and 6pm to 10pm. On weekends and free days, I leetcoded from 8am to 9pm (1h lunch break). I also prepared for System Design and Behavioural rounds during that time.
Interviews and result
Snap:
1 Phone screen
5 Rounds of onsite interviews | Coding, System Design, Behavioural | Virtual: I have really enjoyed the interviews, discussions and problems! The interviewers did a really great job!
Google:
1 Phone screen
7 Rounds of onsite interviews | Coding, System Design, Behavioural | Virtual: The interviews mostly focused on the problems which were leetcode hard I would say. Less dicussions about my background and topics which were not related to the coding questions.
Palantir:
1 Online assessment
1 Phone screen
5 Rounds of onsite interviews | Coding, System Design, Behavioural | Virtual: I especially enjoyed the debugging and decomposition rounds (the decomposition round is very similar to a "regular" System design round).
Result: I have received offers from all 3 in the end!
Longer story:
I had all my onsite rounds within 7 days! That was quite stressful and exhausting. I had a hard time coping with my nervousness on the onsite days (shortly before the interviews started). I wasn't able to sleep well but I knew that I have (probably) prepared enough and that helped (worth noting here: IMO you are never perfectly prepared and it will probably always be "scary" - the most important thing is to try!). I also received good feedback from friends and other people after doing a lot of mock interviews. That certainly also helped with the confidence.
I tried to not eat too much before the interviews to avoid a food coma and always had a Coke, Red Bull and a chocolate bar ready in case I get tired during the interviews.
I was being "myself" during the interviews and I think that is always the best thing to do (there is no sense in trying to pretend anything). I followed my defined structure that I knew by heart due to many mock interviews and adjusted it slightly depending on how the interview went. Worth noting here is also that I tried to follow the STAR-schema during the behavioural rounds.
Tips and recommendations
I want to share the things that I think are really important to focus on as well as a list of topics that I have studied.
Important aspects:
- Quality matters, not quantity! Try to really understand the patterns behind problems and being able to "modify" those patterns to apply them to other problems.
- Consistency is key! I have solved at least 4 problems each day. Also try to revise problems that you have already solved to create "connections" between problems and identify similarities.
- Try to solve a problem in multiple ways: A graph problem can often be solved using different algorithms and approaches. Other problems can be solved iteratively and recursively. Understand the trade-offs and code all options.
- Try to also focus on testing! It is really important to understand testing strategies: Unit-Testing, Integration-Testing, etc.
- Understanding the data structures and how they internally work is also very important! I got multiple questions about how certain data structures are implemented.
- Typing speed: I think typing speed is very essential for being successful. A fast typing speed will make a good impression and it will also save you a lot of time during a coding round.
- Quality of code: Focus on good naming (language conventions and language agnostic patterns), maintainability, testability, DRY (don't repeat yourself), SoC (separation of concerns), etc.
- Make sure to have a very structured approach during the interviews: Clarify input/output/constraints/goals, Explain possible approaches with their trade-offs(!), commit to one and justify why you choose that approach, implement, dry run and test your code, fix bugs.
- Having a very structured approach in System design rounds is even more important!
- Do also prepare yourself for the behavioural rounds! I think a lot of people underestimate those (just my impression). Use a schema like STAR.
- Train your time management with mock interviews! It is very crucial to spend the right amount of time for each step in your structure/approach during an interview round.
- I think it can be a disadvantage if you solve questions by category - you lose the opportunity to "recognize" problems and being able to categorize them. I recommend to only filter questions when you want to revise problems.
I have focused on and studied the following topics:
My personal lists:
Concurrency and OS:
- Processes and Threads
- Interprocess communication models
- Synchronization
- Lock-free syncs (spin locks), volatile
- Sleep, yield, wait
- Lock syncs (semaphore, locks, RW-locks, etc. - try also to be able to implement those yourself!)
- Volatile guarantees
- Lock and conditions
- cyclic barriers, count down latches, rendez-vous etc.
- dead locks, live locks, starvation
- thread-pools and their concepts
- Future API (Java)
- CPU, PCB, TCB, MMU, Page Table, TLB, Context switching, etc.
System Design:
- Data models and query languages
- Storage and retrieval (B-trees, LSM-trees, WAL, Clustered/Non-clustered indexes, how they work in LSM-trees vs B-Trees, etc., OLAP vs OLTP, Fuzzy searches, etc.)
- Encoding and evolution and versioning
- Data flows: sync and asyc., trade-offs sync vs async, etc.
- Distributed data: replication (single-master, multi-master, leaderless, pros and cons), replication log types, async vs sync replication, trade-offs, Problems like "reading your own writes", "monotonic reads", "consistent prefix reads", conflict resolution strategies, etc.
- Distributed data: Partitioning, by key range, by hash, consistent hashing, trade-offs, hot keys/shards, local indexes, global indexes, partitioning by primary key, compound key, sedondary indexes, rebalancing, consistent hashing
- request routing: decentral, centralized, protocols like RAFT, Paxos, ZooKeepers protocol, Broadcasting, Gossip, trade-offs
- Transactions: ACID, Isolation levels, serializability, linearizability
- Problems in distributed systems: Faults and partial failures, timeouts and unbounded delays (packet switched vs circuit switched, etc.), Consistency and consensus, clocks/monotonic clocks
- You can read about all those topics in the book "Design* data-inte* a*" (which IMO is an absolutely great book!)
- I also think that a "reasonable" knowledge in CN (Computer Networks) is helpful for any Software Engineer (I personally regard it as a fundamental). I can personally recommend material from e.g. Cisco (CCNA covers a good range of topics).
Data structures and Algorithms (patterns):
- Binary search: BS can be used in so many different situations!
- Leap year, GCD, LCM, isPrime, prime finding, prime factorization
- Bit manipulation
- Reservoir sampling
- 2 pointer strategy and sliding window
- cumulative sum, prefix sum (1d, 2d, 3d)
- Sorting: selection sort, quick sort, quick select, insertion sort (with binary search optimization), merge sort, heap sort, radix sort, counting sort, bucket sort
- String strategies: rabin-karp, KMP, Boyer-Moore
- Graph: Dijkstra, Bellman-Ford, Union find, Kruskal, Prim, Floyd-Warshall, Tarjan, DFS, BFS, Ford Fulkerson & Edmond (Min cut max flow), Hamiltonion path (with bitmasking), Eulerian cycle, Topological sorting
- DFS: backtracking
- Monotonically increasing stack, queue, etc.
- DP: Top-down using recursion and memoization, Bottom up using iteration and tabulation
- Classic DP patterns: LCS, LIS, LIS (strictly increasing), Equal sum partition
- BIT: binary indexed tree/sedgwick tree
- Interval trees
- Tree: inorder, preorder, postorder traversal: iterative and recursive, morris traversal to do those 3 in O(1) space
- Binary search trees (BSTs), heaps, splay trees, red-black trees, skip list, avl tree
At the time of the interviews I was able to code all that by heart. I have revised and coded most of those algorithms one day before each onsite round.
My decision
I have decided to join Snap and I am looking forward to starting there :)!