├── drumkit
├── .DS_Store
├── sounds
│ ├── boom.wav
│ ├── clap.wav
│ ├── hihat.wav
│ ├── kick.wav
│ ├── ride.wav
│ ├── snare.wav
│ ├── tink.wav
│ ├── tom.wav
│ └── openhat.wav
└── style.css
├── exercises
├── strings
│ ├── stringRotation.js
│ ├── uniqueChar.js
│ ├── countFrequency.js
│ ├── replaceSpaces.js
│ ├── readN.js
│ ├── maxChar.js
│ ├── reverseInt.js
│ ├── vowels.js
│ ├── stringCompression.js
│ ├── palindrome.js
│ ├── rearrangeString.js
│ ├── longestSubStringWithAtMostK.js
│ ├── longestPalindrome.js
│ ├── reverseString.js
│ ├── isPalindrome.js
│ ├── longestIncreasingSubSequence.js
│ ├── lengthOfLongestSubstring.js
│ ├── reverseString2.js
│ ├── isIsomorphic.js
│ ├── smallestCharacter.js
│ ├── anagrams.js
│ ├── capitalize.js
│ ├── simplifyPath.js
│ ├── stringToInt.js
│ └── reverseEachWord.js
├── misc
│ ├── swapNum.js
│ ├── checkPrime.js
│ ├── binaryDivisible.js
│ ├── multiplesOf.js
│ ├── primeSummation.js
│ ├── intToRoman.js
│ ├── lcm.js
│ ├── pythagoreanTriplet.js
│ ├── sumEvenFibonacci.js
│ ├── buildEvent.js
│ ├── fizzBuzz.js
│ ├── sumSquareDiff.js
│ ├── largestPalindromeProduct.js
│ ├── threeSum.js
│ ├── findOptimalRoute.js
│ ├── fib.js
│ ├── pyramid.js
│ ├── matrix.js
│ ├── 10001stPrime.js
│ ├── romanToInt.js
│ ├── steps.js
│ └── findKClosestPoints.js
├── stacks&queues
│ ├── stack.js
│ ├── stackMin.js
│ ├── queue.js
│ ├── sortStack.js
│ ├── readme.md
│ ├── weave.js
│ ├── stackSet.js
│ └── queueFromStack.js
├── arrays
│ ├── duplicate.js
│ ├── buyAndSellStock.js
│ ├── keyPair.js
│ ├── findMissingElement.js
│ ├── findMaxSum.js
│ ├── removeDuplicate.js
│ ├── findLargestProduct.js
│ ├── findLargestDifference.js
│ ├── findMajorityElement.js
│ ├── printColorfulLetters.js
│ ├── twoSum.js
│ ├── trapRainWater.js
│ ├── productExceptSelf.js
│ ├── missingRanges.js
│ ├── maxArea.js
│ ├── unchunk.js
│ ├── increasingTriplet.js
│ ├── groupAnagrams.js
│ ├── peakIndex.js
│ ├── summaryRanges.js
│ ├── findIntersection.js
│ ├── validParenthesis.js
│ ├── searchRange.js
│ ├── rotateImage.js
│ ├── removeDuplicateContacts.js
│ ├── chunk.js
│ ├── removeDuplicates.js
│ ├── jumpGame.js
│ ├── setZeroes.js
│ ├── canJump.js
│ ├── spiralMatrix.js
│ ├── insertInterval.js
│ └── employeeFreeTime.js
├── sorting
│ ├── bubbleSort.js
│ ├── selectionSort.js
│ ├── mergeSort.js
│ ├── sortColors.js
│ ├── findMedianSorted.js
│ └── searchInRotatedSortedArray.js
├── linkedlist
│ ├── intersectionLinkedList.js
│ ├── reverseLinkedList.js
│ ├── removeDuplicateLinkedList.js
│ ├── fromLast.js
│ ├── midPointLinkedList.js
│ ├── deleteMiddleNode.js
│ ├── removeKthElement.js
│ ├── removeNthNodeFromEnd.js
│ ├── mergeKSortedList.js
│ ├── partitionLinkedList.js
│ ├── hasCycle.js
│ ├── oddEvenLinkedList.js
│ ├── circularLinkedList.js
│ ├── sumLinkedList.js
│ ├── sumLinkedList-II.js
│ └── checkPalindromeLinkedList.js
├── trees
│ ├── diameterOfBinaryTree.js
│ ├── countCompleteTreeNodes.js
│ ├── validateBst.js
│ ├── levelWidth.js
│ ├── zigzagTraversal.js
│ ├── cloneGraph.js
│ ├── inorderTraversal.js
│ ├── maxPathSumBinaryTree.js
│ ├── tree.js
│ ├── binarySearchTree.js
│ ├── populateNextRightPointer.js
│ ├── countSmaller.js
│ └── populateNextRightPointer-II.js
├── leetcode
│ ├── amazon
│ │ ├── distinctSets.js
│ │ ├── topKFrequent.js
│ │ ├── mergeSortedList.js
│ │ ├── prisonStateAfterNDays.js
│ │ ├── topNCompetitors.js
│ │ ├── partitionLabel.js
│ │ ├── mergeIntervals.js
│ │ ├── longestStringWithout3ConsecutiveChars.js
│ │ ├── twoSumUniquePairs.js
│ │ ├── pathSumMax.js
│ │ ├── twoPairSum.js
│ │ ├── kDistinct.js
│ │ ├── kDistinctStringsOfSizeK.js
│ │ ├── search2DMatrix.js
│ │ ├── minCostToConnect.js
│ │ ├── numberOfIslands.js
│ │ ├── subTreeOfAnother.js
│ │ ├── copyListWithRandomPointer.js
│ │ ├── lowestCommonAncestor.js
│ │ ├── subTreeAverage.js
│ │ ├── reorderLogs.js
│ │ ├── optimizeUtilization.js
│ │ ├── minHours.js
│ │ └── minCostToConnectNodes.js
│ └── letterCombinations.js
└── hashTable
│ └── hashTable.js
├── FE-JS-Questions
├── getElementsByClassName.md
├── ReduceString.md
├── eventEmitter.md
├── JSONPath.md
├── DeepFilter.md
├── InfiniteScroll.md
├── throtlle.md
├── formatPhoneNumber.md
└── Pagination.md
├── concepts
├── HashTable.js
├── EventDelegation.md
├── Graph.js
├── HTTP.md
├── Debounce.md
├── Callbacks.md
├── BinarySearchTree.js
├── List.md
├── Ajax.md
├── Tree.js
└── LinkedList.md
├── progressBar
└── progressBar.md
├── carousel
└── carousel.md
├── checkboxes
└── checkboxes.md
├── README.md
└── CSS-JS
└── index.html
/drumkit/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/HEAD/drumkit/.DS_Store
--------------------------------------------------------------------------------
/drumkit/sounds/boom.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/HEAD/drumkit/sounds/boom.wav
--------------------------------------------------------------------------------
/drumkit/sounds/clap.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/HEAD/drumkit/sounds/clap.wav
--------------------------------------------------------------------------------
/drumkit/sounds/hihat.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/HEAD/drumkit/sounds/hihat.wav
--------------------------------------------------------------------------------
/drumkit/sounds/kick.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/HEAD/drumkit/sounds/kick.wav
--------------------------------------------------------------------------------
/drumkit/sounds/ride.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/HEAD/drumkit/sounds/ride.wav
--------------------------------------------------------------------------------
/drumkit/sounds/snare.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/HEAD/drumkit/sounds/snare.wav
--------------------------------------------------------------------------------
/drumkit/sounds/tink.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/HEAD/drumkit/sounds/tink.wav
--------------------------------------------------------------------------------
/drumkit/sounds/tom.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/HEAD/drumkit/sounds/tom.wav
--------------------------------------------------------------------------------
/drumkit/sounds/openhat.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/HEAD/drumkit/sounds/openhat.wav
--------------------------------------------------------------------------------
/exercises/strings/stringRotation.js:
--------------------------------------------------------------------------------
1 | function stringRotation(string1, string2) {
2 | if (string1.length !== string2.length) {
3 | return false;
4 | }
5 |
6 | return (string2 + string2).includes(string1);
7 | }
8 |
--------------------------------------------------------------------------------
/exercises/misc/swapNum.js:
--------------------------------------------------------------------------------
1 | // Swap numbers without using temp variable
2 | // lets assume numA is 5 and numB is 3 or that numA > numB
3 | function swapNumber(numA, numB) {
4 | numA = numA + numB; // 5 + 3 = 8
5 | numB = numA - numB; // 8 - 3 = 5
6 | numA = numA - numB; // 8 - 5 = 3
7 | }
--------------------------------------------------------------------------------
/exercises/misc/checkPrime.js:
--------------------------------------------------------------------------------
1 | // Check if a number is prime
2 |
3 | function isPrime(n) {
4 | if (n === 1) {
5 | return false;
6 | }
7 |
8 | for (let x = 2; x * x <=n; x++) {
9 | if (n % x === 0) {
10 | return false;
11 | }
12 | }
13 |
14 | return true;
15 | }
--------------------------------------------------------------------------------
/exercises/stacks&queues/stack.js:
--------------------------------------------------------------------------------
1 | class Stack {
2 | constructor() {
3 | this.data = [];
4 | }
5 |
6 | push(record) {
7 | this.data.push(record);
8 | }
9 |
10 | pop() {
11 | return this.data.pop();
12 | }
13 |
14 | peek() {
15 | return this.data[this.data.length - 1];
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/exercises/arrays/duplicate.js:
--------------------------------------------------------------------------------
1 | // duplicate an array
2 |
3 | function duplicate(arr, n) {
4 | let duplicated = [];
5 | let index = 0;
6 | while (index < n) {
7 | duplicated = duplicated.concat(arr);
8 | index++;
9 | }
10 | return duplicated
11 | }
12 |
13 | duplicate([1,2,3,4], 6);
14 |
15 |
16 | //Output
17 | //[1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4,1,2,3,4]
18 |
--------------------------------------------------------------------------------
/exercises/misc/binaryDivisible.js:
--------------------------------------------------------------------------------
1 | //Given a binary number, write a program that prints 1 if given binary number is a multiple of 3.
2 | //Else prints 0. The given number can be big upto 2^100
3 |
4 | function binaryDivisble(binaryNumber) {
5 | const baseTenNumber = parseInt(binaryNumber, 2);
6 |
7 | if (baseTenNumber % 3 === 0) {
8 | return true;
9 | } else {
10 | return false;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/exercises/sorting/bubbleSort.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Implement bubbleSort
3 |
4 | function bubbleSort(arr) {
5 | for (let i = 0; i < arr.length; i++) {
6 | for (let j = 0; j < (arr.length - i - 1); j++) {
7 | if (arr[j] > arr[j+1]) {
8 | const lesser = arr[j+1];
9 | arr[j+1] = arr[j];
10 | arr[j] = lesser;
11 | }
12 | }
13 | }
14 |
15 | return arr;
16 | }
17 |
--------------------------------------------------------------------------------
/exercises/arrays/buyAndSellStock.js:
--------------------------------------------------------------------------------
1 | const calculateMaxProfit = prices => {
2 | let minPrice = Number.MIN_SAFE_INTEGER;
3 | let maxProfit = 0;
4 |
5 | for (let price of prices) {
6 | if (price < minPrice) {
7 | minPrice = price;
8 | } else if (price - minPrice > maxProfit) {
9 | maxProfit = price - minPrice;
10 | }
11 | }
12 |
13 | return maxProfit;
14 | }
--------------------------------------------------------------------------------
/exercises/arrays/keyPair.js:
--------------------------------------------------------------------------------
1 | //Given an array A[] of n numbers and another number x,
2 | //determine whether or not there exist two elements in A whose sum is exactly x.
3 |
4 | function keyPair(arr, sum) {
5 | for (let i = 0; i < arr.length; i++) {
6 | for (let j = i + 1; j < arr.length; j++) {
7 | if (arr[i] + arr[j] === sum) {
8 | return true;
9 | }
10 | }
11 | }
12 | return false;
13 | }
14 |
--------------------------------------------------------------------------------
/exercises/linkedlist/intersectionLinkedList.js:
--------------------------------------------------------------------------------
1 | const getIntersectionNode = (headA, headB) => {
2 | let ptrA = headA;
3 | let ptrB = headB;
4 |
5 | while (ptrA !== ptrB) {
6 | ptrA = ptrA !== null ? ptrA.next : headB;
7 | ptrB = ptrB !== null ? ptrB.next : headA;
8 | }
9 |
10 | return (ptrA === ptrB && ptrA !== null) ? ptrA : null;
11 | }
12 | /**
13 | * Time Complexity: O (m + n);
14 | * Space Complexity: O(1)
15 | */
--------------------------------------------------------------------------------
/exercises/misc/multiplesOf.js:
--------------------------------------------------------------------------------
1 | // If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
2 | //
3 | // Find the sum of all the multiples of 3 or 5 below 1000.
4 |
5 | function multipleSum(n) {
6 | let sum = 0;
7 |
8 | for (let i = 1; i < n; i++) {
9 | if (i % 3 === 0 || i % 5 === 0) {
10 | sum += i;
11 | }
12 | }
13 |
14 | return sum;
15 | }
16 |
--------------------------------------------------------------------------------
/exercises/arrays/findMissingElement.js:
--------------------------------------------------------------------------------
1 | // Given an array of size n-1 and given that there are numbers from 1 to n with one missing,
2 | // the missing number is to be found.
3 |
4 | function findMissingElement(n, arr) {
5 | const sum = n * (n + 1) / 2;
6 | const arraySum = arr.reduce((accumulator, element) => accumulator + element, 0);
7 |
8 | if (sum - arraySum) {
9 | return sum - arraySum;
10 | } else {
11 | return "No missing element";
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/exercises/arrays/findMaxSum.js:
--------------------------------------------------------------------------------
1 | // Given an array containing both negative and positive integers.
2 | // Find the contiguous sub-array with maximum sum.
3 |
4 | function findMaxSum(arr) {
5 | let globalMaxSum = arr[0];
6 | let currentMaxSum = arr[0];
7 |
8 | for (let i = 1; i < arr.length; i++) {
9 | currentMaxSum = Math.max(arr[i], currentMaxSum + arr[i]);
10 | globalMaxSum = Math.max(globalMaxSum, currentMaxSum);
11 | }
12 |
13 | return globalMaxSum;
14 | }
15 |
--------------------------------------------------------------------------------
/exercises/linkedlist/reverseLinkedList.js:
--------------------------------------------------------------------------------
1 | // Given a linked list, the task is to reverse the linked list.
2 |
3 | function reverseLinkedList(list) {
4 | let node = list.head;
5 | let previous = null;
6 | let next = null;
7 |
8 | if (!list.head || !list.head.next) {
9 | return list.head;
10 | }
11 |
12 | while (node) {
13 | next = node.next;
14 | node.next = previous;
15 | previous = node;
16 | node = next;
17 | }
18 |
19 | return previous;
20 | }
21 |
--------------------------------------------------------------------------------
/exercises/strings/uniqueChar.js:
--------------------------------------------------------------------------------
1 | //Given a string, of characters with multiple occurrences, find the character
2 | // which is unique and occurs only once
3 |
4 | function uniqueChar(str) {
5 | const charMap = {};
6 | let uniqueChar = '';
7 |
8 | for (let char of str) {
9 | charMap[char] = charMap[char] + 1 || 1;
10 | }
11 |
12 | for (let char in charMap) {
13 | if(charMap[char] === 1) {
14 | uniqueChar = char;
15 | }
16 | }
17 | return uniqueChar;
18 | }
19 |
--------------------------------------------------------------------------------
/exercises/misc/primeSummation.js:
--------------------------------------------------------------------------------
1 | /*
2 | The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
3 |
4 | Find the sum of all the primes below two million.
5 | */
6 |
7 | function summationPrimes() {
8 | const maxPrime = 10;
9 | let j = 2;
10 | let sum = 0;
11 |
12 | for (let i = 2; i < maxPrime; i++) {
13 | while (i % j !== 0) {
14 | j++;
15 |
16 | if (i === j) {
17 | sum += i;
18 | break;
19 | }
20 | }
21 | j = 2;
22 | }
23 |
24 | return sum;
25 | }
26 |
--------------------------------------------------------------------------------
/exercises/misc/intToRoman.js:
--------------------------------------------------------------------------------
1 | const intToRoman = function(num) {
2 | const romanArray = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
3 | const numberArray = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
4 | let str = '';
5 |
6 | for (let i = 0; i < numberArray.length; i++) {
7 | while (num >= numberArray[i]) {
8 | str = str.concat(romanArray[i]);
9 | num = num - numberArray[i];
10 | }
11 | }
12 |
13 | return str;
14 |
15 | }
--------------------------------------------------------------------------------
/exercises/sorting/selectionSort.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Implement selectionSort
3 |
4 | function selectionSort(arr) {
5 | for (let i = 0; i < arr.length; i++) {
6 | let indexOfMin = i;
7 |
8 | for (let j = i+1; j < arr.length; j++) {
9 | if (arr[j] < arr[indexOfMin]) {
10 | indexOfMin = j;
11 | }
12 | }
13 |
14 | if (indexOfMin !== i) {
15 | const lesser = arr[indexOfMin];
16 | arr[indexOfMin] = arr[i];
17 | arr[i] = lesser;
18 | }
19 | }
20 |
21 | return arr;
22 | }
23 |
--------------------------------------------------------------------------------
/exercises/strings/countFrequency.js:
--------------------------------------------------------------------------------
1 | // In a file there are 1 million words . Find n most frequent words in that file.
2 |
3 | function countFrequency(str, n) {
4 | let words = str.split(/\s+/);
5 |
6 | var countMap = words.reduce((wordMap, word) => {
7 | if (word) {
8 | wordMap[word] = wordMap[word] + 1 || 1;
9 | }
10 | return wordMap;
11 | }, {});
12 |
13 | let sortedMap = Object.keys(countMap).sort((a, b) => {
14 | return countMap[b] - countMap[a];
15 | });
16 |
17 | return sortedMap.slice(0, n).join('\n');
18 | }
19 |
--------------------------------------------------------------------------------
/exercises/strings/replaceSpaces.js:
--------------------------------------------------------------------------------
1 | // Write a method to replace all spaces in a string with'%20'. You may assume that
2 | // the string has sufficient space at the end of the string to hold the additional
3 | // characters, and that you are given the "true" length of the string.
4 |
5 | function replaceSpaces(str) {
6 | let newStr = '';
7 |
8 | for (let i = 0; i < str.length; i++) {
9 | if (str.charAt(i) === ' ') {
10 | newStr += '%20';
11 | } else {
12 | newStr += str[i];
13 | }
14 | }
15 |
16 | return newStr;
17 | }
18 |
--------------------------------------------------------------------------------
/exercises/strings/readN.js:
--------------------------------------------------------------------------------
1 | const readN = read4 => {
2 | let bufferIndex = 0;
3 | let res = [];
4 |
5 | return function(buf, n) {
6 | let charsToRead = Math.ceil((bufferIndex + n) / 4);
7 |
8 | for (let i = 0; i < charsToRead; i++) {
9 | let tmp = [];
10 | read4(tmp);
11 | res = [...res, ...tmp];
12 | }
13 |
14 | for (let k = 0; k < n; k++) {
15 | buf[k] = res[bufferIndex + k];
16 | }
17 |
18 | bufferIndex += n;
19 |
20 | return bufferIndex;
21 | }
22 | }
--------------------------------------------------------------------------------
/exercises/misc/lcm.js:
--------------------------------------------------------------------------------
1 | // 2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.
2 | //
3 | // What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?
4 |
5 | function findLCM(n) {
6 | let answer = 1;
7 | for (let i = 1; i <= n; i++) {
8 | answer = (answer * i) / findGCD(answer, i);
9 | }
10 |
11 | return answer;
12 | }
13 |
14 | function findGCD(element, result) {
15 | if (element === 0) {
16 | return result;
17 | }
18 | return findGCD(result % element, element);
19 | }
20 |
--------------------------------------------------------------------------------
/FE-JS-Questions/getElementsByClassName.md:
--------------------------------------------------------------------------------
1 | ## Implement getElementsByClassName
2 |
3 | ```js
4 | function getElementsByClassName(className) {
5 | const classList = [];
6 |
7 | function getNodes(node) {
8 | if (node.classList && node.classList.contains(className)) {
9 | classList.push(node);
10 | }
11 |
12 | for (let i = 0; i < node.childNodes.length; i++) {
13 | getNodes(node.childNodes[i]);
14 | }
15 | }
16 |
17 | getNodes(document.body); // Access the DOM's document.body
18 | return classList;
19 | }
20 | ```
21 |
--------------------------------------------------------------------------------
/exercises/trees/diameterOfBinaryTree.js:
--------------------------------------------------------------------------------
1 | class TreeNode {
2 | constructor(val) {
3 | this.val = val;
4 | this.left = null;
5 | this.right = null;
6 | }
7 | }
8 | let ans;
9 |
10 | const maxDepth = node => {
11 | if (!node) {
12 | return 0;
13 | }
14 |
15 | let left = depth(node.left);
16 | let right = depth(node.right);
17 |
18 | ans = Math.max(ans, left + right + 1);
19 |
20 | return Math.max(left, right) + 1;
21 | }
22 | const diameterOfBinaryTree = root => {
23 | ans = 1;
24 | maxDepth(root);
25 | return ans - 1;
26 | }
--------------------------------------------------------------------------------
/exercises/arrays/removeDuplicate.js:
--------------------------------------------------------------------------------
1 | // Removing duplicates of an array
2 | // and returning an array of only unique elements
3 |
4 | function removeDuplicates(arr) {
5 | const elementMap = {};
6 | const uniqueArr = [];
7 |
8 | for (let element of arr) {
9 | // Check if element exists in the object already
10 | if (!elementMap[element]) {
11 | // Set element count to 1
12 | elementMap[element] = 1;
13 | // Push to unique array
14 | uniqueArr.push(element);
15 | }
16 | }
17 |
18 | return uniqueArr;
19 | }
20 |
--------------------------------------------------------------------------------
/exercises/linkedlist/removeDuplicateLinkedList.js:
--------------------------------------------------------------------------------
1 | // Write code to remove duplicates from an unsorted linked list.
2 |
3 | class Node {
4 | constructor(data, next = null) {
5 | this.data = data;
6 | this.next = next;
7 | }
8 | }
9 |
10 | class LinkedList {
11 | constructor() {
12 | this.head = null;
13 | }
14 | }
15 |
16 | function removeDuplicates(head) {
17 | let node = head;
18 | while (node && node.next) {
19 | if (node.next.data === node.data) {
20 | node.next = node.next.next;
21 | } else {
22 | node = node.next;
23 | }
24 | }
25 |
26 | return head;
27 | }
28 |
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/distinctSets.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a set with distinct elements, find all of its distinc subsets.
3 | *
4 | * Example: Input: [1,5,3]
5 | * Output: [1], [5], [3], [1,5], [1,3], [5,3], [1,5,3]
6 | */
7 |
8 | const generateSubsets = set => {
9 | const subsets = [[]];
10 |
11 | for (let element of set) {
12 | const n = subsets.length;
13 |
14 | for (let i = 0; i < n; i++) {
15 | const arr = [...subsets[i]];
16 |
17 | arr.push(element);
18 | subsets.push(arr);
19 | }
20 | }
21 |
22 | return subsets;
23 | }
--------------------------------------------------------------------------------
/exercises/strings/maxChar.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Given a string, return the character that is most
3 | // commonly used in the string.
4 | // --- Examples
5 | // maxChar("abcccccccd") === "c"
6 | // maxChar("apple 1231111") === "1"
7 |
8 | function maxChar(str) {
9 | const charMap = {};
10 | let max = 0;
11 | let maxChar = '';
12 |
13 | for (let char of str) {
14 | charMap[char] = charMap[char] + 1 || 1;
15 | }
16 |
17 | for (let char in charMap) {
18 | if(charMap[char] > max) {
19 | max = charMap[char];
20 | maxChar = char;
21 | }
22 | }
23 | return maxChar;
24 | }
25 |
--------------------------------------------------------------------------------
/exercises/stacks&queues/stackMin.js:
--------------------------------------------------------------------------------
1 | class Stack {
2 | constructor() {
3 | this.data = [];
4 | this.minStack = [];
5 | }
6 |
7 | push(record) {
8 | if (record <= this.min()) {
9 | this.minStack.push(record);
10 | }
11 | this.data.push(record);
12 | }
13 |
14 | pop() {
15 | let result = this.data.pop();
16 | if (result === this.currentMin) {
17 | this.minStack.pop();
18 | }
19 | return result;
20 | }
21 |
22 | peek() {
23 | return this.data[this.data.length - 1];
24 | }
25 |
26 | min() {
27 | return this.minStack[this.minStack.length - 1];
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/exercises/strings/reverseInt.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Given an integer, return an integer that is the reverse
3 | // ordering of numbers.
4 | // --- Examples
5 | // reverseInt(15) === 51
6 | // reverseInt(981) === 189
7 | // reverseInt(500) === 5
8 | // reverseInt(-15) === -51
9 | // reverseInt(-90) === -9
10 |
11 |
12 | function reverseInt(n) {
13 | const reversed = n.toString().split('').reverse().join('');
14 |
15 | return parseInt(reversed) * Math.sign(n);
16 | }
17 |
18 | // One Liner solution
19 | function reverseInt(n) {
20 | return (
21 | parseInt(
22 | n.toString().split('').reverse().join('')
23 | ) * Math.sign(n)
24 | );
25 | }
26 |
--------------------------------------------------------------------------------
/exercises/misc/pythagoreanTriplet.js:
--------------------------------------------------------------------------------
1 | /*
2 | A Pythagorean triplet is a set of three natural numbers, a < b < c, for which,
3 |
4 | a2 + b2 = c2
5 | For example, 32 + 42 = 9 + 16 = 25 = 52.
6 |
7 | There exists exactly one Pythagorean triplet for which a + b + c = 1000.
8 | Find the product abc.
9 | */
10 |
11 | function pythagoreanTriplet() {
12 | const sum = 1000;
13 | let product = 0;
14 |
15 | for (let a = 1; a <= sum / 3; a++) {
16 | for (let b = a + 1; b <= sum / 2; b++) {
17 | let c = sum - a - b;
18 | if (c * c === a * a + b * b) {
19 | product = a * b * c;
20 | break;
21 | }
22 | }
23 | }
24 |
25 | return product;
26 | }
27 |
--------------------------------------------------------------------------------
/exercises/trees/countCompleteTreeNodes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a complete binary tree, count the number of nodes.
3 |
4 | Note:
5 |
6 | Definition of a complete binary tree from Wikipedia:
7 | In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.
8 |
9 | Example:
10 |
11 | Input:
12 | 1
13 | / \
14 | 2 3
15 | / \ /
16 | 4 5 6
17 |
18 | Output: 6
19 | */
20 |
21 | const countCompleteTreeNodes = (root) => {
22 | return root !== null ? 1 + countCompleteTreeNodes(root.right) + countCompleteTreeNodes(root.left) : 0;
23 | }
--------------------------------------------------------------------------------
/exercises/arrays/findLargestProduct.js:
--------------------------------------------------------------------------------
1 | //Given an array of integers,
2 | // find the largest product yielded from three of the integers
3 |
4 | function findLargestProduct(arr) {
5 | const sortedArr = arr.sort(sortArray);
6 | let product1 = 1;
7 | let product2 = 1;
8 | let lastElementIndex = sortedArr.length - 1;
9 |
10 | for (let i = lastElementIndex; i > lastElementIndex - 3; i--) {
11 | product1 *= sortedArr[i];
12 | }
13 |
14 | product2 = sortedArr[0] * sortedArr[1] * sortedArr[lastElementIndex];
15 |
16 | if (product1 > product2) {
17 | return product1;
18 | }
19 |
20 | return product2;
21 | }
22 |
23 | function sortArray(a, b) {
24 | return a - b;
25 | }
26 |
--------------------------------------------------------------------------------
/exercises/misc/sumEvenFibonacci.js:
--------------------------------------------------------------------------------
1 | // Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:
2 | //
3 | // 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
4 | //
5 | // By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
6 | function fib() {
7 | let prev = 0;
8 | let curr = 1;
9 |
10 | let sum = 0;
11 | while (true) {
12 | if (sum > 4000000) {
13 | break;
14 | }
15 | let temp = prev + curr;
16 | if (temp % 2 === 0) {
17 | sum += temp;
18 | }
19 | prev = curr;
20 | curr = temp;
21 | }
22 | return sum;
23 | }
24 |
--------------------------------------------------------------------------------
/exercises/trees/validateBst.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Given a node, validate the binary search tree,
3 | // ensuring that every node's left hand child is
4 | // less than the parent node's value, and that
5 | // every node's right hand child is greater than
6 | // the parent
7 |
8 | function validate(node, min = null, max = null) {
9 | if (max !== null && node.data > max) {
10 | return false;
11 | }
12 |
13 | if (min !== null && node.data < min) {
14 | return false;
15 | }
16 |
17 | if (node.left && !validate(node, min, node.data)) {
18 | return false;
19 | }
20 |
21 | if (node.right && !validate(node, node.data, max)) {
22 | return false;
23 | }
24 |
25 | return true;
26 | }
27 |
--------------------------------------------------------------------------------
/exercises/trees/levelWidth.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Given the root node of a tree, return
3 | // an array where each element is the width
4 | // of the tree at each level.
5 | // --- Example
6 | // Given:
7 | // 0
8 | // / | \
9 | // 1 2 3
10 | // | |
11 | // 4 5
12 | // Answer: [1, 3, 2]
13 |
14 | function levelWidth(root) {
15 | const arr = [root, 's'];
16 | const counters = [0];
17 |
18 | while (arr.length > 1) {
19 | const node = arr.shift();
20 |
21 | if (node === 's') {
22 | counters.push(0);
23 | arr.push('s');
24 | } else {
25 | arr.push(...node.children);
26 | counters[counters.length - 1]++;
27 | }
28 | }
29 |
30 | return counters;
31 | }
32 |
--------------------------------------------------------------------------------
/exercises/arrays/findLargestDifference.js:
--------------------------------------------------------------------------------
1 | // Given an array of integers,
2 | // find the largest difference between two elements
3 | // such that the element of lesser value must come before the greater element
4 |
5 | function findLargestDifference(arr) {
6 | if (arr.length <= 1) {
7 | return -1;
8 | }
9 |
10 | let currentMin = arr[0];
11 | let currentMaxDifference = 0;
12 | for (let i = 1; i < arr.length; i++) {
13 | if (arr[i] > currentMin && (arr[i] - currentMin > currentMaxDifference)) {
14 | currentMaxDifference = arr[i] - currentMin;
15 | } else if (arr[i] <= currentMin) {
16 | currentMin = arr[i];
17 | }
18 | }
19 |
20 | return currentMaxDifference <= 0 ? -1 : currentMaxDifference;
21 | }
22 |
--------------------------------------------------------------------------------
/exercises/arrays/findMajorityElement.js:
--------------------------------------------------------------------------------
1 | // Write a program to find the majority element in the array.
2 | // A majority element in an array A[] of size n is an element that appears more than n/2 times
3 | // (and hence there is at most one such element).
4 | // If input array doesn't contain a majority element, then output "NO Majority Element"
5 |
6 | function findMajorityElement(n, arr) {
7 | const majorityCount = n / 2;
8 | const arrayMap = {};
9 |
10 | for (let element of arr) {
11 | arrayMap[element] = arrayMap[element] + 1 || 1;
12 | }
13 |
14 | for (let element in arrayMap) {
15 | if (arrayMap[element] > majorityCount) {
16 | return element;
17 | }
18 | }
19 |
20 | return "No majority element";
21 | }
22 |
--------------------------------------------------------------------------------
/exercises/strings/vowels.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Write a function that returns the number of vowels
3 | // used in a string. Vowels are the characters 'a', 'e'
4 | // 'i', 'o', and 'u'.
5 | // --- Examples
6 | // vowels('Hi There!') --> 3
7 | // vowels('Why do you ask?') --> 4
8 | // vowels('Why?') --> 0
9 |
10 |
11 | function vowels(str) {
12 | let count = 0;
13 | const vowelArray = ['a', 'e', 'i', 'o', 'u'];
14 |
15 | for (let char of str) {
16 | if (vowelArray.matches(char)) {
17 | count++;
18 | }
19 | }
20 |
21 | return count;
22 | }
23 |
24 | // Solution using regexp
25 |
26 | function vowels(str) {
27 | const matches = str.matches(/[aeiou]/gi);
28 | return matches ? matches.length : 0;
29 | }
30 |
--------------------------------------------------------------------------------
/exercises/stacks&queues/queue.js:
--------------------------------------------------------------------------------
1 | // --- Description
2 | // Create a queue data structure. The queue
3 | // should be a class with methods 'add' and 'remove'.
4 | // Adding to the queue should store an element until
5 | // it is removed
6 | // --- Examples
7 | // const q = new Queue();
8 | // q.add(1);
9 | // q.remove(); // returns 1;
10 |
11 | class Queue {
12 | constructor() {
13 | this.data = [];
14 | }
15 |
16 | // Add a record to the Queue
17 | add(record) {
18 | this.data.push(record);
19 | }
20 |
21 | // Remove a record from the Queue
22 | remove() {
23 | return this.data.shift();
24 | }
25 |
26 | // Return the last element in the queue without popping
27 | peek() {
28 | return this.data[0];
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/exercises/strings/stringCompression.js:
--------------------------------------------------------------------------------
1 | // Implement a method to perform basic string compression using the counts
2 | // of repeated characters. For example, the string aabcccccaaa would become
3 | // a2blc5a3. If the "compressed" string would not become smaller than the original
4 | // string, your method should return the original string.
5 |
6 | function compressString(str) {
7 | let compressedStr = str[0];
8 | let previousChar = str[0];
9 | let count = 1;
10 |
11 | for (let i = 1; i < str.length; i++) {
12 | if (previousChar === str.charAt(i)) {
13 | count++;
14 | } else {
15 | compressedStr += count + str[i];
16 | previousChar = str[i];
17 | count = 1;
18 | }
19 | }
20 |
21 | return compressedStr + count;
22 | }
23 |
--------------------------------------------------------------------------------
/exercises/misc/buildEvent.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Create an 'eventing' library out of the
3 | // Events class. The Events class should
4 | // have methods 'on', 'trigger', and 'off'.
5 |
6 | class Events {
7 | constructor() {
8 | this.events = {};
9 | }
10 |
11 | // Register an event handler
12 | on(eventName, callback) {
13 | if (this.events[eventName]) {
14 | this.events[eventName].push(callback);
15 | } else {
16 | this.events[eventName] = [callback];
17 | }
18 | }
19 |
20 | trigger(eventName) {
21 | if (this.events[eventName]) {
22 | for (let cb of this.events[eventName]) {
23 | cb();
24 | }
25 | }
26 | }
27 |
28 | off(eventName) {
29 | delete this.events[eventName];
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/exercises/arrays/printColorfulLetters.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given
3 | colors = ["red", "blue", "green", "yellow"];
4 | and a string
5 | str = "Lorem ipsum dolor sit amet";
6 | write a function that prints each letter of the string in different colors.
7 | ex. L is red, o is blue, r is green, e is yellow, m is red,
8 | after the space, i should be blue.
9 | */
10 |
11 | function printLetterinColors(str, colors) {
12 | let colorIndex = 0;
13 |
14 | for (let char of str.split('')) {
15 | if (char !== ' ') {
16 | console.log('%c ' + char, 'color:' + colors[colorIndex]);
17 | } else {
18 | console.log(char);
19 | }
20 | colorIndex++;
21 | if (colorIndex === colors.length) {
22 | colorIndex = 0;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/exercises/linkedlist/fromLast.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Given a linked list, return the element n spaces
3 | // from the last node in the list. Do not call the 'size'
4 | // method of the linked list. Assume that n will always
5 | // be less than the length of the list.
6 | // --- Examples
7 | // const list = new List();
8 | // list.insertLast('a');
9 | // list.insertLast('b');
10 | // list.insertLast('c');
11 | // list.insertLast('d');
12 | // fromLast(list, 2).data // 'b'
13 |
14 | function fromLast (list, n) {
15 | let slow = list.head;
16 | let fast = list.head;
17 |
18 | while (n > 0) {
19 | fast = fast.next;
20 | n--;
21 | }
22 |
23 | while (fast.next) {
24 | slow = slow.next;
25 | fast = fast.next;
26 | }
27 |
28 | return slow;
29 | }
30 |
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/topKFrequent.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a non-empty array of integers, return the k most frequent elements.
3 |
4 | Example 1:
5 |
6 | Input: nums = [1,1,1,2,2,3], k = 2
7 | Output: [1,2]
8 | Example 2:
9 |
10 | Input: nums = [1], k = 1
11 | Output: [1]
12 | Note:
13 |
14 | You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
15 | Your algorithm's time complexity must be better than O(n log n), where n is the array's size.
16 | */
17 |
18 | const topKFrequent = (nums, k) => {
19 | const elementMap = {};
20 |
21 | for (let num of nums) {
22 | elementMap[num] = elementMap[num] + 1 || 1;
23 | }
24 |
25 | const sortedKeys = Object.keys(elementMap).sort((a, b) => elementMap[b] - elementMap[a]);
26 |
27 | return sortedKeys.slice(0, k);
28 | }
--------------------------------------------------------------------------------
/exercises/linkedlist/midPointLinkedList.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Return the 'middle' node of a linked list.
3 | // If the list has an even number of elements, return
4 | // the node at the end of the first half of the list.
5 | // *Do not* use a counter variable, *do not* retrieve
6 | // the size of the list, and only iterate
7 | // through the list one time.
8 | // --- Example
9 | // const l = new LinkedList();
10 | // l.insertLast('a')
11 | // l.insertLast('b')
12 | // l.insertLast('c')
13 | // midpoint(l); // returns { data: 'b' }
14 |
15 | function midPoint(list) {
16 | let slow = list.getFirst();
17 | let fast = list.getFirst();
18 |
19 | while(fast.next && fast.next.next) {
20 | slow = slow.next;
21 | fast = fast.next.next;
22 | }
23 |
24 | return slow;
25 | }
26 |
--------------------------------------------------------------------------------
/exercises/hashTable/hashTable.js:
--------------------------------------------------------------------------------
1 | class HashTable {
2 | constructor() {
3 | this.memory = [];
4 | }
5 |
6 | hashKey(key) {
7 | for (let index = 0; index < key; index++) {
8 | let code = key.charCodeAt(index);
9 | hash = ((hash << 5) - hash) + code | 0;
10 | }
11 |
12 | return hash;
13 | }
14 |
15 | get(key) {
16 | let address = this.hashKey(key);
17 | return this.memory[address];
18 | }
19 |
20 | set(key, value) {
21 | let address = this.hashKey(key);
22 | this.memory[address] = value;
23 | }
24 |
25 | remove(key) {
26 | let address = this.hashKey(key);
27 |
28 | if (this.memory[address]) {
29 | delete this.memory[address];
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/concepts/HashTable.js:
--------------------------------------------------------------------------------
1 | class HashTable {
2 | constructor() {
3 | this.memory = [];
4 | }
5 |
6 | hashKey(key) {
7 | let hash = 0;
8 | for (let index = 0; index < key.length; index++) {
9 | let code = key.charCodeAt(index);
10 | hash = ((hash << 5) - hash) + code | 0;
11 | }
12 |
13 | return hash;
14 | }
15 |
16 | get(key) {
17 | let address = this.hashKey(key);
18 | return this.memory[address];
19 | }
20 |
21 | set(key, value) {
22 | let address = this.hashKey(key);
23 | this.memory[address] = value;
24 | }
25 |
26 | remove(key) {
27 | let address = this.hashKey(key);
28 |
29 | if (this.memory[address]) {
30 | delete this.memory[address];
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/exercises/misc/fizzBuzz.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Write a program that console logs the numbers
3 | // from 1 to n. But for multiples of three print
4 | // “fizz” instead of the number and for the multiples
5 | // of five print “buzz”. For numbers which are multiples
6 | // of both three and five print “fizzbuzz”.
7 | // --- Example
8 | // fizzBuzz(5);
9 | // 1
10 | // 2
11 | // fizz
12 | // 4
13 | // buzz
14 |
15 |
16 | function fizzBuzz(n) {
17 | for (let i = 1; i <= n; i++) {
18 | // Check if the number is multiple of 3 and 5 first
19 | if (i % 3 === 0 && i % 5 === 0) {
20 | console.log("fizzbuzz");
21 | } else if (i % 3 === 0) {
22 | console.log("fizz");
23 | } else if (i % 5 === 0) {
24 | console.log('buzz');
25 | } else {
26 | console.log(i);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/exercises/strings/palindrome.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Given a string, return true if the string is a palindrome
3 | // or false if it is not. Palindromes are strings that
4 | // form the same word if it is reversed. *Do* include spaces
5 | // and punctuation in determining if the string is a palindrome.
6 | // --- Examples:
7 | // palindrome("abba") === true
8 | // palindrome("abcdefg") === false
9 |
10 |
11 | // Using array reverse function
12 | function palindrome(str) {
13 | const reversed = str.split('').reverse().join('');
14 |
15 | return str === reversed;
16 | }
17 |
18 |
19 | // Using array every() function
20 | // not fully efficient as we do multiple comparisons
21 | function palindrome(str) {
22 | str.split('').every((char, index) => {
23 | return char === str[str.length - index - 1];
24 | });
25 | }
26 |
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/mergeSortedList.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Merge two sorted linked lists and return it as a new list.
3 | * The new list should be made by splicing together the nodes of the first two lists.
4 |
5 | Example:
6 |
7 | Input: 1->2->4, 1->3->4
8 | Output: 1->1->2->3->4->4
9 | */
10 | function ListNode(val) {
11 | this.val = val;
12 | this.next = null;
13 | }
14 |
15 | const mergeTwoLists = (l1, l2) => {
16 | let head = new ListNode();
17 | let current = head;
18 |
19 | while (l1 && l2) {
20 | if (l1.val <= l2.val) {
21 | current.next = l1;
22 | l1 = l1.next;
23 | } else {
24 | current.next = l2;
25 | l2 = l2.next;
26 | }
27 | current = current.next;
28 | }
29 |
30 | current.next = l1 || l2;
31 |
32 | return head.next
33 | }
--------------------------------------------------------------------------------
/exercises/linkedlist/deleteMiddleNode.js:
--------------------------------------------------------------------------------
1 | // Implement an algorithm to delete a node in the middle of a singly linked list,
2 | // given only access to that node.
3 | // EXAMPLE
4 | // Input: the node c from the linked list a->b->c->d->e
5 | // Result: nothing is returned, but the new linked list looks like a- >b- >d->e
6 |
7 |
8 | // Writing Structure for LinkedList and Node for learning purpose
9 | class Node {
10 | constructor(data, next = null) {
11 | this.data = data;
12 | this.next = next;
13 | }
14 | }
15 |
16 | class LinkedList {
17 | constructor() {
18 | this.head = null;
19 | }
20 | }
21 |
22 | function deleteMiddleNode(node) {
23 | while (node && node.next) {
24 | node.value = node.next.value
25 |
26 | if (!node.next.next) {
27 | node.next = null;
28 | }
29 | node = node.next;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/exercises/misc/sumSquareDiff.js:
--------------------------------------------------------------------------------
1 | /*
2 | The sum of the squares of the first ten natural numbers is,
3 | 1^2 + 2^2 + ... + 10^2 = 385
4 |
5 | The square of the sum of the first ten natural numbers is,
6 | (1 + 2 + ... + 10)^2 = 552 = 3025
7 |
8 | Hence the difference between the sum of the squares of the first ten natural numbers
9 | and the square of the sum is 3025 − 385 = 2640.
10 |
11 | Find the difference between the sum of the squares of the first one hundred natural numbers
12 | and the square of the sum.
13 | */
14 |
15 | function findSumSquareDiff(n) {
16 | let sumSquares = 0;
17 | let squareSum = 0;
18 |
19 | for (i = 1; i <= n; i++) {
20 | sumSquares += i * i;
21 | }
22 |
23 | //find sum of first n natural numbers
24 | let sum = (n * (n + 1)) / 2;
25 | squareSum = sum * sum;
26 |
27 | return squareSum - sumSquares;
28 | }
29 |
--------------------------------------------------------------------------------
/exercises/arrays/twoSum.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an array of integers, return indices of the two numbers such that they add up to a specific target.
3 |
4 | You may assume that each input would have exactly one solution, and you may not use the same element twice.
5 |
6 | Example:
7 |
8 | Given nums = [2, 7, 11, 15], target = 9,
9 |
10 | Because nums[0] + nums[1] = 2 + 7 = 9,
11 | return [0, 1].
12 | */
13 |
14 | const twoSum = (nums, target) => {
15 | const numberMap = new Map();
16 |
17 | for (let i = 0; i < nums.length; i++) {
18 | let compliment = target - nums[i];
19 | if (numberMap.has(compliment)) {
20 | return [numberMap.get(compliment), i];
21 | }
22 | numberMap.set(nums[i], i);
23 | }
24 |
25 | return null;
26 | }
27 |
28 | /**
29 | * Time Complexity: O(n)
30 | * Space Complexity: O(n)
31 | */
--------------------------------------------------------------------------------
/exercises/arrays/trapRainWater.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given n non-negative integers representing an elevation map where the width of each bar is 1,
3 | * compute how much water it is able to trap after raining.
4 | */
5 |
6 | const maxTrap = height => {
7 | let leftMax = [];
8 | let rightMax = [];
9 | let ans = 0;
10 |
11 | if (!height || height.length === 0) {
12 | return 0;
13 | }
14 |
15 | leftMax[0] = height[0];
16 | for (let i = 1; i < height.length - 1; i++) {
17 | leftMax[i] = Math.max(height[i], leftMax[i - 1]);
18 | }
19 |
20 | rightMax[height.length - 1] = height[height.length - 1];
21 | for (let i = height.length - 2; i >=0; i--) {
22 | rightMax[i] = Math.max(height[i], rightMax[i + 1]);
23 | }
24 |
25 | for (let i = 0; i < height.length - 1; i++) {
26 | ans += Math.min(rightMax[i], leftMax[i]) - height[i];
27 | }
28 |
29 | return ans;
30 | }
--------------------------------------------------------------------------------
/exercises/sorting/mergeSort.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Implement merge sort
3 |
4 |
5 | function mergeSort(arr) {
6 | if (arr.length === 1) {
7 | return arr;
8 | }
9 |
10 | const center = Math.floor(arr.length / 2);
11 | const left = arr.slice(0, center);
12 | const right = arr.slice(center);
13 |
14 | return merge(mergeSort(left), mergeSort(right));
15 | }
16 |
17 | // Merge function takes 2 sorted arrays and returns the merged sorted array
18 | function merge(left, right) {
19 | const results = [];
20 |
21 | while (left.length && right.length) {
22 | if (left[0] < right[0]) {
23 | results.push(left.shift());
24 | } else {
25 | results.push(right.shift());
26 | }
27 | }
28 |
29 | // Using the spread operator to push any remaining elements in left or right array
30 | return [...results, ...left, ...right];
31 | }
32 |
--------------------------------------------------------------------------------
/exercises/arrays/productExceptSelf.js:
--------------------------------------------------------------------------------
1 | // Given an array of integers,
2 | // return an output array such that
3 | // output[i] is equal to the product of all the elements in the array other than itself.
4 | // (Solve this in O(n) without division)
5 |
6 |
7 | function productExceptSelf(arr) {
8 | let product = 1;
9 | let outputArr = [];
10 |
11 | // Find the product of the elements to the left of each element
12 | // and store in array
13 | for (let i = 0; i <= arr.length - 1; i++) {
14 | outputArr.push(product);
15 | product = product * arr[i];
16 | }
17 |
18 | // Find the product of elements to the right of each element
19 | // and update the output array
20 | product = 1;
21 | for (let i = arr.length - 1; i >= 0; i--) {
22 | outputArr[i] = outputArr[i] * product;
23 | product = product * arr[i]
24 | }
25 |
26 | return outputArr;
27 | }
28 |
--------------------------------------------------------------------------------
/exercises/strings/rearrangeString.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a string with lowercase, uppercase and numbers, rearrange it so that uppercase letters are first,
3 | * then lowercase and then numbers. It should maintain the original order.
4 |
5 | Input- "cdBnC52c" output - "BCcdnc52"
6 | Input - "123abA" output - "Aab123"
7 |
8 | Rearrange it in o(n) in one pass without using extra space.
9 | */
10 |
11 | const rearrangeString = str => {
12 | let lower = '';
13 | let upper = '';
14 | let num = '';
15 |
16 | let index = 0;
17 |
18 | while (index < str.length) {
19 | if (!isNaN(str[index] * 1)) {
20 | num = num + str[index];
21 | } else if (str[index] == str[index].toUpperCase()) {
22 | upper += str[index];
23 | } else if (str[index] == str[index].toLowerCase()) {
24 | lower += str[index];
25 | }
26 |
27 | index++;
28 | }
29 |
30 | return upper + lower + num;
31 | }
--------------------------------------------------------------------------------
/exercises/arrays/missingRanges.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a sorted integer array nums, where the range of elements are in the inclusive range
3 | * [lower, upper], return its missing ranges.
4 |
5 | Example:
6 |
7 | Input: nums = [0, 1, 3, 50, 75], lower = 0 and upper = 99,
8 | Output: ["2", "4->49", "51->74", "76->99"]
9 | */
10 |
11 | /**
12 | * @param {number[]} nums
13 | * @param {number} lower
14 | * @param {number} upper
15 | * @return {string[]}
16 | */
17 | const missingRanges = (nums, lower, upper) => {
18 | nums = [lower - 1, ...nums, upper + 1];
19 |
20 | const results = [];
21 |
22 | for (let i = 1; i < nums.length; i++) {
23 | if (nums[i] !== nums[i - 1] && nums[i] - 1 !== nums[i -1]) {
24 | let num1 = nums[i - 1] + 1;
25 | let num2 = nums[i] - 1;
26 | results.push(
27 | num1 + (num2 === num1 ? "" : "->" + num2)
28 | );
29 | }
30 | }
31 |
32 | return results;
33 | }
--------------------------------------------------------------------------------
/exercises/linkedlist/removeKthElement.js:
--------------------------------------------------------------------------------
1 | // Given a singly linked list, Your task is to remove every Kth node.
2 | // The task is to complete a method deleteK that takes two argument,
3 | // head of linked list and an integer k.
4 | // The method returns the head of the new linked list
5 |
6 |
7 | function removeKthElement(list, k) {
8 | let node = list.head;
9 | let previous = list.head;
10 | let counter = 0;
11 |
12 | if (!list.head) {
13 | return;
14 | }
15 |
16 | // Loop over the list and increment the counter
17 | while (node) {
18 | counter++;
19 |
20 | // if counter equals k, then remove the element and reset the counter
21 | if (k === counter) {
22 | previous.next = node.next;
23 | counter = 0;
24 | }
25 |
26 | if (counter !== 0) {
27 | previous = node;
28 | }
29 | node = node.next;
30 | }
31 |
32 | return list.head
33 | }
34 |
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/prisonStateAfterNDays.js:
--------------------------------------------------------------------------------
1 | var prisonAfterNDays = function(cells, N) {
2 | let output = [...cells];
3 |
4 | while (N > 0) {
5 | for (let i = 0; i < cells.length; i++) {
6 | output[i] = (cells[i-1] === cells[i+1]) ? 1 : 0;
7 | }
8 |
9 | cells = [...output];
10 | N = (N - 1) % 14;
11 | }
12 |
13 | return cells;
14 | };
15 |
16 | /*************** OR *****************/
17 |
18 | const prisonAfterNDays = (cells, N) => {
19 | let output = [...cells];
20 |
21 | while (N > 0) {
22 | output[0] = 0;
23 |
24 | for (let i = 1; i <= cells.length - 2; i++) {
25 | output[i] = (cells[i - 1] === cells[i + 1]) ? 1 : 0;
26 | }
27 |
28 | output[cells.length - 1] = 0;
29 |
30 | cells = [...output];
31 | N = (N - 1) % 14;
32 | }
33 |
34 | return cells;
35 | }
--------------------------------------------------------------------------------
/exercises/stacks&queues/sortStack.js:
--------------------------------------------------------------------------------
1 | // Write a program to sort a stack in ascending order (with biggest items on top).
2 | // You may use at most one additional stack to hold items, but you may not copy
3 | // the elements into any other data structure (such as an array)
4 |
5 | class Stack {
6 | constructor() {
7 | this.data = [];
8 | }
9 |
10 | push(record) {
11 | this.data.push(record);
12 | }
13 |
14 | pop() {
15 | return this.data.pop();
16 | }
17 |
18 | peek() {
19 | return this.data[this.data.length - 1];
20 | }
21 | }
22 |
23 | function sortStack(stack) {
24 | const sortedStack = new Stack();
25 |
26 | while (stack.peek()) {
27 | let temp = stack.pop();
28 |
29 | while (sortedStack.peek()) {
30 | if (sortedStack.peek() > temp) {
31 | stack.push(sortedStack.pop());
32 | }
33 | }
34 |
35 | sortedStack.push(temp);
36 | }
37 |
38 | return sortedStack;
39 | }
40 |
--------------------------------------------------------------------------------
/exercises/arrays/maxArea.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given n non-negative integers a1, a2, ..., an , where each represents a point at coordinate (i, ai).
3 | * n vertical lines are drawn such that the two endpoints of line i is at (i, ai) and (i, 0).
4 | * Find two lines, which together with x-axis forms a container,
5 | * such that the container contains the most water.
6 | *
7 | * Example:
8 |
9 | Input: [1,8,6,2,5,4,8,3,7]
10 | Output: 49
11 |
12 | Note: You may not slant the container and n is at least 2.
13 | */
14 |
15 | const maxArea = height => {
16 | let left = 0;
17 | let right = height.length - 1;
18 | let maxarea = 0;
19 |
20 | while (left < right) {
21 | maxarea = Math.max(maxarea, Math.min(height[left], height[right]) * (right - left));
22 |
23 | if (height[left] < height[right]) {
24 | left++;
25 | } else {
26 | right--;
27 | }
28 | }
29 |
30 | return maxarea;
31 | }
--------------------------------------------------------------------------------
/exercises/arrays/unchunk.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Given a chunked array join the array into a single array
3 | // --- Examples
4 | // unChunkArray([[ 1, 2], [3, 4]]) --> [ 1, 2, 3, 4]
5 |
6 |
7 | function unChunkArray() {
8 | let unchunked = [];
9 | const arr = [[1,2], [3,4,5], [6], 7, [8]];
10 |
11 | for(let element of arr) {
12 | if(Array.isArray(element)) {
13 | for(let e of element) {
14 | unchunked.push(e);
15 | }
16 | } else {
17 | unchunked.push(element);
18 | }
19 | }
20 | return unchunked;
21 | }
22 |
23 | // function call for test
24 | //unChunkArray();
25 |
26 | const unchunk = array => {
27 | let unchunked = [];
28 |
29 | for (let element of array) {
30 | if (Array.isArray(element)) {
31 | unchunked = unchunked.concat(unchunk(element));
32 | } else {
33 | unchunked.push(element);
34 | }
35 | }
36 |
37 | return unchunked;
38 | }
39 |
--------------------------------------------------------------------------------
/exercises/arrays/increasingTriplet.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an unsorted array return whether an increasing subsequence of length 3 exists or not in the array.
3 |
4 | Formally the function should:
5 |
6 | Return true if there exists i, j, k
7 | such that arr[i] < arr[j] < arr[k] given 0 ≤ i < j < k ≤ n-1 else return false.
8 | Note: Your algorithm should run in O(n) time complexity and O(1) space complexity.
9 |
10 | Example 1:
11 |
12 | Input: [1,2,3,4,5]
13 | Output: true
14 | Example 2:
15 |
16 | Input: [5,4,3,2,1]
17 | Output: false
18 | */
19 | /**
20 | * @param {number[]} nums
21 | * @return {boolean}
22 | */
23 | const increasingTriplet = nums => {
24 | let first = Number.MAX_SAFE_INTEGER;
25 | let second = Number.MAX_SAFE_INTEGER;
26 |
27 | for (let num of nums) {
28 | if (num <= first) {
29 | first = num;
30 | } else if (num <=second) {
31 | second = num;
32 | } else {
33 | return true;
34 | }
35 | }
36 |
37 | return false;
38 | }
--------------------------------------------------------------------------------
/exercises/strings/longestSubStringWithAtMostK.js:
--------------------------------------------------------------------------------
1 | const longestStringWithAtMostK = (str, k) => {
2 | let left = 0;
3 | let right = 0;
4 | const windowMap = new Map();
5 | let maxLength = k;
6 |
7 | while (right < str.length) {
8 | let ch = str[right];
9 |
10 | if (windowMap.size < k + 1) {
11 | windowMap.set(ch, right);
12 | }
13 | right++;
14 |
15 | if (windowMap.size === k + 1) {
16 | let deleteIndex = Array.from(
17 | windowMap.keys()
18 | ).reduce(
19 | (a, b) => windowMap.get(a) < windowMap.get(b) ? a : b
20 | );
21 |
22 | left = windowMap.get(deleteIndex) + 1;
23 | windowMap.delete(deleteIndex);
24 | }
25 |
26 | maxLength = Math.max(maxLength, right - left);
27 | }
28 |
29 | return maxLength;
30 | }
--------------------------------------------------------------------------------
/exercises/linkedlist/removeNthNodeFromEnd.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a linked list, remove the n-th node from the end of list and return its head.
3 | Example:
4 | Given linked list: 1->2->3->4->5, and n = 2.
5 | After removing the second node from the end, the linked list becomes 1->2->3->5.
6 |
7 | Note:
8 | Given n will always be valid.
9 |
10 | Follow up:
11 | Could you do this in one pass?
12 | */
13 |
14 | function ListNode(val) {
15 | this.val = val;
16 | this.next = null;
17 | }
18 |
19 | const removeNthFromEnd = (head, n) => {
20 | if (!head) {
21 | return null;
22 | }
23 |
24 | let dummy = new ListNode(0);
25 | dummy.next = head;
26 | let fast = dummy;
27 | let slow = dummy;
28 |
29 | while (n >= 0) {
30 | fast = fast.next;
31 | n--;
32 | }
33 |
34 | while (fast) {
35 | fast = fast.next;
36 | slow = slow.next;
37 | }
38 |
39 | slow.next = slow.next.next;
40 |
41 | return dummy.next;
42 | }
--------------------------------------------------------------------------------
/concepts/EventDelegation.md:
--------------------------------------------------------------------------------
1 | ## EVENT DELEGATION
2 |
3 | ```html
4 |
5 | - Item 1
6 | - Item 2
7 | - Item 3
8 | - Item 4
9 |
10 | ```
11 |
12 | ```js
13 | document.getElementById("posts").addEventListener(function(e) {
14 | if (e.target && e.target.nodeName === 'LI') {
15 | console.log("List item " + e.target.id.replace("post-", "") + " was clicked");
16 | }
17 | })
18 | ```
19 |
20 |
21 | ```html
22 |
29 | ```
30 |
31 | ```js
32 | document.getElementById("parentDiv").addEventListener(event => {
33 | if (event.target && event.target.matches("a.classA")) {
34 | console.log("Anchor tag with class A was clicked");
35 | }
36 | })
37 | ```
--------------------------------------------------------------------------------
/concepts/Graph.js:
--------------------------------------------------------------------------------
1 | /*
2 | Graph consists of a series of nodes. Each node contains a
3 | value and reference to other nodes.
4 |
5 | Node {
6 | value,
7 | lines: [(Node), (Node)]
8 | }
9 |
10 | Graph{
11 | nodes: [
12 | Node {...},
13 | Node {...},
14 | ...
15 | ]
16 | }
17 | */
18 | class Graph {
19 | constructor() {
20 | this.nodes = [];
21 | }
22 |
23 | addNode(value) {
24 | this.nodes.push({
25 | value,
26 | lines: []
27 | });
28 | }
29 |
30 | find(value) {
31 | this.nodes.find(node => {
32 | return node.value === value;
33 | });
34 | }
35 |
36 | addLine(startValue, endValue) {
37 | let startNode = this.find(startValue);
38 | let endNode = this.find(endValue);
39 |
40 | if (!startNode || !endNode) {
41 | throw new Error ("Both nodes must exist");
42 | }
43 |
44 | startNode.lines.push(endNode);
45 | }
46 | }
--------------------------------------------------------------------------------
/FE-JS-Questions/ReduceString.md:
--------------------------------------------------------------------------------
1 | > Given a string return a reduced string such that , the reduced string has the characters re-arranged
2 |
3 | * in order of characters having highest frequencey
4 | * followed by character which appears just once in the same order as in the original string
5 | * and no duplicate characters
6 |
7 | ```
8 | Input: "hello world"
9 | Output: "lohe wrd"
10 | Explaination: 'l' appears thrice, 'o' appears twice, 'h','e', ' '(space) ,'w','r','d' all appear once
11 | 'h','e',' ','w','r','d' should be appended in the same order as they appear in the original string hello world
12 | ```
13 |
14 | ```js
15 | const reducedString = str => {
16 | const charMap = new Map();
17 |
18 | for (let char of str.split('')) {
19 | charMap.has(char) ? charMap.set(char, charMap.get(char) + 1) : charMap.set(char, 1);
20 | }
21 |
22 | return (
23 | [...charMap.entries()]
24 | .sort((a, b) => b[1] - a[1])
25 | .map(s => s[0])
26 | ).join('');
27 | }
28 | ```
29 |
--------------------------------------------------------------------------------
/drumkit/style.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-size: 10px;
3 | background: url(http://i.imgur.com/b9r5sEL.jpg) bottom center;
4 | background-size: cover;
5 | }
6 | body,html {
7 | margin: 0;
8 | padding: 0;
9 | font-family: sans-serif;
10 | }
11 |
12 | .keys {
13 | display: flex;
14 | flex: 1;
15 | min-height: 100vh;
16 | align-items: center;
17 | justify-content: center;
18 | }
19 |
20 | .key {
21 | border: .4rem solid black;
22 | border-radius: .5rem;
23 | margin: 1rem;
24 | font-size: 1.5rem;
25 | padding: 1rem .5rem;
26 | transition: all .07s ease;
27 | width: 10rem;
28 | text-align: center;
29 | color: white;
30 | background: rgba(0,0,0,0.4);
31 | text-shadow: 0 0 .5rem black;
32 | }
33 |
34 | .playing {
35 | transform: scale(1.2);
36 | border-color: #ffc600;
37 | box-shadow: 0 0 1rem #ffc600;
38 | }
39 |
40 | kbd {
41 | display: block;
42 | font-size: 4rem;
43 | }
44 |
45 | .sound {
46 | font-size: 1.2rem;
47 | text-transform: uppercase;
48 | letter-spacing: .1rem;
49 | color: #ffc600;
50 | }
51 |
--------------------------------------------------------------------------------
/exercises/arrays/groupAnagrams.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an array of strings, group anagrams together.
3 |
4 | Example:
5 |
6 | Input: ["eat", "tea", "tan", "ate", "nat", "bat"],
7 | Output:
8 | [
9 | ["ate","eat","tea"],
10 | ["nat","tan"],
11 | ["bat"]
12 | ]
13 | Note:
14 |
15 | All inputs will be in lowercase.
16 | The order of your output does not matter.
17 | */
18 |
19 |
20 | const groupAnagrams = strs => {
21 | // create a map with key as sorted char and value as the array of anagram word sets
22 | const anagramMap = new Map();
23 |
24 | for (let s of strs) {
25 | let sortedChar = s.split('').sort().join('');
26 |
27 | if (!anagramMap.has(sortedChar)) {
28 | anagramMap.set(sortedChar, []);
29 | }
30 |
31 | anagramMap.get(sortedChar).push(s);
32 | }
33 |
34 | return Array.from(anagramMap.values());
35 | }
36 |
37 | /**
38 | * Time Complexity: O(NKlogK) - Outer Loop : O(N) and string sort O(KlogK) where K is max length
39 | * of a string in strs
40 | * Space Complexity: O(NK) (N elements with string of size K stored ?)
41 | */
--------------------------------------------------------------------------------
/exercises/arrays/peakIndex.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Let's call an array A a mountain if the following properties hold:
3 |
4 | A.length >= 3
5 | There exists some 0 < i < A.length - 1 such that A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1]
6 | Given an array that is definitely a mountain, return any i such that A[0] < A[1] < ... A[i-1] < A[i] > A[i+1] > ... > A[A.length - 1].
7 |
8 | Example 1:
9 |
10 | Input: [0,1,0]
11 | Output: 1
12 | Example 2:
13 |
14 | Input: [0,2,1,0]
15 | Output: 1
16 | Note:
17 |
18 | 3 <= A.length <= 10000
19 | 0 <= A[i] <= 10^6
20 | A is a mountain, as defined above.
21 | */
22 |
23 | const peakIndex = A => {
24 | if (A.length < 3) {
25 | return -1;
26 | }
27 |
28 | let left = 0;
29 | let right = A.length - 1;
30 |
31 | while (left < right) {
32 | let mid = left + Math.floor((right - left) / 2);
33 |
34 | if (A[mid] < A[mid + 1]) {
35 | left = mid + 1;
36 | } else {
37 | right = mid;
38 | }
39 | }
40 |
41 | return left;
42 | }
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/topNCompetitors.js:
--------------------------------------------------------------------------------
1 | const topNCompetitors = (numCompetitors, topN, competitors, numReviews, reviews) => {
2 | const map = {};
3 |
4 | for (let competitor of competitors) {
5 | let competitorReview = reviews.filter(
6 | review => review.toLowerCase()
7 | .includes(competitor)
8 | );
9 | map[competitor] = competitorReview.length || 0;
10 | }
11 |
12 | const sortedComp = Object.keys(map).sort((a, b) => map[b] - map[a]);
13 |
14 | return sortedComp.slice(0, topN);
15 | }
16 |
17 | /**
18 | * const reviews = ['newshop is providing good services in the city',
19 | * 'best services by newshop', 'fashionbeats has great services in the city',
20 | * 'I am proud to have fashionbeats', 'mymarket has awesome services',
21 | * 'thanks NewShop for great delivery']
22 |
23 | const competitors = ['newshop', 'shopnow', 'afashion', 'fashionbeats', 'mymarket', 'tcellular'];
24 |
25 | console.log(topNCompetitors(6, 2, competitors, 6, reviews));
26 | */
--------------------------------------------------------------------------------
/exercises/arrays/summaryRanges.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a unsorted integer array without duplicates, return the summary of its ranges.
3 |
4 | Example 1:
5 |
6 | Input: [0,1,2,4,5,7]
7 | Output: ["0->2","4->5","7"]
8 | Explanation: 0,1,2 form a continuous range; 4,5 form a continuous range.
9 | Example 2:
10 |
11 | Input: [0,2,3,4,6,8,9]
12 | Output: ["0","2->4","6","8->9"]
13 | Explanation: 2,3,4 form a continuous range; 8,9 form a continuous range.
14 | */
15 |
16 | const summaryRanges = nums => {
17 | if (nums.length === 0) {
18 | return [];
19 | }
20 |
21 | nums.sort((a, b) => a - b);
22 | const result = [];
23 |
24 | for (let start = 0, end = 0; end < nums.length; end++) {
25 | if (end + 1 < nums.length && nums[end + 1] === nums[end] + 1) {
26 | continue;
27 | }
28 |
29 | if (start === end) {
30 | result.push(nums[start] + '');
31 | } else {
32 | result.push(start + '->' + end);
33 | }
34 | start = end + 1;
35 | }
36 |
37 | return result;
38 | }
--------------------------------------------------------------------------------
/progressBar/progressBar.md:
--------------------------------------------------------------------------------
1 | ## Progress Bar with Vanilla JS
2 |
3 | ### HTML
4 |
5 | ```html
6 |
9 |
10 |
11 | ```
12 |
13 | ### CSS
14 |
15 | ```css
16 | .progressBarContainer {
17 | width: 400px;
18 | height: 30px;
19 | margin: 40px;
20 | background-color: light-grey;
21 | }
22 |
23 | .progressBar {
24 | background-color: green;
25 | height: 100%;
26 | width: 0%;
27 | }
28 | ```
29 |
30 | ### JS
31 |
32 | ```js
33 | const updateProgress = delayInSeconds => {
34 | let atPercent = 0;
35 | const progressBar = document.querySelector(".progressBar");
36 |
37 | const interval = setInterval(() => {
38 | atPercent++;
39 | progressBar.style.width = `${atPercent}%`;
40 | progressBar.style.innerText = `${atPercent}%`;
41 |
42 | if (atPercent >= 100) {
43 | clearInterval(interval);
44 | }
45 | }, (delayInSeconds * 1000) / 100);
46 | }
47 | ```
48 |
--------------------------------------------------------------------------------
/exercises/linkedlist/mergeKSortedList.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
3 |
4 | Example:
5 |
6 | Input:
7 | [
8 | 1->4->5,
9 | 1->3->4,
10 | 2->6
11 | ]
12 | Output: 1->1->2->3->4->4->5->6
13 | */
14 | /**
15 | * Definition for singly-linked list. */
16 | function ListNode(val) {
17 | this.val = val;
18 | this.next = null;
19 | }
20 |
21 |
22 | const mergeKLists = lists => {
23 | let head = new ListNode();
24 | let point = head;
25 | let nodes = [];
26 |
27 | for (let l of lists) {
28 | while (l) {
29 | nodes.push(l.val);
30 | l = l.next;
31 | }
32 | }
33 | nodes.sort((a, b) => a - b);
34 | for (let n of nodes) {
35 | point.next = new ListNode(n);
36 | point = point.next;
37 | }
38 |
39 | return head.next;
40 | }
41 |
42 | // Time Complexity: O (NlogN) => O(N) for looping list and creating array
43 | // O(NlogN) for sorting
44 | // O(N) for creating new list
45 | // Space Complexity: O(N)
--------------------------------------------------------------------------------
/FE-JS-Questions/eventEmitter.md:
--------------------------------------------------------------------------------
1 | ## Implement an EventEmitter
2 |
3 | ```js
4 | const emitter = new EventEmitter();
5 | const sub = emitter.subscribe(eventName, callback); // typeof eventName === string
6 | emitter.emit(eventName, a, b, c, d, ...);
7 | sub.unsubscribe();
8 | ```
9 |
10 | ```js
11 | class EventEmitter {
12 | constructor() {
13 | this.events = new Map();
14 | }
15 |
16 | subscribe(eventName, callback) {
17 | this.events.set(eventName, callback);
18 |
19 | return {
20 | unsubscribe : () => this.events.delete(eventName)
21 | };
22 | }
23 |
24 | emit(eventName, ...args) {
25 | if (this.events.has(eventName)) {
26 | this.events.get(eventName).apply(null, args);
27 | }
28 | }
29 | }
30 | ```
31 |
32 |
33 | ```js
34 | // Example:
35 | function emitSuccess() {
36 | console.log("Emitter class implemented");
37 | }
38 | const emitter = new EventEmitter();
39 | const sub = emitter.subscribe("change", emitSuccess);
40 | emitter.emit("change", 1,2,3,4);
41 | sub.unsubscribe();
42 | ```
--------------------------------------------------------------------------------
/exercises/trees/zigzagTraversal.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between).
3 |
4 | For example:
5 | Given binary tree [3,9,20,null,null,15,7],
6 | 3
7 | / \
8 | 9 20
9 | / \
10 | 15 7
11 | return its zigzag level order traversal as:
12 | [
13 | [3],
14 | [20,9],
15 | [15,7]
16 | ]
17 | */
18 |
19 | const traverseZigzag = (node, level, output) => {
20 | if (!node) {
21 | return output;
22 | }
23 |
24 | if (output.length === level) {
25 | output.push([]);
26 | }
27 |
28 | if (level % 2 !== 0) {
29 | output[level].unshift(node.val);
30 | } else {
31 | output[level].push(node.val);
32 | }
33 |
34 | traverseZigzag(node.left, level + 1, output);
35 | traverseZigzag(node.right, level + 1, output);
36 | }
37 |
38 | const zigzagLevelOrder = root => {
39 | const output = [];
40 |
41 | traverseZigzag(root, 0, output);
42 |
43 | return output;
44 | }
--------------------------------------------------------------------------------
/carousel/carousel.md:
--------------------------------------------------------------------------------
1 | ```html
2 |
30 | ```
--------------------------------------------------------------------------------
/exercises/strings/longestPalindrome.js:
--------------------------------------------------------------------------------
1 | // Given a string s, find the longest palindromic substring in s.
2 | //
3 | // Example 1:
4 | //
5 | // Input: "babad"
6 | // Output: "bab"
7 | // Note: "aba" is also a valid answer.
8 | // Example 2:
9 | //
10 | // Input: "cbbd"
11 | // Output: "bb"
12 |
13 | const longestPalindrome = s => {
14 | if (!s || s.length < 1) {
15 | return '';
16 | }
17 |
18 | const expandAroundCenter = (s, L, R) => {
19 | while (L >= 0 && R < s.length && s.charAt(L) == s.charAt(R)) {
20 | L--;
21 | R++;
22 | }
23 | return R - L - 1;
24 | }
25 |
26 | let start = 0;
27 | let end = 0;
28 |
29 | for (let i = 0; i < s.length; i++) {
30 | let len1 = expandAroundCenter(s, i, i);
31 | let len2 = expandAroundCenter(s, i, i + 1);
32 | let len = Math.max(len1, len2);
33 |
34 | if (len > (end - start)) {
35 | start = Math.ceil(i - (len - 1) / 2);
36 | end = Math.floor(i + len / 2);
37 | }
38 | }
39 |
40 | return s.substring(start, end + 1);
41 | }
42 |
--------------------------------------------------------------------------------
/exercises/arrays/findIntersection.js:
--------------------------------------------------------------------------------
1 | // Find the intersection of two arrays.
2 | // An intersection would be the common elements that exists within both arrays.
3 | // In this case, these elements should be unique!
4 | // var firstArray = [2, 2, 4, 1];
5 | // var secondArray = [1, 2, 0, 2];
6 |
7 | // intersection(firstArray, secondArray); // [2, 1]
8 |
9 | function intersection(firstArray, secondArray) {
10 | const arrayMap = {};
11 | const intersectionArray = [];
12 |
13 | firstArray.forEach(element => {
14 | arrayMap[element] = 1;
15 | });
16 |
17 | secondArray.forEach(element => {
18 | if (arrayMap[element]) {
19 | intersectionArray.push(element);
20 | arrayMap[element]++;
21 | }
22 | });
23 |
24 | return intersectionArray;
25 | }
26 |
27 | const intersection = (array1, array2) => {
28 | const intersectionArray = [];
29 |
30 | array1.filter(element => {
31 | if (array2.includes(element)) {
32 | intersectionArray.push(element);
33 | array1.splice(array1.indexOf(element), 1);
34 | }
35 | });
36 |
37 | return intersectionArray;
38 | }
39 |
--------------------------------------------------------------------------------
/exercises/strings/reverseString.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Given a string, return a new string with the reversed
3 | // order of characters
4 | // --- Examples
5 | // reverse('apple') === 'leppa'
6 | // reverse('hello') === 'olleh'
7 | // reverse('Greetings!') === '!sgniteerG'
8 |
9 | // 3 Possible solutions
10 |
11 | // Using Array reverse function
12 | function reverse(str) {
13 | return str.split('').reverse().join('');
14 | }
15 |
16 | // Using for loop
17 | function reverse(str) {
18 | let reversed = '';
19 |
20 | for (let character of str) {
21 | reversed = character + reversed;
22 | }
23 |
24 | return reversed;
25 | }
26 |
27 | // Using reduce function
28 | // The reduce function takes 2 arguments
29 | // First argument below is a function, and second argument is an empty string
30 |
31 | function reverse(str) {
32 | return str.split('').reduce((rev, char) => char + rev, '');
33 | }
34 |
35 | function reverse(str) {
36 | let left = 0;
37 | let right = str.length - 1;
38 |
39 | while (left < right) {
40 | [str[left], str[right]] = [str[right], str[left]];
41 | left++;
42 | right--;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/exercises/strings/isPalindrome.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
3 |
4 | Note: For the purpose of this problem, we define empty string as valid palindrome.
5 |
6 | Example 1:
7 |
8 | Input: "A man, a plan, a canal: Panama"
9 | Output: true
10 | Example 2:
11 |
12 | Input: "race a car"
13 | Output: false
14 | */
15 |
16 | const isPalindrome = s => {
17 | // replace all punctuations and chars other than alpha numeric to check if reversed str is a palindrome
18 | s = s.replace(/[^A-Z0-9+$]/gi, '').toLowerCase();
19 | const rev = s.split('').reverse().join('');
20 |
21 | return s === rev;
22 | }
23 |
24 | const isPalindrome = s => {
25 | let charArray = s.replace(/[^A-Z0-9+$]/gi, '').toLowerCase().split('');
26 | let start = 0, end = charArray.length - 1;
27 |
28 | while (start <= end) {
29 | if (charArray[start] !== charArray[end]) {
30 | return false;
31 | }
32 | start++;
33 | end--;
34 | }
35 |
36 | return true;
37 | }
38 |
39 | /**
40 | * Time Complexity: O(log N)
41 | * Space Complexity: O(N)
42 | */
--------------------------------------------------------------------------------
/exercises/trees/cloneGraph.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a reference of a node in a connected undirected graph,
3 | * return a deep copy (clone) of the graph.
4 | * Each node in the graph contains a val (int) and a list (List[Node]) of its neighbors.
5 | */
6 | /**
7 | * // Definition for a Node.
8 | * function Node(val,neighbors) {
9 | * this.val = val;
10 | * this.neighbors = neighbors;
11 | * };
12 | */
13 | /**
14 | * @param {Node} node
15 | * @return {Node}
16 | */
17 | const visited = new Map();
18 | const cloneGraph = node => {
19 | if (node === null) {
20 | return node;
21 | }
22 |
23 | if (visited.has(node)) {
24 | return visited.get(node);
25 | }
26 |
27 | let cloneNode = new Node(node, []);
28 | visited.put(node, cloneNode);
29 |
30 | for (let neighbor of node.neighbors) {
31 | cloneNode.neighbors.push(cloneGraph(neighbor));
32 | }
33 |
34 | return cloneNode;
35 | }
36 |
37 | /**
38 | * Time Complexity: O(N) (As we process each node once)
39 | * Space Complexity: O(N) (Space taken by the map -> visited, and also the space taken up
40 | * by the height of the recursion stack O(H))
41 | */
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/partitionLabel.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A string S of lowercase letters is given.
3 | * We want to partition this string into as many parts as possible
4 | * so that each letter appears in at most one part,
5 | * and return a list of integers representing the size of these parts.
6 | *
7 | * Input: S = "ababcbacadefegdehijhklij"
8 | Output: [9,7,8]
9 | Explanation:
10 | The partition is "ababcbaca", "defegde", "hijhklij".
11 | This is a partition so that each letter appears in at most one part.
12 | A partition like "ababcbacadefegde", "hijhklij" is incorrect, because it splits S into less parts.
13 | */
14 |
15 | const partitionLabel = S => {
16 | const partitions = [];
17 | const lastIndexMap = {};
18 |
19 | for (let i = 0; i < S.length; i++) {
20 | lastIndexMap[S[i]] = i;
21 | }
22 |
23 | let startIndex = 0; let endIndex = 0;
24 |
25 | for (let i = 0; i < S.length; i++) {
26 | startIndex = Math.max(startIndex, lastIndexMap[S[i]]);
27 |
28 | if (startIndex === i) {
29 | partitions.push(i - endIndex + 1);
30 | lastIndex = i + 1;
31 | }
32 | }
33 |
34 | return partitions;
35 | }
--------------------------------------------------------------------------------
/concepts/HTTP.md:
--------------------------------------------------------------------------------
1 | ### HTTP Requests
2 |
3 | HTTP requests contains of 3 main parts
4 |
5 | 1. Start Line
6 | * Noun or verb describing the request : `GET`, `PUT`, `POST`, `HEAD`, `OPTIONS`
7 |
8 | * URL part requesting the server for information or updating the server with new information called request target
9 |
10 | Below are origin forms
11 | ```
12 | POST / HTTP 1.1
13 | GET /background.png HTTP 1.1
14 | HEAD /test.html?query=testString HTTP 1.1
15 | ```
16 | Below are absolute forms used for proxy connections
17 | ```
18 | GET http://developer.mozilla.org/en-US/docs/Web HTTP 1.1
19 | ```
20 |
21 | Authority Form - for tunnel connections
22 | Asterisk form - used for representing the server as a whole.
23 |
24 | 2. Headers
25 | 3. Body (usually in case of POST requests containing form data)
26 |
27 | ```
28 | POST / HTTP 1.1
29 | Host: Localhost:8000
30 | User-Agent: Mozilla/5.0 (Macintosh; )
31 | Accept: text/html, application/xhtml+xml,...,*/*; q=0.8
32 | Accept-language: en-US, en;q=0.5
33 | Accept-Encoding: gzip, deflate
34 | Connection: keep-alive
35 | Upgrade Insecure-Requests: 1
36 | Content-type: multipart/form-data; boundary=123456789
37 | Content-length: 345
38 | ```
39 |
--------------------------------------------------------------------------------
/exercises/misc/largestPalindromeProduct.js:
--------------------------------------------------------------------------------
1 | // A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
2 | //
3 | // Find the largest palindrome made from the product of two 3-digit numbers.
4 | // for any n digit number calculate upperLimit and lowerLimit using below loop
5 | /*
6 | for (let i = 1; i <= n; i++) {
7 | upperLimit *= 10;
8 | upperLimit += 9;
9 | }
10 | lowerLimit = 1 + Math.floor(upperLimit / 10);
11 | */
12 |
13 | function largestPalindromeProduct() {
14 | let upperLimit = 999;
15 | let maxProduct = 0;
16 | while (upperLimit > 100) {
17 | for (let lowerLimit = 999; lowerLimit > 100; lowerLimit--) {
18 | let product = upperLimit * lowerLimit;
19 | let reversed =
20 | parseInt(
21 | product
22 | .toString()
23 | .split('')
24 | .reverse()
25 | .join('')
26 | ) * Math.sign(product);
27 | if (product === reversed) {
28 | if (product > maxProduct) {
29 | maxProduct = product;
30 | }
31 | }
32 | }
33 | upperLimit--;
34 | }
35 |
36 | return maxProduct;
37 | }
38 |
--------------------------------------------------------------------------------
/exercises/linkedlist/partitionLinkedList.js:
--------------------------------------------------------------------------------
1 | // Write code to partition a linked list around a value x, such that all nodes less than
2 | // x come before all nodes greater than or equal to x.
3 |
4 | class Node {
5 | constructor(data, next = null) {
6 | this.data = data;
7 | this.next = next;
8 | }
9 | }
10 |
11 | class LinkedList {
12 | constructor() {
13 | this.head = null;
14 | }
15 | }
16 |
17 | function partition(list, x) {
18 | let left = null;
19 | let currLeft = null;
20 | let right = null;
21 | let currRight = null;
22 |
23 | let node = list.head;
24 |
25 | while (node) {
26 | if (node.data < x) {
27 | if (!left) {
28 | left = node;
29 | currLeft = left;
30 | } else {
31 | currLeft.next = node;
32 | currLeft = currLeft.next;
33 | }
34 | } else if (node.data > x) {
35 | if (!right) {
36 | right = node;
37 | currRight = right;
38 | } else {
39 | currRight.next = node;
40 | currRight = currRight.next;
41 | }
42 | }
43 | node = node.next;
44 | }
45 |
46 | currRight.next = null;
47 | currLeft.next = right;
48 |
49 | return left;
50 | }
51 |
--------------------------------------------------------------------------------
/FE-JS-Questions/JSONPath.md:
--------------------------------------------------------------------------------
1 | ## JSON PATH
2 |
3 | > Given an object and a string path, write a method getValue to get the value at given path.
4 |
5 | ```
6 | Example:
7 |
8 | const obj = { 'x': [{ 'y': { 'z': 100 } }] };
9 |
10 | getValue(obj, 'x[0].y.z'); // 100
11 | ```
12 |
13 | ```js
14 | const obj = { 'x': [{ 'y': { 'z': 100 } }] };
15 |
16 | const getCurrentLevelValue = (obj, level) => {
17 | const regex = /[\[\]]/g;
18 |
19 | if (regex.test(level)) {
20 | const arrayKeyStr = level.substring(level.indexOf('['));
21 | const arrayKey = arrayKeyStr.split('').filter(char => char !== '[' && char !== ']');
22 | const objKey = level[0]; // first char of string would be object key
23 | return obj[objKey][arrayKey];
24 | } else {
25 | return obj[level];
26 | }
27 | }
28 |
29 | const getValue = (obj, path) => {
30 | const pathArray = path.split('.');
31 | let result = obj;
32 |
33 | for (let level of pathArray) {
34 | result = getCurrentLevelValue(result, level)
35 | if (!result) {
36 | break;
37 | }
38 | }
39 |
40 | return result;
41 | }
42 |
43 | console.log(getValue(obj, 'x[0].y.z')); // 100
44 | ```
45 |
--------------------------------------------------------------------------------
/exercises/arrays/validParenthesis.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
3 |
4 | An input string is valid if:
5 |
6 | Open brackets must be closed by the same type of brackets.
7 | Open brackets must be closed in the correct order.
8 | Note that an empty string is also considered valid.
9 | */
10 |
11 | const validParenthesis = str => {
12 | const bracketMap = new Map();
13 |
14 | bracketMap.set(')', '(');
15 | bracketMap.set('}', '{');
16 | bracketMap.set(']', '[');
17 |
18 | const strStack = [];
19 |
20 | for (let ch of str.split('')) {
21 | // check if the char is a closing bracket
22 | if (bracketMap.has(ch)) {
23 | // find the top element from the stack
24 | let top = strStack.length === 0 ? '#' : strStack.pop();
25 |
26 | // if top element is not an opening bracket, expression is invalid
27 | if (top !== bracketMap.get(ch)) {
28 | return false;
29 | }
30 | } else {
31 | // its an opening bracket, push it to the stack
32 | strStack.push(ch);
33 | }
34 | }
35 |
36 | return strStack.length === 0;
37 | }
38 | /**
39 | * Time Complexity: O(n)
40 | * Space Complexity: O(n)
41 | */
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/mergeIntervals.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a collection of intervals, merge all overlapping intervals.
3 |
4 | Example 1:
5 |
6 | Input: [[1,3],[2,6],[8,10],[15,18]]
7 | Output: [[1,6],[8,10],[15,18]]
8 | Explanation: Since intervals [1,3] and [2,6] overlaps, merge them into [1,6].
9 | Example 2:
10 |
11 | Input: [[1,4],[4,5]]
12 | Output: [[1,5]]
13 | Explanation: Intervals [1,4] and [4,5] are considered overlapping.
14 | */
15 |
16 | const mergeIntervals = intervals => {
17 | let n = intervals.length;
18 |
19 | if (n <= 1) {
20 | return intervals;
21 | }
22 |
23 | intervals.sort(([a, b], [c, d]) => a - c || b - d);
24 |
25 | let i = 1;
26 | let start = intervals[0][0];
27 | let end = intervals[0][1];
28 | const result = [];
29 |
30 | while (i < n) {
31 | if (intervals[i][0] <= end) {
32 | start = Math.min(start, intervals[i][0]);
33 | end = Math.max(end, intervals[i][1]);
34 | } else {
35 | result.push([start, end]);
36 | start = intervals[i][0];
37 | end = intervals[i][1];
38 | }
39 | i++;
40 | }
41 |
42 | result.push([start, end]);
43 | return result;
44 | }
45 |
--------------------------------------------------------------------------------
/exercises/misc/threeSum.js:
--------------------------------------------------------------------------------
1 | /*
2 | Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
3 |
4 | Note:
5 |
6 | The solution set must not contain duplicate triplets.
7 | */
8 |
9 | var threeSum = function(nums) {
10 | const results = [];
11 | nums.sort();
12 |
13 | for (let i = 0; i < nums.length-2; i++) {
14 | let j = i + 1;
15 | let k = nums.length - 1;
16 |
17 | if (nums[i] === nums[i-1]) {
18 | continue;
19 | }
20 |
21 | while(j < k) {
22 | if (nums[i] + nums[j] + nums[k] < 0) {
23 | j++;
24 | } else if (nums[i] + nums[j] + nums[k] > 0) {
25 | k--;
26 | } else {
27 | results.push([nums[i], nums[j], nums[k]]);
28 | j++;
29 | k--;
30 | while (j < k && nums[j] === nums[j-1]) {
31 | j++
32 | }
33 | while (j < k && nums[k] === nums[k+1]) {
34 | k--;
35 | }
36 | }
37 | }
38 | }
39 | return results;
40 | };
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/longestStringWithout3ConsecutiveChars.js:
--------------------------------------------------------------------------------
1 | // total string length is a + b + c
2 |
3 | /**
4 | * while length is less total length allowed
5 | *
6 | * conseccounter, acounter, bcounter ccounter
7 | *
8 | * for i = 0 i < A; i++ if acounter < 2 => string += 'a' else A -= acounter
9 | *
10 | * B
11 | * C
12 | */
13 |
14 | const longestStringWithout3ConsecutiveChars = (A, B, C) => {
15 | let outputString = '';
16 | const totalStringLength = A + B + C;
17 |
18 | const addChar = (maxLimit, char) => {
19 | let counter = 0;
20 | for (let i = 0; i < maxLimit; i++) {
21 | if (counter < 2) {
22 | outputString += char;
23 | counter++;
24 | } else {
25 | maxLimit -= counter;
26 | break;
27 | }
28 | }
29 | return maxLimit;
30 | }
31 |
32 | const charLimits = [['a', A], ['b', B], ['c', C]]
33 | charLimits.sort((a, b) => b[1] - a[1]);
34 |
35 | while (outputString.length < totalStringLength) {
36 | for (let [char, limit] of charLimits) {
37 | limit = addChar(limit, char);
38 | }
39 | }
40 |
41 | return outputString;
42 | }
--------------------------------------------------------------------------------
/exercises/sorting/sortColors.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an array with n objects colored red, white or blue, sort them in-place so that objects of the same color are adjacent,
3 | * with the colors in the order red, white and blue.
4 |
5 | Here, we will use the integers 0, 1, and 2 to represent the color red, white, and blue respectively.
6 |
7 | Note: You are not suppose to use the library's sort function for this problem.
8 |
9 | Example:
10 |
11 | Input: [2,0,2,1,1,0]
12 | Output: [0,0,1,1,2,2]
13 | Follow up:
14 |
15 | A rather straight forward solution is a two-pass algorithm using counting sort.
16 | First, iterate the array counting number of 0's, 1's, and 2's, then overwrite array with total number of 0's, then 1's and followed by 2's.
17 | Could you come up with a one-pass algorithm using only constant space?
18 | */
19 |
20 | const sortColors = nums => {
21 | let p0 = 0;
22 | let curr = 0;
23 | let p2 = nums.length - 1;
24 |
25 | while (curr <= p2) {
26 | if (nums[curr] === 0) {
27 | [nums[curr], nums[p0]] = [nums[p0], nums[curr]];
28 | curr++;
29 | p0++;
30 | } else if (nums[curr] === 2) {
31 | [nums[curr], nums[p2]] = [nums[p2], nums[curr]];
32 | p2--;
33 | } else {
34 | curr++;
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/exercises/strings/longestIncreasingSubSequence.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an unsorted array of integers, find the length of longest increasing subsequence.
3 |
4 | Example:
5 |
6 | Input: [10,9,2,5,3,7,101,18]
7 | Output: 4
8 | Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
9 | Note:
10 |
11 | There may be more than one LIS combination, it is only necessary for you to return the length.
12 | Your algorithm should run in O(n2) complexity.
13 | Follow up: Could you improve it to O(n log n) time complexity?
14 | */
15 |
16 | const lengthOfLIS = nums => {
17 | if (nums.length === 0) {
18 | return 0;
19 | }
20 |
21 | // array to store length of longest sequence up to each index
22 | let dp = [0];
23 | let maxAns = 1;
24 |
25 | for (let i = 1; i < nums.length; i++) {
26 | let maxVal = 0;
27 | for (let j = 0; j < i; j++) {
28 | if (nums[i] > nums[j]) {
29 | maxVal = Math.max(maxVal, dp[j]);
30 | }
31 | }
32 | dp[i] = maxVal + 1;
33 | maxAns = Math.max(maxAns, dp[i]);
34 | }
35 |
36 | return maxAns;
37 | }
38 |
39 | /**
40 | * Time Complexity: O(n^2)
41 | * Space Complexity: O(n)
42 | */
--------------------------------------------------------------------------------
/exercises/trees/inorderTraversal.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a binary tree, return the inorder traversal of its nodes' values.
3 |
4 | Example:
5 |
6 | Input: [1,null,2,3]
7 | 1
8 | \
9 | 2
10 | /
11 | 3
12 |
13 | Output: [1,3,2]
14 | Follow up: Recursive solution is trivial, could you do it iteratively?
15 | */
16 | const traverse = (node, result) => {
17 | if (node !== null) {
18 | if (node.left !== null) {
19 | traverse(node.left, result);
20 | }
21 | result.push(node.val);
22 | if (node.right !== null) {
23 | traverse(node.right, result);
24 | }
25 | }
26 | }
27 | const inOrderTraversal = root => {
28 | const result = [];
29 |
30 | traverse(root, result);
31 |
32 | return result;
33 | }
34 |
35 | // Iterative solution
36 | const inorderTraversal = root => {
37 | const result = [];
38 | const stack = [];
39 | let curr = root;
40 |
41 | while (curr !== null || stack.length()) {
42 | while (curr !== null) {
43 | stack.push(curr);
44 | curr = curr.left;
45 | }
46 | curr = stack.pop();
47 | result.push(curr.val);
48 | curr = curr.right;
49 | }
50 |
51 | return result;
52 | }
--------------------------------------------------------------------------------
/exercises/strings/lengthOfLongestSubstring.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a string, find the length of the longest substring without repeating characters.
3 |
4 | Example 1:
5 |
6 | Input: "abcabcbb"
7 | Output: 3
8 | Explanation: The answer is "abc", with the length of 3.
9 | Example 2:
10 |
11 | Input: "bbbbb"
12 | Output: 1
13 | Explanation: The answer is "b", with the length of 1.
14 | Example 3:
15 |
16 | Input: "pwwkew"
17 | Output: 3
18 | Explanation: The answer is "wke", with the length of 3.
19 | Note that the answer must be a substring, "pwke" is a subsequence and not a substring.
20 | */
21 |
22 | const lengthOfLongestSubstring = str => {
23 | if (str.length === 0 || str.length === 1) {
24 | return str.length;
25 | }
26 |
27 | let maxLength = 0;
28 | let longestSubstring = '';
29 |
30 | for (let char of str) {
31 | if (longestSubstring.includes(char)) {
32 | let index = longestSubstring.indexOf(char);
33 | longestSubstring = longestSubstring.substring(index + 1);
34 | }
35 |
36 | longestSubstring += char;
37 | if (longestSubstring.length > maxLength) {
38 | maxLength = longestSubstring.length;
39 | }
40 | }
41 |
42 | return maxLength;
43 | }
--------------------------------------------------------------------------------
/exercises/misc/findOptimalRoute.js:
--------------------------------------------------------------------------------
1 | function findOptimalRoute(forwardRouteArr, returnRouteArr, maxTravelDistance) {
2 | let routeWithDistance = [];
3 |
4 | for (let i = 0; i < forwardRouteArr.length; i++) {
5 | let currentForwardRoute = forwardRouteArr[i];
6 | for (let j = 0; j < returnRouteArr.length; j++) {
7 | let currenReturnRoute = returnRouteArr[j];
8 | let distance = currentForwardRoute[1] + currenReturnRoute[1];
9 | routeWithDistance.push({
10 | route: [currentForwardRoute[0], currenReturnRoute[0]],
11 | distance: distance
12 | });
13 | }
14 | }
15 |
16 | routeWithDistance.sort((a, b) => {
17 | if (a.distance > b.distance) {
18 | return -1;
19 | }
20 |
21 | if (a.distance < b.distance) {
22 | return 1;
23 | }
24 |
25 | return 0;
26 | });
27 |
28 | let optimalDistance = routeWithDistance[0].distance;
29 | outputArray.push(routeWithDistance[0].route);
30 |
31 | for (let i = 1; i < routeWithDistance.length; i++) {
32 | if (
33 | routeWithDistance[i].distance <= maxTravelDistance &&
34 | routeWithDistance[i].distance === optimalDistance
35 | ) {
36 | outputArray.push(routeWithDistance[i].route);
37 | }
38 | }
39 |
40 | return outputArray;
41 | }
42 |
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/twoSumUniquePairs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an int array nums and an int target,
3 | * find how many unique pairs in the array such that their sum is equal to target.
4 | * Return the number of pairs.
5 | *
6 | * Eg:
7 | * Input: nums = [1, 1, 2, 45, 46, 46], target = 47
8 | Output: 2
9 | Explanation:
10 | 1 + 46 = 47
11 | 2 + 45 = 47
12 |
13 | Input: nums = [1, 1], target = 2
14 | Output: 1
15 | Explanation:
16 | 1 + 1 = 2
17 |
18 | Input: nums = [1, 5, 1, 5], target = 6
19 | Output: 1
20 | Explanation:
21 | [1, 5] and [5, 1] are considered the same.
22 | */
23 |
24 | const twoSumUniquePairs = (nums, target) => {
25 | let left = 0;
26 | let right = nums.length - 1;
27 | let pairCount = 0;
28 | const set = new Set();
29 |
30 | while (right > left) {
31 | if (nums[left] + nums[right] === target) {
32 | if (!set.has(nums[left]) && !set.has(nums[right])) {
33 | set.add(nums[left]);
34 | set.add(nums[right]);
35 | pairCount++;
36 | }
37 | }
38 |
39 | if (nums[left] + nums[right] > target) {
40 | right--;
41 | } else {
42 | left++;
43 | }
44 | }
45 |
46 | return pairCount;
47 | }
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/pathSumMax.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a matrix with r rows and c columns,
3 | * find the maximum score of a path starting at [0, 0] and ending at [r-1, c-1].
4 | * The score of a path is the minimum value in that path.
5 | * For example, the score of the path 8 → 4 → 5 → 9 is 4.
6 | *
7 | * Don't include the first or final entry.
8 | * You can only move either down or right at any point in time.
9 | */
10 |
11 | const pathWithMaxScore = grid => {
12 | for (let row = 2; row < grid[0].length; row++) {
13 | grid[0][row] = Math.min(grid[0][row], grid[0][row - 1]);
14 | }
15 |
16 | for (let column = 2; column < grid.length; column++) {
17 | grid[column][0] = Math.min(grid[column][0], grid[column - 1][0]);
18 | }
19 |
20 | for (let i = 1; i < grid.length; i++) {
21 | for (let j = 1; j < grid[0].length; j++) {
22 | if (i === grid.length - 1 && j === grid[0].length - 1) {
23 | grid[i][j] = Math.max(grid[i - 1][j], grid[i][j - 1]);
24 | } else {
25 | grid[i][j] = Math.max(Math.min(grid[i - 1][j], grid[i][j]),
26 | Math.min(grid[i][j], grid[i][j - 1]));
27 | }
28 | }
29 | }
30 |
31 | return grid[grid.length - 1][grid[0].length - 1];
32 | }
--------------------------------------------------------------------------------
/exercises/linkedlist/hasCycle.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a linked list, determine if it has a cycle in it.
3 |
4 | To represent a cycle in the given linked list, we use an integer pos which represents the position (0-indexed) in the linked list where tail connects to. If pos is -1, then there is no cycle in the linked list.
5 |
6 |
7 |
8 | Example 1:
9 |
10 | Input: head = [3,2,0,-4], pos = 1
11 | Output: true
12 | Explanation: There is a cycle in the linked list, where tail connects to the second node.
13 |
14 | Input: head = [1,2], pos = 0
15 | Output: true
16 | Explanation: There is a cycle in the linked list, where tail connects to the first node.
17 |
18 | Input: head = [1], pos = -1
19 | Output: false
20 | Explanation: There is no cycle in the linked list.
21 |
22 | function ListNode(val) {
23 | this.val = val;
24 | this.next = null;
25 | }
26 | @param {ListNode} (head)
27 | @return {boolean}
28 | */
29 | const hasCycle = head => {
30 | if (!head || !head.next) {
31 | return false;
32 | }
33 |
34 | let slow = head;
35 | let fast = head.next;
36 |
37 | while (slow !== fast) {
38 | if (fast === null || fast.next === null) {
39 | return false;
40 | }
41 | slow = slow.next;
42 | fast = fast.next.next;
43 | }
44 |
45 | return true;
46 | }
47 | /**
48 | * Time Complexity: O(N)
49 | * Space Complexity: O(1)
50 | */
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/twoPairSum.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a list of positive integers nums and an int target, return indices of the two numbers such that they add up to a target - 30.
3 |
4 | Conditions:
5 |
6 | You will pick exactly 2 numbers.
7 | You cannot pick the same element twice.
8 | If you have muliple pairs, select the pair with the largest number.
9 |
10 | Input: nums = [1, 10, 25, 35, 60], target = 90
11 | Output: [2, 3]
12 | Explanation:
13 | nums[2] + nums[3] = 25 + 35 = 60 = 90 - 30
14 | */
15 |
16 | const findTwoPairSum = (nums, target) => {
17 | let left = 0; let right = nums.length - 1;
18 | target = target - 30;
19 | let output = [];
20 |
21 | while (right > left) {
22 | if (nums[left] + nums[right] === target) {
23 | if (output.length) {
24 | if (nums[left] === Math.max(nums[left], output[0], output[1]) ||
25 | nums[right] === Math.max(nums[right], output[0], output[1])) {
26 | output = [left, right];
27 | }
28 | } else {
29 | output = [left, right];
30 | }
31 | }
32 |
33 | if (nums[left] + nums[right] > target) {
34 | right--;
35 | } else {
36 | left++;
37 | }
38 | }
39 |
40 | return output;
41 | }
--------------------------------------------------------------------------------
/FE-JS-Questions/DeepFilter.md:
--------------------------------------------------------------------------------
1 | ## Deep Filter
2 |
3 | > Given an object and a filter function, write a function that will go through and filter the object, then return a filtered object
4 |
5 | ```
6 | Example 1
7 | Input Object
8 |
9 | {
10 | a: 1,
11 | b: {
12 | c: 2,
13 | d: -3,
14 | e: {
15 | f: {
16 | g: -4,
17 | },
18 | },
19 | h: {
20 | i: 5,
21 | j: 6,
22 | },
23 | }
24 | Input Function
25 | const filter = (n) => n >= 0
26 |
27 | Output
28 |
29 | { a: 1, b: { c: 2, h: { i: 5, j: 6 } } }
30 | ```
31 |
32 | ```js
33 | const filter = (n) => n >= 0;
34 | let inputObj = {
35 | 'a': 1,
36 | 'b': {
37 | 'c': 2,
38 | 'd': -3,
39 | 'e': {
40 | 'f': {
41 | 'g': -4,
42 | },
43 | },
44 | 'h': {
45 | 'i': 5,
46 | 'j': 6,
47 | },
48 | }
49 | }
50 |
51 | const deepFilter = (inputObject, callbackFilterFn) => {
52 |
53 | for (let key in inputObject) {
54 | if (typeof inputObject[key] === 'object') {
55 | deepFilter(inputObject[key], callbackFilterFn);
56 | if (Object.keys(inputObject[key]).length === 0) {
57 | delete inputObject[key];
58 | }
59 | } else {
60 | if (!callbackFilterFn(inputObject[key])) {
61 | delete inputObject[key];
62 | }
63 | }
64 | }
65 |
66 | return inputObject;
67 | }
68 |
69 | deepFilter(inputObj, filter);
70 | ```
--------------------------------------------------------------------------------
/exercises/arrays/searchRange.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value.
3 |
4 | Your algorithm's runtime complexity must be in the order of O(log n).
5 |
6 | If the target is not found in the array, return [-1, -1].
7 |
8 | Example 1:
9 |
10 | Input: nums = [5,7,7,8,8,10], target = 8
11 | Output: [3,4]
12 | Example 2:
13 |
14 | Input: nums = [5,7,7,8,8,10], target = 6
15 | Output: [-1,-1]
16 | */
17 |
18 | const findExtremeIndex = (nums, target, findLeft) => {
19 | let left = 0;
20 | let right = nums.length;
21 |
22 | while (left < right) {
23 | let mid = Math.floor((left + right) / 2);
24 |
25 | if (target < nums[mid] || (findLeft && target === nums[mid])) {
26 | right = mid;
27 | } else {
28 | left = mid + 1;
29 | }
30 | }
31 |
32 | return left;
33 | }
34 |
35 | const searchRange = (nums, target) => {
36 | let result = [-1, -1];
37 |
38 | const leftExtremeIndex = findExtremeIndex(nums, target, true);
39 |
40 | if (leftExtremeIndex === nums.length || nums[leftExtremeIndex] !== target) {
41 | return result;
42 | }
43 |
44 | result[0] = leftExtremeIndex;
45 | result[1] = findExtremeIndex(nums, target, false) - 1;
46 |
47 | return result;
48 | }
--------------------------------------------------------------------------------
/exercises/strings/reverseString2.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an input string , reverse the string word by word.
3 |
4 | Example:
5 |
6 | Input: ["t","h","e"," ","s","k","y"," ","i","s"," ","b","l","u","e"]
7 | Output: ["b","l","u","e"," ","i","s"," ","s","k","y"," ","t","h","e"]
8 | Note:
9 |
10 | A word is defined as a sequence of non-space characters.
11 | The input string does not contain leading or trailing spaces.
12 | The words are always separated by a single space.
13 | */
14 |
15 |
16 | // All of them must be a single instance of s (like s is a property of the class)
17 | const reverse = (str, left, right) => {
18 | while (left < right) {
19 | [str[left], str[right]] = [str[right], str[left]];
20 | left++;
21 | right--;
22 | }
23 | }
24 |
25 | const reverseEachWord = str => {
26 | let start = 0, end = 0;
27 | let n = str.length;
28 |
29 | while (start < n) {
30 | while(end < n && str[end] !== ' ') {
31 | end++;
32 | }
33 | reverse(str, start, end - 1);
34 | start = end + 1;
35 | end++;
36 | }
37 | }
38 |
39 | const reverseWords = s => {
40 | // reverse the string
41 | reverse(s, 0, s.length - 1);
42 | // reverse each word
43 | reverseEachWord(s);
44 | }
45 |
46 | /**
47 | * Time Complexity: O(N);
48 | * Space Complexity: O(1);
49 | */
--------------------------------------------------------------------------------
/exercises/trees/maxPathSumBinaryTree.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a non-empty binary tree, find the maximum path sum.
3 |
4 | For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections.
5 | The path must contain at least one node and does not need to go through the root.
6 |
7 | Example 1:
8 |
9 | Input: [1,2,3]
10 |
11 | 1
12 | / \
13 | 2 3
14 |
15 | Output: 6
16 | Example 2:
17 |
18 | Input: [-10,9,20,null,null,15,7]
19 |
20 | -10
21 | / \
22 | 9 20
23 | / \
24 | 15 7
25 |
26 | Output: 42
27 | */
28 |
29 | class TreeNode {
30 | constructor(val) {
31 | this.val = val;
32 | this.left = null;
33 | this.right = null;
34 | }
35 | }
36 |
37 | let maxSum;
38 |
39 | const maxGain = node => {
40 | if (!node) {
41 | return Number.NEGATIVE_INFINITY;
42 | }
43 |
44 | let leftGain = Math.max(maxGain(node.left), 0);
45 | let rightGain = Math.max(maxGain(node.right), 0);
46 |
47 | let newPathMax = node.val + leftGain + rightGain;
48 |
49 | maxSum = Math.max(maxSum, newPathMax);
50 |
51 | return node.val + Math.max(leftGain, rightGain);
52 | }
53 | const maxPathSum = root => {
54 | maxSum = Number.NEGATIVE_INFINITY;
55 |
56 | maxGain(root);
57 |
58 | return maxSum;
59 | }
60 |
--------------------------------------------------------------------------------
/concepts/Debounce.md:
--------------------------------------------------------------------------------
1 | ## DEBOUNCE
2 |
3 | Debouncing is a programming practice, which ensures time consuming tasks do not fire so often, that it affects the browser performance and the performance of the webpage. It limits the rate at which function gets invoked.
4 |
5 | ```js
6 | // Sample debounce function
7 |
8 | const debounce = (func, delay) => {
9 | let debounceTimer;
10 |
11 | return function() {
12 | const context = this;
13 | const arg = arguments;
14 | clearTimeout(debounceTimer);
15 |
16 | debounceTimer = setTimeout(() => {
17 | func.apply(context, arg);
18 | }, delay);
19 | }
20 | }
21 |
22 | const button = document.getElementById('debouncedButton');
23 |
24 | button.addEventListener('click', debounce(function() {
25 | console.log('I am a debounced button and no matter how many times I am clicked, I only get executed once every 3 seconds');
26 | }, 3000));
27 | ```
28 |
29 | The debounce function returns a function, which uses a debounceTimer to call the passed function after a delay.
30 |
31 | If the debounce button is clicked once, the function is called after the delay. However, if the button is clicked again, before the delay has completed, the timer is reset to the specified delay and then called after the timeout. Thus every time the debounce function is called, the timer is reset and the call is delayed.
--------------------------------------------------------------------------------
/exercises/arrays/rotateImage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * You are given an n x n 2D matrix representing an image.
3 |
4 | Rotate the image by 90 degrees (clockwise).
5 |
6 | Note:
7 |
8 | You have to rotate the image in-place, which means you have to modify the
9 | input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.
10 |
11 | Example 1:
12 |
13 | Given input matrix =
14 | [
15 | [1,2,3],
16 | [4,5,6],
17 | [7,8,9]
18 | ],
19 |
20 | rotate the input matrix in-place such that it becomes:
21 | [
22 | [7,4,1],
23 | [8,5,2],
24 | [9,6,3]
25 | ]
26 | Example 2:
27 |
28 | Given input matrix =
29 | [
30 | [ 5, 1, 9,11],
31 | [ 2, 4, 8,10],
32 | [13, 3, 6, 7],
33 | [15,14,12,16]
34 | ],
35 |
36 | rotate the input matrix in-place such that it becomes:
37 | [
38 | [15,13, 2, 5],
39 | [14, 3, 4, 1],
40 | [12, 6, 8, 9],
41 | [16, 7,10,11]
42 | ]
43 | */
44 |
45 | const rotate = matrix => {
46 | const step = matrix.length - 1;
47 |
48 | for (let i = 0; i < (matrix.length / 2); i++) {
49 | for (let j = 0; j < (matrix.length - 1) / 2; j++) {
50 | let temp = matrix[i][j];
51 | matrix[i][j] = matrix[step - j][i];
52 | matrix[step - j][i] = matrix[step - i][step - j];
53 | matrix[step - i][step - j] = matrix[j][step - i];
54 | matrix[j][step - i] = temp;
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/exercises/strings/isIsomorphic.js:
--------------------------------------------------------------------------------
1 | // Check if a given string is a isomorphic
2 | // For two strings to be isomorphic, all occurrences of a character in string A can be replaced with another character
3 | // to get string B. The order of the characters must be preserved. There must be one-to-one mapping for ever char of
4 | // string A to every char of string B.
5 | //
6 | // `paper` and `title` would return true.
7 | // `egg` and `sad` would return false.
8 | // `dgg` and `add` would return true.
9 | //
10 | // isIsomorphic("egg", 'add'); // true
11 | // isIsomorphic("paper", 'title'); // true
12 | // isIsomorphic("kick", 'side'); // false
13 |
14 | function isIsomorphic(stringA, stringB) {
15 |
16 | if(stringA.length !== stringB.length) {
17 | return false;
18 | }
19 |
20 | const charMap = {};
21 | let charA = '';
22 | let charB = '';
23 | // If a charMap does not exist, create a charMap with charA as key and charB as value
24 | for (let i = 0; i < stringA.length; i++) {
25 | charA = stringA[i];
26 | charB = stringB[i];
27 |
28 | if (!charMap[charA]) {
29 | // Else if charA already exists in the map, but it does not map to
30 | // charB, that means that charA is mapping to more than one letter.
31 | charMap[charA] = charB;
32 | } else if (charMap[charA] !== charB) {
33 | return false;
34 | }
35 | }
36 |
37 | return true;
38 | }
39 |
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/kDistinct.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a string s and an int k, return an int representing the number of substrings
3 | * (not unique) of s with exactly k distinct characters.
4 | * If the given string doesn't have k distinct characters, return 0.
5 | *
6 | * Eg:
7 | * Input: s = "pqpqs", k = 2
8 | Output: 7
9 | Explanation: ["pq", "pqp", "pqpq", "qp", "qpq", "pq", "qs"]
10 |
11 | Input: s = "aabab", k = 3
12 | Output: 0
13 |
14 | Constraints:
15 | The input string consists of only lowercase English letters [a-z]
16 | 0 ≤ k ≤ 26
17 | */
18 |
19 | const findKDistinct = (A, K) => {
20 | const atMost = k => {
21 | let left = 0;
22 | let result = 0;
23 | const count = {};
24 |
25 | for (let right = 0; right < A.length; right++) {
26 | if (count[A[right]] == null) {
27 | count[A[right]] = 0;
28 | }
29 |
30 | if (count[A[right]] === 0) {
31 | k--;
32 | }
33 | count[A[right]]++
34 |
35 | while (k < 0) {
36 | count[A[left]]--;
37 | if (count[A[left]] === 0) {
38 | k++;
39 | }
40 | left++;
41 | }
42 | result += right - left + 1;
43 | }
44 |
45 | return result;
46 | }
47 |
48 | return atMost(K) - atMost(K - 1);
49 | }
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/kDistinctStringsOfSizeK.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a string s and an int k, return all unique substrings of s of size k with k
3 | * distinct characters.
4 | *
5 | * Example 1:
6 |
7 | Input: s = "abcabc", k = 3
8 | Output: ["abc", "bca", "cab"]
9 | Example 2:
10 |
11 | Input: s = "abacab", k = 3
12 | Output: ["bac", "cab"]
13 | Example 3:
14 |
15 | Input: s = "awaglknagawunagwkwagl", k = 4
16 | Output: ["wagl", "aglk", "glkn", "lkna", "knag", "gawu", "awun", "wuna", "unag", "nagw", "agwk", "kwag"]
17 | Explanation:
18 | Substrings in order are: "wagl", "aglk", "glkn", "lkna", "knag", "gawu", "awun", "wuna", "unag", "nagw", "agwk", "kwag", "wagl"
19 | "wagl" is repeated twice, but is included in the output once.
20 | */
21 |
22 |
23 | const findKDistinctOfSizeK = (str, k) => {
24 | const set = new Set();
25 | const map = {};
26 |
27 | let left = 0;
28 |
29 | for (let right = 0; right < str.length; right++) {
30 | if (map[str[right]] === null) {
31 | map[str[right]] = 0;
32 | }
33 | map[str[right]]++;
34 | while (map[str[right]] > 1) {
35 | map[str[left]]--;
36 | left++;
37 | }
38 | if (right - left + 1 === k) {
39 | set.add(str.slice(left, right + 1));
40 | map[str[left]]--;
41 | left++;
42 | }
43 | }
44 |
45 | return Array.from(set);
46 | }
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/search2DMatrix.js:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Write an efficient algorithm that searches for a value in an m x n matrix.
4 | * This matrix has the following properties:
5 | *
6 | * Integers in each row are sorted in ascending from left to right.
7 | *
8 | * Integers in each column are sorted in ascending from top to bottom.
9 | Example:
10 |
11 | Consider the following matrix:
12 |
13 | [
14 | [1, 4, 7, 11, 15],
15 | [2, 5, 8, 12, 19],
16 | [3, 6, 9, 16, 22],
17 | [10, 13, 14, 17, 24],
18 | [18, 21, 23, 26, 30]
19 | ]
20 | Given target = 5, return true.
21 |
22 | Given target = 20, return false.
23 | */
24 |
25 | const searchMatrix = (matrix, target) => {
26 | const binarySearch = (row, target) => {
27 | let start = 0;
28 | let end = row.length - 1;
29 |
30 | while (start <= end) {
31 | let midPoint = Math.floor((start + end) / 2);
32 |
33 | if (target === row[midPoint]) {
34 | return true;
35 | } else if (target <= row[midPoint]) {
36 | end = midPoint - 1;
37 | } else {
38 | start = midPoint + 1;
39 | }
40 | }
41 |
42 | return false;
43 | }
44 |
45 | for (let row of matrix) {
46 | if (binarySearch(matrix[row], target)) {
47 | return true;
48 | }
49 | }
50 |
51 | return false;
52 | }
--------------------------------------------------------------------------------
/exercises/arrays/removeDuplicateContacts.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a list of Contacts, where each contact consists of a contact ID and a list of email IDs.
3 | * Output a unique list of contacts by removing duplicates. Two contacts are considered to be the same,
4 | * if they share at least one email ID.
5 | *
6 | * [
7 | * [
8 | * 'Andy': ['andy@linkedin.com', 'andy@outlook.com']
9 | * ],
10 | * [
11 | * 'Andy1': ['andy@linkedin.com', 'andy@gmail.com']
12 | * ],
13 | * [
14 | * 'Andy Work': [ 'andy@outlook.com' ]
15 | * ],
16 | * [
17 | * 'Bob': [ 'bob@outlook.com' ]
18 | * ],
19 | * [
20 | * 'Bob1': [ 'andy@outlook.com', 'bob@linkedin.com' ]
21 | * ]
22 | * ]
23 | *
24 | * Output: [ ['Andy', 'Andy1', 'Andy Work']
25 | * ['Bob', 'Bob1']
26 | * ]
27 | */
28 |
29 | const removeDuplicates = contacts => {
30 | const emails = new Map();
31 | const result = [];
32 |
33 | for (let contact of contacts) {
34 | for (let name in contact) {
35 | let emailArray = contact[name];
36 |
37 | for (let email of emailArray) {
38 | if (emails.has(email)) {
39 | // merge the contact
40 |
41 | } else {
42 | emails.set(email, [name])
43 | }
44 | }
45 | }
46 | }
47 | }
48 |
49 | const merge = (result, name) => {
50 | if (!result.length) {
51 | result.push[[name]];
52 | } else {
53 | for (let values of result) {
54 |
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/exercises/misc/fib.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Print out the n-th entry in the fibonacci series.
3 | // The fibonacci series is an ordering of numbers where
4 | // each number is the sum of the preceeding two.
5 | // For example, the sequence
6 | // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34]
7 | // forms the first ten entries of the fibonacci series.
8 | // Example:
9 | // fib(4) === 3
10 |
11 |
12 | // Function with Runtime Complexity of O(n) -> Linear Complexity
13 | function fib(n) {
14 | const results = [0, 1];
15 |
16 | for (let i = 2; i <= n; i++) {
17 | const a = results[i - 1];
18 | const b = results[i - 2];
19 |
20 | results.push(a + b);
21 | }
22 |
23 | return results[n];
24 | }
25 |
26 | // Function with recursive solution and exponential Complexity
27 | function fib(n) {
28 | if (n < 2) {
29 | return n;
30 | }
31 |
32 | return fib(n - 1) + fib(n - 2);
33 | }
34 |
35 | // Function using memoization to reduce runtime Complexity
36 | function memoize(fn) {
37 | const cache = {};
38 |
39 | return function(...args) {
40 | if (cache[args]) {
41 | return cache[args];
42 | }
43 |
44 | const result = fn.apply(this, args);
45 | cache[args] = result;
46 |
47 | return result;
48 | };
49 | }
50 |
51 | function slowFib(n) {
52 | if (n < 2) {
53 | return n;
54 | }
55 |
56 | return fib(n - 1) + fib(n - 2);
57 | }
58 |
59 | const fib = memoize(slowFib);
60 |
--------------------------------------------------------------------------------
/exercises/trees/tree.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // 1) Create a node class. The constructor
3 | // should accept an argument that gets assigned
4 | // to the data property and initialize an
5 | // empty array for storing children. The node
6 | // class should have methods 'add' and 'remove'.
7 | // 2) Create a tree class. The tree constructor
8 | // should initialize a 'root' property to null.
9 | // 3) Implement 'traverseBF' and 'traverseDF'
10 | // on the tree class. Each method should accept a
11 | // function that gets called with each element in the tree
12 |
13 | class Node {
14 | constructor(data) {
15 | this.data = data;
16 | this.children = [];
17 | }
18 |
19 | add(data) {
20 | this.children.push(new Node(data));
21 | }
22 |
23 | remove(data) {
24 | this.children = this.children.filter( node => {
25 | return node.data !== data;
26 | });
27 | }
28 | }
29 |
30 | class Tree {
31 | constructor() {
32 | this.root = null;
33 | }
34 |
35 | traverseBF(fn) {
36 | const arr = [this.root];
37 |
38 | while (arr.length) {
39 | const node = arr.shift();
40 |
41 | arr.push(...node.children);
42 | fn(node);
43 | }
44 | }
45 |
46 | traverseDF(fn) {
47 | const arr = [this.root];
48 |
49 | while (arr.length) {
50 | const node = arr.shift();
51 |
52 | arr.unshift(...node.children);
53 | fn(node);
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/FE-JS-Questions/InfiniteScroll.md:
--------------------------------------------------------------------------------
1 | ## Infinite Scroll
2 | > Implement Infinite Scroll in JS
3 |
4 | ```js
5 | /**
6 | * API Docs
7 | * ---------
8 | * /posts?page=0 => [{id: 1, title: "Post 1"}, {id: 2, title: "Post 2"}, {id: 3, title: "Post 3"}, N...]
9 | * /posts?page=1 => [{id: 4, title: "Post 4"}, {id: 5, title: "Post 5"}, {id: 6, title: "Post 6"}, N...]
10 | * /posts?page=N => [N...]
11 | */
12 | ```
13 |
14 | ```html
15 |
16 | ```
17 |
18 | ```css
19 | .infiniteList {
20 | height: 200px;
21 | width: 200px;
22 | overflow: auto;
23 | margin: 30px;
24 | padding: 20px;
25 | border: 5px solid black;
26 | }
27 |
28 | li {
29 | padding: 10px;
30 | list-style-type: none;
31 | }
32 |
33 | li:hover {
34 | background: #ccc;
35 | }
36 | ```
37 |
38 | ```js
39 | const listElements = document.querySelector(".infiniteList");
40 | let nextItem = 1;
41 |
42 | const loadMoreItems = () => {
43 | const postsRetrieved = [];
44 |
45 | // make API call
46 | getPosts().then(posts => {
47 | postsRetrieved = posts.map(post => {
48 | return `${post.title}`;
49 | });
50 | });
51 |
52 | listElements.innerHTML = postsRetrieved.join('');
53 | };
54 |
55 | listElements.addEventListener('scroll', () => {
56 | if (listElements.scrollTop + listElements.clientHeight >= listElements.scrollHeight) {
57 | loadMoreItems();
58 | }
59 | });
60 |
61 | loadMoreItems();
62 | ```
--------------------------------------------------------------------------------
/exercises/linkedlist/oddEvenLinkedList.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a singly linked list, group all odd nodes together followed by the even nodes.
3 | * Please note here we are talking about the node number and not the value in the nodes.
4 | *
5 | * You should try to do it in place.
6 | * The program should run in O(1) space complexity and O(nodes) time complexity.
7 |
8 | Example 1:
9 |
10 | Input: 1->2->3->4->5->NULL
11 | Output: 1->3->5->2->4->NULL
12 | Example 2:
13 |
14 | Input: 2->1->3->5->6->4->7->NULL
15 | Output: 2->3->6->7->1->5->4->NULL
16 | Note:
17 |
18 | The relative order inside both the even and odd groups should remain as it was in the input.
19 | The first node is considered odd, the second node even and so on ...
20 | */
21 |
22 | /**
23 | * Definition for singly-linked list.
24 | * function ListNode(val) {
25 | * this.val = val;
26 | * this.next = null;
27 | * }
28 | */
29 | /**
30 | * @param {ListNode} head
31 | * @return {ListNode}
32 | */
33 | const oddEvenLinkedList = head => {
34 |
35 | if (!head) {
36 | return null;
37 | }
38 |
39 | let odd = head;
40 | let even = head.next;
41 | let evenHead = even;
42 |
43 | while (even !== null && even.next !== null) {
44 | odd.next = even.next;
45 | odd = odd.next;
46 | even.next = odd.next;
47 | even = even.next;
48 | }
49 |
50 | odd.next = evenHead;
51 | return head;
52 | }
--------------------------------------------------------------------------------
/exercises/trees/binarySearchTree.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // 1) Implement the Node class to create
3 | // a binary search tree. The constructor
4 | // should initialize values 'data', 'left',
5 | // and 'right'.
6 | // 2) Implement the 'insert' method for the
7 | // Node class. Insert should accept an argument
8 | // 'data', then create an insert a new node
9 | // at the appropriate location in the tree.
10 | // 3) Implement the 'contains' method for the Node
11 | // class. Contains should accept a 'data' argument
12 | // and return the Node in the tree with the same value.
13 |
14 |
15 | class Node {
16 | constructor(data) {
17 | this.data = data;
18 | this.left = null;
19 | this.right = null;
20 | }
21 |
22 | insert(data) {
23 | if (data < this.data && this.left) {
24 | this.left.insert(data);
25 | } else if (data < this.data) {
26 | this.left = new Node(data);
27 | } else if (data > this.data && this.right) {
28 | this.right.insert(data);
29 | } else if (data > this.data) {
30 | this.right = new Node(data);
31 | }
32 | }
33 |
34 | contains(data) {
35 | if (data === this.data) {
36 | return this;
37 | }
38 |
39 | if (data < this.data && this.left) {
40 | return this.left.contains(data);
41 | } else if (data > this.data && this.right) {
42 | return this.right.contains(data);
43 | }
44 |
45 | return null;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/FE-JS-Questions/throtlle.md:
--------------------------------------------------------------------------------
1 | ## Design a Throttler
2 |
3 | > Implement a throttler that executes an array of tasks. When the throttler is passed a number, only execute that number of the tasks and passes the other tasks into a queue.This problem has a stackoverflow post from a year ago : https://stackoverflow.com/questions/49826332/simple-task-runner-in-javascript-with-waiting?rq=1
4 |
5 | ```js
6 | class Runner {
7 | constructor(concurrent) {
8 | this.taskQueue = []; //this should have "concurrent" number of tasks running at any given time
9 |
10 | }
11 |
12 | push(task) {
13 | /* pushes to the queue and then runs the whole queue */
14 | }
15 | }
16 | ```
17 | The calling pattern would be:
18 | ```js
19 | let runner = new Runner(3);
20 | runner.push(task1);
21 | runner.push(task2);
22 | runner.push(task3);
23 | runner.push(task4);
24 | ```
25 |
26 | ```js
27 | class Runner {
28 | constructor(concurrent) {
29 | this.maxCount = concurrent;
30 | this.taskQueue = [];
31 | this.runningCount = 0;
32 | }
33 |
34 | notifyTaskEnd() {
35 | this.runningCount--;
36 | this.run();
37 | }
38 |
39 | run() {
40 | while (this.taskQueue.length && (this.runningCount < this.maxCount)) {
41 | this.runningCount++;
42 | const currentTask = this.taskQueue.shift();
43 |
44 | currentTask(this.notifyTaskEnd);
45 | }
46 | }
47 |
48 | push(task) {
49 | this.taskQueue.push(task);
50 | this.run();
51 | }
52 | }
53 | ```
--------------------------------------------------------------------------------
/concepts/Callbacks.md:
--------------------------------------------------------------------------------
1 | # CALLBACKS
2 |
3 | ### MAP
4 |
5 | ```js
6 | function map(array, callback) {
7 | const output = [];
8 | for (let element of array) {
9 | output.push(callback(element));
10 | }
11 | return output;
12 | }
13 | ```
14 |
15 | ### FOR EACH
16 |
17 | ```js
18 | function forEach(array, callback) {
19 | for (let element of array) {
20 | callback(element);
21 | }
22 | }
23 | ```
24 |
25 | ### REDUCE
26 |
27 | ```js
28 | function reduce(array, callback, initialValue) {
29 | array.forEach(element => initialValue += callback(element));
30 |
31 | return initialValue;
32 | }
33 | ```
34 |
35 | ### INTERSECTION
36 |
37 | ```js
38 | function intersection(arrays) {
39 | return arrays.reduce(intersectionReducer);
40 | }
41 |
42 | function intersectionReducer(accumulator, currentValue) {
43 | return accumulator.filter(element => currentValue.includes(element));
44 | }
45 | ```
46 |
47 | ### UNION
48 |
49 | ```js
50 | function union(arrays) {
51 | return arrays.reduce(unionReducer);
52 | }
53 |
54 | function unionReducer(accumulator, currentValue) {
55 | return [...new Set([...accumulator, ...currentValue])];
56 | }
57 | ```
58 |
59 | ```js
60 | // What happens when we call "new" keyword behind the scenes
61 |
62 | var obj = new Foo();
63 |
64 | // translates to
65 |
66 | var obj = new Object();
67 | obj.[[Prototype]] = Foo.prototype;
68 | Foo.call(o);
69 | ```
70 |
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/minCostToConnect.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given n ropes of different lengths, we need to connect these ropes into one rope.
3 | * We can connect only 2 ropes at a time.
4 | * The cost required to connect 2 ropes is equal to sum of their lengths.
5 | * The length of this connected rope is also equal to the sum of their lengths.
6 | * This process is repeated until n ropes are connected into a single rope.
7 | * Find the min possible cost required to connect all ropes.
8 | *
9 | * Eg:
10 | * Input: ropes = [8, 4, 6, 12]
11 | Output: 58
12 | Explanation: The optimal way to connect ropes is as follows
13 | 1. Connect the ropes of length 4 and 6 (cost is 10). Ropes after connecting: [8, 10, 12]
14 | 2. Connect the ropes of length 8 and 10 (cost is 18). Ropes after connecting: [18, 12]
15 | 3. Connect the ropes of length 18 and 12 (cost is 30).
16 | Total cost to connect the ropes is 10 + 18 + 30 = 58
17 |
18 | Input: ropes = [20, 4, 8, 2]
19 | Output: 54
20 |
21 | Input: ropes = [1, 2, 5, 10, 35, 89]
22 | Output: 224
23 |
24 | Input: ropes = [2, 2, 3, 3]
25 | Output: 20
26 | */
27 |
28 | const minCostToConnect = ropes => {
29 | let minCost = 0;
30 |
31 | while (ropes.length > 1) {
32 | ropes.sort((a, b) => a - b);
33 |
34 | let sum = ropes.shift();
35 | sum += ropes.shift();
36 |
37 | minCost += sum;
38 | ropes.push(sum);
39 | }
40 |
41 | return minCost;
42 | }
--------------------------------------------------------------------------------
/exercises/misc/pyramid.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Write a function that accepts a positive number N.
3 | // The function should console log a pyramid shape
4 | // with N levels using the # character. Make sure the
5 | // pyramid has spaces on both the left *and* right hand sides
6 | // --- Examples
7 | // pyramid(1)
8 | // '#'
9 | // pyramid(2)
10 | // ' # '
11 | // '###'
12 | // pyramid(3)
13 | // ' # '
14 | // ' ### '
15 | // '#####'
16 |
17 | function pyramid(n) {
18 | const midPoint = Math.floor((2 * n - 1) / 2);
19 |
20 | for (let row = 0; row < n; row++) {
21 | let level = '';
22 |
23 | for (let columns = 0; columns < (2 * n - 1); columns++) {
24 | if (midPoint - row <= columns && midPoint + row >= columns) {
25 | level += '#';
26 | } else {
27 | level += ' ';
28 | }
29 | }
30 | console.log(level);
31 | }
32 | }
33 |
34 |
35 | // Recursove soliution
36 | function pyramid(n, row = 0; level = '') {
37 | if (n === row) {
38 | return;
39 | }
40 |
41 | if (level.length === (2 * n - 1)) {
42 | console.log(level);
43 | return pyramid(n, row + 1);
44 | }
45 |
46 | const midPoint = Math.floor((2 * n -1) / 2);
47 | let add = '';
48 |
49 | if (midPoint - row <= level.length && midPoint + row >= level.length) {
50 | add += '#';
51 | } else {
52 | add += ' ';
53 | }
54 |
55 | pyramid(n, row, level + add);
56 | }
57 |
--------------------------------------------------------------------------------
/exercises/strings/smallestCharacter.js:
--------------------------------------------------------------------------------
1 | // find the smallest character in each string
2 | // find frequency of smallest character in each string
3 | // loop over strings in B and see if frequency if i-th string is greater strings in A
4 |
5 | const compareStrings = (A, B) => {
6 | const findSmallestChar = string => {
7 | let smallestChar = 'z';
8 |
9 | for (let char of string) {
10 | if (char < smallestChar) {
11 | smallestChar = char;
12 | }
13 | }
14 |
15 | return smallestChar;
16 | }
17 |
18 | const findFrequency = (char, string) => {
19 | let counter = 0;
20 |
21 | for (let c of string) {
22 | if (c === char) {
23 | counter++;
24 | }
25 | }
26 |
27 | return counter;
28 | }
29 |
30 | const result = [];
31 | let count = 0;
32 |
33 | let arrA = A.split(' ');
34 | let arrB = B.split(' ');
35 | for (let stringB of arrB) {
36 | let stringBMinCount = findFrequency(findSmallestChar(stringB), stringB);
37 |
38 | for (let stringA of arrA) {
39 | let stringAMinCount = findFrequency(findSmallestChar(stringA), stringA)
40 |
41 | if (stringAMinCount < stringBMinCount) {
42 | count++;
43 | }
44 | }
45 |
46 | result.push(count);
47 | count = 0;
48 | }
49 |
50 | return result;
51 | }
--------------------------------------------------------------------------------
/exercises/stacks&queues/readme.md:
--------------------------------------------------------------------------------
1 | ### STACKS
2 |
3 | * Stacks are similar to lists in the fact that they have an order. Stacks are limited to pushing and popping values at the end of the list, which are very fast operations when mapping directly to memory.
4 |
5 | ```js
6 | class Stack {
7 | constructor() {
8 | this.list = [];
9 | this.length = 0;
10 | }
11 |
12 | push(value) {
13 | this.length++;
14 | this.list.push(value);
15 | }
16 |
17 | pop() {
18 | if (this.length === 0) {
19 | console.log("No elements in stack to pop");
20 | return ;
21 | }
22 | this.length--;
23 | return this.list.pop();
24 | }
25 |
26 | peek() {
27 | return this.list[this.length - 1];
28 | }
29 | }
30 | ```
31 |
32 | ### QUEUES
33 |
34 | Queues are complimentary to stacks. In this type of DS, elements are removed from the start. The oldest element is removed first.
35 |
36 | ```js
37 | class Queue {
38 | constructor() {
39 | this.list = [];
40 | this.length = 0;
41 | }
42 |
43 | enqueue(value) {
44 | this.list.push(value);
45 | this.length++;
46 | }
47 |
48 | dequeue() {
49 | if (this.length === 0) {
50 | return;
51 | }
52 |
53 | this.length--;
54 | return this.list.shift();
55 | }
56 |
57 | peek() {
58 | return this.list[0];
59 | }
60 | }
61 | ```
--------------------------------------------------------------------------------
/exercises/sorting/findMedianSorted.js:
--------------------------------------------------------------------------------
1 | /**
2 | * There are two sorted arrays nums1 and nums2 of size m and n respectively.
3 | * Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
4 | You may assume nums1 and nums2 cannot be both empty.
5 |
6 | Example 1:
7 |
8 | nums1 = [1, 3]
9 | nums2 = [2]
10 |
11 | The median is 2.0
12 | Example 2:
13 |
14 | nums1 = [1, 2]
15 | nums2 = [3, 4]
16 |
17 | The median is (2 + 3)/2 = 2.5
18 | */
19 |
20 | const findMedianSortedArrays = (nums1, nums2) => {
21 | let a = 0;
22 | let b = 0;
23 | const totalLength = nums1.length + nums2.length;
24 | const result = [];
25 |
26 | for (let i = 0; i < totalLength; i++) {
27 | if (a < nums1.length && b < nums2.length) {
28 | if (nums1[a] < nums2[b]) {
29 | result[i] = nums1[a];
30 | a++;
31 | } else {
32 | result[i] = nums2[b];
33 | b++;
34 | }
35 | } else {
36 | if (a < nums1.length) {
37 | result[i] = nums1[a];
38 | a++;
39 | } else {
40 | result[i] = nums2[b];
41 | b++;
42 | }
43 | }
44 | }
45 |
46 | let medIdx = Math.floor(result.length / 2);
47 |
48 | if (result.length % 2 === 0) {
49 | return (result[medIdx] + result[medIdx - 1]) / 2;
50 | }
51 |
52 | return result[medIdx];
53 | }
--------------------------------------------------------------------------------
/exercises/leetcode/letterCombinations.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent.
3 |
4 | A mapping of digit to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters
5 |
6 | Example:
7 |
8 | Input: "23"
9 | Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
10 | */
11 |
12 | let output = [];
13 | const phoneNumberMap = new Map();
14 | phoneNumberMap.set("2", "abc");
15 | phoneNumberMap.set("3", "def");
16 | phoneNumberMap.set("4", "ghi");
17 | phoneNumberMap.set("5", "jkl");
18 | phoneNumberMap.set("6", "mno");
19 | phoneNumberMap.set("7", "pqrs");
20 | phoneNumberMap.set("8", "tuv");
21 | phoneNumberMap.set("9", "wxyz");
22 |
23 | const backtrack = (combination, nextDigits) => {
24 | if (nextDigits.length === 0) {
25 | output.push(combination);
26 | } else {
27 | let digit = nextDigits.substring(0, 1);
28 | let letters = phoneNumberMap.get(digit);
29 |
30 | for (let i = 0; i < letters.length; i++) {
31 | let letter = phoneNumberMap.get(digit).substring(i, i+1);
32 | backtrack(combination + letter, nextDigits.substring(1));
33 | }
34 | }
35 | }
36 |
37 | const letterCombinations = digits => {
38 | output = [];
39 | if (digits.length !== 0) {
40 | backtrack("", digits);
41 | }
42 |
43 | return output;
44 | }
45 |
46 | /**
47 | * Time Complexity: 3 ^ N x 4 ^ M
48 | * Space Complexity: 3 ^ N x 4 ^ M
49 | */
--------------------------------------------------------------------------------
/FE-JS-Questions/formatPhoneNumber.md:
--------------------------------------------------------------------------------
1 | ## Format Phone Number
2 |
3 | ```html
4 |
5 |
6 | Invalid Phone number format
7 |
8 | ```
9 |
10 | ```css
11 | .errorMessage {
12 | display: none;
13 | color: red;
14 | }
15 |
16 | .errorMessage .show {
17 | display: block;
18 | }
19 | ```
20 |
21 | ```js
22 | const phoneField = document.querySelector(".phoneNumber");
23 |
24 | function formatPhone(event) {
25 | const phoneInput = event.target.value;
26 | const validPhoneFormat = /(\(\d{3}\)?)-\d{3}-\d{4}/;
27 |
28 | if (phoneInput.length < 10) {
29 | const errorSpan = document.querySelector(".errorMessage");
30 | errorSpan.innerHTML = "Phone Number too short. Enter in this format: (###)-###-####";
31 |
32 | errorSpan.classList.add('show');
33 | return;
34 | }
35 |
36 | const isPhoneFormatted = validPhoneFormat.test(phoneInput);
37 |
38 | if (!isPhoneFormatted) {
39 | const phoneAreaCode = phoneInput.slice(0, 3);
40 | const phoneFirstThree = phoneInput.slice(3, 6);
41 | const phoneLastFour = phoneInput.slice(6, 10);
42 |
43 | event.target.value = `(${phoneAreaCode})-${phoneFirstThree}-${phoneLastFour}`;
44 | }
45 | }
46 |
47 | phoneField.addEventListener("change", formatPhone);
48 | phoneField.addEventListener("keyUp", formatPhone);
49 |
50 | // debounce can be added if event listener is added on input, to limit number of calls to format the phone
51 | ```
--------------------------------------------------------------------------------
/exercises/linkedlist/circularLinkedList.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Given a linked list, return true if the list
3 | // is circular, false if it is not.
4 | // --- Examples
5 | // const l = new List();
6 | // const a = new Node('a');
7 | // const b = new Node('b');
8 | // const c = new Node('c');
9 | // l.head = a;
10 | // a.next = b;
11 | // b.next = c;
12 | // c.next = b;
13 | // circular(l) // true
14 |
15 | // OR
16 | // Given a circular linked list, implement an algorithm which returns the node at
17 | // the beginning of the loop.
18 | // DEFINITION
19 | // Circular linked list: A (corrupt) linked list in which a node's next pointer points
20 | // to an earlier node, so as to make a loop in the linked list.
21 | // EXAMPLE
22 | // Input: A - > B - > C - > D - > E - > C [the same C as earlier]
23 | // Output: C
24 |
25 | function circular(list) {
26 | let slow = list.getFirst();
27 | let fast = list.getFirst();
28 |
29 | while(fast.next && fast.next.next) {
30 | slow = slow.next;
31 | fast = fast.next.next;
32 |
33 | if(slow === fast) {
34 | return true;
35 | }
36 |
37 | return false;
38 | }
39 | }
40 |
41 | function circularList(list) {
42 | let slow = list.head;
43 | let fast = list.head;
44 |
45 | while (fast.next && fast.next.next) {
46 | slow = slow.next;
47 | fast = fast.next.next;
48 |
49 | if (slow === fast) {
50 | return slow;
51 | }
52 | }
53 |
54 | return 'Not a circular Linked List';
55 | }
56 |
--------------------------------------------------------------------------------
/exercises/trees/populateNextRightPointer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * You are given a perfect binary tree where all leaves are on the same level, and every parent has two children.
3 | * The binary tree has the following definition:
4 |
5 | struct Node {
6 | int val;
7 | Node *left;
8 | Node *right;
9 | Node *next;
10 | }
11 | Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.
12 |
13 | Initially, all next pointers are set to NULL.
14 | */
15 |
16 | class Queue {
17 | constructor() {
18 | this.data = [];
19 | }
20 | add(val) {
21 | this.data.push(val);
22 | }
23 | remove() {
24 | return this.data.shift();
25 | }
26 | peek() {
27 | return this.data[0];
28 | }
29 | size() {
30 | this.data.length;
31 | }
32 | }
33 |
34 | const connect = root => {
35 | if (root === null) {
36 | return root;
37 | }
38 |
39 | // create a queue to push nodes from each level
40 | const queue = new Queue();
41 |
42 | queue.add(root);
43 | while (queue.size() > 0) {
44 | // we want to do BFS so we take the size of each level
45 | let size = queue.size();
46 |
47 | for (let i = 0; i < size; i++) {
48 | let node = queue.remove();
49 |
50 | if (i < size - 1) {
51 | node.next = queue.peek();
52 | }
53 |
54 | if (node.left !== null) {
55 | queue.add(node.left);
56 | }
57 |
58 | if (node.right !== null) {
59 | queue.add(node.right);
60 | }
61 | }
62 | }
63 |
64 | return root;
65 | }
--------------------------------------------------------------------------------
/checkboxes/checkboxes.md:
--------------------------------------------------------------------------------
1 | ## SELECT / UNSELECT ALL CHECKBOXES
2 |
3 | ```html
4 |
34 | ```
35 |
36 | ```js
37 | const selectAllButton = document.getElementById("selectAll");
38 |
39 | selectAllButton.addEventListener("click", function() {
40 | const checkboxes = document.querySelectorAll("input[type=checkbox]");
41 | // check if button has allChecked class
42 | if (selectAllButton.classList.contains("allChecked")) {
43 | checkboxes.forEach(checkbox => checkbox.checked = false);
44 | } else {
45 | checkboxes.forEach(checkbox => checkbox.checked = true);
46 | }
47 |
48 | selectAllButton.classList.toggle("allChecked");
49 | })
50 | ```
51 |
--------------------------------------------------------------------------------
/exercises/sorting/searchInRotatedSortedArray.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand.
3 | * (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]).
4 | * You are given a target value to search. If found in the array return its index, otherwise return -1.
5 | * You may assume no duplicate exists in the array.
6 | * Your algorithm's runtime complexity must be in the order of O(log n).
7 | * Example 1:
8 | Input: nums = [4,5,6,7,0,1,2], target = 0
9 | Output: 4
10 | [6,7,0,1,2,4,5]
11 | Example 2:
12 | Input: nums = [4,5,6,7,0,1,2], target = 3
13 | Output: -1
14 | * @param {array} nums
15 | * @param {int} target
16 | */
17 | const search = (nums, target) => {
18 | let start = 0;
19 | let end = nums.length - 1;
20 |
21 | while (start <= end) {
22 | let midPoint = Math.floor((start + end) / 2);
23 | if (nums[midPoint] === target) {
24 | return midPoint;
25 | } else if (nums[midPoint] > target) {
26 | if (target <= nums[end] && nums[end] < nums[midPoint]) {
27 | start = midPoint + 1;
28 | } else {
29 | end = midPoint - 1;
30 | }
31 | } else if (nums[midPoint] < target) {
32 | if (target >= nums[start] && nums[start] > nums[midPoint]) {
33 | end = midPoint - 1;
34 | } else {
35 | start = midPoint + 1;
36 | }
37 | }
38 | }
39 |
40 | return -1;
41 | }
--------------------------------------------------------------------------------
/exercises/arrays/chunk.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Given an array and chunk size, divide the array into many subarrays
3 | // where each subarray is of length size
4 | // --- Examples
5 | // chunk([1, 2, 3, 4], 2) --> [[ 1, 2], [3, 4]]
6 | // chunk([1, 2, 3, 4, 5], 2) --> [[ 1, 2], [3, 4], [5]]
7 | // chunk([1, 2, 3, 4, 5, 6, 7, 8], 3) --> [[ 1, 2, 3], [4, 5, 6], [7, 8]]
8 | // chunk([1, 2, 3, 4, 5], 4) --> [[ 1, 2, 3, 4], [5]]
9 | // chunk([1, 2, 3, 4, 5], 10) --> [[ 1, 2, 3, 4, 5]]
10 |
11 |
12 | function chunk(array, size) {
13 | // Declare an array to hold the chunked array
14 | const chunked = [];
15 |
16 | // Iterate over each element of the unchunked array
17 | for (let element of array) {
18 |
19 | // Find the last element of the chunked array
20 | const lastElement = chunked[chunked.length - 1];
21 |
22 | // if lastElement does not exist or its size is equal to chunk size, push a new chunk and the element to chunked array
23 | if (!lastElement || lastElement.length === size) {
24 | chunked.push([element]);
25 | } else {
26 | // Else push the element to the current chunk
27 | lastElement.push(element);
28 | }
29 | }
30 |
31 | return chunked;
32 | }
33 |
34 |
35 | // Using the slice method in subarray
36 |
37 | function chunk(array, size) {
38 | const chunked = [];
39 | let index = 0;
40 |
41 | while (index < array.length) {
42 | chunked.push(array.slice(index, index + size));
43 | index += size;
44 | }
45 |
46 | return chunked;
47 | }
48 |
--------------------------------------------------------------------------------
/exercises/arrays/removeDuplicates.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a sorted array nums, remove the duplicates in-place such that each element appear only once and return the new length.
3 |
4 | Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
5 |
6 | Example 1:
7 |
8 | Given nums = [1,1,2],
9 |
10 | Your function should return length = 2, with the first two elements of nums being 1 and 2 respectively.
11 |
12 | It doesn't matter what you leave beyond the returned length.
13 | Example 2:
14 |
15 | Given nums = [0,0,1,1,1,2,2,3,3,4],
16 |
17 | Your function should return length = 5, with the first five elements of nums being modified to 0, 1, 2, 3, and 4 respectively.
18 |
19 | It doesn't matter what values are set beyond the returned length.
20 | */
21 |
22 | const removeDuplicates = nums => {
23 | if (nums.length === 0) {
24 | return 0;
25 | }
26 |
27 | let i = 0;
28 | for (let j = 1; j < nums.length; j++) {
29 | if (nums[i] !== nums[j]) {
30 | i++;
31 | nums[i] = nums[j];
32 | }
33 | }
34 |
35 | return i + 1;
36 | }
37 |
38 | // To return the uniqueArray
39 |
40 | const removeDuplicatesAndReturnUnique = nums => {
41 | if (!nums.length) {
42 | return [];
43 | }
44 |
45 | let i = 0;
46 | const uniqueArray = [nums[0]];
47 |
48 | for (let j = 1; j < nums.length; j++) {
49 | if (nums[i] !== nums[j]) {
50 | uniqueArray.push(nums[j]);
51 | i++;
52 | nums[i] = nums[j];
53 | }
54 | }
55 |
56 | return uniqueArray;
57 | }
--------------------------------------------------------------------------------
/exercises/misc/matrix.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Write a function that accepts an integer N
3 | // and returns a NxN spiral matrix.
4 | // --- Examples
5 | // matrix(2)
6 | // [[1, 2],
7 | // [4, 3]]
8 | // matrix(3)
9 | // [[1, 2, 3],
10 | // [8, 9, 4],
11 | // [7, 6, 5]]
12 | // matrix(4)
13 | // [[1, 2, 3, 4],
14 | // [12, 13, 14, 5],
15 | // [11, 16, 15, 6],
16 | // [10, 9, 8, 7]]
17 |
18 |
19 | function matrix(n) {
20 | const results = [];
21 |
22 | for (let i = 0; i < n; i++) {
23 | results.push([]);
24 | }
25 |
26 | let counter = 1;
27 | let startRow = 0;
28 | let startColumn = 0;
29 | let endRow = n - 1;
30 | let endColumn = n - 1;
31 |
32 | while (startRow <= endRow && startColumn <= endColumn) {
33 | // Top Row
34 | for (let i = startColumn; i <= endColumn; i++) {
35 | results[startRow][i] = counter;
36 | counter++;
37 | }
38 | startRow++;
39 |
40 | // Right Column
41 | for (let i = startRow; i <= endRow; i++) {
42 | results[i][endColumn] = counter;
43 | counter++;
44 | }
45 | endColumn--;
46 |
47 | // Bottom row
48 | for (let i = endColumn; i >= startColumn; i--) {
49 | results[endRow][i] = counter;
50 | counter++;
51 | }
52 | endRow--;
53 |
54 | // Left Column
55 | for (let i = endRow; i >= startRow; i--) {
56 | results[i][startColumn] = counter;
57 | counter++;
58 | }
59 | startColumn++;
60 | }
61 |
62 | return results;
63 | }
64 |
--------------------------------------------------------------------------------
/exercises/arrays/jumpGame.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an array of non-negative integers, you are initially positioned at the first index of the array.
3 |
4 | Each element in the array represents your maximum jump length at that position.
5 |
6 | Your goal is to reach the last index in the minimum number of jumps.
7 |
8 | Example:
9 |
10 | Input: [2,3,1,1,4]
11 | Output: 2
12 | Explanation: The minimum number of jumps to reach the last index is 2.
13 | Jump 1 step from index 0 to 1, then 3 steps to the last index.
14 | Note:
15 |
16 | You can assume that you can always reach the last index.
17 | */
18 |
19 | const minJump = nums => {
20 | const jumpsArray = [0];
21 |
22 | for (let i = 1; i < nums.length; i++) {
23 | jumpsArray[i] = Number.MAX_SAFE_INTEGER;
24 | }
25 | for (let i = 1; i < nums.length; i++) {
26 | for (let j = 0; j < i; j++) {
27 | if (i <= j + nums[j]) {
28 | jumpsArray[i] = Math.min(jumpsArray[i], jumpsArray[j] + 1);
29 | }
30 | }
31 | }
32 |
33 | return jumpsArray[jumpsArray.length - 1];
34 | }
35 |
36 | // Optimal Solution
37 |
38 | const jump = nums => {
39 | if (nums.length < 2) {
40 | return 0;
41 | }
42 |
43 | let i = 0;
44 | let jumps = 0;
45 |
46 | while (i + nums[i] < nums.length - 1) {
47 | let maxVal = 0;
48 | let maxValIndex = 0;
49 |
50 | for (let j = 1; j <= nums[i]; j++) {
51 | if (nums [i + j] + j > maxVal) {
52 | maxVal = nums[i + j] + j;
53 | maxValIndex = i + j;
54 | }
55 | }
56 | i = maxValIndex;
57 | jumps++;
58 | }
59 |
60 | return jumps + 1;
61 | }
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/numberOfIslands.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a 2d grid map of '1's (land) and '0's (water),
3 | * count the number of islands. An island is surrounded by water
4 | * and is formed by connecting adjacent lands horizontally or vertically.
5 | * You may assume all four edges of the grid are all surrounded by water.
6 |
7 | Example 1:
8 |
9 | Input:
10 | 11110
11 | 11010
12 | 11000
13 | 00000
14 |
15 | Output: 1
16 | Example 2:
17 |
18 | Input:
19 | 11000
20 | 11000
21 | 00100
22 | 00011
23 |
24 | Output: 3
25 | */
26 |
27 | const numberOfIslands = grid => {
28 | let result = 0;
29 |
30 | const dx = [1, -1, 0, 0];
31 | const dy = [0, 0, 1, -1];
32 |
33 | const isLand = (x, y) => {
34 | return x > -1 && x < grid.length && y > -1 &&
35 | y < grid[0].length && grid[x][y] !== '0';
36 | }
37 |
38 | const removeIsland = (startX, startY) => {
39 | if (grid[startX][startY] === '0') {
40 | return 0;
41 | }
42 |
43 | grid[startX][startY] = '0';
44 | for (let k = 0; k < dx.length; k++) {
45 | let x = startX + dx[k];
46 | let y = startY + dy[k];
47 |
48 | if (isLand(x, y)) {
49 | result += removeIsland(x, y)
50 | }
51 | }
52 |
53 | return 1;
54 | }
55 |
56 | for (let i = 0; i < grid.length; i++) {
57 | for (let j = 0; j < grid[i].length; j++) {
58 | result += removeIsland(i, j);
59 | }
60 | }
61 |
62 | return result;
63 | }
--------------------------------------------------------------------------------
/exercises/arrays/setZeroes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a m x n matrix, if an element is 0, set its entire row and column to 0. Do it in-place.
3 |
4 | Example 1:
5 |
6 | Input:
7 | [
8 | [1,1,1],
9 | [1,0,1],
10 | [1,1,1]
11 | ]
12 | Output:
13 | [
14 | [1,0,1],
15 | [0,0,0],
16 | [1,0,1]
17 | ]
18 | Example 2:
19 |
20 | Input:
21 | [
22 | [0,1,2,0],
23 | [3,4,5,2],
24 | [1,3,1,5]
25 | ]
26 | Output:
27 | [
28 | [0,0,0,0],
29 | [0,4,5,0],
30 | [0,3,1,0]
31 | ]
32 | Follow up:
33 |
34 | A straight forward solution using O(mn) space is probably a bad idea.
35 | A simple improvement uses O(m + n) space, but still not the best solution.
36 | Could you devise a constant space solution?
37 | * @param {*} matrix
38 | */
39 |
40 | const setZeroes = matrix => {
41 | let isCol = false;
42 | const rows = matrix.length;
43 | const columns = matrix[0].length;
44 |
45 | for (let i = 0; i < rows; i++) {
46 | if (matrix[i][0] === 0) {
47 | isCol = true;
48 | }
49 |
50 | for (let j = 1; j < columns; j++) {
51 | if (matrix[i][j] === 0) {
52 | matrix[i][0] = 0;
53 | matrix[0][j] = 0;
54 | }
55 | }
56 | }
57 |
58 | for (let i = 1; i < rows; i++) {
59 | for (let j = 1; j < columns; j++) {
60 | if (matrix[i][0] === 0 || matrix[0][j] === 0) {
61 | matrix[i][j] = 0;
62 | }
63 | }
64 | }
65 |
66 | if (matrix[0][0] === 0) {
67 | for (let j = 0; j < columns; j++) {
68 | matrix[0][j] = 0;
69 | }
70 | }
71 |
72 | if (isCol) {
73 | for (let i = 0; i < rows; i++) {
74 | matrix[i][0] = 0;
75 | }
76 | }
77 | }
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/subTreeOfAnother.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given two non-empty binary trees s and t, check whether tree t has
3 | * exactly the same structure and node values with a subtree of s.
4 | * A subtree of s is a tree consists of a node in s and all of this node's descendants.
5 | * The tree s could also be considered as a subtree of itself.
6 |
7 | Example 1:
8 | Given tree s:
9 |
10 | 3
11 | / \
12 | 4 5
13 | / \
14 | 1 2
15 | Given tree t:
16 | 4
17 | / \
18 | 1 2
19 | Return true, because t has the same structure and node values with a subtree of s.
20 | Example 2:
21 | Given tree s:
22 |
23 | 3
24 | / \
25 | 4 5
26 | / \
27 | 1 2
28 | /
29 | 0
30 | Given tree t:
31 | 4
32 | / \
33 | 1 2
34 | Return false.
35 | */
36 | function TreeNode(val) {
37 | this.val = val;
38 | this.left = null;
39 | this.right = null;
40 | }
41 |
42 | const isSubtree = (s, t) => {
43 | const isIdentical = (t1, t2) => {
44 | if (!t1 && !t2) {
45 | return false;
46 | }
47 |
48 | if (t1 && t2) {
49 | return (t1.val === t2.val &&
50 | isIdentical(t1.left, t2.left) &&
51 | isIdentical(t1.right, t2.right));
52 | }
53 |
54 | return false;
55 | }
56 |
57 | if (!s) {
58 | return false;
59 | }
60 |
61 | if (!t) {
62 | return true;
63 | }
64 |
65 | if (isIdentical(s, t)) {
66 | return true;
67 | }
68 |
69 | return (isSubtree(s.left, t) || isSubtree(s.right, t));
70 | }
--------------------------------------------------------------------------------
/exercises/strings/anagrams.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Check to see if two provided strings are anagrams of eachother.
3 | // One string is an anagram of another if it uses the same characters
4 | // in the same quantity. Only consider characters, not spaces
5 | // or punctuation. Consider capital letters to be the same as lower case
6 | // --- Examples
7 | // anagrams('rail safety', 'fairy tales') --> True
8 | // anagrams('RAIL! SAFETY!', 'fairy tales') --> True
9 | // anagrams('Hi there', 'Bye there') --> False
10 |
11 | function anagrams(stringA, stringB) {
12 | const charMapA = buildCharMap(stringA);
13 | const charMapB = buildCharMap(stringB);
14 |
15 | //Check if both objects have same number of keys
16 | if(Object.keys(charMapA).length !== Object.keys(charMapB).length) {
17 | return false;
18 | }
19 |
20 | // Loop through each of the char maps and check for values
21 | for (let char in charMapA) {
22 | if (charMapA[char] !== charMapB[char]) {
23 | return false;
24 | }
25 | }
26 |
27 | return true;
28 |
29 | }
30 |
31 | function buildCharMap(str) {
32 | const charMap = {};
33 | for (let char of str.replace(/[^\w]/g, '').toLowerCase()) {
34 | charMap = charMap[char] + 1 || 1;
35 | }
36 |
37 | return charMap;
38 | }
39 |
40 |
41 | //-------------------------//
42 | // Using sort() function
43 |
44 | function anagrams(stringA, stringB) {
45 | return cleanString(stringA) === cleanString(stringB);
46 | }
47 |
48 | function cleanString(str) {
49 | return str.replace(/[^\w]/g, '').toLowerCase().split('').sort().join();
50 | }
51 |
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/copyListWithRandomPointer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * A linked list is given such that each node contains an additional random pointer
3 | * which could point to any node in the list or null.
4 | *
5 | * Return a deep copy of the list.
6 | *
7 | * Input:
8 | {"$id":"1","next":{"$id":"2","next":null,"random":{"$ref":"2"},"val":2},"random":{"$ref":"2"},"val":1}
9 |
10 | Explanation:
11 | Node 1's value is 1, both of its next and random pointer points to Node 2.
12 | Node 2's value is 2, its next pointer points to null and its random pointer points to itself.
13 | */
14 |
15 | function Node(val, next, random) {
16 | this.val = val;
17 | this.next = next;
18 | this.random = random;
19 | }
20 |
21 | const copyRandomList = head => {
22 | if (!head) {
23 | return null;
24 | }
25 |
26 | let oldNode = head;
27 | let newNode = new Node(head.val, head.next, head.random);
28 | let visited = new Map();
29 |
30 | visited.set(oldNode, newNode);
31 |
32 | const getNode = node => {
33 | if (!node) {
34 | return null;
35 | }
36 |
37 | if (visited.has(node)) {
38 | return visited.get(node);
39 | }
40 |
41 | visited.set(node, new Node(node.val, node.next, node.random));
42 | return visited.get(node);
43 | }
44 |
45 | while (oldNode) {
46 | newNode.random = getNode(oldNode.random);
47 | newNode.next = getNode(oldNode.next);
48 | oldNode = oldNode.next;
49 | newNode = newNode.next;
50 | }
51 |
52 | return visited.get(head);
53 | }
--------------------------------------------------------------------------------
/exercises/stacks&queues/weave.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // 1) Complete the task in weave/queue.js
3 | // 2) Implement the 'weave' function. Weave
4 | // receives two queues as arguments and combines the
5 | // contents of each into a new, third queue.
6 | // The third queue should contain the *alterating* content
7 | // of the two queues. The function should handle
8 | // queues of different lengths without inserting
9 | // 'undefined' into the new one.
10 | // *Do not* access the array inside of any queue, only
11 | // use the 'add', 'remove', and 'peek' functions.
12 | // --- Example
13 | // const queueOne = new Queue();
14 | // queueOne.add(1);
15 | // queueOne.add(2);
16 | // const queueTwo = new Queue();
17 | // queueTwo.add('Hi');
18 | // queueTwo.add('There');
19 | // const q = weave(queueOne, queueTwo);
20 | // q.remove() // 1
21 | // q.remove() // 'Hi'
22 | // q.remove() // 2
23 | // q.remove() // 'There'
24 |
25 | class Queue {
26 | constructor() {
27 | this.data = [];
28 | }
29 |
30 | add(record) {
31 | this.data.unshift(record);
32 | }
33 |
34 | remove() {
35 | this.data.pop();
36 | }
37 |
38 | peek() {
39 | this.data[this.data.length - 1];
40 | }
41 | }
42 |
43 |
44 | // Function to weave 2 queues into a third queue
45 | function weave(sourceOne, sourceTwo) {
46 | const q = new Queue();
47 |
48 | while(sourceOne.peek() || sourceTwo.peek()) {
49 | if (sourceOne.peek()) {
50 | q.add(sourceOne.remove());
51 | }
52 |
53 | if (sourceTwo.peek()) {
54 | q.add(sourceTwo.remove());
55 | }
56 | }
57 |
58 | return q;
59 | }
60 |
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/lowestCommonAncestor.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes
3 | * in the BST.
4 | *
5 | * According to the definition of LCA on Wikipedia:
6 | * “The lowest common ancestor is defined between two nodes p and q as the lowest node in
7 | * T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
8 |
9 | Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5]
10 |
11 | Example 1:
12 |
13 | Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8
14 | Output: 6
15 | Explanation: The LCA of nodes 2 and 8 is 6.
16 |
17 | Example 2:
18 |
19 | Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4
20 | Output: 2
21 | Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.
22 |
23 | */
24 | var lowestCommonAncestor = function(root, p, q) {
25 | if (!root) {
26 | return root;
27 | }
28 |
29 | const swap = (a, b) => {
30 | let tmp = a;
31 | a = b;
32 | b = tmp;
33 | }
34 |
35 | if (p > q) {
36 | swap(p, q);
37 | }
38 |
39 | if (root.val > p.val && root.val > q.val) {
40 | return lowestCommonAncestor(root.left, p, q);
41 | }
42 |
43 | if (root.val < p.val && root.val < q.val) {
44 | return lowestCommonAncestor(root.right, p, q);
45 | }
46 |
47 |
48 | if ( (root.val >= p.val && root.val <= q.val) || (root.val <= p.val && root.val >= q.val)) {
49 | return root;
50 | }
51 |
52 | return null;
53 | };
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/subTreeAverage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a M-ary tree, find the subtree with maximum average. Return the root of the subtree.
3 | * A subtree of a tree is any node of that tree plus all its descendants.
4 | * The average value of a subtree is the sum of its values, divided by the number of nodes.
5 | */
6 |
7 |
8 | class Node {
9 | constructor(val) {
10 | this.val = val;
11 | this.children = [];
12 | }
13 | }
14 |
15 | class Tree {
16 | constructor() {
17 | this.root = null;
18 | }
19 | }
20 |
21 | const subTreeAverage = root => {
22 | const count = node => {
23 | let sum = 0;
24 | let number = 0;
25 |
26 | if (!node) {
27 | return [sum, number]
28 | }
29 |
30 | sum += node.val;
31 | number++;
32 |
33 | const childCount = [];
34 | for (let child of node.children) {
35 | childCount = count(child);
36 | sum += childCount[0];
37 | number += childCount[1];
38 | }
39 |
40 | return [sum, number];
41 | }
42 |
43 | const rootCount = count(root);
44 | let currentMaxAvg = Math.floor(rootCount[0] / rootCount[1]);
45 | let node = root;
46 |
47 | for (let child of root.children) {
48 | let childOfMaxAvg = subTreeAverage(child);
49 | let childCount = count(childOfMaxAvg);
50 |
51 | if (Math.floor(childCount[0] / childCount[1]) > currentMaxAvg) {
52 | currentMaxAvg = Math.floor(childCount[0] / childCount[1]);
53 | node = childOfMaxAvg;
54 | }
55 | }
56 |
57 | return node;
58 | }
--------------------------------------------------------------------------------
/exercises/stacks&queues/stackSet.js:
--------------------------------------------------------------------------------
1 | // Imagine a (literal) stack of plates. If the stack gets too high, it might topple.
2 | // Therefore, in real life, we would likely start a new stack when the previous stack
3 | // exceeds some threshold. Implement a data structure SetOf Stacks that mimics
4 | // this. SetOf Stacks should be composed of several stacks and should create a
5 | // new stack once the previous one exceeds capacity. SetOf Stacks. push() and
6 | // SetOf Stacks. pop() should behave identically to a single stack (that is, popO
7 | // should return the same values as it would if there were just a single stack).
8 |
9 | // Implement a function popAt(int index) which performs a pop operation on
10 | // a specific sub-stack.
11 |
12 | class StackSet {
13 | constructor(capacity) {
14 | this.capacity = capacity;
15 | this.setStack = [];
16 | }
17 |
18 | push(record) {
19 | if (this.setStack.length === 0 || this.setStack[this.setStack.length - 1].length === this.capacity) {
20 | let newStack = [];
21 | newStack.push(record);
22 | this.setStack.push(newStack);
23 | } else {
24 | this.setStack[this.setStack.length - 1].push(record);
25 | }
26 | }
27 |
28 | pop() {
29 | if (this.setStack[this.setStack.length - 1].length === 0) {
30 | return this.setStack.pop();
31 | }
32 |
33 | return this.setStack[this.setStack.length - 1].pop();
34 | }
35 |
36 | peek() {
37 | let currStack = this.setStack[this.setStack.length - 1];
38 | return currStack[currStack.length - 1];
39 | }
40 |
41 | popAt(index) {
42 | return this.setStack[index].pop();
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/exercises/strings/capitalize.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Write a function that accepts a string. The function should
3 | // capitalize the first letter of each word in the string then
4 | // return the capitalized string.
5 | // --- Examples
6 | // capitalize('a short sentence') --> 'A Short Sentence'
7 | // capitalize('a lazy fox') --> 'A Lazy Fox'
8 | // capitalize('look, it is working!') --> 'Look, It Is Working!'
9 |
10 |
11 | function capitalize(str) {
12 | // Array to split the string and hold each word in the string
13 | const words = [];
14 |
15 | // Split each word in the string by space
16 | for (let word of str.split(' ')) {
17 | // Capitalize the first letter of each word and join it with the remaining word usng slice
18 | // Push it to the words array
19 | words.push(word[0].toUpperCase() + word.slice(1));
20 | }
21 |
22 | // Return the words array after joining it to form a string
23 | return words.join(' ');
24 | }
25 |
26 |
27 | //-----------------Second Solution-------------//
28 | // Not the most efficient/effective
29 |
30 | function capitalize(str) {
31 | // Capitalize the first letter of the string
32 | let result = str[0].toUpperCase();
33 |
34 | // Loop through the string from index 1 and check if the left character
35 | // of current index is a space, If true, capitalize the character at the current index
36 | // Else add the character to result string
37 |
38 | for (let i = 1; i < str.length; i++) {
39 | if (str[i - 1] === ' ') {
40 | result += str[i].toUpperCase();
41 | } else {
42 | result += str[i];
43 | }
44 | }
45 |
46 | return result;
47 | }
48 |
--------------------------------------------------------------------------------
/exercises/misc/10001stPrime.js:
--------------------------------------------------------------------------------
1 | // By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.
2 | //
3 | // What is the 10 001st prime number?
4 |
5 | function findNthPrime() {
6 | const primes = [2];
7 | let i = 3;
8 | let j = 2;
9 | let maxPrime = 10001;
10 |
11 | while (primes.length < maxPrime) {
12 | while (i % j !== 0) {
13 | j++;
14 |
15 | if (i === j) {
16 | primes.push(i);
17 | break;
18 | }
19 | }
20 | i++;
21 | j = 2;
22 | }
23 |
24 | return primes[primes.length - 1];
25 | }
26 | //6th prime is 13
27 |
28 | // Using closures and storing primes of found numbers
29 | function findNthPrimeMemoize(maxPrime) {
30 | const primes = [2];
31 | let startingValue = 3;
32 | let divisor = 2;
33 | const store = {};
34 |
35 | function memoize() {
36 | if (store[maxPrime]) {
37 | console.log("returning from store");
38 | return store[maxPrime];
39 | } else {
40 | while (primes.length < maxPrime) {
41 | while (startingValue % divisor !== 0) {
42 | divisor++;
43 |
44 | if (startingValue === divisor) {
45 | primes.push(startingValue);
46 | break;
47 | }
48 | }
49 | startingValue++;
50 | divisor = 2;
51 | }
52 | store[maxPrime] = primes[primes.length - 1];
53 |
54 | return store[maxPrime];
55 | }
56 | }
57 |
58 | return memoize;
59 | }
60 |
61 |
62 |
--------------------------------------------------------------------------------
/exercises/arrays/canJump.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an array of non-negative integers,
3 | * you are initially positioned at the first index of the array.
4 |
5 | Each element in the array represents your maximum jump length at that position.
6 |
7 | Determine if you are able to reach the last index.
8 |
9 | Example 1:
10 |
11 | Input: [2,3,1,1,4]
12 | Output: true
13 | Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
14 | Example 2:
15 |
16 | Input: [3,2,1,0,4]
17 | Output: false
18 | Explanation: You will always arrive at index 3 no matter what. Its maximum
19 | jump length is 0, which makes it impossible to reach the last index.
20 | */
21 |
22 | // O(n2) : Time Complexity
23 | // O(n) : Space Complexity
24 | const INDEX = {
25 | 'G': 'GOOD',
26 | 'B': 'BAD',
27 | 'U': 'UNKNOWN'
28 | }
29 | const canJump = nums => {
30 | const map = [];
31 |
32 | for (let i = 0; i < nums; i++) {
33 | map[i] = INDEX.U;
34 | }
35 | map[map.length - 1] = INDEX.G
36 |
37 | for (let pos = nums.length - 2; pos >= 0; pos--) {
38 | let furthestJump = Math.min(pos + nums[pos], nums.length - 1);
39 | for (let j = pos + 1; j <= furthestJump; j++) {
40 | if (map[j] == INDEX.G) {
41 | map[pos] = INDEX.G;
42 | break;
43 | }
44 | }
45 | }
46 |
47 | return map[0] == INDEX.G;
48 | }
49 |
50 | // Greedy Approach
51 |
52 | const canJump = nums => {
53 | let lastPos = nums.length - 1;
54 |
55 | for (let i = nums.length - 1; i >= 0; i--) {
56 | if (i + nums[i] >= lastPos) {
57 | lastPos = i;
58 | }
59 | }
60 |
61 | return lastPos == 0;
62 | }
--------------------------------------------------------------------------------
/exercises/stacks&queues/queueFromStack.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Implement a Queue datastructure using two stacks.
3 | // *Do not* create an array inside of the 'Queue' class.
4 | // Queue should implement the methods 'add', 'remove', and 'peek'.
5 | // For a reminder on what each method does, look back
6 | // at the Queue exercise.
7 | // --- Examples
8 | // const q = new Queue();
9 | // q.add(1);
10 | // q.add(2);
11 | // q.peek(); // returns 1
12 | // q.remove(); // returns 1
13 | // q.remove(); // returns 2
14 |
15 | class Stack {
16 | constructor() {
17 | this.data = [];
18 | }
19 |
20 | push(record) {
21 | this.data.push(record);
22 | }
23 |
24 | pop() {
25 | return this.data.pop();
26 | }
27 |
28 | peek() {
29 | return this.data[this.data.length - 1];
30 | }
31 | }
32 |
33 | // Class to create a Queue from a Stack
34 | class Queue {
35 | constructor() {
36 | this.first = new Stack();
37 | this.second = new Stack();
38 | }
39 |
40 | // Add method of queue using stack function
41 | add(record) {
42 | this.first.push(record);
43 | }
44 |
45 | remove() {
46 | while(this.first.peek()) {
47 | this.second.push(this.first.pop());
48 | }
49 |
50 | const record = this.second.pop();
51 |
52 | while(this.second.peek()) {
53 | this.first.push(this.second.pop());
54 | }
55 |
56 | return record;
57 | }
58 |
59 | peek() {
60 | while(this.first.peek()) {
61 | this.second.push(this.first.pop());
62 | }
63 |
64 | const record = this.second.peek();
65 |
66 | while(this.second.peek()) {
67 | this.first.push(this.second.pop());
68 | }
69 |
70 | return record;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/exercises/misc/romanToInt.js:
--------------------------------------------------------------------------------
1 | /*
2 | Roman numerals are usually written largest to smallest from left to right.
3 | However, the numeral for four is not IIII.
4 | Instead, the number four is written as IV.
5 | Because the one is before the five we subtract it making four.
6 | The same principle applies to the number nine, which is written as IX.
7 | There are six instances where subtraction is used:
8 | I can be placed before V (5) and X (10) to make 4 and 9.
9 | X can be placed before L (50) and C (100) to make 40 and 90.
10 | C can be placed before D (500) and M (1000) to make 400 and 900.
11 | Given a roman numeral, convert it to an integer. Input is guaranteed to be within the range from 1 to 3999.
12 | */
13 | const romanToInt = function(str) {
14 | const mappingRomanNumbers = {
15 | I: 1,
16 | V: 5,
17 | X: 10,
18 | L: 50,
19 | C: 100,
20 | D: 500,
21 | M: 1000
22 | };
23 | let romanNumeralArray = str.split('');
24 | let intNum = 0;
25 | let index = 0;
26 | while (index < romanNumeralArray.length - 1) {
27 | let currentNum = mappingRomanNumbers[romanNumeralArray[index]];
28 | let nextNum = mappingRomanNumbers[romanNumeralArray[index + 1]];
29 | let result = 0;
30 |
31 | if (nextNum && currentNum < nextNum) {
32 | result = doSubtraction(currentNum, nextNum);
33 | index = index + 2;
34 | } else {
35 | result = currentNum;
36 | index = index + 1;
37 | }
38 | intNum += result;
39 | }
40 |
41 | return intNum;
42 | }
43 |
44 | function doSubtraction(smaller, larger) {
45 | return larger - smaller;
46 | }
--------------------------------------------------------------------------------
/exercises/misc/steps.js:
--------------------------------------------------------------------------------
1 | // --- Directions
2 | // Write a function that accepts a positive number N.
3 | // The function should console log a step shape
4 | // with N levels using the # character. Make sure the
5 | // step has spaces on the right hand side!
6 | // --- Examples
7 | // steps(2)
8 | // '# '
9 | // '##'
10 | // steps(3)
11 | // '# '
12 | // '## '
13 | // '###'
14 | // steps(4)
15 | // '# '
16 | // '## '
17 | // '### '
18 | // '####'
19 |
20 |
21 | // Using repeat function
22 | function steps(n) {
23 | for (let i = 1; i <= n; i++) {
24 | console.log('#'.repeat(i) + ' '.repeat(n-i));
25 | }
26 | }
27 |
28 |
29 | //------------Solution 2---------------//
30 | function steps(n) {
31 |
32 | //Loop through the row
33 | for (let row = 0; row < n; row++) {
34 | let stair = '';
35 |
36 | for (let column = 0; column < n; column++) {
37 | // If the current column value is leser than the row value add a '#';
38 | if (column <= row) {
39 | stair += '#';
40 | } else {
41 | stair += ' ';
42 | }
43 | }
44 | console.log(stair);
45 | }
46 | }
47 |
48 |
49 | //-------------Solution 3 - Using Recurson------------//
50 |
51 | function steps(n, row = 0, stair = '') {
52 | if (n === row) {
53 | return;
54 | }
55 |
56 | if (n === stair.length) {
57 | console.log(stair);
58 | steps(n, row + 1);
59 | }
60 |
61 | // if (stair.length <= row) {
62 | // stair += '#';
63 | // } else {
64 | // stair += ' ';
65 | // }
66 | //
67 | // steps(n, row, stair);
68 |
69 | // Shorthand version of above lines
70 | const add = stair.length <= row ? '#' : ' ';
71 | steps(n, row, stair + add);
72 | }
73 |
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/reorderLogs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * You have an array of logs. Each log is a space delimited string of words.
3 | * For each log, the first word in each log is an alphanumeric identifier. Then, either:
4 | * Each word after the identifier will consist only of lowercase letters, or;
5 | * Each word after the identifier will consist only of digits.
6 | * We will call these two varieties of logs letter-logs and digit-logs. It is guaranteed that each log has at least one word after its identifier.
7 | * Reorder the logs so that all of the letter-logs come before any digit-log. The letter-logs are ordered lexicographically ignoring identifier, with the identifier used in case of ties. The digit-logs should be put in their original order.
8 | *
9 | * Return the final order of the logs.
10 | *
11 | * Example:
12 | * Input: logs = ["dig1 8 1 5 1","let1 art can","dig2 3 6","let2 own kit dig","let3 art zero"]
13 | * Output: ["let1 art can","let3 art zero","let2 own kit dig","dig1 8 1 5 1","dig2 3 6"]
14 | */
15 |
16 | const reorderLogFiles = (logs) => {
17 | const body = log => log.slice(log.indexOf(' ') + 1);
18 | const isNumber = log => /\d/.test(log);
19 |
20 | const compare = (a, b) => {
21 | const n = body(a).localeCompare(body(b));
22 |
23 | if (n !== 0) {
24 | return n;
25 | }
26 |
27 | return a.localeCompare(b);
28 | }
29 |
30 | const digitLogs = [];
31 | const letterLogs = [];
32 |
33 | for (let log of logs) {
34 | if (isNumber(body(log))) {
35 | digitLogs.push(log);
36 | } else {
37 | letterLogs.push(log);
38 | }
39 | }
40 |
41 | return [...letterLogs.sort(compare), ...digitLogs];
42 | }
43 |
44 |
--------------------------------------------------------------------------------
/exercises/linkedlist/sumLinkedList.js:
--------------------------------------------------------------------------------
1 | // You have two numbers represented by a linked list, where each node contains a
2 | // single digit. The digits are stored in reverse order, such that the Ts digit is at the
3 | // head of the list. Write a function that adds the two numbers and returns the sum
4 | // as a linked list.
5 | // EXAMPLE
6 | // Input: (7-> 1 -> 6) + (5 -> 9 -> 2).That is, 617 + 295.
7 | // Output: 2 -> 1 -> 9.That is, 912.
8 | // FOLLOW UP
9 | // Suppose the digits are stored in forward order. Repeat the above problem.
10 | // EXAMPLE
11 | // Input: (6 -> 1 -> 7) + (2 -> 9 -> 5).That is, 617 + 295.
12 | // Output: 9 -> 1 -> 2.That is, 912.
13 |
14 | // Assuming both lists are equal in length
15 |
16 | class Node {
17 | constructor(data, next = null) {
18 | this.data = data;
19 | this.next = next;
20 | }
21 | }
22 |
23 | class LinkedList {
24 | constructor() {
25 | this.head = null;
26 | }
27 | }
28 |
29 | function sumLinkedList(list1, list2) {
30 | let node1 = list1.head;
31 | let node2 = list2.head;
32 | let resultNode = null;
33 | let headNode = null;
34 |
35 | var sum;
36 | var ones;
37 | let tens = 0;
38 |
39 | while (node1 && node2) {
40 | sum = node1.data + node2.data;
41 |
42 | sum += tens;
43 | ones = sum % 10;
44 |
45 | if (!resultNode) {
46 | headNode = new Node(ones);
47 | resultNode = headNode;
48 | } else {
49 | resultNode.next = new Node(ones);
50 | resultNode = resultNode.next;
51 | }
52 |
53 | tens = Math.floor(sum / 10);
54 | node1 = node1.next;
55 | node2 = node2.next;
56 | }
57 |
58 | if (tens > 0) {
59 | resultNode.next = new Node(tens);
60 | resultNode = resultNode.next;
61 | }
62 |
63 | return headNode;
64 | }
65 |
--------------------------------------------------------------------------------
/concepts/BinarySearchTree.js:
--------------------------------------------------------------------------------
1 | /*
2 | In a binary search tree, each node on the left is smaller than
3 | the parent node, and each node on the right is greater than the
4 | parent node.
5 | */
6 |
7 | class BinarySearchTree {
8 | constructor() {
9 | this.root = null;
10 | }
11 |
12 | // Check if a value exists in the tree
13 | contains(value) {
14 | let current = this.root;
15 |
16 | while(current) {
17 | if (value > current.value) {
18 | current = current.right;
19 | } else if (value < current.value) {
20 | current = current.left;
21 | } else {
22 | return true;
23 | }
24 | }
25 | return false;
26 | }
27 |
28 | add(value) {
29 | let newNode = {
30 | value,
31 | left: null,
32 | right: null
33 | };
34 |
35 | if (!this.root) {
36 | this.root = newNode;
37 | return;
38 | }
39 |
40 | let current = this.root;
41 |
42 | while(true) {
43 | if (value > current.value) {
44 | if (!current.right) {
45 | current.right = newNode;
46 | break;
47 | }
48 |
49 | current = current.right;
50 | } else if (value < current.value) {
51 | if (!current.left) {
52 | current.left = newNode;
53 | break;
54 | }
55 |
56 | current = current.left;
57 | } else {
58 | // Log and do nothing in the tree
59 | console.log("Number is same as root")
60 | break;
61 | }
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/optimizeUtilization.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given 2 lists a and b. Each element is a pair of integers where the first integer represents
3 | * the unique id and the second integer represents a value.
4 | * Your task is to find an element from a and an element form b
5 | * such that the sum of their values is less or equal to target
6 | * and as close to target as possible. Return a list of ids of selected elements.
7 | * If no pair is possible, return an empty list.
8 |
9 | Example 1:
10 | Input:
11 | a = [[1, 2], [2, 4], [3, 6]]
12 | b = [[1, 2]]
13 | target = 7
14 |
15 | Output: [[2, 1]]
16 |
17 | Explanation:
18 | There are only three combinations [1, 1], [2, 1], and [3, 1], which have a total sum of 4, 6 and 8, respectively.
19 | Since 6 is the largest sum that does not exceed 7, [2, 1] is the optimal pair.
20 |
21 | */
22 |
23 | const optimizeUtilization = (a, b, target) => {
24 | a.sort((x, y) => x[1] - y)[1];
25 | b.sort((x, y) => x[1] - y[1]);
26 |
27 | let left = 0;
28 | let right = b.length - 1;
29 | let smallestDifference = target;
30 | let output = [];
31 |
32 | while (left < a.length && right >= 0) {
33 | let currentDifference = target - (a[left][1] + b[right][1]);
34 |
35 | if (currentDifference >= 0 && currentDifference < smallestDifference) {
36 | output = [ [a[left][0], b[right][0]] ];
37 | smallestDifference = currentDifference
38 | } else if (currentDifference >= 0 && currentDifference === smallestDifference) {
39 | output.push([a[left][0], b[right][0]]);
40 | }
41 |
42 | if (a[left][1] + b[right][1] > target) {
43 | right--;
44 | } else {
45 | left++;
46 | }
47 | }
48 |
49 | return output;
50 | }
--------------------------------------------------------------------------------
/exercises/arrays/spiralMatrix.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a matrix of m x n elements (m rows, n columns), return all elements of the matrix in spiral order.
3 |
4 | Example 1:
5 |
6 | Input:
7 | [
8 | [ 1, 2, 3 ],
9 | [ 4, 5, 6 ],
10 | [ 7, 8, 9 ]
11 | ]
12 | Output: [1,2,3,6,9,8,7,4,5]
13 | Example 2:
14 |
15 | Input:
16 | [
17 | [1, 2, 3, 4],
18 | [5, 6, 7, 8],
19 | [9,10,11,12]
20 | ]
21 | Output: [1,2,3,4,8,12,11,10,9,5,6,7]
22 | * @param {*} matrix
23 | */
24 | const spiralMatrix = matrix => {
25 | const result = [];
26 |
27 | if (matrix.length === 0) {
28 | return [];
29 | }
30 |
31 | let startRow = 0;
32 | let endRow = matrix.length - 1;
33 | let startColumn = 0;
34 | let endColumn = matrix[0].length - 1;
35 |
36 |
37 | while (startRow <= endRow && startColumn <= endColumn) {
38 | for (let i = startColumn; i <= endColumn; i++) {
39 | result.push(matrix[startRow][i]);
40 | }
41 |
42 | for (let i = startRow + 1; i <= endRow; i++) {
43 | result.push(matrix[i][endColumn]);
44 | }
45 |
46 | if (startRow < endRow && startColumn < endColumn) {
47 | for (let i = endColumn - 1; i > startColumn; i--) {
48 | result.push(matrix[endRow][i]);
49 | }
50 |
51 | for (let i = endRow; i > startRow; i--) {
52 | result.push(matrix[i][startColumn])
53 | }
54 | }
55 | startRow++;
56 | endRow--;
57 | startColumn++;
58 | endColumn--;
59 | }
60 |
61 | return result;
62 | }
63 |
64 | /**
65 | * startRow = 0
66 | * endColumn = 3
67 | * endRow = 2
68 | * startColumn = 0
69 | */
70 |
71 | /**
72 | * [
73 | [1, 2, 3, 4],
74 | [5, 6, 7, 8],
75 | [9,10,11,12]
76 | ]
77 | * [
78 | [ 1, 2, 3 ],
79 | [ 4, 5, 6 ],
80 | [ 7, 8, 9 ]
81 | ]
82 | startRow = 0 => 1 => 2
83 | endRow = 2 => 1 => 0
84 | startColumn = 0 => 1
85 | endColumn = 2 => 1
86 | */
--------------------------------------------------------------------------------
/concepts/List.md:
--------------------------------------------------------------------------------
1 | ### LIST
2 | * A list is a representation of an ordered sequence of elements, where the same element may appear many times
3 |
4 | ```js
5 | class List {
6 | constructor() {
7 | this.memory = [];
8 | this.length = 0;
9 | }
10 |
11 | get(address) {
12 | return this.memory[address];
13 | }
14 |
15 | push(value) {
16 | this.memory[this.length] = value;
17 | this.length++;
18 | }
19 |
20 | pop() {
21 | if (this.length === 0) {
22 | console.log("No elements in list");
23 | return;
24 | }
25 |
26 | let lastAddress = this.length - 1;
27 | const value = this.memory[lastAddress];
28 |
29 | delete this.memory[lastAddress];
30 | this.length--;
31 |
32 | return value;
33 | }
34 |
35 | unshift(value) {
36 | // Insert an element at the beginning of the list
37 | let previous = value;
38 |
39 | for (let address = 0; address < this.length; address++) {
40 | let current = this.memory[address];
41 | this.memory[address] = previous;
42 | previous = current;
43 | }
44 |
45 | this.memory[this.length] = previous;
46 | this.length++;
47 | }
48 |
49 | shift() {
50 | // Remove an item at the beginning of the list
51 | if (this.length === 0) {
52 | console.log("No elements in list");
53 | return;
54 | }
55 | let value = this.memory[0];
56 |
57 | for (let address = 0; address < this.length - 1; address++) {
58 | this.memory[address] = this.memory[address + 1];
59 | }
60 |
61 | delete this.memory[this.length - 1];
62 | this.length--;
63 |
64 | return value;
65 | }
66 | }
67 | ```
--------------------------------------------------------------------------------
/concepts/Ajax.md:
--------------------------------------------------------------------------------
1 | ## AJAX
2 |
3 | ```js
4 | try {
5 | const data = await postData("https://www.example.com/answer", {answer : 42});
6 | console.log(JSON.stringify(data));
7 | } catch (error) {
8 | console.error(error);
9 | }
10 | ```
11 |
12 | ```js
13 | async function postData(url = '', data = {}) {
14 | const response = await fetch(url , {
15 | method: 'POST',
16 | mode: 'cors',
17 | cache: 'no-cache',
18 | credentials: 'same-origin',
19 | headers: {
20 | 'Content-Type': 'application/json'
21 | },
22 | redirect: 'follow',
23 | referrer: 'no-referrer',
24 | body: JSON.stringify(data)
25 | });
26 |
27 | return await response.json();
28 | }
29 |
30 | // Eg. using XHR
31 |
32 | function listenRequest() {
33 | console.log(this.responseText);
34 | }
35 | var request = new XMLHttpRequest();
36 | request.addEventListener('load', listenRequest);
37 | request.open("GET", "https://www.example.com/eg.txt");
38 | request.send();
39 | ```
40 |
41 |
42 | ### Promisifying HTTP Request
43 |
44 | ```js
45 | function get(url) {
46 | return new Promise((resolve, reject) => {
47 | let req = new XMLHttpRequest();
48 | req.open('GET', url);
49 |
50 | req.onload = function() {
51 | if (req.status === 200) {
52 | resolve(response);
53 | } else {
54 | reject(Error(req.errorText));
55 | }
56 | };
57 |
58 | req.onError = function() {
59 | reject(Error('Network Error'));
60 | }
61 |
62 | req.send();
63 | });
64 | }
65 |
66 | get('dummyApiResponse.json').then(response => {
67 | console.log("Success ", JSON.parse(response));
68 | }).catch(error => {
69 | console.log("Error ", error);
70 | })
71 | ```
72 |
--------------------------------------------------------------------------------
/exercises/trees/countSmaller.js:
--------------------------------------------------------------------------------
1 | /**
2 | * You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].
3 |
4 | Example:
5 |
6 | Input: [5,2,6,1]
7 | Output: [2,1,1,0]
8 | Explanation:
9 | To the right of 5 there are 2 smaller elements (2 and 1).
10 | To the right of 2 there is only 1 smaller element (1).
11 | To the right of 6 there is 1 smaller element (1).
12 | To the right of 1 there is 0 smaller element.
13 | */
14 |
15 | class TreeNode {
16 | constructor(val) {
17 | this.val = val;
18 | this.left = null;
19 | this.right = null;
20 | this.count = 1;
21 | }
22 | }
23 |
24 | const insert = (root, val) => {
25 | let thisCount = 0;
26 |
27 | while (true) {
28 | if (val <= root.val) {
29 | root.count++;
30 |
31 | if (!root.left) {
32 | root.left = new TreeNode(val);
33 | break;
34 | } else {
35 | root = root.left;
36 | }
37 | } else {
38 | thisCount += root.count;
39 |
40 | if (!root.right) {
41 | root.right = new TreeNode(val);
42 | break;
43 | } else {
44 | root = root.right;
45 | }
46 | }
47 | }
48 |
49 | return thisCount;
50 | }
51 |
52 | const countSmaller = nums => {
53 | if (!nums || nums.length === 0) {
54 | return [];
55 | }
56 |
57 | const result = [];
58 | let root = new TreeNode(nums[nums.length - 1]);
59 |
60 | for (let i = nums.length - 2; i >= 0; i--) {
61 | let count = insertAndReturnCount(root, nums[i]);
62 | result.push(count);
63 | }
64 |
65 | return result.reverse();
66 | }
--------------------------------------------------------------------------------
/concepts/Tree.js:
--------------------------------------------------------------------------------
1 | /*
2 | Trees are data structures which are uni-directional
3 | They cannot have loops of references.
4 | Sample Tree Structure:
5 |
6 | Tree {
7 | root: {
8 | value,
9 | children: [
10 | {
11 | value,
12 | children: [...]
13 | },
14 | {
15 | value,
16 | children: [...]
17 | }
18 | ]
19 | }
20 | }
21 |
22 | Functions for a Tree include "traverse" to loop through
23 | the tree
24 | add an element to the tree
25 | */
26 |
27 | class Tree {
28 | constructor() {
29 | this.root = null;
30 | }
31 |
32 | // The traverse function will take a callback function
33 | // as argument and loop over the tree from the root
34 | // to its children
35 | traverse(callback) {
36 | function walk(node) {
37 | // Call the callback function on the current node
38 | callback(node);
39 |
40 | // loop over the node's children recursively
41 | node.children.forEach(walk);
42 | }
43 |
44 | // Start the traversal process
45 | walk(this.root);
46 | }
47 |
48 | // lets add an element to one of the node's children
49 | add(value, parentValue) {
50 | let newNode = {
51 | value,
52 | children: []
53 | };
54 |
55 | // if there is no root, set it to the newNode
56 | if (this.root === null) {
57 | this.root = newNode;
58 | return;
59 | }
60 | // Else traverse through the tree and find the node, and add it to it's children
61 | this.traverse(node => {
62 | if (node.value === parentValue) {
63 | node.children.push(newNode);
64 | }
65 | });
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/exercises/trees/populateNextRightPointer-II.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a binary tree
3 |
4 | struct Node {
5 | int val;
6 | Node *left;
7 | Node *right;
8 | Node *next;
9 | }
10 | Populate each next pointer to point to its next right node. If there is no next right node, the next pointer should be set to NULL.
11 |
12 | Initially, all next pointers are set to NULL.
13 |
14 |
15 |
16 | Follow up:
17 |
18 | You may only use constant extra space.
19 | Recursive approach is fine, you may assume implicit stack space does not count as extra space for this problem.
20 | */
21 | /**
22 | * // Definition for a Node.
23 | * function Node(val, left, right, next) {
24 | * this.val = val === undefined ? null : val;
25 | * this.left = left === undefined ? null : left;
26 | * this.right = right === undefined ? null : right;
27 | * this.next = next === undefined ? null : next;
28 | * };
29 | */
30 | let prev, leftMost;
31 |
32 | const processChild = childNode => {
33 | if (childNode !== null) {
34 | if (prev !== null) {
35 | // If a node exists at this level already, assign the childNode as next of prev
36 | prev.next = childNode;
37 | } else {
38 | // else this is the first node on this level
39 | leftMost = childNode;
40 | }
41 | prev = childNode;
42 | }
43 | }
44 | const connect = root => {
45 | if (root === null) {
46 | return root;
47 | }
48 | leftMost = root;
49 |
50 | while (leftMost !== null) {
51 | // No nodes before this at this level
52 | prev = null;
53 | // Node to keep track of the current level in Tree
54 | let curr = leftMost;
55 | // Now that we have saved the current node, reassign the leftMost to null
56 | leftMost = null;
57 |
58 | while (curr !== null) {
59 | processChild(curr.left);
60 | processChild(curr.right);
61 | curr = curr.next;
62 | }
63 | }
64 | return root;
65 | }
66 |
67 | /**
68 | * Time Complexity: O(N)
69 | * Space Complexity: O(1)
70 | */
--------------------------------------------------------------------------------
/exercises/linkedlist/sumLinkedList-II.js:
--------------------------------------------------------------------------------
1 | /**
2 | * You are given two non-empty linked lists representing two non-negative integers.
3 | * The most significant digit comes first and each of their nodes contain a single digit.
4 | * Add the two numbers and return it as a linked list.
5 | * You may assume the two numbers do not contain any leading zero, except the number 0 itself.
6 |
7 | Follow up:
8 | What if you cannot modify the input lists? In other words, reversing the lists is not allowed.
9 |
10 | Example:
11 |
12 | Input: (7 -> 2 -> 4 -> 3) + (5 -> 6 -> 4)
13 | Output: 7 -> 8 -> 0 -> 7
14 | */
15 | /**
16 | * Definition for singly-linked list.
17 | * function ListNode(val) {
18 | * this.val = val;
19 | * this.next = null;
20 | * }
21 | */
22 | /**
23 | * @param {ListNode} l1
24 | * @param {ListNode} l2
25 | * @return {ListNode}
26 | */
27 | const addTwoNumbers = (l1, l2) => {
28 | const s1 = [];
29 | let node1 = l1;
30 |
31 | while (node1) {
32 | s1.push(node1);
33 | node1 = node1.next;
34 | }
35 |
36 | const s2 = [];
37 | let node2 = l2;
38 |
39 | while (node2) {
40 | s2.push(node2);
41 | node2 = node2.next;
42 | }
43 |
44 | let carry = 0;
45 | let prev = null;
46 | let result = 0;
47 |
48 | while (s1.length > 0 || s2.length > 0) {
49 | let num1 = s1.length > 0 ? s1.pop().val : 0;
50 | let num2 = s2.length > 0 ? s2.pop().val : 0;
51 |
52 | result = num1 + num2 + carry;
53 | if (result > 9) {
54 | result = result - 10;
55 | carry = 1;
56 | } else {
57 | carry = 0;
58 | }
59 |
60 | let curr = new ListNode(result);
61 | curr.next = prev;
62 | prev = curr;
63 | }
64 |
65 | if (carry) {
66 | let curr = new ListNode(carry);
67 | curr.next = prev;
68 | prev = curr;
69 | }
70 |
71 | return prev;
72 | }
--------------------------------------------------------------------------------
/exercises/arrays/insertInterval.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a set of non-overlapping intervals, insert a new interval into the intervals (merge if necessary).
3 |
4 | You may assume that the intervals were initially sorted according to their start times.
5 |
6 | Example 1:
7 |
8 | Input: intervals = [[1,3],[6,9]], newInterval = [2,5]
9 | Output: [[1,5],[6,9]]
10 | Example 2:
11 |
12 | Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
13 | Output: [[1,2],[3,10],[12,16]]
14 | Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10].
15 | */
16 |
17 | const insertInterval = (intervals, newInterval) => {
18 | // first add all intervals before new interval to output
19 | const output = [];
20 | let newStart = newInterval[0];
21 | let newEnd = newInterval[1];
22 | let index = 0;
23 | let n = intervals.length;
24 |
25 | while (index < n && intervals[index][0] < newStart) {
26 | output.push(intervals[index]);
27 | index++;
28 | }
29 |
30 | if (output.length === 0 || output[output.length - 1][1] < newStart) {
31 | // new Interval is not overlapping with any prev intervals, so just add it
32 | output.push(newInterval);
33 | } else {
34 | // merge the overlapping intervals
35 | let interval = output.pop();
36 | interval[1] = Math.max(interval[1], newEnd);
37 | output.push(interval);
38 | }
39 |
40 | // push all other intervals after new interval
41 | while (index < n) {
42 | let interval = intervals[index];
43 | let start = interval[0];
44 | let end = interval[1];
45 |
46 | if (output[output.length - 1][1] < start) {
47 | output.push(interval);
48 | } else {
49 | interval = output.pop();
50 | interval[1] = Math.max(interval[1], end);
51 | output.push(interval);
52 | }
53 | index++;
54 | }
55 |
56 | return output;
57 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # JavaScript Questions & Problems for an Interview
2 |
3 | > Contains common JavaScript questions, problems, generally asked in technical and software coding interviews. This is based on my preparation and research for a software developer interview
4 |
5 | 1. [Arrays](https://github.com/Narahari-Sundaragopalan/JavaScript-Interview-Prep/tree/master/exercises/arrays)
6 | 2. [Linked List](https://github.com/Narahari-Sundaragopalan/JavaScript-Interview-Prep/tree/master/exercises/linkedlist)
7 | 3. [Sorting](https://github.com/Narahari-Sundaragopalan/JavaScript-Interview-Prep/tree/master/exercises/sorting)
8 | 4. [Stacks & Queues](https://github.com/Narahari-Sundaragopalan/JavaScript-Interview-Prep/tree/master/exercises/stacks%26queues)
9 | 5. [Strings](https://github.com/Narahari-Sundaragopalan/JavaScript-Interview-Prep/tree/master/exercises/strings)
10 | 6. [Trees](https://github.com/Narahari-Sundaragopalan/JavaScript-Interview-Prep/tree/master/exercises/trees)
11 | 7. [Miscellaneous](https://github.com/Narahari-Sundaragopalan/JavaScript-Interview-Prep/tree/master/exercises/misc)
12 | 8. [Technical-Questions-JavaScript](https://github.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/blob/master/questions/JS-questions.md)
13 | 9. [Front-End-Problems](https://github.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/tree/master/FE-JS-Questions)
14 | 10. [Web Development Concepts](https://github.com/Narahari-Sundaragopalan/JavaScript-Interview-Questions/tree/master/concepts)
15 |
16 |
17 | ## License
18 |
19 | 
This repository is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
20 |
--------------------------------------------------------------------------------
/exercises/strings/simplifyPath.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an absolute path for a file (Unix-style), simplify it. Or in other words, convert it to the canonical path.
3 | * In a UNIX-style file system, a period . refers to the current directory.
4 | * Furthermore, a double period .. moves the directory up a level.
5 | *
6 | * Note that the returned canonical path must always begin with a slash /,
7 | * and there must be only a single slash / between two directory names.
8 | * The last directory name (if it exists) must not end with a trailing /.
9 | * Also, the canonical path must be the shortest string representing the absolute path.
10 | * Example 1:
11 | * Input: "/home/"
12 | * Output: "/home"
13 | * Explanation: Note that there is no trailing slash after the last directory name.
14 | *
15 | * Example 2:
16 | * Input: "/../"
17 | * Output: "/"
18 | * Explanation: Going one level up from the root directory is a no-op, as the root level is the highest level you can go.
19 | *
20 | * Example 3:
21 | * Input: "/home//foo/"
22 | * Output: "/home/foo"
23 | * Explanation: In the canonical path, multiple consecutive slashes are replaced by a single one.
24 | *
25 | * Example 4:
26 | * Input: "/a/./b/../../c/"
27 | * Output: "/c"
28 | *
29 | * Example 5:
30 | * Input: "/a/../../b/../c//.//"
31 | * Output: "/c"
32 | *
33 | * Example 6:
34 | * Input: "/a//b////c/d//././/.."
35 | * Output: "/a/b/c"
36 | */
37 |
38 | const simplifyPath = path => {
39 | const dirs = path.split('/');
40 | const pathStack = [];
41 |
42 | for (let dir of dirs) {
43 | if (dir === '.' || dir === '') {
44 | continue;
45 | } else if (dir !== '..') {
46 | pathStack.push(dir);
47 | } else {
48 | pathStack.pop();
49 | }
50 | }
51 | let canonicalPath = '/';
52 | for (let i = 0; i < pathStack.length; i++) {
53 | if (i === pathStack.length - 1) {
54 | canonicalPath += pathStack[i];
55 | } else {
56 | canonicalPath += `${pathStack[i]}/`;
57 | }
58 | }
59 |
60 | return canonicalPath;
61 | }
--------------------------------------------------------------------------------
/exercises/strings/stringToInt.js:
--------------------------------------------------------------------------------
1 | /*
2 | Implement atoi which converts a string to an integer.
3 | The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.
4 | The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.
5 | If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.
6 | If no valid conversion could be performed, a zero value is returned.
7 | */
8 |
9 | const myAtoi = function(str) {
10 | let base = 10;
11 | let parsedNumber = 0;
12 | let sign = 1;
13 | const INT_MAX = Math.pow(2, 31) - 1;
14 | const INT_MIN = Math.pow(-2, 31);
15 |
16 | // clean the string
17 | let cleanedString = str.trim().split('');
18 |
19 | // check if first char is sign for positive or negative number
20 | if (cleanedString[0] === '-' || cleanedString[0] === '+') {
21 | if (cleanedString[0] === '-') {
22 | sign = -1;
23 | }
24 | cleanedString.shift();
25 | } else if (Number.isNaN(parseInt(cleanedString[0]))) {
26 | return 0;
27 | }
28 |
29 | for (let char of cleanedString) {
30 | let num = parseInt(char);
31 |
32 | if (!isNaN(num)) {
33 | parsedNumber *= base;
34 | parsedNumber += num;
35 |
36 | if (parsedNumber * sign > INT_MAX) {
37 | return INT_MAX;
38 | } else if (parsedNumber * sign < INT_MIN) {
39 | return INT_MIN;
40 | }
41 | } else {
42 | break;
43 | }
44 | }
45 |
46 | return parsedNumber * sign;
47 | }
--------------------------------------------------------------------------------
/exercises/linkedlist/checkPalindromeLinkedList.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a singly linked list, determine if it is a palindrome.
3 |
4 | Example 1:
5 |
6 | Input: 1->2
7 | Output: false
8 | Example 2:
9 |
10 | Input: 1->2->2->1
11 | Output: true
12 | Follow up:
13 | Could you do it in O(n) time and O(1) space?
14 | * @param {LinkedList} list
15 | * @return {boolean}
16 | */
17 |
18 | function checkPalindrome(list) {
19 | // Find the midpoint of the linked list
20 | let node = list.head;
21 | let midPoint = findMidPoint(list);
22 | // Compute reverse of linked list from midPoint to end
23 | let tail = reverseLinkedList(midPoint);
24 | // compare both lists
25 | while (tail) {
26 | if (tail.data !== node.data) {
27 | return false;
28 | }
29 | tail = tail.next;
30 | node = node.next;
31 | }
32 |
33 | return true;
34 | }
35 |
36 | function findMidPoint(list) {
37 | let slow = list.head;
38 | let fast = list.head;
39 |
40 | while (fast.next && fast.next.next) {
41 | slow = slow.next;
42 | fast = fast.next.next;
43 | }
44 |
45 | return slow;
46 | }
47 |
48 | function reverseList(node) {
49 | let next = null;
50 | let previous = null;
51 | while (node) {
52 | next = node.next;
53 | node.next = previous;
54 | previous = node;
55 | node = next;
56 | }
57 |
58 | return previous;
59 | }
60 |
61 | /**
62 | * Time Complexity: O(N)
63 | * Space Complexity: O(1)
64 | */
65 |
66 | // Approach 2
67 | const checkPalindrome = list => {
68 | if (!list.head) {
69 | return false;
70 | }
71 |
72 | const arrayList = [];
73 | let node = list.head;
74 | while (node) {
75 | arrayList.push(node.val);
76 | node = node.next;
77 | }
78 |
79 | let start = 0, end = arrayList.length - 1;
80 |
81 | while (start <= end) {
82 | if (arrayList[start] !== arrayList[end]) {
83 | return false;
84 | }
85 | start++;
86 | end--;
87 | }
88 |
89 | return true;
90 | }
91 |
92 | /**
93 | * Time Complexity: O(N)
94 | * Space Complexity: O(N)
95 | */
96 |
--------------------------------------------------------------------------------
/CSS-JS/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Scoped CSS variables and JS
7 |
8 |
9 |
10 | Update CSS variables with
11 | JS
12 |
13 |
14 |
17 |
18 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
64 |
65 |
78 |
79 |
--------------------------------------------------------------------------------
/concepts/LinkedList.md:
--------------------------------------------------------------------------------
1 | ## LINKED LIST
2 |
3 | Linked lists are a common data structure used to implment
4 | other data structures. They allow data to be inserted at
5 | the start, middle or end.
6 |
7 | A good way to implement linked list is `1 -> 2 -> 3 -> 4 -> 5`
8 |
9 | Visualize them as a JSON like structure
10 |
11 | ```
12 | {
13 | value: 1,
14 | next: {
15 | value: 2,
16 | next: {
17 | value: 3,
18 | next: { ... }
19 | }
20 | }
21 | }
22 | ```
23 |
24 | ```js
25 | class LinkedList {
26 | constructor() {
27 | this.head = null;
28 | this.length = 0;
29 | }
30 |
31 | get(position) {
32 | if (position >= this.length) {
33 | throw new Error('Position cannot be greater than linked list size');
34 | }
35 |
36 | let current = this.head;
37 |
38 | for (let index = 0; index < position; index++) {
39 | current = current.next;
40 | }
41 |
42 | return current;
43 | }
44 |
45 | add(position, value) {
46 | let node = {
47 | value,
48 | next: null
49 | };
50 |
51 | if (position === 0) {
52 | node.next = this.head;
53 | this.head = node;
54 | } else {
55 | let previous = this.get(position - 1);
56 | let current = previous.next;
57 |
58 | node.next = current;
59 | previous.next = node;
60 | }
61 |
62 | this.length++;
63 | }
64 |
65 | remove(position) {
66 | if (!this.head) {
67 | throw new Error('Linked List is empty');
68 | }
69 |
70 | // If we're removing the first node we simply need to set the head to the next node in the chain
71 | if (position === 0) {
72 | this.head = this.head.next;
73 | } else {
74 | // For any other position, we need to look up the previous node and set it to the node after the current position.
75 | let previous = this.get(position - 1);
76 | previous.next = previous.next.next;
77 | }
78 |
79 | this.length--;
80 | }
81 | }
82 | ```
83 |
--------------------------------------------------------------------------------
/exercises/strings/reverseEachWord.js:
--------------------------------------------------------------------------------
1 | // Given a string, reverse each word in the sentence
2 | // "Welcome to this Javascript Guide!" should be become "emocleW ot siht tpircsavaJ !ediuG"
3 |
4 | function reverseBySeparator(string, separator) {
5 | return string.split(separator)
6 | .map(word => word.split('').reverse().join(''))
7 | .join(separator);
8 | }
9 |
10 | // To test
11 | //
12 | // let string = "Welcome to JavaScript";
13 | //
14 | // // Output becomes tpircsavaJ siht ot emocleW
15 | // let reverseSentence = reverseBySeparator(string, "");
16 | //
17 | // // Output becomes emocleW ot siht tpircsavaJ
18 | // let reverseWord = reverseBySeparator(reverseBySentence, " ");
19 |
20 | // Without using split and reverse functions
21 |
22 | const reverseEachWord = str => {
23 | let words = split(str);
24 | let result = '';
25 |
26 | for (let word of words) {
27 | result = result + reverse(word) + ' ';
28 | }
29 |
30 | return result.trim();
31 | }
32 |
33 | const split = str => {
34 | const words = [];
35 | let word = '';
36 |
37 | for (let i = 0; i < str.length; i++) {
38 | if (str.charAt(i) === ' ') {
39 | words.push(word);
40 | word = '';
41 | } else {
42 | word += str.charAt(i);
43 | }
44 | }
45 | words.push(word);
46 | return words;
47 | }
48 |
49 | const reverse = word => {
50 | let result = '';
51 |
52 | for (let i = word.length - 1; i >= 0; i--) {
53 | result += word[i];
54 | }
55 |
56 | return result;
57 | }
58 |
59 |
60 | /**
61 | * If its function to only reverse words of a sentence and not words individually
62 | * */
63 | var reverseWords = function(s) {
64 | //return s.split(' ').reverse().filter(word => word !== '').join(' ').trim();
65 | return s.split(/\s+/).reverse().join(' ').trim();
66 | };
67 |
68 | /**
69 | * Time Complexity: O(N)
70 | * Space Complexity: O(N)
71 | */
72 |
73 | /**
74 | * Without using built in functions
75 | * @param {string} s
76 | */
77 | const reverseWords = s => {
78 | let result = '';
79 | const words = split(s); // or built in fn: s.split(/\s+/)
80 |
81 | for (let word of words) {
82 | result = word + result;
83 | }
84 |
85 | return result.trim();
86 | }
--------------------------------------------------------------------------------
/exercises/arrays/employeeFreeTime.js:
--------------------------------------------------------------------------------
1 | /**
2 | * We are given a list schedule of employees, which represents the working time for each employee.
3 |
4 | Each employee has a list of non-overlapping Intervals, and these intervals are in sorted order.
5 |
6 | Return the list of finite intervals representing common, positive-length free time for all employees,
7 | also in sorted order.
8 |
9 | (Even though we are representing Intervals in the form [x, y], the objects inside are Intervals,
10 | not lists or arrays.
11 | For example, schedule[0][0].start = 1, schedule[0][0].end = 2, and
12 | schedule[0][0][0] is not defined).
13 | Also, we wouldn't include intervals like [5, 5] in our answer, as they have zero length.
14 |
15 | Example 1:
16 | Input: schedule = [[[1,2],[5,6]],[[1,3]],[[4,10]]]
17 | Output: [[3,4]]
18 | Explanation: There are a total of three employees, and all common
19 | free time intervals would be [-inf, 1], [3, 4], [10, inf].
20 | We discard any intervals that contain inf as they aren't finite.
21 |
22 | Example 2:
23 | Input: schedule = [[[1,3],[6,7]],[[2,4]],[[2,5],[9,12]]]
24 | Output: [[5,6],[7,9]]
25 | */
26 | /**
27 | * // Definition for an Interval.
28 | * function Interval(start, end) {
29 | * this.start = start;
30 | * this.end = end;
31 | * };
32 | */
33 | /**
34 | * @param {Interval[][]} schedule
35 | * @return {Interval[]}
36 | */
37 | const employeeFreeTime = schedule => {
38 | const result = [];
39 | const blockers = [];
40 |
41 | for (let intervals of schedule) {
42 | for (let interval of intervals) {
43 | blockers.push(interval);
44 | }
45 | }
46 |
47 | blockers.sort((a, b) => a.start - b.start);
48 | let previous = blockers[0];
49 |
50 | for (let i = 1; i < blockers.length; i++) {
51 | let current = blockers[i];
52 |
53 | if (current.start > previous.end) {
54 | result.push(new Interval(previous.end, current.start));
55 | previous = current;
56 | } else {
57 | previous.start = Math.min(previous.start, current.start);
58 | previous.end = Math.max(previous.end, current.end);
59 | }
60 | }
61 |
62 | return result;
63 | };
--------------------------------------------------------------------------------
/exercises/misc/findKClosestPoints.js:
--------------------------------------------------------------------------------
1 | /*Amazon SDE Assessment // QUESTION: There are a set of locations, represented by points.
2 | Find the closest locations for the truck with start point (0,0), for the number of deliveries to be made
3 |
4 | For eg: if the locations are "[[1,-1], [-2,4], [1,1], [3,2]]"
5 | numDeliveries = 2
6 | Closest locations would be [[1, -1], [1, 1]]
7 | */
8 |
9 | function findKClosest(numDestinations, allLocations, numDeliveries) {
10 | // Array to store coordinates and distance
11 | let pointsWithDistance = [];
12 | const outputArray = [];
13 | for (let i = 0; i < allLocations.length; i++) {
14 | let currentLocation = allLocations[i];
15 | distance = Math.sqrt(
16 | currentLocation[0] * currentLocation[0] +
17 | currentLocation[1] * currentLocation[1]
18 | );
19 | pointsWithDistance.push({ location: currentLocation, distance: distance });
20 | }
21 |
22 | pointsWithDistance.sort(function(a, b) {
23 | if (a.distance > b.distance) {
24 | return 1;
25 | }
26 |
27 | if (a.distance < b.distance) {
28 | return -1;
29 | }
30 | return 0;
31 | });
32 |
33 | for (let i = 0; i < numDeliveries; i++) {
34 | outputArray.push(pointsWithDistance[i].location);
35 | }
36 | return outputArray;
37 | }
38 |
39 |
40 | // More generic version
41 |
42 | const findKClosestPoints = (origin, pointsArray, k) => {
43 | const output = [];
44 | const pointsDistanceMap = [];
45 |
46 | const distanceFromOrigin = point => {
47 | return (
48 | ( (origin[0] - point[0]) * (origin[0] - point[0]) ) +
49 | ( (origin[1] - point[1]) * (origin[1] - point[1]) )
50 | );
51 | }
52 |
53 | for (let point of pointsArray) {
54 | pointsDistanceMap.push({
55 | location: point,
56 | distance: distanceFromOrigin(point)
57 | });
58 | }
59 |
60 | pointsDistanceMap.sort((a, b) => a.distance - b.distance);
61 |
62 | for (let i = 0; i < k; i++) {
63 | output.push(pointsDistanceMap[i].location);
64 | }
65 |
66 | return output;
67 | }
68 |
69 |
70 | // console.log(findKClosestPoints([0,0], [[-16, 5], [-1, 2], [4, 3], [10, -2], [0, 3], [-5, -9]], 3));
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/minHours.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given a 2D grid, each cell is either a zombie 1 or a human 0.
3 | * Zombies can turn adjacent (up/down/left/right) human beings into zombies every hour.
4 | * Find out how many hours does it take to infect all humans?
5 | *
6 | * Input:
7 | [[0, 1, 1, 0, 1],
8 | [0, 1, 0, 1, 0],
9 | [0, 0, 0, 0, 1],
10 | [0, 1, 0, 0, 0]]
11 |
12 | Output: 2
13 |
14 | Explanation:
15 | At the end of the 1st hour, the status of the grid:
16 | [[1, 1, 1, 1, 1],
17 | [1, 1, 1, 1, 1],
18 | [0, 1, 0, 1, 1],
19 | [1, 1, 1, 0, 1]]
20 |
21 | At the end of the 2nd hour, the status of the grid:
22 | [[1, 1, 1, 1, 1],
23 | [1, 1, 1, 1, 1],
24 | [1, 1, 1, 1, 1],
25 | [1, 1, 1, 1, 1]]
26 | */
27 |
28 | const minHours = grid => {
29 | const rows = grid.length;
30 | const columns = grid[0].length;
31 | const dirs = [[1, 0], [0, 1], [0, -1], [-1, 0]];
32 | const queue = [];
33 |
34 | let population = rows * columns;
35 | let hours = 0;
36 |
37 | // add all zombies to a queue
38 | grid.forEach((row, r) => {
39 | row.forEach((person, c) => {
40 | if (person === 1) {
41 | queue.push([r, c]);
42 | }
43 | });
44 | });
45 |
46 | // if length of queue is equal to total population(elements),
47 | // everyone is infected, return hours
48 | if (queue.length === population) {
49 | return hours;
50 | }
51 |
52 | population -= queue.length;
53 |
54 | while(queue.length) {
55 | if (!population) {
56 | break;
57 | }
58 |
59 | // increment as we are in next hour
60 | hours++;
61 |
62 | for (let i = 0; i < queue.length; i++) {
63 | const zombie = queue.shift();
64 |
65 | dirs.forEach(dir => {
66 | const target = [zombie[0] + dir[0], zombie[1] + dir[1]];
67 |
68 | if (target[0] >= 0 && target[0] < rows
69 | && target[1] >= 0 && target[1] < columns
70 | && grid[target[0]][target[1]] === 0) {
71 | queue.push(target);
72 | grid[target[0]][target[1]]++;
73 | population--;
74 | }
75 | });
76 | }
77 | }
78 |
79 | return hours;
80 | }
--------------------------------------------------------------------------------
/exercises/leetcode/amazon/minCostToConnectNodes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Given an undirected graph with n nodes labeled 1..n.
3 | * Some of the nodes are already connected.
4 | * The i-th edge connects nodes edges[i][0] and edges[i][1] together.
5 | * Your task is to augment this set of edges with additional edges to connect all the nodes.
6 | * Find the minimum cost to add new edges between the nodes such that all the nodes are
7 | * accessible from each other.
8 |
9 | Input:
10 |
11 | n, an int representing the total number of nodes.
12 | edges, a list of integer pair representing the nodes already connected by an edge.
13 | newEdges, a list where each element is a triplet representing the pair of nodes
14 | between which an edge can be added and the cost of addition, respectively
15 | (e.g. [1, 2, 5] means to add an edge between node 1 and 2, the cost would be 5).
16 | */
17 |
18 | const minCostToConnect = (N, edges, newEdges) => {
19 | let n = N;
20 | const parents = [];
21 |
22 | for (let i = 0; i < N; i++) {
23 | parents.push(i);
24 | }
25 |
26 | const find = u => {
27 | if (u !== parents[u]) {
28 | parents[u] = find(parents[u]);
29 | }
30 |
31 | return parents[u];
32 | }
33 |
34 | const union = (u, v) => {
35 | const p1 = find(u);
36 | const p2 = find(v);
37 |
38 | if (p1 !== p2) {
39 | parents[p1] = p2;
40 | n--;
41 | }
42 | }
43 |
44 | const isSameEdge = (edge1, edge2) => {
45 | const [u1, v1] = edge1;
46 | const [u2, v2] = edge2;
47 |
48 | return (u1 === u2 && v1 === v2);
49 | }
50 |
51 | const isEdgeToBeConnected = (edge) => {
52 | for (let e of newEdges) {
53 | if (isSameEdge(edge, e)) {
54 | return true;
55 | }
56 | }
57 |
58 | return false;
59 | }
60 |
61 | for (let [u, v] of edges) {
62 | if (!isEdgeToBeConnected([u, v])) {
63 | union(u, v);
64 | }
65 | }
66 |
67 | newEdges.sort((a, b) => a[2] - b[2]);
68 |
69 | let res = 0;
70 | for (let [u, v, cost] of newEdges) {
71 | if (find(u) !== find(v)) {
72 | union(u, v);
73 | res += cost;
74 | }
75 | }
76 |
77 | return n === 1 ? res : -1;
78 | }
--------------------------------------------------------------------------------
/FE-JS-Questions/Pagination.md:
--------------------------------------------------------------------------------
1 | ## Pagination
2 |
3 | ```html
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | ```
12 |
13 | ```js
14 | const list = [];
15 | const currentPageList = [];
16 | let currentPage = 1;
17 | let numOfPages = 0;
18 | let itemsPerPage = 10;
19 |
20 | const makeList = (listLength) => {
21 | for (let i = 1; i <= listLength; i++) {
22 | list.push(i);
23 | }
24 |
25 | numOfPages = Math.ceil(listLength / itemsPerPage);
26 | }
27 |
28 | const drawList = () => {
29 | const list = document.querySelector(".list");
30 | let items = '';
31 |
32 | for (let i = 0; i < currentPageList.length; i++) {
33 | items += 'Item-' + currentPageList[i] + '
';
34 | }
35 |
36 | list.innerHTML = items;
37 | }
38 |
39 | const updateButtons = () => {
40 | document.querySelector(".next").disabled = currentPage === numOfPages ? true : false;
41 | document.querySelector(".previous").disabled = currentPage === 1 ? true : false;
42 | }
43 |
44 | const loadList = (currentPage) => {
45 | let start = (currentPage - 1) * itemsPerPage;
46 | let end = start + itemsPerPage;
47 |
48 | currentPageList = list.slice(start, end);
49 | drawList();
50 | updateButtons();
51 | };
52 |
53 | const goToPage = pageNum => {
54 | currentPage = pageNum;
55 | loadList(currentPage);
56 | };
57 |
58 | const nextPage = () => {
59 | goToPage(currentPage + 1);
60 | };
61 |
62 | const prevPage = () => {
63 | goToPage(currentPage - 1);
64 | };
65 |
66 | const firstPage = () => {
67 | goToPage(1);
68 | };
69 |
70 | const lastPage = () => {
71 | goToPage(numOfPages);
72 | };
73 |
74 | makeList(50);
75 | loadList(1);
76 |
77 | const nextButton = document.querySelector(".next");
78 | const prevButton = document.querySelector(".previous");
79 | const firstButton = document.querySelector(".first");
80 | const lastButton = document.querySelector(".last");
81 |
82 | nextButton.addEventListener('click', nextPage);
83 | prevButton.addEventListener('click', prevPage);
84 | firstButton.addEventListener('click', firstPage);
85 | lastButton.addEventListener('click', lastPage);
86 | ```
--------------------------------------------------------------------------------