diff --git a/3) Task Challanges.md b/3) Task Challanges.md index 78dc5f2..5ef88e7 100644 --- a/3) Task Challanges.md +++ b/3) Task Challanges.md @@ -526,7 +526,3 @@ function getAsyncArraySizePromise(asyncArray) { ``` Note how in the `getChunk` function we use `Promise.all` to parallel and thus speed up the execution of the code. - -# More tasks - -Don't worry lads, there are always more tasks to solve. Feel free to check out [Task Archieve](./task-archieve/README.md). diff --git a/task-archieve/README.md b/task-archieve/README.md deleted file mode 100644 index 165f20d..0000000 --- a/task-archieve/README.md +++ /dev/null @@ -1,20 +0,0 @@ -## Task Archieve [:scroll:](./task-type.md) - -_List of tasks_ - ---- - -- [Container With Most Water](./most-water/task.md) -- [Zigzag Conversion](./zigzag-conversion/task.md) -- [Longest sequence of letters](./longest-letter-subsequence/task.md) -- [Longest sequence of 1's](./longest-sequence-of-1s/task.md) -- [Sort letters from one array via another array](./sort-letters-two-arrays/task.md) -- [Flatten non-recursive v2](./flatten-nonrecursive-v2/task.md) -- [Intersection of intervals](./intersection-intervals/task.md) -- [Sort the Matrix diagonally](./matrix-diagonal-sort/task.md) -- [Keygen](./keygen/task.md) -- [Combinations](./combinations/task.md) -- [Word Search](./word-search/task.md) -- [Climbing Stairs](./climb-stairs/task.md) -- [Remove Duplicates from Sorted Array v2](./remove-duplicates-v2/task.md) -- [Best Time to Buy and Sell Stock](./best-time-to-buy-and-sell-stock/task.md) diff --git a/task-archieve/best-time-to-buy-and-sell-stock/solution-2.js b/task-archieve/best-time-to-buy-and-sell-stock/solution-2.js deleted file mode 100644 index 9843898..0000000 --- a/task-archieve/best-time-to-buy-and-sell-stock/solution-2.js +++ /dev/null @@ -1,29 +0,0 @@ -function maxProfit(prices) { - if (prices.length < 2) { - return 0; - } - - let profit = 0; - let [buy, sell] = prices; - - for (let i = 1; i < prices.length; i++) { - let currentBuy = prices[i - 1]; - let currentSell = prices[i]; - - if (currentSell > sell) { - sell = currentSell; - } - - if (currentBuy < buy) { - buy = currentBuy; - sell = currentSell; - } - - profit = Math.max(profit, sell - buy); - } - - return profit; -} - -console.log(maxProfit([7,1,5,3,6,4])); -console.log(maxProfit([7,6,4,3,1])); diff --git a/task-archieve/best-time-to-buy-and-sell-stock/solution.js b/task-archieve/best-time-to-buy-and-sell-stock/solution.js deleted file mode 100644 index 6c25cfc..0000000 --- a/task-archieve/best-time-to-buy-and-sell-stock/solution.js +++ /dev/null @@ -1,22 +0,0 @@ -function maxProfit(prices) { - let left = 0; // buy - let right = 1; // sell - let profit = 0; - - while (right < prices.length) { - // profitable? - if (prices[left] < prices[right]) { - profit = Math.max(profit, prices[right] - prices[left]); - } else { - // we found a left that is even smaller than the previous one (buy cheaper) - left = right; - } - - right++; - } - - return profit; -} - -console.log(maxProfit([7,1,5,3,6,4])); -console.log(maxProfit([7,6,4,3,1])); diff --git a/task-archieve/best-time-to-buy-and-sell-stock/task.md b/task-archieve/best-time-to-buy-and-sell-stock/task.md deleted file mode 100644 index 3aafedf..0000000 --- a/task-archieve/best-time-to-buy-and-sell-stock/task.md +++ /dev/null @@ -1,6 +0,0 @@ -# Best Time to Buy and Sell Stock - ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) | [:white_check_mark: solution 2](./solution-2.js) | -| :---: | :---: | :---: | diff --git a/task-archieve/climb-stairs/solution-2.js b/task-archieve/climb-stairs/solution-2.js deleted file mode 100644 index d2119bb..0000000 --- a/task-archieve/climb-stairs/solution-2.js +++ /dev/null @@ -1,13 +0,0 @@ -function climbStairs(n) { - if (n <= 3) { - return n; - } - - const steps = [0, 1, 2, 3]; - - for (let i = 4; i < n + 1; i++) { - steps.push(steps[i - 1] + steps[i - 2]); - } - - return steps.pop(); -} diff --git a/task-archieve/climb-stairs/solution-3.js b/task-archieve/climb-stairs/solution-3.js deleted file mode 100644 index a807a8f..0000000 --- a/task-archieve/climb-stairs/solution-3.js +++ /dev/null @@ -1,20 +0,0 @@ -function climbStairs(n) { - if (n <= 1) { - return n; - } - - let step1 = 1; - let step2 = 2; - let i = 3; - - while (i < n + 1) { - const currentStep = step1 + step2; - - step1 = step2; - step2 = currentStep; - - i++; - } - - return step2; -} diff --git a/task-archieve/climb-stairs/solution.js b/task-archieve/climb-stairs/solution.js deleted file mode 100644 index a75b7e9..0000000 --- a/task-archieve/climb-stairs/solution.js +++ /dev/null @@ -1,12 +0,0 @@ -function climbStairs(n) { - const numbers = [0, 1, 1, 2]; - - let i = 3; - - while (i < n + 1) { - numbers.push(numbers[i - 1] + numbers[i]); - i++; - } - - return numbers[n + 1]; -} diff --git a/task-archieve/climb-stairs/task.md b/task-archieve/climb-stairs/task.md deleted file mode 100644 index 7fd7ccf..0000000 --- a/task-archieve/climb-stairs/task.md +++ /dev/null @@ -1,49 +0,0 @@ -# Climbing Stairs - -You are climbing a staircase. It takes `n` steps to reach the top - -Each time you can either climb `1` or `2` steps. In how many distinct ways can you climb to the top? - -__Example 1:__ - -``` -Input: n = 2 -Output: 2 -Explanation: There are two ways to climb to the top: - 1. 1 step + 1 step - 2. 2 steps -``` - -__Example 2:__ - -``` -Input: n = 3 -Output: 3 -Explanation: There are three ways to climb to the top: - 1. 1 step + 1 step + 1 step - 2. 1 step + 2 steps - 3. 2 steps + 1 step -``` - -__Note:__ you need to write a function that returns _the number of ways to climb a staircase (integer)_ __not__ the possible combinations of steps to climb a staircase - -
- -Task Type - -This is a numbers task type. You need to use Fibonacci Sequence to solve it - -
- -
- -Hint - -You can store a Fibonacci Sequence in an array and you get `O(n)` memory complexity but you can also solve the task with `O(1)` memory complexity by using two counters instead of an array to get a Fibonacci Sequence - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) | [:white_check_mark: solution 2](./solution-2.js) | [:white_check_mark: solution 3](./solution-3.js) | -| :---: | :---: | :---: | :---: | diff --git a/task-archieve/combinations/solution.js b/task-archieve/combinations/solution.js deleted file mode 100644 index e5160de..0000000 --- a/task-archieve/combinations/solution.js +++ /dev/null @@ -1,24 +0,0 @@ -function combine(n, k) { - const result = []; - - function dfs(cur) { - if (cur.length === k) { - result.push([...cur]); - return; - } - - for (let i = (cur.at(-1) ?? 0) + 1; i <= n; i++) { - // instead of .concat we do .push/.pop - cur.push(i); - dfs(cur); - cur.pop(); - } - } - - dfs([]); - - return result; -} - -console.log('n=4, k=2', combine(4, 2)); -console.log('n=1, k=1', combine(1, 1)); diff --git a/task-archieve/combinations/task.md b/task-archieve/combinations/task.md deleted file mode 100644 index 314bd29..0000000 --- a/task-archieve/combinations/task.md +++ /dev/null @@ -1,87 +0,0 @@ -# Combinations - -Given two integers `n` and `k`, return _all possible combinations of_ `k` _numbers chosen from the range_ `[1, n]` - -You may return the answer in __any order__ - -__Example 1:__ - -``` -Input: n = 4, k = 2 -Output: [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]] -Explanation: There are 4 choose 2 = 6 total combinations -Note that combinations are unordered, i.e., [1,2] and [2,1] are considered to be the same combination -``` - -__Example 2:__ - -``` -Input: n = 1, k = 1 -Output: [[1]] -Explanation: There is 1 choose 1 = 1 total combination -``` - -
- -Task Type - -This task is for __*Recursive Backtracking*__ - -
- -
- -Hint - -This task is for __*Recursive Backtracking*__. Note that unlike the ["Permutations of a String" task](../../2\)%20Task%20Challanges.md#28-permutations-of-a-string), in this task we are supposed to return the output in __any order__. So for this task the order of the permutations doesn't matter. When the order of the permutations doesn't matter you should apply a permutations algorithm that is actually different from the one we saw before in the "Permutations of a String" task in order not to come up with duplicates (i.e., `[1,2]` and `[2,1]`) - -While in the "Permutations of a String" task we would iterate the array and take out one element out of the array and get the rest of the permutations by recursively backtracking thereby always splitting the array into smaller and smaller chunks what we need to do here is somewhat the opposite though similar: we need to apply the function that by recursively backtracking builds back the array into bigger and bigger chunks (appending elements on the right to the elements on the left) - -This is what the output of the function should look like: - -``` -Input: [1,2,3] -Output: [ - [], - [1], [2], [3], - [1,2],[1,3], [2,3] - [1,2,3], -] -``` - -Every level (for example `[1], [2], [3]` is level 1, `[1,2],[1,3], [2,3]` is level 2 and `[1,2,3]` is level 3) indicates the depth of the call stack (thus every next level is a recursive call) and every element separated by a space " " indicates iterations within the same function call - -Here is the function: - -```js -function backtrack(arr) { - const result = []; - - function dfs(cur, offset) { // depth first search - result.push(cur); - - if (offset === arr.length) { - return; - } - - for (let i = offset; i < arr.length; i++) { - dfs(cur.concat(arr[i]), i + 1); - } - } - - dfs([], 0); - - return result; -} -``` - -In order to solve the task you need to tweak this function to suit your needs - -__Note:__ we called the recursive function inside the `backtrack` function as `dfs` meaning _Depth-first Search_ because it behaves similarly to the Depth-first Search in Binary Trees (or Graphs) but please don't confuse the two: the Binary Trees versions can be found [here](../../corejs-codejam/test/07-yield-tests.js#L457), [here](../../corejs-codejam/task/07-yield-tasks.js#L113) and of course [here](../../snippets/Data%20Structures/binary-search-tree.js) - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) -| :---: | :---: | diff --git a/task-archieve/flatten-nonrecursive-v2/solution-2.js b/task-archieve/flatten-nonrecursive-v2/solution-2.js deleted file mode 100644 index d2494a0..0000000 --- a/task-archieve/flatten-nonrecursive-v2/solution-2.js +++ /dev/null @@ -1,23 +0,0 @@ -function flatten(array) { - const result = []; - const arraysToProcess = [array]; - - while (arraysToProcess.length > 0) { - const currentArray = arraysToProcess.pop(); - - while (currentArray.length) { - const element = currentArray.pop(); - - if (Array.isArray(element)) { - arraysToProcess.push(currentArray, element); - break; - } else { - result.push(element); - } - } - } - - return result.reverse(); -} - -console.log(flatten([1,2,3,[4,[5]],[6],7])); diff --git a/task-archieve/flatten-nonrecursive-v2/solution.js b/task-archieve/flatten-nonrecursive-v2/solution.js deleted file mode 100644 index b695bc2..0000000 --- a/task-archieve/flatten-nonrecursive-v2/solution.js +++ /dev/null @@ -1,18 +0,0 @@ -function flatten(array) { - var stack = [array]; - var result = []; - - while (stack.length > 0) { - var element = stack.pop(); - if (Array.isArray(element)) { - for (var i = element.length - 1; i >= 0; i--) { - stack.push(element[i]); - } - } else { - result.push(element); - } - } - return result; -} - -console.log(flatten([1,2,3,[4,[5]],[6],7])); diff --git a/task-archieve/flatten-nonrecursive-v2/task.md b/task-archieve/flatten-nonrecursive-v2/task.md deleted file mode 100644 index a81a88d..0000000 --- a/task-archieve/flatten-nonrecursive-v2/task.md +++ /dev/null @@ -1,26 +0,0 @@ -# Flatten non-recursive v2 - -Your task is to write a function that flattens the array like so: - -```js -flatten([1,2,3,[4,[5]],[6],7]); // -> [1,2,3,4,5,6,7] -``` - -So we need to unpack the arrays inside this array (and leave other data types untouched) - -But the difficulty is that you can only use `.push()` and `.pop()` methods of the `Array` because all the other methods are badly optimized across different JS engines in different browsers - -Also you cannot use recursion because an array can be very big and nested very deep and you may thus get a stack overflow error - -
- -Task Type - -You can achieve the non-recursive solution by using a simple "stack and while loop" technique but at least one way of solving this means pushing elements into the stack in reverse order - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) | [:white_check_mark: solution 2](./solution-2.js) | -| :---: | :---: | :---: | diff --git a/task-archieve/intersection-intervals/solution-2.js b/task-archieve/intersection-intervals/solution-2.js deleted file mode 100644 index f418717..0000000 --- a/task-archieve/intersection-intervals/solution-2.js +++ /dev/null @@ -1,46 +0,0 @@ -console.log(intersection( - [[8, 12], [17, 22]], - [[5, 11], [14, 18], [20, 23]] -)); // [[8, 11], [17, 18], [20, 22]] - -console.log(intersection( - [[9, 15], [18, 21]], - [[10, 14], [21, 22]] -)); // [[10, 14]] - -function intersection(user1, user2) { - const result = []; - let n = 0; - let m = 0; - - while (n < user1.length) { - const interval = getInterval(user1[n], user2[m]); - - if (interval) { - result.push(interval); - m++; - } else { - n++; - } - } - - return result; -} - -function getInterval(interval1, interval2) { - if (!interval1 || !interval2) { - return null; - } - - const [start1, end1] = interval1; - const [start2, end2] = interval2; - - if (start1 < end2 && start2 < end1) { - return [ - Math.max(start1, start2), - Math.min(end1, end2) - ]; - } - - return null; -} diff --git a/task-archieve/intersection-intervals/solution.js b/task-archieve/intersection-intervals/solution.js deleted file mode 100644 index 2b7b903..0000000 --- a/task-archieve/intersection-intervals/solution.js +++ /dev/null @@ -1,28 +0,0 @@ -console.log(intersection( - [[8, 12], [17, 22]], - [[5, 11], [14, 18], [20, 23]] -)); // [[8, 11], [17, 18], [20, 22]] - -console.log(intersection( - [[9, 15], [18, 21]], - [[10, 14], [21, 22]] -)); // [[10, 14]] - -function intersection(user1, user2) { - const list = []; - let i1 = 0; - let i2 = 0; - - while (i1 < user1.length && i2 < user2.length) { - const leftOffset = Math.max(user1[i1][0], user2[i2][0]); - const rightOffset = Math.min(user1[i1][1], user2[i2][1]); - - if (rightOffset > leftOffset) { - list.push([leftOffset, rightOffset]); - } - - user1[i1][1] < user2[i2][1] ? ++i1 : ++i2; - } - - return list; -} diff --git a/task-archieve/intersection-intervals/task.md b/task-archieve/intersection-intervals/task.md deleted file mode 100644 index fe98e57..0000000 --- a/task-archieve/intersection-intervals/task.md +++ /dev/null @@ -1,30 +0,0 @@ -# Intersection of intervals - -We have two sorted lists of intervals indicating from which hour until which two users were online (1st array is 1st user and 2nd array is 2nd user). The start of each interval is always less than the end - -We need to calculate and return a new list of intervals indicating the intervals when both users were online - -_Examples:_ - -``` -user1 [(8, 12), (17, 22)] -user2 [(5, 11), (14, 18), (20, 23), (42, 55)] - => [(8, 11), (17, 18), (20, 22)] - -user1 [(9, 15), (18, 21)] -user2 [(10, 14), (21, 22)] - => [(10, 14)] -``` - -
- -Task Type - -It is one of those tasks where you use two pointers (save indexes like `i` and `j` to a variable, `i` is for the 1st array and `j` is for the 2nd array) to iterate __two__ arrays _specially_ for example by increasing / decrasing either one or the other or both pointers per iteration. The part of the "Merge Sort" algorithm that checks two sub-arrays uses similar mechanics ([link](../../snippets/algorithms/merge-sort.js#L12)) - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) | [:white_check_mark: solution 2](./solution-2.js) | -| :---: | :---: | :---: | diff --git a/task-archieve/keygen/solution.js b/task-archieve/keygen/solution.js deleted file mode 100644 index 87e8c2a..0000000 --- a/task-archieve/keygen/solution.js +++ /dev/null @@ -1,29 +0,0 @@ -// min included, max excluded -function random(min, max) { - return Math.floor(Math.random() * (max - min)) + min; -} - -function keygen(len, sum) { - if (len === 1) { - return [sum]; - } - - const res = []; - let f = null; - - while (sum > 0) { - if (len - res.length > 1) { - f = random(1, Math.floor(sum / 2)); - } else { - f = sum; - } - - res.push(f); - sum -= f; - } - - return res; -} - -console.log('keygen(5, 10)', keygen(5, 10)); -console.log('keygen(4, 13)', keygen(4, 13)); diff --git a/task-archieve/keygen/task.md b/task-archieve/keygen/task.md deleted file mode 100644 index ea7b99a..0000000 --- a/task-archieve/keygen/task.md +++ /dev/null @@ -1,31 +0,0 @@ -# Keygen - -Your task is to write a function that accepts two arguments: -1. count of elements in array -2. sum of these elements (the elements of the array are numbers) - -The function should randomly generate the array that fits the requirements above. Also there should not be zeros in the generated array - -Here are a few examples: - -```js -function keygen(count, sum) { - // ...your code -} - -keygen(5, 10); // => [3, 2, 1, 3, 1] -keygen(4, 13); // => [2, 5, 3, 3] -``` - -
- -Task Type - -This is more of a numbers task type than any of the array task types - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) -| :---: | :---: | diff --git a/task-archieve/longest-letter-subsequence/solution.js b/task-archieve/longest-letter-subsequence/solution.js deleted file mode 100644 index 9163523..0000000 --- a/task-archieve/longest-letter-subsequence/solution.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @param {string} str - * @param {number} K - */ -function longestStr(str, K) { - const registry = {}; - let start = 0; - let end = 0; - let max = 0; - - while (end <= str.length) { - const startLetter = str[start]; - const endLetter = str[end]; - const count = Object.keys(registry).length; - - if (count === K) { - max = Math.max(max, - Object.values(registry).reduce((a, b) => a + b, 0) - ); - } - - if (end === str.length) { - // we also break here because we need to consider the last letter and thus evaluate the if above - break; - } - - if (count <= K) { - registry[endLetter] = (registry[endLetter] ?? 0) + 1; - end++; - } else { - registry[startLetter]--; - start++; - if (registry[startLetter] === 0) { - delete registry[startLetter]; - } - } - } - - return max; -} diff --git a/task-archieve/longest-letter-subsequence/task.md b/task-archieve/longest-letter-subsequence/task.md deleted file mode 100644 index b3993c2..0000000 --- a/task-archieve/longest-letter-subsequence/task.md +++ /dev/null @@ -1,32 +0,0 @@ -# Longest sequence of letters - -You are given a string of length `L` composed of `N` different letters. Your task is to find the longest substring that would consist of at least `K` different letters - -__Example:__ -string `'aaccdd'` if `L = 6` and `N = 3` and -- `K=1` then `2` -- `K=2` then `4` -- `K=3` then `6` - -```js -longestStr('aaccdd', 1); // L=6 N=3 K=1 result: 2 -longestStr('aaccdd', 2); // L=6 N=3 K=2 result: 4 -longestStr('aaccdd', 3); // L=6 N=3 K=3 result: 6 -longestStr('aabaaccdd', 3); // L=9 N=4 K=3 result: 7 -longestStr('ababababccddddddd', 3); // L=17 N=4 K=3 result: 10 -``` - -
- -Task Type - -It is one of those tasks where you use two pointers (save indexes like `i` and `j` to a variable) to iterate an array _specially_ for example by increasing / decrasing either one or the other or both pointers per iteration. Here is [another task](../most-water/task.md) whose solution uses similar mechanics - -But for this particular task you may also need to enable the _power of hashmap_ - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) -| :---: | :---: | diff --git a/task-archieve/longest-sequence-of-1s/solution.js b/task-archieve/longest-sequence-of-1s/solution.js deleted file mode 100644 index 355e05e..0000000 --- a/task-archieve/longest-sequence-of-1s/solution.js +++ /dev/null @@ -1,25 +0,0 @@ -function countOnes(array) { - let max = 0; - let current = 0; - let prev = 0; - - for (let i = 0; i < array.length; i++) { - if (array[i] === 1) { - current++; - } - - if (array[i] === 0) { - prev = current; - current = 0; - } - - max = Math.max(current + prev, max); - } - - return max === array.length ? max - 1 : max; -} - -console.log(countOnes([1, 0])); // 1 -console.log(countOnes([1, 1])); // 1 -console.log(countOnes([0, 0])); // 0 -console.log(countOnes([1, 1, 1, 0, 1, 0, 0, 1, 1, 1])); // 4 diff --git a/task-archieve/longest-sequence-of-1s/task.md b/task-archieve/longest-sequence-of-1s/task.md deleted file mode 100644 index 54c4a30..0000000 --- a/task-archieve/longest-sequence-of-1s/task.md +++ /dev/null @@ -1,24 +0,0 @@ -# Longest sequence of 1's - -Your task is to implement algorithm that finds the longest sequence of 1's in array consisting of 1's and 0's. For this task you also have to -exclude at least 1 element out of the array, for example: - -```js -countOnes([1, 0]); // 1 -countOnes([1, 1]); // 1 (because we have to throw away at least one element, thus we throw away 1) -countOnes([0, 0]); // 0 -countOnes([1, 1, 1, 0, 1, 0, 0, 1, 1, 1]); // 4 (we throw away 0 at index 3 and get four 1's) -``` - -
- -Task Type - -It is one of those tasks where you use one pointer to iterate the array as well as one or more counters that we may or may not reset sometimes - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) -| :---: | :---: | diff --git a/task-archieve/matrix-diagonal-sort/solution.js b/task-archieve/matrix-diagonal-sort/solution.js deleted file mode 100644 index 3c02f5d..0000000 --- a/task-archieve/matrix-diagonal-sort/solution.js +++ /dev/null @@ -1,65 +0,0 @@ -function diagonalSort(matrix) { - for (let start = 0; start < matrix[0].length; start++) { - const tmp = []; - let i = 0; - let j = start; - - while (matrix[i]?.[j] !== undefined) { - tmp.push(matrix[i][j]); - - i++; - j++; - } - - tmp.sort((a, b) => a - b); - - i = 0; - j = start; - let k = 0; - - while (matrix[i]?.[j] !== undefined) { - matrix[i][j] = tmp[k]; - - i++; - j++; - k++ - } - } - - for (let start = 1; start < matrix.length; start++) { - const tmp = []; - let i = start; - let j = 0; - - while (matrix[i]?.[j] !== undefined) { - tmp.push(matrix[i][j]); - - i++; - j++; - } - - tmp.sort((a, b) => a - b); - - i = start; - j = 0; - let k = 0; - - while (matrix[i]?.[j] !== undefined) { - matrix[i][j] = tmp[k]; - - i++; - j++; - k++ - } - } - - return matrix; -} - -console.log( - diagonalSort([ - [3,3,1,1], - [2,2,1,2], - [1,1,1,2] - ]) -); diff --git a/task-archieve/matrix-diagonal-sort/task.md b/task-archieve/matrix-diagonal-sort/task.md deleted file mode 100644 index e04422e..0000000 --- a/task-archieve/matrix-diagonal-sort/task.md +++ /dev/null @@ -1,47 +0,0 @@ -# Sort the Matrix diagonally - -Your task is to sort the Matrix diagonally meaning you should sort every diagonal row (going diagonally left to right and top to bottom) - -Here is an example: - -```js -// -> Unsorted Matrix: -[ -[3,3,1,1], -[2,2,1,2], -[1,1,1,2] -] - -// <- Diagonally-sorted Matrix: -[ -[1,1,1,1], -[1,2,2,2], -[1,2,3,3] -] -``` - -
- -Hint - -- `1.` Iterate the first row (subarray at index 0) and _for each element_ do the following: - - `1.1` Create a temporary array - - `1.2` Go diagonally (left to right and top to bottom) and put each element into the temporary array - - `1.3` Sort the temporary array - - `1.4` Go diagonally again (left to right and top to bottom) over the same diagonal lines of the subarrays and replace each element with the element from the temporary array -- `2.` Starting at the second row (subarrays at index 1+) we can iterate and sort via a temporary array (see point 1. above) not each element but only the first element because the diagonal lines along the rest of the elements in the subarrays at index 1+ have already been sorted in point 1. above - -
- -
- -Task Type - -This is a Matrix type task using Matrix mechanics or you could also say that you need to look at the _relation_ between the indexes of the array like [here](../zigzag-conversion/task.md). - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) -| :---: | :---: | diff --git a/task-archieve/most-water/assets/hint_water_trap_1.png b/task-archieve/most-water/assets/hint_water_trap_1.png deleted file mode 100644 index dae8bad..0000000 Binary files a/task-archieve/most-water/assets/hint_water_trap_1.png and /dev/null differ diff --git a/task-archieve/most-water/assets/hint_water_trap_2.png b/task-archieve/most-water/assets/hint_water_trap_2.png deleted file mode 100644 index 69b0896..0000000 Binary files a/task-archieve/most-water/assets/hint_water_trap_2.png and /dev/null differ diff --git a/task-archieve/most-water/assets/question_11.jpg b/task-archieve/most-water/assets/question_11.jpg deleted file mode 100644 index 7661efe..0000000 Binary files a/task-archieve/most-water/assets/question_11.jpg and /dev/null differ diff --git a/task-archieve/most-water/solution.js b/task-archieve/most-water/solution.js deleted file mode 100644 index 6dbe38b..0000000 --- a/task-archieve/most-water/solution.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @param {number[]} height - * @return {number} - */ -function maxArea(height) { - let max = 0; - let i = 0; - let j = height.length - 1; - - while (i < j) { - const v1 = height[i]; - const v2 = height[j]; - const amount = Math.min(v1, v2) * (j - i); - - if (max < amount) { - max = amount; - } - - if (v1 <= v2) { - while (i < j) { - i++; - if (height[i] >= v2) { - break; - } - } - } - - if (v2 < v1) { - while(j > i) { - j--; - if (height[j] >= v1) { - break; - } - } - } - } - - return max; -}; - -[ - [1,8,6,2,5,4,8,3,7], // 7 * 7 = 49 - [3, 9, 3, 4, 7, 2, 12, 6] // 5 * 9 = 45 -].forEach((v) => { - console.log(`answer [${v}]`, maxArea(v)); -}); diff --git a/task-archieve/most-water/task.md b/task-archieve/most-water/task.md deleted file mode 100644 index b7ab77d..0000000 --- a/task-archieve/most-water/task.md +++ /dev/null @@ -1,61 +0,0 @@ -# Container With Most Water - -You are given an integer array `height` of length `n`. There are `n` vertical lines drawn such that the two endpoints of the `i'th` line are `(i, 0)` and `(i, height[i])` - -Find two lines that together with the x-axis form a container, such that the container contains the most water - -Return _the maximum amount of water a container can store_ - -__Notice__ that you may not slant the container - -__Example 1:__ - - - -__Input:__ `height = [1,8,6,2,5,4,8,3,7]` - -__Output:__ `49` - -__Explanation:__ The above vertical lines are represented by array `[1,8,6,2,5,4,8,3,7]`. In this case, the max area of water (blue section) the container can contain is `49` - -__Example 2:__ - -``` -Input: height = [1,1] -Output: 1 -``` - -
- -Hint 1 - -The aim is to maximize the area formed between the vertical lines. The area of any container is calculated using the shorter line as length and the distance between the lines as the width of the rectangle - -`Area = length of shorter vertical line * distance between lines` - -We can definitely get the maximum width container as the outermost lines have the maximum distance between them. However, this container __might not be the maximum in size__ as one of the vertical lines of -this container could be really short - -Contemplate this example: -``` -[3, 9, 3, 4, 7, 2, 12, 6] -``` - - -
- - -
- -
- -Hint 2 - -Start with the maximum width container and go to a shorter width container if there is a vertical line longer than the current containers shorter line. This way we are compromising on the width but we are looking forward to a longer length container - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) -| :---: | :---: | diff --git a/task-archieve/remove-duplicates-v2/solution.js b/task-archieve/remove-duplicates-v2/solution.js deleted file mode 100644 index 67a2dce..0000000 --- a/task-archieve/remove-duplicates-v2/solution.js +++ /dev/null @@ -1,13 +0,0 @@ -const MAX_UNIQUE = 2; - -function removeDuplicates(nums) { - let k = 0; - - for (const num of nums) { - if (k < MAX_UNIQUE || num > nums[k - MAX_UNIQUE]) { - nums[k++] = num; - } - } - - return k; -} diff --git a/task-archieve/remove-duplicates-v2/task.md b/task-archieve/remove-duplicates-v2/task.md deleted file mode 100644 index 0efaf4f..0000000 --- a/task-archieve/remove-duplicates-v2/task.md +++ /dev/null @@ -1,50 +0,0 @@ -# Remove Duplicates from Sorted Array v2 - -Given an integer array `nums` sorted in __non-decreasing order__, remove some duplicates __in-place__ such that each unique element appears __at most twice__. The __relative order__ of the elements should be kept the __same__ - -Since it is impossible to change the length of the array in some languages, you must instead have the result be placed in the __first part__ of the array `nums`. More formally, if there are `k` elements after removing the duplicates, then the first `k` elements of `nums` should hold the final result. It does not matter what you leave beyond the first `k` elements - -Return `k` _after placing the final result in the first_ `k` _slots of_ `nums` - -Do __not__ allocate extra space for another array. You must do this by __modifying the input array in-place__ with `O(1)` extra memory - -__Example 1:__ - -``` -Input: nums = [1,1,1,2,2,3] -Output: 5, nums = [1,1,2,2,3,_] -Explanation: Your function should return k = 5, with the first five elements of nums being 1, 1, 2, 2 and 3 respectively. -It does not matter what you leave beyond the returned k (hence they are underscores). -``` - -__Example 2:__ - -``` -Input: nums = [0,0,1,1,1,1,2,3,3] -Output: 7, nums = [0,0,1,1,2,3,3,_,_] -Explanation: Your function should return k = 7, with the first seven elements of nums being 0, 0, 1, 1, 2, 3 and 3 respectively. -It does not matter what you leave beyond the returned k (hence they are underscores). -``` - -
- -Task Type - -This is an in-place algorithm just like we have seen in [that task](../sort-letters-two-arrays/task.md) except instead of swapping the elements we are going to be _overwriting_ the elements of the array with new values - -So in other words it is the same algorithm type as [that task](../sort-letters-two-arrays/task.md) except in this task we can see its counterpart type where we are overwriting elements of an array instead of swapping elements of an array - -There are only two types of in-place algorithms: swapping and overwriting. Here is a quote from Wikipedia to prove my point: - -""" - -_In computer science, an in-place algorithm is an algorithm which transforms input using no auxiliary data structure. However, a small amount of extra storage space is allowed for auxiliary variables. The input is usually overwritten by the output as the algorithm executes. An in-place algorithm updates its input sequence only through replacement or swapping of elements. An algorithm which is not in-place is sometimes called not-in-place or out-of-place._ - -""" - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) -| :---: | :---: | diff --git a/task-archieve/sort-letters-two-arrays/solution.js b/task-archieve/sort-letters-two-arrays/solution.js deleted file mode 100644 index 363b1cf..0000000 --- a/task-archieve/sort-letters-two-arrays/solution.js +++ /dev/null @@ -1,18 +0,0 @@ -function swap(array, i1, i2) { - ([array[i1], array[i2]] = [array[i2], array[i1]]); -} - -function solution(letters, indexes) { - /** - * for simplicity we use Bubble Sort here, but in real interview please use Quick Sort - * see ./snippets/algorithms/quick-sort.html - */ - for (let i = 1; i < indexes.length; i++) { - let j = i; - while (indexes[j] < indexes[j - 1] && j > 0) { - swap(indexes, j, j - 1); - swap(letters, j, j - 1); - j--; - } - } -} diff --git a/task-archieve/sort-letters-two-arrays/task.md b/task-archieve/sort-letters-two-arrays/task.md deleted file mode 100644 index 017b981..0000000 --- a/task-archieve/sort-letters-two-arrays/task.md +++ /dev/null @@ -1,75 +0,0 @@ -# Sort letters from one array via another array - -We have 2 arrays with a length equal to `n`: one filled with letters, the other filled with numbers (the number are from 0 to n-1) - -You gotta swap letters _in place_ in the 1st array such that the letters at indexes `i` from the 1st array correspond to numbers at indexes `i` from the 2nd array - -For example: - -``` -[D A B E C] [3 0 1 4 2] -> [A B C D E] -``` - -So we look at 0'th element: it is `D` in the 1st array and `3` in the 2nd array, therefore `D` should be at index `3` in the result array and so on for each letter, `A` to `0`, `B` to `1`, `E` to `4` and `C` to `2` - -The phrase "in place" in the extract above means that we don't create an intermediary array to return it, thus we gotta swap elements of the 1st array to get the result array - -You also have a memory constraint here: `O(1)` (it means that the more elements the arrays have should not icrease memory consumption, this is also why we have to swap elements of the arrays _in place_, without creating intermediary arrays) - -Note that you can mutate both of the arrays - -
- -Hint 1 - -We could jump over the elements of the 2nd array like so: - -- first element is `3`, therefore go to element at index `3` -- at index `3` we have `4`, therefore go to element at index `4` -- at index `4` we have `2`, therefore go to element at index `2` -- at index `2` we have `1`, therefore go to element at index `1` -- at index `1` we have `0`, therefore go to element at index `0` -- we have iterated the 2nd array - -If we do it like that also swapping the elements along the way we will indeed be able to match the arrays above but the problem here is that there can be a situation where you can be caught in a loop and therefore skip some part of the array, here is an example: - -``` -[D C B A E] [3 2 1 0 4] -3 -> 0 -> 3 -> ... -``` - -Therefore such solution, though clever, does not suit the requirements - -
- -
- -Hint 2 - -To solve this task you need to simply _sort_ the elements of the 2nd array (the numbers) and every time you swap the elements of the 2nd array you need to also likewise swap the same elements of the 1st array (the letters). As a result you are going to get the letters in the right order sorted thanks to the 2nd array - -
- -
- -Task Type - -We sort in place the 2nd array but together with the elements of the 2nd array we also swap the elements of the 1st array. There is a whole type of tasks that can be solved by swapping the elements of the array in a clever way (or in our case we swap the elements of the two arrays simultaneously) - -Here is another example of a solution for these kind of tasks with `O(n)` complexity though it doesn't solve this particular task: - -```js -function sort(array, order) { - for (var i = 0; i < order.length; i++) { - order[i] = array[order[i]]; - } - return order; -} -``` - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) -| :---: | :---: | diff --git a/task-archieve/task-type.md b/task-archieve/task-type.md deleted file mode 100644 index ba4dc87..0000000 --- a/task-archieve/task-type.md +++ /dev/null @@ -1,33 +0,0 @@ -## Task Archieve [:scroll:](./README.md) - -_Tasks grouped by_ `Task Type` - ---- - -- __Two Pointers One Array__ - - [Container With Most Water](./most-water/task.md) - - [Longest sequence of letters](./longest-letter-subsequence/task.md) -- __Two Pointers Two Arrays__ - - [Intersection of intervals](./intersection-intervals/task.md) -- __One Pointer One Array and One or More Counters__ - - [Longest sequence of 1's](./longest-sequence-of-1s/task.md) -- __Two Pointers Sliding Window Array__ - - [Best Time to Buy and Sell Stock](./best-time-to-buy-and-sell-stock/task.md) -- __Array Relation of Indexes and Values or Indexes to Values__ - - [Zigzag Conversion](./zigzag-conversion/task.md) -- __In-Place Swap and Overwrite__ - - [Sort letters from one array via another array](./sort-letters-two-arrays/task.md) - - [Remove Duplicates from Sorted Array v2](./remove-duplicates-v2/task.md) -- __While Loop and Stack__ - - [Flatten non-recursive v2](./flatten-nonrecursive-v2/task.md) -- __Matrix__ - - [Sort the Matrix diagonally](./matrix-diagonal-sort/task.md) -- __Numbers Math__ - - [Keygen](./keygen/task.md) -- __Fibonacci Sequence__ - - [Climbing Stairs](./climb-stairs/task.md) -- __Check if Puzzle is Solvable__ - - [Word Search](./word-search/task.md) - - [Sudoku Solver](../cheatsheet/sudoku.js) -- __Backtracking Depth-first Search of Array__ - - [Combinations](./combinations/task.md) diff --git a/task-archieve/word-search/assets/word1.jpeg b/task-archieve/word-search/assets/word1.jpeg deleted file mode 100644 index 583f5a6..0000000 Binary files a/task-archieve/word-search/assets/word1.jpeg and /dev/null differ diff --git a/task-archieve/word-search/assets/word2.jpeg b/task-archieve/word-search/assets/word2.jpeg deleted file mode 100644 index 5bce855..0000000 Binary files a/task-archieve/word-search/assets/word2.jpeg and /dev/null differ diff --git a/task-archieve/word-search/assets/word3.jpeg b/task-archieve/word-search/assets/word3.jpeg deleted file mode 100644 index 5683faa..0000000 Binary files a/task-archieve/word-search/assets/word3.jpeg and /dev/null differ diff --git a/task-archieve/word-search/solution-2.js b/task-archieve/word-search/solution-2.js deleted file mode 100644 index 536f933..0000000 --- a/task-archieve/word-search/solution-2.js +++ /dev/null @@ -1,21 +0,0 @@ -function exist(board, word) { - const traverse = (x, y, i) => { - if (i === word.length) return true; - - if (board[y]?.[x] !== word[i]) return false; - - board[y][x] = '#'; - - for (const [dx, dy] of [[-1, 0], [0, -1], [1, 0], [0, 1]]) { - if (traverse(x + dx, y + dy, i + 1)) { - return true; - } - } - - board[y][x] = word[i]; - - return false; - } - - return board.some((row, y) => row.some((_col, x) => traverse(x, y, 0))); -} diff --git a/task-archieve/word-search/solution.js b/task-archieve/word-search/solution.js deleted file mode 100644 index a033130..0000000 --- a/task-archieve/word-search/solution.js +++ /dev/null @@ -1,100 +0,0 @@ -function exist(board, word) { - for (let i = 0; i < board.length; i++) { - for (let j = 0; j < board[i].length; j++) { - if (check(board, word, i, j)) { - return true; - } - } - } - - return false; -} - -function check(board, word, i, j, pos = 0, checked = {}) { - if (board[i][j] !== word[pos]) { - return false; - } - - checked[getCheckedKey(i ,j)] = true; - - if (pos === word.length - 1) { - return true; - } - - const NEIGHBORS = [ - [1, 0], - [0, 1], - [-1, 0], - [0, -1] - ]; - - for (const [iNeighbor, jNeighbor] of NEIGHBORS) { - const iNext = i + iNeighbor; - const jNext = j + jNeighbor; - - if (checked[getCheckedKey(iNext, jNext)]) { - continue; - } - - if (isOutOfBounds(board, iNext, jNext)) { - continue; - } - - if (check(board, word, iNext, jNext, pos + 1, checked)) { - return true; - } - } - - checked[getCheckedKey(i ,j)] = false; - - return false; -} - -function getCheckedKey(i, j) { - return [i, j].join('-'); -} - -function isOutOfBounds(board, i, j) { - if (i >= board.length || i < 0) { - return true; - } - - if (j >= board[i].length || j < 0) { - return true; - } - - return false; -} - -console.log('Example 1, true', exist( - [ - ['A','B','C','E'], - ['S','F','C','S'], - ['A','D','E','E'], - ], - 'ABCCED' -)); -console.log('Example 2, true', exist( - [ - ['A','B','C','E'], - ['S','F','C','S'], - ['A','D','E','E'], - ], - 'SEE' -)); -console.log('Example 3, false', exist( - [ - ['A','B','C','E'], - ['S','F','C','S'], - ['A','D','E','E'], - ], - 'ABCB' -)); -console.log('Example 4, true', exist( - [ - ['A','B','C','E'], - ['S','F','E','S'], - ['A','D','E','E'] - ], - 'ABCESEEEFS' -)); diff --git a/task-archieve/word-search/task.md b/task-archieve/word-search/task.md deleted file mode 100644 index 3ca9e15..0000000 --- a/task-archieve/word-search/task.md +++ /dev/null @@ -1,47 +0,0 @@ -# Word Search - -Given an `m x n` grid of characters `board` and a string `word`, return `true` _if_ `word` _exists in the grid_ - -The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once - -__Example 1:__ - - - -``` -Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED" -Output: true -``` - -__Example 2:__ - - - -``` -Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE" -Output: true -``` - -__Example 3:__ - - - -``` -Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB" -Output: false -``` - -
- -Task Type - -This task is similar to [Sudoku solver](../../cheatsheet/sudoku.js) where you call a function to see if you can solve the game starting at a certain position as you iterate through the board - -In this task we should see if a letter matches the one in the word and if so recursively check its neighbors as well as marking the letters that we looked at - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) | [:white_check_mark: solution 2](./solution-2.js) | -| :---: | :---: | :---: | diff --git a/task-archieve/zigzag-conversion/solution.js b/task-archieve/zigzag-conversion/solution.js deleted file mode 100644 index fcf6311..0000000 --- a/task-archieve/zigzag-conversion/solution.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @param {string} s - * @param {number} numRows - * @return {string} - */ -function convert(s, numRows) { - if (s.length === 1) { - return s; - } - - const numOfVertical = numRows > 2 ? numRows - 2 : 0; - const incrementor = numRows + numOfVertical; - let out = ''; - - for (let i = 0; i < numRows; i++) { - const isFirstRow = i === 0; - const isLastRow = i === numRows - 1; - - if (!isLastRow) { - out += s[i]; - } - - let j = 0; - - while (true) { - const index1 = (incrementor - i) + (incrementor * j); - - if (!s[index1]) { - break; - } else { - out += s[index1]; - } - - if (!isFirstRow && !isLastRow) { - const index2 = (incrementor + i) + (incrementor * j); - if (s[index2]) { - out += s[index2]; - } - } - - j++; - } - } - - return out; -}; - -[ - ['PAYPALISHIRING', 3, 'PAHNAPLSIIGYIR'], - ['PAYPALISHIRING', 4, 'PINALSIGYAHRPI'], - ['A', 1, 'A'], -].forEach(([s, numRows, expected]) => { - const actual = convert(s, numRows); - console.log(); - console.log(`Input: s="${s}", numRows=${numRows}`); - console.log(`Output: "${actual}"`); - console.log(`PASS: ${actual === expected}`); -}); diff --git a/task-archieve/zigzag-conversion/task.md b/task-archieve/zigzag-conversion/task.md deleted file mode 100644 index d93013d..0000000 --- a/task-archieve/zigzag-conversion/task.md +++ /dev/null @@ -1,89 +0,0 @@ -# Zigzag Conversion - -The string `"PAYPALISHIRING"` is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility) - -``` -P A H N -A P L S I I G -Y I R -``` - -And then read line by line: `"PAHNAPLSIIGYIR"` - -Write the code that will take a string and make this conversion given a number of rows: - -``` -string convert(string s, int numRows); -``` - -__Example 1:__ - -__Input:__ `s = "PAYPALISHIRING", numRows = 3` - -__Output:__ `"PAHNAPLSIIGYIR"` - -__Example 2:__ - -__Input:__ `s = "PAYPALISHIRING", numRows = 4` - -__Output:__ `"PINALSIGYAHRPI"` - -__Explanation:__ - -``` -P I N -A L S I G -Y A H R -P I -``` - -__Example 3:__ - -__Input:__ `s = "A", numRows = 1` - -__Output:__ `"A"` - -
- -Task Type - -To solve this task you need to analyze the _relation_ between the indexes of the characters in the string - -
- -
- -Pseudo code - -``` -// SPOILER ALERT - -/** - -// NUMBER OF VERTICAL DIGITS = n - 2 (used below) -// KEY = 6 (n + (n - 2), n = 4) - -0 6 12 // 0 + 6, ... OR 6 - 0 + 6 ... -1 5 7 11 13 // 1 + 6, ... AND 6 - 1 + 6 ... -2 4 8 10 14 // 2 + 6, ... AND 6 - 2 + 6 ... -3 9 15 // 3 + 6, ... OR 6 - 3 + 6 ... - -0, 6, 12, 1, 5, 7, 11, 13, 2, 3, 8, 10, 14, 3, 9, 15 - -/** - -/** -0 8 -1 7 9 -2 6 10 -3 5 11 -4 12 -**/ -``` - -
- ---- - -| [:arrow_left: back](../README.md) | [:white_check_mark: solution](./solution.js) -| :---: | :---: |