mirror of
https://github.com/yangshun/tech-interview-handbook.git
synced 2026-04-24 02:22:39 +08:00
website: launch website
This commit is contained in:
@@ -1,580 +0,0 @@
|
||||
# Algorithm Questions
|
||||
|
||||
This section dives deep into practical tips for specific topics of algorithms and data structures which appear frequently in coding questions. Many algorithm questions involve techniques that can be applied to questions of similar nature. The more techniques you have in your arsenal, the higher the chances of passing the interview. They may lead you to discover corner cases you might have missed out or even lead you towards the optimal approach!
|
||||
|
||||
For each topic, study links are recommended to help you master the topic. There is a list of recommended common questions to practice which in my opinion is highly valuable for mastering the core concepts for the topic.
|
||||
|
||||
If you are interested in how data structures are implemented, check out [Lago](https://github.com/yangshun/lago), a Data Structures and Algorithms library for JavaScript. It is pretty much still WIP but I intend to make it into a library that is able to be used in production and also a reference resource for revising Data Structures and Algorithms.
|
||||
|
||||
## Contents
|
||||
|
||||
- [Array](array.md)
|
||||
- [Dynamic Programming and Memoization](dynamic-programming.md)
|
||||
- [Geometry](geometry.md)
|
||||
- [Graph](graph.md)
|
||||
- [Hash Table](hash-table.md)
|
||||
- [Heap](heap.md)
|
||||
- [Interval](interval.md)
|
||||
- [Linked List](linked-list.md)
|
||||
- [Math](math.md)
|
||||
- [Matrix](matrix.md)
|
||||
- [Object-Oriented Programming](oop.md)
|
||||
- [Permutation](permutation.md)
|
||||
- [Queue](queue.md)
|
||||
- [Sorting and Searching](sorting-searching.md)
|
||||
- [Stack](stack.md)
|
||||
- [String](string.md)
|
||||
- [Tree](tree.md)
|
||||
|
||||
## General Tips
|
||||
|
||||
Clarify any assumptions you made subconsciously. Many questions are under-specified on purpose.
|
||||
|
||||
Always validate input first. Check for invalid/empty/negative/different type input. Never assume you are given the valid parameters. Alternatively, clarify with the interviewer whether you can assume valid input (usually yes), which can save you time from writing code that does input validation.
|
||||
|
||||
Are there any time/space complexity requirements/constraints?
|
||||
|
||||
Check for off-by-one errors.
|
||||
|
||||
In languages where there are no automatic type coercion, check that concatenation of values are of the same type: `int`/`str`/`list`.
|
||||
|
||||
After finishing your code, use a few example inputs to test your solution.
|
||||
|
||||
Is the algorithm meant to be run multiple times, for example in a web server? If yes, the input is likely to be preprocess-able to improve the efficiency in each call.
|
||||
|
||||
Use a mix of functional and imperative programming paradigms:
|
||||
|
||||
- Write pure functions as much as possible.
|
||||
- Pure functions are easier to reason about and can help to reduce bugs in your implementation.
|
||||
- Avoid mutating the parameters passed into your function especially if they are passed by reference unless you are sure of what you are doing.
|
||||
- However, functional programming is usually expensive in terms of space complexity because of non-mutation and the repeated allocation of new objects. On the other hand, imperative code is faster because you operate on existing objects. Hence you will need to achieve a balance between accuracy vs efficiency, by using the right amount of functional and imperative code where appropriate.
|
||||
- Avoid relying on and mutating global variables. Global variables introduce state.
|
||||
- If you have to rely on global variables, make sure that you do not mutate it by accident.
|
||||
|
||||
Generally, to improve the speed of a program, we can either: (1) choose a more appropriate data structure/algorithm; or (2) use more memory. The latter demonstrates a classic space vs. time tradeoff, but it is not necessarily the case that you can only achieve better speed at the expense of space. Also, note that there is often a theoretical limit to how fast your program can run (in terms of time complexity). For instance, a question that requires you to find the smallest/largest element in an unsorted array cannot run faster than O(N).
|
||||
|
||||
Data structures are your weapons. Choosing the right weapon for the right battle is the key to victory. Be very familiar about the strengths of each data structure and the time complexities for its various operations.
|
||||
|
||||
Data structures can be augmented to achieve efficient time complexities across different operations. For example, a hash map can be used together with a doubly-linked list to achieve O(1) time complexity for both the `get` and `put` operation in an [LRU cache](https://leetcode.com/problems/lru-cache/).
|
||||
|
||||
Hashmaps are probably the most commonly used data structure for algorithm questions. If you are stuck on a question, your last resort can be to enumerate through the possible data structures (thankfully there aren't that many of them) and consider whether each of them can be applied to the problem. This has worked for me sometimes.
|
||||
|
||||
If you are cutting corners in your code, state that out loud to your interviewer and say what you would do in a non-interview setting (no time constraints). E.g., I would write a regex to parse this string rather than using `split()` which may not cover all cases.
|
||||
|
||||
## Sequence
|
||||
|
||||
#### Notes
|
||||
|
||||
Arrays and strings are considered sequences (a string is a sequence of characters). There are tips relevant for dealing with both arrays and strings which will be covered here.
|
||||
|
||||
Are there duplicate values in the sequence, would it affect the answer?
|
||||
|
||||
Check for sequence out of bounds.
|
||||
|
||||
Be mindful about slicing or concatenating sequences in your code. Typically, slicing and concatenating sequences require O(n) time. Use start and end indices to demarcate a subarray/substring where possible.
|
||||
|
||||
Sometimes you can traverse the sequence from the right rather than from the left.
|
||||
|
||||
Master the [sliding window technique](https://discuss.leetcode.com/topic/30941/here-is-a-10-line-template-that-can-solve-most-substring-problems) that applies to many substring/subarray problems.
|
||||
|
||||
When you are given two sequences to process, it is common to have one index per sequence to traverse/compare the both of them. For example, we use the same approach to merge two sorted arrays.
|
||||
|
||||
#### Corner Cases
|
||||
|
||||
- Empty sequence.
|
||||
- Sequence with 1 or 2 elements.
|
||||
- Sequence with repeated elements.
|
||||
|
||||
## Array
|
||||
|
||||
#### Notes
|
||||
|
||||
Is the array sorted or partially sorted? If it is, some form of binary search should be possible. This also usually means that the interviewer is looking for a solution that is faster than O(n).
|
||||
|
||||
Can you sort the array? Sometimes sorting the array first may significantly simplify the problem. Make sure that the order of array elements do not need to be preserved before attempting a sort.
|
||||
|
||||
For questions where summation or multiplication of a subarray is involved, pre-computation using hashing or a prefix/suffix sum/product might be useful.
|
||||
|
||||
If you are given a sequence and the interviewer asks for O(1) space, it might be possible to use the array itself as a hash table. For example, if the array only has values from 1 to N, where N is the length of the array, negate the value at that index (minus one) to indicate presence of that number.
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Two Sum](https://leetcode.com/problems/two-sum/)
|
||||
- [Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/)
|
||||
- [Contains Duplicate](https://leetcode.com/problems/contains-duplicate/)
|
||||
- [Product of Array Except Self](https://leetcode.com/problems/product-of-array-except-self/)
|
||||
- [Maximum Subarray](https://leetcode.com/problems/maximum-subarray/)
|
||||
- [Maximum Product Subarray](https://leetcode.com/problems/maximum-product-subarray/)
|
||||
- [Find Minimum in Rotated Sorted Array](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/)
|
||||
- [Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array/)
|
||||
- [3Sum](https://leetcode.com/problems/3sum/)
|
||||
- [Container With Most Water](https://leetcode.com/problems/container-with-most-water/)
|
||||
|
||||
## Binary
|
||||
|
||||
#### Study Links
|
||||
|
||||
- [Bits, Bytes, Building With Binary](https://medium.com/basecs/bits-bytes-building-with-binary-13cb4289aafa)
|
||||
|
||||
#### Notes
|
||||
|
||||
Questions involving binary representations and bitwise operations are asked sometimes and you must be absolutely familiar with how to convert a number from decimal form into binary form (and vice versa) in your chosen programming language.
|
||||
|
||||
Some helpful utility snippets:
|
||||
|
||||
- Test k<sup>th</sup> bit is set: `num & (1 << k) != 0`.
|
||||
- Set k<sup>th</sup> bit: `num |= (1 << k)`.
|
||||
- Turn off k<sup>th</sup> bit: `num &= ~(1 << k)`.
|
||||
- Toggle the k<sup>th</sup> bit: `num ^= (1 << k)`.
|
||||
- To check if a number is a power of 2, `num & num - 1 == 0`.
|
||||
|
||||
#### Corner Cases
|
||||
|
||||
- Check for overflow/underflow.
|
||||
- Negative numbers.
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Sum of Two Integers](https://leetcode.com/problems/sum-of-two-integers/)
|
||||
- [Number of 1 Bits](https://leetcode.com/problems/number-of-1-bits/)
|
||||
- [Counting Bits](https://leetcode.com/problems/counting-bits/)
|
||||
- [Missing Number](https://leetcode.com/problems/missing-number/)
|
||||
- [Reverse Bits](https://leetcode.com/problems/reverse-bits/)
|
||||
|
||||
## Dynamic Programming
|
||||
|
||||
#### Study Links
|
||||
|
||||
- [Demystifying Dynamic Programming](https://medium.freecodecamp.org/demystifying-dynamic-programming-3efafb8d4296)
|
||||
- [Dynamic Programming – 7 Steps to Solve any DP Interview Problem](https://dev.to/nikolaotasevic/dynamic-programming--7-steps-to-solve-any-dp-interview-problem-3870)
|
||||
|
||||
#### Notes
|
||||
|
||||
Dynamic Programming (DP) is usually used to solve optimization problems. The only way to get better at DP is to practice. It takes some amount of practice to be able to recognize that a problem can be solved by DP.
|
||||
|
||||
Sometimes you do not need to store the whole DP table in memory, the last two values or the last two rows of the matrix will suffice.
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- 0/1 Knapsack
|
||||
- [Climbing Stairs](https://leetcode.com/problems/climbing-stairs/)
|
||||
- [Coin Change](https://leetcode.com/problems/coin-change/)
|
||||
- [Longest Increasing Subsequence](https://leetcode.com/problems/longest-increasing-subsequence/)
|
||||
- [Longest Common Subsequence](https://www.geeksforgeeks.org/longest-common-subsequence-dp-4/)
|
||||
- [Word Break Problem](https://leetcode.com/problems/word-break/)
|
||||
- [Combination Sum](https://leetcode.com/problems/combination-sum-iv/)
|
||||
- [House Robber](https://leetcode.com/problems/house-robber/) and [House Robber II](https://leetcode.com/problems/house-robber-ii/)
|
||||
- [Decode Ways](https://leetcode.com/problems/decode-ways/)
|
||||
- [Unique Paths](https://leetcode.com/problems/unique-paths/)
|
||||
- [Jump Game](https://leetcode.com/problems/jump-game/)
|
||||
|
||||
## Geometry
|
||||
|
||||
#### Notes
|
||||
|
||||
When comparing euclidean distance between two pairs of points, using dx<sup>2</sup> + dy<sup>2</sup> is sufficient. It is unnecessary to square root the value.
|
||||
|
||||
To find out if two circles overlap, check that the distance between the two centers of the circles is less than the sum of their radii.
|
||||
|
||||
## Graph
|
||||
|
||||
#### Study Links
|
||||
|
||||
- [From Theory To Practice: Representing Graphs](https://medium.com/basecs/from-theory-to-practice-representing-graphs-cfd782c5be38)
|
||||
- [Deep Dive Through A Graph: DFS Traversal](https://medium.com/basecs/deep-dive-through-a-graph-dfs-traversal-8177df5d0f13)
|
||||
- [Going Broad In A Graph: BFS Traversal](https://medium.com/basecs/going-broad-in-a-graph-bfs-traversal-959bd1a09255)
|
||||
|
||||
#### Notes
|
||||
|
||||
Be familiar with the various graph representations, graph search algorithms and their time and space complexities.
|
||||
|
||||
You can be given a list of edges and tasked to build your own graph from the edges to perform a traversal on. The common graph representations are:
|
||||
|
||||
- Adjacency matrix.
|
||||
- Adjacency list.
|
||||
- Hashmap of hashmaps.
|
||||
|
||||
A tree-like diagram could very well be a graph that allows for cycles and a naive recursive solution would not work. In that case you will have to handle cycles and keep a set of visited nodes when traversing.
|
||||
|
||||
#### Graph search algorithms:
|
||||
|
||||
- **Common** - Breadth-first Search, Depth-first Search
|
||||
- **Uncommon** - Topological Sort, Dijkstra's algorithm
|
||||
- **Rare** - Bellman-Ford algorithm, Floyd-Warshall algorithm, Prim's algorithm, Kruskal's algorithm
|
||||
|
||||
In coding interviews, graphs are commonly represented as 2-D matrices where cells are the nodes and each cell can traverse to its adjacent cells (up/down/left/right). Hence it is important that you be familiar with traversing a 2-D matrix. When recursively traversing the matrix, always ensure that your next position is within the boundary of the matrix. More tips for doing depth-first searches on a matrix can be found [here](https://discuss.leetcode.com/topic/66065/python-dfs-bests-85-tips-for-all-dfs-in-matrix-question/). A simple template for doing depth-first searches on a matrix goes like this:
|
||||
|
||||
```py
|
||||
def traverse(matrix):
|
||||
rows, cols = len(matrix), len(matrix[0])
|
||||
visited = set()
|
||||
directions = ((0, 1), (0, -1), (1, 0), (-1, 0))
|
||||
def dfs(i, j):
|
||||
if (i, j) in visited:
|
||||
return
|
||||
visited.add((i, j))
|
||||
# Traverse neighbors
|
||||
for direction in directions:
|
||||
next_i, next_j = i + direction[0], j + direction[1]
|
||||
if 0 <= next_i < rows and 0 <= next_j < cols: # Check boundary
|
||||
# Add any other checking here ^
|
||||
dfs(next_i, next_j)
|
||||
|
||||
for i in range(rows):
|
||||
for j in range(cols):
|
||||
dfs(i, j)
|
||||
```
|
||||
|
||||
#### Corner Cases
|
||||
|
||||
- Empty graph.
|
||||
- Graph with one or two nodes.
|
||||
- Disjoint graphs.
|
||||
- Graph with cycles.
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Clone Graph](https://leetcode.com/problems/clone-graph/)
|
||||
- [Course Schedule](https://leetcode.com/problems/course-schedule/)
|
||||
- [Pacific Atlantic Water Flow](https://leetcode.com/problems/pacific-atlantic-water-flow/)
|
||||
- [Number of Islands](https://leetcode.com/problems/number-of-islands/)
|
||||
- [Longest Consecutive Sequence](https://leetcode.com/problems/longest-consecutive-sequence/)
|
||||
- [Alien Dictionary (Leetcode Premium)](https://leetcode.com/problems/alien-dictionary/)
|
||||
- [Graph Valid Tree (Leetcode Premium)](https://leetcode.com/problems/graph-valid-tree/)
|
||||
- [Number of Connected Components in an Undirected Graph (Leetcode Premium)](https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/)
|
||||
|
||||
## Interval
|
||||
|
||||
#### Notes
|
||||
|
||||
Interval questions are questions where you are given an array of two-element arrays (an interval) and the two values represent a start and an end value. Interval questions are considered part of the array family but they involve some common techniques hence they are extracted out to this special section of their own.
|
||||
|
||||
An example interval array: `[[1, 2], [4, 7]]`.
|
||||
|
||||
Interval questions can be tricky to those who have not tried them before because of the sheer number of cases to consider when they overlap.
|
||||
|
||||
Do clarify with the interviewer whether `[1, 2]` and `[2, 3]` are considered overlapping intervals as it affects how you will write your equality checks.
|
||||
|
||||
A common routine for interval questions is to sort the array of intervals by each interval's starting value.
|
||||
|
||||
Be familiar with writing code to check if two intervals overlap and merging two overlapping intervals:
|
||||
|
||||
```py
|
||||
def is_overlap(a, b):
|
||||
return a[0] < b[1] and b[0] < a[1]
|
||||
|
||||
def merge_overlapping_intervals(a, b):
|
||||
return [min(a[0], b[0]), max(a[1], b[1])]
|
||||
```
|
||||
|
||||
#### Corner Cases
|
||||
|
||||
- Single interval.
|
||||
- Non-overlapping intervals.
|
||||
- An interval totally consumed within another interval.
|
||||
- Duplicate intervals.
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Insert Interval](https://leetcode.com/problems/insert-interval/)
|
||||
- [Merge Intervals](https://leetcode.com/problems/merge-intervals/)
|
||||
- [Non-overlapping Intervals](https://leetcode.com/problems/non-overlapping-intervals/)
|
||||
- [Meeting Rooms (Leetcode Premium)](https://leetcode.com/problems/meeting-rooms/) and [Meeting Rooms II (Leetcode Premium)](https://leetcode.com/problems/meeting-rooms-ii/)
|
||||
|
||||
## Linked List
|
||||
|
||||
#### Notes
|
||||
|
||||
Like arrays, linked lists are used to represent sequential data. The benefit of linked lists is that insertion and deletion from anywhere in the list is O(1) whereas in arrays the following elements will have to be shifted.
|
||||
|
||||
Adding a dummy node at the head and/or tail might help to handle many edge cases where operations have to be performed at the head or the tail. The presence of dummy nodes essentially ensures that operations will never have be done on the head or the tail, thereby removing a lot of headache in writing conditional checks to dealing with null pointers. Be sure to remember to remove them at the end of the operation.
|
||||
|
||||
Sometimes linked lists problem can be solved without additional storage. Try to borrow ideas from reverse a linked list problem.
|
||||
|
||||
For deletion in linked lists, you can either modify the node values or change the node pointers. You might need to keep a reference to the previous element.
|
||||
|
||||
For partitioning linked lists, create two separate linked lists and join them back together.
|
||||
|
||||
Linked lists problems share similarity with array problems, think about how you would do it for an array and try to apply it to a linked list.
|
||||
|
||||
Two pointer approaches are also common for linked lists. For example:
|
||||
|
||||
- Getting the k<sup>th</sup> from last node - Have two pointers, where one is k nodes ahead of the other. When the node ahead reaches the end, the other node is k nodes behind.
|
||||
- Detecting cycles - Have two pointers, where one pointer increments twice as much as the other, if the two pointers meet, means that there is a cycle.
|
||||
- Getting the middle node - Have two pointers, where one pointer increments twice as much as the other. When the faster node reaches the end of the list, the slower node will be at the middle.
|
||||
|
||||
Be familiar with the following routines because many linked list questions make use of one or more of these routines in the solution:
|
||||
|
||||
- Counting the number of nodes in the linked list.
|
||||
- Reversing a linked list in-place.
|
||||
- Finding the middle node of the linked list using fast/slow pointers.
|
||||
- Merging two lists together.
|
||||
|
||||
#### Corner Cases
|
||||
|
||||
- Single node.
|
||||
- Two nodes.
|
||||
- Linked list has cycle. Clarify with the interviewer whether there can be a cycle in the list. Usually the answer is no.
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Reverse a Linked List](https://leetcode.com/problems/reverse-linked-list/)
|
||||
- [Detect Cycle in a Linked List](https://leetcode.com/problems/linked-list-cycle/)
|
||||
- [Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/)
|
||||
- [Merge K Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/)
|
||||
- [Remove Nth Node From End Of List](https://leetcode.com/problems/remove-nth-node-from-end-of-list/)
|
||||
- [Reorder List](https://leetcode.com/problems/reorder-list/)
|
||||
|
||||
## Math
|
||||
|
||||
#### Notes
|
||||
|
||||
If code involves division or modulo, remember to check for division or modulo by 0 case.
|
||||
|
||||
When a question involves "a multiple of a number", perhaps modulo might be useful.
|
||||
|
||||
Check for and handle overflow/underflow if you are using a typed language like Java and C++. At the very least, mention that overflow/underflow is possible and ask whether you need to handle it.
|
||||
|
||||
Consider negative numbers and floating point numbers. This may sound obvious, but under interview pressure, many obvious cases go unnoticed.
|
||||
|
||||
If the question asks to implement an operator such as power, squareroot or division and want it to be faster than O(n), binary search is usually the approach to go.
|
||||
|
||||
#### Some common formulas:
|
||||
|
||||
- Sum of 1 to N = (n+1) \* n/2
|
||||
- Sum of GP = 2<sup>0</sup> + 2<sup>1</sup> + 2<sup>2</sup> + 2<sup>3</sup> + ... 2<sup>n</sup> = 2<sup>n+1</sup> - 1
|
||||
- Permutations of N = N! / (N-K)!
|
||||
- Combinations of N = N! / (K! \* (N-K)!)
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Pow(x, n)](https://leetcode.com/problems/powx-n/)
|
||||
- [Sqrt(x)](https://leetcode.com/problems/sqrtx/)
|
||||
- [Integer to English Words](https://leetcode.com/problems/integer-to-english-words/)
|
||||
|
||||
## Matrix
|
||||
|
||||
#### Notes
|
||||
|
||||
A matrix is a 2-dimensional array. Questions involving matrices are usually related to dynamic programming or graph traversal.
|
||||
|
||||
For questions involving traversal or dynamic programming, you almost always want to make a copy of the matrix with the same dimensions that is initialized to empty values to store the visited state or dynamic programming table. Be familiar with such a routine:
|
||||
|
||||
```py
|
||||
rows, cols = len(matrix), len(matrix[0])
|
||||
copy = [[0 for _ in range(cols)] for _ in range(rows)]
|
||||
```
|
||||
|
||||
Many grid-based games can be modeled as a matrix, such as Tic-Tac-Toe, Sudoku, Crossword, Connect 4, Battleship, etc. It is not uncommon to be asked to verify the winning condition of the game. For games like Tic-Tac-Toe, Connect 4 and Crosswords, where verification has to be done vertically and horizontally, one trick is to write code to verify the matrix for the horizontal cells, transpose the matrix and reuse the logic for horizontal verification to verify originally vertical cells (which are now horizontal).
|
||||
|
||||
Transposing a matrix in Python is simply:
|
||||
|
||||
```py
|
||||
transposed_matrix = zip(*matrix)
|
||||
```
|
||||
|
||||
#### Corner Cases
|
||||
|
||||
- Empty matrix. Check that none of the arrays are 0 length.
|
||||
- 1 x 1 matrix.
|
||||
- Matrix with only one row or column.
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Set Matrix Zeroes](https://leetcode.com/problems/set-matrix-zeroes/)
|
||||
- [Spiral Matrix](https://leetcode.com/problems/spiral-matrix/)
|
||||
- [Rotate Image](https://leetcode.com/problems/rotate-image/)
|
||||
- [Word Search](https://leetcode.com/problems/word-search/)
|
||||
|
||||
## Recursion
|
||||
|
||||
#### Notes
|
||||
|
||||
Recursion is useful for permutation, because it generates all combinations and tree-based questions. You should know how to generate all permutations of a sequence as well as how to handle duplicates.
|
||||
|
||||
Remember to always define a base case so that your recursion will end.
|
||||
|
||||
Recursion implicitly uses a stack. Hence all recursive approaches can be rewritten iteratively using a stack. Beware of cases where the recursion level goes too deep and causes a stack overflow (the default limit in Python is 1000). You may get bonus points for pointing this out to the interviewer. Recursion will never be O(1) space complexity because a stack is involved, unless there is [tail-call optimization](https://stackoverflow.com/questions/310974/what-is-tail-call-optimization) (TCO). Find out if your chosen language supports TCO.
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Subsets](https://leetcode.com/problems/subsets/) and [Subsets II](https://leetcode.com/problems/subsets-ii/)
|
||||
- [Strobogrammatic Number II (Leetcode Premium)](https://leetcode.com/problems/strobogrammatic-number-ii/)
|
||||
|
||||
## String
|
||||
|
||||
#### Notes
|
||||
|
||||
Please read the above tips on sequence. They apply to strings too.
|
||||
|
||||
Ask about input character set and case sensitivity. Usually the characters are limited to lowercase Latin characters, for example a to z.
|
||||
|
||||
When you need to compare strings where the order isn’t important (like anagram), you may consider using a HashMap as a counter. If your language has a built-in Counter class like Python, ask to use that instead.
|
||||
|
||||
If you need to keep a counter of characters, a common mistake is to say that the space complexity required for the counter is O(n). The space required for a counter is O(1) not O(n). This is because the upper bound is the range of characters, which is usually a fixed constant of 26. The input set is just lowercase Latin characters.
|
||||
|
||||
Common data structures for looking up strings efficiently are
|
||||
|
||||
- [Trie / Prefix Tree](https://en.wikipedia.org/wiki/Trie)
|
||||
- [Suffix Tree](https://en.wikipedia.org/wiki/Suffix_tree)
|
||||
|
||||
Common string algorithms are
|
||||
|
||||
- [Rabin Karp](https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm) for efficient searching of substring using a rolling hash.
|
||||
- [KMP](https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm) for efficient searching of substring.
|
||||
|
||||
#### Corner Cases
|
||||
|
||||
- Strings with only one distinct character.
|
||||
|
||||
#### Non-repeating Characters
|
||||
|
||||
- Use a 26-bit bitmask to indicate which lower case latin characters are inside the string.
|
||||
|
||||
```py
|
||||
mask = 0
|
||||
for c in set(word):
|
||||
mask |= (1 << (ord(c) - ord('a')))
|
||||
```
|
||||
|
||||
To determine if two strings have common characters, perform & on the two bitmasks. If the result is non-zero, `mask_a & mask_b > 0`, then the two strings have common characters.
|
||||
|
||||
### Anagram
|
||||
|
||||
An anagram is word switch or word play. It is the result of re-arranging the letters of a word or phrase to produce a new word or phrase, while using all the original letters only once. In interviews, usually we are only bothered with words without spaces in them.
|
||||
|
||||
To determine if two strings are anagrams, there are a few plausible approaches:
|
||||
|
||||
- Sorting both strings should produce the same resulting string. This takes O(nlgn) time and O(lgn) space.
|
||||
- If we map each character to a prime number and we multiply each mapped number together, anagrams should have the same multiple (prime factor decomposition). This takes O(n) time and O(1) space.
|
||||
- Frequency counting of characters will help to determine if two strings are anagrams. This also takes O(n) time and O(1) space.
|
||||
|
||||
### Palindrome
|
||||
|
||||
A palindrome is a word, phrase, number, or other sequence of characters which reads the same backward as forward, such as _madam_ or _racecar_.
|
||||
|
||||
Here are ways to determine if a string is a palindrome:
|
||||
|
||||
- Reverse the string and it should be equal to itself.
|
||||
- Have two pointers at the start and end of the string. Move the pointers inward till they meet. At any point in time, the characters at both pointers should match.
|
||||
|
||||
The order of characters within the string matters, so HashMaps are usually not helpful.
|
||||
|
||||
When a question is about counting the number of palindromes, a common trick is to have two pointers that move outward, away from the middle. Note that palindromes can be even or odd length. For each middle pivot position, you need to check it twice: Once that includes the character and once without the character.
|
||||
|
||||
- For substrings, you can terminate early once there is no match.
|
||||
- For subsequences, use dynamic programming as there are overlapping subproblems. Check out [this question](https://leetcode.com/problems/longest-palindromic-subsequence/).
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Longest Substring Without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters/)
|
||||
- [Longest Repeating Character Replacement](https://leetcode.com/problems/longest-repeating-character-replacement/)
|
||||
- [Minimum Window Substring](https://leetcode.com/problems/minimum-window-substring/description/)
|
||||
- [Valid Anagram](https://leetcode.com/problems/valid-anagram)
|
||||
- [Group Anagrams](https://leetcode.com/problems/group-anagrams/)
|
||||
- [Valid Parentheses](https://leetcode.com/problems/valid-parentheses)
|
||||
- [Valid Palindrome](https://leetcode.com/problems/valid-palindrome/)
|
||||
- [Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/)
|
||||
- [Palindromic Substrings](https://leetcode.com/problems/palindromic-substrings/)
|
||||
- [Encode and Decode Strings (Leetcode Premium)](https://leetcode.com/problems/encode-and-decode-strings/)
|
||||
|
||||
## Tree
|
||||
|
||||
#### Study Links
|
||||
|
||||
- [Leaf It Up To Binary Trees](https://medium.com/basecs/leaf-it-up-to-binary-trees-11001aaf746d)
|
||||
|
||||
#### Notes
|
||||
|
||||
A tree is an undirected and connected acyclic graph.
|
||||
|
||||
Recursion is a common approach for trees. When you notice that the subtree problem can be used to solve the entire problem, try using recursion.
|
||||
|
||||
When using recursion, always remember to check for the base case, usually where the node is `null`.
|
||||
|
||||
When you are asked to traverse a tree by level, use breadth-first search.
|
||||
|
||||
Sometimes it is possible that your recursive function needs to return two values.
|
||||
|
||||
If the question involves summation of nodes along the way, be sure to check whether nodes can be negative.
|
||||
|
||||
You should be very familiar with writing pre-order, in-order, and post-order traversal recursively. As an extension, challenge yourself by writing them iteratively. Sometimes interviewers ask candidates for the iterative approach, especially if the candidate finishes writing the recursive approach too quickly.
|
||||
|
||||
#### Corner Cases
|
||||
|
||||
- Empty tree.
|
||||
- Single node.
|
||||
- Two nodes.
|
||||
- Very skewed tree (like a linked list).
|
||||
|
||||
### Binary Tree
|
||||
|
||||
In-order traversal of a binary tree is insufficient to uniquely serialize a tree. Pre-order or post-order traversal is also required.
|
||||
|
||||
### Binary Search Tree (BST)
|
||||
|
||||
In-order traversal of a BST will give you all elements in order.
|
||||
|
||||
Be very familiar with the properties of a BST and validating that a binary tree is a BST. This comes up more often than expected.
|
||||
|
||||
When a question involves a BST, the interviewer is usually looking for a solution which runs faster than O(n).
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/)
|
||||
- [Same Tree](https://leetcode.com/problems/same-tree/)
|
||||
- [Invert/Flip Binary Tree](https://leetcode.com/problems/invert-binary-tree/)
|
||||
- [Binary Tree Maximum Path Sum](https://leetcode.com/problems/binary-tree-maximum-path-sum/)
|
||||
- [Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/)
|
||||
- [Serialize and Deserialize Binary Tree](https://leetcode.com/problems/serialize-and-deserialize-binary-tree/)
|
||||
- [Subtree of Another Tree](https://leetcode.com/problems/subtree-of-another-tree/)
|
||||
- [Construct Binary Tree from Preorder and Inorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
|
||||
- [Validate Binary Search Tree](https://leetcode.com/problems/validate-binary-search-tree/)
|
||||
- [Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst/)
|
||||
- [Lowest Common Ancestor of BST](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/)
|
||||
|
||||
## Trie
|
||||
|
||||
#### Study Links
|
||||
|
||||
- [Trying to Understand Tries](https://medium.com/basecs/trying-to-understand-tries-3ec6bede0014)
|
||||
- [Implement Trie (Prefix Tree)](https://leetcode.com/articles/implement-trie-prefix-tree/)
|
||||
|
||||
#### Notes
|
||||
|
||||
Tries are special trees (prefix trees) that make searching and storing strings more efficient. Tries have many practical applications, such as conducting searches and providing autocomplete. It is helpful to know these common applications so that you can easily identify when a problem can be efficiently solved using a trie.
|
||||
|
||||
Sometimes preprocessing a dictionary of words (given in a list) into a trie, will improve the efficiency of searching for a word of length k, among n words. Searching becomes O(k) instead of O(n).
|
||||
|
||||
Be familiar with implementing, from scratch, a `Trie` class and its `add`, `remove` and `search` methods.
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree)
|
||||
- [Add and Search Word](https://leetcode.com/problems/add-and-search-word-data-structure-design)
|
||||
- [Word Search II](https://leetcode.com/problems/word-search-ii/)
|
||||
|
||||
## Heap
|
||||
|
||||
#### Study Links
|
||||
|
||||
- [Learning to Love Heaps](https://medium.com/basecs/learning-to-love-heaps-cef2b273a238)
|
||||
|
||||
#### Notes
|
||||
|
||||
If you see a top or lowest _k_ being mentioned in the question, it is usually a signal that a heap can be used to solve the problem, such as in [Top K Frequent Elements](https://leetcode.com/problems/top-k-frequent-elements/).
|
||||
|
||||
If you require the top _k_ elements use a Min Heap of size _k_. Iterate through each element, pushing it into the heap. Whenever the heap size exceeds _k_, remove the minimum element, that will guarantee that you have the _k_ largest elements.
|
||||
|
||||
#### Practice Questions
|
||||
|
||||
- [Merge K Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/)
|
||||
- [Top K Frequent Elements](https://leetcode.com/problems/top-k-frequent-elements/)
|
||||
- [Find Median from Data Stream](https://leetcode.com/problems/find-median-from-data-stream/)
|
||||
|
||||
###### References
|
||||
|
||||
- http://blog.triplebyte.com/how-to-pass-a-programming-interview
|
||||
- https://quip.com/q41AA3OmoZbC
|
||||
- http://www.geeksforgeeks.org/must-do-coding-questions-for-companies-like-amazon-microsoft-adobe/
|
||||
- https://medium.com/basecs
|
||||
@@ -3,21 +3,52 @@ id: array
|
||||
title: Array
|
||||
---
|
||||
|
||||
#### Hard
|
||||
## Tips
|
||||
|
||||
- Given a set of rectangles represented by a height and an interval along the y-axis, determine the size of its union. ([Solution](https://www.geeksforgeeks.org/divide-and-conquer-set-7-the-skyline-problem/))
|
||||
- Given an array, find the longest arithmetic progression. ([Solution](https://www.geeksforgeeks.org/longest-arithmetic-progression-dp-35/))
|
||||
- Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
|
||||
- E.g. `[100, 4, 200, 1, 3, 2] => 4`. Explanation: The longest consecutive elements sequence is `[1, 2, 3, 4]`. Therefore its length is 4. Note: Your algorithm should run in O(n) complexity. ([Solution](https://www.geeksforgeeks.org/longest-consecutive-subsequence/))
|
||||
Is the array sorted or partially sorted? If it is, some form of binary search should be possible. This also usually means that the interviewer is looking for a solution that is faster than O(n).
|
||||
|
||||
#### Medium
|
||||
Can you sort the array? Sometimes sorting the array first may significantly simplify the problem. Make sure that the order of array elements do not need to be preserved before attempting a sort.
|
||||
|
||||
- Given a list of item prices, find all possible combinations of items that sum a particular value `K`. ([Solution](https://www.geeksforgeeks.org/combinational-sum/))
|
||||
- Given an array of integers find whether there is a sub-sequence that sums to 0 and return it. ([Solution](https://www.geeksforgeeks.org/find-if-there-is-a-subarray-with-0-sum/))
|
||||
- E.g. `[1, 2, -3, 1]` => `[1, 2, -3]` or `[2, -3, 1]`
|
||||
- Trapping rain water: You have an array with the heights of an island (at point 1, point 2 etc) and you want to know how much water would remain on this island (without flowing away). ([Solution](https://www.geeksforgeeks.org/trapping-rain-water/))
|
||||
For questions where summation or multiplication of a subarray is involved, pre-computation using hashing or a prefix/suffix sum/product might be useful.
|
||||
|
||||
#### Easy
|
||||
If you are given a sequence and the interviewer asks for O(1) space, it might be possible to use the array itself as a hash table. For example, if the array only has values from 1 to N, where N is the length of the array, negate the value at that index (minus one) to indicate presence of that number.
|
||||
|
||||
## Arrays are sequences
|
||||
|
||||
Are there duplicate values in the array, would it affect the answer?
|
||||
|
||||
When using an index to iterate through array elements, be careful not to go out of bounds.
|
||||
|
||||
Be mindful about slicing or concatenating arrays in your code. Typically, slicing and concatenating arrays require O(n) time. Use start and end indices to demarcate a subarray/range where possible.
|
||||
|
||||
Sometimes you can traverse the array from the right rather than from the left.
|
||||
|
||||
Master the [sliding window technique](https://discuss.leetcode.com/topic/30941/here-is-a-10-line-template-that-can-solve-most-substring-problems) that applies to many subarray problems.
|
||||
|
||||
When you are given two arrays to process, it is common to have one index per array (pointer) to traverse/compare the both of them. For example, we use the same approach to merge two sorted arrays.
|
||||
|
||||
## Corner cases
|
||||
|
||||
- Empty sequence
|
||||
- Sequence with 1 or 2 elements
|
||||
- Sequence with repeated elements
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- [Two Sum](https://leetcode.com/problems/two-sum/)
|
||||
- [Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/)
|
||||
- [Contains Duplicate](https://leetcode.com/problems/contains-duplicate/)
|
||||
- [Product of Array Except Self](https://leetcode.com/problems/product-of-array-except-self/)
|
||||
- [Maximum Subarray](https://leetcode.com/problems/maximum-subarray/)
|
||||
- [Maximum Product Subarray](https://leetcode.com/problems/maximum-product-subarray/)
|
||||
- [Find Minimum in Rotated Sorted Array](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/)
|
||||
- [Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array/)
|
||||
- [3Sum](https://leetcode.com/problems/3sum/)
|
||||
- [Container With Most Water](https://leetcode.com/problems/container-with-most-water/)
|
||||
|
||||
## More questions
|
||||
|
||||
### Easy
|
||||
|
||||
- Implement a circular buffer using an array. ([Solution](https://www.geeksforgeeks.org/circular-queue-set-1-introduction-array-implementation/))
|
||||
- Given an array of integers, print out a histogram using the said array; include a base layer (all stars) ([Solution](https://www.geeksforgeeks.org/program-make-histogram-array/))
|
||||
@@ -46,7 +77,21 @@ title: Array
|
||||
- Given an array of integers where every value appears twice except one, find the single, non-repeating value. Follow up: do so with O(1) space. ([Solution](https://www.geeksforgeeks.org/find-element-appears-array-every-element-appears-twice/))
|
||||
- E.g., `[2, 5, 3, 2, 1, 3, 4, 5, 1]` returns 4, because it is the only value that appears in the array only once.
|
||||
|
||||
#### Other
|
||||
### Medium
|
||||
|
||||
- Given a list of item prices, find all possible combinations of items that sum a particular value `K`. ([Solution](https://www.geeksforgeeks.org/combinational-sum/))
|
||||
- Given an array of integers find whether there is a sub-sequence that sums to 0 and return it. ([Solution](https://www.geeksforgeeks.org/find-if-there-is-a-subarray-with-0-sum/))
|
||||
- E.g. `[1, 2, -3, 1]` => `[1, 2, -3]` or `[2, -3, 1]`
|
||||
- Trapping rain water: You have an array with the heights of an island (at point 1, point 2 etc) and you want to know how much water would remain on this island (without flowing away). ([Solution](https://www.geeksforgeeks.org/trapping-rain-water/))
|
||||
|
||||
### Hard
|
||||
|
||||
- Given a set of rectangles represented by a height and an interval along the y-axis, determine the size of its union. ([Solution](https://www.geeksforgeeks.org/divide-and-conquer-set-7-the-skyline-problem/))
|
||||
- Given an array, find the longest arithmetic progression. ([Solution](https://www.geeksforgeeks.org/longest-arithmetic-progression-dp-35/))
|
||||
- Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
|
||||
- E.g. `[100, 4, 200, 1, 3, 2] => 4`. Explanation: The longest consecutive elements sequence is `[1, 2, 3, 4]`. Therefore its length is 4. Note: Your algorithm should run in O(n) complexity. ([Solution](https://www.geeksforgeeks.org/longest-consecutive-subsequence/))
|
||||
|
||||
### Other
|
||||
|
||||
- In an array of arrays, e.g. given `[[], [1, 2, 3], [4, 5], [], [], [6, 7], [8], [9, 10], [], []]`, print: `1, 2, 3, 4, 5, 6, 7, 8, 9, 10`.
|
||||
- Implement an iterator that supports `hasNext()`, `next()` and `remove()` methods.
|
||||
|
||||
@@ -3,7 +3,38 @@ id: binary
|
||||
title: Binary
|
||||
---
|
||||
|
||||
- How do you verify if an interger is a power of 2?
|
||||
## Study links
|
||||
|
||||
- [Bits, Bytes, Building With Binary](https://medium.com/basecs/bits-bytes-building-with-binary-13cb4289aafa)
|
||||
|
||||
## Notes
|
||||
|
||||
Questions involving binary representations and bitwise operations are asked sometimes and you must be absolutely familiar with how to convert a number from decimal form into binary form (and vice versa) in your chosen programming language.
|
||||
|
||||
Some helpful utility snippets:
|
||||
|
||||
- Test k<sup>th</sup> bit is set: `num & (1 << k) != 0`.
|
||||
- Set k<sup>th</sup> bit: `num |= (1 << k)`.
|
||||
- Turn off k<sup>th</sup> bit: `num &= ~(1 << k)`.
|
||||
- Toggle the k<sup>th</sup> bit: `num ^= (1 << k)`.
|
||||
- To check if a number is a power of 2, `num & num - 1 == 0`.
|
||||
|
||||
## Corner cases
|
||||
|
||||
- Be aware and check for overflow/underflow
|
||||
- Negative numbers
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- [Sum of Two Integers](https://leetcode.com/problems/sum-of-two-integers/)
|
||||
- [Number of 1 Bits](https://leetcode.com/problems/number-of-1-bits/)
|
||||
- [Counting Bits](https://leetcode.com/problems/counting-bits/)
|
||||
- [Missing Number](https://leetcode.com/problems/missing-number/)
|
||||
- [Reverse Bits](https://leetcode.com/problems/reverse-bits/)
|
||||
|
||||
## More questions
|
||||
|
||||
- How do you verify if an integer is a power of 2?
|
||||
- Write a program to print the binary representation of an integer.
|
||||
- Write a program to print out the number of 1 bits in a given integer.
|
||||
- Write a program to determine the largest possible integer using the same number of 1 bits in a given number.
|
||||
|
||||
@@ -3,6 +3,33 @@ id: dynamic-programming
|
||||
title: Dynamic Programming
|
||||
---
|
||||
|
||||
## Study links
|
||||
|
||||
- [Demystifying Dynamic Programming](https://medium.freecodecamp.org/demystifying-dynamic-programming-3efafb8d4296)
|
||||
- [Dynamic Programming – 7 Steps to Solve any DP Interview Problem](https://dev.to/nikolaotasevic/dynamic-programming--7-steps-to-solve-any-dp-interview-problem-3870)
|
||||
|
||||
## Notes
|
||||
|
||||
Dynamic Programming (DP) is usually used to solve optimization problems. The only way to get better at DP is to practice. It takes some amount of practice to be able to recognize that a problem can be solved by DP.
|
||||
|
||||
Sometimes you do not need to store the whole DP table in memory, the last two values or the last two rows of the matrix will suffice.
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- 0/1 Knapsack
|
||||
- [Climbing Stairs](https://leetcode.com/problems/climbing-stairs/)
|
||||
- [Coin Change](https://leetcode.com/problems/coin-change/)
|
||||
- [Longest Increasing Subsequence](https://leetcode.com/problems/longest-increasing-subsequence/)
|
||||
- [Longest Common Subsequence](https://www.geeksforgeeks.org/longest-common-subsequence-dp-4/)
|
||||
- [Word Break Problem](https://leetcode.com/problems/word-break/)
|
||||
- [Combination Sum](https://leetcode.com/problems/combination-sum-iv/)
|
||||
- [House Robber](https://leetcode.com/problems/house-robber/) and [House Robber II](https://leetcode.com/problems/house-robber-ii/)
|
||||
- [Decode Ways](https://leetcode.com/problems/decode-ways/)
|
||||
- [Unique Paths](https://leetcode.com/problems/unique-paths/)
|
||||
- [Jump Game](https://leetcode.com/problems/jump-game/)
|
||||
|
||||
## More questions
|
||||
|
||||
- Given a flight itinerary consisting of starting city, destination city, and ticket price (2D list) - find the optimal price flight path to get from start to destination. (A variation of Dynamic Programming Shortest Path)
|
||||
- Given some coin denominations and a target value `M`, return the coins combination with the minimum number of coins.
|
||||
- Time complexity: `O(MN)`, where N is the number of distinct type of coins.
|
||||
|
||||
@@ -3,6 +3,14 @@ id: geometry
|
||||
title: Geometry
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
When comparing euclidean distance between two pairs of points, using dx<sup>2</sup> + dy<sup>2</sup> is sufficient. It is unnecessary to square root the value.
|
||||
|
||||
To find out if two circles overlap, check that the distance between the two centers of the circles is less than the sum of their radii.
|
||||
|
||||
## More questions
|
||||
|
||||
- You have a plane with lots of rectangles on it, find out how many of them intersect.
|
||||
- Which data structure would you use to query the k-nearest points of a set on a 2D plane?
|
||||
- Given many points, find k points that are closest to the origin.
|
||||
|
||||
@@ -3,6 +3,73 @@ id: graph
|
||||
title: Graph
|
||||
---
|
||||
|
||||
## Study links
|
||||
|
||||
- [From Theory To Practice: Representing Graphs](https://medium.com/basecs/from-theory-to-practice-representing-graphs-cfd782c5be38)
|
||||
- [Deep Dive Through A Graph: DFS Traversal](https://medium.com/basecs/deep-dive-through-a-graph-dfs-traversal-8177df5d0f13)
|
||||
- [Going Broad In A Graph: BFS Traversal](https://medium.com/basecs/going-broad-in-a-graph-bfs-traversal-959bd1a09255)
|
||||
|
||||
## Notes
|
||||
|
||||
Be familiar with the various graph representations, graph search algorithms and their time and space complexities.
|
||||
|
||||
You can be given a list of edges and tasked to build your own graph from the edges to perform a traversal on. The common graph representations are:
|
||||
|
||||
- Adjacency matrix.
|
||||
- Adjacency list.
|
||||
- Hashmap of hashmaps.
|
||||
|
||||
A tree-like diagram could very well be a graph that allows for cycles and a naive recursive solution would not work. In that case you will have to handle cycles and keep a set of visited nodes when traversing.
|
||||
|
||||
## Graph search algorithms:
|
||||
|
||||
- **Common** - Breadth-first Search, Depth-first Search
|
||||
- **Uncommon** - Topological Sort, Dijkstra's algorithm
|
||||
- **Rare** - Bellman-Ford algorithm, Floyd-Warshall algorithm, Prim's algorithm, Kruskal's algorithm
|
||||
|
||||
In coding interviews, graphs are commonly represented as 2-D matrices where cells are the nodes and each cell can traverse to its adjacent cells (up/down/left/right). Hence it is important that you be familiar with traversing a 2-D matrix. When recursively traversing the matrix, always ensure that your next position is within the boundary of the matrix. More tips for doing depth-first searches on a matrix can be found [here](https://discuss.leetcode.com/topic/66065/python-dfs-bests-85-tips-for-all-dfs-in-matrix-question/). A simple template for doing depth-first searches on a matrix goes like this:
|
||||
|
||||
```py
|
||||
def traverse(matrix):
|
||||
rows, cols = len(matrix), len(matrix[0])
|
||||
visited = set()
|
||||
directions = ((0, 1), (0, -1), (1, 0), (-1, 0))
|
||||
def dfs(i, j):
|
||||
if (i, j) in visited:
|
||||
return
|
||||
visited.add((i, j))
|
||||
# Traverse neighbors
|
||||
for direction in directions:
|
||||
next_i, next_j = i + direction[0], j + direction[1]
|
||||
if 0 <= next_i < rows and 0 <= next_j < cols: # Check boundary
|
||||
# Add any other checking here ^
|
||||
dfs(next_i, next_j)
|
||||
|
||||
for i in range(rows):
|
||||
for j in range(cols):
|
||||
dfs(i, j)
|
||||
```
|
||||
|
||||
## Corner cases
|
||||
|
||||
- Empty graph
|
||||
- Graph with one or two nodes
|
||||
- Disjoint graphs
|
||||
- Graph with cycles
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- [Clone Graph](https://leetcode.com/problems/clone-graph/)
|
||||
- [Course Schedule](https://leetcode.com/problems/course-schedule/)
|
||||
- [Pacific Atlantic Water Flow](https://leetcode.com/problems/pacific-atlantic-water-flow/)
|
||||
- [Number of Islands](https://leetcode.com/problems/number-of-islands/)
|
||||
- [Longest Consecutive Sequence](https://leetcode.com/problems/longest-consecutive-sequence/)
|
||||
- [Alien Dictionary (Leetcode Premium)](https://leetcode.com/problems/alien-dictionary/)
|
||||
- [Graph Valid Tree (Leetcode Premium)](https://leetcode.com/problems/graph-valid-tree/)
|
||||
- [Number of Connected Components in an Undirected Graph (Leetcode Premium)](https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/)
|
||||
|
||||
## More questions
|
||||
|
||||
- Given a list of sorted words from an alien dictionary, find the order of the alphabet.
|
||||
- Alien Dictionary Topological Sort question.
|
||||
- Find if a given string matches any path in a labeled graph. A path may contain cycles.
|
||||
|
||||
@@ -3,9 +3,8 @@ id: hash-table
|
||||
title: Hash Table
|
||||
---
|
||||
|
||||
Hash Table
|
||||
## More questions
|
||||
|
||||
- Describe an implementation of a least-used cache, and big-O notation of it.
|
||||
- A question involving an API's integration with hash map where the buckets of hash map are made up of linked lists.
|
||||
- Implement data structure `Map` storing pairs of integers (key, value) and define following member functions in O(1) runtime: `void insert(key, value)`, `void delete(key)`, `int get(key)`, `int getRandomKey()`.
|
||||
- [Source](http://blog.gainlo.co/index.php/2016/08/14/uber-interview-question-map-implementation/).
|
||||
- Implement data structure `Map` storing pairs of integers (key, value) and define following member functions in O(1) runtime: `void insert(key, value)`, `void delete(key)`, `int get(key)`, `int getRandomKey()`. [(Solution)](http://blog.gainlo.co/index.php/2016/08/14/uber-interview-question-map-implementation/)
|
||||
|
||||
@@ -3,5 +3,23 @@ id: heap
|
||||
title: Heap
|
||||
---
|
||||
|
||||
## Study links
|
||||
|
||||
- [Learning to Love Heaps](https://medium.com/basecs/learning-to-love-heaps-cef2b273a238)
|
||||
|
||||
## Notes
|
||||
|
||||
If you see a top or lowest _k_ being mentioned in the question, it is usually a signal that a heap can be used to solve the problem, such as in [Top K Frequent Elements](https://leetcode.com/problems/top-k-frequent-elements/).
|
||||
|
||||
If you require the top _k_ elements use a Min Heap of size _k_. Iterate through each element, pushing it into the heap. Whenever the heap size exceeds _k_, remove the minimum element, that will guarantee that you have the _k_ largest elements.
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- [Merge K Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/)
|
||||
- [Top K Frequent Elements](https://leetcode.com/problems/top-k-frequent-elements/)
|
||||
- [Find Median from Data Stream](https://leetcode.com/problems/find-median-from-data-stream/)
|
||||
|
||||
## More questions
|
||||
|
||||
- Merge `K` sorted lists together into a single list.
|
||||
- Given a stream of integers, write an efficient function that returns the median value of the integers.
|
||||
|
||||
@@ -3,6 +3,44 @@ id: interval
|
||||
title: Interval
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
Interval questions are questions where you are given an array of two-element arrays (an interval) and the two values represent a start and an end value. Interval questions are considered part of the array family but they involve some common techniques hence they are extracted out to this special section of their own.
|
||||
|
||||
An example interval array: `[[1, 2], [4, 7]]`.
|
||||
|
||||
Interval questions can be tricky to those who have not tried them before because of the sheer number of cases to consider when they overlap.
|
||||
|
||||
Do clarify with the interviewer whether `[1, 2]` and `[2, 3]` are considered overlapping intervals as it affects how you will write your equality checks.
|
||||
|
||||
A common routine for interval questions is to sort the array of intervals by each interval's starting value.
|
||||
|
||||
Be familiar with writing code to check if two intervals overlap and merging two overlapping intervals:
|
||||
|
||||
```py
|
||||
def is_overlap(a, b):
|
||||
return a[0] < b[1] and b[0] < a[1]
|
||||
|
||||
def merge_overlapping_intervals(a, b):
|
||||
return [min(a[0], b[0]), max(a[1], b[1])]
|
||||
```
|
||||
|
||||
## Corner cases
|
||||
|
||||
- Single interval
|
||||
- Non-overlapping intervals
|
||||
- An interval totally consumed within another interval
|
||||
- Duplicate intervals
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- [Insert Interval](https://leetcode.com/problems/insert-interval/)
|
||||
- [Merge Intervals](https://leetcode.com/problems/merge-intervals/)
|
||||
- [Non-overlapping Intervals](https://leetcode.com/problems/non-overlapping-intervals/)
|
||||
- [Meeting Rooms (Leetcode Premium)](https://leetcode.com/problems/meeting-rooms/) and [Meeting Rooms II (Leetcode Premium)](https://leetcode.com/problems/meeting-rooms-ii/)
|
||||
|
||||
## More questions
|
||||
|
||||
- Given a list of schedules, provide a list of times that are available for a meeting.
|
||||
|
||||
```
|
||||
@@ -24,8 +62,7 @@ title: Interval
|
||||
- Given 2 interval ranges that intersect, now create a function to merge the 2 ranges into a single continuous range.
|
||||
- E.g. `[1, 4]` and `[3, 6]` => `[1, 6]`
|
||||
- Now create a function that takes a group of unsorted, unorganized intervals, merge any intervals that intersect and sort them. The result should be a group of sorted, non-intersecting intervals.
|
||||
- Now create a function to merge a new interval into a group of sorted, non-intersecting intervals. After the merge, all intervals should remain
|
||||
non-intersecting.
|
||||
- Now create a function to merge a new interval into a group of sorted, non-intersecting intervals. After the merge, all intervals should remain non-intersecting.
|
||||
- Given a list of meeting times, check if any of them overlap. The follow-up question is to return the minimum number of rooms required to accommodate all the meetings.
|
||||
- [Source](http://blog.gainlo.co/index.php/2016/07/12/meeting-room-scheduling-problem/)
|
||||
- If you have a list of intervals, how would you merge them?
|
||||
|
||||
52
contents/algorithms/introduction.md
Normal file
52
contents/algorithms/introduction.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
id: algorithms-introduction
|
||||
title: Introduction
|
||||
---
|
||||
|
||||
This section dives deep into practical tips for specific topics of algorithms and data structures which appear frequently in coding questions. Many algorithm questions involve techniques that can be applied to questions of similar nature. The more techniques you have in your arsenal, the higher the chances of passing the interview. They may lead you to discover corner cases you might have missed out or even lead you towards the optimal approach!
|
||||
|
||||
For each topic, study links are recommended to help you master the topic. There is a list of recommended common questions to practice which in my opinion is highly valuable for mastering the core concepts for the topic.
|
||||
|
||||
If you are interested in how data structures are implemented, check out [Lago](https://github.com/yangshun/lago), a Data Structures and Algorithms library for JavaScript. It is pretty much still WIP but I intend to make it into a library that is able to be used in production and also a reference resource for revising Data Structures and Algorithms.
|
||||
|
||||
## General tips
|
||||
|
||||
Clarify any assumptions you made subconsciously. Many questions are under-specified on purpose.
|
||||
|
||||
Always validate input first. Check for invalid/empty/negative/different type input. Never assume you are given the valid parameters. Alternatively, clarify with the interviewer whether you can assume valid input (usually yes), which can save you time from writing code that does input validation.
|
||||
|
||||
Are there any time/space complexity requirements/constraints?
|
||||
|
||||
Check for off-by-one errors.
|
||||
|
||||
In languages where there are no automatic type coercion, check that concatenation of values are of the same type: `int`/`str`/`list`.
|
||||
|
||||
After finishing your code, use a few example inputs to test your solution.
|
||||
|
||||
Is the algorithm meant to be run multiple times, for example in a web server? If yes, the input is likely to be preprocess-able to improve the efficiency in each call.
|
||||
|
||||
Use a mix of functional and imperative programming paradigms:
|
||||
|
||||
- Write pure functions as much as possible.
|
||||
- Pure functions are easier to reason about and can help to reduce bugs in your implementation.
|
||||
- Avoid mutating the parameters passed into your function especially if they are passed by reference unless you are sure of what you are doing.
|
||||
- However, functional programming is usually expensive in terms of space complexity because of non-mutation and the repeated allocation of new objects. On the other hand, imperative code is faster because you operate on existing objects. Hence you will need to achieve a balance between accuracy vs efficiency, by using the right amount of functional and imperative code where appropriate.
|
||||
- Avoid relying on and mutating global variables. Global variables introduce state.
|
||||
- If you have to rely on global variables, make sure that you do not mutate it by accident.
|
||||
|
||||
Generally, to improve the speed of a program, we can either: (1) choose a more appropriate data structure/algorithm; or (2) use more memory. The latter demonstrates a classic space vs. time tradeoff, but it is not necessarily the case that you can only achieve better speed at the expense of space. Also, note that there is often a theoretical limit to how fast your program can run (in terms of time complexity). For instance, a question that requires you to find the smallest/largest element in an unsorted array cannot run faster than O(N).
|
||||
|
||||
Data structures are your weapons. Choosing the right weapon for the right battle is the key to victory. Be very familiar about the strengths of each data structure and the time complexities for its various operations.
|
||||
|
||||
Data structures can be augmented to achieve efficient time complexities across different operations. For example, a hash map can be used together with a doubly-linked list to achieve O(1) time complexity for both the `get` and `put` operation in an [LRU cache](https://leetcode.com/problems/lru-cache/).
|
||||
|
||||
Hashmaps are probably the most commonly used data structure for algorithm questions. If you are stuck on a question, your last resort can be to enumerate through the common possible data structures (thankfully there aren't that many of them) and consider whether each of them can be applied to the problem. This has worked for me sometimes.
|
||||
|
||||
If you are cutting corners in your code, state that out loud to your interviewer and say what you would do in a non-interview setting (no time constraints). E.g., I would write a regex to parse this string rather than using `split()` which may not cover all cases.
|
||||
|
||||
###### References
|
||||
|
||||
- http://blog.triplebyte.com/how-to-pass-a-programming-interview
|
||||
- https://quip.com/q41AA3OmoZbC
|
||||
- http://www.geeksforgeeks.org/must-do-coding-questions-for-companies-like-amazon-microsoft-adobe/
|
||||
- https://medium.com/basecs
|
||||
@@ -3,6 +3,52 @@ id: linked-list
|
||||
title: Linked List
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
Like arrays, linked lists are used to represent sequential data. The benefit of linked lists is that insertion and deletion from anywhere in the list is O(1) whereas in arrays the following elements will have to be shifted.
|
||||
|
||||
Adding a dummy node at the head and/or tail might help to handle many edge cases where operations have to be performed at the head or the tail. The presence of dummy nodes essentially ensures that operations will never have be done on the head or the tail, thereby removing a lot of headache in writing conditional checks to dealing with null pointers. Be sure to remember to remove them at the end of the operation.
|
||||
|
||||
Sometimes linked lists problem can be solved without additional storage. Try to borrow ideas from reverse a linked list problem.
|
||||
|
||||
For deletion in linked lists, you can either modify the node values or change the node pointers. You might need to keep a reference to the previous element.
|
||||
|
||||
For partitioning linked lists, create two separate linked lists and join them back together.
|
||||
|
||||
Linked lists problems share similarity with array problems, think about how you would do it for an array and try to apply it to a linked list.
|
||||
|
||||
Two pointer approaches are also common for linked lists. For example:
|
||||
|
||||
- Getting the k<sup>th</sup> from last node - Have two pointers, where one is k nodes ahead of the other. When the node ahead reaches the end, the other node is k nodes behind
|
||||
- Detecting cycles - Have two pointers, where one pointer increments twice as much as the other, if the two pointers meet, means that there is a cycle
|
||||
- Getting the middle node - Have two pointers, where one pointer increments twice as much as the other. When the faster node reaches the end of the list, the slower node will be at the middle
|
||||
|
||||
## Common Routines
|
||||
|
||||
Be familiar with the following routines because many linked list questions make use of one or more of these routines in the solution:
|
||||
|
||||
- Counting the number of nodes in the linked list
|
||||
- Reversing a linked list in-place
|
||||
- Finding the middle node of the linked list using fast/slow pointers
|
||||
- Merging two lists together
|
||||
|
||||
## Corner cases
|
||||
|
||||
- Single node
|
||||
- Two nodes
|
||||
- Linked list has cycle. **Tip:** Clarify with the interviewer whether there can be a cycle in the list. Usually the answer is no
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- [Reverse a Linked List](https://leetcode.com/problems/reverse-linked-list/)
|
||||
- [Detect Cycle in a Linked List](https://leetcode.com/problems/linked-list-cycle/)
|
||||
- [Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/)
|
||||
- [Merge K Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/)
|
||||
- [Remove Nth Node From End Of List](https://leetcode.com/problems/remove-nth-node-from-end-of-list/)
|
||||
- [Reorder List](https://leetcode.com/problems/reorder-list/)
|
||||
|
||||
## More questions
|
||||
|
||||
- Given a linked list, in addition to the next pointer, each node has a child pointer that can point to a separate list. With the head node, flatten the list to a single-level linked list.
|
||||
- [Source](http://blog.gainlo.co/index.php/2016/06/12/flatten-a-linked-list/)
|
||||
- Reverse a singly linked list. Implement it recursively and iteratively.
|
||||
|
||||
@@ -3,6 +3,33 @@ id: math
|
||||
title: Math
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
If code involves division or modulo, remember to check for division or modulo by 0 case.
|
||||
|
||||
When a question involves "a multiple of a number", perhaps modulo might be useful.
|
||||
|
||||
Check for and handle overflow/underflow if you are using a typed language like Java and C++. At the very least, mention that overflow/underflow is possible and ask whether you need to handle it.
|
||||
|
||||
Consider negative numbers and floating point numbers. This may sound obvious, but under interview pressure, many obvious cases go unnoticed.
|
||||
|
||||
If the question asks to implement an operator such as power, squareroot or division and want it to be faster than O(n), binary search is usually the approach to go.
|
||||
|
||||
#### Some common formulas:
|
||||
|
||||
- Sum of 1 to N = (n+1) \* n/2
|
||||
- Sum of GP = 2<sup>0</sup> + 2<sup>1</sup> + 2<sup>2</sup> + 2<sup>3</sup> + ... 2<sup>n</sup> = 2<sup>n+1</sup> - 1
|
||||
- Permutations of N = N! / (N-K)!
|
||||
- Combinations of N = N! / (K! \* (N-K)!)
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- [Pow(x, n)](https://leetcode.com/problems/powx-n/)
|
||||
- [Sqrt(x)](https://leetcode.com/problems/sqrtx/)
|
||||
- [Integer to English Words](https://leetcode.com/problems/integer-to-english-words/)
|
||||
|
||||
## More questions
|
||||
|
||||
- Create a square root function.
|
||||
- Given a string such as "123" or "67", write a function to output the number represented by the string without using casting.
|
||||
- Make a program that can print out the text form of numbers from 1 - 1000 (ex. 20 is "twenty", 105 is "one hundred and five").
|
||||
|
||||
@@ -3,6 +3,40 @@ id: matrix
|
||||
title: Matrix
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
A matrix is a 2-dimensional array. Questions involving matrices are usually related to dynamic programming or graph traversal.
|
||||
|
||||
For questions involving traversal or dynamic programming, you almost always want to make a copy of the matrix with the same dimensions that is initialized to empty values to store the visited state or dynamic programming table. Be familiar with such a routine:
|
||||
|
||||
```py
|
||||
rows, cols = len(matrix), len(matrix[0])
|
||||
copy = [[0 for _ in range(cols)] for _ in range(rows)]
|
||||
```
|
||||
|
||||
Many grid-based games can be modeled as a matrix, such as Tic-Tac-Toe, Sudoku, Crossword, Connect 4, Battleship, etc. It is not uncommon to be asked to verify the winning condition of the game. For games like Tic-Tac-Toe, Connect 4 and Crosswords, where verification has to be done vertically and horizontally, one trick is to write code to verify the matrix for the horizontal cells, transpose the matrix and reuse the logic for horizontal verification to verify originally vertical cells (which are now horizontal).
|
||||
|
||||
Transposing a matrix in Python is simply:
|
||||
|
||||
```py
|
||||
transposed_matrix = zip(*matrix)
|
||||
```
|
||||
|
||||
## Corner cases
|
||||
|
||||
- Empty matrix. Check that none of the arrays are 0 length
|
||||
- 1 x 1 matrix
|
||||
- Matrix with only one row or column
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- [Set Matrix Zeroes](https://leetcode.com/problems/set-matrix-zeroes/)
|
||||
- [Spiral Matrix](https://leetcode.com/problems/spiral-matrix/)
|
||||
- [Rotate Image](https://leetcode.com/problems/rotate-image/)
|
||||
- [Word Search](https://leetcode.com/problems/word-search/)
|
||||
|
||||
## More questions
|
||||
|
||||
- You're given a 3 x 3 board of a tile puzzle, with 8 tiles numbered 1 to 8, and an empty spot. You can move any tile adjacent to the empty spot, to the empty spot, creating an empty spot where the tile originally was. The goal is to find a series of moves that will solve the board, i.e. get `[[1, 2, 3], [4, 5, 6], [7, 8, - ]]` where - is the empty tile.
|
||||
- Boggle implementation. Given a dictionary, and a matrix of letters, find all the words in the matrix that are in the dictionary. You can go across, down or diagonally.
|
||||
- The values of the matrix will represent numbers of carrots available to the rabbit in each square of the garden. If the garden does not have an exact center, the rabbit should start in the square closest to the center with the highest carrot count. On a given turn, the rabbit will eat the carrots available on the square that it is on, and then move up, down, left, or right, choosing the square that has the most carrots. If there are no carrots left on any of the adjacent squares, the rabbit will go to sleep. You may assume that the rabbit will never have to choose between two squares with the same number of carrots. Write a function which takes a garden matrix and returns the number of carrots the rabbit eats. You may assume the matrix is rectangular with at least 1 row and 1 column, and that it is populated with non-negative integers. For example,
|
||||
|
||||
@@ -3,6 +3,8 @@ id: oop
|
||||
title: Object-Oriented Programming
|
||||
---
|
||||
|
||||
## More questions
|
||||
|
||||
- How would you design a chess game? What classes and objects would you use? What methods would they have?
|
||||
- How would you design the data structures for a book keeping system for a library?
|
||||
- Explain how you would design a HTTP server? Give examples of classes, methods, and interfaces. What are the challenges here?
|
||||
|
||||
@@ -3,6 +3,8 @@ id: permutation
|
||||
title: Permutation
|
||||
---
|
||||
|
||||
## More questions
|
||||
|
||||
- You are given a 7 digit phone number, and you should find all possible letter combinations based on the digit-to-letter mapping on numeric pad and return only the ones that have valid match against a given dictionary of words.
|
||||
- Give all possible letter combinations from a phone number.
|
||||
- Generate all subsets of a string.
|
||||
|
||||
@@ -3,5 +3,7 @@ id: queue
|
||||
title: Queue
|
||||
---
|
||||
|
||||
## More questions
|
||||
|
||||
- Implement a Queue class from scratch with an existing bug, the bug is that it cannot take more than 5 elements.
|
||||
- Implement a Queue using two stacks. You may only use the standard `push()`, `pop()`, and `peek()` operations traditionally available to stacks. You do not need to implement the stack yourself (i.e. an array can be used to simulate a stack).
|
||||
|
||||
17
contents/algorithms/recursion.md
Normal file
17
contents/algorithms/recursion.md
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
id: recursion
|
||||
title: Recursion
|
||||
---
|
||||
|
||||
## Notes
|
||||
|
||||
Recursion is useful for permutation, because it generates all combinations and tree-based questions. You should know how to generate all permutations of a sequence as well as how to handle duplicates.
|
||||
|
||||
Remember to always define a base case so that your recursion will end.
|
||||
|
||||
Recursion implicitly uses a stack. Hence all recursive approaches can be rewritten iteratively using a stack. Beware of cases where the recursion level goes too deep and causes a stack overflow (the default limit in Python is 1000). You may get bonus points for pointing this out to the interviewer. Recursion will never be O(1) space complexity because a stack is involved, unless there is [tail-call optimization](https://stackoverflow.com/questions/310974/what-is-tail-call-optimization) (TCO). Find out if your chosen language supports TCO.
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- [Subsets](https://leetcode.com/problems/subsets/) and [Subsets II](https://leetcode.com/problems/subsets-ii/)
|
||||
- [Strobogrammatic Number II (Leetcode Premium)](https://leetcode.com/problems/strobogrammatic-number-ii/)
|
||||
@@ -3,6 +3,8 @@ id: sorting-searching
|
||||
title: Sorting and Searching
|
||||
---
|
||||
|
||||
## More questions
|
||||
|
||||
- Sorting search results on a page given a certain set of criteria.
|
||||
- Sort a list of numbers in which each number is at a distance `K` from its actual position.
|
||||
- Given an array of integers, sort the array so that all odd indexes are greater than the even indexes.
|
||||
|
||||
@@ -3,6 +3,8 @@ id: stack
|
||||
title: Stack
|
||||
---
|
||||
|
||||
## More questions
|
||||
|
||||
- Implementation of an interpreter for a small language that does multiplication/addition/etc.
|
||||
- Design a `MinStack` data structure that supports a `min()` operation that returns the minimum value in the stack in O(1) time.
|
||||
- Write an algorithm to determine if all of the delimiters in an expression are matched and closed.
|
||||
|
||||
@@ -3,6 +3,104 @@ id: string
|
||||
title: String
|
||||
---
|
||||
|
||||
## Tips
|
||||
|
||||
Ask about input character set and case sensitivity. Usually the characters are limited to lowercase Latin characters, for example a to z.
|
||||
|
||||
When you need to compare strings where the order isn’t important (like anagram), you may consider using a HashMap as a counter. If your language has a built-in Counter class like Python, ask to use that instead.
|
||||
|
||||
If you need to keep a counter of characters, a common mistake is to say that the space complexity required for the counter is O(n). The space required for a counter is O(1) not O(n). This is because the upper bound is the range of characters, which is usually a fixed constant of 26. The input set is just lowercase Latin characters.
|
||||
|
||||
Common data structures for looking up strings efficiently are
|
||||
|
||||
- [Trie/Prefix Tree](https://en.wikipedia.org/wiki/Trie)
|
||||
- [Suffix Tree](https://en.wikipedia.org/wiki/Suffix_tree)
|
||||
|
||||
Common string algorithms are
|
||||
|
||||
- [Rabin Karp](https://en.wikipedia.org/wiki/Rabin%E2%80%93Karp_algorithm) for efficient searching of substring using a rolling hash
|
||||
- [KMP](https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm) for efficient searching of substring
|
||||
|
||||
## Strings are sequences
|
||||
|
||||
A string is a sequence of characters. Many tips that apply to arrays also apply to strings.
|
||||
|
||||
Are there duplicate characters in the string, would it affect the answer?
|
||||
|
||||
When using an index to iterate through characters, be careful not to go out of bounds.
|
||||
|
||||
Be mindful about slicing or concatenating strings in your code. Typically, slicing and concatenating strings require O(n) time. Use start and end indices to demarcate a substring where possible.
|
||||
|
||||
Sometimes you can traverse the string from the right rather than from the left.
|
||||
|
||||
Master the [sliding window technique](https://discuss.leetcode.com/topic/30941/here-is-a-10-line-template-that-can-solve-most-substring-problems) that applies to many substring problems.
|
||||
|
||||
When you are given two strings to process, it is common to have one index per string (pointer) to traverse/compare the both of them. For example, we use the same approach to merge two sorted arrays.
|
||||
|
||||
## Common question topics
|
||||
|
||||
Many string questions fall into one of these buckets.
|
||||
|
||||
### Non-repeating Characters
|
||||
|
||||
- Use a 26-bit bitmask to indicate which lower case latin characters are inside the string.
|
||||
|
||||
```py
|
||||
mask = 0
|
||||
for c in set(word):
|
||||
mask |= (1 << (ord(c) - ord('a')))
|
||||
```
|
||||
|
||||
To determine if two strings have common characters, perform & on the two bitmasks. If the result is non-zero, `mask_a & mask_b > 0`, then the two strings have common characters.
|
||||
|
||||
### Anagram
|
||||
|
||||
An anagram is word switch or word play. It is the result of re-arranging the letters of a word or phrase to produce a new word or phrase, while using all the original letters only once. In interviews, usually we are only bothered with words without spaces in them.
|
||||
|
||||
To determine if two strings are anagrams, there are a few plausible approaches:
|
||||
|
||||
- Sorting both strings should produce the same resulting string. This takes O(nlgn) time and O(lgn) space.
|
||||
- If we map each character to a prime number and we multiply each mapped number together, anagrams should have the same multiple (prime factor decomposition). This takes O(n) time and O(1) space.
|
||||
- Frequency counting of characters will help to determine if two strings are anagrams. This also takes O(n) time and O(1) space.
|
||||
|
||||
### Palindrome
|
||||
|
||||
A palindrome is a word, phrase, number, or other sequence of characters which reads the same backward as forward, such as _madam_ or _racecar_.
|
||||
|
||||
Here are ways to determine if a string is a palindrome:
|
||||
|
||||
- Reverse the string and it should be equal to itself.
|
||||
- Have two pointers at the start and end of the string. Move the pointers inward till they meet. At any point in time, the characters at both pointers should match.
|
||||
|
||||
The order of characters within the string matters, so HashMaps are usually not helpful.
|
||||
|
||||
When a question is about counting the number of palindromes, a common trick is to have two pointers that move outward, away from the middle. Note that palindromes can be even or odd length. For each middle pivot position, you need to check it twice: Once that includes the character and once without the character.
|
||||
|
||||
- For substrings, you can terminate early once there is no match.
|
||||
- For subsequences, use dynamic programming as there are overlapping subproblems. Check out [this question](https://leetcode.com/problems/longest-palindromic-subsequence/).
|
||||
|
||||
## Corner cases
|
||||
|
||||
- Empty string
|
||||
- String with 1 or 2 characters
|
||||
- String with repeated characters
|
||||
- Strings with only one distinct character
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- [Longest Substring Without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters/)
|
||||
- [Longest Repeating Character Replacement](https://leetcode.com/problems/longest-repeating-character-replacement/)
|
||||
- [Minimum Window Substring](https://leetcode.com/problems/minimum-window-substring/description/)
|
||||
- [Valid Anagram](https://leetcode.com/problems/valid-anagram)
|
||||
- [Group Anagrams](https://leetcode.com/problems/group-anagrams/)
|
||||
- [Valid Parentheses](https://leetcode.com/problems/valid-parentheses)
|
||||
- [Valid Palindrome](https://leetcode.com/problems/valid-palindrome/)
|
||||
- [Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/)
|
||||
- [Palindromic Substrings](https://leetcode.com/problems/palindromic-substrings/)
|
||||
- [Encode and Decode Strings (Leetcode Premium)](https://leetcode.com/problems/encode-and-decode-strings/)
|
||||
|
||||
## More questions
|
||||
|
||||
- Output list of strings representing a page of hostings given a list of CSV strings.
|
||||
- Given a list of words, find the word pairs that when concatenated form a palindrome.
|
||||
- Find the most efficient way to identify what character is out of place in a non-palindrome.
|
||||
|
||||
@@ -3,6 +3,65 @@ id: tree
|
||||
title: Tree
|
||||
---
|
||||
|
||||
## Study links
|
||||
|
||||
- [Leaf It Up To Binary Trees](https://medium.com/basecs/leaf-it-up-to-binary-trees-11001aaf746d)
|
||||
|
||||
## Notes
|
||||
|
||||
A tree is an undirected and connected acyclic graph.
|
||||
|
||||
Recursion is a common approach for trees. When you notice that the subtree problem can be used to solve the entire problem, try using recursion.
|
||||
|
||||
When using recursion, always remember to check for the base case, usually where the node is `null`.
|
||||
|
||||
When you are asked to traverse a tree by level, use breadth-first search.
|
||||
|
||||
Sometimes it is possible that your recursive function needs to return two values.
|
||||
|
||||
If the question involves summation of nodes along the way, be sure to check whether nodes can be negative.
|
||||
|
||||
You should be very familiar with writing pre-order, in-order, and post-order traversal recursively. As an extension, challenge yourself by writing them iteratively. Sometimes interviewers ask candidates for the iterative approach, especially if the candidate finishes writing the recursive approach too quickly.
|
||||
|
||||
Do check out the section on [Trie](trie.md), which is an advanced tree.
|
||||
|
||||
## Corner cases
|
||||
|
||||
- Empty tree
|
||||
- Single node
|
||||
- Two nodes
|
||||
- Very skewed tree (like a linked list)
|
||||
|
||||
## Special Trees
|
||||
|
||||
### Binary Tree
|
||||
|
||||
In-order traversal of a binary tree is insufficient to uniquely serialize a tree. Pre-order or post-order traversal is also required.
|
||||
|
||||
### Binary Search Tree (BST)
|
||||
|
||||
In-order traversal of a BST will give you all elements in order.
|
||||
|
||||
Be very familiar with the properties of a BST and validating that a binary tree is a BST. This comes up more often than expected.
|
||||
|
||||
When a question involves a BST, the interviewer is usually looking for a solution which runs faster than O(n).
|
||||
|
||||
#### Recommended Leetcode questions
|
||||
|
||||
- [Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/)
|
||||
- [Same Tree](https://leetcode.com/problems/same-tree/)
|
||||
- [Invert/Flip Binary Tree](https://leetcode.com/problems/invert-binary-tree/)
|
||||
- [Binary Tree Maximum Path Sum](https://leetcode.com/problems/binary-tree-maximum-path-sum/)
|
||||
- [Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/)
|
||||
- [Serialize and Deserialize Binary Tree](https://leetcode.com/problems/serialize-and-deserialize-binary-tree/)
|
||||
- [Subtree of Another Tree](https://leetcode.com/problems/subtree-of-another-tree/)
|
||||
- [Construct Binary Tree from Preorder and Inorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal/)
|
||||
- [Validate Binary Search Tree](https://leetcode.com/problems/validate-binary-search-tree/)
|
||||
- [Kth Smallest Element in a BST](https://leetcode.com/problems/kth-smallest-element-in-a-bst/)
|
||||
- [Lowest Common Ancestor of BST](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/)
|
||||
|
||||
## More questions
|
||||
|
||||
- Find the height of a tree.
|
||||
- Find the longest path from the root to leaf in a tree.
|
||||
- Find the deepest left leaf of a tree.
|
||||
|
||||
23
contents/algorithms/trie.md
Normal file
23
contents/algorithms/trie.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
id: trie
|
||||
title: Trie
|
||||
---
|
||||
|
||||
## Study links
|
||||
|
||||
- [Trying to Understand Tries](https://medium.com/basecs/trying-to-understand-tries-3ec6bede0014)
|
||||
- [Implement Trie (Prefix Tree)](https://leetcode.com/articles/implement-trie-prefix-tree/)
|
||||
|
||||
## Notes
|
||||
|
||||
Tries are special trees (prefix trees) that make searching and storing strings more efficient. Tries have many practical applications, such as conducting searches and providing autocomplete. It is helpful to know these common applications so that you can easily identify when a problem can be efficiently solved using a trie.
|
||||
|
||||
Sometimes preprocessing a dictionary of words (given in a list) into a trie, will improve the efficiency of searching for a word of length k, among n words. Searching becomes O(k) instead of O(n).
|
||||
|
||||
Be familiar with implementing, from scratch, a `Trie` class and its `add`, `remove` and `search` methods.
|
||||
|
||||
## Recommended Leetcode questions
|
||||
|
||||
- [Implement Trie (Prefix Tree)](https://leetcode.com/problems/implement-trie-prefix-tree)
|
||||
- [Add and Search Word](https://leetcode.com/problems/add-and-search-word-data-structure-design)
|
||||
- [Word Search II](https://leetcode.com/problems/word-search-ii/)
|
||||
Reference in New Issue
Block a user