diff --git a/.editorconfig b/.editorconfig index be3654ef..8412c119 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,4 +8,4 @@ trim_trailing_whitespace = true [*.{js,py}] charset = utf-8 indent_style = space -indent_size = 4 +indent_size = 2 diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 00000000..a2a849e3 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,8 @@ +{ + "bracketSpacing": false, + "jsxBracketSameLine": true, + "printWidth": 80, + "proseWrap": "never", + "singleQuote": true, + "trailingComma": "all" +} diff --git a/algorithms/README.md b/contents/algorithms/README.md similarity index 100% rename from algorithms/README.md rename to contents/algorithms/README.md diff --git a/algorithms/array.md b/contents/algorithms/array.md similarity index 100% rename from algorithms/array.md rename to contents/algorithms/array.md diff --git a/algorithms/binary.md b/contents/algorithms/binary.md similarity index 100% rename from algorithms/binary.md rename to contents/algorithms/binary.md diff --git a/algorithms/dynamic-programming.md b/contents/algorithms/dynamic-programming.md similarity index 100% rename from algorithms/dynamic-programming.md rename to contents/algorithms/dynamic-programming.md diff --git a/algorithms/geometry.md b/contents/algorithms/geometry.md similarity index 100% rename from algorithms/geometry.md rename to contents/algorithms/geometry.md diff --git a/algorithms/graph.md b/contents/algorithms/graph.md similarity index 100% rename from algorithms/graph.md rename to contents/algorithms/graph.md diff --git a/algorithms/hash-table.md b/contents/algorithms/hash-table.md similarity index 100% rename from algorithms/hash-table.md rename to contents/algorithms/hash-table.md diff --git a/algorithms/heap.md b/contents/algorithms/heap.md similarity index 100% rename from algorithms/heap.md rename to contents/algorithms/heap.md diff --git a/algorithms/interval.md b/contents/algorithms/interval.md similarity index 100% rename from algorithms/interval.md rename to contents/algorithms/interval.md diff --git a/algorithms/linked-list.md b/contents/algorithms/linked-list.md similarity index 100% rename from algorithms/linked-list.md rename to contents/algorithms/linked-list.md diff --git a/algorithms/math.md b/contents/algorithms/math.md similarity index 100% rename from algorithms/math.md rename to contents/algorithms/math.md diff --git a/algorithms/matrix.md b/contents/algorithms/matrix.md similarity index 100% rename from algorithms/matrix.md rename to contents/algorithms/matrix.md diff --git a/algorithms/oop.md b/contents/algorithms/oop.md similarity index 100% rename from algorithms/oop.md rename to contents/algorithms/oop.md diff --git a/algorithms/permutation.md b/contents/algorithms/permutation.md similarity index 100% rename from algorithms/permutation.md rename to contents/algorithms/permutation.md diff --git a/algorithms/queue.md b/contents/algorithms/queue.md similarity index 100% rename from algorithms/queue.md rename to contents/algorithms/queue.md diff --git a/algorithms/sorting-searching.md b/contents/algorithms/sorting-searching.md similarity index 100% rename from algorithms/sorting-searching.md rename to contents/algorithms/sorting-searching.md diff --git a/algorithms/stack.md b/contents/algorithms/stack.md similarity index 100% rename from algorithms/stack.md rename to contents/algorithms/stack.md diff --git a/algorithms/string.md b/contents/algorithms/string.md similarity index 100% rename from algorithms/string.md rename to contents/algorithms/string.md diff --git a/algorithms/topics.md b/contents/algorithms/topics.md similarity index 100% rename from algorithms/topics.md rename to contents/algorithms/topics.md diff --git a/algorithms/tree.md b/contents/algorithms/tree.md similarity index 100% rename from algorithms/tree.md rename to contents/algorithms/tree.md diff --git a/non-technical/behavioral.md b/contents/non-technical/behavioral.md similarity index 100% rename from non-technical/behavioral.md rename to contents/non-technical/behavioral.md diff --git a/non-technical/cover-letter.md b/contents/non-technical/cover-letter.md similarity index 100% rename from non-technical/cover-letter.md rename to contents/non-technical/cover-letter.md diff --git a/non-technical/interview-formats.md b/contents/non-technical/interview-formats.md similarity index 100% rename from non-technical/interview-formats.md rename to contents/non-technical/interview-formats.md diff --git a/non-technical/negotiation.md b/contents/non-technical/negotiation.md similarity index 100% rename from non-technical/negotiation.md rename to contents/non-technical/negotiation.md diff --git a/non-technical/psychological-tricks.md b/contents/non-technical/psychological-tricks.md similarity index 100% rename from non-technical/psychological-tricks.md rename to contents/non-technical/psychological-tricks.md diff --git a/non-technical/questions-to-ask.md b/contents/non-technical/questions-to-ask.md similarity index 100% rename from non-technical/questions-to-ask.md rename to contents/non-technical/questions-to-ask.md diff --git a/non-technical/resume.md b/contents/non-technical/resume.md similarity index 100% rename from non-technical/resume.md rename to contents/non-technical/resume.md diff --git a/non-technical/self-introduction.md b/contents/non-technical/self-introduction.md similarity index 100% rename from non-technical/self-introduction.md rename to contents/non-technical/self-introduction.md diff --git a/preparing/README.md b/contents/preparing/README.md similarity index 100% rename from preparing/README.md rename to contents/preparing/README.md diff --git a/contents/preparing/cheatsheet.md b/contents/preparing/cheatsheet.md new file mode 100644 index 00000000..51f38d51 --- /dev/null +++ b/contents/preparing/cheatsheet.md @@ -0,0 +1,105 @@ +--- +id: interview-cheatsheet +title: Interview Cheatsheet +--- + +This is a straight-to-the-point, distilled list of technical interview Do's and Don'ts, mainly for algorithmic interviews. Some of these may apply to only phone screens or whiteboard interviews, but most will apply to both. I revise this list before each of my interviews to remind myself of them and eventually internalized all of them to the point I do not have to rely on it anymore. + +For a detailed walkthrough of interview preparation, refer to the ["Preparing for a Coding Interview"](./) section. + +**Legend:** ✅ = Do, ❌ = Don't, ⚠️ = Situational + +### 1. Before Interview + +| | Things | +| --- | --- | +| ✅ | Prepare pen, paper and earphones/headphones. | +| ✅ | Find a quiet environment with good Internet connection. | +| ✅ | Ensure webcam and audio are working. There were times I had to restart Chrome to get Hangouts to work again. | +| ✅ | Request for the option to interview over Hangouts/Skype instead of a phone call; it is easier to send links or text across. | +| ✅ | Decide on and be familiar with a programming language. | +| ✅ | Familiarize yourself with the coding environment (CoderPad/CodePen). Set up the coding shortcuts, turn on autocompletion, tab spacing, etc. | +| ✅ | Prepare answers to the [frequently-asked questions](../non-technical/behavioral.md) in an interview. | +| ✅ | Prepare some [questions to ask](../non-technical/questions-to-ask.md) at the end of the interview. | +| ✅ | Dress comfortably. Usually you do not need to wear smart clothes, casual should be fine. T-shirts and jeans are acceptable at most places. | +| ✅ | Stay calm and composed. | +| ⚠️ | Turn off the webcam if possible. Most remote interviews will not require video chat and leaving it on only serves as a distraction. | + +### 2. Introduction + +| | Things | +| --- | --- | +| ✅ | Introduce yourself in a few sentences under a minute or two. | +| ✅ | Mention interesting points that are relevant to the role you are applying for. | +| ✅ | Sound enthusiastic! Speak with a smile and you will naturally sound more engaging. | +| ❌ | Spend too long introducing yourself. The more time you spend talking the less time you have to code. | + +### 3. Upon Getting the Question + +| | Things | +| --- | --- | +| ✅ | Repeat the question back at the interviewer. | +| ✅ | Clarify any assumptions you made subconsciously. Many questions are under-specified on purpose. A tree-like diagram could very well be a graph that allows for cycles and a naive recursive solution would not work. | +| ✅ | Clarify input format and range. Ask whether input can be assumed to be well-formed and non-null. | +| ✅ | Work through a small example to ensure you understood the question. | +| ✅ | Explain a high level approach even if it is a brute force one. | +| ✅ | Improve upon the approach and optimize. Reduce duplicated work and cache repeated computations. | +| ✅ | Think carefully, then state and explain the time and space complexity of your approaches. | +| ✅ | If stuck, think about related problems you have seen before and how they were solved. Check out the [tips](../algorithms) in this section. | +| ❌ | Ignore information given to you. Every piece is important. | +| ❌ | Jump into coding straightaway. | +| ❌ | Start coding without interviewer's green light. | +| ❌ | Appear too unsure about your approach or analysis. | + +### 4. During Coding + +| | Things | +| --- | --- | +| ✅ | Explain what you are coding/typing to the interviewer, what you are trying to achieve. | +| ✅ | Practice good coding style. Clear variable names, consistent operator spacing, proper indentation, etc. | +| ✅ | Type/write at a reasonable speed. | +| ✅ | As much as possible, write actual compilable code, not pseudocode. | +| ✅ | Write in a modular fashion. Extract out chunks of repeated code into functions. | +| ✅ | Ask for permission to use trivial functions without having to implement them; saves you some time. | +| ✅ | Use the hints given by the interviewer. | +| ✅ | Demonstrate mastery of your chosen programming language. | +| ✅ | Demonstrate technical knowledge in data structures and algorithms. | +| ✅ | 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. | +| ✅ | Practice whiteboard space-management skills. | +| ⚠️ | Reasonable defensive coding. Check for nulls, empty collections, etc. Can omit if input validity has been clarified with the interviewer. | +| ❌ | Remain quiet the whole time. | +| ❌ | Spend too much time writing comments. | +| ❌ | Use extremely verbose variable names. | +| ❌ | Copy and paste code without checking. | +| ❌ | Interrupt your interviewer when they are talking. Usually if they speak, they are trying to give you hints or steer you in the right direction. | +| ❌ | Write too big (takes up too much space) or too small (illegible) if on a whiteboard. | + +### 5. After Coding + +| | Things | +| --- | --- | +| ✅ | Scan through your code for mistakes as if it was your first time seeing code written by someone else. | +| ✅ | Check for off-by-one errors. | +| ✅ | Come up with more test cases. Try extreme test cases. | +| ✅ | Step through your code with those test cases. | +| ✅ | Look out for places where you can refactor. | +| ✅ | Reiterate the time and space complexity of your code. | +| ✅ | Explain trade-offs and how the code/approach can be improved if given more time. | +| ❌ | Immediately announce that you are done coding. Do the above first! | +| ❌ | Argue with the interviewer. They may be wrong but that is very unlikely given that they are familiar with the question. | + +### 6. Wrap Up + +| | Things | +| --- | --- | +| ✅ | Ask questions. More importantly, ask good and engaging questions that are tailored to the company! Pick some questions from [this list](../non-technical/questions-to-ask.md). | +| ✅ | Thank the interviewer. | +| ⚠️ | Ask about your interview performance. It can get awkward. | +| ❌ | End the interview without asking any questions. | + +### 7. Post Interview + +| | Things | +| --- | --- | +| ✅ | Record the interview questions and answers down as these can be useful for future reference. | +| ⚠️ | Send a follow up email to your interviewer(s) thanking them for their time and the opportunity to interview with them. | diff --git a/design/README.md b/experimental/design/README.md similarity index 100% rename from design/README.md rename to experimental/design/README.md diff --git a/design/collaborative-editor.md b/experimental/design/collaborative-editor.md similarity index 100% rename from design/collaborative-editor.md rename to experimental/design/collaborative-editor.md diff --git a/design/news-feed.md b/experimental/design/news-feed.md similarity index 100% rename from design/news-feed.md rename to experimental/design/news-feed.md diff --git a/design/search-engine.md b/experimental/design/search-engine.md similarity index 100% rename from design/search-engine.md rename to experimental/design/search-engine.md diff --git a/domain/async-loading/index.html b/experimental/domain/async-loading/index.html similarity index 100% rename from domain/async-loading/index.html rename to experimental/domain/async-loading/index.html diff --git a/domain/databases.md b/experimental/domain/databases.md similarity index 100% rename from domain/databases.md rename to experimental/domain/databases.md diff --git a/domain/networking.md b/experimental/domain/networking.md similarity index 100% rename from domain/networking.md rename to experimental/domain/networking.md diff --git a/domain/pagination-sorting/data.js b/experimental/domain/pagination-sorting/data.js similarity index 100% rename from domain/pagination-sorting/data.js rename to experimental/domain/pagination-sorting/data.js diff --git a/domain/pagination-sorting/index.html b/experimental/domain/pagination-sorting/index.html similarity index 100% rename from domain/pagination-sorting/index.html rename to experimental/domain/pagination-sorting/index.html diff --git a/domain/security.md b/experimental/domain/security.md similarity index 100% rename from domain/security.md rename to experimental/domain/security.md diff --git a/domain/snake-game/snake-game.md b/experimental/domain/snake-game/snake-game.md similarity index 100% rename from domain/snake-game/snake-game.md rename to experimental/domain/snake-game/snake-game.md diff --git a/domain/software-engineering.md b/experimental/domain/software-engineering.md similarity index 100% rename from domain/software-engineering.md rename to experimental/domain/software-engineering.md diff --git a/domain/tic-tac-toe/index.html b/experimental/domain/tic-tac-toe/index.html similarity index 100% rename from domain/tic-tac-toe/index.html rename to experimental/domain/tic-tac-toe/index.html diff --git a/front-end/README.md b/experimental/front-end/README.md similarity index 100% rename from front-end/README.md rename to experimental/front-end/README.md diff --git a/interviewers/basics.md b/experimental/interviewers/basics.md similarity index 100% rename from interviewers/basics.md rename to experimental/interviewers/basics.md diff --git a/utilities/javascript/binToInt.js b/experimental/utilities/javascript/binToInt.js similarity index 68% rename from utilities/javascript/binToInt.js rename to experimental/utilities/javascript/binToInt.js index c34a278d..35a87127 100644 --- a/utilities/javascript/binToInt.js +++ b/experimental/utilities/javascript/binToInt.js @@ -1,10 +1,10 @@ // Does not handle negative binary numbers. function binToInt(binary) { - let res = 0; - for (let i = 0; i < binary.length; i++) { - res = res * 2 + (+binary[i]); - } - return res; + let res = 0; + for (let i = 0; i < binary.length; i++) { + res = res * 2 + +binary[i]; + } + return res; } console.log(binToInt('0') === parseInt('0', 2) && parseInt('0', 2) === 0); @@ -12,4 +12,7 @@ console.log(binToInt('1') === parseInt('1', 2) && parseInt('1', 2) === 1); console.log(binToInt('10') === parseInt('10', 2) && parseInt('10', 2) === 2); console.log(binToInt('11') === parseInt('11', 2) && parseInt('11', 2) === 3); console.log(binToInt('101') === parseInt('101', 2) && parseInt('101', 2) === 5); -console.log(binToInt('1100011') === parseInt('1100011', 2) && parseInt('1100011', 2) === 99); +console.log( + binToInt('1100011') === parseInt('1100011', 2) && + parseInt('1100011', 2) === 99, +); diff --git a/utilities/javascript/binarySearch.js b/experimental/utilities/javascript/binarySearch.js similarity index 60% rename from utilities/javascript/binarySearch.js rename to experimental/utilities/javascript/binarySearch.js index 9ce8b336..e36f54bd 100644 --- a/utilities/javascript/binarySearch.js +++ b/experimental/utilities/javascript/binarySearch.js @@ -1,18 +1,18 @@ function binarySearch(arr, target) { - let left = 0; - let right = arr.length - 1; - while (left <= right) { - const mid = left + Math.floor((right - left) / 2); - if (arr[mid] === target) { - return mid; - } - if (arr[mid] < target) { - left = mid + 1; - } else { - right = mid - 1; - } + let left = 0; + let right = arr.length - 1; + while (left <= right) { + const mid = left + Math.floor((right - left) / 2); + if (arr[mid] === target) { + return mid; } - return -1; + if (arr[mid] < target) { + left = mid + 1; + } else { + right = mid - 1; + } + } + return -1; } console.log(binarySearch([1, 2, 3, 10], 1) === 0); diff --git a/experimental/utilities/javascript/deepEqual.js b/experimental/utilities/javascript/deepEqual.js new file mode 100644 index 00000000..826fdb20 --- /dev/null +++ b/experimental/utilities/javascript/deepEqual.js @@ -0,0 +1,43 @@ +function deepEqual(val1, val2) { + if (typeof val1 !== typeof val2) { + return false; + } + + // Array comparison. + if (Array.isArray(val1) && Array.isArray(val2)) { + if (val1.length !== val2.length) { + return false; + } + for (let i = 0; i < val1.length; i++) { + if (!deepEqual(val1[i], val2[i])) { + return false; + } + } + return true; + } + + // Object comparison. + if ( + typeof val1 === 'object' && + typeof val2 === 'object' && + val1 !== null && + val2 !== null + ) { + const keys1 = Object.keys(val1), + keys2 = Object.keys(val2); + if (keys1.length !== keys2.length) { + return false; + } + for (let i = 0; i < keys1.length; i++) { + if (!deepEqual(val1[keys1[i]], val2[keys2[i]])) { + return false; + } + } + return true; + } + + // Primitive comparison. + return val1 === val2; +} + +module.exports = deepEqual; diff --git a/experimental/utilities/javascript/graphTopoSort.js b/experimental/utilities/javascript/graphTopoSort.js new file mode 100644 index 00000000..3bbd8232 --- /dev/null +++ b/experimental/utilities/javascript/graphTopoSort.js @@ -0,0 +1,35 @@ +function graphTopoSort(numberNodes, edges) { + const nodes = new Map(); + const order = []; + const queue = []; + for (let i = 0; i < numberNodes; i++) { + nodes.set(i, {in: 0, out: new Set()}); + } + + edges.forEach(edge => { + const [node_id, pre_id] = edge; + nodes.get(node_id).in += 1; + nodes.get(pre_id).out.add(node_id); + }); + + for (let [node_id, value] of nodes.entries()) { + if (value.in === 0) { + queue.push(node_id); + } + } + + while (queue.length) { + const node_id = queue.shift(); + for (let outgoing_id of nodes.get(node_id).out) { + nodes.get(outgoing_id).in -= 1; + if (nodes.get(outgoing_id).in === 0) { + queue.push(outgoing_id); + } + } + order.push(node_id); + } + + return order.length == numberNodes ? order : []; +} + +console.log(graphTopoSort(3, [[0, 1], [0, 2]])); diff --git a/experimental/utilities/javascript/intToBin.js b/experimental/utilities/javascript/intToBin.js new file mode 100644 index 00000000..187cdf1a --- /dev/null +++ b/experimental/utilities/javascript/intToBin.js @@ -0,0 +1,21 @@ +// Does not handle negative numbers. +function intToBin(number) { + if (number === 0) { + return '0'; + } + let res = ''; + while (number > 0) { + res = String(number % 2) + res; + number = parseInt(number / 2, 10); + } + return res; +} + +console.log(intToBin(0) === (0).toString(2) && (0).toString(2) === '0'); +console.log(intToBin(1) === (1).toString(2) && (1).toString(2) === '1'); +console.log(intToBin(2) === (2).toString(2) && (2).toString(2) === '10'); +console.log(intToBin(3) === (3).toString(2) && (3).toString(2) === '11'); +console.log(intToBin(5) === (5).toString(2) && (5).toString(2) === '101'); +console.log( + intToBin(99) === (99).toString(2) && (99).toString(2) === '1100011', +); diff --git a/utilities/javascript/intervalsIntersect.js b/experimental/utilities/javascript/intervalsIntersect.js similarity index 95% rename from utilities/javascript/intervalsIntersect.js rename to experimental/utilities/javascript/intervalsIntersect.js index 2c6d59a0..4d13dfa8 100644 --- a/utilities/javascript/intervalsIntersect.js +++ b/experimental/utilities/javascript/intervalsIntersect.js @@ -1,6 +1,6 @@ // Interval: [start, end]. function intervalsIntersect(a, b) { - return a[0] < b[1] && b[0] < a[1]; + return a[0] < b[1] && b[0] < a[1]; } console.log(intervalsIntersect([1, 2], [3, 4]) === false); diff --git a/utilities/javascript/intervalsMerge.js b/experimental/utilities/javascript/intervalsMerge.js similarity index 92% rename from utilities/javascript/intervalsMerge.js rename to experimental/utilities/javascript/intervalsMerge.js index 795ca37a..b574f19d 100644 --- a/utilities/javascript/intervalsMerge.js +++ b/experimental/utilities/javascript/intervalsMerge.js @@ -1,7 +1,7 @@ // Interval: [start, end]. // Merges two overlapping intervals into one. function intervalsMerge(a, b) { - return [Math.min(a[0], b[0]), Math.max(a[1], b[1])]; + return [Math.min(a[0], b[0]), Math.max(a[1], b[1])]; } const deepEqual = require('./deepEqual'); diff --git a/utilities/javascript/isSubsequence.js b/experimental/utilities/javascript/isSubsequence.js similarity index 56% rename from utilities/javascript/isSubsequence.js rename to experimental/utilities/javascript/isSubsequence.js index b529399c..532ae26e 100644 --- a/utilities/javascript/isSubsequence.js +++ b/experimental/utilities/javascript/isSubsequence.js @@ -1,14 +1,14 @@ function isSubsequence(s, t) { - if (s.length > t.length) { - return false; + if (s.length > t.length) { + return false; + } + let matchedLength = 0; + for (let i = 0; i < t.length; i++) { + if (matchedLength < s.length && s[matchedLength] === t[i]) { + matchedLength += 1; } - let matchedLength = 0; - for (let i = 0; i < t.length; i++) { - if (matchedLength < s.length && s[matchedLength] === t[i]) { - matchedLength += 1; - } - } - return matchedLength === s.length; + } + return matchedLength === s.length; } console.log(isSubsequence('abc', 'abcde') === true); diff --git a/utilities/javascript/matrixClone.js b/experimental/utilities/javascript/matrixClone.js similarity index 64% rename from utilities/javascript/matrixClone.js rename to experimental/utilities/javascript/matrixClone.js index b3f3f996..2dc00dc2 100644 --- a/utilities/javascript/matrixClone.js +++ b/experimental/utilities/javascript/matrixClone.js @@ -1,7 +1,9 @@ function matrixClone(matrix, defaultValue) { - return matrix.map(row => { - return defaultValue === undefined ? row.slice(0) : Array(row.length).fill(defaultValue); - }); + return matrix.map(row => { + return defaultValue === undefined + ? row.slice(0) + : Array(row.length).fill(defaultValue); + }); } const deepEqual = require('./deepEqual'); @@ -15,4 +17,6 @@ console.log(deepEqual(matrixClone([[1]]), [[1]])); // Test clone with default value. console.log(deepEqual(matrixClone([[1, 2], [1, 4]], 1), [[1, 1], [1, 1]])); -console.log(deepEqual(matrixClone([[1, 2], [1, 4]], null), [[null, null], [null, null]])); +console.log( + deepEqual(matrixClone([[1, 2], [1, 4]], null), [[null, null], [null, null]]), +); diff --git a/utilities/javascript/matrixTranspose.js b/experimental/utilities/javascript/matrixTranspose.js similarity index 63% rename from utilities/javascript/matrixTranspose.js rename to experimental/utilities/javascript/matrixTranspose.js index 0418a426..134dc918 100644 --- a/utilities/javascript/matrixTranspose.js +++ b/experimental/utilities/javascript/matrixTranspose.js @@ -1,5 +1,5 @@ function matrixTranspose(matrix) { - return matrix[0].map((col, i) => matrix.map(row => row[i])); + return matrix[0].map((col, i) => matrix.map(row => row[i])); } const deepEqual = require('./deepEqual'); @@ -7,5 +7,6 @@ const deepEqual = require('./deepEqual'); console.log(deepEqual(matrixTranspose([[1]]), [[1]])); console.log(deepEqual(matrixTranspose([[1, 2]]), [[1], [2]])); console.log(deepEqual(matrixTranspose([[1, 2], [1, 4]]), [[1, 1], [2, 4]])); -console.log(deepEqual(matrixTranspose([[1, 2, 3], [4, 5, 6]]), [[1, 4], [2, 5], [3, 6]])); - +console.log( + deepEqual(matrixTranspose([[1, 2, 3], [4, 5, 6]]), [[1, 4], [2, 5], [3, 6]]), +); diff --git a/experimental/utilities/javascript/matrixTraverse.js b/experimental/utilities/javascript/matrixTraverse.js new file mode 100644 index 00000000..40619f78 --- /dev/null +++ b/experimental/utilities/javascript/matrixTraverse.js @@ -0,0 +1,30 @@ +function traverse(matrix) { + const DIRECTIONS = [[0, 1], [0, -1], [1, 0], [-1, 0]]; + const rows = matrix.length; + const cols = matrix[0].length; + const visited = matrix.map(row => Array(row.length).fill(false)); + function dfs(i, j) { + if (visited[i][j]) { + return; + } + visited[i][j] = true; + DIRECTIONS.forEach(dir => { + const row = i + dir[0], + col = j + dir[1]; + // Boundary check. + if (row < 0 || row >= rows || col < 0 || col >= cols) { + return; + } + // Valid neighbor check. + if (matrix[row][col] !== 1) { + return; + } + dfs(row, col); + }); + } + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + dfs(i, j); + } + } +} diff --git a/experimental/utilities/javascript/mergeSort.js b/experimental/utilities/javascript/mergeSort.js new file mode 100644 index 00000000..49cf2469 --- /dev/null +++ b/experimental/utilities/javascript/mergeSort.js @@ -0,0 +1,62 @@ +function mergeSort(arr) { + if (arr.length < 2) { + // Arrays of length 0 or 1 are sorted by definition. + return arr; + } + + const left = arr.slice(0, Math.floor(arr.length / 2)); + const right = arr.slice(Math.floor(arr.length / 2), Math.floor(arr.length)); + + return merge(mergeSort(left), mergeSort(right)); +} + +function merge(arr1, arr2) { + const merged = []; + let i = 0, + j = 0; + + while (i < arr1.length && j < arr2.length) { + if (arr1[i] <= arr2[j]) { + merged.push(arr1[i]); + i++; + } else if (arr2[j] < arr1[i]) { + merged.push(arr2[j]); + j++; + } + } + + merged.push(...arr1.slice(i), ...arr2.slice(j)); + return merged; +} + +const deepEqual = require('./deepEqual'); + +console.log(deepEqual(mergeSort([]), [])); +console.log(deepEqual(mergeSort([1]), [1])); +console.log(deepEqual(mergeSort([2, 1]), [1, 2])); +console.log(deepEqual(mergeSort([7, 2, 4, 3, 1, 2]), [1, 2, 2, 3, 4, 7])); +console.log(deepEqual(mergeSort([1, 2, 3, 4, 5, 0]), [0, 1, 2, 3, 4, 5])); +console.log( + deepEqual(mergeSort([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), [ + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + ]), +); +console.log( + deepEqual(mergeSort([98322, 3242, 876, -234, 34, 12331]), [ + -234, + 34, + 876, + 3242, + 12331, + 98322, + ]), +); diff --git a/experimental/utilities/javascript/treeEqual.js b/experimental/utilities/javascript/treeEqual.js new file mode 100644 index 00000000..e5c23c0a --- /dev/null +++ b/experimental/utilities/javascript/treeEqual.js @@ -0,0 +1,13 @@ +function treeEqual(node1, node2) { + if (!node1 && !node2) { + return true; + } + if (!node1 || !node2) { + return false; + } + return ( + node1.val == node2.val && + treeEqual(node1.left, node2.left) && + treeEqual(node1.right, node2.right) + ); +} diff --git a/experimental/utilities/javascript/treeMirror.js b/experimental/utilities/javascript/treeMirror.js new file mode 100644 index 00000000..ad8be653 --- /dev/null +++ b/experimental/utilities/javascript/treeMirror.js @@ -0,0 +1,10 @@ +function treeMirror(node) { + if (!node) { + return; + } + let temp = node.left; + node.left = node.right; + node.right = temp; + treeMirror(node.left); + treeMirror(node.right); +} diff --git a/utilities/python/binary_search.py b/experimental/utilities/python/binary_search.py similarity index 99% rename from utilities/python/binary_search.py rename to experimental/utilities/python/binary_search.py index 4e664c72..b0f97c4a 100644 --- a/utilities/python/binary_search.py +++ b/experimental/utilities/python/binary_search.py @@ -66,4 +66,3 @@ print(bisect_right([1, 2, 3, 3, 10], 10) == 5) print(bisect_right([1, 2, 3, 3, 10], 9) == 4) print(bisect_right([1, 2, 3, 3, 10], 0) == 0) # Insert "0" at front print(bisect_right([1, 2, 3, 3, 10], 11) == 5) # Insert "5" at back - diff --git a/utilities/python/char_prime_map.py b/experimental/utilities/python/char_prime_map.py similarity index 100% rename from utilities/python/char_prime_map.py rename to experimental/utilities/python/char_prime_map.py diff --git a/utilities/python/graph_dfs.py b/experimental/utilities/python/graph_dfs.py similarity index 100% rename from utilities/python/graph_dfs.py rename to experimental/utilities/python/graph_dfs.py diff --git a/utilities/python/graph_topo_sort.py b/experimental/utilities/python/graph_topo_sort.py similarity index 100% rename from utilities/python/graph_topo_sort.py rename to experimental/utilities/python/graph_topo_sort.py diff --git a/utilities/python/heap.py b/experimental/utilities/python/heap.py similarity index 100% rename from utilities/python/heap.py rename to experimental/utilities/python/heap.py diff --git a/utilities/python/is_subsequence.py b/experimental/utilities/python/is_subsequence.py similarity index 100% rename from utilities/python/is_subsequence.py rename to experimental/utilities/python/is_subsequence.py diff --git a/utilities/python/linked_list.py b/experimental/utilities/python/linked_list.py similarity index 100% rename from utilities/python/linked_list.py rename to experimental/utilities/python/linked_list.py diff --git a/utilities/python/quick_select.py b/experimental/utilities/python/quick_select.py similarity index 100% rename from utilities/python/quick_select.py rename to experimental/utilities/python/quick_select.py diff --git a/utilities/python/rabin_karp_hash.py b/experimental/utilities/python/rabin_karp_hash.py similarity index 100% rename from utilities/python/rabin_karp_hash.py rename to experimental/utilities/python/rabin_karp_hash.py diff --git a/utilities/python/tree_equal.py b/experimental/utilities/python/tree_equal.py similarity index 100% rename from utilities/python/tree_equal.py rename to experimental/utilities/python/tree_equal.py diff --git a/utilities/python/tree_mirror.py b/experimental/utilities/python/tree_mirror.py similarity index 100% rename from utilities/python/tree_mirror.py rename to experimental/utilities/python/tree_mirror.py diff --git a/utilities/python/tree_traversal.py b/experimental/utilities/python/tree_traversal.py similarity index 100% rename from utilities/python/tree_traversal.py rename to experimental/utilities/python/tree_traversal.py diff --git a/utilities/python/trie.py b/experimental/utilities/python/trie.py similarity index 100% rename from utilities/python/trie.py rename to experimental/utilities/python/trie.py diff --git a/utilities/python/union_find.py b/experimental/utilities/python/union_find.py similarity index 100% rename from utilities/python/union_find.py rename to experimental/utilities/python/union_find.py diff --git a/preparing/cheatsheet.md b/preparing/cheatsheet.md deleted file mode 100644 index 96f4b210..00000000 --- a/preparing/cheatsheet.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -id: interview-cheatsheet -title: Interview Cheatsheet ---- - -This is a straight-to-the-point, distilled list of technical interview Do's and Don'ts, mainly for algorithmic interviews. Some of these may apply to only phone screens or whiteboard interviews, but most will apply to both. I revise this list before each of my interviews to remind myself of them and eventually internalized all of them to the point I do not have to rely on it anymore. - -For a detailed walkthrough of interview preparation, refer to the ["Preparing for a Coding Interview"](./) section. - -**Legend:** ✅ = Do, ❌ = Don't, ⚠️ = Situational - -### 1. Before Interview - -|| Things | -|-|-| -|✅|Prepare pen, paper and earphones/headphones.| -|✅|Find a quiet environment with good Internet connection.| -|✅|Ensure webcam and audio are working. There were times I had to restart Chrome to get Hangouts to work again.| -|✅|Request for the option to interview over Hangouts/Skype instead of a phone call; it is easier to send links or text across.| -|✅|Decide on and be familiar with a programming language.| -|✅|Familiarize yourself with the coding environment (CoderPad/CodePen). Set up the coding shortcuts, turn on autocompletion, tab spacing, etc.| -|✅|Prepare answers to the [frequently-asked questions](../non-technical/behavioral.md) in an interview.| -|✅|Prepare some [questions to ask](../non-technical/questions-to-ask.md) at the end of the interview.| -|✅|Dress comfortably. Usually you do not need to wear smart clothes, casual should be fine. T-shirts and jeans are acceptable at most places.| -|✅|Stay calm and composed.| -|⚠️|Turn off the webcam if possible. Most remote interviews will not require video chat and leaving it on only serves as a distraction.| - -### 2. Introduction - -|| Things | -|-|-| -|✅|Introduce yourself in a few sentences under a minute or two.| -|✅|Mention interesting points that are relevant to the role you are applying for.| -|✅|Sound enthusiastic! Speak with a smile and you will naturally sound more engaging.| -|❌|Spend too long introducing yourself. The more time you spend talking the less time you have to code.| - -### 3. Upon Getting the Question - -|| Things | -|-|-| -|✅|Repeat the question back at the interviewer.| -|✅|Clarify any assumptions you made subconsciously. Many questions are under-specified on purpose. A tree-like diagram could very well be a graph that allows for cycles and a naive recursive solution would not work.| -|✅|Clarify input format and range. Ask whether input can be assumed to be well-formed and non-null.| -|✅|Work through a small example to ensure you understood the question.| -|✅|Explain a high level approach even if it is a brute force one.| -|✅|Improve upon the approach and optimize. Reduce duplicated work and cache repeated computations.| -|✅|Think carefully, then state and explain the time and space complexity of your approaches.| -|✅|If stuck, think about related problems you have seen before and how they were solved. Check out the [tips](../algorithms) in this section.| -|❌|Ignore information given to you. Every piece is important.| -|❌|Jump into coding straightaway.| -|❌|Start coding without interviewer's green light.| -|❌|Appear too unsure about your approach or analysis.| - -### 4. During Coding - -|| Things | -|-|-| -|✅|Explain what you are coding/typing to the interviewer, what you are trying to achieve.| -|✅|Practice good coding style. Clear variable names, consistent operator spacing, proper indentation, etc.| -|✅|Type/write at a reasonable speed.| -|✅|As much as possible, write actual compilable code, not pseudocode.| -|✅|Write in a modular fashion. Extract out chunks of repeated code into functions.| -|✅|Ask for permission to use trivial functions without having to implement them; saves you some time.| -|✅|Use the hints given by the interviewer.| -|✅|Demonstrate mastery of your chosen programming language.| -|✅|Demonstrate technical knowledge in data structures and algorithms.| -|✅|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.| -|✅|Practice whiteboard space-management skills.| -|⚠️|Reasonable defensive coding. Check for nulls, empty collections, etc. Can omit if input validity has been clarified with the interviewer.| -|❌|Remain quiet the whole time.| -|❌|Spend too much time writing comments.| -|❌|Use extremely verbose variable names.| -|❌|Copy and paste code without checking.| -|❌|Interrupt your interviewer when they are talking. Usually if they speak, they are trying to give you hints or steer you in the right direction.| -|❌|Write too big (takes up too much space) or too small (illegible) if on a whiteboard.| - -### 5. After Coding - -|| Things | -|-|-| -|✅|Scan through your code for mistakes as if it was your first time seeing code written by someone else.| -|✅|Check for off-by-one errors.| -|✅|Come up with more test cases. Try extreme test cases.| -|✅|Step through your code with those test cases.| -|✅|Look out for places where you can refactor.| -|✅|Reiterate the time and space complexity of your code.| -|✅|Explain trade-offs and how the code/approach can be improved if given more time.| -|❌|Immediately announce that you are done coding. Do the above first!| -|❌|Argue with the interviewer. They may be wrong but that is very unlikely given that they are familiar with the question.| - -### 6. Wrap Up - -|| Things | -|-|-| -|✅|Ask questions. More importantly, ask good and engaging questions that are tailored to the company! Pick some questions from [this list](../non-technical/questions-to-ask.md).| -|✅|Thank the interviewer.| -|⚠️|Ask about your interview performance. It can get awkward.| -|❌|End the interview without asking any questions.| - -### 7. Post Interview - -|| Things | -|-|-| -|✅|Record the interview questions and answers down as these can be useful for future reference.| -|⚠️|Send a follow up email to your interviewer(s) thanking them for their time and the opportunity to interview with them.| diff --git a/utilities/javascript/deepEqual.js b/utilities/javascript/deepEqual.js deleted file mode 100644 index d2c9f649..00000000 --- a/utilities/javascript/deepEqual.js +++ /dev/null @@ -1,37 +0,0 @@ -function deepEqual(val1, val2) { - if (typeof val1 !== typeof val2) { - return false; - } - - // Array comparison. - if (Array.isArray(val1) && Array.isArray(val2)) { - if (val1.length !== val2.length) { - return false; - } - for (let i = 0; i < val1.length; i++) { - if (!deepEqual(val1[i], val2[i])) { - return false; - } - } - return true; - } - - // Object comparison. - if (typeof val1 === 'object' && typeof val2 === 'object' && val1 !== null && val2 !== null) { - const keys1 = Object.keys(val1), keys2 = Object.keys(val2); - if (keys1.length !== keys2.length) { - return false; - } - for (let i = 0; i < keys1.length; i++) { - if (!deepEqual(val1[keys1[i]], val2[keys2[i]])) { - return false; - } - } - return true; - } - - // Primitive comparison. - return val1 === val2; -} - -module.exports = deepEqual; diff --git a/utilities/javascript/graphTopoSort.js b/utilities/javascript/graphTopoSort.js deleted file mode 100644 index 13468026..00000000 --- a/utilities/javascript/graphTopoSort.js +++ /dev/null @@ -1,35 +0,0 @@ -function graphTopoSort(numberNodes, edges) { - const nodes = new Map(); - const order = []; - const queue = []; - for (let i = 0; i < numberNodes; i++) { - nodes.set(i, { in: 0, out: new Set() }); - } - - edges.forEach(edge => { - const [node_id, pre_id] = edge; - nodes.get(node_id).in += 1; - nodes.get(pre_id).out.add(node_id); - }); - - for (let [node_id, value] of nodes.entries()) { - if (value.in === 0) { - queue.push(node_id); - } - } - - while (queue.length) { - const node_id = queue.shift(); - for (let outgoing_id of nodes.get(node_id).out) { - nodes.get(outgoing_id).in -= 1; - if (nodes.get(outgoing_id).in === 0) { - queue.push(outgoing_id); - } - } - order.push(node_id); - } - - return order.length == numberNodes ? order : []; -} - -console.log(graphTopoSort(3, [[0, 1], [0, 2]])); diff --git a/utilities/javascript/intToBin.js b/utilities/javascript/intToBin.js deleted file mode 100644 index 6d33e7e5..00000000 --- a/utilities/javascript/intToBin.js +++ /dev/null @@ -1,19 +0,0 @@ -// Does not handle negative numbers. -function intToBin(number) { - if (number === 0) { - return '0'; - } - let res = ''; - while (number > 0) { - res = String(number % 2) + res; - number = parseInt(number / 2, 10); - } - return res; -} - -console.log(intToBin(0) === 0..toString(2) && 0..toString(2) === '0'); -console.log(intToBin(1) === 1..toString(2) && 1..toString(2) === '1'); -console.log(intToBin(2) === 2..toString(2) && 2..toString(2) === '10'); -console.log(intToBin(3) === 3..toString(2) && 3..toString(2) === '11'); -console.log(intToBin(5) === 5..toString(2) && 5..toString(2) === '101'); -console.log(intToBin(99) === 99..toString(2) && 99..toString(2) === '1100011'); diff --git a/utilities/javascript/matrixTraverse.js b/utilities/javascript/matrixTraverse.js deleted file mode 100644 index 331a24e4..00000000 --- a/utilities/javascript/matrixTraverse.js +++ /dev/null @@ -1,28 +0,0 @@ -function traverse(matrix) { - const DIRECTIONS = [[0, 1], [0, -1], [1, 0], [-1, 0]]; - const rows = matrix.length, cols = matrix[0].length; - const visited = matrix.map(row => Array(row.length).fill(false)); - function dfs(i, j) { - if (visited[i][j]) { - return; - } - visited[i][j] = true; - DIRECTIONS.forEach(dir => { - const row = i + dir[0], col = j + dir[1]; - // Boundary check. - if (row < 0 || row >= rows || col < 0 || col >= cols) { - return; - } - // Valid neighbor check. - if (matrix[row][col] !== 1) { - return; - } - dfs(row, col); - }); - } - for (let i = 0; i < rows; i++) { - for (let j = 0; j < cols; j++) { - dfs(i, j); - } - } -} diff --git a/utilities/javascript/mergeSort.js b/utilities/javascript/mergeSort.js deleted file mode 100644 index d66537fd..00000000 --- a/utilities/javascript/mergeSort.js +++ /dev/null @@ -1,60 +0,0 @@ -function mergeSort(arr) { - if (arr.length < 2) { - // Arrays of length 0 or 1 are sorted by definition. - return arr; - } - - const left = arr.slice(0, Math.floor(arr.length / 2)); - const right = arr.slice(Math.floor(arr.length / 2), Math.floor(arr.length)); - - return merge(mergeSort(left), mergeSort(right)); -} - -function merge(arr1, arr2) { - const merged = []; - let i = 0, j = 0; - - while (i < arr1.length && j < arr2.length) { - if (arr1[i] <= arr2[j]) { - merged.push(arr1[i]); - i++; - } else if (arr2[j] < arr1[i]) { - merged.push(arr2[j]); - j++; - } - } - - merged.push(...arr1.slice(i), ...arr2.slice(j)); - return merged; -} - -const deepEqual = require('./deepEqual'); - -console.log(deepEqual( - mergeSort([]), - [], -)); -console.log(deepEqual( - mergeSort([1]), - [1], -)); -console.log(deepEqual( - mergeSort([2, 1]), - [1, 2], -)); -console.log(deepEqual( - mergeSort([7, 2, 4, 3, 1, 2]), - [1, 2, 2, 3, 4, 7], -)); -console.log(deepEqual( - mergeSort([1, 2, 3, 4, 5, 0]), - [0, 1, 2, 3, 4, 5], -)); -console.log(deepEqual( - mergeSort([10, 9, 8, 7, 6, 5, 4, 3, 2, 1]), - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], -)); -console.log(deepEqual( - mergeSort([98322, 3242, 876, -234, 34, 12331]), - [-234, 34, 876, 3242, 12331, 98322], -)); diff --git a/utilities/javascript/treeEqual.js b/utilities/javascript/treeEqual.js deleted file mode 100644 index 10774619..00000000 --- a/utilities/javascript/treeEqual.js +++ /dev/null @@ -1,11 +0,0 @@ -function treeEqual(node1, node2) { - if (!node1 && !node2) { - return true; - } - if (!node1 || !node2) { - return false; - } - return node1.val == node2.val && - treeEqual(node1.left, node2.left) && - treeEqual(node1.right, node2.right); -} diff --git a/utilities/javascript/treeMirror.js b/utilities/javascript/treeMirror.js deleted file mode 100644 index 63d37155..00000000 --- a/utilities/javascript/treeMirror.js +++ /dev/null @@ -1,10 +0,0 @@ -function treeMirror(node) { - if (!node) { - return; - } - let temp = node.left; - node.left = node.right; - node.right = temp; - treeMirror(node.left); - treeMirror(node.right); -}