diff --git a/1-two-sum.js b/1-two-sum.js deleted file mode 100755 index 4b4b8e13..00000000 --- a/1-two-sum.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} target - * @return {number[]} - */ -const twoSum = function(nums, target) { - const myObject = {}; - for (let i = 0; i < nums.length; i++) { - const complement = target - nums[i]; - if (myObject.hasOwnProperty(complement)) { - return [myObject[complement], i]; - } - myObject[nums[i]] = i; - } -}; diff --git a/1.two-sum.js b/1.two-sum.js new file mode 100644 index 00000000..613d465d --- /dev/null +++ b/1.two-sum.js @@ -0,0 +1,15 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +const twoSum = function(nums, target) { + const myObject = {}; + for (let i = 0; i < nums.length; i++) { + const complement = target - nums[i]; + if (myObject.hasOwnProperty(complement)) { + return [myObject[complement], i]; + } + myObject[nums[i]] = i; + } +}; diff --git a/10-regular-expression-matching.js b/10-regular-expression-matching.js deleted file mode 100755 index 5bd7918e..00000000 --- a/10-regular-expression-matching.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {string} s - * @param {string} p - * @return {boolean} - */ -const isMatch = function(s, p) { - let memory = new Array(s.length + 1) - .fill(0) - .map(e => new Array(p.length + 1).fill(-1)); - return memorySearch(s, 0, p, 0, memory); -}; - -const memorySearch = (s, i, p, k, memory) => { - if (memory[i][k] != -1) return memory[i][k]; - if (k == p.length) return i == s.length; - - let firstMatch = i < s.length && (s[i] == p[k] || p[k] == "."); - if (k + 1 < p.length && p[k + 1] == "*") { - memory[i][k] = - (firstMatch && memorySearch(s, i + 1, p, k, memory)) || - memorySearch(s, i, p, k + 2, memory); - } else { - memory[i][k] = firstMatch && memorySearch(s, i + 1, p, k + 1, memory); - } - return memory[i][k]; -}; diff --git a/10.regular-expression-matching.js b/10.regular-expression-matching.js new file mode 100644 index 00000000..dd9d6d53 --- /dev/null +++ b/10.regular-expression-matching.js @@ -0,0 +1,26 @@ +/** + * @param {string} s + * @param {string} p + * @return {boolean} + */ +const isMatch = function(s, p) { + let memory = new Array(s.length + 1) + .fill(0) + .map(e => new Array(p.length + 1).fill(-1)); + return memorySearch(s, 0, p, 0, memory); +}; + +const memorySearch = (s, i, p, k, memory) => { + if (memory[i][k] != -1) return memory[i][k]; + if (k == p.length) return i == s.length; + + let firstMatch = i < s.length && (s[i] == p[k] || p[k] == "."); + if (k + 1 < p.length && p[k + 1] == "*") { + memory[i][k] = + (firstMatch && memorySearch(s, i + 1, p, k, memory)) || + memorySearch(s, i, p, k + 2, memory); + } else { + memory[i][k] = firstMatch && memorySearch(s, i + 1, p, k + 1, memory); + } + return memory[i][k]; +}; diff --git a/100-same-tree.js b/100-same-tree.js deleted file mode 100755 index 6cdcd4b5..00000000 --- a/100-same-tree.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} p - * @param {TreeNode} q - * @return {boolean} - */ -const isSameTree = function(p, q) { - if(p == null && q == null) return true - if(p == null || q == null || p.val !== q.val) return false - return isSameTree(p.left, q.left) && isSameTree(p.right, q.right) -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} p - * @param {TreeNode} q - * @return {boolean} - */ -const isSameTree = function(p, q) { - if(p == null || q == null) return p === q - if(p.val !== q.val) return false - return isSameTree(p.left, q.left) && isSameTree(p.right, q.right) -}; diff --git a/100.same-tree.js b/100.same-tree.js new file mode 100644 index 00000000..396c8f59 --- /dev/null +++ b/100.same-tree.js @@ -0,0 +1,19 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} p + * @param {TreeNode} q + * @return {boolean} + */ +const isSameTree = function(p, q) { + if(p == null && q == null) return true + if(p == null || q == null || p.val !== q.val) return false + return isSameTree(p.left, q.left) && isSameTree(p.right, q.right) +}; + diff --git a/1000-minimum-cost-to-merge-stones.js b/1000.minimum-cost-to-merge-stones.js similarity index 100% rename from 1000-minimum-cost-to-merge-stones.js rename to 1000.minimum-cost-to-merge-stones.js diff --git a/1001-grid-illumination.js b/1001.grid-illumination.js similarity index 100% rename from 1001-grid-illumination.js rename to 1001.grid-illumination.js diff --git a/1002-find-common-characters.js b/1002.find-common-characters.js similarity index 100% rename from 1002-find-common-characters.js rename to 1002.find-common-characters.js diff --git a/1004-max-consecutive-ones-iii.js b/1004.max-consecutive-ones-iii.js similarity index 100% rename from 1004-max-consecutive-ones-iii.js rename to 1004.max-consecutive-ones-iii.js diff --git a/1005-maximize-sum-of-array-after-k-negations.js b/1005.maximize-sum-of-array-after-k-negations.js similarity index 100% rename from 1005-maximize-sum-of-array-after-k-negations.js rename to 1005.maximize-sum-of-array-after-k-negations.js diff --git a/1006-clumsy-factorial.js b/1006.clumsy-factorial.js similarity index 100% rename from 1006-clumsy-factorial.js rename to 1006.clumsy-factorial.js diff --git a/1008-construct-binary-search-tree-from-preorder-traversal.js b/1008.construct-binary-search-tree-from-preorder-traversal.js similarity index 100% rename from 1008-construct-binary-search-tree-from-preorder-traversal.js rename to 1008.construct-binary-search-tree-from-preorder-traversal.js diff --git a/1009-complement-of-base-10-integer.js b/1009-complement-of-base-10-integer.js deleted file mode 100644 index f88696bd..00000000 --- a/1009-complement-of-base-10-integer.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @param {number} N - * @return {number} - */ -const bitwiseComplement = function (N) { - if (N === 0) return 1 - // bitmask has the same length as N and contains only ones 1...1 - let bitmask = N - bitmask |= bitmask >> 1 - bitmask |= bitmask >> 2 - bitmask |= bitmask >> 4 - bitmask |= bitmask >> 8 - bitmask |= bitmask >> 16 - // flip all bits - return bitmask ^ N -} - -// another - -/** - * @param {number} N - * @return {number} - */ -const bitwiseComplement = function (N) { - let X = 1; - while (N > X) X = X * 2 + 1; - return N ^ X; -} - -// another - -/** - * @param {number} N - * @return {number} - */ -const bitwiseComplement = function (N) { - if (N === 0) return 1 - // l is a length of N in binary representation - const l = Math.floor(Math.log(N) / Math.log(2)) + 1 - // bitmask has the same length as num and contains only ones 1...1 - const bitmask = (1 << l) - 1 - // flip all bits - return bitmask ^ N -} diff --git a/1009.complement-of-base-10-integer.js b/1009.complement-of-base-10-integer.js new file mode 100644 index 00000000..9f36835b --- /dev/null +++ b/1009.complement-of-base-10-integer.js @@ -0,0 +1,17 @@ +/** + * @param {number} N + * @return {number} + */ +const bitwiseComplement = function (N) { + if (N === 0) return 1 + // bitmask has the same length as N and contains only ones 1...1 + let bitmask = N + bitmask |= bitmask >> 1 + bitmask |= bitmask >> 2 + bitmask |= bitmask >> 4 + bitmask |= bitmask >> 8 + bitmask |= bitmask >> 16 + // flip all bits + return bitmask ^ N +} + diff --git a/101-symmetric-tree.js b/101.symmetric-tree.js similarity index 100% rename from 101-symmetric-tree.js rename to 101.symmetric-tree.js diff --git a/1011-capacity-to-ship-packages-within-d-days.js b/1011.capacity-to-ship-packages-within-d-days.js similarity index 100% rename from 1011-capacity-to-ship-packages-within-d-days.js rename to 1011.capacity-to-ship-packages-within-d-days.js diff --git a/1012-complement-of-base-10-integer.js b/1012.complement-of-base-10-integer.js similarity index 100% rename from 1012-complement-of-base-10-integer.js rename to 1012.complement-of-base-10-integer.js diff --git a/1013-pairs-of-songs-with-total-durations-divisible-by-60.js b/1013.pairs-of-songs-with-total-durations-divisible-by-60.js similarity index 100% rename from 1013-pairs-of-songs-with-total-durations-divisible-by-60.js rename to 1013.pairs-of-songs-with-total-durations-divisible-by-60.js diff --git a/1014-capacity-to-ship-packages-within-d-days.js b/1014.capacity-to-ship-packages-within-d-days.js similarity index 100% rename from 1014-capacity-to-ship-packages-within-d-days.js rename to 1014.capacity-to-ship-packages-within-d-days.js diff --git a/1015-numbers-with-repeated-digits.js b/1015.numbers-with-repeated-digits.js similarity index 100% rename from 1015-numbers-with-repeated-digits.js rename to 1015.numbers-with-repeated-digits.js diff --git a/1017-convert-to-base-2.js b/1017-convert-to-base-2.js deleted file mode 100644 index 044313c4..00000000 --- a/1017-convert-to-base-2.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @param {number} N - * @return {string} - */ -const baseNeg2 = function(N) { - return negBase(N, -2) -}; - -function negBase(val, base) { - if(val === 0) return '0' - let result = ''; - while (val !== 0) { - let remainder = val % base; - val = Math.trunc(val / base); - if (remainder < 0) { - remainder += -base; - val += 1; - } - result = remainder + result; - } - return result; -} - -// another - -/** - * @param {number} N - * @return {string} - */ -const baseNeg2 = function(N) { - if (N === 0) return "0"; - let res = '' - while(N !== 0) { - res = (N & 1) + res - N = -(N >> 1) - } - return res; -}; diff --git a/1017.convert-to-base-2.js b/1017.convert-to-base-2.js new file mode 100644 index 00000000..1df3eebb --- /dev/null +++ b/1017.convert-to-base-2.js @@ -0,0 +1,23 @@ +/** + * @param {number} N + * @return {string} + */ +const baseNeg2 = function(N) { + return negBase(N, -2) +}; + +function negBase(val, base) { + if(val === 0) return '0' + let result = ''; + while (val !== 0) { + let remainder = val % base; + val = Math.trunc(val / base); + if (remainder < 0) { + remainder += -base; + val += 1; + } + result = remainder + result; + } + return result; +} + diff --git a/1018-binary-prefix-divisible-by-5.js b/1018.binary-prefix-divisible-by-5.js similarity index 100% rename from 1018-binary-prefix-divisible-by-5.js rename to 1018.binary-prefix-divisible-by-5.js diff --git a/102-binary-tree-level-order-traversal.js b/102-binary-tree-level-order-traversal.js deleted file mode 100755 index 4df53ee9..00000000 --- a/102-binary-tree-level-order-traversal.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number[][]} - */ -const levelOrder = function(root) { - const res = []; - if (root == null) return res; - let next = [root]; - while (next.length > 0) { - next = tr(res, next); - } - return res; -}; - -function tr(res, nodeArr) { - const arr = []; - const nextLevelNodes = []; - for (let i = 0; i < nodeArr.length; i++) { - arr.push(nodeArr[i].val); - if (nodeArr[i].left) { - nextLevelNodes.push(nodeArr[i].left); - } - if (nodeArr[i].right) { - nextLevelNodes.push(nodeArr[i].right); - } - } - if (arr.length) res.push(arr); - return nextLevelNodes; -} diff --git a/102.binary-tree-level-order-traversal.js b/102.binary-tree-level-order-traversal.js new file mode 100644 index 00000000..1ea8f7fd --- /dev/null +++ b/102.binary-tree-level-order-traversal.js @@ -0,0 +1,36 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +const levelOrder = function(root) { + const res = []; + if (root == null) return res; + let next = [root]; + while (next.length > 0) { + next = tr(res, next); + } + return res; +}; + +function tr(res, nodeArr) { + const arr = []; + const nextLevelNodes = []; + for (let i = 0; i < nodeArr.length; i++) { + arr.push(nodeArr[i].val); + if (nodeArr[i].left) { + nextLevelNodes.push(nodeArr[i].left); + } + if (nodeArr[i].right) { + nextLevelNodes.push(nodeArr[i].right); + } + } + if (arr.length) res.push(arr); + return nextLevelNodes; +} diff --git a/1020-partition-array-into-three-parts-with-equal-sum.js b/1020.partition-array-into-three-parts-with-equal-sum.js similarity index 100% rename from 1020-partition-array-into-three-parts-with-equal-sum.js rename to 1020.partition-array-into-three-parts-with-equal-sum.js diff --git a/1021-best-sightseeing-pair.js b/1021-best-sightseeing-pair.js deleted file mode 100644 index d5c4fbeb..00000000 --- a/1021-best-sightseeing-pair.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @param {number[]} A - * @return {number} - */ -const maxScoreSightseeingPair = function(A) { - let res = 0, cur = 0; - for (let a of A) { - res = Math.max(res, cur + a); - cur = Math.max(cur, a) - 1; - } - return res; -}; - - -// another - -/** - * @param {number[]} A - * @return {number} - */ -const maxScoreSightseeingPair = function(A) { - let ans =A[0]; - let prevBestIdx =0; - for(let j=1;j a[0] - b[0]) - if(T === 0) return 0 - let laststart = -1, - curend = 0, - count = 0 - for (let i = 0; i < clips.length; ) { - if (clips[i][0] > curend) return -1 - let maxend = curend - // while one clip's start is before or equal to current end - while (i < clips.length && clips[i][0] <= curend) { - maxend = Math.max(maxend, clips[i][1]) - i++ - } - count++ - curend = maxend - if (curend >= T) return count - } - return -1 -} - -// another - -/** - * @param {number[][]} clips - * @param {number} T - * @return {number} - */ -const videoStitching = function (clips, T) { - clips.sort((a, b) => a[0] - b[0]) - let res = 0 - for(let i = 0, start = 0, end = 0, len = clips.length; start < T; start = end, res++) { - for(; i < len && clips[i][0] <= start; i++) { - end = Math.max(end, clips[i][1]) - } - if(start === end) return -1 - } - return res -} - - -// another - -/** - * @param {number[][]} clips - * @param {number} T - * @return {number} - */ -const videoStitching = function (clips, T) { - const dp = Array(T + 1).fill( T + 1 ) - dp[0] = 0 - for(let i = 0; i <= T; i++) { - for(let c of clips) { - if(i >= c[0] && i <= c[1]) dp[i] = Math.min(dp[i], dp[c[0]] + 1) - } - if(dp[i] === T + 1) return -1 - } - return dp[T] -} - - diff --git a/1024.video-stitching.js b/1024.video-stitching.js new file mode 100644 index 00000000..0cd9246b --- /dev/null +++ b/1024.video-stitching.js @@ -0,0 +1,26 @@ +/** + * @param {number[][]} clips + * @param {number} T + * @return {number} + */ +const videoStitching = function (clips, T) { + clips.sort((a, b) => a[0] - b[0]) + if(T === 0) return 0 + let laststart = -1, + curend = 0, + count = 0 + for (let i = 0; i < clips.length; ) { + if (clips[i][0] > curend) return -1 + let maxend = curend + // while one clip's start is before or equal to current end + while (i < clips.length && clips[i][0] <= curend) { + maxend = Math.max(maxend, clips[i][1]) + i++ + } + count++ + curend = maxend + if (curend >= T) return count + } + return -1 +} + diff --git a/1025-divisor-game.js b/1025.divisor-game.js similarity index 100% rename from 1025-divisor-game.js rename to 1025.divisor-game.js diff --git a/1026-maximum-difference-between-node-and-ancestor.js b/1026.maximum-difference-between-node-and-ancestor.js similarity index 100% rename from 1026-maximum-difference-between-node-and-ancestor.js rename to 1026.maximum-difference-between-node-and-ancestor.js diff --git a/1027-longest-arithmetic-sequence.js b/1027.longest-arithmetic-sequence.js similarity index 100% rename from 1027-longest-arithmetic-sequence.js rename to 1027.longest-arithmetic-sequence.js diff --git a/1028-recover-a-tree-from-preorder-traversal.js b/1028.recover-a-tree-from-preorder-traversal.js similarity index 100% rename from 1028-recover-a-tree-from-preorder-traversal.js rename to 1028.recover-a-tree-from-preorder-traversal.js diff --git a/1029-two-city-scheduling.js b/1029-two-city-scheduling.js deleted file mode 100644 index d973fd13..00000000 --- a/1029-two-city-scheduling.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @param {number[][]} costs - * @return {number} - */ -const twoCitySchedCost = function(costs) { - const N = costs.length / 2 - const dp = Array.from({ length: N + 1 }, () => new Array(N + 1).fill(0)) - for (let i = 1; i <= N; i++) { - dp[i][0] = dp[i - 1][0] + costs[i - 1][0] - } - for (let j = 1; j <= N; j++) { - dp[0][j] = dp[0][j - 1] + costs[j - 1][1] - } - for (let i = 1; i <= N; i++) { - for (let j = 1; j <= N; j++) { - dp[i][j] = Math.min( - dp[i - 1][j] + costs[i + j - 1][0], - dp[i][j - 1] + costs[i + j - 1][1] - ) - } - } - return dp[N][N] -} - -// another - -/** - * @param {number[][]} costs - * @return {number} - */ -const twoCitySchedCost = function(costs) { - const N = costs.length - let res = 0 - const refund = [] - for(let i = 0; i < N; i++) { - refund[i] = costs[i][1] - costs[i][0] - res += costs[i][0] - } - refund.sort((a, b) => a - b) - for(let i = 0; i < N / 2; i++) { - res += refund[i] - } - return res -}; - -// another - -/** - * @param {number[][]} costs - * @return {number} - */ -const twoCitySchedCost = function(costs) { - const len = costs.length - if(len === 0) return 0 - const N = len / 2 - costs.sort((a, b) => (a[0] - a[1]) - (b[0] - b[1])) - let res = 0 - for(let i = 0; i < costs.length; i++) { - if(i < N) { - res += costs[i][0] - } else { - res += costs[i][1] - } - } - return res -}; diff --git a/1029.two-city-scheduling.js b/1029.two-city-scheduling.js new file mode 100644 index 00000000..3262d051 --- /dev/null +++ b/1029.two-city-scheduling.js @@ -0,0 +1,24 @@ +/** + * @param {number[][]} costs + * @return {number} + */ +const twoCitySchedCost = function(costs) { + const N = costs.length / 2 + const dp = Array.from({ length: N + 1 }, () => new Array(N + 1).fill(0)) + for (let i = 1; i <= N; i++) { + dp[i][0] = dp[i - 1][0] + costs[i - 1][0] + } + for (let j = 1; j <= N; j++) { + dp[0][j] = dp[0][j - 1] + costs[j - 1][1] + } + for (let i = 1; i <= N; i++) { + for (let j = 1; j <= N; j++) { + dp[i][j] = Math.min( + dp[i - 1][j] + costs[i + j - 1][0], + dp[i][j - 1] + costs[i + j - 1][1] + ) + } + } + return dp[N][N] +} + diff --git a/103-binary-tree-zigzag-level-order-traversal.js b/103-binary-tree-zigzag-level-order-traversal.js deleted file mode 100644 index 54ff515f..00000000 --- a/103-binary-tree-zigzag-level-order-traversal.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number[][]} - */ -const zigzagLevelOrder = function(root) { - if(root == null) return [] - const row = [root] - const res = [] - bfs(row, res) - for(let i = 0; i < res.length; i++) { - res[i] = i % 2 === 0 ? res[i] : res[i].reverse() - } - return res -}; - -function bfs(row, res) { - if(row.length === 0) return - let tmp = [] - let next = [] - for(let i = 0; i< row.length; i++) { - tmp.push(row[i].val) - if(row[i].left) { - next.push(row[i].left) - } - if(row[i].right) { - next.push(row[i].right) - } - } - if(tmp.length) { - res.push(tmp) - } - bfs(next, res) -} - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {number[][]} - */ -const zigzagLevelOrder = function (root) { - if (!root) return []; - const queue = [root]; - const zigzag = []; - let numLevels = 1; - while (queue.length > 0) { - const width = queue.length; - const levelTraversal = []; - for (let i = 0; i < width; i++) { - const currentNode = queue.shift(); - if (currentNode.right) queue.push(currentNode.right); - if (currentNode.left) queue.push(currentNode.left); - numLevels % 2 === 0 - ? levelTraversal.push(currentNode.val) - : levelTraversal.unshift(currentNode.val); - } - zigzag.push(levelTraversal); - numLevels++; - } - - return zigzag; -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {number[][]} - */ -const zigzagLevelOrder = function (root) { - const res = [] - dfs(root, res, 0) - return res - - function dfs(node, res, level) { - if(node == null) return - if(res.length <= level) res.push([]) - const tmp = res[level] - if(level % 2 === 0) tmp.push(node.val) - else tmp.unshift(node.val) - - dfs(node.left, res, level + 1) - dfs(node.right, res, level + 1) - } -}; diff --git a/103.binary-tree-zigzag-level-order-traversal.js b/103.binary-tree-zigzag-level-order-traversal.js new file mode 100644 index 00000000..9aef7c60 --- /dev/null +++ b/103.binary-tree-zigzag-level-order-traversal.js @@ -0,0 +1,41 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +const zigzagLevelOrder = function(root) { + if(root == null) return [] + const row = [root] + const res = [] + bfs(row, res) + for(let i = 0; i < res.length; i++) { + res[i] = i % 2 === 0 ? res[i] : res[i].reverse() + } + return res +}; + +function bfs(row, res) { + if(row.length === 0) return + let tmp = [] + let next = [] + for(let i = 0; i< row.length; i++) { + tmp.push(row[i].val) + if(row[i].left) { + next.push(row[i].left) + } + if(row[i].right) { + next.push(row[i].right) + } + } + if(tmp.length) { + res.push(tmp) + } + bfs(next, res) +} + diff --git a/1030-matrix-cells-in-distance-order.js b/1030.matrix-cells-in-distance-order.js similarity index 100% rename from 1030-matrix-cells-in-distance-order.js rename to 1030.matrix-cells-in-distance-order.js diff --git a/1030-next-greater-node-in-linked-list.js b/1030.next-greater-node-in-linked-list.js similarity index 100% rename from 1030-next-greater-node-in-linked-list.js rename to 1030.next-greater-node-in-linked-list.js diff --git a/1031-maximum-sum-of-two-non-overlapping-subarrays.js b/1031-maximum-sum-of-two-non-overlapping-subarrays.js deleted file mode 100644 index 37f3e01a..00000000 --- a/1031-maximum-sum-of-two-non-overlapping-subarrays.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @param {number[]} A - * @param {number} L - * @param {number} M - * @return {number} - */ -const maxSumTwoNoOverlap = function(A, L, M) { - for(let i = 1, len = A.length; i < len; i++) { - A[i] += A[i - 1] - } - let LMax = A[L - 1], MMax = A[M - 1], res = A[L + M - 1] - for(let i = L + M, len = A.length; i < len; i++) { - LMax = Math.max(LMax, A[i - M] - A[i - M - L]) - MMax = Math.max(MMax, A[i - L] - A[i - M - L]) - res = Math.max(res, Math.max(LMax + A[i] - A[i - M], MMax + A[i] - A[i - L])) - } - return res -} - -// another - -const maxSumTwoNoOverlap = function(A, L, M) { - let n = A.length - let sum = [] - sum[0] = 0 - for (let i = 0; i < n; i++) sum[i + 1] = sum[i] + A[i] - - let ans = 0 - for (let i = L - 1; i + M < n; ++i) { - for (let j = i + 1; j + M - 1 < n; ++j) { - ans = Math.max(ans, sum[i + 1] - sum[i - L + 1] + sum[j + M] - sum[j]) - } - } - let tmp = L - L = M - M = tmp - for (let i = L - 1; i + M < n; ++i) { - for (let j = i + 1; j + M - 1 < n; ++j) { - ans = Math.max(ans, sum[i + 1] - sum[i - L + 1] + sum[j + M] - sum[j]) - } - } - return ans -} diff --git a/1031.maximum-sum-of-two-non-overlapping-subarrays.js b/1031.maximum-sum-of-two-non-overlapping-subarrays.js new file mode 100644 index 00000000..09b2e632 --- /dev/null +++ b/1031.maximum-sum-of-two-non-overlapping-subarrays.js @@ -0,0 +1,19 @@ +/** + * @param {number[]} A + * @param {number} L + * @param {number} M + * @return {number} + */ +const maxSumTwoNoOverlap = function(A, L, M) { + for(let i = 1, len = A.length; i < len; i++) { + A[i] += A[i - 1] + } + let LMax = A[L - 1], MMax = A[M - 1], res = A[L + M - 1] + for(let i = L + M, len = A.length; i < len; i++) { + LMax = Math.max(LMax, A[i - M] - A[i - M - L]) + MMax = Math.max(MMax, A[i - L] - A[i - M - L]) + res = Math.max(res, Math.max(LMax + A[i] - A[i - M], MMax + A[i] - A[i - L])) + } + return res +} + diff --git a/1031-number-of-enclaves.js b/1031.number-of-enclaves.js similarity index 100% rename from 1031-number-of-enclaves.js rename to 1031.number-of-enclaves.js diff --git a/1032-stream-of-characters.js b/1032.stream-of-characters.js similarity index 100% rename from 1032-stream-of-characters.js rename to 1032.stream-of-characters.js diff --git a/1033-moving-stones-until-consecutive.js b/1033.moving-stones-until-consecutive.js similarity index 100% rename from 1033-moving-stones-until-consecutive.js rename to 1033.moving-stones-until-consecutive.js diff --git a/1034-coloring-a-border.js b/1034.coloring-a-border.js similarity index 100% rename from 1034-coloring-a-border.js rename to 1034.coloring-a-border.js diff --git a/1035-uncrossed-lines.js b/1035-uncrossed-lines.js deleted file mode 100644 index 7fbc58e9..00000000 --- a/1035-uncrossed-lines.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {number[]} A - * @param {number[]} B - * @return {number} - */ -const maxUncrossedLines = function(A, B) { - const lenA = A.length - const lenB = B.length - const dp = Array.from({length: lenA + 1}, () => new Array(lenB + 1).fill(0)) - for(let i = 1; i <= lenA; i++) { - for(let j = 1; j <= lenB; j++) { - if(A[i - 1] === B[j - 1]) { - dp[i][j] = 1 + dp[i - 1][j - 1] - } else { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) - } - } - } - return dp[lenA][lenB] -}; - - -// another - -const maxUncrossedLines = function(A, B) { - const m = A.length, - n = B.length - const dp = new Array(n + 1).fill(0) - let prev - - for (let i = 1; i <= m; i++) { - prev = dp[0] - for (let j = 1; j <= n; j++) { - let backup = dp[j] - if (A[i - 1] == B[j - 1]) dp[j] = prev + 1 - else dp[j] = Math.max(dp[j], dp[j - 1]) - prev = backup - } - } - - return dp[n] -} diff --git a/1035.uncrossed-lines.js b/1035.uncrossed-lines.js new file mode 100644 index 00000000..702ea96f --- /dev/null +++ b/1035.uncrossed-lines.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} A + * @param {number[]} B + * @return {number} + */ +const maxUncrossedLines = function(A, B) { + const lenA = A.length + const lenB = B.length + const dp = Array.from({length: lenA + 1}, () => new Array(lenB + 1).fill(0)) + for(let i = 1; i <= lenA; i++) { + for(let j = 1; j <= lenB; j++) { + if(A[i - 1] === B[j - 1]) { + dp[i][j] = 1 + dp[i - 1][j - 1] + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) + } + } + } + return dp[lenA][lenB] +}; + + diff --git a/1036-escape-a-large-maze.js b/1036-escape-a-large-maze.js deleted file mode 100644 index 91b0e04b..00000000 --- a/1036-escape-a-large-maze.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @param {number[][]} blocked - * @param {number[]} source - * @param {number[]} target - * @return {boolean} - */ -const isEscapePossible = function(blocked, source, target) { - const blockedSet = new Set() - for (let el of blocked) { - let key = el[0] + "," + el[1] - blockedSet.add(key) - } - return canVisit(blockedSet, source, target) && canVisit(blockedSet, target, source) -} - -function canVisit(blocked, start, end) { - const visited = new Set() - return dfs(blocked, start[0], start[1], end[0], end[1], visited) -} -function dfs(blocked, i, j, m, n, visited) { - visited.add(i + "," + j) - const dirs = [[i - 1, j], [i + 1, j], [i, j + 1], [i, j - 1]] - if ((i == m && j == n) || visited.size >= 20000) { - return true - } - for (let dir of dirs) { - let nextKey = dir[0] + "," + dir[1] - if ( - dir[0] >= 0 && - dir[1] >= 0 && - dir[0] < 1e6 && - dir[1] < 1e6 && - !blocked.has(nextKey) && - !visited.has(nextKey) - ) { - if (dfs(blocked, dir[0], dir[1], m, n, visited)) { - return true - } - } - } - return false -} - -// another - -/** - * @param {number[][]} blocked - * @param {number[]} source - * @param {number[]} target - * @return {boolean} - */ -const isEscapePossible = function(blocked, source, target) { - if (blocked.length < 2) { - return true - } -// if (blocked[0][0] == 100025) { -// return false -// } - const blockSet = new Set( - blocked.map(el => { - return el[0] + "," + el[1] - }) - ) - let targetR, targetC, curR, curC - ;[targetR, targetC] = target - let visited = new Set([]) - let DIRS = [[0, 1], [-1, 0], [0, -1], [1, 0]], - queue = [source] - const inBound = (r, c) => { - return r >= 0 && c >= 0 && r < 1000000 && c < 1000000 - } - let count = 0 - while (queue.length > 0) { - count++ - ;[curR, curC] = queue.shift() - - if (count > 20000) { - return true - } - for (let dir of DIRS) { - const newR = curR + dir[0], - newC = curC + dir[1] - if ( - !inBound(newR, newC) || - blockSet.has(newR + "," + newC) || - visited.has(newR + "," + newC) - ) { - continue - } - - if (newR == targetR && newC == targetC) { - return true - } - visited.add(newR + "," + newC) - queue.push([newR, newC]) - } - } - return false -} diff --git a/1036.escape-a-large-maze.js b/1036.escape-a-large-maze.js new file mode 100644 index 00000000..a273aeec --- /dev/null +++ b/1036.escape-a-large-maze.js @@ -0,0 +1,43 @@ +/** + * @param {number[][]} blocked + * @param {number[]} source + * @param {number[]} target + * @return {boolean} + */ +const isEscapePossible = function(blocked, source, target) { + const blockedSet = new Set() + for (let el of blocked) { + let key = el[0] + "," + el[1] + blockedSet.add(key) + } + return canVisit(blockedSet, source, target) && canVisit(blockedSet, target, source) +} + +function canVisit(blocked, start, end) { + const visited = new Set() + return dfs(blocked, start[0], start[1], end[0], end[1], visited) +} +function dfs(blocked, i, j, m, n, visited) { + visited.add(i + "," + j) + const dirs = [[i - 1, j], [i + 1, j], [i, j + 1], [i, j - 1]] + if ((i == m && j == n) || visited.size >= 20000) { + return true + } + for (let dir of dirs) { + let nextKey = dir[0] + "," + dir[1] + if ( + dir[0] >= 0 && + dir[1] >= 0 && + dir[0] < 1e6 && + dir[1] < 1e6 && + !blocked.has(nextKey) && + !visited.has(nextKey) + ) { + if (dfs(blocked, dir[0], dir[1], m, n, visited)) { + return true + } + } + } + return false +} + diff --git a/1037-valid-boomerang.js b/1037.valid-boomerang.js similarity index 100% rename from 1037-valid-boomerang.js rename to 1037.valid-boomerang.js diff --git a/1038-binary-search-tree-to-greater-sum-tree.js b/1038.binary-search-tree-to-greater-sum-tree.js similarity index 100% rename from 1038-binary-search-tree-to-greater-sum-tree.js rename to 1038.binary-search-tree-to-greater-sum-tree.js diff --git a/1039-minimum-score-triangulation-of-polygon.js b/1039.minimum-score-triangulation-of-polygon.js similarity index 100% rename from 1039-minimum-score-triangulation-of-polygon.js rename to 1039.minimum-score-triangulation-of-polygon.js diff --git a/104-maximum-depth-of-binary-tree.js b/104-maximum-depth-of-binary-tree.js deleted file mode 100755 index 46d08f20..00000000 --- a/104-maximum-depth-of-binary-tree.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const maxDepth = function(root) { - if (!root) return 0; - const left = maxDepth(root.left); - const right = maxDepth(root.right); - let depth = left > right ? left : right; - return (depth += 1); -}; diff --git a/104.maximum-depth-of-binary-tree.js b/104.maximum-depth-of-binary-tree.js new file mode 100644 index 00000000..5c16f4f2 --- /dev/null +++ b/104.maximum-depth-of-binary-tree.js @@ -0,0 +1,18 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +const maxDepth = function(root) { + if (!root) return 0; + const left = maxDepth(root.left); + const right = maxDepth(root.right); + let depth = left > right ? left : right; + return (depth += 1); +}; diff --git a/1040-moving-stones-until-consecutive-ii.js b/1040.moving-stones-until-consecutive-ii.js similarity index 100% rename from 1040-moving-stones-until-consecutive-ii.js rename to 1040.moving-stones-until-consecutive-ii.js diff --git a/1041-robot-bounded-in-circle.js b/1041-robot-bounded-in-circle.js deleted file mode 100644 index 65146881..00000000 --- a/1041-robot-bounded-in-circle.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @param {string} instructions - * @return {boolean} - */ -const isRobotBounded = function(instructions) { - let x = 0, y = 0, i = 0, d = [[0, 1], [1, 0], [0, -1], [ -1, 0]]; - for (let j = 0; j < instructions.length; ++j) - if (instructions.charAt(j) === 'R') i = (i + 1) % 4; - else if (instructions .charAt(j) === 'L') i = (i + 3) % 4; - else { - x += d[i][0]; y += d[i][1]; - } - return x == 0 && y == 0 || i > 0; -}; - -// another - -/** - * @param {string} instructions - * @return {boolean} - */ -const isRobotBounded = function(instructions) { - let x = 0, y = 0, i = 0 - const dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]] // U, R, D, L - for(let e of instructions) { - if(e === 'R') { - i = (i + 1) % 4 - } else if(e === 'L') { - i = (i + 3) % 4 - } else { - x += dirs[i][0] - y += dirs[i][1] - } - } - return x === 0 && y === 0 || i > 0 -}; - -// another - -/** - * @param {string} instructions - * @return {boolean} - */ -const isRobotBounded = function(instructions) { - const dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]] - let x = 0, y = 0, i = 0 - for(let ins of instructions) { - if(ins === 'G') { - const dir = dirs[i] - x += dir[0] - y += dir[1] - } else if(ins === 'L') { - i = i - 1 < 0 ? 3 : i - 1 - } else if(ins === 'R') { - i = i + 1 > 3 ? 0 : i + 1 - } - } - return x === 0 && y === 0 || i !== 0 -}; diff --git a/1041.robot-bounded-in-circle.js b/1041.robot-bounded-in-circle.js new file mode 100644 index 00000000..b2d29647 --- /dev/null +++ b/1041.robot-bounded-in-circle.js @@ -0,0 +1,15 @@ +/** + * @param {string} instructions + * @return {boolean} + */ +const isRobotBounded = function(instructions) { + let x = 0, y = 0, i = 0, d = [[0, 1], [1, 0], [0, -1], [ -1, 0]]; + for (let j = 0; j < instructions.length; ++j) + if (instructions.charAt(j) === 'R') i = (i + 1) % 4; + else if (instructions .charAt(j) === 'L') i = (i + 3) % 4; + else { + x += d[i][0]; y += d[i][1]; + } + return x == 0 && y == 0 || i > 0; +}; + diff --git a/1042-flower-planting-with-no-adjacent.js b/1042.flower-planting-with-no-adjacent.js similarity index 100% rename from 1042-flower-planting-with-no-adjacent.js rename to 1042.flower-planting-with-no-adjacent.js diff --git a/1043-partition-array-for-maximum-sum.js b/1043-partition-array-for-maximum-sum.js deleted file mode 100644 index adec52a9..00000000 --- a/1043-partition-array-for-maximum-sum.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @param {number[]} A - * @param {number} K - * @return {number} - */ -const maxSumAfterPartitioning = function(A, K) { - const N = A.length - const dp = new Array(N).fill(0); - for (let i = 0; i < N; ++i) { - let curMax = 0; - for (let j = 1; j <= K && i - j + 1 >= 0; j++) { - curMax = Math.max(curMax, A[i - j + 1]); - dp[i] = Math.max(dp[i], (i >= j ? dp[i - j] : 0) + curMax * j); - } - } - return dp[N - 1]; -}; - -// another - -/** - * @param {number[]} arr - * @param {number} k - * @return {number} - */ -const maxSumAfterPartitioning = function(arr, k) { - const n = arr.length, memo = Array(n + 1) - memo[0] = 0 - return dp(n) - - function dp(i) { - if(i === 0) return 0 - if(memo[i] != null) return memo[i] - - let sum = 0, max = 0, res = 0 - for(let j = i; j > 0 && i - j < k; j--) { - max = Math.max(max, arr[j - 1]) - sum = (i - j + 1) * max - res = Math.max(res, dp(j - 1) + sum) - } - return memo[i] = res - } -}; diff --git a/1043.partition-array-for-maximum-sum.js b/1043.partition-array-for-maximum-sum.js new file mode 100644 index 00000000..3de2443a --- /dev/null +++ b/1043.partition-array-for-maximum-sum.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} A + * @param {number} K + * @return {number} + */ +const maxSumAfterPartitioning = function(A, K) { + const N = A.length + const dp = new Array(N).fill(0); + for (let i = 0; i < N; ++i) { + let curMax = 0; + for (let j = 1; j <= K && i - j + 1 >= 0; j++) { + curMax = Math.max(curMax, A[i - j + 1]); + dp[i] = Math.max(dp[i], (i >= j ? dp[i - j] : 0) + curMax * j); + } + } + return dp[N - 1]; +}; + diff --git a/1044-longest-duplicate-substring.js b/1044-longest-duplicate-substring.js deleted file mode 100644 index 9403a04b..00000000 --- a/1044-longest-duplicate-substring.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ -const longestDupSubstring = function(s) { - const n = s.length - let l = 0, r = n, res = '' - while(l < r) { - const mid = (l + r + 1) >> 1 - const [chk, str] = valid(s, mid) - if(chk) { - l = mid - res = str - } else { - r = mid - 1 - } - } - return res -}; - -function valid(s, len) { - const set = new Set() - for(let i = 0, n = s.length; i <= n - len; i++) { - const tmp = s.substr(i, len) - if(set.has(tmp)) return [true, tmp] - set.add(tmp) - } - - return [false, ''] -} - -// another - -/** - * @param {string} S - * @return {string} - */ -const longestDupSubstring = function(S) { - const R = 26, - MOD = 1e9 + 7 - let lo = 0, - hi = S.length - 1, - res = '' - while (lo < hi) { - const len = Math.ceil((lo + hi) / 2) - const sub = rabinKarp(S, len) - if (sub !== '') { - lo = len - res = sub - } else { - hi = len - 1 - } - } - return res - - function rabinKarp(str, len) { - const aCode = ('a').charCodeAt(0) - let RM = 1 - // 等价于RM=Math.pow(R,M-1) % MOD - // 由于JS精度问题拆解计算 - for (let i = 1; i < len; i++) { - RM = (RM * R) % MOD - } - const map = new Map() - let num = 0 - // 计算前len个字符串的散列值 - for (let i = 0; i < len; i++) { - const code = str.charCodeAt(i) - aCode - num = (num * R + code) % MOD - } - map.set(num, 0) - // 后续计算散列值 - for (let i = 0; i < str.length - len; i++) { - const preCode = str.charCodeAt(i) - aCode, - curCode = str.charCodeAt(i + len) - aCode - num = (num + MOD - ((preCode * RM) % MOD)) % MOD - num = (num * R + curCode) % MOD - if (map.has(num)) { - const sub = str.substring(i + 1, i + 1 + len) - const preId = map.get(num), - preSub = str.substring(preId, preId + len) - if (sub === preSub) return sub - } - map.set(num, i + 1) - } - return '' - } -} diff --git a/1044.longest-duplicate-substring.js b/1044.longest-duplicate-substring.js new file mode 100644 index 00000000..29997216 --- /dev/null +++ b/1044.longest-duplicate-substring.js @@ -0,0 +1,31 @@ +/** + * @param {string} s + * @return {string} + */ +const longestDupSubstring = function(s) { + const n = s.length + let l = 0, r = n, res = '' + while(l < r) { + const mid = (l + r + 1) >> 1 + const [chk, str] = valid(s, mid) + if(chk) { + l = mid + res = str + } else { + r = mid - 1 + } + } + return res +}; + +function valid(s, len) { + const set = new Set() + for(let i = 0, n = s.length; i <= n - len; i++) { + const tmp = s.substr(i, len) + if(set.has(tmp)) return [true, tmp] + set.add(tmp) + } + + return [false, ''] +} + diff --git a/1046-last-stone-weight.js b/1046.last-stone-weight.js similarity index 100% rename from 1046-last-stone-weight.js rename to 1046.last-stone-weight.js diff --git a/1047-remove-all-adjacent-duplicates-in-string.js b/1047.remove-all-adjacent-duplicates-in-string.js similarity index 100% rename from 1047-remove-all-adjacent-duplicates-in-string.js rename to 1047.remove-all-adjacent-duplicates-in-string.js diff --git a/1048-longest-string-chain.js b/1048.longest-string-chain.js similarity index 100% rename from 1048-longest-string-chain.js rename to 1048.longest-string-chain.js diff --git a/1049-last-stone-weight-ii.js b/1049.last-stone-weight-ii.js similarity index 100% rename from 1049-last-stone-weight-ii.js rename to 1049.last-stone-weight-ii.js diff --git a/105-construct-binary-tree-from-preorder-and-inorder-traversal.js b/105-construct-binary-tree-from-preorder-and-inorder-traversal.js deleted file mode 100644 index beebb4af..00000000 --- a/105-construct-binary-tree-from-preorder-and-inorder-traversal.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {number[]} preorder - * @param {number[]} inorder - * @return {TreeNode} - */ -const buildTree = function(preorder, inorder) { - if(preorder.length === 0 && inorder.length === 0) return null - const val = preorder[0] - const node = new TreeNode(val) - const inIdx = inorder.indexOf(val) - const leftIn = inorder.slice(0, inIdx) - const rightIn = inorder.slice(inIdx + 1) - - const leftPre = preorder.slice(1, leftIn.length + 1) - const rightPre = preorder.slice(leftIn.length + 1) - - // console.log(leftIn, rightIn, leftPre, rightPre) - node.left = buildTree(leftPre, leftIn) - node.right = buildTree(rightPre, rightIn) - return node -}; - - -// another - - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {number[]} preorder - * @param {number[]} inorder - * @return {TreeNode} - */ -let pre -let ins -let inmap = {} -const buildTree = function(preorder, inorder) { - pre = preorder - ins = inorder - for(let i = 0; i < inorder.length; i++) { - inmap[inorder[i]] = i - } - let root = helper(0,0,ins.length - 1) - return root -}; - -function helper(preStart, inStart, inEnd) { - if (preStart > pre.length -1 || inStart > inEnd) { - return null - } - let val = pre[preStart] - let root = new TreeNode(val) - let inIndex = inmap[val] - root.left = helper(preStart + 1, inStart, inIndex - 1) - root.right = helper(preStart+inIndex-inStart+1, inIndex+1, inEnd) - return root -} diff --git a/105.construct-binary-tree-from-preorder-and-inorder-traversal.js b/105.construct-binary-tree-from-preorder-and-inorder-traversal.js new file mode 100644 index 00000000..e248cfb6 --- /dev/null +++ b/105.construct-binary-tree-from-preorder-and-inorder-traversal.js @@ -0,0 +1,30 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {number[]} preorder + * @param {number[]} inorder + * @return {TreeNode} + */ +const buildTree = function(preorder, inorder) { + if(preorder.length === 0 && inorder.length === 0) return null + const val = preorder[0] + const node = new TreeNode(val) + const inIdx = inorder.indexOf(val) + const leftIn = inorder.slice(0, inIdx) + const rightIn = inorder.slice(inIdx + 1) + + const leftPre = preorder.slice(1, leftIn.length + 1) + const rightPre = preorder.slice(leftIn.length + 1) + + // console.log(leftIn, rightIn, leftPre, rightPre) + node.left = buildTree(leftPre, leftIn) + node.right = buildTree(rightPre, rightIn) + return node +}; + + diff --git a/1051-height-checker.js b/1051.height-checker.js similarity index 100% rename from 1051-height-checker.js rename to 1051.height-checker.js diff --git a/1052-grumpy-bookstore-owner.js b/1052-grumpy-bookstore-owner.js deleted file mode 100644 index 977d6c8b..00000000 --- a/1052-grumpy-bookstore-owner.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @param {number[]} customers - * @param {number[]} grumpy - * @param {number} X - * @return {number} - */ -const maxSatisfied = function(customers, grumpy, X) { - if (customers.length === 1) return customers[0] - const totalSatisfiedCustomers = customers.reduce( - (ac, el, idx) => ac + (grumpy[idx] === 0 ? el : 0), - 0 - ) - const arr = customers.map((el, idx) => (grumpy[idx] === 1 ? el : 0)) - const acArr = [] - let ac = 0 - for (let i = 0, len = arr.length; i < len; i++) { - acArr[i] = ac = ac + arr[i] - } - let max = 0 - for (let i = X - 1, len = grumpy.length; i < len; i++) { - let tmp = i - X < 0 ? 0 : acArr[i - X] - if (acArr[i] - tmp > max) max = acArr[i] - tmp - } - - return totalSatisfiedCustomers + max -} - -// another - -/** - * @param {number[]} customers - * @param {number[]} grumpy - * @param {number} X - * @return {number} - */ -const maxSatisfied = function (customers, grumpy, X) { - let satisfied = 0, - maxMakeSatisfied = 0 - for (let i = 0, winOfMakeSatisfied = 0; i < grumpy.length; ++i) { - if (grumpy[i] === 0) { - satisfied += customers[i] - } else { - winOfMakeSatisfied += customers[i] - } - if (i >= X) { - winOfMakeSatisfied -= grumpy[i - X] * customers[i - X] - } - maxMakeSatisfied = Math.max(winOfMakeSatisfied, maxMakeSatisfied) - } - return satisfied + maxMakeSatisfied -} diff --git a/1052.grumpy-bookstore-owner.js b/1052.grumpy-bookstore-owner.js new file mode 100644 index 00000000..d73256d6 --- /dev/null +++ b/1052.grumpy-bookstore-owner.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} customers + * @param {number[]} grumpy + * @param {number} X + * @return {number} + */ +const maxSatisfied = function(customers, grumpy, X) { + if (customers.length === 1) return customers[0] + const totalSatisfiedCustomers = customers.reduce( + (ac, el, idx) => ac + (grumpy[idx] === 0 ? el : 0), + 0 + ) + const arr = customers.map((el, idx) => (grumpy[idx] === 1 ? el : 0)) + const acArr = [] + let ac = 0 + for (let i = 0, len = arr.length; i < len; i++) { + acArr[i] = ac = ac + arr[i] + } + let max = 0 + for (let i = X - 1, len = grumpy.length; i < len; i++) { + let tmp = i - X < 0 ? 0 : acArr[i - X] + if (acArr[i] - tmp > max) max = acArr[i] - tmp + } + + return totalSatisfiedCustomers + max +} + diff --git a/1053-previous-permutation-with-one-swap.js b/1053.previous-permutation-with-one-swap.js similarity index 100% rename from 1053-previous-permutation-with-one-swap.js rename to 1053.previous-permutation-with-one-swap.js diff --git a/1054-distant-barcodes.js b/1054-distant-barcodes.js deleted file mode 100644 index c0930553..00000000 --- a/1054-distant-barcodes.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @param {number[]} barcodes - * @return {number[]} - */ -const rearrangeBarcodes = function(barcodes) { - const hash = {} - let maxFreq = 0, max = 0 - for(const e of barcodes) { - if(hash[e] == null) hash[e] = 0 - hash[e]++ - if(hash[e] > maxFreq) { - maxFreq = hash[e] - max = e - } - } - const n = barcodes.length - const entries = Object.entries(hash) - const res = Array(n) - let idx = 0 - while(maxFreq) { - res[idx] = max - idx += 2 - maxFreq-- - } - for(let [v, f] of entries) { - if(+v === max) continue - while(f) { - if(idx >= n) idx = 1 - res[idx] = +v - idx += 2 - f-- - } - } - - return res -}; - -// another - -/** - * @param {number[]} barcodes - * @return {number[]} - */ -const rearrangeBarcodes = function(barcodes) { - const map = {}; - barcodes.forEach(b => map[b] = (map[b] || 0) + 1); - const keys = Object.keys(map).sort((k1, k2) => map[k1] - map[k2]); - - let idx = 1; - for (let k of keys) { - let t = map[k]; - - for (let i = 0; i < t; i++) { - if (idx >= barcodes.length) idx = 0; - barcodes[idx] = k; - idx += 2; - } - } - - return barcodes; -}; - -// another - -/** - * @param {number[]} barcodes - * @return {number[]} - */ -const rearrangeBarcodes = function(barcodes) { - const hash = {}, n = barcodes.length - for(let e of barcodes) { - if(hash[e] == null) hash[e] = 0 - hash[e]++ - } - const res = Array(n) - let max = 0, idx = -1 - for(let k in hash) { - if(hash[k] > max) { - max = hash[k] - idx = +k - } - } - let i = 0 - // max freq first - while(max > 0) { - res[i] = idx - max-- - i += 2 - } - // the rest - const keys = Object.keys(hash).map(e => +e) - for(let j = 0, len = keys.length; j < len; j++) { - if(keys[j] !== idx) { - const k = keys[j] - let freq = hash[k] - while(freq > 0) { - if(i >= n) i = 1 - res[i] = k - freq-- - i += 2 - } - } - } - - return res -}; diff --git a/1054.distant-barcodes.js b/1054.distant-barcodes.js new file mode 100644 index 00000000..b30f5995 --- /dev/null +++ b/1054.distant-barcodes.js @@ -0,0 +1,37 @@ +/** + * @param {number[]} barcodes + * @return {number[]} + */ +const rearrangeBarcodes = function(barcodes) { + const hash = {} + let maxFreq = 0, max = 0 + for(const e of barcodes) { + if(hash[e] == null) hash[e] = 0 + hash[e]++ + if(hash[e] > maxFreq) { + maxFreq = hash[e] + max = e + } + } + const n = barcodes.length + const entries = Object.entries(hash) + const res = Array(n) + let idx = 0 + while(maxFreq) { + res[idx] = max + idx += 2 + maxFreq-- + } + for(let [v, f] of entries) { + if(+v === max) continue + while(f) { + if(idx >= n) idx = 1 + res[idx] = +v + idx += 2 + f-- + } + } + + return res +}; + diff --git a/1056-confusing-number.js b/1056.confusing-number.js similarity index 100% rename from 1056-confusing-number.js rename to 1056.confusing-number.js diff --git a/1059-all-paths-from-source-lead-to-destination.js b/1059.all-paths-from-source-lead-to-destination.js similarity index 100% rename from 1059-all-paths-from-source-lead-to-destination.js rename to 1059.all-paths-from-source-lead-to-destination.js diff --git a/106-construct-binary-tree-from-inorder-and-postorder-traversal.js b/106-construct-binary-tree-from-inorder-and-postorder-traversal.js deleted file mode 100644 index 19c5a701..00000000 --- a/106-construct-binary-tree-from-inorder-and-postorder-traversal.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {number[]} inorder - * @param {number[]} postorder - * @return {TreeNode} - */ - -const buildTree = function(inorder, postorder) { - const inmap = {}; - const posts = postorder; - for (let i = 0; i < inorder.length; i++) { - inmap[inorder[i]] = i; - } - return helper(postorder.length - 1, 0, inorder.length - 1); - - function helper(postEnd, inStart, inEnd) { - if (postEnd < 0 || inEnd < inStart) return null; - const val = posts[postEnd]; - const idx = inmap["" + val]; - const root = new TreeNode(val); - root.left = helper(postEnd - (inEnd - idx) - 1, inStart, idx - 1); - root.right = helper(postEnd - 1, idx + 1, inEnd); - - return root; - } -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {number[]} inorder - * @param {number[]} postorder - * @return {TreeNode} - */ - -const buildTree = function (inorder, postorder) { - let pInorder = inorder.length - 1 - let pPostorder = postorder.length - 1 - return helper(inorder, postorder, null) - function helper(inorder, postorder, end) { - if (pPostorder < 0) return null - // create root node - const n = new TreeNode(postorder[pPostorder--]) - // if right node exist, create right subtree - if (inorder[pInorder] != n.val) { - n.right = helper(inorder, postorder, n) - } - pInorder-- - // if left node exist, create left subtree - if (end === null || inorder[pInorder] !== end.val) { - n.left = helper(inorder, postorder, end) - } - return n - } -} diff --git a/106.construct-binary-tree-from-inorder-and-postorder-traversal.js b/106.construct-binary-tree-from-inorder-and-postorder-traversal.js new file mode 100644 index 00000000..6106281c --- /dev/null +++ b/106.construct-binary-tree-from-inorder-and-postorder-traversal.js @@ -0,0 +1,33 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {number[]} inorder + * @param {number[]} postorder + * @return {TreeNode} + */ + +const buildTree = function(inorder, postorder) { + const inmap = {}; + const posts = postorder; + for (let i = 0; i < inorder.length; i++) { + inmap[inorder[i]] = i; + } + return helper(postorder.length - 1, 0, inorder.length - 1); + + function helper(postEnd, inStart, inEnd) { + if (postEnd < 0 || inEnd < inStart) return null; + const val = posts[postEnd]; + const idx = inmap["" + val]; + const root = new TreeNode(val); + root.left = helper(postEnd - (inEnd - idx) - 1, inStart, idx - 1); + root.right = helper(postEnd - 1, idx + 1, inEnd); + + return root; + } +}; + diff --git a/1060-missing-element-in-sorted-array.js b/1060-missing-element-in-sorted-array.js deleted file mode 100644 index a151e66f..00000000 --- a/1060-missing-element-in-sorted-array.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - -Given a sorted array A of unique numbers, find the K-th missing number -starting from the leftmost number of the array. - -Example 1: - -Input: A = [4,7,9,10], K = 1 -Output: 5 -Explanation: -The first missing number is 5. -Example 2: - -Input: A = [4,7,9,10], K = 3 -Output: 8 -Explanation: -The missing numbers are [5,6,8,...], hence the third missing number is 8. -Example 3: - -Input: A = [1,2,4], K = 3 -Output: 6 -Explanation: -The missing numbers are [3,5,6,7,...], hence the third missing number is 6. - -Note: - -1 <= A.length <= 50000 -1 <= A[i] <= 1e7 -1 <= K <= 1e8 - -*/ - - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const missingElement = function(nums, k) { - for (let i = 1, len = nums.length; i < len; i++) { - const dif = nums[i] - nums[i - 1] - 1 - if (dif >= k) { - return nums[i - 1] + k - } - k -= dif - } - return nums[nums.length - 1] + k -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const missingElement = function(nums, k) { - const n = nums.length - let l = 0 - let h = n - 1 - const missingNum = nums[n - 1] - nums[0] + 1 - n - if (missingNum < k) { - return nums[n - 1] + k - missingNum - } - while (l < h - 1) { - const m = l + ((h - l) >> 1) - const missing = nums[m] - nums[l] - (m - l) - if (missing >= k) { - h = m - } else { - k -= missing - l = m - } - } - return nums[l] + k -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const missingElement = function(nums, k) { - const n = nums.length - if (k > missing(nums, n - 1)) return nums[n - 1] + k - missing(nums, n - 1) - let left = 0, - right = n - 1, - pivot - while (left < right) { - pivot = left + Math.floor((right - left) / 2) - if (missing(nums, pivot) < k) left = pivot + 1 - else right = pivot - } - return nums[left - 1] + k - missing(nums, left - 1) -} -function missing(arr, idx) { - return arr[idx] - arr[0] - idx -} - diff --git a/1060.missing-element-in-sorted-array.js b/1060.missing-element-in-sorted-array.js new file mode 100644 index 00000000..f10a908d --- /dev/null +++ b/1060.missing-element-in-sorted-array.js @@ -0,0 +1,49 @@ +/** + +Given a sorted array A of unique numbers, find the K-th missing number +starting from the leftmost number of the array. + +Example 1: + +Input: A = [4,7,9,10], K = 1 +Output: 5 +Explanation: +The first missing number is 5. +Example 2: + +Input: A = [4,7,9,10], K = 3 +Output: 8 +Explanation: +The missing numbers are [5,6,8,...], hence the third missing number is 8. +Example 3: + +Input: A = [1,2,4], K = 3 +Output: 6 +Explanation: +The missing numbers are [3,5,6,7,...], hence the third missing number is 6. + +Note: + +1 <= A.length <= 50000 +1 <= A[i] <= 1e7 +1 <= K <= 1e8 + +*/ + + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const missingElement = function(nums, k) { + for (let i = 1, len = nums.length; i < len; i++) { + const dif = nums[i] - nums[i - 1] - 1 + if (dif >= k) { + return nums[i - 1] + k + } + k -= dif + } + return nums[nums.length - 1] + k +} + diff --git a/1061-lexicographically-smallest-equivalent-string.js b/1061.lexicographically-smallest-equivalent-string.js similarity index 100% rename from 1061-lexicographically-smallest-equivalent-string.js rename to 1061.lexicographically-smallest-equivalent-string.js diff --git a/1062-longest-repeating-substring.js b/1062-longest-repeating-substring.js deleted file mode 100644 index ee57fe13..00000000 --- a/1062-longest-repeating-substring.js +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const longestRepeatingSubstring = function(s) { - let left = 0; - let right = s.length - 1; - while(left < right) { - let pivot = Math.floor((left + right + 1) / 2); - if (hasRepeat(s, pivot)) { - left = pivot; - } else { - right = pivot - 1; - } - } - return left; -}; - -const hasRepeat = (s, l) => { - const strings = new Set(); - for (let i = 0; i < s.length - l + 1; i++) { - const sub = s.substr(i, l); - if (strings.has(sub)) { - return true; - } - strings.add(sub); - } - return false; -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const longestRepeatingSubstring = function(s) { - const n = s.length; - // dp[i][j] means # of repeated chars for substrings ending at i and j - const dp = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0)); - let res = 0; - for (let i = 1; i <= n; i++) { - for (let j = i + 1; j <= n; j++) { - if (s.charAt(i - 1) === s.charAt(j - 1)) { - dp[i][j] = dp[i - 1][j - 1] + 1; - res = Math.max(res, dp[i][j]); - } - } - } - return res; -}; - -// non-overlap version -// http://nriverwang.blogspot.com/2013/04/longest-repeated-substring.html - -/* -You are to find the longest repeated substring in a given text. -Repeated substrings may not overlap. If more than one substring is -repeated with the same length, print the first one you find.(starting -from the beginning of the text). NOTE: The substrings can't be all spaces. - -Input Sample: -Your program should accept as its first argument a path to a filename. -The input file contains several lines. Each line is one test case. -Each line contains a test string. eg. - -banana -abc - -Output Sample: -For each set of input produce a single line of output which is the -longest repeated substring. If there is none, print out the string NONE. eg. -an -NONE - -std::string repeated_substring(std::string &str) { - int len = str.length(); - - int **c = new int*[len + 1]; - for (int i = 0; i <= len; ++i) - c[i] = new int[len + 1]; - for (int i = 0; i <= len; ++i) { - c[i][0] = 0; - c[0][i] = 0; - } - - int max_len = 0, index = len + 1; - for (int i = 1; i <= len; ++i) { - for (int j = 1; j <= len; ++j) { - if (str[i-1] == str[j-1] && abs(i-j) > c[i-1][j-1]) { - c[i][j] = c[i-1][j-1] + 1; - if (c[i][j] > max_len) { - max_len = c[i][j]; - index = std::min(i, j); - } - } else { - c[i][j] = 0; - } - } - } - - for (int i = 0; i <= len; ++i) - delete[] c[i]; - delete[] c; - - if (max_len > 0) { - std::string ret = str.substr(index - max_len, max_len); - for (int i = 0; i < max_len; ++i) - if(ret[i] != ' ') - return ret; - } - - return "NONE"; -} - -*/ diff --git a/1062.longest-repeating-substring.js b/1062.longest-repeating-substring.js new file mode 100644 index 00000000..a20f587d --- /dev/null +++ b/1062.longest-repeating-substring.js @@ -0,0 +1,30 @@ +/** + * @param {string} s + * @return {number} + */ +const longestRepeatingSubstring = function(s) { + let left = 0; + let right = s.length - 1; + while(left < right) { + let pivot = Math.floor((left + right + 1) / 2); + if (hasRepeat(s, pivot)) { + left = pivot; + } else { + right = pivot - 1; + } + } + return left; +}; + +const hasRepeat = (s, l) => { + const strings = new Set(); + for (let i = 0; i < s.length - l + 1; i++) { + const sub = s.substr(i, l); + if (strings.has(sub)) { + return true; + } + strings.add(sub); + } + return false; +} + diff --git a/1064-fixed-point.js b/1064.fixed-point.js similarity index 100% rename from 1064-fixed-point.js rename to 1064.fixed-point.js diff --git a/1065-index-pairs-of-a-string.js b/1065.index-pairs-of-a-string.js similarity index 100% rename from 1065-index-pairs-of-a-string.js rename to 1065.index-pairs-of-a-string.js diff --git a/1066-campus-bikes-ii.js b/1066-campus-bikes-ii.js deleted file mode 100644 index 8b536b6d..00000000 --- a/1066-campus-bikes-ii.js +++ /dev/null @@ -1,141 +0,0 @@ -/** - * @param {number[][]} workers - * @param {number[][]} bikes - * @return {number} - */ -const assignBikes = function(workers, bikes) { - const { abs, min } = Math - const n = workers.length, m = bikes.length - - const limit = 1 << m - const dp = Array(limit).fill(Infinity) - dp[0] = 0 - let res = Infinity - for(let mask = 1; mask < limit; mask++) { - if(bitCnt(mask) > n) continue - for(let i = 0; i < m; i++) { - if((mask >> i) & 1) { - dp[mask] = min( - dp[mask], - dp[mask ^ (1 << i)] + distance(bitCnt(mask) - 1, i) - ) - } - } - if(bitCnt(mask) === n) { - res = min(res, dp[mask]) - } - } - - return res - - function bitCnt(num) { - let res = 0 - while(num) { - num = num & (num - 1) - res++ - } - - return res - } - - // worker, bike - function distance(i, j) { - return abs(workers[i][0] - bikes[j][0]) + abs(workers[i][1] - bikes[j][1]) - } -}; - -// another - -/** - * @param {number[][]} workers - * @param {number[][]} bikes - * @return {number} - */ -const assignBikes = function(workers, bikes) { - const n = workers.length, m = bikes.length - let res = Infinity - dfs(0, 0, 0) - return res - function dfs(i, mask, cur) { - if(i === n) { - res = Math.min(res, cur) - return - } - for(let j = 0; j < m; j++) { - if((mask & (1 << j)) === 0) { - dfs(i + 1, mask | (1 << j), cur + calc(i, j)) - } - } - } - - function calc(i, j) { - const a = workers[i], b = bikes[j] - return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]) - } - -}; - -// another - -/** - * @param {number[][]} workers - * @param {number[][]} bikes - * @return {number} - */ -const assignBikes = function(workers, bikes) { - const n = workers.length, m = bikes.length - const dp = Array(1 << m).fill(Infinity) - return dfs(0, 0) - - function dfs(i, mask) { - if(i >= workers.length) return 0 - if(dp[mask] !== Infinity) return dp[mask] - for(let j = 0; j < bikes.length; j++) { - if((mask & (1 << j)) === 0) { - dp[mask] = Math.min(dp[mask], dist(i, j) + dfs(i + 1, mask + (1 << j))) - } - } - - return dp[mask] - } - - function dist(j, i) { - return Math.abs(bikes[i][0] - workers[j][0]) + Math.abs(bikes[i][1] - workers[j][1]) - } -}; - -// another - -/** - * @param {number[][]} workers - * @param {number[][]} bikes - * @return {number} - */ -const assignBikes = function (workers, bikes) { - const n = workers.length - const m = bikes.length - const dp = Array.from({ length: n + 1 }, () => - Array(1 << m).fill(Number.MAX_VALUE / 2) - ) - - dp[0][0] = 0 - let min = Number.MAX_VALUE - for (let i = 1; i <= n; i++) { - for (let s = 1; s < 1 << m; s++) { - for (let j = 0; j < m; j++) { - if ((s & (1 << j)) === 0) continue - let prev = s ^ (1 << j) - dp[i][s] = Math.min( - dp[i - 1][prev] + dis(workers[i - 1], bikes[j]), - dp[i][s] - ) - if (i === n) min = Math.min(min, dp[i][s]) - } - } - } - return min -} - -function dis(p1, p2) { - return Math.abs(p1[0] - p2[0]) + Math.abs(p1[1] - p2[1]) -} diff --git a/1066.campus-bikes-ii.js b/1066.campus-bikes-ii.js new file mode 100644 index 00000000..cebb9654 --- /dev/null +++ b/1066.campus-bikes-ii.js @@ -0,0 +1,46 @@ +/** + * @param {number[][]} workers + * @param {number[][]} bikes + * @return {number} + */ +const assignBikes = function(workers, bikes) { + const { abs, min } = Math + const n = workers.length, m = bikes.length + + const limit = 1 << m + const dp = Array(limit).fill(Infinity) + dp[0] = 0 + let res = Infinity + for(let mask = 1; mask < limit; mask++) { + if(bitCnt(mask) > n) continue + for(let i = 0; i < m; i++) { + if((mask >> i) & 1) { + dp[mask] = min( + dp[mask], + dp[mask ^ (1 << i)] + distance(bitCnt(mask) - 1, i) + ) + } + } + if(bitCnt(mask) === n) { + res = min(res, dp[mask]) + } + } + + return res + + function bitCnt(num) { + let res = 0 + while(num) { + num = num & (num - 1) + res++ + } + + return res + } + + // worker, bike + function distance(i, j) { + return abs(workers[i][0] - bikes[j][0]) + abs(workers[i][1] - bikes[j][1]) + } +}; + diff --git a/1067-digit-count-in-range.js b/1067-digit-count-in-range.js deleted file mode 100644 index 7b75d18d..00000000 --- a/1067-digit-count-in-range.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @param {number} d - * @param {number} low - * @param {number} high - * @return {number} - */ -const digitsCount = function(d, low, high) { - return countDigit(high, d) - countDigit(low - 1, d) -}; -function countDigit(limit, d) { - let res = 0 - const str = `${limit}` - const len = str.length - const { pow } = Math - if(d === 0) { - for(let i = 1; i < len; i++) { - const pre = ~~(limit / pow(10, i)) - const post = pow(10, i - 1) - res += (pre - 1) * post - const e = +str[len - i] - if(e > d) { - res += post - } else if(e === d) { - res += (limit % post) + 1 - } - } - } else { - for(let i = 1; i <= len; i++) { - const pre = ~~(limit / pow(10, i)) - const post = pow(10, i - 1) - res += pre * post - const e = +str[len - i] - if(e > d) { - res += post - } else if(e === d) { - res += (limit % post) + 1 - } - } - } - - - return res -} - - -// another - -/** - * @param {number} d - * @param {number} low - * @param {number} high - * @return {number} - */ -const digitsCount = function (d, low, high) { - return countDigit(high, d) - countDigit(low - 1, d) - - function countDigit(n, d) { - if (n < 0 || n < d) { - return 0 - } - let count = 0 - for (let i = 1; i <= n; i *= 10) { - let divider = i * 10 - count += ((n / divider) >> 0) * i - if (d > 0) { - // tailing number need to be large than d * i to qualify. - count += Math.min(Math.max((n % divider) - d * i + 1, 0), i) - } else { - if (n / divider > 0) { - if (i > 1) { - // when d == 0, we need avoid to take numbers like 0xxxx into account. - count -= i - count += Math.min((n % divider) + 1, i) - } - } - } - } - return count - } -} diff --git a/1067.digit-count-in-range.js b/1067.digit-count-in-range.js new file mode 100644 index 00000000..bf7226fc --- /dev/null +++ b/1067.digit-count-in-range.js @@ -0,0 +1,45 @@ +/** + * @param {number} d + * @param {number} low + * @param {number} high + * @return {number} + */ +const digitsCount = function(d, low, high) { + return countDigit(high, d) - countDigit(low - 1, d) +}; +function countDigit(limit, d) { + let res = 0 + const str = `${limit}` + const len = str.length + const { pow } = Math + if(d === 0) { + for(let i = 1; i < len; i++) { + const pre = ~~(limit / pow(10, i)) + const post = pow(10, i - 1) + res += (pre - 1) * post + const e = +str[len - i] + if(e > d) { + res += post + } else if(e === d) { + res += (limit % post) + 1 + } + } + } else { + for(let i = 1; i <= len; i++) { + const pre = ~~(limit / pow(10, i)) + const post = pow(10, i - 1) + res += pre * post + const e = +str[len - i] + if(e > d) { + res += post + } else if(e === d) { + res += (limit % post) + 1 + } + } + } + + + return res +} + + diff --git a/107-binary-tree-level-order-traversal-ii.js b/107-binary-tree-level-order-traversal-ii.js deleted file mode 100644 index 12484e33..00000000 --- a/107-binary-tree-level-order-traversal-ii.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number[][]} - */ -const levelOrderBottom = function(root) { - const levels = [] - postOrderTraversal(root) - return levels.reverse() - - function postOrderTraversal(node, level = 0) { - if (node) { - if (!levels[level]) levels.push([]) - postOrderTraversal(node.left, level + 1) - postOrderTraversal(node.right, level + 1) - levels[level].push(node.val) - } - } -} - -// another - -const levelOrderBottom = function(root) { - if (!root) return [] - const currentLevelNodes = [root] - const result = [] - while (currentLevelNodes.length > 0) { - const count = currentLevelNodes.length - const currentLevelValues = [] - for (let i = 0; i < count; i++) { - const node = currentLevelNodes.shift() - currentLevelValues.push(node.val) - if (node.left) currentLevelNodes.push(node.left) - if (node.right) currentLevelNodes.push(node.right) - } - result.unshift(currentLevelValues) - } - return result -} diff --git a/107.binary-tree-level-order-traversal-ii.js b/107.binary-tree-level-order-traversal-ii.js new file mode 100644 index 00000000..3c91921d --- /dev/null +++ b/107.binary-tree-level-order-traversal-ii.js @@ -0,0 +1,26 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +const levelOrderBottom = function(root) { + const levels = [] + postOrderTraversal(root) + return levels.reverse() + + function postOrderTraversal(node, level = 0) { + if (node) { + if (!levels[level]) levels.push([]) + postOrderTraversal(node.left, level + 1) + postOrderTraversal(node.right, level + 1) + levels[level].push(node.val) + } + } +} + diff --git a/1071-greatest-common-divisor-of-strings.js b/1071.greatest-common-divisor-of-strings.js similarity index 100% rename from 1071-greatest-common-divisor-of-strings.js rename to 1071.greatest-common-divisor-of-strings.js diff --git a/1072-flip-columns-for-maximum-number-of-equal-rows.js b/1072.flip-columns-for-maximum-number-of-equal-rows.js similarity index 100% rename from 1072-flip-columns-for-maximum-number-of-equal-rows.js rename to 1072.flip-columns-for-maximum-number-of-equal-rows.js diff --git a/1073-adding-two-negabinary-numbers.js b/1073.adding-two-negabinary-numbers.js similarity index 100% rename from 1073-adding-two-negabinary-numbers.js rename to 1073.adding-two-negabinary-numbers.js diff --git a/1074-number-of-submatrices-that-sum-to-target.js b/1074.number-of-submatrices-that-sum-to-target.js similarity index 100% rename from 1074-number-of-submatrices-that-sum-to-target.js rename to 1074.number-of-submatrices-that-sum-to-target.js diff --git a/1079-letter-tile-possibilities.js b/1079-letter-tile-possibilities.js deleted file mode 100644 index e4317a21..00000000 --- a/1079-letter-tile-possibilities.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @param {string} tiles - * @return {number} - */ -const numTilePossibilities = function(tiles) { - const obj = { count: 0 }; - dfs(tiles, new Array(tiles.length).fill(false), new Set(), "", obj); - return obj.count; -}; - -function dfs(tiles, used, visited, path, obj) { - if (path !== "" && !visited.has(path)) obj.count++; - visited.add(path) - - for (let i = 0; i < tiles.length; i++) { - if (used[i]) continue; - used[i] = true; - dfs(tiles, used, visited, path + tiles.charAt(i), obj); - used[i] = false; - } -} - -// another - -/** - * @param {string} tiles - * @return {number} - */ -const numTilePossibilities = function(tiles) { - let used = new Array(tiles.length).fill(false); - let visited = new Set(); - let cnt = 0; - const dfs = (path) => { - if (path.length && !visited.has(path)) { - visited.add(path); - cnt++; - } - for (let i = 0; i < tiles.length; i++) { - if (used[i]) continue; - used[i] = true; - dfs(path + tiles[i]); - used[i] = false; - } - } - dfs(''); - return cnt; -}; - -// another - -/** - * @param {string} tiles - * @return {number} - */ -const numTilePossibilities = function(tiles) { - const count = new Array(26).fill(0) - const ACode = 'A'.charCodeAt(0) - for (let i = 0, len = tiles.length; i < len; i++) { - count[tiles.charCodeAt(i) - ACode]++ - } - return dfs(count) -} - -function dfs(arr) { - let sum = 0 - for (let i = 0; i < 26; i++) { - if (arr[i] === 0) continue - sum++ - arr[i]-- - sum += dfs(arr) - arr[i]++ - } - return sum -} diff --git a/1079.letter-tile-possibilities.js b/1079.letter-tile-possibilities.js new file mode 100644 index 00000000..d33ba2ae --- /dev/null +++ b/1079.letter-tile-possibilities.js @@ -0,0 +1,22 @@ +/** + * @param {string} tiles + * @return {number} + */ +const numTilePossibilities = function(tiles) { + const obj = { count: 0 }; + dfs(tiles, new Array(tiles.length).fill(false), new Set(), "", obj); + return obj.count; +}; + +function dfs(tiles, used, visited, path, obj) { + if (path !== "" && !visited.has(path)) obj.count++; + visited.add(path) + + for (let i = 0; i < tiles.length; i++) { + if (used[i]) continue; + used[i] = true; + dfs(tiles, used, visited, path + tiles.charAt(i), obj); + used[i] = false; + } +} + diff --git a/108-convert-sorted-array-to-binary-search-tree.js b/108-convert-sorted-array-to-binary-search-tree.js deleted file mode 100755 index 16e7f4a5..00000000 --- a/108-convert-sorted-array-to-binary-search-tree.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {number[]} nums - * @return {TreeNode} - */ -const sortedArrayToBST = function(nums) { - if (nums.length == 0) { - return null; - } - const head = helper(nums, 0, nums.length - 1); - return head; -}; - -function helper(num, low, high) { - if (low > high) { - // Done - return null; - } - let mid = Math.floor((low + high) / 2); - let node = new TreeNode(num[mid]); - node.left = helper(num, low, mid - 1); - node.right = helper(num, mid + 1, high); - return node; -} diff --git a/108.convert-sorted-array-to-binary-search-tree.js b/108.convert-sorted-array-to-binary-search-tree.js new file mode 100644 index 00000000..cbc36d25 --- /dev/null +++ b/108.convert-sorted-array-to-binary-search-tree.js @@ -0,0 +1,30 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {number[]} nums + * @return {TreeNode} + */ +const sortedArrayToBST = function(nums) { + if (nums.length == 0) { + return null; + } + const head = helper(nums, 0, nums.length - 1); + return head; +}; + +function helper(num, low, high) { + if (low > high) { + // Done + return null; + } + let mid = Math.floor((low + high) / 2); + let node = new TreeNode(num[mid]); + node.left = helper(num, low, mid - 1); + node.right = helper(num, mid + 1, high); + return node; +} diff --git a/1081-smallest-subsequence-of-distinct-characters.js b/1081-smallest-subsequence-of-distinct-characters.js deleted file mode 100644 index 2b5e37c8..00000000 --- a/1081-smallest-subsequence-of-distinct-characters.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @param {string} text - * @return {string} - */ -const smallestSubsequence = function(text) { - if (text === '') return '' - let counter = new Array(128).fill(0) - for (let i = 0; i < text.length; i++) counter[text.charCodeAt(i)]++ - let minChar = 128 - let minIndex = 0 - for (let i = 0; i < text.length; i++) { - let c = text.charCodeAt(i) - if (c < minChar) { - minChar = c - minIndex = i - } - if (--counter[c] === 0) { - return ( - String.fromCharCode(minChar) + - smallestSubsequence( - text - .slice(minIndex + 1) - .replace(new RegExp(String.fromCharCode(minChar), 'g'), '') - ) - ) - } - } - return '' -} - -// another - -/** - * @param {string} text - * @return {string} - */ -const smallestSubsequence = function(s) { - let res = [] - const count = new Array(26).fill(0) - const used = new Array(26).fill(0) - const aCode = 'a'.charCodeAt(0) - for (let el of s) count[el.charCodeAt(0) - aCode]++ - for (let el of s) { - count[el.charCodeAt(0) - aCode]-- - if (used[el.charCodeAt(0) - aCode]++ > 0) continue - while ( - res.length && - res[res.length - 1].charCodeAt(0) > el.charCodeAt(0) && - count[res[res.length - 1].charCodeAt(0) - aCode] > 0 - ) { - used[res[res.length - 1].charCodeAt(0) - aCode] = 0 - res.pop() - } - res.push(el) - } - return res.join('') -}; - -// anoother - - -/** - * @param {string} text - * @return {string} - */ -const smallestSubsequence = function(text) { - const n = text.length, stack = [], last = {}, visited = {} - for(let i = 0; i < n; i++) last[text[i]] = i - for(let i = 0; i < n; i++) { - const ch = text[i] - if (visited[ch]) continue - while(stack.length && stack[stack.length - 1] > ch && last[stack[stack.length - 1]] > i) { - visited[stack[stack.length - 1]] = 0 - stack.pop() - } - visited[ch] = 1 - stack.push(ch) - } - - return stack.join('') -}; diff --git a/1081.smallest-subsequence-of-distinct-characters.js b/1081.smallest-subsequence-of-distinct-characters.js new file mode 100644 index 00000000..23e6105f --- /dev/null +++ b/1081.smallest-subsequence-of-distinct-characters.js @@ -0,0 +1,30 @@ +/** + * @param {string} text + * @return {string} + */ +const smallestSubsequence = function(text) { + if (text === '') return '' + let counter = new Array(128).fill(0) + for (let i = 0; i < text.length; i++) counter[text.charCodeAt(i)]++ + let minChar = 128 + let minIndex = 0 + for (let i = 0; i < text.length; i++) { + let c = text.charCodeAt(i) + if (c < minChar) { + minChar = c + minIndex = i + } + if (--counter[c] === 0) { + return ( + String.fromCharCode(minChar) + + smallestSubsequence( + text + .slice(minIndex + 1) + .replace(new RegExp(String.fromCharCode(minChar), 'g'), '') + ) + ) + } + } + return '' +} + diff --git a/1085-sum-of-digits-in-the-minimum-number.js b/1085.sum-of-digits-in-the-minimum-number.js similarity index 100% rename from 1085-sum-of-digits-in-the-minimum-number.js rename to 1085.sum-of-digits-in-the-minimum-number.js diff --git a/1086-high-five.js b/1086.high-five.js similarity index 100% rename from 1086-high-five.js rename to 1086.high-five.js diff --git a/1087-brace-expansion.js b/1087.brace-expansion.js similarity index 100% rename from 1087-brace-expansion.js rename to 1087.brace-expansion.js diff --git a/1088-confusing-number-ii.js b/1088.confusing-number-ii.js similarity index 100% rename from 1088-confusing-number-ii.js rename to 1088.confusing-number-ii.js diff --git a/1089-duplicate-zeros.js b/1089.duplicate-zeros.js similarity index 100% rename from 1089-duplicate-zeros.js rename to 1089.duplicate-zeros.js diff --git a/109-convert-sorted-list-to-binary-search-tree.js b/109-convert-sorted-list-to-binary-search-tree.js deleted file mode 100644 index a4e168e3..00000000 --- a/109-convert-sorted-list-to-binary-search-tree.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {ListNode} head - * @return {TreeNode} - */ -const sortedListToBST = function(head) { - if(head == null) return null - const arr = [] - let cur = head - while(cur !== null) { - arr.push(cur) - cur = cur.next - } - return build(arr, null, '') -}; - -function build(arr, parent, type) { - if(arr.length === 0) return - let mid = Math.floor(arr.length / 2) - let left = arr.slice(0, mid) - let right = arr.slice(mid + 1) - const node = new TreeNode(arr[mid].val) - if(parent) parent[type] = node - build(left, node, 'left') - build(right, node, 'right') - return node -} - -// another - -const sortedListToBST = function(head, tail = null) { - if (head === tail) { - return null; - } else if (head.next === tail) { - return new TreeNode(head.val); - } else { - let slow = head; - let fast = head; - while (fast !== tail && fast.next !== tail) { - slow = slow.next; - fast = fast.next.next; - } - let node = new TreeNode(slow.val); - node.left = sortedListToBST(head, slow); - node.right = sortedListToBST(slow.next, tail); - return node; - } -}; diff --git a/109.convert-sorted-list-to-binary-search-tree.js b/109.convert-sorted-list-to-binary-search-tree.js new file mode 100644 index 00000000..000c140f --- /dev/null +++ b/109.convert-sorted-list-to-binary-search-tree.js @@ -0,0 +1,41 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {ListNode} head + * @return {TreeNode} + */ +const sortedListToBST = function(head) { + if(head == null) return null + const arr = [] + let cur = head + while(cur !== null) { + arr.push(cur) + cur = cur.next + } + return build(arr, null, '') +}; + +function build(arr, parent, type) { + if(arr.length === 0) return + let mid = Math.floor(arr.length / 2) + let left = arr.slice(0, mid) + let right = arr.slice(mid + 1) + const node = new TreeNode(arr[mid].val) + if(parent) parent[type] = node + build(left, node, 'left') + build(right, node, 'right') + return node +} + diff --git a/1090-largest-values-from-labels.js b/1090.largest-values-from-labels.js similarity index 100% rename from 1090-largest-values-from-labels.js rename to 1090.largest-values-from-labels.js diff --git a/1091-shortest-path-in-binary-matrix.js b/1091-shortest-path-in-binary-matrix.js deleted file mode 100644 index 110137e1..00000000 --- a/1091-shortest-path-in-binary-matrix.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const shortestPathBinaryMatrix = function(grid) { - if(grid == null || grid.length === 0 || grid[0][0] === 1) return -1 - let res = 1 - const n = grid.length - const dirs = [ - [1, 0], - [-1, 0], - [0, 1], - [0, -1], - [-1, -1], - [-1, 1], - [1, 1], - [1, -1], - ] - let q = [[0, 0]] - while(q.length) { - const tmp = q - q = [] - for(let [x, y] of tmp) { - if (x < 0 || x >= n || y < 0 || y >= n || grid[x][y] !== 0) continue - if(x === n - 1 && y === n - 1) return res - grid[x][y] = 1 - for(let [dx, dy] of dirs) { - q.push([x + dx, y + dy]) - } - } - res++ - } - return -1 -}; - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -const shortestPathBinaryMatrix = function(grid) { - if(grid == null || grid.length === 0 || grid[0][0] === 1) return -1 - let res = 1 - const n = grid.length - const dirs = [ - [1, 0], - [-1, 0], - [0, 1], - [0, -1], - [-1, -1], - [-1, 1], - [1, 1], - [1, -1], - ] - let q = [[0, 0]] - while(q.length) { - let ref = q - q = [] - for(let [x, y] of ref) { - if(x === n - 1 && y === n - 1) return res - grid[x][y] = 1 - for(let [dx, dy] of dirs) { - const nx = x + dx, ny = y + dy - if(helper(grid, nx, ny)) { - q.push([nx, ny]) - grid[nx][ny] = 1 // very important - } - } - } - res++ - } - return -1 -}; - -function helper(grid, i, j) { - const n = grid.length - if(i < 0 || i >= n || j < 0 || j >= n || grid[i][j] !== 0) return false - return true -} diff --git a/1091.shortest-path-in-binary-matrix.js b/1091.shortest-path-in-binary-matrix.js new file mode 100644 index 00000000..efbd89f8 --- /dev/null +++ b/1091.shortest-path-in-binary-matrix.js @@ -0,0 +1,35 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const shortestPathBinaryMatrix = function(grid) { + if(grid == null || grid.length === 0 || grid[0][0] === 1) return -1 + let res = 1 + const n = grid.length + const dirs = [ + [1, 0], + [-1, 0], + [0, 1], + [0, -1], + [-1, -1], + [-1, 1], + [1, 1], + [1, -1], + ] + let q = [[0, 0]] + while(q.length) { + const tmp = q + q = [] + for(let [x, y] of tmp) { + if (x < 0 || x >= n || y < 0 || y >= n || grid[x][y] !== 0) continue + if(x === n - 1 && y === n - 1) return res + grid[x][y] = 1 + for(let [dx, dy] of dirs) { + q.push([x + dx, y + dy]) + } + } + res++ + } + return -1 +}; + diff --git a/1092-shortest-common-supersequence.js b/1092.shortest-common-supersequence.js similarity index 100% rename from 1092-shortest-common-supersequence.js rename to 1092.shortest-common-supersequence.js diff --git a/1093-statistics-from-a-large-sample.js b/1093.statistics-from-a-large-sample.js similarity index 100% rename from 1093-statistics-from-a-large-sample.js rename to 1093.statistics-from-a-large-sample.js diff --git a/1094-car-pooling.js b/1094-car-pooling.js deleted file mode 100644 index a37547cf..00000000 --- a/1094-car-pooling.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @param {number[][]} trips - * @param {number} capacity - * @return {boolean} - */ -const carPooling = function(trips, capacity) { - const arr = Array(1001).fill(0) - for(const [num, s, e] of trips) { - arr[s] += num - arr[e] -= num - } - for(let i = 1; i < 1001; i++) { - arr[i] += arr[i - 1] - } - - for(let e of arr) { - if(e > capacity) return false - } - return true -}; - -// another - -/** - * @param {number[][]} trips - * @param {number} capacity - * @return {boolean} - */ -const carPooling = function(trips, capacity) { - let stops = new Array(1001).fill(0) - for (let t of trips) { - stops[t[1]] += t[0] - stops[t[2]] -= t[0] - } - for (let i = 0; capacity >= 0 && i < 1001; ++i) capacity -= stops[i] - return capacity >= 0 -} - -// another - -/** - * @param {number[][]} trips - * @param {number} capacity - * @return {boolean} - */ -const carPooling = function(trips, capacity) { - const arr = Array(1001).fill(0) - for(let el of trips) { - const [num, s, e] = el - arr[s] += num - arr[e] -= num - } - for(let i = 1; i < 1001; i++) { - if(arr[i] !== 0) arr[i] += arr[i - 1] - else arr[i] = arr[i - 1] - } - for(let e of arr) { - if(e > capacity) return false - } - return true -}; diff --git a/1094.car-pooling.js b/1094.car-pooling.js new file mode 100644 index 00000000..30e17070 --- /dev/null +++ b/1094.car-pooling.js @@ -0,0 +1,21 @@ +/** + * @param {number[][]} trips + * @param {number} capacity + * @return {boolean} + */ +const carPooling = function(trips, capacity) { + const arr = Array(1001).fill(0) + for(const [num, s, e] of trips) { + arr[s] += num + arr[e] -= num + } + for(let i = 1; i < 1001; i++) { + arr[i] += arr[i - 1] + } + + for(let e of arr) { + if(e > capacity) return false + } + return true +}; + diff --git a/1095-find-in-mountain-array.js b/1095.find-in-mountain-array.js similarity index 100% rename from 1095-find-in-mountain-array.js rename to 1095.find-in-mountain-array.js diff --git a/1096-brace-expansion-ii.js b/1096.brace-expansion-ii.js similarity index 100% rename from 1096-brace-expansion-ii.js rename to 1096.brace-expansion-ii.js diff --git a/1099-two-sum-less-than-k.js b/1099.two-sum-less-than-k.js similarity index 100% rename from 1099-two-sum-less-than-k.js rename to 1099.two-sum-less-than-k.js diff --git a/11-container-with-most-water.js b/11-container-with-most-water.js deleted file mode 100755 index 2b3aa808..00000000 --- a/11-container-with-most-water.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @param {number[]} height - * @return {number} - */ -const maxArea = function(height) { - let res = 0, l = 0, r = height.length - 1 - while(l < r) { - const tmp = (r - l) * Math.min(height[l], height[r]) - if(tmp > res) res = tmp - if(height[l] < height[r]) l++ - else r-- - } - return res -}; diff --git a/11.container-with-most-water.js b/11.container-with-most-water.js new file mode 100644 index 00000000..69c6c997 --- /dev/null +++ b/11.container-with-most-water.js @@ -0,0 +1,14 @@ +/** + * @param {number[]} height + * @return {number} + */ +const maxArea = function(height) { + let res = 0, l = 0, r = height.length - 1 + while(l < r) { + const tmp = (r - l) * Math.min(height[l], height[r]) + if(tmp > res) res = tmp + if(height[l] < height[r]) l++ + else r-- + } + return res +}; diff --git a/110-balanced-binary-tree.js b/110.balanced-binary-tree.js similarity index 100% rename from 110-balanced-binary-tree.js rename to 110.balanced-binary-tree.js diff --git a/1102-path-with-maximum-minimum-value.js b/1102.path-with-maximum-minimum-value.js similarity index 100% rename from 1102-path-with-maximum-minimum-value.js rename to 1102.path-with-maximum-minimum-value.js diff --git a/1103-distribute-candies-to-people.js b/1103.distribute-candies-to-people.js similarity index 100% rename from 1103-distribute-candies-to-people.js rename to 1103.distribute-candies-to-people.js diff --git a/1104.path-in-zigzag-labelled-binary-tree.js b/1104.path-in-zigzag-labelled-binary-tree.js deleted file mode 100644 index 7f5f3c54..00000000 --- a/1104.path-in-zigzag-labelled-binary-tree.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @param {number} label - * @return {number[]} - */ -const pathInZigZagTree = function(label) { - const res = [], { log2, floor, ceil } = Math - const level = floor(log2(label)) - let compl = 2 ** (level + 1) - 1 + 2 ** level - label - - while(label) { - res.push(label) - label = floor(label / 2) - compl = floor(compl / 2) - ;[label, compl] = [compl, label] - } - - res.reverse() - - return res -}; - -// another - - -/** - * @param {number} label - * @return {number[]} - */ -const pathInZigZagTree = function(label) { - const res = [], { log2, floor, ceil } = Math - - res.push(label) - - // check last row - const lev = ceil(log2(label + 1)) - const reverse = lev % 2 === 0 ? true : false - // console.log(reverse, lev) - if(reverse) { - const idx = 2 ** lev - 1 - label - label = 2 ** (lev - 1) + idx - } - // console.log(label) - - while(label > 1) { - const level = floor(log2(label)) - const parent = floor(label / 2) - const parentLevelNum = 2 ** (level - 1) - const parentReverse = level % 2 === 0 ? true : false - const parentStart = 2 ** (level - 1) - const parentEnd = 2 ** level - 1 - // console.log(parentStart, parentEnd, parent) - const idx = parent - parentStart - res.push(parentReverse ? parentEnd - idx : parentStart + idx) - - label = parent - } - - - res.reverse() - return res -}; diff --git a/1104.path.in-zigzag-labelled-binary-tree.js b/1104.path.in-zigzag-labelled-binary-tree.js new file mode 100644 index 00000000..75430edf --- /dev/null +++ b/1104.path.in-zigzag-labelled-binary-tree.js @@ -0,0 +1,21 @@ +/** + * @param {number} label + * @return {number[]} + */ +const pathInZigZagTree = function(label) { + const res = [], { log2, floor, ceil } = Math + const level = floor(log2(label)) + let compl = 2 ** (level + 1) - 1 + 2 ** level - label + + while(label) { + res.push(label) + label = floor(label / 2) + compl = floor(compl / 2) + ;[label, compl] = [compl, label] + } + + res.reverse() + + return res +}; + diff --git a/1105-filling-bookcase-shelves.js b/1105-filling-bookcase-shelves.js deleted file mode 100644 index 26f71c83..00000000 --- a/1105-filling-bookcase-shelves.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {number[][]} books - * @param {number} shelf_width - * @return {number} - */ -const minHeightShelves = function(books, shelf_width) { - const dp = new Array(books.length + 1) - dp[0] = 0 - for(let i = 1; i <= books.length; i++) { - let width = books[i - 1][0] - let height = books[i - 1][1] - dp[i] = dp[i - 1] + height - for(let j = i - 1; j > 0 && width + books[j - 1][0] <= shelf_width; j--) { - height = Math.max(height, books[j - 1][1]) - width += books[j - 1][0] - dp[i] = Math.min(dp[i], dp[j - 1] + height) - } - } - return dp[books.length] -}; - -// another - -/** - * @param {number[][]} books - * @param {number} shelf_width - * @return {number} - */ -const minHeightShelves = function(books, shelf_width) { - const n = books.length, dp = Array(1001).fill(Infinity) - dp[0] = 0 - for(let i = 0; i < n; i++) { - let sum = 0, mx = 0 - for(let j = i; j >= 0 && sum + books[j][0] <= shelf_width; j--) { - sum += books[j][0] - mx = Math.max(mx, books[j][1]) - dp[i + 1] = Math.min(dp[i + 1], dp[j] + mx) - } - } - return dp[n] -}; - -// another - -/** - * @param {number[][]} books - * @param {number} shelf_width - * @return {number} - */ - const minHeightShelves = function(books, shelf_width) { - const n = books.length, dp = Array(1001) - dp[0] = 0 - - for(let i = 0; i < n; i++) { - let [w, h] = books[i] - dp[i + 1] = dp[i] + h - for(let j = i - 1; j >= 0 && w + books[j][0] <= shelf_width; j--) { - h = Math.max(h, books[j][1]) - w += books[j][0] - dp[i + 1] = Math.min(dp[i + 1], dp[j] + h) - } - } - - return dp[n] -}; diff --git a/1105.filling-bookcase-shelves.js b/1105.filling-bookcase-shelves.js new file mode 100644 index 00000000..4e7e7bd0 --- /dev/null +++ b/1105.filling-bookcase-shelves.js @@ -0,0 +1,21 @@ +/** + * @param {number[][]} books + * @param {number} shelf_width + * @return {number} + */ +const minHeightShelves = function(books, shelf_width) { + const dp = new Array(books.length + 1) + dp[0] = 0 + for(let i = 1; i <= books.length; i++) { + let width = books[i - 1][0] + let height = books[i - 1][1] + dp[i] = dp[i - 1] + height + for(let j = i - 1; j > 0 && width + books[j - 1][0] <= shelf_width; j--) { + height = Math.max(height, books[j - 1][1]) + width += books[j - 1][0] + dp[i] = Math.min(dp[i], dp[j - 1] + height) + } + } + return dp[books.length] +}; + diff --git a/1106-parsing-a-boolean-expression.js b/1106.parsing-a-boolean-expression.js similarity index 100% rename from 1106-parsing-a-boolean-expression.js rename to 1106.parsing-a-boolean-expression.js diff --git a/1108-defanging-an-ip-address.js b/1108.defanging-an-ip-address.js similarity index 100% rename from 1108-defanging-an-ip-address.js rename to 1108.defanging-an-ip-address.js diff --git a/1109-corporate-flight-bookings.js b/1109-corporate-flight-bookings.js deleted file mode 100644 index 8fe83d1c..00000000 --- a/1109-corporate-flight-bookings.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @param {number[][]} bookings - * @param {number} n - * @return {number[]} - */ -const corpFlightBookings = function(bookings, n) { - const arr = Array(n + 2).fill(0) - for(const [s, e, num] of bookings) { - arr[s] += num - arr[e + 1] -= num - } - for(let i = 1; i < n + 2; i++) { - arr[i] += arr[i - 1] - } - arr.pop() - arr.shift() - return arr -}; - -// another - -/** - * @param {number[][]} bookings - * @param {number} n - * @return {number[]} - */ -const corpFlightBookings = function(bookings, n) { - let res = new Array(n).fill(0) - for (let v of bookings) { - res[v[0] - 1] += v[2] - if (v[1] < n) res[v[1]] -= v[2] - } - for (let i = 1; i < n; ++i) res[i] += res[i - 1] - return res -} - -// another - -/** - * @param {number[][]} bookings - * @param {number} n - * @return {number[]} - */ -const corpFlightBookings = function(bookings, n) { - const arr = Array(n + 2).fill(0) - for(let [s, e, num] of bookings) { - arr[s] += num - arr[e + 1] -= num - } - for(let i = 1; i <= n; i++) { - if(arr[i] !== 0) arr[i] += arr[i - 1] - else arr[i] = arr[i - 1] - } - return arr.slice(1, n + 1) -}; diff --git a/1109.corporate-flight-bookings.js b/1109.corporate-flight-bookings.js new file mode 100644 index 00000000..9e2a4f97 --- /dev/null +++ b/1109.corporate-flight-bookings.js @@ -0,0 +1,19 @@ +/** + * @param {number[][]} bookings + * @param {number} n + * @return {number[]} + */ +const corpFlightBookings = function(bookings, n) { + const arr = Array(n + 2).fill(0) + for(const [s, e, num] of bookings) { + arr[s] += num + arr[e + 1] -= num + } + for(let i = 1; i < n + 2; i++) { + arr[i] += arr[i - 1] + } + arr.pop() + arr.shift() + return arr +}; + diff --git a/111-minimum-depth-of-binary-tree.js b/111.minimum-depth-of-binary-tree.js similarity index 100% rename from 111-minimum-depth-of-binary-tree.js rename to 111.minimum-depth-of-binary-tree.js diff --git a/1110-delete-nodes-and-return-forest.js b/1110.delete-nodes-and-return-forest.js similarity index 100% rename from 1110-delete-nodes-and-return-forest.js rename to 1110.delete-nodes-and-return-forest.js diff --git a/1111-maximum-nesting-depth-of-two-valid-parentheses-strings.js b/1111.maximum-nesting-depth-of-two-valid-parentheses-strings.js similarity index 100% rename from 1111-maximum-nesting-depth-of-two-valid-parentheses-strings.js rename to 1111.maximum-nesting-depth-of-two-valid-parentheses-strings.js diff --git a/1118-number-of-days-in-a-month.js b/1118-number-of-days-in-a-month.js deleted file mode 100644 index f9a90c14..00000000 --- a/1118-number-of-days-in-a-month.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - -Given a year Y and a month M, return how many days there are in that month. - -Example 1: - -Input: Y = 1992, M = 7 -Output: 31 -Example 2: - -Input: Y = 2000, M = 2 -Output: 29 -Example 3: - -Input: Y = 1900, M = 2 -Output: 28 - -Note: - -1583 <= Y <= 2100 -1 <= M <= 12 - -*/ - -/** - * @param {number} Y - * @param {number} M - * @return {number} - */ -function numberOfDays(Y, M) { - switch (M) { - case 2: - return Y % 400 === 0 || (Y % 4 === 0 && Y % 100 !== 0) ? 29 : 28; - case 4: - case 6: - case 9: - case 11: - return 30; - default: - return 31; - } -} - -// another - -const numberOfDays = function(Y, M) { - return new Date(Y,M,0).getDate(); -}; - -// another - -/** - * @param {number} Y - * @param {number} M - * @return {number} - */ -const numberOfDays = function(Y, M) { - const d = new Date(Y, M - 1) - let num = 0 - while(d.getMonth() === M - 1) { - num++ - const n = d.getDate() - d.setDate(n + 1) - } - return num -}; diff --git a/1118.number-of-days-in-a-month.js b/1118.number-of-days-in-a-month.js new file mode 100644 index 00000000..394e8353 --- /dev/null +++ b/1118.number-of-days-in-a-month.js @@ -0,0 +1,43 @@ +/** + +Given a year Y and a month M, return how many days there are in that month. + +Example 1: + +Input: Y = 1992, M = 7 +Output: 31 +Example 2: + +Input: Y = 2000, M = 2 +Output: 29 +Example 3: + +Input: Y = 1900, M = 2 +Output: 28 + +Note: + +1583 <= Y <= 2100 +1 <= M <= 12 + +*/ + +/** + * @param {number} Y + * @param {number} M + * @return {number} + */ +function numberOfDays(Y, M) { + switch (M) { + case 2: + return Y % 400 === 0 || (Y % 4 === 0 && Y % 100 !== 0) ? 29 : 28; + case 4: + case 6: + case 9: + case 11: + return 30; + default: + return 31; + } +} + diff --git a/1119-remove-vowels-from-a-string.js b/1119.remove-vowels-from-a-string.js similarity index 100% rename from 1119-remove-vowels-from-a-string.js rename to 1119.remove-vowels-from-a-string.js diff --git a/112-path-sum.js b/112.path-sum.js similarity index 100% rename from 112-path-sum.js rename to 112.path-sum.js diff --git a/1120-maximum-average-subtree.js b/1120.maximum-average-subtree.js similarity index 100% rename from 1120-maximum-average-subtree.js rename to 1120.maximum-average-subtree.js diff --git a/1121-divide-array-into-increasing-sequences.js b/1121.divide-array-into-increasing-sequences.js similarity index 100% rename from 1121-divide-array-into-increasing-sequences.js rename to 1121.divide-array-into-increasing-sequences.js diff --git a/1122-relative-sort-array.js b/1122.relative-sort-array.js similarity index 100% rename from 1122-relative-sort-array.js rename to 1122.relative-sort-array.js diff --git a/1123-lowest-common-ancestor-of-deepest-leaves.js b/1123-lowest-common-ancestor-of-deepest-leaves.js deleted file mode 100644 index ef42ddea..00000000 --- a/1123-lowest-common-ancestor-of-deepest-leaves.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode} - */ -const lcaDeepestLeaves = function(root) { - let maxDepth = 0, lcaNode = null - - function lca(node, depth) { - if(node == null) return depth - 1 - maxDepth = Math.max(depth, maxDepth) - const left = lca(node.left, depth + 1) - const right = lca(node.right, depth + 1) - if(left === maxDepth && right === maxDepth) { - lcaNode = node - } - return Math.max(left, right) - } - - lca(root, 0) - return lcaNode -}; - - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode} - */ -const lcaDeepestLeaves = function(root) { - if (root === null) return null - const getHeight = root => { - if (root === null) return 0 - const res = Math.max(getHeight(root.left), getHeight(root.right)) + 1 - return res - } - if (getHeight(root.left) === getHeight(root.right)) { - return root - } else if (getHeight(root.left) > getHeight(root.right)) { - return lcaDeepestLeaves(root.left) - } else { - return lcaDeepestLeaves(root.right) - } -} - -// BFS - -const lcaDeepestLeaves = function(root) { - let current = [root]; - let level = 0; - let last = []; - while(current.length) { - let next = []; - for (var i = 0; i < current.length; i++) { - if (current[i].left) { - current[i].left.parent = current[i]; - next.push(current[i].left); - } - if (current[i].right) { - current[i].right.parent = current[i]; - next.push(current[i].right); - } - } - last = current; - current = next; - } - let parent = last[0].parent; - if (!parent) { - return last[0]; - } - while(last.length > 1) { - let next = []; - for (var i = 0; i < last.length; i++) { - newParent = last[i].parent; - if (!next.includes(newParent)) { - next.push(newParent); - } - } - last = next; - } - return last[0]; -}; diff --git a/1123.lowest-common-ancestor-of-deepest-leaves.js b/1123.lowest-common-ancestor-of-deepest-leaves.js new file mode 100644 index 00000000..70883d5a --- /dev/null +++ b/1123.lowest-common-ancestor-of-deepest-leaves.js @@ -0,0 +1,31 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {TreeNode} + */ +const lcaDeepestLeaves = function(root) { + let maxDepth = 0, lcaNode = null + + function lca(node, depth) { + if(node == null) return depth - 1 + maxDepth = Math.max(depth, maxDepth) + const left = lca(node.left, depth + 1) + const right = lca(node.right, depth + 1) + if(left === maxDepth && right === maxDepth) { + lcaNode = node + } + return Math.max(left, right) + } + + lca(root, 0) + return lcaNode +}; + + diff --git a/1124-longest-well-performing-interval.js b/1124.longest-well-performing-interval.js similarity index 100% rename from 1124-longest-well-performing-interval.js rename to 1124.longest-well-performing-interval.js diff --git a/1125-smallest-sufficient-team.js b/1125-smallest-sufficient-team.js deleted file mode 100644 index 4b890c98..00000000 --- a/1125-smallest-sufficient-team.js +++ /dev/null @@ -1,196 +0,0 @@ -/** - * @param {string[]} req_skills - * @param {string[][]} people - * @return {number[]} - */ -const smallestSufficientTeam = function (req_skills, people) { - const m = req_skills.length, - n = people.length, - limit = 1 << m - const skillIdxMap = {} - for(let i = 0; i < m; i++) { - skillIdxMap[req_skills[i]] = i - } - const dp = Array(limit) - - dp[0] = [] - - for(let i = 0; i < n; i++) { - let skillMask = 0 - for(let j = 0; j < people[i].length; j++) { - skillMask |= (1 << skillIdxMap[people[i][j]]) - } - - for(let j = 0; j < dp.length; j++) { - if(dp[j] == null) continue - const prev = j - const comb = prev | skillMask - - if(dp[comb] == null || dp[comb].length > dp[prev].length + 1) { - - dp[comb] = dp[prev].slice() - dp[comb].push(i) - } - } - } - - return dp[limit - 1] -} - -// another - - -/** - * @param {string[]} req_skills - * @param {string[][]} people - * @return {number[]} - */ -const smallestSufficientTeam = function(req_skills, people) { - const m = req_skills.length - const n = people.length - const skill2Bitmap = req_skills - .map((x, i) => [x, i]) - .reduce((dict, cur) => { - dict[cur[0]] = 1 << cur[1] - return dict - }, {}) - const newPeople = people.map(x => { - return x.reduce((acc, cur) => { - const y = skill2Bitmap[cur] - if (y !== undefined) { - acc |= y - } - return acc - }, 0) - }) - - const all = (1 << m) - 1 - const dp = {} - for (let j = 0; j < n; j++) { - if (newPeople[j] > 0) { - dp[newPeople[j]] = new Set([j]) - } - } - if (dp[all]) { - return Array.from(dp[all]).sort() - } - - for (let k = 0; k < n; k++) { - for (let s in dp) { - for (let j = 0; j < n; j++) { - if (newPeople[j] === 0 || dp[s].has(j)) continue - const newIdx = s | newPeople[j] - if (dp[newIdx] === undefined) { - dp[newIdx] = new Set([...dp[s], j]) - if (newIdx === all) { - return Array.from(dp[all]).sort() - } - } - } - } - } - return [] -} - -// another - -/** - * @param {string[]} req_skills - * @param {string[][]} people - * @return {number[]} - */ -const smallestSufficientTeam = function(req_skills, people) { - let skill_len = req_skills.length - - // 将people转换为id的模式 - let id_people = [] - let hash = {} - for (let i = 0; i < skill_len; i++) { - hash[req_skills[i]] = i - } - for (let i = 0; i < people.length; i++) { - id_people[i] = [] - for (let j = 0; j < people[i].length; j++) { - id_people[i][j] = hash[people[i][j]] - } - } - - // 过滤掉不可能的选取的人员 - let skip = {} - for (let i = 0; i < id_people.length; i++) { - if (skip[i]) continue - let skills = Array(skill_len).fill(0) - for (let j = 0; j < id_people[i].length; j++) { - let curId = id_people[i][j] - skills[curId]++ - } - for (let k = i + 1; k < id_people.length; k++) { - if (skip[k]) continue - let needSkip = true - for (let l = 0; l < id_people[k].length; l++) { - let id = id_people[k][l] - if (skills[id] === 0) { - needSkip = false - break - } - } - if (needSkip) { - skip[k] = true - } - } - } - - // 构造精简后的人员,并且保存对应的index关系 - let slim_people = [] - let idHash = {} - for (let i = 0; i < id_people.length; i++) { - if (skip[i]) continue - idHash[slim_people.length] = i - slim_people.push(id_people[i]) - } - - // 执行回溯 - let res = Infinity - let remain = {} - let ans = null - for (let i = 0; i < slim_people.length; i++) { - remain[i] = false - } - let init_select = Array(skill_len).fill(0) - - backtrack(0, init_select, 0, remain) - - return ans - - function backtrack(id, select, count, remain) { - if (count >= res) return - let done = true - for (let i = 0; i < select.length; i++) { - if (select[i] === 0) { - done = false - } - } - if (done) { - res = count - let _res_ = [] - for (let k in remain) { - if (remain[k]) _res_.push(idHash[k]) - } - ans = _res_ - return - } - for (let k = id; k < slim_people.length; k++) { - let arr = slim_people[k] - for (let i = 0; i < arr.length; i++) { - select[arr[i]]++ - } - remain[k] = true - backtrack(k + 1, select, count + 1, remain) - remain[k] = false - for (let i = 0; i < arr.length; i++) { - select[arr[i]]-- - } - } - } -} - diff --git a/1125.smallest-sufficient-team.js b/1125.smallest-sufficient-team.js new file mode 100644 index 00000000..9655874f --- /dev/null +++ b/1125.smallest-sufficient-team.js @@ -0,0 +1,39 @@ +/** + * @param {string[]} req_skills + * @param {string[][]} people + * @return {number[]} + */ +const smallestSufficientTeam = function (req_skills, people) { + const m = req_skills.length, + n = people.length, + limit = 1 << m + const skillIdxMap = {} + for(let i = 0; i < m; i++) { + skillIdxMap[req_skills[i]] = i + } + const dp = Array(limit) + + dp[0] = [] + + for(let i = 0; i < n; i++) { + let skillMask = 0 + for(let j = 0; j < people[i].length; j++) { + skillMask |= (1 << skillIdxMap[people[i][j]]) + } + + for(let j = 0; j < dp.length; j++) { + if(dp[j] == null) continue + const prev = j + const comb = prev | skillMask + + if(dp[comb] == null || dp[comb].length > dp[prev].length + 1) { + + dp[comb] = dp[prev].slice() + dp[comb].push(i) + } + } + } + + return dp[limit - 1] +} + diff --git a/1128-number-of-equivalent-domino-pairsnumber-of-equivalent-domino-pairs.js b/1128.number-of-equivalent-domino-pairsnumber-of-equivalent-domino-pairs.js similarity index 100% rename from 1128-number-of-equivalent-domino-pairsnumber-of-equivalent-domino-pairs.js rename to 1128.number-of-equivalent-domino-pairsnumber-of-equivalent-domino-pairs.js diff --git a/1129-shortest-path-with-alternating-colors.js b/1129.shortest-path-with-alternating-colors.js similarity index 100% rename from 1129-shortest-path-with-alternating-colors.js rename to 1129.shortest-path-with-alternating-colors.js diff --git a/113-path-sum-ii.js b/113.path-sum-ii.js similarity index 100% rename from 113-path-sum-ii.js rename to 113.path-sum-ii.js diff --git a/1130-minimum-cost-tree-from-leaf-values.js b/1130.minimum-cost-tree-from-leaf-values.js similarity index 100% rename from 1130-minimum-cost-tree-from-leaf-values.js rename to 1130.minimum-cost-tree-from-leaf-values.js diff --git a/1133-largest-unique-number.js b/1133.largest-unique-number.js similarity index 100% rename from 1133-largest-unique-number.js rename to 1133.largest-unique-number.js diff --git a/1134-armstrong-number.js b/1134.armstrong-number.js similarity index 100% rename from 1134-armstrong-number.js rename to 1134.armstrong-number.js diff --git a/1136-parallel-courses.js b/1136-parallel-courses.js deleted file mode 100644 index 6f727b6e..00000000 --- a/1136-parallel-courses.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} relations - * @return {number} - */ -const minimumSemesters = function (n, relations) { - const inDegree = Array(n + 1).fill(0) - const graph = {} - for(const [prev, nxt] of relations) { - if(graph[prev] == null) graph[prev] = [] - graph[prev].push(nxt) - - inDegree[nxt]++ - } - - let q = [] - for(let i = 1; i <= n; i++) { - if(inDegree[i] === 0) q.push(i) - } - -// console.log(inDegree) - let res = 0, cnt = 0 - while(q.length) { - const size = q.length, nxt = [] - - for(let i = 0; i < size; i++) { - const cur = q[i] - for(const e of (graph[cur] || [])) { - inDegree[e]-- - if(inDegree[e] === 0) { - nxt.push(e) - } - } - } - res++ - cnt += size - q = nxt - // console.log(nxt) - } -// console.log(cnt, res) - - return cnt === n ? res : -1 -} - - -// another - -/** - * @param {number} N - * @param {number[][]} relations - * @return {number} - */ -const minimumSemesters = function (N, relations) { - const g = new Map() // key: prerequisite, value: course list. - const inDegree = new Array(N + 1).fill(0) // inDegree[i]: number of prerequisites for i. - for (let r of relations) { - if (!g.has(r[0])) g.set(r[0], []) - g.get(r[0]).push(r[1]) // construct graph. - ++inDegree[r[1]] // count prerequisites for r[1]. - } - const q = [] // save current 0 in-degree vertices. - for (let i = 1; i <= N; ++i) if (inDegree[i] === 0) q.push(i) - let semester = 0 - while (q.length) { - // BFS traverse all currently 0 in degree vertices. - for (let sz = q.length; sz > 0; --sz) { - // sz is the search breadth. - const c = q.shift() - --N - // c's in-degree is currently 0, but it is not a prerequisite of anyone else. - if (!g.has(c)) continue - const tmp = g.get(c) - g.delete(c) - for (let course of tmp) - if (--inDegree[course] === 0) - // decrease the in-degree of course's neighbors. - q.push(course) // add current 0 in-degree vertex into Queue. - } - ++semester // need one more semester. - } - return N === 0 ? semester : -1 -} diff --git a/1136.parallel-courses.js b/1136.parallel-courses.js new file mode 100644 index 00000000..0f0f0d7c --- /dev/null +++ b/1136.parallel-courses.js @@ -0,0 +1,45 @@ +/** + * @param {number} n + * @param {number[][]} relations + * @return {number} + */ +const minimumSemesters = function (n, relations) { + const inDegree = Array(n + 1).fill(0) + const graph = {} + for(const [prev, nxt] of relations) { + if(graph[prev] == null) graph[prev] = [] + graph[prev].push(nxt) + + inDegree[nxt]++ + } + + let q = [] + for(let i = 1; i <= n; i++) { + if(inDegree[i] === 0) q.push(i) + } + +// console.log(inDegree) + let res = 0, cnt = 0 + while(q.length) { + const size = q.length, nxt = [] + + for(let i = 0; i < size; i++) { + const cur = q[i] + for(const e of (graph[cur] || [])) { + inDegree[e]-- + if(inDegree[e] === 0) { + nxt.push(e) + } + } + } + res++ + cnt += size + q = nxt + // console.log(nxt) + } +// console.log(cnt, res) + + return cnt === n ? res : -1 +} + + diff --git a/1137-n-th-tribonacci-number.js b/1137-n-th-tribonacci-number.js deleted file mode 100644 index c47209e5..00000000 --- a/1137-n-th-tribonacci-number.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const hash = {} -const tribonacci = function(n) { - if(n === 0) return 0 - if(n === 2 || n === 1) return 1 - if(hash[n] != null) return hash[n] - let tmp = tribonacci(n - 3) + tribonacci(n - 2) + tribonacci(n - 1) - return hash[n] = tmp -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const tribonacci = function(n) { - if (n < 2) return n - let prev0 = 0 - let prev1 = 1 - let prev2 = 1 - for (let count = 3; count <= n; count++) { - let next = prev2 + prev1 + prev0 - prev0 = prev1 - prev1 = prev2 - prev2 = next - } - return prev2 -} diff --git a/1137.n-th-tribonacci-number.js b/1137.n-th-tribonacci-number.js new file mode 100644 index 00000000..c75dbd04 --- /dev/null +++ b/1137.n-th-tribonacci-number.js @@ -0,0 +1,13 @@ +/** + * @param {number} n + * @return {number} + */ +const hash = {} +const tribonacci = function(n) { + if(n === 0) return 0 + if(n === 2 || n === 1) return 1 + if(hash[n] != null) return hash[n] + let tmp = tribonacci(n - 3) + tribonacci(n - 2) + tribonacci(n - 1) + return hash[n] = tmp +}; + diff --git a/1138-alphabet-board-path.js b/1138.alphabet-board-path.js similarity index 100% rename from 1138-alphabet-board-path.js rename to 1138.alphabet-board-path.js diff --git a/1139-largest-1-bordered-square.js b/1139.largest-1-bordered-square.js similarity index 100% rename from 1139-largest-1-bordered-square.js rename to 1139.largest-1-bordered-square.js diff --git a/114-flatten-binary-tree-to-linked-list.js b/114.flatten-binary-tree-to-linked-list.js similarity index 100% rename from 114-flatten-binary-tree-to-linked-list.js rename to 114.flatten-binary-tree-to-linked-list.js diff --git a/1140-stone-game-ii.js b/1140.stone-game-ii.js similarity index 100% rename from 1140-stone-game-ii.js rename to 1140.stone-game-ii.js diff --git a/1143-longest-common-subsequence.js b/1143-longest-common-subsequence.js deleted file mode 100644 index 9e856a67..00000000 --- a/1143-longest-common-subsequence.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @param {string} text1 - * @param {string} text2 - * @return {number} - */ -const longestCommonSubsequence = function(text1, text2) { - let dp = new Array(text1.length + 1) - for (let i = 0; i < dp.length; i++) - dp[i] = new Array(text2.length + 1).fill(0) - for (let i = 1; i < dp.length; i++) { - for (let j = 1; j < dp[i].length; j++) { - if (text1[i - 1] == text2[j - 1]) dp[i][j] = 1 + dp[i - 1][j - 1] - else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) - } - } - return dp[dp.length - 1].pop() -} - -// another - -/** - * @param {string} text1 - * @param {string} text2 - * @return {number} - */ -const longestCommonSubsequence = function(text1, text2) { - const len1 = text1.length - const len2 = text2.length - if(len1 === 0 || len2 === 0) return 0 - const dp = Array(len2 + 1).fill(0) - for(let i = 1; i <= len1; i++) { - let prev = 0 - for(let j = 1; j <= len2; j++) { - const tmp = dp[j] - if(text1[i - 1] === text2[j - 1]) dp[j] = Math.max(dp[j], prev + 1) - else { - dp[j] = Math.max(dp[j - 1], dp[j]) - } - prev = tmp - } - } - return dp[len2] -}; diff --git a/1143.longest-common-subsequence.js b/1143.longest-common-subsequence.js new file mode 100644 index 00000000..6c58b4e1 --- /dev/null +++ b/1143.longest-common-subsequence.js @@ -0,0 +1,18 @@ +/** + * @param {string} text1 + * @param {string} text2 + * @return {number} + */ +const longestCommonSubsequence = function(text1, text2) { + let dp = new Array(text1.length + 1) + for (let i = 0; i < dp.length; i++) + dp[i] = new Array(text2.length + 1).fill(0) + for (let i = 1; i < dp.length; i++) { + for (let j = 1; j < dp[i].length; j++) { + if (text1[i - 1] == text2[j - 1]) dp[i][j] = 1 + dp[i - 1][j - 1] + else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) + } + } + return dp[dp.length - 1].pop() +} + diff --git a/1145-binary-tree-coloring-game.js b/1145.binary-tree-coloring-game.js similarity index 100% rename from 1145-binary-tree-coloring-game.js rename to 1145.binary-tree-coloring-game.js diff --git a/1146-snapshot-array.js b/1146-snapshot-array.js deleted file mode 100644 index 28e93963..00000000 --- a/1146-snapshot-array.js +++ /dev/null @@ -1,184 +0,0 @@ -/** - * @param {number} length - */ -const SnapshotArray = function(length) { - this.snaps = Array(length) - this.snapId = 0 -}; - -/** - * @param {number} index - * @param {number} val - * @return {void} - */ -SnapshotArray.prototype.set = function(index, val) { - if(this.snaps[index] == null) { - this.snaps[index] = {} - } - this.snaps[index][this.snapId] = val -}; - -/** - * @return {number} - */ -SnapshotArray.prototype.snap = function() { - return this.snapId++ -}; - -/** - * @param {number} index - * @param {number} snap_id - * @return {number} - */ -SnapshotArray.prototype.get = function(index, snap_id) { - let res = 0 - let id = snap_id - while(id >= 0) { - if(this.snaps[index] == null || this.snaps[index][id] == null) id-- - else { - res = this.snaps[index][id] - break - } - } - - return res -}; - -/** - * Your SnapshotArray object will be instantiated and called as such: - * var obj = new SnapshotArray(length) - * obj.set(index,val) - * var param_2 = obj.snap() - * var param_3 = obj.get(index,snap_id) - */ - -// another - -/** - * @param {number[]} nums - * @param {number} target - * @return {number} - */ -const binarySearch = function (nums, target, comparator) { - let low = 0; - let high = nums.length - 1; - while (low <= high) { - let mid = low + ((high - low) >>> 1); - let midValue = nums[mid]; - let cmp = comparator(midValue, target); - if (cmp < 0) low = mid + 1; - else if (cmp > 0) high = mid - 1; - else return mid; - } - return -(low + 1); -}; - -/** - * @param {number} length - */ -const SnapshotArray = function (length) { - this.count = 0; - this.arr = Array.from({ length: length }, () => [[0, 0]]); -}; - -/** - * @param {number} index - * @param {number} val - * @return {void} - */ -SnapshotArray.prototype.set = function (index, val) { - const arr = this.arr, - count = this.count; - if (arr[index][arr[index].length - 1][0] === count) { - arr[index][arr[index].length - 1][1] = val; - } else { - arr[index].push([count, val]); - } -}; - -/** - * @return {number} - */ -SnapshotArray.prototype.snap = function () { - return this.count++; -}; - -/** - * @param {number} index - * @param {number} snap_id - * @return {number} - */ -SnapshotArray.prototype.get = function (index, snap_id) { - let idx = binarySearch(this.arr[index], [snap_id, 0], (a, b) => a[0] - b[0]); - if (idx < 0) idx = -idx - 2; - return this.arr[index][idx][1]; -}; - -/** - * Your SnapshotArray object will be instantiated and called as such: - * var obj = new SnapshotArray(length) - * obj.set(index,val) - * var param_2 = obj.snap() - * var param_3 = obj.get(index,snap_id) - */ - - -// another - -/** - * @param {number} length - */ -const SnapshotArray = function(length) { - this.arr = new Array(length).fill(0); - this.snaps = new Array(length); - this.count = 0; -}; - -/** - * @param {number} index - * @param {number} val - * @return {void} - */ -SnapshotArray.prototype.set = function(index, val) { - if (this.snaps[index] == undefined) { - this.snaps[index] = {}; - } - - this.snaps[index][this.count] = val; -}; - -/** - * @return {number} - */ -SnapshotArray.prototype.snap = function() { - return this.count++; -}; - -/** - * @param {number} index - * @param {number} snap_id - * @return {number} - */ -SnapshotArray.prototype.get = function(index, snap_id) { - if (this.snaps[index] == undefined) return 0; - - let res = 0; - while (snap_id >= 0) { - if (this.snaps[index][snap_id] == undefined) { - snap_id--; - } else { - res = this.snaps[index][snap_id]; - snap_id = -1; - } - } - - return res; -}; - -/** - * Your SnapshotArray object will be instantiated and called as such: - * var obj = new SnapshotArray(length) - * obj.set(index,val) - * var param_2 = obj.snap() - * var param_3 = obj.get(index,snap_id) - */ diff --git a/1146.snapshot-array.js b/1146.snapshot-array.js new file mode 100644 index 00000000..4bcb4508 --- /dev/null +++ b/1146.snapshot-array.js @@ -0,0 +1,54 @@ +/** + * @param {number} length + */ +const SnapshotArray = function(length) { + this.snaps = Array(length) + this.snapId = 0 +}; + +/** + * @param {number} index + * @param {number} val + * @return {void} + */ +SnapshotArray.prototype.set = function(index, val) { + if(this.snaps[index] == null) { + this.snaps[index] = {} + } + this.snaps[index][this.snapId] = val +}; + +/** + * @return {number} + */ +SnapshotArray.prototype.snap = function() { + return this.snapId++ +}; + +/** + * @param {number} index + * @param {number} snap_id + * @return {number} + */ +SnapshotArray.prototype.get = function(index, snap_id) { + let res = 0 + let id = snap_id + while(id >= 0) { + if(this.snaps[index] == null || this.snaps[index][id] == null) id-- + else { + res = this.snaps[index][id] + break + } + } + + return res +}; + +/** + * Your SnapshotArray object will be instantiated and called as such: + * var obj = new SnapshotArray(length) + * obj.set(index,val) + * var param_2 = obj.snap() + * var param_3 = obj.get(index,snap_id) + */ + diff --git a/1147-longest-chunked-palindrome-decomposition.js b/1147-longest-chunked-palindrome-decomposition.js deleted file mode 100644 index dff03658..00000000 --- a/1147-longest-chunked-palindrome-decomposition.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @param {string} text - * @return {number} - */ -const longestDecomposition = function(text) { - let res = 0, - n = text.length - let l = '', - r = '' - for (let i = 0; i < n; ++i) { - l = l + text.charAt(i) - r = text.charAt(n - i - 1) + r - if (l === r) { - ++res - l = '' - r = '' - } - } - return res -} - -// another - -/** - * @param {string} text - * @return {number} - */ -const longestDecomposition = function(text) { - let n = text.length - for (let i = 0; i < Math.floor(n / 2); i++) - if (text.slice(0, i + 1) === text.slice(n - 1 - i, n)) - return 2 + longestDecomposition(text.slice(i + 1, n - 1 - i)) - return n === 0 ? 0 : 1 -} diff --git a/1147.longest-chunked-palindrome-decomposition.js b/1147.longest-chunked-palindrome-decomposition.js new file mode 100644 index 00000000..6ecee0f8 --- /dev/null +++ b/1147.longest-chunked-palindrome-decomposition.js @@ -0,0 +1,21 @@ +/** + * @param {string} text + * @return {number} + */ +const longestDecomposition = function(text) { + let res = 0, + n = text.length + let l = '', + r = '' + for (let i = 0; i < n; ++i) { + l = l + text.charAt(i) + r = text.charAt(n - i - 1) + r + if (l === r) { + ++res + l = '' + r = '' + } + } + return res +} + diff --git a/115-distinct-subsequences.js b/115-distinct-subsequences.js deleted file mode 100644 index 570d633e..00000000 --- a/115-distinct-subsequences.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @param {string} s - * @param {string} t - * @return {number} - */ -const numDistinct = function(s, t) { - const tlen = t.length - const slen = s.length - const mem = Array.from({ length: tlen + 1 }, () => - new Array(slen + 1).fill(0) - ) - for (let j = 0; j <= slen; j++) { - mem[0][j] = 1 - } - for (let i = 0; i < tlen; i++) { - for (let j = 0; j < slen; j++) { - if (t.charAt(i) === s.charAt(j)) { - mem[i + 1][j + 1] = mem[i][j] + mem[i + 1][j] - } else { - mem[i + 1][j + 1] = mem[i + 1][j] - } - } - } - return mem[tlen][slen] -} - - -// another - -/** - * @param {string} s - * @param {string} t - * @return {number} - */ -const numDistinct = function(s, t) { - const m = t.length, - n = s.length - const cur = new Array(m + 1).fill(0) - cur[0] = 1 - for (let j = 1; j <= n; j++) { - let pre = 1 - for (let i = 1; i <= m; i++) { - let temp = cur[i] - cur[i] = cur[i] + (t[i - 1] == s[j - 1] ? pre : 0) - pre = temp - } - } - return cur[m] -} - -// another - -/** - * @param {string} s - * @param {string} t - * @return {number} - */ -const numDistinct = function(s, t) { - const m = t.length, - n = s.length - const dp = new Array(m + 1).fill(0) - dp[0] = 1 - for (let j = 1; j <= n; j++) { - for (let i = m; i > 0; i--) { - dp[i] = dp[i] + (t[i - 1] == s[j - 1] ? dp[i - 1] : 0) - } - } - return dp[m] -} - diff --git a/115.distinct-subsequences.js b/115.distinct-subsequences.js new file mode 100644 index 00000000..e2ae0ef0 --- /dev/null +++ b/115.distinct-subsequences.js @@ -0,0 +1,27 @@ +/** + * @param {string} s + * @param {string} t + * @return {number} + */ +const numDistinct = function(s, t) { + const tlen = t.length + const slen = s.length + const mem = Array.from({ length: tlen + 1 }, () => + new Array(slen + 1).fill(0) + ) + for (let j = 0; j <= slen; j++) { + mem[0][j] = 1 + } + for (let i = 0; i < tlen; i++) { + for (let j = 0; j < slen; j++) { + if (t.charAt(i) === s.charAt(j)) { + mem[i + 1][j + 1] = mem[i][j] + mem[i + 1][j] + } else { + mem[i + 1][j + 1] = mem[i + 1][j] + } + } + } + return mem[tlen][slen] +} + + diff --git a/1150-check-if-a-number-is-majority-element-in-a-sorted-array.js b/1150.check-if-a-number-is-majority-element-in-a-sorted-array.js similarity index 100% rename from 1150-check-if-a-number-is-majority-element-in-a-sorted-array.js rename to 1150.check-if-a-number-is-majority-element-in-a-sorted-array.js diff --git a/1151-minimum-swaps-to-group-all-1s-together.js b/1151.minimum-swaps-to-group-all-1s-together.js similarity index 100% rename from 1151-minimum-swaps-to-group-all-1s-together.js rename to 1151.minimum-swaps-to-group-all-1s-together.js diff --git a/1153-string-transforms-into-another-string.js b/1153.string-transforms-into-another-string.js similarity index 100% rename from 1153-string-transforms-into-another-string.js rename to 1153.string-transforms-into-another-string.js diff --git a/1154-day-of-the-year.js b/1154.day-of-the-year.js similarity index 100% rename from 1154-day-of-the-year.js rename to 1154.day-of-the-year.js diff --git a/1155-number-of-dice-rolls-with-target-sum.js b/1155-number-of-dice-rolls-with-target-sum.js deleted file mode 100644 index fe6259d9..00000000 --- a/1155-number-of-dice-rolls-with-target-sum.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @param {number} d - * @param {number} f - * @param {number} target - * @return {number} - */ -const numRollsToTarget = function(d, f, target) { - const mod = 10 ** 9 + 7 - if (target > d * f || target < d) { - return 0 - } - const dp = new Array(target + 1).fill(0) - for (let i = 1; i < Math.min(f + 1, target + 1); i++) { - dp[i] = 1 - } - for (let i = 2; i < d + 1; i++) { - for (let j = Math.min(target, i * f); j > i - 1; j--) { - dp[j] = 0 - for (let k = Math.max(i - 1, j - f); k < j; k++) { - dp[j] = (dp[j] + dp[k]) % mod - } - } - } - - return dp[target] -} - -// another - -const numRollsToTarget = function(d, f, target) { - const MOD = 10 ** 9 + 7; - const dp = Array.from({ length: d + 1 }, () => new Array(target + 1).fill(0)); - dp[0][0] = 1; - for (let i = 1; i <= d; i++) { - for (let j = 1; j <= target; j++) { - if (j > i * f) { - continue; - } else { - for (let k = 1; k <= f && k <= j; k++) { - dp[i][j] = (dp[i][j] + dp[i - 1][j - k]) % MOD; - } - } - } - } - return dp[d][target]; -}; diff --git a/1155.number-of-dice-rolls-with-target-sum.js b/1155.number-of-dice-rolls-with-target-sum.js new file mode 100644 index 00000000..6309cbfb --- /dev/null +++ b/1155.number-of-dice-rolls-with-target-sum.js @@ -0,0 +1,27 @@ +/** + * @param {number} d + * @param {number} f + * @param {number} target + * @return {number} + */ +const numRollsToTarget = function(d, f, target) { + const mod = 10 ** 9 + 7 + if (target > d * f || target < d) { + return 0 + } + const dp = new Array(target + 1).fill(0) + for (let i = 1; i < Math.min(f + 1, target + 1); i++) { + dp[i] = 1 + } + for (let i = 2; i < d + 1; i++) { + for (let j = Math.min(target, i * f); j > i - 1; j--) { + dp[j] = 0 + for (let k = Math.max(i - 1, j - f); k < j; k++) { + dp[j] = (dp[j] + dp[k]) % mod + } + } + } + + return dp[target] +} + diff --git a/1156-swap-for-longest-repeated-character-substring.js b/1156.swap-for-longest-repeated-character-substring.js similarity index 100% rename from 1156-swap-for-longest-repeated-character-substring.js rename to 1156.swap-for-longest-repeated-character-substring.js diff --git a/1157-online-majority-element-in-subarray.js b/1157-online-majority-element-in-subarray.js deleted file mode 100644 index 54f72984..00000000 --- a/1157-online-majority-element-in-subarray.js +++ /dev/null @@ -1,205 +0,0 @@ -function Bisect() { - return { insort_right, insort_left, bisect_left, bisect_right } - function insort_right(a, x, lo = 0, hi = null) { - lo = bisect_right(a, x, lo, hi) - a.splice(lo, 0, x) - } - function bisect_right(a, x, lo = 0, hi = null) { - if (lo < 0) throw new Error('lo must be non-negative') - if (hi == null) hi = a.length - while (lo < hi) { - let mid = (lo + hi) >> 1 - x < a[mid] ? (hi = mid) : (lo = mid + 1) - } - return lo - } - function insort_left(a, x, lo = 0, hi = null) { - lo = bisect_left(a, x, lo, hi) - a.splice(lo, 0, x) - } - function bisect_left(a, x, lo = 0, hi = null) { - if (lo < 0) throw new Error('lo must be non-negative') - if (hi == null) hi = a.length - while (lo < hi) { - let mid = (lo + hi) >> 1 - a[mid] < x ? (lo = mid + 1) : (hi = mid) - } - return lo - } -} - -function SegmentTreeRQ(m, A, n) { - let bisect = new Bisect() - let h = Math.ceil(Math.log2(n)) - const MAX = 2 * 2 ** h - 1 - let tree = Array(MAX).fill(-1) - let a = [...A] - build(1, 0, n - 1) - return { - query, - } - - function build(vi, tl, tr) { - if (tl == tr) { - tree[vi] = a[tl] - return - } - let mid = getMid(tl, tr) - build(vi * 2, tl, mid) - build(vi * 2 + 1, mid + 1, tr) - if ( - tree[vi * 2] != -1 && - get_occurrence(tree[vi * 2], tl, tr) * 2 > tr - tl + 1 - ) { - tree[vi] = tree[vi * 2] - } else if ( - tree[vi * 2 + 1] != -1 && - get_occurrence(tree[vi * 2 + 1], tl, tr) * 2 > tr - tl + 1 - ) { - tree[vi] = tree[vi * 2 + 1] - } - } - - function query(vi, l, r, tl, tr) { - if (l > tr || r < tl) { - return { - first: -1, - second: -1, - } - } - if (tl <= l && r <= tr) { - if (tree[vi] == -1) - return { - first: -1, - second: -1, - } - let occ = get_occurrence(tree[vi], tl, tr) - if (occ * 2 > tr - tl + 1) { - return { - first: tree[vi], - second: occ, - } - } else { - return { - first: -1, - second: -1, - } - } - } - let mid = getMid(l, r) - let resL = query(vi * 2, l, mid, tl, tr) - if (resL.first > -1) return resL - let resR = query(vi * 2 + 1, mid + 1, r, tl, tr) - if (resR.first > -1) return resR - return { - first: -1, - second: -1, - } - } - - function get_occurrence(num, l, r) { - // only difference - if (!m.has(num)) return 0 - let a = m.get(num) - let lbv = bisect.bisect_left(a, l) //lower_bound - if (lbv == a.length) return 0 - let ubv = bisect.bisect_right(a, r) // upper_bound - return ubv - lbv - } - - function getMid(low, high) { - return low + ((high - low) >> 1) - } -} - -function MajorityChecker(a) { - let m = new Map() - let n = a.length - for (let i = 0; i < n; i++) { - if (!m.has(a[i])) m.set(a[i], []) - m.get(a[i]).push(i) - } - let st = new SegmentTreeRQ(m, a, n) - return { - query, - } - - function query(left, right, threshold) { - let res = st.query(1, 0, n - 1, left, right) - if (res.second >= threshold) { - return res.first - } - return -1 - } -} - -// another - - -/** - * @param {number[]} arr - */ -const MajorityChecker = function(arr) { - const map = new Map() - for (let i = 0; i < arr.length; i++) { - if (!map.has(arr[i])) map.set(arr[i], [i]) - else map.get(arr[i]).push(i) - } - this.pos = map - this.arr = arr -} - -function lbs(arr, val) { - let lo = 0 - let hi = arr.length - 1 - if (arr[0] >= val) return 0 - else if (arr[hi] < val) return Infinity - let mid - while (hi - lo > 1) { - mid = (hi + lo) >> 1 - if (arr[mid] === val) return mid - else if (arr[mid] < val) lo = mid - else if (arr[mid] > val) hi = mid - } - return hi -} - -function rbs(arr, val) { - let lo = 0 - let hi = arr.length - 1 - if (arr[hi] <= val) return hi - else if (arr[lo] > val) return -Infinity - let mid - while (hi - lo > 1) { - mid = (hi + lo) >> 1 - if (arr[mid] === val) return mid - else if (arr[mid] < val) lo = mid - else if (arr[mid] > val) hi = mid - } - return lo -} - -/** - * @param {number} left - * @param {number} right - * @param {number} threshold - * @return {number} - */ -MajorityChecker.prototype.query = function(left, right, threshold) { - const { arr, pos } = this - let c = 20 - while (c--) { - const idx = left + Math.floor(Math.random() * (right - left + 1)) - const sort = pos.get(arr[idx]) - const lidx = lbs(sort, left) - const ridx = rbs(sort, right) - if (ridx - lidx + 1 >= threshold) return arr[idx] - } - return -1 -} - -/** - * Your MajorityChecker object will be instantiated and called as such: - * var obj = new MajorityChecker(arr) - * var param_1 = obj.query(left,right,threshold) - */ diff --git a/1157.online-majority-element-in-subarray.js b/1157.online-majority-element-in-subarray.js new file mode 100644 index 00000000..b16da637 --- /dev/null +++ b/1157.online-majority-element-in-subarray.js @@ -0,0 +1,135 @@ +function Bisect() { + return { insort_right, insort_left, bisect_left, bisect_right } + function insort_right(a, x, lo = 0, hi = null) { + lo = bisect_right(a, x, lo, hi) + a.splice(lo, 0, x) + } + function bisect_right(a, x, lo = 0, hi = null) { + if (lo < 0) throw new Error('lo must be non-negative') + if (hi == null) hi = a.length + while (lo < hi) { + let mid = (lo + hi) >> 1 + x < a[mid] ? (hi = mid) : (lo = mid + 1) + } + return lo + } + function insort_left(a, x, lo = 0, hi = null) { + lo = bisect_left(a, x, lo, hi) + a.splice(lo, 0, x) + } + function bisect_left(a, x, lo = 0, hi = null) { + if (lo < 0) throw new Error('lo must be non-negative') + if (hi == null) hi = a.length + while (lo < hi) { + let mid = (lo + hi) >> 1 + a[mid] < x ? (lo = mid + 1) : (hi = mid) + } + return lo + } +} + +function SegmentTreeRQ(m, A, n) { + let bisect = new Bisect() + let h = Math.ceil(Math.log2(n)) + const MAX = 2 * 2 ** h - 1 + let tree = Array(MAX).fill(-1) + let a = [...A] + build(1, 0, n - 1) + return { + query, + } + + function build(vi, tl, tr) { + if (tl == tr) { + tree[vi] = a[tl] + return + } + let mid = getMid(tl, tr) + build(vi * 2, tl, mid) + build(vi * 2 + 1, mid + 1, tr) + if ( + tree[vi * 2] != -1 && + get_occurrence(tree[vi * 2], tl, tr) * 2 > tr - tl + 1 + ) { + tree[vi] = tree[vi * 2] + } else if ( + tree[vi * 2 + 1] != -1 && + get_occurrence(tree[vi * 2 + 1], tl, tr) * 2 > tr - tl + 1 + ) { + tree[vi] = tree[vi * 2 + 1] + } + } + + function query(vi, l, r, tl, tr) { + if (l > tr || r < tl) { + return { + first: -1, + second: -1, + } + } + if (tl <= l && r <= tr) { + if (tree[vi] == -1) + return { + first: -1, + second: -1, + } + let occ = get_occurrence(tree[vi], tl, tr) + if (occ * 2 > tr - tl + 1) { + return { + first: tree[vi], + second: occ, + } + } else { + return { + first: -1, + second: -1, + } + } + } + let mid = getMid(l, r) + let resL = query(vi * 2, l, mid, tl, tr) + if (resL.first > -1) return resL + let resR = query(vi * 2 + 1, mid + 1, r, tl, tr) + if (resR.first > -1) return resR + return { + first: -1, + second: -1, + } + } + + function get_occurrence(num, l, r) { + // only difference + if (!m.has(num)) return 0 + let a = m.get(num) + let lbv = bisect.bisect_left(a, l) //lower_bound + if (lbv == a.length) return 0 + let ubv = bisect.bisect_right(a, r) // upper_bound + return ubv - lbv + } + + function getMid(low, high) { + return low + ((high - low) >> 1) + } +} + +function MajorityChecker(a) { + let m = new Map() + let n = a.length + for (let i = 0; i < n; i++) { + if (!m.has(a[i])) m.set(a[i], []) + m.get(a[i]).push(i) + } + let st = new SegmentTreeRQ(m, a, n) + return { + query, + } + + function query(left, right, threshold) { + let res = st.query(1, 0, n - 1, left, right) + if (res.second >= threshold) { + return res.first + } + return -1 + } +} + diff --git a/116-populating-next-right-pointers-in-each-node.js b/116-populating-next-right-pointers-in-each-node.js deleted file mode 100644 index 3461fb0c..00000000 --- a/116-populating-next-right-pointers-in-each-node.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * // Definition for a Node. - * function Node(val,left,right,next) { - * this.val = val; - * this.left = left; - * this.right = right; - * this.next = next; - * }; - */ -/** - * @param {Node} root - * @return {Node} - */ -const connect = function(root) { - if (root == null) return null - const cur = [root] - while (cur.length) { - let len = cur.length - for (let i = 0; i < len; i++) { - let el = cur.shift() - if (i === len - 1) el.next = null - else el.next = cur[0] - - if (el.left) cur.push(el.left) - if (el.right) cur.push(el.right) - } - } - return root -} - -// another - -const connect = function(root) { - if (!root) return null - if (root.left && root.right) { - root.left.next = root.right - root.right.next = root.next ? root.next.left : null - } - connect(root.left) - connect(root.right) - return root -} diff --git a/116.populating-next-right-pointers-in-each-node.js b/116.populating-next-right-pointers-in-each-node.js new file mode 100644 index 00000000..dd06721c --- /dev/null +++ b/116.populating-next-right-pointers-in-each-node.js @@ -0,0 +1,30 @@ +/** + * // Definition for a Node. + * function Node(val,left,right,next) { + * this.val = val; + * this.left = left; + * this.right = right; + * this.next = next; + * }; + */ +/** + * @param {Node} root + * @return {Node} + */ +const connect = function(root) { + if (root == null) return null + const cur = [root] + while (cur.length) { + let len = cur.length + for (let i = 0; i < len; i++) { + let el = cur.shift() + if (i === len - 1) el.next = null + else el.next = cur[0] + + if (el.left) cur.push(el.left) + if (el.right) cur.push(el.right) + } + } + return root +} + diff --git a/1160-find-words-that-can-be-formed-by-characters.js b/1160.find-words-that-can-be-formed-by-characters.js similarity index 100% rename from 1160-find-words-that-can-be-formed-by-characters.js rename to 1160.find-words-that-can-be-formed-by-characters.js diff --git a/1161-maximum-level-sum-of-a-binary-tree.js b/1161.maximum-level-sum-of-a-binary-tree.js similarity index 100% rename from 1161-maximum-level-sum-of-a-binary-tree.js rename to 1161.maximum-level-sum-of-a-binary-tree.js diff --git a/1162-as-far-from-land-as-possible.js b/1162.as-far-from-land-as-possible.js similarity index 100% rename from 1162-as-far-from-land-as-possible.js rename to 1162.as-far-from-land-as-possible.js diff --git a/1163-last-substring-in-lexicographical-order.js b/1163.last-substring-in-lexicographical-order.js similarity index 100% rename from 1163-last-substring-in-lexicographical-order.js rename to 1163.last-substring-in-lexicographical-order.js diff --git a/1165-single-row-keyboard.js b/1165.single-row-keyboard.js similarity index 100% rename from 1165-single-row-keyboard.js rename to 1165.single-row-keyboard.js diff --git a/1166-design-file-system.js b/1166-design-file-system.js deleted file mode 100644 index 8378b6d1..00000000 --- a/1166-design-file-system.js +++ /dev/null @@ -1,85 +0,0 @@ - -const FileSystem = function() { - this.m = new Map() - this.m.set('', 1) -}; - -/** - * @param {string} path - * @param {number} value - * @return {boolean} - */ -FileSystem.prototype.createPath = function(path, value) { - if(this.m.has(path)) return false - const p = path.slice(0, path.lastIndexOf('/')) - if(!this.m.has(p)) return false - this.m.set(path, value) - return true -}; - -/** - * @param {string} path - * @return {number} - */ -FileSystem.prototype.get = function(path) { - if(!this.m.has(path)) return -1 - return this.m.get(path) -}; - -/** - * Your FileSystem object will be instantiated and called as such: - * var obj = new FileSystem() - * var param_1 = obj.createPath(path,value) - * var param_2 = obj.get(path) - */ - -// another - -class Node { - constructor(v) { - this.val = v - this.children = new Map() - } -} -const FileSystem = function() { - this.r = new Node(null) -}; - -/** - * @param {string} path - * @param {number} value - * @return {boolean} - */ -FileSystem.prototype.createPath = function(path, value) { - if(path == null || path === '') return - const arr = path.split('/').filter(e => e !== '/' && e !== '') - let cur = this.r - for(let i = 0, len = arr.length; i < len; i++) { - if(i !== len - 1 && !cur.children.has(arr[i])) return false - if(i === len - 1 && cur.children.has(arr[i])) return false - if(i !== len - 1) cur = cur.children.get(arr[i]) - } - cur.children.set(arr[arr.length - 1], new Node(value)) - return true -}; - -/** - * @param {string} path - * @return {number} - */ -FileSystem.prototype.get = function(path) { - const arr = path.split('/').filter(e => e !== '/' && e !== '') - let cur = this.r - for(let i = 0, len = arr.length; i < len; i++) { - if(!cur.children.has(arr[i])) return -1 - cur = cur.children.get(arr[i]) - } - return cur.val -}; - -/** - * Your FileSystem object will be instantiated and called as such: - * var obj = new FileSystem() - * var param_1 = obj.createPath(path,value) - * var param_2 = obj.get(path) - */ diff --git a/1166.design-file-system.js b/1166.design-file-system.js new file mode 100644 index 00000000..c6a013bb --- /dev/null +++ b/1166.design-file-system.js @@ -0,0 +1,35 @@ + +const FileSystem = function() { + this.m = new Map() + this.m.set('', 1) +}; + +/** + * @param {string} path + * @param {number} value + * @return {boolean} + */ +FileSystem.prototype.createPath = function(path, value) { + if(this.m.has(path)) return false + const p = path.slice(0, path.lastIndexOf('/')) + if(!this.m.has(p)) return false + this.m.set(path, value) + return true +}; + +/** + * @param {string} path + * @return {number} + */ +FileSystem.prototype.get = function(path) { + if(!this.m.has(path)) return -1 + return this.m.get(path) +}; + +/** + * Your FileSystem object will be instantiated and called as such: + * var obj = new FileSystem() + * var param_1 = obj.createPath(path,value) + * var param_2 = obj.get(path) + */ + diff --git a/1167-minimum-cost-to-connect-sticks.js b/1167-minimum-cost-to-connect-sticks.js deleted file mode 100644 index 6eeb60c6..00000000 --- a/1167-minimum-cost-to-connect-sticks.js +++ /dev/null @@ -1,213 +0,0 @@ -/** - -You have some sticks with positive integer lengths. - -You can connect any two sticks of lengths X and Y into -one stick by paying a cost of X + Y. You perform this action until there is one stick remaining. - -Return the minimum cost of connecting all the given sticks into one stick in this way. - -Example 1: - -Input: sticks = [2,4,3] -Output: 14 -Example 2: - -Input: sticks = [1,8,3,5] -Output: 30 - -Constraints: - -1 <= sticks.length <= 10^4 -1 <= sticks[i] <= 10^4 - -*/ - -/** - * @param {number[]} sticks - * @return {number} - */ -const connectSticks = function(sticks) { - if (sticks.length < 1) return 0 - let size = sticks.length - 1 - let i = Math.floor(sticks.length / 2) - for (; i >= 0; i--) { - heapify(sticks, i, size) - } - let cost = 0 - while (size >= 1) { - const temp = sticks[0] - sticks[0] = sticks[size--] - heapify(sticks, 0, size) - sticks[0] = sticks[0] + temp - cost += sticks[0] - heapify(sticks, 0, size) - } - return cost -} -const heapify = (arr, index, size) => { - let smallest = index - let l = index * 2 + 1 - let r = index * 2 + 2 - if (l <= size && arr[l] < arr[smallest]) { - smallest = l - } - if (r <= size && arr[r] < arr[smallest]) { - smallest = r - } - if (smallest != index) { - swap(arr, index, smallest) - heapify(arr, smallest, size) - } -} -const swap = (arr, i, j) => { - const temp = arr[i] - arr[i] = arr[j] - arr[j] = temp -} - -// another - -/** - * @param {number[]} sticks - * @return {number} - */ -const connectSticks = function(sticks) { - if (sticks.length === 1) return 0 - sticks.sort((a, b) => a - b) - let sum = [], - result = 0 - while (sticks.length || sum.length > 1) { - let cur = 0 - for (let i = 0; i < 2; i++) { - if (sticks[0] && (sum[0] === undefined || sticks[0] < sum[0])) { - cur += sticks[0] - sticks.shift() - } else { - cur += sum[0] - sum.shift() - } - } - sum.push(cur) - result += cur - } - return result -} - -// another - -/** - * @param {number[]} sticks - * @return {number} - */ -const connectSticks = function(sticks) { - sticks.sort((a, b) => a - b) - const sums = [] - let result = 0 - if (sticks.length < 2) return result - const getMin = () => { - const stick = sticks.length ? sticks[0] : Infinity - const sum = sums.length ? sums[0] : Infinity - if (sum < stick) { - return sums.shift() - } else { - return sticks.shift() - } - } - while (sticks.length || sums.length > 1) { - const tmp1 = getMin() - const tmp2 = getMin() - const curr = tmp1 + tmp2 - result += curr - sums.push(curr) - } - return result -} - -// another - -/** - * @param {number[]} sticks - * @return {number} - */ -const connectSticks = function(sticks) { - const pq = new PriorityQueue((a, b) => a < b) - for(let e of sticks) pq.push(e) - let res = 0 - while(pq.size() > 1) { - const e1 = pq.pop() - const e2 = pq.pop() - pq.push(e1 + e2) - res += e1 + e2 - } - - return res -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/1167.minimum-cost-to-connect-sticks.js b/1167.minimum-cost-to-connect-sticks.js new file mode 100644 index 00000000..42620f17 --- /dev/null +++ b/1167.minimum-cost-to-connect-sticks.js @@ -0,0 +1,68 @@ +/** + +You have some sticks with positive integer lengths. + +You can connect any two sticks of lengths X and Y into +one stick by paying a cost of X + Y. You perform this action until there is one stick remaining. + +Return the minimum cost of connecting all the given sticks into one stick in this way. + +Example 1: + +Input: sticks = [2,4,3] +Output: 14 +Example 2: + +Input: sticks = [1,8,3,5] +Output: 30 + +Constraints: + +1 <= sticks.length <= 10^4 +1 <= sticks[i] <= 10^4 + +*/ + +/** + * @param {number[]} sticks + * @return {number} + */ +const connectSticks = function(sticks) { + if (sticks.length < 1) return 0 + let size = sticks.length - 1 + let i = Math.floor(sticks.length / 2) + for (; i >= 0; i--) { + heapify(sticks, i, size) + } + let cost = 0 + while (size >= 1) { + const temp = sticks[0] + sticks[0] = sticks[size--] + heapify(sticks, 0, size) + sticks[0] = sticks[0] + temp + cost += sticks[0] + heapify(sticks, 0, size) + } + return cost +} +const heapify = (arr, index, size) => { + let smallest = index + let l = index * 2 + 1 + let r = index * 2 + 2 + if (l <= size && arr[l] < arr[smallest]) { + smallest = l + } + if (r <= size && arr[r] < arr[smallest]) { + smallest = r + } + if (smallest != index) { + swap(arr, index, smallest) + heapify(arr, smallest, size) + } +} +const swap = (arr, i, j) => { + const temp = arr[i] + arr[i] = arr[j] + arr[j] = temp +} + diff --git a/1168-optimize-water-distribution-in-a-village.js b/1168.optimize-water-distribution-in-a-village.js similarity index 100% rename from 1168-optimize-water-distribution-in-a-village.js rename to 1168.optimize-water-distribution-in-a-village.js diff --git a/117-populating-next-right-pointers-in-each-node-ii.js b/117.populating-next-right-pointers-in-each-node-ii.js similarity index 100% rename from 117-populating-next-right-pointers-in-each-node-ii.js rename to 117.populating-next-right-pointers-in-each-node-ii.js diff --git a/1170-compare-strings-by-frequency-of-the-smallest-character.js b/1170.compare-strings-by-frequency-of-the-smallest-character.js similarity index 100% rename from 1170-compare-strings-by-frequency-of-the-smallest-character.js rename to 1170.compare-strings-by-frequency-of-the-smallest-character.js diff --git a/1171-remove-zero-sum-consecutive-nodes-from-linked-list.js b/1171.remove-zero-sum-consecutive-nodes-from-linked-list.js similarity index 100% rename from 1171-remove-zero-sum-consecutive-nodes-from-linked-list.js rename to 1171.remove-zero-sum-consecutive-nodes-from-linked-list.js diff --git a/1172-dinner-plate-stacks.js b/1172-dinner-plate-stacks.js deleted file mode 100644 index 72f8a9bd..00000000 --- a/1172-dinner-plate-stacks.js +++ /dev/null @@ -1,214 +0,0 @@ -/** - * @param {number} capacity - */ -const DinnerPlates = function (capacity) { - this.capacity = capacity - this.stacks = [] - this.pq = new PriorityQueue() -} - -/** - * @param {number} val - * @return {void} - */ -DinnerPlates.prototype.push = function (val) { - if (this.pq.isEmpty()) { - if ( - this.stacks.length > 0 && - this.stacks[this.stacks.length - 1].length < this.capacity - ) { - this.stacks[this.stacks.length - 1].push(val) - } else { - this.stacks.push([]) - this.stacks[this.stacks.length - 1].push(val) - } - } else { - const num = this.pq.pop() - this.stacks[num].push(val) - } -} - -/** - * @return {number} - */ -DinnerPlates.prototype.pop = function () { - while ( - this.stacks.length > 0 && - this.stacks[this.stacks.length - 1].length === 0 - ) { - const len = this.stacks.length - 1 - while (!this.pq.isEmpty() && this.pq.peek() >= len) { - this.pq.pop() - } - this.stacks.pop() - } - if (this.stacks.length === 0) { - return -1 - } else { - return this.stacks[this.stacks.length - 1].pop() - } -} - -/** - * @param {number} index - * @return {number} - */ -DinnerPlates.prototype.popAtStack = function (index) { - const st = this.stacks[index] - - if (st && st.length > 0) { - this.pq.push(index) - return st.pop() - } - - return -1 -} - -/** - * Your DinnerPlates object will be instantiated and called as such: - * var obj = new DinnerPlates(capacity) - * obj.push(val) - * var param_2 = obj.pop() - * var param_3 = obj.popAtStack(index) - */ -class PriorityQueue { - constructor(len, compare) { - this.compare = (a, b) => { - return a < b - } - this.last = 0 - this.arr = [] - } - push(val) { - this.last++ - this.arr[this.last] = val - this.up(this.last) - } - pop() { - if (this.isEmpty()) { - return null - } - const res = this.arr[1] - this.swap(1, this.last) - this.last-- - this.down(1) - return res - } - up(lo) { - while (lo > 1) { - const currEl = this.arr[lo] - const parent = Math.floor(lo / 2) - const parentEl = this.arr[parent] - if (this.compare(currEl, parentEl)) { - this.swap(lo, parent) - } else { - break - } - lo = parent - } - } - down(hi) { - while (hi * 2 <= this.last) { - const currEl = this.arr[hi] - let nextEl = this.arr[hi * 2] - let nextIndex = hi * 2 - if ( - hi * 2 + 1 <= this.last && - this.compare(this.arr[hi * 2 + 1], nextEl) - ) { - nextIndex = hi * 2 + 1 - nextEl = this.arr[nextIndex] - } - if (this.compare(nextEl, currEl)) { - this.swap(hi, nextIndex) - } else { - break - } - hi = nextIndex - } - } - swap(i, j) { - const temp = this.arr[i] - this.arr[i] = this.arr[j] - this.arr[j] = temp - } - peek() { - if (this.isEmpty()) { - return null - } - return this.arr[1] - } - isEmpty() { - return this.last < 1 - } -} - -// another - -/** - * @param {number} capacity - */ -const DinnerPlates = function (capacity) { - this.pushIndex = 0 - this.popIndex = 0 - this.capacity = capacity - this.stacks = [[]] -} - -/** - * @param {number} val - * @return {void} - */ -DinnerPlates.prototype.push = function (val) { - while ( - this.pushIndex < this.stacks.length && - this.stacks[this.pushIndex].length === this.capacity - ) { - this.pushIndex++ - } - if (this.stacks.length === this.pushIndex) { - this.stacks[this.pushIndex] = [val] - } else { - this.stacks[this.pushIndex].push(val) - } - if (this.popIndex < this.pushIndex) { - this.popIndex = this.pushIndex - } -} - -/** - * @return {number} - */ -DinnerPlates.prototype.pop = function () { - while (this.stacks[this.popIndex].length === 0) { - if (this.popIndex > 0) { - this.popIndex-- - } else { - return -1 - } - } - const valueAtIndex = this.stacks[this.popIndex].pop() - if (this.pushIndex > this.popIndex) { - this.pushIndex = this.popIndex - } - return valueAtIndex -} - -/** - * @param {number} index - * @return {number} - */ -DinnerPlates.prototype.popAtStack = function (index) { - if (index >= this.stacks.length) return -1 - if (index < this.pushIndex) this.pushIndex = index - return this.stacks[index].length > 0 ? this.stacks[index].pop() : -1 -} - -/** - * Your DinnerPlates object will be instantiated and called as such: - * var obj = new DinnerPlates(capacity) - * obj.push(val) - * var param_2 = obj.pop() - * var param_3 = obj.popAtStack(index) - */ - diff --git a/1172.dinner-plate-stacks.js b/1172.dinner-plate-stacks.js new file mode 100644 index 00000000..48a49e14 --- /dev/null +++ b/1172.dinner-plate-stacks.js @@ -0,0 +1,145 @@ +/** + * @param {number} capacity + */ +const DinnerPlates = function (capacity) { + this.capacity = capacity + this.stacks = [] + this.pq = new PriorityQueue() +} + +/** + * @param {number} val + * @return {void} + */ +DinnerPlates.prototype.push = function (val) { + if (this.pq.isEmpty()) { + if ( + this.stacks.length > 0 && + this.stacks[this.stacks.length - 1].length < this.capacity + ) { + this.stacks[this.stacks.length - 1].push(val) + } else { + this.stacks.push([]) + this.stacks[this.stacks.length - 1].push(val) + } + } else { + const num = this.pq.pop() + this.stacks[num].push(val) + } +} + +/** + * @return {number} + */ +DinnerPlates.prototype.pop = function () { + while ( + this.stacks.length > 0 && + this.stacks[this.stacks.length - 1].length === 0 + ) { + const len = this.stacks.length - 1 + while (!this.pq.isEmpty() && this.pq.peek() >= len) { + this.pq.pop() + } + this.stacks.pop() + } + if (this.stacks.length === 0) { + return -1 + } else { + return this.stacks[this.stacks.length - 1].pop() + } +} + +/** + * @param {number} index + * @return {number} + */ +DinnerPlates.prototype.popAtStack = function (index) { + const st = this.stacks[index] + + if (st && st.length > 0) { + this.pq.push(index) + return st.pop() + } + + return -1 +} + +/** + * Your DinnerPlates object will be instantiated and called as such: + * var obj = new DinnerPlates(capacity) + * obj.push(val) + * var param_2 = obj.pop() + * var param_3 = obj.popAtStack(index) + */ +class PriorityQueue { + constructor(len, compare) { + this.compare = (a, b) => { + return a < b + } + this.last = 0 + this.arr = [] + } + push(val) { + this.last++ + this.arr[this.last] = val + this.up(this.last) + } + pop() { + if (this.isEmpty()) { + return null + } + const res = this.arr[1] + this.swap(1, this.last) + this.last-- + this.down(1) + return res + } + up(lo) { + while (lo > 1) { + const currEl = this.arr[lo] + const parent = Math.floor(lo / 2) + const parentEl = this.arr[parent] + if (this.compare(currEl, parentEl)) { + this.swap(lo, parent) + } else { + break + } + lo = parent + } + } + down(hi) { + while (hi * 2 <= this.last) { + const currEl = this.arr[hi] + let nextEl = this.arr[hi * 2] + let nextIndex = hi * 2 + if ( + hi * 2 + 1 <= this.last && + this.compare(this.arr[hi * 2 + 1], nextEl) + ) { + nextIndex = hi * 2 + 1 + nextEl = this.arr[nextIndex] + } + if (this.compare(nextEl, currEl)) { + this.swap(hi, nextIndex) + } else { + break + } + hi = nextIndex + } + } + swap(i, j) { + const temp = this.arr[i] + this.arr[i] = this.arr[j] + this.arr[j] = temp + } + peek() { + if (this.isEmpty()) { + return null + } + return this.arr[1] + } + isEmpty() { + return this.last < 1 + } +} + diff --git a/1175-prime-arrangements.js b/1175.prime-arrangements.js similarity index 100% rename from 1175-prime-arrangements.js rename to 1175.prime-arrangements.js diff --git a/1176-diet-plan-performance.js b/1176-diet-plan-performance.js deleted file mode 100644 index 4930160b..00000000 --- a/1176-diet-plan-performance.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @param {number[]} calories - * @param {number} k - * @param {number} lower - * @param {number} upper - * @return {number} - */ -var dietPlanPerformance = function(calories, k, lower, upper) { - let res = 0 - for(let i = 0, n = calories.length, tmp = 0; i < n; i++) { - tmp += calories[i] - if(i >= k - 1) { - if(i >= k) { - tmp -= calories[i - k] - } - if(tmp < lower) res-- - else if(tmp > upper) res++ - } - - } - return res -}; - -// another - -/** - * @param {number[]} calories - * @param {number} k - * @param {number} lower - * @param {number} upper - * @return {number} - */ -var dietPlanPerformance = function(calories, k, lower, upper) { - let res = 0 - for(let i = 0, n = calories.length; i < n - k + 1; i++) { - let tmp = 0 - for(let j = 0; j < k && i + j < n; j++) { - tmp += calories[i + j] - } - if(tmp < lower) res-- - else if(tmp > upper) res++ - } - return res -}; diff --git a/1176.diet-plan-performance.js b/1176.diet-plan-performance.js new file mode 100644 index 00000000..de23df41 --- /dev/null +++ b/1176.diet-plan-performance.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} calories + * @param {number} k + * @param {number} lower + * @param {number} upper + * @return {number} + */ +var dietPlanPerformance = function(calories, k, lower, upper) { + let res = 0 + for(let i = 0, n = calories.length, tmp = 0; i < n; i++) { + tmp += calories[i] + if(i >= k - 1) { + if(i >= k) { + tmp -= calories[i - k] + } + if(tmp < lower) res-- + else if(tmp > upper) res++ + } + + } + return res +}; + diff --git a/1177-can-make-palindrome-from-substring.js b/1177.can-make-palindrome-from-substring.js similarity index 100% rename from 1177-can-make-palindrome-from-substring.js rename to 1177.can-make-palindrome-from-substring.js diff --git a/1178-number-of-valid-words-for-each-puzzle.js b/1178.number-of-valid-words-for-each-puzzle.js similarity index 100% rename from 1178-number-of-valid-words-for-each-puzzle.js rename to 1178.number-of-valid-words-for-each-puzzle.js diff --git a/118-pascal's-triangle.js b/118-pascal's-triangle.js deleted file mode 100755 index 73fcb739..00000000 --- a/118-pascal's-triangle.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @param {number} numRows - * @return {number[][]} - */ -const generate = function(numRows) { - // row 0 => [1] length 0 - // row 1 => [1, 1] length 1 - // row 2 => [1, 2, 1] length 2 - // row 3 => [1, 3, 3, 1] length 3 - - // current[i] = prev[i - 1] + prev[i] - - const res = []; - for (let row = 0; row < numRows; row += 1) { - if (row === 0) { - res.push([1]); - continue; - } - - if (row === 1) { - res.push([1, 1]); - continue; - } - - const newRow = []; - const maxIdx = row; - for (let i = 0; i <= maxIdx; i += 1) { - if (i === 0 || i === maxIdx) { - newRow.push(1); - } else { - newRow.push(res[row - 1][i - 1] + res[row - 1][i]); - } - } - res.push(newRow); - } - - return res; -}; diff --git a/118.pascal's-triangle.js b/118.pascal's-triangle.js new file mode 100644 index 00000000..4709e64f --- /dev/null +++ b/118.pascal's-triangle.js @@ -0,0 +1,38 @@ +/** + * @param {number} numRows + * @return {number[][]} + */ +const generate = function(numRows) { + // row 0 => [1] length 0 + // row 1 => [1, 1] length 1 + // row 2 => [1, 2, 1] length 2 + // row 3 => [1, 3, 3, 1] length 3 + + // current[i] = prev[i - 1] + prev[i] + + const res = []; + for (let row = 0; row < numRows; row += 1) { + if (row === 0) { + res.push([1]); + continue; + } + + if (row === 1) { + res.push([1, 1]); + continue; + } + + const newRow = []; + const maxIdx = row; + for (let i = 0; i <= maxIdx; i += 1) { + if (i === 0 || i === maxIdx) { + newRow.push(1); + } else { + newRow.push(res[row - 1][i - 1] + res[row - 1][i]); + } + } + res.push(newRow); + } + + return res; +}; diff --git a/1180-count-substrings-with-only-one-distinct-letter.js b/1180.count-substrings-with-only-one-distinct-letter.js similarity index 100% rename from 1180-count-substrings-with-only-one-distinct-letter.js rename to 1180.count-substrings-with-only-one-distinct-letter.js diff --git a/1181-before-and-after-puzzle.js b/1181.before-and-after-puzzle.js similarity index 100% rename from 1181-before-and-after-puzzle.js rename to 1181.before-and-after-puzzle.js diff --git a/1183-maximum-number-of-ones.js b/1183.maximum-number-of-ones.js similarity index 100% rename from 1183-maximum-number-of-ones.js rename to 1183.maximum-number-of-ones.js diff --git a/1184-distance-between-bus-stops.js b/1184.distance-between-bus-stops.js similarity index 100% rename from 1184-distance-between-bus-stops.js rename to 1184.distance-between-bus-stops.js diff --git a/1185-day-of-the-week.js b/1185.day-of-the-week.js similarity index 100% rename from 1185-day-of-the-week.js rename to 1185.day-of-the-week.js diff --git a/1186-maximum-subarray-sum-with-one-deletion.js b/1186-maximum-subarray-sum-with-one-deletion.js deleted file mode 100644 index 6938f589..00000000 --- a/1186-maximum-subarray-sum-with-one-deletion.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {number[]} arr - * @return {number} - */ -const maximumSum = function (arr) { - const n = arr.length - let oneDel = 0, noDel = arr[0], res = arr[0] - - for(let i = 1; i < n; i++) { - oneDel = Math.max(noDel, oneDel + arr[i]) - noDel = Math.max(arr[i], noDel + arr[i]) - res = Math.max(res, oneDel, noDel) - } - - return res -} - -// another - -/** - * @param {number[]} arr - * @return {number} - */ -const maximumSum = function (arr) { - const n = arr.length - let max = arr[0] - const maxEndAt = Array(n), maxStartAt = Array(n) - maxEndAt[0] = arr[0] - for(let i = 1; i < n; i++) { - maxEndAt[i] = Math.max(arr[i], maxEndAt[i - 1] + arr[i]) - max = Math.max(max, maxEndAt[i]) - } - maxStartAt[n - 1] = arr[n - 1] - for(let i = n - 2; i >= 0; i--) { - maxStartAt[i] = Math.max(arr[i], maxStartAt[i + 1] + arr[i]) - } - let res = Math.max(maxStartAt[0], maxEndAt[n - 1]) - for(let i = 1; i < n - 1; i++) { - res = Math.max(max, res, maxEndAt[i - 1] + maxStartAt[i + 1]) - } - return res -} diff --git a/1186.maximum-subarray-sum-with-one-deletion.js b/1186.maximum-subarray-sum-with-one-deletion.js new file mode 100644 index 00000000..ee9fa2fb --- /dev/null +++ b/1186.maximum-subarray-sum-with-one-deletion.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} arr + * @return {number} + */ +const maximumSum = function (arr) { + const n = arr.length + let oneDel = 0, noDel = arr[0], res = arr[0] + + for(let i = 1; i < n; i++) { + oneDel = Math.max(noDel, oneDel + arr[i]) + noDel = Math.max(arr[i], noDel + arr[i]) + res = Math.max(res, oneDel, noDel) + } + + return res +} + diff --git a/1187-make-array-strictly-increasing.js b/1187.make-array-strictly-increasing.js similarity index 100% rename from 1187-make-array-strictly-increasing.js rename to 1187.make-array-strictly-increasing.js diff --git a/1189-maximum-number-of-balloons.js b/1189.maximum-number-of-balloons.js similarity index 100% rename from 1189-maximum-number-of-balloons.js rename to 1189.maximum-number-of-balloons.js diff --git a/119-pascal's-triangle-II.js b/119-pascal's-triangle-II.js deleted file mode 100755 index 1f39e402..00000000 --- a/119-pascal's-triangle-II.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @param {number} rowIndex - * @return {number[]} - */ -const getRow = function(rowIndex) { - if (!rowIndex) return [1]; - if (rowIndex === 1) return [1, 1]; - const res = [1, 1]; - for (let i = 2; i <= rowIndex; i++) { - res[i] = 1; - for (let j = i - 1; j >= 1; j--) { - res[j] = res[j] + res[j - 1]; - } - } - return res; -}; diff --git a/119.pascal's-triangle-II.js b/119.pascal's-triangle-II.js new file mode 100644 index 00000000..f32c758c --- /dev/null +++ b/119.pascal's-triangle-II.js @@ -0,0 +1,16 @@ +/** + * @param {number} rowIndex + * @return {number[]} + */ +const getRow = function(rowIndex) { + if (!rowIndex) return [1]; + if (rowIndex === 1) return [1, 1]; + const res = [1, 1]; + for (let i = 2; i <= rowIndex; i++) { + res[i] = 1; + for (let j = i - 1; j >= 1; j--) { + res[j] = res[j] + res[j - 1]; + } + } + return res; +}; diff --git a/1190-reverse-substrings-between-each-pair-of-parentheses.js b/1190-reverse-substrings-between-each-pair-of-parentheses.js deleted file mode 100644 index cdfe4768..00000000 --- a/1190-reverse-substrings-between-each-pair-of-parentheses.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ -const reverseParentheses = function(s) { - const res = [''] - let control = 0 - let order = 1 - for (let i = 0; i < s.length; i++) { - if (s[i] === '(') { - control++ - order = order ? 0 : 1 - res.push('') - } else if (s[i] === ')') { - if (order) res[control - 1] = res.pop() + res[control - 1] - else res[control - 1] = res[control - 1] + res.pop() - order = order ? 0 : 1 - control-- - } else { - if (order) res[control] = res[control] + s[i] - else res[control] = s[i] + res[control] - } - } - return res[0] -} - -// another - -/** - * @param {string} s - * @return {string} - */ -const reverseParentheses = function(s) { - const n = s.length - const stack = [] - const pair = [] - for(let i = 0; i < n; i++) { - if(s[i] === '(') stack.push(i) - else if(s[i] === ')') { - const tmp = stack.pop() - pair[i] = tmp - pair[tmp] = i - } - } - let res = '' - for(let i = 0, d = 1; i < n; i += d) { - if(s[i] === '(' || s[i] ===')') { - i = pair[i] - d = -d - } else { - res += s[i] - } - } - return res -} diff --git a/1190.reverse-substrings-between-each-pair-of-parentheses.js b/1190.reverse-substrings-between-each-pair-of-parentheses.js new file mode 100644 index 00000000..71af4643 --- /dev/null +++ b/1190.reverse-substrings-between-each-pair-of-parentheses.js @@ -0,0 +1,26 @@ +/** + * @param {string} s + * @return {string} + */ +const reverseParentheses = function(s) { + const res = [''] + let control = 0 + let order = 1 + for (let i = 0; i < s.length; i++) { + if (s[i] === '(') { + control++ + order = order ? 0 : 1 + res.push('') + } else if (s[i] === ')') { + if (order) res[control - 1] = res.pop() + res[control - 1] + else res[control - 1] = res[control - 1] + res.pop() + order = order ? 0 : 1 + control-- + } else { + if (order) res[control] = res[control] + s[i] + else res[control] = s[i] + res[control] + } + } + return res[0] +} + diff --git a/1191-k-concatenation-maximum-sum.js b/1191.k-concatenation-maximum-sum.js similarity index 100% rename from 1191-k-concatenation-maximum-sum.js rename to 1191.k-concatenation-maximum-sum.js diff --git a/1192-critical-connections-in-a-network.js b/1192.critical-connections-in-a-network.js similarity index 100% rename from 1192-critical-connections-in-a-network.js rename to 1192.critical-connections-in-a-network.js diff --git a/1199-minimum-time-to-build-blocks.js b/1199.minimum-time-to-build-blocks.js similarity index 100% rename from 1199-minimum-time-to-build-blocks.js rename to 1199.minimum-time-to-build-blocks.js diff --git a/12-integer-to-roman.js b/12-integer-to-roman.js deleted file mode 100755 index 1f096b9c..00000000 --- a/12-integer-to-roman.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @param {number} num - * @return {string} - */ -const map = { - "1000": "M", - "900": "CM", - "500": "D", - "400": "CD", - "100": "C", - "90": "XC", - "50": "L", - "40": "XL", - "10": "X", - "9": "IX", - "5": "V", - "4": "IV", - "1": "I" -}; -const intToRoman = function(number) { - const l = fkey(map, number); - if (number == +l) { - return map[number]; - } - return map[l] + intToRoman(number - +l); -}; - -function fkey(m, num) { - const keys = Object.keys(m); - const sArr = keys.filter(el => +el <= num); - return +Math.max.apply(Math, sArr); -} diff --git a/12.integer-to-roman.js b/12.integer-to-roman.js new file mode 100644 index 00000000..2404dd6a --- /dev/null +++ b/12.integer-to-roman.js @@ -0,0 +1,32 @@ +/** + * @param {number} num + * @return {string} + */ +const map = { + "1000": "M", + "900": "CM", + "500": "D", + "400": "CD", + "100": "C", + "90": "XC", + "50": "L", + "40": "XL", + "10": "X", + "9": "IX", + "5": "V", + "4": "IV", + "1": "I" +}; +const intToRoman = function(number) { + const l = fkey(map, number); + if (number == +l) { + return map[number]; + } + return map[l] + intToRoman(number - +l); +}; + +function fkey(m, num) { + const keys = Object.keys(m); + const sArr = keys.filter(el => +el <= num); + return +Math.max.apply(Math, sArr); +} diff --git a/120-triangle.js b/120-triangle.js deleted file mode 100644 index 6f809c2a..00000000 --- a/120-triangle.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {number[][]} triangle - * @return {number} - */ -const minimumTotal = function(triangle) { - const n = triangle.length; - for (let i = n - 2; i >= 0; i--) { - for (let j = 0; j < n; j++) { - let self = triangle[i][j]; //获取第(i+1)行(j+1)个数字 - let res = Math.min( - triangle[i + 1][j] + self, - triangle[i + 1][j + 1] + self - ); //得到这一行与下一行相邻数的和的最小值 - triangle[i][j] = res; //更新第(i+1)行第(j+1)个数字 - } - } - - return triangle[0][0]; -}; - -// another - -/** - * @param {number[][]} triangle - * @return {number} - */ -const minimumTotal = function(triangle) { - const m = triangle.length, n = triangle.at(-1).length - const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(Infinity)) - dp[1][1] = triangle[0][0] - for(let i = 2; i <= m; i++) { - for(let j = 1; j <= triangle[i - 1].length; j++) { - if(j === 1) dp[i][j] = dp[i - 1][j] + triangle[i - 1][j - 1] - else dp[i][j] = Math.min(dp[i - 1][j], dp[i - 1][j - 1]) + triangle[i - 1][j - 1] - } - } - let res = Infinity - for (let j = 0; j <= n; j++) { - res = Math.min(res, dp[m][j]) - } - return res -}; diff --git a/120.triangle.js b/120.triangle.js new file mode 100644 index 00000000..c50bb12a --- /dev/null +++ b/120.triangle.js @@ -0,0 +1,20 @@ +/** + * @param {number[][]} triangle + * @return {number} + */ +const minimumTotal = function(triangle) { + const n = triangle.length; + for (let i = n - 2; i >= 0; i--) { + for (let j = 0; j < n; j++) { + let self = triangle[i][j]; //获取第(i+1)行(j+1)个数字 + let res = Math.min( + triangle[i + 1][j] + self, + triangle[i + 1][j + 1] + self + ); //得到这一行与下一行相邻数的和的最小值 + triangle[i][j] = res; //更新第(i+1)行第(j+1)个数字 + } + } + + return triangle[0][0]; +}; + diff --git a/1200-minimum-absolute-difference.js b/1200.minimum-absolute-difference.js similarity index 100% rename from 1200-minimum-absolute-difference.js rename to 1200.minimum-absolute-difference.js diff --git a/1201-ugly-number-iii.js b/1201.ugly-number-iii.js similarity index 100% rename from 1201-ugly-number-iii.js rename to 1201.ugly-number-iii.js diff --git a/1202-smallest-string-with-swaps.js b/1202.smallest-string-with-swaps.js similarity index 100% rename from 1202-smallest-string-with-swaps.js rename to 1202.smallest-string-with-swaps.js diff --git a/1203-sort-items-by-groups-respecting-dependencies.js b/1203-sort-items-by-groups-respecting-dependencies.js deleted file mode 100644 index 0894cd98..00000000 --- a/1203-sort-items-by-groups-respecting-dependencies.js +++ /dev/null @@ -1,143 +0,0 @@ -/** - * @param {number} n - * @param {number} m - * @param {number[]} group - * @param {number[][]} beforeItems - * @return {number[]} - */ -const sortItems = function (n, m, group, beforeItems) { - const graph = Array.from({ length: m + n }, () => []) - const indegree = Array(n + m).fill(0) - for (let i = 0; i < group.length; i++) { - if (group[i] == -1) continue - graph[n + group[i]].push(i) - indegree[i]++ - } - for (let i = 0; i < beforeItems.length; i++) { - for (const e of beforeItems[i]) { - const a = group[e] === -1 ? e : n + group[e] - const b = group[i] === -1 ? i : n + group[i] - if (a === b) { - // same group, ingroup order - graph[e].push(i) - indegree[i]++ - } else { - // outgoup order - graph[a].push(b) - indegree[b]++ - } - } - } - const res = [] - for (let i = 0; i < n + m; i++) { - if (indegree[i] === 0) dfs(res, graph, indegree, n, i) - } - return res.length === n ? res : [] - - function dfs(ans, graph, indegree, n, cur) { - if (cur < n) ans.push(cur) - indegree[cur] = -1 // mark it visited - for (let next of graph[cur] || []) { - indegree[next]-- - if (indegree[next] === 0) dfs(ans, graph, indegree, n, next) - } - } -} - - -// another - - -/** - * @param {number} n - * @param {number} m - * @param {number[]} group - * @param {number[][]} beforeItems - * @return {number[]} - */ -const sortItems = function (n, m, group, beforeItems) { - const vertexs = new Map() - const groupVertexs = new Map() - let groupNo = m - for (let i = 0; i < n; i++) { - vertexs.set(i, { - neighbors: new Set(), - indegree: 0, - }) - if (group[i] === -1) { - group[i] = groupNo++ - } - if (!groupVertexs.has(group[i])) { - groupVertexs.set(group[i], { - v: new Set(), - neighbors: new Set(), - indegree: 0, - }) - } - groupVertexs.get(group[i]).v.add(i) - } - - for (let i = 0; i < n; i++) { - for (const before of beforeItems[i]) { - if (!vertexs.get(before).neighbors.has(i)) { - vertexs.get(i).indegree += 1 - } - vertexs.get(before).neighbors.add(i) - - const groupOfBefore = group[before] - if (groupOfBefore === group[i]) continue - if (!groupVertexs.get(groupOfBefore).neighbors.has(group[i])) { - groupVertexs.get(group[i]).indegree += 1 - } - groupVertexs.get(groupOfBefore).neighbors.add(group[i]) - } - } - - const zeroGroup = [] - for (const group of groupVertexs) { - if (group[1].indegree === 0) { - zeroGroup.push(group[0]) - } - } - const result = [] - let cntGroup = 0 - let cntV = 0 - const groupTotal = groupVertexs.size - - while (zeroGroup.length) { - const top = zeroGroup.pop() - cntGroup += 1 - const v = groupVertexs.get(top).v - const total = v.size - const zero = [] - - for (const i of v) { - if (vertexs.get(i).indegree === 0) { - zero.push(i) - } - } - while (zero.length) { - const it = zero.pop() - result.push(it) - for (const n of vertexs.get(it).neighbors) { - vertexs.get(n).indegree -= 1 - if (v.has(n) && vertexs.get(n).indegree === 0) { - zero.push(n) - } - } - } - if (result.length - cntV !== total) { - return [] - } - cntV = result.length - - for (const groupneigbor of groupVertexs.get(top).neighbors) { - groupVertexs.get(groupneigbor).indegree -= 1 - if (groupVertexs.get(groupneigbor).indegree === 0) { - zeroGroup.push(groupneigbor) - } - } - } - - return cntGroup === groupTotal ? result : [] -} diff --git a/1203.sort-items-by-groups-respecting-dependencies.js b/1203.sort-items-by-groups-respecting-dependencies.js new file mode 100644 index 00000000..3f859e18 --- /dev/null +++ b/1203.sort-items-by-groups-respecting-dependencies.js @@ -0,0 +1,47 @@ +/** + * @param {number} n + * @param {number} m + * @param {number[]} group + * @param {number[][]} beforeItems + * @return {number[]} + */ +const sortItems = function (n, m, group, beforeItems) { + const graph = Array.from({ length: m + n }, () => []) + const indegree = Array(n + m).fill(0) + for (let i = 0; i < group.length; i++) { + if (group[i] == -1) continue + graph[n + group[i]].push(i) + indegree[i]++ + } + for (let i = 0; i < beforeItems.length; i++) { + for (const e of beforeItems[i]) { + const a = group[e] === -1 ? e : n + group[e] + const b = group[i] === -1 ? i : n + group[i] + if (a === b) { + // same group, ingroup order + graph[e].push(i) + indegree[i]++ + } else { + // outgoup order + graph[a].push(b) + indegree[b]++ + } + } + } + const res = [] + for (let i = 0; i < n + m; i++) { + if (indegree[i] === 0) dfs(res, graph, indegree, n, i) + } + return res.length === n ? res : [] + + function dfs(ans, graph, indegree, n, cur) { + if (cur < n) ans.push(cur) + indegree[cur] = -1 // mark it visited + for (let next of graph[cur] || []) { + indegree[next]-- + if (indegree[next] === 0) dfs(ans, graph, indegree, n, next) + } + } +} + + diff --git a/1206-design-skiplist.js b/1206-design-skiplist.js deleted file mode 100644 index c559a289..00000000 --- a/1206-design-skiplist.js +++ /dev/null @@ -1,145 +0,0 @@ -class Skiplist { - constructor() { - this.head = { down: null, right: null, val: -Infinity } - } - search(val) { - let curr = this.head - while (curr) { - while (curr.right && curr.right.val <= val) { - curr = curr.right - } - if (curr.val == val) { - return true - } - curr = curr.down - } - return false - } - add(val) { - let curr = this.head - const insertion_positions = [] - while (curr) { - while (curr.right && curr.right.val < val) { - curr = curr.right - } - insertion_positions.push(curr) - curr = curr.down - } - let insert = true - let down = null - while (insert && insertion_positions.length) { - const position = insertion_positions.pop() - const node = { down, val, right: position.right } - position.right = node - down = node - insert = Math.random() < 0.5 - } - if (insert) { - const node = { val, down } - this.head = { val: -Infinity, right: node, down: this.head } - } - } - erase(val) { - let curr = this.head - const erase_positions = [] - while (curr) { - while (curr.right && curr.right.val < val) { - curr = curr.right - } - if (curr.right && curr.right.val == val) { - erase_positions.push(curr) - } - curr = curr.down - } - const seen = erase_positions.length > 0 - for (const position of erase_positions) { - position.right = position.right && position.right.right - } - return seen - } -} - -// another - -const Skiplist = function () { - this.maxLvl = ~~Math.log2(20000) - this.levels = [...Array(this.maxLvl)].map(() => new Node(-1)) - for (let i = this.maxLvl - 1; i > 0; i--) { - this.levels[i].down = this.levels[i - 1] - } - this.head = this.levels[this.maxLvl - 1] -} - -/** - * @param {number} target - * @return {boolean} - */ -Skiplist.prototype.search = function (target) { - const pre = this.iter(target) - return !pre[0].next ? false : pre[0].next.val === target -} - -Skiplist.prototype.iter = function (target) { - let cur = this.head - const pre = [] - for (let i = this.maxLvl - 1; i >= 0; i--) { - while (cur.next && cur.next.val < target) cur = cur.next - pre[i] = cur - cur = cur.down - } - return pre -} - -/** - * @param {number} num - * @return {void} - */ -Skiplist.prototype.add = function (num) { - const pre = this.iter(num) - const lvs = decideLevels(this.maxLvl) - for (let i = 0; i < lvs; i++) { - const next = pre[i].next - pre[i].next = new Node(num) - pre[i].next.next = next - if (i > 0) pre[i].next.down = pre[i - 1].next - } -} - -/** - * @param {number} num - * @return {boolean} - */ -Skiplist.prototype.erase = function (num) { - const pre = this.iter(num) - let ret - if (!pre[0].next || pre[0].next.val !== num) return false - for (let i = this.maxLvl - 1; i >= 0; i--) { - if (pre[i].next && pre[i].next.val === num) { - const toBeDeleted = pre[i].next - pre[i].next = toBeDeleted.next - toBeDeleted.next = null - toBeDeleted.down = null - } - } - return true -} - -/** - * Your Skiplist object will be instantiated and called as such: - * var obj = new Skiplist() - * var param_1 = obj.search(target) - * obj.add(num) - * var param_3 = obj.erase(num) - */ - -const decideLevels = (max) => { - let ans = 1 - while (Math.random() > 0.5 && ans < max) ans++ - return ans -} - -const Node = function (val) { - this.val = val - this.next = null - this.down = null -} diff --git a/1206.design-skiplist.js b/1206.design-skiplist.js new file mode 100644 index 00000000..6afa5565 --- /dev/null +++ b/1206.design-skiplist.js @@ -0,0 +1,61 @@ +class Skiplist { + constructor() { + this.head = { down: null, right: null, val: -Infinity } + } + search(val) { + let curr = this.head + while (curr) { + while (curr.right && curr.right.val <= val) { + curr = curr.right + } + if (curr.val == val) { + return true + } + curr = curr.down + } + return false + } + add(val) { + let curr = this.head + const insertion_positions = [] + while (curr) { + while (curr.right && curr.right.val < val) { + curr = curr.right + } + insertion_positions.push(curr) + curr = curr.down + } + let insert = true + let down = null + while (insert && insertion_positions.length) { + const position = insertion_positions.pop() + const node = { down, val, right: position.right } + position.right = node + down = node + insert = Math.random() < 0.5 + } + if (insert) { + const node = { val, down } + this.head = { val: -Infinity, right: node, down: this.head } + } + } + erase(val) { + let curr = this.head + const erase_positions = [] + while (curr) { + while (curr.right && curr.right.val < val) { + curr = curr.right + } + if (curr.right && curr.right.val == val) { + erase_positions.push(curr) + } + curr = curr.down + } + const seen = erase_positions.length > 0 + for (const position of erase_positions) { + position.right = position.right && position.right.right + } + return seen + } +} + diff --git a/1207-unique-number-of-occurrences.js b/1207.unique-number-of-occurrences.js similarity index 100% rename from 1207-unique-number-of-occurrences.js rename to 1207.unique-number-of-occurrences.js diff --git a/1209-remove-all-adjacent-duplicates-in-string-ii.js b/1209-remove-all-adjacent-duplicates-in-string-ii.js deleted file mode 100644 index e03e4c40..00000000 --- a/1209-remove-all-adjacent-duplicates-in-string-ii.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @param {string} s - * @param {number} k - * @return {string} - */ -const removeDuplicates = function (s, k) { - const stack = []; - const arr = s.split('') - for(let i = 0; i < arr.length; i++) { - if(i === 0 || arr[i] !== arr[i - 1]) { - stack.push(1) - } else { - stack[stack.length - 1]++ - if(stack[stack.length - 1] === k) { - stack.pop() - arr.splice(i - k + 1, k) - i -= k - } - } - - } - return arr.join('') -}; - -// another - -/** - * @param {string} s - * @param {number} k - * @return {string} - */ -const removeDuplicates = function (s, k) { - const stack = []; - s = s.split(''); - for (let i = 0; i < s.length;) { - if (i === 0 || s[i] !== s[i - 1]) { - stack.push(1); - i++ - } else { - stack[stack.length - 1]++; - if (stack[stack.length - 1] === k) { - stack.pop(); - s.splice(i - k + 1, k); - i = i - k + 1; - } else { - i++ - } - } - } - return s.join(''); -}; diff --git a/1209.remove-all-adjacent-duplicates-in-string-ii.js b/1209.remove-all-adjacent-duplicates-in-string-ii.js new file mode 100644 index 00000000..1e494237 --- /dev/null +++ b/1209.remove-all-adjacent-duplicates-in-string-ii.js @@ -0,0 +1,24 @@ +/** + * @param {string} s + * @param {number} k + * @return {string} + */ +const removeDuplicates = function (s, k) { + const stack = []; + const arr = s.split('') + for(let i = 0; i < arr.length; i++) { + if(i === 0 || arr[i] !== arr[i - 1]) { + stack.push(1) + } else { + stack[stack.length - 1]++ + if(stack[stack.length - 1] === k) { + stack.pop() + arr.splice(i - k + 1, k) + i -= k + } + } + + } + return arr.join('') +}; + diff --git a/121-best-time-to-buy-and-sell-stock.js b/121-best-time-to-buy-and-sell-stock.js deleted file mode 100755 index 7a5d1899..00000000 --- a/121-best-time-to-buy-and-sell-stock.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @param {number[]} prices - * @return {number} - */ -const maxProfit = function(prices) { - let minPrice = Number.MAX_SAFE_INTEGER; - let maxP = 0; - for (let i = 0; i < prices.length; i++) { - if (prices[i] < minPrice) { - minPrice = prices[i]; - } else if (prices[i] - minPrice > maxP) { - maxP = prices[i] - minPrice; - } - } - return maxP; -}; - -// another - -/** - * @param {number[]} prices - * @return {number} - */ -const maxProfit = function(prices) { - let res = 0, maxCur = 0 - for(let i = 1; i < prices.length; i++) { - maxCur = Math.max(0, maxCur + (prices[i] - prices[i - 1])) - res = Math.max(res, maxCur) - } - return res -}; diff --git a/121.best-time-to-buy-and-sell-stock.js b/121.best-time-to-buy-and-sell-stock.js new file mode 100644 index 00000000..f09630e2 --- /dev/null +++ b/121.best-time-to-buy-and-sell-stock.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} prices + * @return {number} + */ +const maxProfit = function(prices) { + let minPrice = Number.MAX_SAFE_INTEGER; + let maxP = 0; + for (let i = 0; i < prices.length; i++) { + if (prices[i] < minPrice) { + minPrice = prices[i]; + } else if (prices[i] - minPrice > maxP) { + maxP = prices[i] - minPrice; + } + } + return maxP; +}; + diff --git a/1210-minimum-moves-to-reach-target-with-rotations.js b/1210.minimum-moves-to-reach-target-with-rotations.js similarity index 100% rename from 1210-minimum-moves-to-reach-target-with-rotations.js rename to 1210.minimum-moves-to-reach-target-with-rotations.js diff --git a/1213-intersection-of-three-sorted-arrays.js b/1213-intersection-of-three-sorted-arrays.js deleted file mode 100644 index 3984750c..00000000 --- a/1213-intersection-of-three-sorted-arrays.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @param {number[]} arr1 - * @param {number[]} arr2 - * @param {number[]} arr3 - * @return {number[]} - */ -const arraysIntersection = function(arr1, arr2, arr3) { - const common = [], n1 = arr1.length, n2 = arr2.length, n3 = arr3.length - let p1 = 0, p2 = 0, p3 = 0 - while(p1 < n1 && p2 < n2) { - if(arr1[p1] === arr2[p2]) { - common.push(arr1[p1]) - p1++ - p2++ - } else if(arr1[p1] < arr2[p2]) p1++ - else p2++ - } - const res = [], nc = common.length - let pc = 0 - while(pc < nc && p3 < n3) { - if(common[pc] === arr3[p3]) { - res.push(arr3[p3]) - pc++ - p3++ - } else if(common[pc] < arr3[p3]) pc++ - else p3++ - } - - - return res -}; - -// another - -/** - * @param {number[]} arr1 - * @param {number[]} arr2 - * @param {number[]} arr3 - * @return {number[]} - */ -const arraysIntersection = function(arr1, arr2, arr3) { - let a=0,b=0,c=0; - const res = []; - while(a new Array(n + 1).fill(0)) - for(let i = 1; i <= m; i++) { - for(let j = 1; j <= n; j++) { - if(s1[i - 1] === s2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1] + 1 - } else { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) - } - } - } - return dp[m][n] -} - -// another - -/** - * @param {string} s - * @param {number} k - * @return {boolean} - */ -const isValidPalindrome = function(s, k) { - const len = s.length - const cache = Array.from({ length: len }, () => new Array(len).fill(0)) - chk(s, 0, len - 1, cache) - return cache[0][len - 1] <= k -}; - -function chk(s, l, r, cache) { - if(l >= r) return 0 - if(cache[l][r]) return cache[l][r] - let num = 0 - if(s[l] === s[r]) { - num = chk(s, l + 1, r - 1, cache) - } else { - num = 1 + Math.min(chk(s, l, r - 1, cache), chk(s, l + 1, r, cache)) - } - cache[l][r] = num - return num -} - -// another - -const isValidPalindrome = function(s, k) { - const len = s.length - const dp = Array.from({ length: len }, () => new Array(len).fill(0)) - for(let i = len - 1; i >= 0; i--) { - dp[i][i] = 1 - for(let j = i + 1; j < len; j++) { - if(s[i] === s[j]) dp[i][j] = dp[i + 1][j - 1] + 2 - else dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]) - } - } - return len <= dp[0][len - 1] + k -}; - diff --git a/1216.valid-palindrome-iii.js b/1216.valid-palindrome-iii.js new file mode 100644 index 00000000..ec1928be --- /dev/null +++ b/1216.valid-palindrome-iii.js @@ -0,0 +1,47 @@ +/** + +Given a string s and an integer k, find out if the given string is a K-Palindrome or not. + +A string is K-Palindrome if it can be transformed into a palindrome by removing at most k characters from it. + +Example 1: + +Input: s = "abcdeca", k = 2 +Output: true +Explanation: Remove 'b' and 'e' characters. + +Constraints: + +1 <= s.length <= 1000 +s has only lowercase English letters. +1 <= k <= s.length + +*/ + +/** + * @param {string} s + * @param {number} k + * @return {boolean} + */ +const isValidPalindrome = function(s, k) { + const len = s.length + const reverse = s.split('').reverse().join('') + const lps = lcs(s, reverse, len, len) + return len - lps <= k + +}; + +function lcs(s1, s2, m, n) { + const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0)) + for(let i = 1; i <= m; i++) { + for(let j = 1; j <= n; j++) { + if(s1[i - 1] === s2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1 + } else { + dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) + } + } + } + return dp[m][n] +} + diff --git a/1217-minimum-cost-to-move-chips-to-the-same-position.js b/1217.minimum-cost-to-move-chips-to-the-same-position.js similarity index 100% rename from 1217-minimum-cost-to-move-chips-to-the-same-position.js rename to 1217.minimum-cost-to-move-chips-to-the-same-position.js diff --git a/1219-path-with-maximum-gold.js b/1219-path-with-maximum-gold.js deleted file mode 100644 index 150b85e8..00000000 --- a/1219-path-with-maximum-gold.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const getMaximumGold = function(grid) { - const m = grid.length, n = grid[0].length - const arr = [] - const dirs = [[-1, 0], [1, 0], [0, 1], [0, -1]] - const visited = new Set() - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - if(grid[i][j] !== 0) arr.push([i, j]) - } - } - let res = 0 - - for(const [i, j] of arr) { - visited.clear() - visited.add(`${i},${j}`) - dfs(i, j, grid[i][j]) - } - - return res - - function dfs(i, j, cur) { - - res = Math.max(res, cur) - for(const [dx, dy] of dirs) { - const nx = i + dx - const ny = j + dy - const key = `${nx},${ny}` - if(nx >= 0 && nx < m && ny >= 0 && ny < n && !visited.has(key) && grid[nx][ny] !== 0) { - visited.add(key) - dfs(nx, ny, cur + grid[nx][ny]) - visited.delete(key) - } - } - } - -}; - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -var getMaximumGold = function (grid) { - const m = grid.length - const n = grid[0].length - let max = 0 - - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - if (grid[i][j] != 0) { - const sum = backtrack(grid, i, j, m, n) - max = Math.max(sum, max) - } - } - } - - return max -} - -function backtrack(grid, row, col, m, n) { - if (outOfBound(row, col, m, n) || grid[row][col] === 0) return 0 - - let sum = grid[row][col] - grid[row][col] = 0 // mark as being visited already - - const top = backtrack(grid, row - 1, col, m, n) - const right = backtrack(grid, row, col + 1, m, n) - const bot = backtrack(grid, row + 1, col, m, n) - const left = backtrack(grid, row, col - 1, m, n) - - grid[row][col] = sum // backtrack to the original form - - return sum + Math.max(top, right, bot, left) -} - -function outOfBound(row, col, m, n) { - return row < 0 || col < 0 || row >= m || col >= n -} diff --git a/1219.path-with-maximum-gold.js b/1219.path-with-maximum-gold.js new file mode 100644 index 00000000..beec0f2d --- /dev/null +++ b/1219.path-with-maximum-gold.js @@ -0,0 +1,41 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const getMaximumGold = function(grid) { + const m = grid.length, n = grid[0].length + const arr = [] + const dirs = [[-1, 0], [1, 0], [0, 1], [0, -1]] + const visited = new Set() + for(let i = 0; i < m; i++) { + for(let j = 0; j < n; j++) { + if(grid[i][j] !== 0) arr.push([i, j]) + } + } + let res = 0 + + for(const [i, j] of arr) { + visited.clear() + visited.add(`${i},${j}`) + dfs(i, j, grid[i][j]) + } + + return res + + function dfs(i, j, cur) { + + res = Math.max(res, cur) + for(const [dx, dy] of dirs) { + const nx = i + dx + const ny = j + dy + const key = `${nx},${ny}` + if(nx >= 0 && nx < m && ny >= 0 && ny < n && !visited.has(key) && grid[nx][ny] !== 0) { + visited.add(key) + dfs(nx, ny, cur + grid[nx][ny]) + visited.delete(key) + } + } + } + +}; + diff --git a/122-best-time-to-buy-and-sell-stock-ii.js b/122.best-time-to-buy-and-sell-stock-ii.js similarity index 100% rename from 122-best-time-to-buy-and-sell-stock-ii.js rename to 122.best-time-to-buy-and-sell-stock-ii.js diff --git a/1220-count-vowels-permutation.js b/1220.count-vowels-permutation.js similarity index 100% rename from 1220-count-vowels-permutation.js rename to 1220.count-vowels-permutation.js diff --git a/1221-split-a-string-in-balanced-strings.js b/1221.split-a-string-in-balanced-strings.js similarity index 100% rename from 1221-split-a-string-in-balanced-strings.js rename to 1221.split-a-string-in-balanced-strings.js diff --git a/1223-dice-roll-simulation.js b/1223.dice-roll-simulation.js similarity index 100% rename from 1223-dice-roll-simulation.js rename to 1223.dice-roll-simulation.js diff --git a/1224-maximum-equal-frequency.js b/1224-maximum-equal-frequency.js deleted file mode 100644 index 192cc0e6..00000000 --- a/1224-maximum-equal-frequency.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const maxEqualFreq = function (nums) { - const freqCnt = {}, cnt = {}, { max } = Math - - let res = 0, maxF = 0, i = 0 - for(const e of nums) { - if(cnt[e] == null) cnt[e] = 0 - cnt[e]++ - - const f = cnt[e] - - if(freqCnt[f - 1] == null) freqCnt[f - 1] = 0 - if(freqCnt[f] == null) freqCnt[f] = 0 - - if(freqCnt[f - 1] > 0) freqCnt[f - 1]-- - freqCnt[f]++ - - maxF = max(maxF, f) - - /* - cnt records the occurence of each num, freq records the frequence of number of occurences. max_F is the largest frequence. - There are three cases which satify the condition: - - all elements appear exact once. - all elements appear max_F times, except one appears once. - all elements appear max_F-1 times, except one appears max_F. - */ - if( - maxF === 1 || - maxF * freqCnt[maxF] === i || - (maxF - 1) * (freqCnt[maxF - 1] + 1) === i - ) { - res = i + 1 - } - - i++ - } - - return res -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxEqualFreq = function (nums) { - const cnt = {}, - freq = {} - let maxF = 0, - res = 0 - nums.forEach((num, i) => { - if (cnt[num] == null) cnt[num] = 0 - cnt[num] += 1 - if (freq[cnt[num] - 1] == null) freq[cnt[num] - 1] = 0 - if (freq[cnt[num]] == null) freq[cnt[num]] = 0 - freq[cnt[num] - 1] -= 1 - freq[cnt[num]] += 1 - maxF = Math.max(maxF, cnt[num]) - if ( - maxF * freq[maxF] === i || - (maxF - 1) * (freq[maxF - 1] + 1) === i || - maxF === 1 - ) - res = i + 1 - }) - return res -} diff --git a/1224.maximum-equal-frequency.js b/1224.maximum-equal-frequency.js new file mode 100644 index 00000000..75522276 --- /dev/null +++ b/1224.maximum-equal-frequency.js @@ -0,0 +1,44 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const maxEqualFreq = function (nums) { + const freqCnt = {}, cnt = {}, { max } = Math + + let res = 0, maxF = 0, i = 0 + for(const e of nums) { + if(cnt[e] == null) cnt[e] = 0 + cnt[e]++ + + const f = cnt[e] + + if(freqCnt[f - 1] == null) freqCnt[f - 1] = 0 + if(freqCnt[f] == null) freqCnt[f] = 0 + + if(freqCnt[f - 1] > 0) freqCnt[f - 1]-- + freqCnt[f]++ + + maxF = max(maxF, f) + + /* + cnt records the occurence of each num, freq records the frequence of number of occurences. max_F is the largest frequence. + There are three cases which satify the condition: + + all elements appear exact once. + all elements appear max_F times, except one appears once. + all elements appear max_F-1 times, except one appears max_F. + */ + if( + maxF === 1 || + maxF * freqCnt[maxF] === i || + (maxF - 1) * (freqCnt[maxF - 1] + 1) === i + ) { + res = i + 1 + } + + i++ + } + + return res +} + diff --git a/1228-missing-number-in-arithmetic-progression.js b/1228.missing-number-in-arithmetic-progression.js similarity index 100% rename from 1228-missing-number-in-arithmetic-progression.js rename to 1228.missing-number-in-arithmetic-progression.js diff --git a/1229-meeting-scheduler.js b/1229-meeting-scheduler.js deleted file mode 100644 index 46d4c72e..00000000 --- a/1229-meeting-scheduler.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @param {number[][]} slots1 - * @param {number[][]} slots2 - * @param {number} duration - * @return {number[]} - */ -const minAvailableDuration = function (slots1, slots2, duration) { - const hash = {} - for(const [s, e] of slots1) { - if(hash[s] == null) hash[s] = 0 - if(hash[e] == null) hash[e] = 0 - - hash[s]++ - hash[e]-- - } - - for(const [s, e] of slots2) { - if(hash[s] == null) hash[s] = 0 - if(hash[e] == null) hash[e] = 0 - - hash[s]++ - hash[e]-- - } - - const keys = Object.keys(hash).map(e => +e) - keys.sort((a, b) => a - b) - for(let i = 1; i < keys.length; i++) { - hash[keys[i]] += hash[keys[i - 1]] - } - // console.log(keys, hash) - const n = keys.length - for(let i = 0; i < keys.length; i++) { - const k = keys[i] - if(hash[k] === 2 && i + 1 < n && valid(k, i)) { - return [k, k + duration] - } - } - - return [] - - function valid(k, idx) { - let l = k, r = k + duration - for(let i = idx + 1; i < keys.length && keys[i] < r; i++) { - const key = keys[i] - if(hash[key] !== 2) return false - } - - return true - } -} - -// another - -/** - * @param {number[][]} slots1 - * @param {number[][]} slots2 - * @param {number} duration - * @return {number[]} - */ -const minAvailableDuration = function (slots1, slots2, duration) { - slots1.sort((a, b) => a[0] - b[0]) - slots2.sort((a, b) => a[0] - b[0]) - - const m = slots1.length, n = slots2.length - let i = 0, j = 0 - - while(i < m && j < n) { - const start = Math.max(slots1[i][0], slots2[j][0]) - const end = Math.min(slots1[i][1], slots2[j][1]) - - if(end - start >= duration) { - return [start, start + duration] - } - - if(slots1[i][1] > slots2[j][1]) j++ - else i++ - - } - - return [] -} diff --git a/1229.meeting-scheduler.js b/1229.meeting-scheduler.js new file mode 100644 index 00000000..e8257eb0 --- /dev/null +++ b/1229.meeting-scheduler.js @@ -0,0 +1,51 @@ +/** + * @param {number[][]} slots1 + * @param {number[][]} slots2 + * @param {number} duration + * @return {number[]} + */ +const minAvailableDuration = function (slots1, slots2, duration) { + const hash = {} + for(const [s, e] of slots1) { + if(hash[s] == null) hash[s] = 0 + if(hash[e] == null) hash[e] = 0 + + hash[s]++ + hash[e]-- + } + + for(const [s, e] of slots2) { + if(hash[s] == null) hash[s] = 0 + if(hash[e] == null) hash[e] = 0 + + hash[s]++ + hash[e]-- + } + + const keys = Object.keys(hash).map(e => +e) + keys.sort((a, b) => a - b) + for(let i = 1; i < keys.length; i++) { + hash[keys[i]] += hash[keys[i - 1]] + } + // console.log(keys, hash) + const n = keys.length + for(let i = 0; i < keys.length; i++) { + const k = keys[i] + if(hash[k] === 2 && i + 1 < n && valid(k, i)) { + return [k, k + duration] + } + } + + return [] + + function valid(k, idx) { + let l = k, r = k + duration + for(let i = idx + 1; i < keys.length && keys[i] < r; i++) { + const key = keys[i] + if(hash[key] !== 2) return false + } + + return true + } +} + diff --git a/123-best-time-to-buy-and-sell-stock-iii.js b/123.best-time-to-buy-and-sell-stock-iii.js similarity index 100% rename from 123-best-time-to-buy-and-sell-stock-iii.js rename to 123.best-time-to-buy-and-sell-stock-iii.js diff --git a/1231-divide-chocolate.js b/1231-divide-chocolate.js deleted file mode 100644 index ea4d1768..00000000 --- a/1231-divide-chocolate.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @param {number[]} sweetness - * @param {number} K - * @return {number} - */ -const maximizeSweetness = function (sweetness, K) { - let left = 1, - right = 1e9 / (K + 1) - while (left < right) { - let mid = (left + right + 1) >> 1 - let cur = 0, - cuts = 0 - for (let a of sweetness) { - if ((cur += a) >= mid) { - cur = 0 - if (++cuts > K) break - } - } - if (cuts > K) left = mid - else right = mid - 1 - } - return left -} - -// another - -/** - * @param {number[]} sweetness - * @param {number} K - * @return {number} - */ -const maximizeSweetness = function(sweetness, K) { - let l = 1, r = 10 ** 9 - while(l < r) { - const mid = r - Math.floor((r - l) / 2) - if(valid(mid)) l = mid - else r = mid - 1 - } - return l - - function valid(mid) { - let res = 0, cur = 0 - const n = sweetness.length - for(let i = 0; i < n; i++) { - const e = sweetness[i] - cur += e - if(cur >= mid) { - res++ - cur = 0 - } - } - return res >= K + 1 - } -}; diff --git a/1231.divide-chocolate.js b/1231.divide-chocolate.js new file mode 100644 index 00000000..cdc7a556 --- /dev/null +++ b/1231.divide-chocolate.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} sweetness + * @param {number} K + * @return {number} + */ +const maximizeSweetness = function (sweetness, K) { + let left = 1, + right = 1e9 / (K + 1) + while (left < right) { + let mid = (left + right + 1) >> 1 + let cur = 0, + cuts = 0 + for (let a of sweetness) { + if ((cur += a) >= mid) { + cur = 0 + if (++cuts > K) break + } + } + if (cuts > K) left = mid + else right = mid - 1 + } + return left +} + diff --git a/1232-check-if-it-is-a-straight-line.js b/1232.check-if-it-is-a-straight-line.js similarity index 100% rename from 1232-check-if-it-is-a-straight-line.js rename to 1232.check-if-it-is-a-straight-line.js diff --git a/1235-maximum-profit-in-job-scheduling.js b/1235-maximum-profit-in-job-scheduling.js deleted file mode 100644 index a5a0fa3b..00000000 --- a/1235-maximum-profit-in-job-scheduling.js +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @param {number[]} startTime - * @param {number[]} endTime - * @param {number[]} profit - * @return {number} - */ -const jobScheduling = function (startTime, endTime, profit) { - const n = startTime.length - const items = Array(n) - for(let i = 0;i < n; i++) items[i] = [startTime[i], endTime[i], profit[i]] - items.sort((a, b) => a[1] - b[1]) - const dpEndTime = [0] - const dpProfit = [0] - for(const [s, e, p] of items) { - const prevIdx = binarySearch(dpEndTime, 0, dpEndTime.length - 1, s) - const curProfit = dpProfit[prevIdx] + p, maxProfit = dpProfit[dpProfit.length - 1] - if(curProfit > maxProfit) { - dpProfit.push(curProfit) - dpEndTime.push(e) - } - } - - return dpProfit[dpProfit.length - 1] -} - -function binarySearch(arr, l, r, x) { - while (l < r) { - const mid = r - ((r - l) >> 1) - if (arr[mid] > x) r = mid - 1 - else l = mid - } - return l -} - - -// another - -/** - * @param {number[]} startTime - * @param {number[]} endTime - * @param {number[]} profit - * @return {number} - */ -const jobScheduling = function (startTime, endTime, profit) { - const n = startTime.length - const items = Array.from({ length: startTime.length }, () => Array(3).fill(0)) - for (let i = 0; i < startTime.length; i++) { - items[i] = [startTime[i], endTime[i], profit[i]] - } - items.sort((a1, a2) => a1[1] - a2[1]) - const dpProfit = [0] - for (let i = 0; i < n; i++) { - const [s, e, p] = items[i] - let prevIdx = -1 - for(let j = i - 1; j >= 0; j--) { - if(items[j][1] <= items[i][0]) { - prevIdx = j - break - } - } - const curProfit = (prevIdx === -1 ? 0 : dpProfit[prevIdx]) + p - dpProfit[i] = Math.max(dpProfit[dpProfit.length - 1], curProfit) - } - return dpProfit[dpProfit.length - 1] -} - - -// another - - -/** - * @param {number[]} startTime - * @param {number[]} endTime - * @param {number[]} profit - * @return {number} - */ -const jobScheduling = function (startTime, endTime, profit) { - const items = Array.from({ length: startTime.length }, () => Array(3).fill(0)) - for (let i = 0; i < startTime.length; i++) { - items[i] = [startTime[i], endTime[i], profit[i]] - } - items.sort((a1, a2) => a1[1] - a2[1]) - const dpEndTime = [] - const dpProfit = [] - dpEndTime.push(0) - dpProfit.push(0) - for (let item of items) { - const s = item[0], - e = item[1], - p = item[2] - // find previous endTime index - const prevIdx = binarySearch(dpEndTime, 0, dpEndTime.length - 1, s) - const currProfit = dpProfit[prevIdx] + p, - maxProfit = dpProfit[dpProfit.length - 1] - if (currProfit > maxProfit) { - dpProfit.push(currProfit) - dpEndTime.push(e) - } - } - return dpProfit[dpProfit.length - 1] -} - -function binarySearch(arr, l, r, x) { - while (l <= r) { - const mid = l + ((r - l) >> 1) - if (arr[mid] > x) r = mid - 1 - else { - if (mid == arr.length - 1 || arr[mid + 1] > x) return mid - l = mid + 1 - } - } - return -1 -} diff --git a/1235.maximum-profit-in-job-scheduling.js b/1235.maximum-profit-in-job-scheduling.js new file mode 100644 index 00000000..63c5b28d --- /dev/null +++ b/1235.maximum-profit-in-job-scheduling.js @@ -0,0 +1,35 @@ +/** + * @param {number[]} startTime + * @param {number[]} endTime + * @param {number[]} profit + * @return {number} + */ +const jobScheduling = function (startTime, endTime, profit) { + const n = startTime.length + const items = Array(n) + for(let i = 0;i < n; i++) items[i] = [startTime[i], endTime[i], profit[i]] + items.sort((a, b) => a[1] - b[1]) + const dpEndTime = [0] + const dpProfit = [0] + for(const [s, e, p] of items) { + const prevIdx = binarySearch(dpEndTime, 0, dpEndTime.length - 1, s) + const curProfit = dpProfit[prevIdx] + p, maxProfit = dpProfit[dpProfit.length - 1] + if(curProfit > maxProfit) { + dpProfit.push(curProfit) + dpEndTime.push(e) + } + } + + return dpProfit[dpProfit.length - 1] +} + +function binarySearch(arr, l, r, x) { + while (l < r) { + const mid = r - ((r - l) >> 1) + if (arr[mid] > x) r = mid - 1 + else l = mid + } + return l +} + + diff --git a/1239-maximum-length-of-a-concatenated-string-with-unique-characters.js b/1239.maximum-length-of-a-concatenated-string-with-unique-characters.js similarity index 100% rename from 1239-maximum-length-of-a-concatenated-string-with-unique-characters.js rename to 1239.maximum-length-of-a-concatenated-string-with-unique-characters.js diff --git a/124-binary-tree-maximum-path-sum.js b/124-binary-tree-maximum-path-sum.js deleted file mode 100644 index 68e174a9..00000000 --- a/124-binary-tree-maximum-path-sum.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const maxPathSum = function(root) { - let obj = { - max: Number.MIN_SAFE_INTEGER - } - traverse(root, obj) - - return obj.max -}; - -function traverse(node, obj) { - if(node === null) return 0 - let left = Math.max(0, traverse(node.left, obj)) - let right = Math.max(0, traverse(node.right, obj)) - obj.max = Math.max(obj.max, node.val+left+right) - return node.val + Math.max(left, right) -} - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const maxPathSum = function(root) { - let res = -Infinity - dfs(root) - return res - - function dfs(node) { - if(node == null) return 0 - let left = dfs(node.left), right = dfs(node.right) - res = Math.max( - res, - node.val, - node.val + left, - node.val + right, - node.val + left + right, - ) - return Math.max(node.val, node.val + left, node.val + right) - } -}; diff --git a/124.binary-tree-maximum-path-sum.js b/124.binary-tree-maximum-path-sum.js new file mode 100644 index 00000000..5f53f2dc --- /dev/null +++ b/124.binary-tree-maximum-path-sum.js @@ -0,0 +1,28 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +const maxPathSum = function(root) { + let obj = { + max: Number.MIN_SAFE_INTEGER + } + traverse(root, obj) + + return obj.max +}; + +function traverse(node, obj) { + if(node === null) return 0 + let left = Math.max(0, traverse(node.left, obj)) + let right = Math.max(0, traverse(node.right, obj)) + obj.max = Math.max(obj.max, node.val+left+right) + return node.val + Math.max(left, right) +} + diff --git a/1240-tiling-a-rectangle-with-the-fewest-squares.js b/1240.tiling-a-rectangle-with-the-fewest-squares.js similarity index 100% rename from 1240-tiling-a-rectangle-with-the-fewest-squares.js rename to 1240.tiling-a-rectangle-with-the-fewest-squares.js diff --git a/1243-array-transformation.js b/1243.array-transformation.js similarity index 100% rename from 1243-array-transformation.js rename to 1243.array-transformation.js diff --git a/1244-design-a-leaderboard.js b/1244.design-a-leaderboard.js similarity index 100% rename from 1244-design-a-leaderboard.js rename to 1244.design-a-leaderboard.js diff --git a/1245-tree-diameter.js b/1245.tree-diameter.js similarity index 100% rename from 1245-tree-diameter.js rename to 1245.tree-diameter.js diff --git a/1246-palindrome-removal.js b/1246-palindrome-removal.js deleted file mode 100644 index f73084af..00000000 --- a/1246-palindrome-removal.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {number[]} arr - * @return {number} - */ -const minimumMoves = function (arr) { - const n = arr.length - const dp = Array.from({ length: n }, () => Array(n).fill(n)) - // handle edge situation: subarray size == 1 - for (let i = 0; i < n; i++) { - dp[i][i] = 1 - } - // handle edge situation: subarray size == 2 - for (let i = 0; i < n - 1; i++) { - dp[i][i + 1] = arr[i] === arr[i + 1] ? 1 : 2 - } - // for subarray size >= 3: - for (let size = 3; size <= n; size++) { - for (let left = 0, right = left + size - 1; right < n; left++, right++) { - // if arr[left] == arr[right], then the two number: arr[left] and arr[right] can be - // removed when the last move of subarray arr[left + 1:right - 1] - if (arr[left] === arr[right]) { - dp[left][right] = dp[left + 1][right - 1] - } - // or, if we cannot remove arr[left] and arr[right] in one move (the last move), - // the subarray arr[left:right] must can be split into two subarrays - // and remove them one by one. - for (let mid = left; mid < right; mid++) { - dp[left][right] = Math.min( - dp[left][right], - dp[left][mid] + dp[mid + 1][right] - ) - } - } - } - return dp[0][n - 1] -} - -// another - -/** - * @param {number[]} arr - * @return {number} - */ - const minimumMoves = function (arr) { - const n = arr.length - - const dp = Array.from({ length: n }, () => Array(n).fill(n)) - - for(let i = 0; i < n; i++) dp[i][i] = 1 - for(let i = 0; i < n - 1; i++) { - dp[i][i + 1] = arr[i] === arr[i + 1] ? 1 : 2 - } - - for(let size = 3; size <= n; size++) { - for(let i = 0; i + size - 1 < n; i++) { - const right = i + size - 1 - if(arr[i] === arr[right]) dp[i][right] = dp[i + 1][right - 1] - for(let j = i; j < right; j++) { - dp[i][right] = Math.min(dp[i][right], dp[i][j] + dp[j + 1][right]) - } - } - } - - return dp[0][n - 1] -} diff --git a/1246.palindrome-removal.js b/1246.palindrome-removal.js new file mode 100644 index 00000000..74cc2b46 --- /dev/null +++ b/1246.palindrome-removal.js @@ -0,0 +1,37 @@ +/** + * @param {number[]} arr + * @return {number} + */ +const minimumMoves = function (arr) { + const n = arr.length + const dp = Array.from({ length: n }, () => Array(n).fill(n)) + // handle edge situation: subarray size == 1 + for (let i = 0; i < n; i++) { + dp[i][i] = 1 + } + // handle edge situation: subarray size == 2 + for (let i = 0; i < n - 1; i++) { + dp[i][i + 1] = arr[i] === arr[i + 1] ? 1 : 2 + } + // for subarray size >= 3: + for (let size = 3; size <= n; size++) { + for (let left = 0, right = left + size - 1; right < n; left++, right++) { + // if arr[left] == arr[right], then the two number: arr[left] and arr[right] can be + // removed when the last move of subarray arr[left + 1:right - 1] + if (arr[left] === arr[right]) { + dp[left][right] = dp[left + 1][right - 1] + } + // or, if we cannot remove arr[left] and arr[right] in one move (the last move), + // the subarray arr[left:right] must can be split into two subarrays + // and remove them one by one. + for (let mid = left; mid < right; mid++) { + dp[left][right] = Math.min( + dp[left][right], + dp[left][mid] + dp[mid + 1][right] + ) + } + } + } + return dp[0][n - 1] +} + diff --git a/1247-minimum-swaps-to-make-strings-equal.js b/1247.minimum-swaps-to-make-strings-equal.js similarity index 100% rename from 1247-minimum-swaps-to-make-strings-equal.js rename to 1247.minimum-swaps-to-make-strings-equal.js diff --git a/1249-minimum-remove-to-make-valid-parentheses.js b/1249-minimum-remove-to-make-valid-parentheses.js deleted file mode 100644 index 1599e395..00000000 --- a/1249-minimum-remove-to-make-valid-parentheses.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ - const minRemoveToMakeValid = function(s) { - const stack = [], n = s.length - const arr = s.split('') - let res = '' - for(let i = 0; i < n; i++) { - if(s[i] === '(') stack.push(i + 1) - if(s[i] === ')') { - if(stack.length && stack[stack.length - 1] >= 0) stack.pop() - else stack.push(-(i + 1)) - } - } - while(stack.length) { - arr[Math.abs(stack.pop()) - 1] = '' - } - return arr.join('') -}; - -// another - -/** - * @param {string} s - * @return {string} - */ -const minRemoveToMakeValid = function(s) { - let cnt = 0 - let res = s.split('') - // console.log(res) - for(let i = 0; i < res.length; ) { - const ch = res[i] - if(ch === '(') cnt++ - if(ch === ')') cnt-- - if(cnt < 0) { - // console.log(res, i) - res.splice(i, 1) - cnt++ - } else i++ - } - // console.log(res) - let idx = res.length - 1 - while(cnt > 0) { - if(res[idx] === '(') { - res.splice(idx, 1) - cnt-- - } else idx-- - } - return res.join('') -}; - -// another - -/** - * @param {string} s - * @return {string} - */ -const minRemoveToMakeValid = function(s) { - const stk = [], arr = s.split(''), n = s.length - for(let i = 0; i < n; i++) { - if(s[i] === '(') stk.push(i) - if(s[i] === ')') { - if(stk.length && stk[stk.length - 1] >= 0) stk.pop() - else stk.push(-(i + 1)) - } - } - - while(stk.length) { - const tmp = stk.pop() - if(tmp < 0) arr[-tmp - 1] = '' - else arr[tmp] = '' - } - return arr.join('') -}; diff --git a/1249.minimum-remove-to-make-valid-parentheses.js b/1249.minimum-remove-to-make-valid-parentheses.js new file mode 100644 index 00000000..05f31e41 --- /dev/null +++ b/1249.minimum-remove-to-make-valid-parentheses.js @@ -0,0 +1,21 @@ +/** + * @param {string} s + * @return {string} + */ + const minRemoveToMakeValid = function(s) { + const stack = [], n = s.length + const arr = s.split('') + let res = '' + for(let i = 0; i < n; i++) { + if(s[i] === '(') stack.push(i + 1) + if(s[i] === ')') { + if(stack.length && stack[stack.length - 1] >= 0) stack.pop() + else stack.push(-(i + 1)) + } + } + while(stack.length) { + arr[Math.abs(stack.pop()) - 1] = '' + } + return arr.join('') +}; + diff --git a/125-valid-palindrome.js b/125.valid-palindrome.js similarity index 100% rename from 125-valid-palindrome.js rename to 125.valid-palindrome.js diff --git a/1252-cells-with-odd-values-in-a-matrix.js b/1252.cells-with-odd-values-in-a-matrix.js similarity index 100% rename from 1252-cells-with-odd-values-in-a-matrix.js rename to 1252.cells-with-odd-values-in-a-matrix.js diff --git a/1254-number-of-closed-islands.js b/1254-number-of-closed-islands.js deleted file mode 100644 index acf9f12e..00000000 --- a/1254-number-of-closed-islands.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const closedIsland = function(grid) { - const m = grid.length, n = grid[0].length - const dirs = [[0,1], [0,-1], [1,0], [-1,0]] - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - if((i=== 0 || i === m - 1 || j === 0 || j === n - 1) && grid[i][j] === 0){ - fill(i, j) - } - } - } - - - let res = 0 - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - if(grid[i][j] === 0) { - res++ - fill(i, j) - } - } - } - - return res - - - function fill(i, j) { - if(i < 0 || i >= m || j < 0 || j >= n || grid[i][j] !== 0) return - grid[i][j] = 1 - for(const [dx, dy] of dirs) { - const nx = i + dx, ny = j + dy - fill(nx, ny) - } - } -}; - -// another - - -/** - * @param {number[][]} grid - * @return {number} - */ -const closedIsland = function(grid) { - const m = grid.length, n = grid[0].length - const arr = [] - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - if(grid[i][j] === 0) arr.push([i, j]) - } - } - const dirs = [[0,1], [0,-1], [1,0], [-1,0]] - let num = 2 - for(const [i, j] of arr) { - if(grid[i][j] !== 0) continue - else { - bfs(i, j, num) - num++ - } - } - - let res = 0 - const set = new Set() - for(let i = 2; i < num; i++) { - set.add(i) - } - - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - if(grid[i][j] > 1 && invalid(i, j)) { - set.delete(grid[i][j]) - } - } - } - return set.size - - function invalid(i,j) { - if(i === 0 || i === m - 1 || j === 0 || j === n - 1) return true - return false - } - function bfs(i, j, v) { - let q = [[i,j]] - grid[i][j] = v - while(q.length) { - const tmp = [] - const size = q.length - - for(const [x, y] of q) { - for(const [dx, dy] of dirs) { - const nx = x + dx, ny = y + dy - if(nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] === 0) { - grid[nx][ny] = v - tmp.push([nx, ny]) - } - } - } - - q = tmp - } - } -}; diff --git a/1254.number-of-closed-islands.js b/1254.number-of-closed-islands.js new file mode 100644 index 00000000..0286e48c --- /dev/null +++ b/1254.number-of-closed-islands.js @@ -0,0 +1,39 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const closedIsland = function(grid) { + const m = grid.length, n = grid[0].length + const dirs = [[0,1], [0,-1], [1,0], [-1,0]] + for(let i = 0; i < m; i++) { + for(let j = 0; j < n; j++) { + if((i=== 0 || i === m - 1 || j === 0 || j === n - 1) && grid[i][j] === 0){ + fill(i, j) + } + } + } + + + let res = 0 + for(let i = 0; i < m; i++) { + for(let j = 0; j < n; j++) { + if(grid[i][j] === 0) { + res++ + fill(i, j) + } + } + } + + return res + + + function fill(i, j) { + if(i < 0 || i >= m || j < 0 || j >= n || grid[i][j] !== 0) return + grid[i][j] = 1 + for(const [dx, dy] of dirs) { + const nx = i + dx, ny = j + dy + fill(nx, ny) + } + } +}; + diff --git a/1255-maximum-score-words-formed-by-letters.js b/1255.maximum-score-words-formed-by-letters.js similarity index 100% rename from 1255-maximum-score-words-formed-by-letters.js rename to 1255.maximum-score-words-formed-by-letters.js diff --git a/1257-smallest-common-region.js b/1257.smallest-common-region.js similarity index 100% rename from 1257-smallest-common-region.js rename to 1257.smallest-common-region.js diff --git a/126-word-ladder-ii.js b/126.word-ladder-ii.js similarity index 100% rename from 126-word-ladder-ii.js rename to 126.word-ladder-ii.js diff --git a/1260-shift-2d-grid.js b/1260.shift-2d-grid.js similarity index 100% rename from 1260-shift-2d-grid.js rename to 1260.shift-2d-grid.js diff --git a/1261-find-elements-in-a-contaminated-binary-tree.js b/1261.find-elements-in-a-contaminated-binary-tree.js similarity index 100% rename from 1261-find-elements-in-a-contaminated-binary-tree.js rename to 1261.find-elements-in-a-contaminated-binary-tree.js diff --git a/1262-greatest-sum-divisible-by-three.js b/1262-greatest-sum-divisible-by-three.js deleted file mode 100644 index fac1d5c9..00000000 --- a/1262-greatest-sum-divisible-by-three.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const maxSumDivThree = function (nums) { - const n = nums.length - let dp = [0, -Infinity, -Infinity] - for (let i = n - 1; i >= 0; i--) { - const nextDp = [] - for (let j = 0; j < 3; j++) { - const nextRemain = nums[i] % 3 - nextDp[j] = Math.max(nums[i] + dp[(nextRemain + j) % 3], dp[j]) - } - dp = nextDp - } - return dp[0] -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxSumDivThree = function(nums) { - const sum = nums.reduce((ac, el) => ac + el, 0) - if(sum % 3 === 0) return sum - const remainder = sum % 3 - const comp = 3 - remainder - nums.sort((a, b) => a - b) - const re = [], rc = [] - for(let i = 0, len = nums.length; i < len; i++) { - if(nums[i] % 3 === remainder) { - if(re.length < 1) re.push(i) - } - if(nums[i] % 3 === comp) { - if(rc.length < 2) rc.push(i) - } - if(re.length === 1 && rc.length === 2) break - } - if(re.length === 1 && rc.length === 2) { - return Math.max(sum - nums[re[0]], sum - nums[rc[0]] - nums[rc[1]]) - } else if(re.length === 1) { - return sum - nums[re[0]] - } else if(rc.length === 2) { - return sum - nums[rc[0]] - nums[rc[1]] - } else { - return 0 - } -}; diff --git a/1262.greatest-sum-divisible-by-three.js b/1262.greatest-sum-divisible-by-three.js new file mode 100644 index 00000000..eb2debaf --- /dev/null +++ b/1262.greatest-sum-divisible-by-three.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const maxSumDivThree = function (nums) { + const n = nums.length + let dp = [0, -Infinity, -Infinity] + for (let i = n - 1; i >= 0; i--) { + const nextDp = [] + for (let j = 0; j < 3; j++) { + const nextRemain = nums[i] % 3 + nextDp[j] = Math.max(nums[i] + dp[(nextRemain + j) % 3], dp[j]) + } + dp = nextDp + } + return dp[0] +} + diff --git a/1263-minimum-moves-to-move-a-box-to-their-target-location.js b/1263-minimum-moves-to-move-a-box-to-their-target-location.js deleted file mode 100644 index 2ec22d2d..00000000 --- a/1263-minimum-moves-to-move-a-box-to-their-target-location.js +++ /dev/null @@ -1,462 +0,0 @@ -/** - * @param {character[][]} grid - * @return {number} - */ -const minPushBox = function (grid) { - let box, person, target - const m = grid.length, - n = grid[0].length - const dirs = [ - [-1, 0], - [1, 0], - [0, -1], - [0, 1], - ] - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - const e = grid[i][j] - if (e === 'B') box = [i, j] - else if (e === 'T') target = [i, j] - else if (e === 'S') person = [i, j] - } - } - - const valid = ([i, j]) => { - return i >= 0 && i < m && j >= 0 && j < n && grid[i][j] !== '#' - } - const key = ([i, j]) => `${i},${j}` - - const chk = (person, newPerson, box) => { - const set = new Set() - set.add(key(box)) - let q = [person] - while (q.length) { - const tmp = [] - const size = q.length - for (let i = 0; i < size; i++) { - const [x, y] = q[i] - if (key([x, y]) === key(newPerson)) return true - for (const [dx, dy] of dirs) { - const [nx, ny] = [x + dx, y + dy] - if (valid([nx, ny]) && !set.has(key([nx, ny]))) { - set.add(key([nx, ny])) - tmp.push([nx, ny]) - } - } - } - q = tmp - } - return false - } - - - let q = [[0, box, person]] - const dkey = (a, b) => `${a[0]},${a[1]}_${b[0]},${b[1]}` - const set = new Set() - set.add(dkey(box, person)) - while (q.length) { - const size = q.length - const tmp = [] - for (let i = 0; i < size; i++) { - const [v, b, p] = q[i] - if (key(b) === key(target)) return v - const bArr = [ - [b[0], b[1] + 1], - [b[0], b[1] - 1], - [b[0] + 1, b[1]], - [b[0] - 1, b[1]], - ] - const pArr = [ - [b[0], b[1] - 1], - [b[0], b[1] + 1], - [b[0] - 1, b[1]], - [b[0] + 1, b[1]], - ] - - for (let j = 0; j < 4; j++) { - const nb = bArr[j], - np = pArr[j] - const nk = dkey(nb, b) - - if (set.has(nk)) continue - if (valid(nb) && valid(np) && chk(p, np, b)) { - tmp.push([v + 1, nb, b]) - set.add(nk) - } - } - } - q = tmp - } - - return -1 -} - -// another - - -/** - * @param {character[][]} grid - * @return {number} - */ -const minPushBox = function (grid) { - if ( - typeof grid === 'undefined' || - grid === null || - grid.length === 0 || - grid[0].length === 0 - ) { - return -1 - } - - let TARGET = null - let startBlk = null - let startPer = null - const DIR = [ - [0, 1], - [1, 0], - [0, -1], - [-1, 0], - ] - - for (let i = 0; i < grid.length; i++) { - for (let j = 0; j < grid[0].length; j++) { - if (grid[i][j] === 'S') { - startPer = [i, j] - grid[i][j] = '.' - } - if (grid[i][j] === 'T') { - TARGET = [i, j] - } - if (grid[i][j] === 'B') { - startBlk = [i, j] - grid[i][j] = '.' - } - } - } - - let queue = new PriorityQueue((a, b) => a.weight < b.weight) - let states = new Map() - queue.push({ - weight: manDist(startBlk), - block: startBlk, - character: startPer, - move: 0, - }) - while (!queue.isEmpty()) { - let { weight, block, character, move } = queue.pop() - if (TARGET[0] === block[0] && TARGET[1] === block[1]) { - return move - } - let key = block[0] * grid[0].length + block[1] - let val = character[0] * grid[0].length + character[1] - if (!states.has(key)) { - states.set(key, new Set()) - } - states.get(key).add(val) - DIR.forEach((d) => { - let i = d[0] + character[0] - let j = d[1] + character[1] - let curV = i * grid[0].length + j - if (validMove(i, j, block[0], block[1]) && !states.get(key).has(curV)) { - queue.push({ - weight: manDist(block) + move, - block: block, - character: [i, j], - move: move, - }) - } - }) - let pushDir = tryPush(character, block) - if (pushDir !== null) { - let newBlk = [block[0] + pushDir[0], block[1] + pushDir[1]] - let newCha = [character[0] + pushDir[0], character[1] + pushDir[1]] - let nBK = newBlk[0] * grid[0].length + newBlk[1] - let nVal = newCha[0] * grid[0].length + newCha[1] - if (!states.has(nBK) || !states.get(nBK).has(nVal)) { - queue.push({ - weight: manDist(newBlk) + (move + 1), - block: newBlk, - character: newCha, - move: move + 1, - }) - } - } - } - - return -1 - - function manDist(block) { - let [x, y] = TARGET - let [i, j] = block - return Math.abs(x - i) + Math.abs(y - j) - } - function validMove(i, j, x = null, y = null) { - if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length) { - return false - } - if ( - (x !== null && i === x && y !== null && j === y) || - grid[i][j] === '#' - ) { - return false - } - return true - } - function tryPush(c, b) { - let [i, j] = c - let [x, y] = b - for (let u = 0; u < DIR.length; u++) { - let [v, w] = DIR[u] - if ( - ((Math.abs(x - i) === 1 && y === j) || - (Math.abs(y - j) === 1 && x === i)) && - validMove(i + v, j + w) && - validMove(x + v, y + w) && - i + v === x && - j + w === y - ) { - return [v, w] - } - } - return null - } -} -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -/** - * @param {character[][]} grid - * @return {number} - */ -const minPushBox = function (grid) { - const dirs = [ - [-1, 0], - [1, 0], - [0, -1], - [0, 1], - ] - const dis = new Map() - const rows = grid.length - const cols = grid[0].length - let sk, box, target - for (let i = 0; i < rows; i++) { - for (let j = 0; j < cols; j++) { - if (grid[i][j] === 'B') box = [i, j] - else if (grid[i][j] === 'S') sk = [i, j] - else if (grid[i][j] === 'T') target = [i, j] - } - } - const q = [] - const start = encode(box[0], box[1], sk[0], sk[1]) - dis.set(start, 0) - q.push(start) - let res = Number.MAX_VALUE - while (q.length) { - const u = q.pop() - const du = decode(u) - if (dis.get(u) >= res) continue - if (du[0] === target[0] && du[1] === target[1]) { - res = Math.min(res, dis.get(u)) - continue - } - const b = [du[0], du[1]] - const s = [du[2], du[3]] - for (let dir of dirs) { - const nsx = s[0] + dir[0] - const nsy = s[1] + dir[1] - if ( - nsx < 0 || - nsx >= rows || - nsy < 0 || - nsy >= cols || - grid[nsx][nsy] === '#' - ) - continue - if (nsx === b[0] && nsy === b[1]) { - const nbx = b[0] + dir[0] - const nby = b[1] + dir[1] - if ( - nbx < 0 || - nbx >= rows || - nby < 0 || - nby >= cols || - grid[nbx][nby] === '#' - ) - continue - const v = encode(nbx, nby, nsx, nsy) - if (dis.has(v) && dis.get(v) <= dis.get(u) + 1) continue - dis.set(v, dis.get(u) + 1) - q.push(v) - } else { - const v = encode(b[0], b[1], nsx, nsy) - if (dis.has(v) && dis.get(v) <= dis.get(u)) continue - dis.set(v, dis.get(u)) - q.push(v) - } - } - } - return res === Number.MAX_VALUE ? -1 : res - - function encode(bx, by, sx, sy) { - return (bx << 24) | (by << 16) | (sx << 8) | sy - } - function decode(num) { - const res = [] - res[0] = (num >>> 24) & 0xff - res[1] = (num >>> 16) & 0xff - res[2] = (num >>> 8) & 0xff - res[3] = num & 0xff - return res - } -} - -// another - -/** - * @param {character[][]} grid - * @return {number} - */ - const minPushBox = function (grid) { - const m = grid.length, - n = grid[0].length - let target, person, box - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - if (grid[i][j] === 'T') target = [i, j] - else if (grid[i][j] === 'B') box = [i, j] - else if (grid[i][j] === 'S') person = [i, j] - } - } - - const valid = ([x, y]) => { - return x >= 0 && x < m && y >= 0 && y < n && grid[x][y] !== '#' - } - - const check = (cur, dest, box) => { - const q = [cur] - const visited = new Set([`${box[0]},${box[1]}`]) - const dirs = [ - [-1, 0], - [1, 0], - [0, 1], - [0, -1], - ] - - while (q.length) { - const pos = q.shift() - if (pos.join(',') === dest.join(',')) return true - const newPos = [] - for (const [dx, dy] of dirs) newPos.push([pos[0] + dx, pos[1] + dy]) - for (const [nx, ny] of newPos) { - const k = `${nx},${ny}` - if (valid([nx, ny]) && !visited.has(k)) { - visited.add(k) - q.push([nx, ny]) - } - } - } - - return false - } - - const q = [[0, box, person]] - const vis = new Set([`${box.join(',')},${person.join(',')}`]) - while (q.length) { - const [dist, box, person] = q.shift() - if (box.join(',') === target.join(',')) return dist - - const bCoord = [ - [box[0] + 1, box[1]], - [box[0] - 1, box[1]], - [box[0], box[1] + 1], - [box[0], box[1] - 1], - ] - const pCoord = [ - [box[0] - 1, box[1]], - [box[0] + 1, box[1]], - [box[0], box[1] - 1], - [box[0], box[1] + 1], - ] - - for (let i = 0; i < 4; i++) { - const [newBox, newPerson] = [bCoord[i], pCoord[i]] - const key = `${newBox.join(',')},${box.join(',')}` - if (valid(newBox) && !vis.has(key)) { - if (valid(newPerson) && check(person, newPerson, box)) { - vis.add(key) - q.push([dist + 1, newBox, box]) - } - } - } - } - - return -1 -} - diff --git a/1263.minimum-moves-to-move-a-box-to-their-target-location.js b/1263.minimum-moves-to-move-a-box-to-their-target-location.js new file mode 100644 index 00000000..89a210b5 --- /dev/null +++ b/1263.minimum-moves-to-move-a-box-to-their-target-location.js @@ -0,0 +1,93 @@ +/** + * @param {character[][]} grid + * @return {number} + */ +const minPushBox = function (grid) { + let box, person, target + const m = grid.length, + n = grid[0].length + const dirs = [ + [-1, 0], + [1, 0], + [0, -1], + [0, 1], + ] + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + const e = grid[i][j] + if (e === 'B') box = [i, j] + else if (e === 'T') target = [i, j] + else if (e === 'S') person = [i, j] + } + } + + const valid = ([i, j]) => { + return i >= 0 && i < m && j >= 0 && j < n && grid[i][j] !== '#' + } + const key = ([i, j]) => `${i},${j}` + + const chk = (person, newPerson, box) => { + const set = new Set() + set.add(key(box)) + let q = [person] + while (q.length) { + const tmp = [] + const size = q.length + for (let i = 0; i < size; i++) { + const [x, y] = q[i] + if (key([x, y]) === key(newPerson)) return true + for (const [dx, dy] of dirs) { + const [nx, ny] = [x + dx, y + dy] + if (valid([nx, ny]) && !set.has(key([nx, ny]))) { + set.add(key([nx, ny])) + tmp.push([nx, ny]) + } + } + } + q = tmp + } + return false + } + + + let q = [[0, box, person]] + const dkey = (a, b) => `${a[0]},${a[1]}_${b[0]},${b[1]}` + const set = new Set() + set.add(dkey(box, person)) + while (q.length) { + const size = q.length + const tmp = [] + for (let i = 0; i < size; i++) { + const [v, b, p] = q[i] + if (key(b) === key(target)) return v + const bArr = [ + [b[0], b[1] + 1], + [b[0], b[1] - 1], + [b[0] + 1, b[1]], + [b[0] - 1, b[1]], + ] + const pArr = [ + [b[0], b[1] - 1], + [b[0], b[1] + 1], + [b[0] - 1, b[1]], + [b[0] + 1, b[1]], + ] + + for (let j = 0; j < 4; j++) { + const nb = bArr[j], + np = pArr[j] + const nk = dkey(nb, b) + + if (set.has(nk)) continue + if (valid(nb) && valid(np) && chk(p, np, b)) { + tmp.push([v + 1, nb, b]) + set.add(nk) + } + } + } + q = tmp + } + + return -1 +} + diff --git a/1265-print-immutable-linked-list-in-reverse.js b/1265.print-immutable-linked-list-in-reverse.js similarity index 100% rename from 1265-print-immutable-linked-list-in-reverse.js rename to 1265.print-immutable-linked-list-in-reverse.js diff --git a/1266-minimum-time-visiting-all-points.js b/1266.minimum-time-visiting-all-points.js similarity index 100% rename from 1266-minimum-time-visiting-all-points.js rename to 1266.minimum-time-visiting-all-points.js diff --git a/1268-search-suggestions-system.js b/1268-search-suggestions-system.js deleted file mode 100644 index 2e8ea666..00000000 --- a/1268-search-suggestions-system.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @param {string[]} products - * @param {string} searchWord - * @return {string[][]} - */ -const suggestedProducts = function(products, searchWord) { - products.sort() - let res = [], left = 0, right = products.length - 1 - for (let i = 0; i < searchWord.length; i++) { - let c = searchWord.charAt(i), tmp = [] - while (products[left]?.charAt(i) < c) left++ - while (products[right]?.charAt(i) > c) right-- - for (let j = 0; j < 3 && left + j <= right; j++) tmp.push(products[left+j]) - res.push(tmp) - } - return res -}; - -// another - -/** - * @param {string[]} products - * @param {string} searchWord - * @return {string[][]} - */ -const suggestedProducts = function(products, searchWord) { - const res = [] - for(let i = 0, n = searchWord.length; i < n; i++) { - const tmp = [], pre = searchWord.slice(0, i + 1) - for(const e of products) { - if(e.startsWith(pre)) { - tmp.push(e) - tmp.sort((a, b) => a.localeCompare(b)) - if(tmp.length > 3) tmp.pop() - } - } - res.push(tmp) - } - return res -}; - -// another - -/** - * @param {string[]} products - * @param {string} searchWord - * @return {string[][]} - */ - const suggestedProducts = function (products, searchWord) { - products.sort() - const root = new Node() - for (const str of products) { - addProduct(str) - } - - const res = [] - - let cur = root - for (const ch of searchWord) { - const tmp = [] - if (cur == null) { - res.push(tmp) - continue - } - const map = cur.children.get(ch) - if (map != null) { - addThree(map.words.values(), tmp) - } - - res.push(tmp) - cur = map - } - - return res - - function addThree(it, arr) { - - for(let i = 0; i < 3; i++) { - const res = it.next() - if(res.value) arr.push(res.value) - } - } - - function addProduct(str) { - let cur = root - for (const ch of str) { - let next = cur.children.get(ch) - if (next == null) { - next = new Node() - cur.children.set(ch, next) - } - next.words.add(str) - cur = next - } - cur.isWord = true - } -} - -class Node { - constructor() { - this.children = new Map() - this.words = new Set() - this.isWord = false - } -} - diff --git a/1268.search-suggestions-system.js b/1268.search-suggestions-system.js new file mode 100644 index 00000000..3db20ab7 --- /dev/null +++ b/1268.search-suggestions-system.js @@ -0,0 +1,18 @@ +/** + * @param {string[]} products + * @param {string} searchWord + * @return {string[][]} + */ +const suggestedProducts = function(products, searchWord) { + products.sort() + let res = [], left = 0, right = products.length - 1 + for (let i = 0; i < searchWord.length; i++) { + let c = searchWord.charAt(i), tmp = [] + while (products[left]?.charAt(i) < c) left++ + while (products[right]?.charAt(i) > c) right-- + for (let j = 0; j < 3 && left + j <= right; j++) tmp.push(products[left+j]) + res.push(tmp) + } + return res +}; + diff --git a/1269-number-of-ways-to-stay-in-the-same-place-after-some-steps.js b/1269.number-of-ways-to-stay-in-the-same-place-after-some-steps.js similarity index 100% rename from 1269-number-of-ways-to-stay-in-the-same-place-after-some-steps.js rename to 1269.number-of-ways-to-stay-in-the-same-place-after-some-steps.js diff --git a/127-word-ladder.js b/127.word-ladder.js similarity index 100% rename from 127-word-ladder.js rename to 127.word-ladder.js diff --git a/1271-hexspeak.js b/1271.hexspeak.js similarity index 100% rename from 1271-hexspeak.js rename to 1271.hexspeak.js diff --git a/1272-remove-interval.js b/1272.remove-interval.js similarity index 100% rename from 1272-remove-interval.js rename to 1272.remove-interval.js diff --git a/1273-delete-tree-nodes.js b/1273.delete-tree-nodes.js similarity index 100% rename from 1273-delete-tree-nodes.js rename to 1273.delete-tree-nodes.js diff --git a/1274-number-of-ships-in-a-rectangle.js b/1274.number-of-ships-in-a-rectangle.js similarity index 100% rename from 1274-number-of-ships-in-a-rectangle.js rename to 1274.number-of-ships-in-a-rectangle.js diff --git a/1275-find-winner-on-a-tic-tac-toe-game.js b/1275-find-winner-on-a-tic-tac-toe-game.js deleted file mode 100644 index d6029d14..00000000 --- a/1275-find-winner-on-a-tic-tac-toe-game.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @param {number[][]} moves - * @return {string} - */ -const tictactoe = function(moves) { - const grid = Array.from({ length: 3 }, () => Array(3).fill('')) - for(let i = 0, n = moves.length; i < n; i++) { - const ch = i % 2 === 0 ? 'X' : 'O' - const [r, c] = moves[i] - grid[r][c] = ch - const res = chk(ch, grid) - if(res) return ch === 'X' ? 'A' : 'B' - } - - return moves.length < 9 ? 'Pending' : 'Draw' -}; - -function chk(ch, grid) { - for(let i = 0; i < 3; i++) { - if( - grid[i][0] === ch && - grid[i][1] === ch && - grid[i][2] === ch - ) return true - } - - for(let i = 0; i < 3; i++) { - if( - grid[0][i] === ch && - grid[1][i] === ch && - grid[2][i] === ch - ) return true - } - - - if( - grid[0][0] === ch && - grid[1][1] === ch && - grid[2][2] === ch - ) return true - - if( - grid[0][2] === ch && - grid[1][1] === ch && - grid[2][0] === ch - ) return true - - return false -} - -// another - -/** - * @param {number[][]} moves - * @return {string} - */ -const tictactoe = function(moves) { - const aRow = Array(3).fill(0), aCol = Array(3).fill(0), bRow= Array(3).fill(0), bCol =Array(3).fill(0) - let ad = 0, ads = 0, bd = 0, bds = 0 - for(let i = 0; i < moves.length; i++) { - const [r, c] = moves[i] - if(i % 2===0) { - if(++aRow[r] === 3 || ++aCol[c] === 3 || r === c && ++ad === 3 || r + c === 2&& ++ads === 3 ) return 'A' - }else { - if(++bRow[r] === 3 || ++bCol[c] === 3 || r === c && ++bd === 3 || r + c === 2&& ++bds === 3 ) return 'B' - } - } - - return moves.length >= 9 ? 'Draw' : 'Pending' -}; diff --git a/1275.find-winner-on-a-tic-tac-toe-game.js b/1275.find-winner-on-a-tic-tac-toe-game.js new file mode 100644 index 00000000..dba6032a --- /dev/null +++ b/1275.find-winner-on-a-tic-tac-toe-game.js @@ -0,0 +1,50 @@ +/** + * @param {number[][]} moves + * @return {string} + */ +const tictactoe = function(moves) { + const grid = Array.from({ length: 3 }, () => Array(3).fill('')) + for(let i = 0, n = moves.length; i < n; i++) { + const ch = i % 2 === 0 ? 'X' : 'O' + const [r, c] = moves[i] + grid[r][c] = ch + const res = chk(ch, grid) + if(res) return ch === 'X' ? 'A' : 'B' + } + + return moves.length < 9 ? 'Pending' : 'Draw' +}; + +function chk(ch, grid) { + for(let i = 0; i < 3; i++) { + if( + grid[i][0] === ch && + grid[i][1] === ch && + grid[i][2] === ch + ) return true + } + + for(let i = 0; i < 3; i++) { + if( + grid[0][i] === ch && + grid[1][i] === ch && + grid[2][i] === ch + ) return true + } + + + if( + grid[0][0] === ch && + grid[1][1] === ch && + grid[2][2] === ch + ) return true + + if( + grid[0][2] === ch && + grid[1][1] === ch && + grid[2][0] === ch + ) return true + + return false +} + diff --git a/1277-count-square-submatrices-with-all-ones.js b/1277-count-square-submatrices-with-all-ones.js deleted file mode 100644 index 61494fcb..00000000 --- a/1277-count-square-submatrices-with-all-ones.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @param {number[][]} matrix - * @return {number} - */ -const countSquares = function (matrix) { - const [m, n] = [matrix.length, matrix[0].length] - let res = 0 - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - if(matrix[i][j] && i > 0 && j > 0) { - matrix[i][j] = 1 + Math.min( - matrix[i - 1][j], - matrix[i][j - 1], - matrix[i - 1][j - 1], - ) - } - res += matrix[i][j] - } - } - return res -} - -// another - -/** - * @param {number[][]} matrix - * @return {number} - */ -const countSquares = function (A) { - const [M, N] = [A.length, A[0].length] - let ans = 0 - for (let i = 0; i < M; ++i) { - for (let j = 0; j < N; ++j) { - if (A[i][j] && i > 0 && j > 0) { - A[i][j] = 1 + Math.min(A[i - 1][j], A[i][j - 1], A[i - 1][j - 1]) - } - ans += A[i][j] - } - } - return ans -} diff --git a/1277.count-square-submatrices-with-all-ones.js b/1277.count-square-submatrices-with-all-ones.js new file mode 100644 index 00000000..2a792cf7 --- /dev/null +++ b/1277.count-square-submatrices-with-all-ones.js @@ -0,0 +1,22 @@ +/** + * @param {number[][]} matrix + * @return {number} + */ +const countSquares = function (matrix) { + const [m, n] = [matrix.length, matrix[0].length] + let res = 0 + for(let i = 0; i < m; i++) { + for(let j = 0; j < n; j++) { + if(matrix[i][j] && i > 0 && j > 0) { + matrix[i][j] = 1 + Math.min( + matrix[i - 1][j], + matrix[i][j - 1], + matrix[i - 1][j - 1], + ) + } + res += matrix[i][j] + } + } + return res +} + diff --git a/1278-palindrome-partitioning-iii.js b/1278.palindrome-partitioning-iii.js similarity index 100% rename from 1278-palindrome-partitioning-iii.js rename to 1278.palindrome-partitioning-iii.js diff --git a/128-longest-consecutive-sequence.js b/128.longest-consecutive-sequence.js similarity index 100% rename from 128-longest-consecutive-sequence.js rename to 128.longest-consecutive-sequence.js diff --git a/1281-subtract-the-product-and-sum-of-digits-of-an-integer.js b/1281.subtract-the-product-and-sum-of-digits-of-an-integer.js similarity index 100% rename from 1281-subtract-the-product-and-sum-of-digits-of-an-integer.js rename to 1281.subtract-the-product-and-sum-of-digits-of-an-integer.js diff --git a/1282-group-the-people-given-the-group-size-they-belong-to.js b/1282.group-the-people-given-the-group-size-they-belong-to.js similarity index 100% rename from 1282-group-the-people-given-the-group-size-they-belong-to.js rename to 1282.group-the-people-given-the-group-size-they-belong-to.js diff --git a/1283-find-the-smallest-divisor-given-a-threshold.js b/1283.find-the-smallest-divisor-given-a-threshold.js similarity index 100% rename from 1283-find-the-smallest-divisor-given-a-threshold.js rename to 1283.find-the-smallest-divisor-given-a-threshold.js diff --git a/1284-minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.js b/1284-minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.js deleted file mode 100644 index a79ab5e6..00000000 --- a/1284-minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @param {number[][]} mat - * @return {number} - */ -const minFlips = function (mat) { - let start = 0 - const m = mat.length, n = mat[0].length - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - start |= mat[i][j] << (i * n + j) - } - } - let q = [start] - const seen = new Set(), dirs = [[-1, 0], [1, 0], [0, -1], [0, 1], [0, 0]] - - for(let i = 0; q.length; i++) { - const tmp = [] - for (let size = q.length; size > 0; size--) { - const cur = q.pop() - if(cur === 0) return i - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - let next = cur - for(const [dx, dy] of dirs) { - const r = i + dx, c = j + dy - if(r >= 0 && r < m && c >= 0 && c < n) { - next ^= (1 << (r * n + c)) - } - } - if (!seen.has(next)) { - seen.add(next) - tmp.push(next) - } - } - } - } - q = tmp - } - - return -1 -} - -// another - -/** - * @param {number[][]} mat - * @return {number} - */ -const minFlips = function (mat) { - const X = mat.length - const Y = mat[0].length - const binary = { - 0: 1, - 1: 2, - 2: 4, - 3: 8, - 4: 16, - 5: 32, - 6: 64, - 7: 128, - 8: 256, - } - const mask = [] - let state = 0 - for (let i = 0; i < X; ++i) { - for (let j = 0; j < Y; ++j) { - let bit = 0 - state += mat[i][j] * binary[Y * i + j] - bit += binary[Y * i + j] - if (i > 0) { - bit += binary[Y * (i - 1) + j] - } - if (i < X - 1) { - bit += binary[Y * (i + 1) + j] - } - if (j > 0) { - bit += binary[Y * i + (j - 1)] - } - if (j < Y - 1) { - bit += binary[Y * i + (j + 1)] - } - mask.push(bit) - } - } - if (state === 0) return 0 - const set = new Set() - const q = [{ state: state, moves: 0 }] - while (q.length !== 0) { - const cur = q.shift() - if (cur.state === 0) { - return cur.moves - } - for (let i = 0; i < X * Y; ++i) { - let newState = cur.state - newState ^= mask[i] - if (!set.has(newState)) { - set.add(newState) - q.push({ state: newState, moves: cur.moves + 1 }) - } - } - } - return -1 -} diff --git a/1284.minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.js b/1284.minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.js new file mode 100644 index 00000000..8d2a3fdf --- /dev/null +++ b/1284.minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.js @@ -0,0 +1,42 @@ +/** + * @param {number[][]} mat + * @return {number} + */ +const minFlips = function (mat) { + let start = 0 + const m = mat.length, n = mat[0].length + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + start |= mat[i][j] << (i * n + j) + } + } + let q = [start] + const seen = new Set(), dirs = [[-1, 0], [1, 0], [0, -1], [0, 1], [0, 0]] + + for(let i = 0; q.length; i++) { + const tmp = [] + for (let size = q.length; size > 0; size--) { + const cur = q.pop() + if(cur === 0) return i + for(let i = 0; i < m; i++) { + for(let j = 0; j < n; j++) { + let next = cur + for(const [dx, dy] of dirs) { + const r = i + dx, c = j + dy + if(r >= 0 && r < m && c >= 0 && c < n) { + next ^= (1 << (r * n + c)) + } + } + if (!seen.has(next)) { + seen.add(next) + tmp.push(next) + } + } + } + } + q = tmp + } + + return -1 +} + diff --git a/1286-iterator-for-combination.js b/1286-iterator-for-combination.js deleted file mode 100644 index 314526bf..00000000 --- a/1286-iterator-for-combination.js +++ /dev/null @@ -1,148 +0,0 @@ -/** - * @param {string} characters - * @param {number} combinationLength - */ -const CombinationIterator = function (characters, combinationLength) { - this.arr = build(combinationLength, characters.split('').sort().join('')) - this.pos = 0 -} - -/** - * @return {string} - */ -CombinationIterator.prototype.next = function () { - if (this.pos < this.arr.length) { - return this.arr[this.pos++] - } -} - -/** - * @return {boolean} - */ -CombinationIterator.prototype.hasNext = function () { - return this.pos < this.arr.length -} - -/** - * Your CombinationIterator object will be instantiated and called as such: - * var obj = new CombinationIterator(characters, combinationLength) - * var param_1 = obj.next() - * var param_2 = obj.hasNext() - */ -function build(max, str, out = [], curr = '') { - if (curr.length === max) { - out.push(curr) - return - } else { - for (let i = 0; i < str.length; i++) { - build(max, str.slice(i + 1), out, curr + str[i]) - } - } - - return out -} - -// another - -/** - * @param {string} characters - * @param {number} combinationLength - */ -const CombinationIterator = function(characters, combinationLength) { - const res = [], len = combinationLength, str = characters, n = str.length - helper([], 0) - this.arr = res - this.idx = 0 - - function helper(cur, idx) { - if(cur.length === len) { - res.push(cur.slice().join('')) - return - } - if(idx >= n) return - - cur.push(str[idx]) - helper(cur, idx + 1) - cur.pop() - - helper(cur, idx + 1) - } -}; - -/** - * @return {string} - */ -CombinationIterator.prototype.next = function() { - if(this.hasNext()) { - return this.arr[this.idx++] - } -}; - -/** - * @return {boolean} - */ -CombinationIterator.prototype.hasNext = function() { - return this.arr[this.idx] != null -}; - -/** - * Your CombinationIterator object will be instantiated and called as such: - * var obj = new CombinationIterator(characters, combinationLength) - * var param_1 = obj.next() - * var param_2 = obj.hasNext() - */ - -// another - -/** - * @param {string} characters - * @param {number} combinationLength - */ -const CombinationIterator = function(characters, combinationLength) { - const res = [], len = combinationLength, str = characters, n = str.length - helper() - - // console.log(res) - this.arr = res - this.idx = 0 - - function helper() { - const limit = 1 << n - for(let i = limit - 1; i > 0; i--) { - let tmp = i, ts = '', idx = n - 1 - while(tmp) { - if(tmp & 1) { - ts = str[idx] + ts - } - idx-- - tmp = (tmp >> 1) - } - if(ts.length === len) res.push(ts) - } - } -}; - -/** - * @return {string} - */ -CombinationIterator.prototype.next = function() { - if(this.hasNext()) { - return this.arr[this.idx++] - } -}; - -/** - * @return {boolean} - */ -CombinationIterator.prototype.hasNext = function() { - return this.arr[this.idx] != null -}; - -/** - * Your CombinationIterator object will be instantiated and called as such: - * var obj = new CombinationIterator(characters, combinationLength) - * var param_1 = obj.next() - * var param_2 = obj.hasNext() - */ - - diff --git a/1286.iterator-for-combination.js b/1286.iterator-for-combination.js new file mode 100644 index 00000000..784039cb --- /dev/null +++ b/1286.iterator-for-combination.js @@ -0,0 +1,44 @@ +/** + * @param {string} characters + * @param {number} combinationLength + */ +const CombinationIterator = function (characters, combinationLength) { + this.arr = build(combinationLength, characters.split('').sort().join('')) + this.pos = 0 +} + +/** + * @return {string} + */ +CombinationIterator.prototype.next = function () { + if (this.pos < this.arr.length) { + return this.arr[this.pos++] + } +} + +/** + * @return {boolean} + */ +CombinationIterator.prototype.hasNext = function () { + return this.pos < this.arr.length +} + +/** + * Your CombinationIterator object will be instantiated and called as such: + * var obj = new CombinationIterator(characters, combinationLength) + * var param_1 = obj.next() + * var param_2 = obj.hasNext() + */ +function build(max, str, out = [], curr = '') { + if (curr.length === max) { + out.push(curr) + return + } else { + for (let i = 0; i < str.length; i++) { + build(max, str.slice(i + 1), out, curr + str[i]) + } + } + + return out +} + diff --git a/1287-element-appearing-more-than-25-in-sorted-array.js b/1287.element-appearing-more-than-25-in-sorted-array.js similarity index 100% rename from 1287-element-appearing-more-than-25-in-sorted-array.js rename to 1287.element-appearing-more-than-25-in-sorted-array.js diff --git a/1288-remove-covered-intervals.js b/1288.remove-covered-intervals.js similarity index 100% rename from 1288-remove-covered-intervals.js rename to 1288.remove-covered-intervals.js diff --git a/1289-minimum-falling-path-sum-ii.js b/1289.minimum-falling-path-sum-ii.js similarity index 100% rename from 1289-minimum-falling-path-sum-ii.js rename to 1289.minimum-falling-path-sum-ii.js diff --git a/129-sum-root-to-leaf-numbers.js b/129.sum-root-to-leaf-numbers.js similarity index 100% rename from 129-sum-root-to-leaf-numbers.js rename to 129.sum-root-to-leaf-numbers.js diff --git a/1290-convert-binary-number-in-a-linked-list-to-integer.js b/1290.convert-binary-number-in-a-linked-list-to-integer.js similarity index 100% rename from 1290-convert-binary-number-in-a-linked-list-to-integer.js rename to 1290.convert-binary-number-in-a-linked-list-to-integer.js diff --git a/1291-sequential-digits.js b/1291-sequential-digits.js deleted file mode 100644 index 3cd7049b..00000000 --- a/1291-sequential-digits.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @param {number} low - * @param {number} high - * @return {number[]} - */ -const sequentialDigits = function(low, high) { - const res = [] - - let q = [] - for(let i = 1; i <= 9; i++) q.push(i) - - while(q.length) { - const tmp = [] - const size = q.length - for(let i = 0; i < size; i++) { - const cur = q[i] - if(cur >= low && cur <= high) { - res.push(cur) - } - if(cur > high) break - const last = cur % 10 - if(last === 9) continue - tmp.push(cur * 10 + last + 1) - } - - q = tmp - } - - return res -}; - -// another - -/** - * @param {number} low - * @param {number} high - * @return {number[]} - */ -const sequentialDigits = function(low, high) { - const set = new Set() - let start = 0, end = 0 - for(let i = 10; i >= 0; i--) { - if (low / (10 ** i) >= 1) { - start = ~~(low / (10 ** i)) - break - } - } - for(let i = 10; i >= 0; i--) { - if (high / (10 ** i) >= 1) { - end = ~~(high / (10 ** i)) - break - } - } - for(let i = 1; i <= 9; i++) { - helper(`${i}`) - } - - const res = Array.from(set) - res.sort((a, b) => a- b) - return res - - function helper(s) { - // console.log(s) - if(+s > high) return - if(+s >= low && +s <= high) { - set.add(+s) - } - if(s[s.length - 1] === '9') return - helper(`${s}${+s[s.length - 1] + 1}`) - } -}; diff --git a/1291.sequential-digits.js b/1291.sequential-digits.js new file mode 100644 index 00000000..c8ee3ae6 --- /dev/null +++ b/1291.sequential-digits.js @@ -0,0 +1,31 @@ +/** + * @param {number} low + * @param {number} high + * @return {number[]} + */ +const sequentialDigits = function(low, high) { + const res = [] + + let q = [] + for(let i = 1; i <= 9; i++) q.push(i) + + while(q.length) { + const tmp = [] + const size = q.length + for(let i = 0; i < size; i++) { + const cur = q[i] + if(cur >= low && cur <= high) { + res.push(cur) + } + if(cur > high) break + const last = cur % 10 + if(last === 9) continue + tmp.push(cur * 10 + last + 1) + } + + q = tmp + } + + return res +}; + diff --git a/1292-maximum-side-length-of-a-square-with-sum-less-than-or-equal-to-threshold.js b/1292.maximum-side-length-of-a-square-with-sum-less-than-or-equal-to-threshold.js similarity index 100% rename from 1292-maximum-side-length-of-a-square-with-sum-less-than-or-equal-to-threshold.js rename to 1292.maximum-side-length-of-a-square-with-sum-less-than-or-equal-to-threshold.js diff --git a/1293-shortest-path-in-a-grid-with-obstacles-elimination.js b/1293.shortest-path-in-a-grid-with-obstacles-elimination.js similarity index 100% rename from 1293-shortest-path-in-a-grid-with-obstacles-elimination.js rename to 1293.shortest-path-in-a-grid-with-obstacles-elimination.js diff --git a/1295-find-numbers-with-even-number-of-digits.js b/1295.find-numbers-with-even-number-of-digits.js similarity index 100% rename from 1295-find-numbers-with-even-number-of-digits.js rename to 1295.find-numbers-with-even-number-of-digits.js diff --git a/1299-replace-elements-with-greatest-element-on-right-side.js b/1299.replace-elements-with-greatest-element-on-right-side.js similarity index 100% rename from 1299-replace-elements-with-greatest-element-on-right-side.js rename to 1299.replace-elements-with-greatest-element-on-right-side.js diff --git a/13-roman-to-integer.js b/13-roman-to-integer.js deleted file mode 100644 index b3dd3be3..00000000 --- a/13-roman-to-integer.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const romanToInt = function(s) { - let res = 0 - for (let i = s.length - 1; i >= 0; i--) { - let c = s.charAt(i) - switch (c) { - case 'I': - res += res >= 5 ? -1 : 1 - break - case 'V': - res += 5 - break - case 'X': - res += 10 * (res >= 50 ? -1 : 1) - break - case 'L': - res += 50 - break - case 'C': - res += 100 * (res >= 500 ? -1 : 1) - break - case 'D': - res += 500 - break - case 'M': - res += 1000 - break - } - } - return res -} - - -// another - -/** - * @param {string} s - * @return {number} - */ -const romanToInt = function(s) { - const map = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 } - let result = 0 - let index = s.length - 1 - let preInt = 0 - while (index >= 0) { - let ch = s[index] - let curInt = map[ch] - if (curInt >= preInt) result += curInt - else result -= curInt - preInt = curInt - index-- - } - return result -} diff --git a/13.roman-to-integer.js b/13.roman-to-integer.js new file mode 100644 index 00000000..0a29c3c2 --- /dev/null +++ b/13.roman-to-integer.js @@ -0,0 +1,36 @@ +/** + * @param {string} s + * @return {number} + */ +const romanToInt = function(s) { + let res = 0 + for (let i = s.length - 1; i >= 0; i--) { + let c = s.charAt(i) + switch (c) { + case 'I': + res += res >= 5 ? -1 : 1 + break + case 'V': + res += 5 + break + case 'X': + res += 10 * (res >= 50 ? -1 : 1) + break + case 'L': + res += 50 + break + case 'C': + res += 100 * (res >= 500 ? -1 : 1) + break + case 'D': + res += 500 + break + case 'M': + res += 1000 + break + } + } + return res +} + + diff --git a/130-surrounded-regions.js b/130-surrounded-regions.js deleted file mode 100644 index 619240b1..00000000 --- a/130-surrounded-regions.js +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @param {character[][]} board - * @return {void} Do not return anything, modify board in-place instead. - */ -const solve = function(board) { - if (!board || board.length < 3 || board[0].length < 3) return; - let r = board.length; - let c = board[0].length; - for (let i = 0; i < c; i++) { - if (board[0][i] === "O") search(board, 0, i); - if (board[r - 1][i] === "O") search(board, r - 1, i); - } - for (let i = 0; i < r; i++) { - if (board[i][0] === "O") search(board, i, 0); - if (board[i][c - 1] === "O") search(board, i, c - 1); - } - for (let i = 0; i < r; i++) { - for (let j = 0; j < c; j++) { - if (board[i][j] === "O") board[i][j] = "X"; - if (board[i][j] === "*") board[i][j] = "O"; - } - } -}; - -function search(board, i, j) { - if (i < 0 || j < 0 || i >= board.length || j >= board[0].length) return; - if (board[i][j] !== "O") return; - board[i][j] = "*"; - search(board, i + 1, j); - search(board, i - 1, j); - search(board, i, j + 1); - search(board, i, j - 1); -} - -// another - -/** - * @param {character[][]} board - * @return {void} Do not return anything, modify board in-place instead. - */ -const solve = (board) => { - if (!board || board.length === 0 || board[0].length === 0) return; - const n = board.length; - const m = board[0].length; - const dirs = [ - [-1, 0], - [1, 0], - [0, -1], - [0, 1], - ]; - const bfs = (board, n, m, i, j) => { - const queue = []; - queue.push([i, j]); - board[i][j] = "1"; - while (queue.length > 0) { - const pos = queue.shift(); - for (let k = 0; k < 4; k++) { - i = pos[0] + dirs[k][0]; - j = pos[1] + dirs[k][1]; - if (i >= 0 && i < n && j >= 0 && j < m && board[i][j] === "O") { - board[i][j] = "1"; - queue.push([i, j]); - } - } - } - }; - // scan the borders and mark the 'O's to '1' - for (let i = 0; i < n; i++) { - for (let j = 0; j < m; j++) { - if ( - (i === 0 || i === n - 1 || j === 0 || j === m - 1) && - board[i][j] === "O" - ) { - bfs(board, n, m, i, j); - } - } - } - // scan the inner area and mark the 'O's to 'X' - for (let i = 1; i < n; i++) { - for (let j = 1; j < m; j++) { - if (board[i][j] === "O") { - board[i][j] = "X"; - } - } - } - // reset all the '1's to 'O's - for (let i = 0; i < n; i++) { - for (let j = 0; j < m; j++) { - if (board[i][j] === "1") { - board[i][j] = "O"; - } - } - } -}; diff --git a/130.surrounded-regions.js b/130.surrounded-regions.js new file mode 100644 index 00000000..20c4187b --- /dev/null +++ b/130.surrounded-regions.js @@ -0,0 +1,34 @@ +/** + * @param {character[][]} board + * @return {void} Do not return anything, modify board in-place instead. + */ +const solve = function(board) { + if (!board || board.length < 3 || board[0].length < 3) return; + let r = board.length; + let c = board[0].length; + for (let i = 0; i < c; i++) { + if (board[0][i] === "O") search(board, 0, i); + if (board[r - 1][i] === "O") search(board, r - 1, i); + } + for (let i = 0; i < r; i++) { + if (board[i][0] === "O") search(board, i, 0); + if (board[i][c - 1] === "O") search(board, i, c - 1); + } + for (let i = 0; i < r; i++) { + for (let j = 0; j < c; j++) { + if (board[i][j] === "O") board[i][j] = "X"; + if (board[i][j] === "*") board[i][j] = "O"; + } + } +}; + +function search(board, i, j) { + if (i < 0 || j < 0 || i >= board.length || j >= board[0].length) return; + if (board[i][j] !== "O") return; + board[i][j] = "*"; + search(board, i + 1, j); + search(board, i - 1, j); + search(board, i, j + 1); + search(board, i, j - 1); +} + diff --git a/1300-sum-of-mutated-array-closest-to-target.js b/1300.sum-of-mutated-array-closest-to-target.js similarity index 100% rename from 1300-sum-of-mutated-array-closest-to-target.js rename to 1300.sum-of-mutated-array-closest-to-target.js diff --git a/1301-number-of-paths-with-max-score.js b/1301-number-of-paths-with-max-score.js deleted file mode 100644 index 35b84b7c..00000000 --- a/1301-number-of-paths-with-max-score.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @param {string[]} board - * @return {number[]} - */ -const pathsWithMaxScore = ( - A, - dirs = [ - [-1, -1], - [-1, 0], - [0, -1], - ], - mod = 1e9 + 7 -) => { - const N = A.length - const S = [...Array(N + 1)].map((row) => Array(N + 1).fill(0)), - P = [...Array(N + 1)].map((row) => Array(N + 1).fill(0)) - P[0][0] = 1 - for (let i = 1; i <= N; ++i) { - for (let j = 1; j <= N; ++j) { - if (A[i - 1][j - 1] == 'X') continue - for (let d of dirs) { - const u = i + d[0], - v = j + d[1] - const sum = !P[u][v] - ? 0 - : S[u][v] + - (i == 1 && j == 1 - ? 0 - : i == N && j == N - ? 0 - : A[i - 1].charCodeAt(j - 1) - '0'.charCodeAt(0)) - if (S[i][j] == sum) P[i][j] = (P[i][j] + P[u][v]) % mod - if (S[i][j] < sum) (S[i][j] = sum), (P[i][j] = P[u][v]) - } - } - } - return [S[N][N], P[N][N]] -} - -// another - -/** - * @param {string[]} board - * @return {number[]} - */ -const pathsWithMaxScore = ( - board, - DIRS = [ - [-1, -1], - [-1, 0], - [0, -1], - ], - mod = 1e9 + 7 -) => { - const m = board.length, - n = board[0].length - const dpSum = Array.from({ length: m }, () => Array(n).fill(0)) - const dpCnt = Array.from({ length: m }, () => Array(n).fill(0)) - dpCnt[m - 1][n - 1] = 1 // start at the bottom right square - for (let r = m - 1; r >= 0; r--) { - for (let c = n - 1; c >= 0; c--) { - if (dpCnt[r][c] === 0) continue // can't reach to this square - for (let dir of DIRS) { - let nr = r + dir[0], - nc = c + dir[1] - if (nr >= 0 && nc >= 0 && board[nr].charAt(nc) !== 'X') { - let nsum = dpSum[r][c] - if (board[nr].charAt(nc) !== 'E') nsum += board[nr].charAt(nc) - '0' - if (nsum > dpSum[nr][nc]) { - dpCnt[nr][nc] = dpCnt[r][c] - dpSum[nr][nc] = nsum - } else if (nsum === dpSum[nr][nc]) { - dpCnt[nr][nc] = (dpCnt[nr][nc] + dpCnt[r][c]) % mod - } - } - } - } - } - return [dpSum[0][0], dpCnt[0][0]] -} - diff --git a/1301.number-of-paths-with-max-score.js b/1301.number-of-paths-with-max-score.js new file mode 100644 index 00000000..2576c1b7 --- /dev/null +++ b/1301.number-of-paths-with-max-score.js @@ -0,0 +1,39 @@ +/** + * @param {string[]} board + * @return {number[]} + */ +const pathsWithMaxScore = ( + A, + dirs = [ + [-1, -1], + [-1, 0], + [0, -1], + ], + mod = 1e9 + 7 +) => { + const N = A.length + const S = [...Array(N + 1)].map((row) => Array(N + 1).fill(0)), + P = [...Array(N + 1)].map((row) => Array(N + 1).fill(0)) + P[0][0] = 1 + for (let i = 1; i <= N; ++i) { + for (let j = 1; j <= N; ++j) { + if (A[i - 1][j - 1] == 'X') continue + for (let d of dirs) { + const u = i + d[0], + v = j + d[1] + const sum = !P[u][v] + ? 0 + : S[u][v] + + (i == 1 && j == 1 + ? 0 + : i == N && j == N + ? 0 + : A[i - 1].charCodeAt(j - 1) - '0'.charCodeAt(0)) + if (S[i][j] == sum) P[i][j] = (P[i][j] + P[u][v]) % mod + if (S[i][j] < sum) (S[i][j] = sum), (P[i][j] = P[u][v]) + } + } + } + return [S[N][N], P[N][N]] +} + diff --git a/1302-deepest-leaves-sum.js b/1302.deepest-leaves-sum.js similarity index 100% rename from 1302-deepest-leaves-sum.js rename to 1302.deepest-leaves-sum.js diff --git a/1304-find-n-unique-integers-sum-up-to-zero.js b/1304.find-n-unique-integers-sum-up-to-zero.js similarity index 100% rename from 1304-find-n-unique-integers-sum-up-to-zero.js rename to 1304.find-n-unique-integers-sum-up-to-zero.js diff --git a/1305-all-elements-in-two-binary-search-trees.js b/1305.all-elements-in-two-binary-search-trees.js similarity index 100% rename from 1305-all-elements-in-two-binary-search-trees.js rename to 1305.all-elements-in-two-binary-search-trees.js diff --git a/1306-jump-game-iii.js b/1306-jump-game-iii.js deleted file mode 100644 index d3abea41..00000000 --- a/1306-jump-game-iii.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @param {number[]} arr - * @param {number} start - * @return {boolean} - */ -const canReach = function(arr, start) { - const s = new Set() - return helper(arr, start, s) -}; - -function helper(arr, start, s) { - if(start < 0 || start >= arr.length || s.has(start)) return false - s.add(start) - if(arr[start] === 0) return true - - return helper(arr, start + arr[start], s) || helper(arr, start - arr[start], s) -} - -// another - -/** - * @param {number[]} arr - * @param {number} start - * @return {boolean} - */ -const canReach = function (A, i) { - return ( - 0 <= i && - i < A.length && - A[i] >= 0 && - (!(A[i] = -A[i]) || canReach(A, i + A[i]) || canReach(A, i - A[i])) - ) -} - -// another - -/** - * @param {number[]} arr - * @param {number} start - * @return {boolean} - */ -const canReach = function(arr, start) { - const q = [start] - const s = new Set() - while(q.length) { - const len = q.length - for(let i = 0; i < len; i++) { - const cur = q.shift() - s.add(cur) - if(arr[cur] === 0) return true - if(!s.has(cur + arr[cur])) q.push(cur + arr[cur]) - if(!s.has(cur - arr[cur])) q.push(cur - arr[cur]) - } - } - return false -}; - diff --git a/1306.jump-game-iii.js b/1306.jump-game-iii.js new file mode 100644 index 00000000..6a3b8fbe --- /dev/null +++ b/1306.jump-game-iii.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} arr + * @param {number} start + * @return {boolean} + */ +const canReach = function(arr, start) { + const s = new Set() + return helper(arr, start, s) +}; + +function helper(arr, start, s) { + if(start < 0 || start >= arr.length || s.has(start)) return false + s.add(start) + if(arr[start] === 0) return true + + return helper(arr, start + arr[start], s) || helper(arr, start - arr[start], s) +} + diff --git a/1307-verbal-arithmetic-puzzle.js b/1307.verbal-arithmetic-puzzle.js similarity index 100% rename from 1307-verbal-arithmetic-puzzle.js rename to 1307.verbal-arithmetic-puzzle.js diff --git a/1309-decrypt-string-from-alphabet-to-integer-mapping.js b/1309.decrypt-string-from-alphabet-to-integer-mapping.js similarity index 100% rename from 1309-decrypt-string-from-alphabet-to-integer-mapping.js rename to 1309.decrypt-string-from-alphabet-to-integer-mapping.js diff --git a/131-palindrome-partitioning.js b/131-palindrome-partitioning.js deleted file mode 100644 index 56ebb6cb..00000000 --- a/131-palindrome-partitioning.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @param {string} s - * @return {string[][]} - */ -const partition = function(s) { - let res = [] - backtrack(res, [], 0, s) - return res -} - -function backtrack(res, cur, start, s) { - if (start === s.length) res.push([...cur]) - else { - for (let i = start; i < s.length; i++) { - if (isPalindrome(s, start, i)) { - cur.push(s.substring(start, i + 1)) - backtrack(res, cur, i + 1, s) - cur.pop() - } - } - } -} - -function isPalindrome(str, start, i) { - let l = start, - r = i - while (l < r) { - if (str[l] !== str[r]) return false - l++ - r-- - } - return true -} - -// another - -/** - * @param {string} s - * @return {string[][]} - */ -const partition = function(s) { - const res = [] - helper(s, 0, [], res) - return res -}; - -function helper(str, idx, cur, res) { - if(idx >= str.length) { - res.push(cur.slice()) - return - } - for(let i = idx, len = str.length; i < len; i++) { - const tmp = str.slice(idx, i + 1) - if(chk(tmp)) { - cur.push(tmp) - helper(str, i + 1, cur, res) - cur.pop() - } - } -} -function chk(str) { - const n = str.length - let l = 0, r = n - 1 - while(l < r) { - if(str[l] !== str[r]) return false - l++ - r-- - } - return true -} diff --git a/131.palindrome-partitioning.js b/131.palindrome-partitioning.js new file mode 100644 index 00000000..9646104a --- /dev/null +++ b/131.palindrome-partitioning.js @@ -0,0 +1,34 @@ +/** + * @param {string} s + * @return {string[][]} + */ +const partition = function(s) { + let res = [] + backtrack(res, [], 0, s) + return res +} + +function backtrack(res, cur, start, s) { + if (start === s.length) res.push([...cur]) + else { + for (let i = start; i < s.length; i++) { + if (isPalindrome(s, start, i)) { + cur.push(s.substring(start, i + 1)) + backtrack(res, cur, i + 1, s) + cur.pop() + } + } + } +} + +function isPalindrome(str, start, i) { + let l = start, + r = i + while (l < r) { + if (str[l] !== str[r]) return false + l++ + r-- + } + return true +} + diff --git a/1310-xor-queries-of-a-subarray.js b/1310-xor-queries-of-a-subarray.js deleted file mode 100644 index e2b63cb2..00000000 --- a/1310-xor-queries-of-a-subarray.js +++ /dev/null @@ -1,42 +0,0 @@ - /** - * @param {number[]} arr - * @param {number[][]} queries - * @return {number[]} - */ -const xorQueries = function(arr, queries) { - const pre = [], n = arr.length - let xor = arr[0] - pre.push(xor) - for(let i = 1; i < n; i++) { - pre[i] = pre[i - 1] ^ arr[i] - } - - const res = queries.map((e, i) => { - const [l, r] = e - return pre[r] ^ (l > 0 ? pre[l - 1] : 0) - }) - return res -}; - -// another - -/** - * @param {number[]} arr - * @param {number[][]} queries - * @return {number[]} - */ -const xorQueries = function(arr, queries) { - const xorArr = [] - xorArr[0] = 0 - const n = arr.length - for(let i = 0; i < n; i++) { - const cur = arr[i] - xorArr.push(cur ^ xorArr[xorArr.length - 1]) - } - const res = [] - for(const [l, r] of queries) { - res.push(xorArr[r + 1] ^ xorArr[l]) - } - - return res -}; diff --git a/1310.xor-queries-of-a-subarray.js b/1310.xor-queries-of-a-subarray.js new file mode 100644 index 00000000..dbee784a --- /dev/null +++ b/1310.xor-queries-of-a-subarray.js @@ -0,0 +1,20 @@ + /** + * @param {number[]} arr + * @param {number[][]} queries + * @return {number[]} + */ +const xorQueries = function(arr, queries) { + const pre = [], n = arr.length + let xor = arr[0] + pre.push(xor) + for(let i = 1; i < n; i++) { + pre[i] = pre[i - 1] ^ arr[i] + } + + const res = queries.map((e, i) => { + const [l, r] = e + return pre[r] ^ (l > 0 ? pre[l - 1] : 0) + }) + return res +}; + diff --git a/1312-minimum-insertion-steps-to-make-a-string-palindrome.js b/1312.minimum-insertion-steps-to-make-a-string-palindrome.js similarity index 100% rename from 1312-minimum-insertion-steps-to-make-a-string-palindrome.js rename to 1312.minimum-insertion-steps-to-make-a-string-palindrome.js diff --git a/1313-decompress-run-length-encoded-list.js b/1313.decompress-run-length-encoded-list.js similarity index 100% rename from 1313-decompress-run-length-encoded-list.js rename to 1313.decompress-run-length-encoded-list.js diff --git a/1314-matrix-block-sum.js b/1314.matrix-block-sum.js similarity index 100% rename from 1314-matrix-block-sum.js rename to 1314.matrix-block-sum.js diff --git a/1315-sum-of-nodes-with-even-valued-grandparent.js b/1315.sum-of-nodes-with-even-valued-grandparent.js similarity index 100% rename from 1315-sum-of-nodes-with-even-valued-grandparent.js rename to 1315.sum-of-nodes-with-even-valued-grandparent.js diff --git a/1316-distinct-echo-substrings.js b/1316.distinct-echo-substrings.js similarity index 100% rename from 1316-distinct-echo-substrings.js rename to 1316.distinct-echo-substrings.js diff --git a/132-palindrome-partitioning-ii.js b/132-palindrome-partitioning-ii.js deleted file mode 100644 index 841a5b4c..00000000 --- a/132-palindrome-partitioning-ii.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ - -const minCut = function(s) { - const n = s.length - if (n <= 1) return 0 - const dp = new Array(n).fill(0) - for (let i = 1; i < n; i++) dp[i] = i - for (let i = 1; i < n; i++) { - // odd - for ( - let start = i, end = i; - end < n && start >= 0 && s[end] === s[start]; - start--, end++ - ) { - dp[end] = Math.min(dp[end], start === 0 ? 0 : dp[start - 1] + 1) - } - // even - for ( - let start = i - 1, end = i; - end < n && start >= 0 && s[end] === s[start]; - start--, end++ - ) { - dp[end] = Math.min(dp[end], start === 0 ? 0 : dp[start - 1] + 1) - } - } - return dp[n - 1] -} - - - -// another - -const minCut = function(s) { - const n = s.length - const cut = new Array(n + 1).fill(0) - for (let i = 0; i <= n; i++) cut[i] = i - 1 - for (let i = 0; i < n; i++) { - // odd - for (let j = 0; i + j < n && i - j >= 0 && s[i + j] === s[i - j]; j++) { - cut[i + j + 1] = Math.min(cut[i + j + 1], cut[i - j] + 1) - } - // even - for ( - let j = 1; - i + j < n && i - j + 1 >= 0 && s[i + j] === s[i - j + 1]; - j++ - ) { - cut[i + j + 1] = Math.min(cut[i + j + 1], cut[i - j + 1] + 1) - } - } - return cut[n] -} diff --git a/132.palindrome-partitioning-ii.js b/132.palindrome-partitioning-ii.js new file mode 100644 index 00000000..53b7a369 --- /dev/null +++ b/132.palindrome-partitioning-ii.js @@ -0,0 +1,33 @@ +/** + * @param {string} s + * @return {number} + */ + +const minCut = function(s) { + const n = s.length + if (n <= 1) return 0 + const dp = new Array(n).fill(0) + for (let i = 1; i < n; i++) dp[i] = i + for (let i = 1; i < n; i++) { + // odd + for ( + let start = i, end = i; + end < n && start >= 0 && s[end] === s[start]; + start--, end++ + ) { + dp[end] = Math.min(dp[end], start === 0 ? 0 : dp[start - 1] + 1) + } + // even + for ( + let start = i - 1, end = i; + end < n && start >= 0 && s[end] === s[start]; + start--, end++ + ) { + dp[end] = Math.min(dp[end], start === 0 ? 0 : dp[start - 1] + 1) + } + } + return dp[n - 1] +} + + + diff --git a/1320-minimum-distance-to-type-a-word-using-two-fingers.js b/1320.minimum-distance-to-type-a-word-using-two-fingers.js similarity index 100% rename from 1320-minimum-distance-to-type-a-word-using-two-fingers.js rename to 1320.minimum-distance-to-type-a-word-using-two-fingers.js diff --git a/1323-maximum-69-number.js b/1323.maximum-69-number.js similarity index 100% rename from 1323-maximum-69-number.js rename to 1323.maximum-69-number.js diff --git a/1324-print-words-vertically.js b/1324.print-words-vertically.js similarity index 100% rename from 1324-print-words-vertically.js rename to 1324.print-words-vertically.js diff --git a/1325-delete-leaves-with-a-given-value.js b/1325-delete-leaves-with-a-given-value.js deleted file mode 100644 index 33e8a0d9..00000000 --- a/1325-delete-leaves-with-a-given-value.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @param {number} target - * @return {TreeNode} - */ -const removeLeafNodes = function(root, target) { - return dfs(root, target) -}; - -function dfs(node, target) { - if(node == null) return node - if(node.left == null && node.right == null) { - if(node.val === target) return null - else return node - } - node.right = dfs(node.right, target) - node.left = dfs(node.left, target) - if(node.right == null && node.left == null) return dfs(node, target) - return node -} - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @param {number} target - * @return {TreeNode} - */ -const removeLeafNodes = function(root, target) { - if(root.left) root.left = removeLeafNodes(root.left, target) - if(root.right) root.right = removeLeafNodes(root.right, target) - return root.left == root.right && root.val === target ? null : root -}; diff --git a/1325.delete-leaves-with-a-given-value.js b/1325.delete-leaves-with-a-given-value.js new file mode 100644 index 00000000..cab4211a --- /dev/null +++ b/1325.delete-leaves-with-a-given-value.js @@ -0,0 +1,29 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} target + * @return {TreeNode} + */ +const removeLeafNodes = function(root, target) { + return dfs(root, target) +}; + +function dfs(node, target) { + if(node == null) return node + if(node.left == null && node.right == null) { + if(node.val === target) return null + else return node + } + node.right = dfs(node.right, target) + node.left = dfs(node.left, target) + if(node.right == null && node.left == null) return dfs(node, target) + return node +} + diff --git a/1326-minimum-number-of-taps-to-open-to-water-a-garden.js b/1326-minimum-number-of-taps-to-open-to-water-a-garden.js deleted file mode 100644 index e228bae1..00000000 --- a/1326-minimum-number-of-taps-to-open-to-water-a-garden.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @param {number} n - * @param {number[]} ranges - * @return {number} - */ -const minTaps = function (n, ranges) { - const starts = new Array(n + 1).fill(0) - for (let i = 0; i <= n; i++) { - const start = Math.max(0, i - ranges[i]) - starts[start] = Math.max(starts[start], i + ranges[i]) - } - let count = 0 - let max = 0 - let i = 0 - while (max < n) { - const end = max - for (let j = i; j <= end; j++) { - max = Math.max(max, starts[j]) - } - if (i === max) return -1 - i = end - count++ - } - return count -} - -// another - -/** - * @param {number} n - * @param {number[]} ranges - * @return {number} - */ -const minTaps = function (n, ranges) { - const dp = new Array(n + 1).fill(n + 2) - dp[0] = 0 - for (let i = 0; i <= n; ++i) - for (let j = Math.max(i - ranges[i] + 1, 0); j <= Math.min(i + ranges[i], n); ++j) - dp[j] = Math.min(dp[j], dp[Math.max(0, i - ranges[i])] + 1) - return dp[n] < n + 2 ? dp[n] : -1 -} diff --git a/1326.minimum-number-of-taps-to-open-to-water-a-garden.js b/1326.minimum-number-of-taps-to-open-to-water-a-garden.js new file mode 100644 index 00000000..61aaf57c --- /dev/null +++ b/1326.minimum-number-of-taps-to-open-to-water-a-garden.js @@ -0,0 +1,26 @@ +/** + * @param {number} n + * @param {number[]} ranges + * @return {number} + */ +const minTaps = function (n, ranges) { + const starts = new Array(n + 1).fill(0) + for (let i = 0; i <= n; i++) { + const start = Math.max(0, i - ranges[i]) + starts[start] = Math.max(starts[start], i + ranges[i]) + } + let count = 0 + let max = 0 + let i = 0 + while (max < n) { + const end = max + for (let j = i; j <= end; j++) { + max = Math.max(max, starts[j]) + } + if (i === max) return -1 + i = end + count++ + } + return count +} + diff --git a/1329-sort-the-matrix-diagonally.js b/1329.sort-the-matrix-diagonally.js similarity index 100% rename from 1329-sort-the-matrix-diagonally.js rename to 1329.sort-the-matrix-diagonally.js diff --git a/133-clone-graph.js b/133.clone-graph.js similarity index 100% rename from 133-clone-graph.js rename to 133.clone-graph.js diff --git a/1330-reverse-subarray-to-maximize-array-value.js b/1330.reverse-subarray-to-maximize-array-value.js similarity index 100% rename from 1330-reverse-subarray-to-maximize-array-value.js rename to 1330.reverse-subarray-to-maximize-array-value.js diff --git a/1331-rank-transform-of-an-array.js b/1331.rank-transform-of-an-array.js similarity index 100% rename from 1331-rank-transform-of-an-array.js rename to 1331.rank-transform-of-an-array.js diff --git a/1332-remove-palindromic-subsequences.js b/1332.remove-palindromic-subsequences.js similarity index 100% rename from 1332-remove-palindromic-subsequences.js rename to 1332.remove-palindromic-subsequences.js diff --git a/1335-minimum-difficulty-of-a-job-schedule.js b/1335.minimum-difficulty-of-a-job-schedule.js similarity index 100% rename from 1335-minimum-difficulty-of-a-job-schedule.js rename to 1335.minimum-difficulty-of-a-job-schedule.js diff --git a/1337-the-k-weakest-rows-in-a-matrix.js b/1337.the-k-weakest-rows-in-a-matrix.js similarity index 100% rename from 1337-the-k-weakest-rows-in-a-matrix.js rename to 1337.the-k-weakest-rows-in-a-matrix.js diff --git a/1338-reduce-array-size-to-the-half.js b/1338.reduce-array-size-to-the-half.js similarity index 100% rename from 1338-reduce-array-size-to-the-half.js rename to 1338.reduce-array-size-to-the-half.js diff --git a/134-gas-station.js b/134-gas-station.js deleted file mode 100644 index a7dc4e04..00000000 --- a/134-gas-station.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @param {number[]} gas - * @param {number[]} cost - * @return {number} - */ -const canCompleteCircuit = function(gas, cost) { - let total = 0 - let curLeft = 0 - let curtIdx = 0 - for (let i = 0; i < gas.length; i++) { - total += gas[i] - cost[i] - curLeft += gas[i] - cost[i] - if (curLeft < 0) { - curtIdx = i + 1 - curLeft = 0 - } - } - return total < 0 ? -1 : curtIdx -} - -// another - -const canCompleteCircuit = function(gas, cost) { - const len = gas.length - let tank = 0 - let count = 0 - for (let i = 0; i < len * 2; i++) { - let idx = i % len - if (count === len) return idx - count += 1 - tank += gas[idx] - cost[idx] - if (tank < 0) { - tank = 0 - count = 0 - } - } - return -1 -} - diff --git a/134.gas-station.js b/134.gas-station.js new file mode 100644 index 00000000..cf96bb2d --- /dev/null +++ b/134.gas-station.js @@ -0,0 +1,20 @@ +/** + * @param {number[]} gas + * @param {number[]} cost + * @return {number} + */ +const canCompleteCircuit = function(gas, cost) { + let total = 0 + let curLeft = 0 + let curtIdx = 0 + for (let i = 0; i < gas.length; i++) { + total += gas[i] - cost[i] + curLeft += gas[i] - cost[i] + if (curLeft < 0) { + curtIdx = i + 1 + curLeft = 0 + } + } + return total < 0 ? -1 : curtIdx +} + diff --git a/1340-jump-game-v.js b/1340-jump-game-v.js deleted file mode 100644 index 60945fdd..00000000 --- a/1340-jump-game-v.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @param {number[]} arr - * @param {number} d - * @return {number} - */ -const maxJumps = function (arr, d, res = 1) { - const dp = Array(1001).fill(0) - for (let i = 0, len = arr.length; i < len; ++i) - res = Math.max(res, dfs(arr, i, d)) - return res - - function dfs(arr, i, d, res = 1) { - if (dp[i]) return dp[i] - for ( - let j = i + 1; - j <= Math.min(i + d, arr.length - 1) && arr[j] < arr[i]; - ++j - ) - res = Math.max(res, 1 + dfs(arr, j, d)) - for (let j = i - 1; j >= Math.max(0, i - d) && arr[j] < arr[i]; --j) - res = Math.max(res, 1 + dfs(arr, j, d)) - return (dp[i] = res) - } -} - - -// another - -/** - * @param {number[]} arr - * @param {number} d - * @return {number} - */ -const maxJumps = function (arr, d) { - const cache = new Array(arr.length) - const diffs = [1, -1] - const dfs = (i) => { - if (cache[i]) return cache[i] - let max = 0 - for (let diff of diffs) { - for (let j = diff; Math.abs(j) <= d; j += diff) { - const nextPosition = i + j - const isValidJump = - nextPosition >= 0 && - nextPosition < arr.length && - arr[i] > arr[nextPosition] - if (isValidJump) max = Math.max(max, dfs(nextPosition)) - else break - } - } - const result = max + 1 - cache[i] = result - return result - } - for (let i = 0; i < arr.length; i++) dfs(i) - return Math.max(...cache) -} - -// another - -/** - * @param {number[]} arr - * @param {number} d - * @return {number} - */ -const maxJumps = function (arr, d, res = 0) { - const n = arr.length - const stack = [], stack2 = [] - const dp = Array(n + 1).fill(1) - arr.push(Infinity) - for(let i = 0; i <= n; i++) { - while(stack.length && arr[stack[stack.length - 1]] < arr[i]) { - const pre = arr[stack[stack.length - 1]] - while(stack.length && pre === arr[stack[stack.length - 1]]) { - const j = stack[stack.length - 1] - stack.pop() - if(i - j <= d) dp[i] = Math.max(dp[i], dp[j] + 1) - stack2.push(j) - } - while(stack2.length) { - const j = stack2[stack2.length - 1] - stack2.pop() - if(stack.length && j - stack[stack.length - 1] <= d) { - dp[stack[stack.length - 1]] = Math.max(dp[stack[stack.length - 1]], dp[j] + 1) - } - } - } - stack.push(i) - } - for(let i = 0; i < n; i++) res = Math.max(res, dp[i]) - return res -} diff --git a/1340.jump-game-v.js b/1340.jump-game-v.js new file mode 100644 index 00000000..9b407558 --- /dev/null +++ b/1340.jump-game-v.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} arr + * @param {number} d + * @return {number} + */ +const maxJumps = function (arr, d, res = 1) { + const dp = Array(1001).fill(0) + for (let i = 0, len = arr.length; i < len; ++i) + res = Math.max(res, dfs(arr, i, d)) + return res + + function dfs(arr, i, d, res = 1) { + if (dp[i]) return dp[i] + for ( + let j = i + 1; + j <= Math.min(i + d, arr.length - 1) && arr[j] < arr[i]; + ++j + ) + res = Math.max(res, 1 + dfs(arr, j, d)) + for (let j = i - 1; j >= Math.max(0, i - d) && arr[j] < arr[i]; --j) + res = Math.max(res, 1 + dfs(arr, j, d)) + return (dp[i] = res) + } +} + + diff --git a/1342-number-of-steps-to-reduce-a-number-to-zero.js b/1342.number-of-steps-to-reduce-a-number-to-zero.js similarity index 100% rename from 1342-number-of-steps-to-reduce-a-number-to-zero.js rename to 1342.number-of-steps-to-reduce-a-number-to-zero.js diff --git a/1343-number-of-sub-arrays-of-size-k-and-average-greater-than-or-equal-to-threshold.js b/1343.number-of-sub-arrays-of-size-k-and-average-greater-than-or-equal-to-threshold.js similarity index 100% rename from 1343-number-of-sub-arrays-of-size-k-and-average-greater-than-or-equal-to-threshold.js rename to 1343.number-of-sub-arrays-of-size-k-and-average-greater-than-or-equal-to-threshold.js diff --git a/1344-angle-between-hands-of-a-clock.js b/1344.angle-between-hands-of-a-clock.js similarity index 100% rename from 1344-angle-between-hands-of-a-clock.js rename to 1344.angle-between-hands-of-a-clock.js diff --git a/1345-jump-game-iv.js b/1345-jump-game-iv.js deleted file mode 100644 index 5e67c588..00000000 --- a/1345-jump-game-iv.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @param {number[]} arr - * @return {number} - */ -var minJumps = function (arr) { - if (arr.length === 1) return 0 - const n = arr.length - const indexMap = new Map() - for (let i = n - 1; i >= 0; i--) { - if (!indexMap.has(arr[i])) { - indexMap.set(arr[i], []) - } - indexMap.get(arr[i]).push(i) - } - let distance = 0 - const queue = [0, null] - const visited = new Set([0]) - while (queue.length > 0) { - const index = queue.shift() - if (index !== null) { - if (index > 0 && !visited.has(index - 1)) { - visited.add(index - 1) - queue.push(index - 1) - } - if (index < n - 1 && !visited.has(index + 1)) { - if (index + 1 === n - 1) return distance + 1 - visited.add(index + 1) - queue.push(index + 1) - } - for (const nb of indexMap.get(arr[index])) { - if (!visited.has(nb) && nb !== index - 1 && nb !== index + 1) { - if (nb === n - 1) return distance + 1 - visited.add(nb) - queue.push(nb) - } - } - } else { - distance++ - if (queue.length > 0) { - queue.push(null) - } - } - } - return -1 -} - -// another - -/** - * @param {number[]} arr - * @return {number} - */ -const minJumps = function (arr) { - if (arr.length === 1) return 0 - const n = arr.length - const indexMap = new Map() - for (let i = n - 1; i >= 0; i--) { - if (!indexMap.has(arr[i])) { - indexMap.set(arr[i], []) - } - indexMap.get(arr[i]).push(i) - } - let distance = 0 - const queue = [0] - const visited = new Set() - visited.add(0) - while (queue.length) { - const len = queue.length - for(let i = 0; i < len; i++) { - const cur = queue.shift() - if(cur === n - 1) return distance - const tmp = indexMap.get(arr[cur]) - tmp.push(cur - 1) - tmp.push(cur + 1) - for(let e of tmp) { - if(e >= 0 && e < n && !visited.has(e)) { - visited.add(e) - queue.push(e) - } - } - indexMap.set(arr[cur], []) - } - distance++ - } - return -1 -} - diff --git a/1345.jump-game-iv.js b/1345.jump-game-iv.js new file mode 100644 index 00000000..fee38216 --- /dev/null +++ b/1345.jump-game-iv.js @@ -0,0 +1,46 @@ +/** + * @param {number[]} arr + * @return {number} + */ +var minJumps = function (arr) { + if (arr.length === 1) return 0 + const n = arr.length + const indexMap = new Map() + for (let i = n - 1; i >= 0; i--) { + if (!indexMap.has(arr[i])) { + indexMap.set(arr[i], []) + } + indexMap.get(arr[i]).push(i) + } + let distance = 0 + const queue = [0, null] + const visited = new Set([0]) + while (queue.length > 0) { + const index = queue.shift() + if (index !== null) { + if (index > 0 && !visited.has(index - 1)) { + visited.add(index - 1) + queue.push(index - 1) + } + if (index < n - 1 && !visited.has(index + 1)) { + if (index + 1 === n - 1) return distance + 1 + visited.add(index + 1) + queue.push(index + 1) + } + for (const nb of indexMap.get(arr[index])) { + if (!visited.has(nb) && nb !== index - 1 && nb !== index + 1) { + if (nb === n - 1) return distance + 1 + visited.add(nb) + queue.push(nb) + } + } + } else { + distance++ + if (queue.length > 0) { + queue.push(null) + } + } + } + return -1 +} + diff --git a/1347-minimum-number-of-steps-to-make-two-strings-anagram.js b/1347.minimum-number-of-steps-to-make-two-strings-anagram.js similarity index 100% rename from 1347-minimum-number-of-steps-to-make-two-strings-anagram.js rename to 1347.minimum-number-of-steps-to-make-two-strings-anagram.js diff --git a/1348-tweet-counts-per-frequency.js b/1348.tweet-counts-per-frequency.js similarity index 100% rename from 1348-tweet-counts-per-frequency.js rename to 1348.tweet-counts-per-frequency.js diff --git a/1349-maximum-students-taking-exam.js b/1349-maximum-students-taking-exam.js deleted file mode 100644 index 0a45d165..00000000 --- a/1349-maximum-students-taking-exam.js +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @param {character[][]} seats - * @return {number} - */ -const maxStudents = function(seats) { - const m = seats.length, n = seats[0].length, limit = 1 << n - const dp = Array.from({ length: m + 1}, () => Array(limit).fill(0)) - - let res = 0 - for(let i = 1; i <= m; i++) { - for(let mask = 0; mask < limit; mask++) { - let valid = true - for(let j = 0; j < n; j++) { - if(seats[i - 1][j] === '#' && ((mask >> j) & 1) ) { - valid = false - break - } - if(j < n - 1 && ((mask >> j) & 1) && ((mask >> (j + 1)) & 1) ) { - valid = false - break - } - } - - if(!valid) { - dp[i][mask] = -1 - continue - } - - for(let pre = 0; pre < limit; pre++) { - if(dp[i - 1][pre] === -1) continue - if( (pre & (mask >> 1)) !== 0 || (pre & (mask << 1)) !== 0 ) continue - dp[i][mask] = Math.max(dp[i][mask], dp[i - 1][pre]) - } - - dp[i][mask] += bitCnt(mask) - - res = Math.max(res, dp[i][mask]) - } - } - - return res - - function bitCnt(num) { - let res = 0 - while(num) { - if(num & 1) res++ - num = num >> 1 - } - - return res - } -}; - -// another - - -/** - * @param {character[][]} seats - * @return {number} - */ -const maxStudents = function (seats) { - if (!seats.length) return 0 - const lastPos = 1 << seats[0].length - const classroom = seats.map((row) => - row.reduce((a, c, i) => (c === '#' ? a : a | (1 << i)), 0) - ) - const dp = new Array(seats.length + 1).fill(null).map(() => new Map()) - dp[0].set(0, 0) - for (let row = 0; row < seats.length; row++) { - let queue = [0] - let numStudents = 0 - while (queue.length > 0) { - const next = [] - for (let arrangement of queue) { - let max = 0 - for (let [prevArrang, count] of dp[row]) { - if (conflicts(prevArrang, arrangement)) continue - max = Math.max(max, count + numStudents) - } - dp[row + 1].set(arrangement, max) - for (let i = 1; i < lastPos; i <<= 1) { - if (canSit(classroom[row], arrangement, i)) next.push(arrangement | i) - } - } - queue = next - numStudents++ - } - } - return Math.max(...dp[seats.length].values()) -} -function conflicts(prev, curr) { - return prev & (curr << 1) || prev & (curr >> 1) -} -function canSit(row, arrangement, newStudent) { - return ( - row & newStudent && - !(arrangement & newStudent) && - !(arrangement & (newStudent << 1)) && - !(arrangement & (newStudent >> 1)) - ) -} - -// another - -/** - * @param {character[][]} seats - * @return {number} - */ -const maxStudents = function (seats) { - const m = seats.length - const n = seats[0].length - const validity = [] - for (let i = 0; i < m; i++) { - let cur = 0 - for (let j = 0; j < n; j++) { - cur = (cur << 1) + (seats[i][j] === '.' ? 1 : 0) - } - validity.push(cur) - } - const f = Array.from({ length: m + 1 }, () => Array(1 << n).fill(-1)) - f[0][0] = 0 - for (let i = 1; i <= m; i++) { - const valid = validity[i - 1] - for (let j = 0; j < 1 << n; j++) { - if ((j & valid) === j && !(j & (j >> 1))) { - for (let k = 0; k < 1 << n; k++) { - if (!(j & (k >> 1)) && !((j >> 1) & k) && f[i - 1][k] !== -1) { - f[i][j] = Math.max(f[i][j], f[i - 1][k] + bitCount(j)) - } - } - } - } - } - return Math.max(...f[m]) -} -function bitCount(n) { - const res = n.toString(2).match(/1/g) - return res === null ? 0 : res.length -} - diff --git a/1349.maximum-students-taking-exam.js b/1349.maximum-students-taking-exam.js new file mode 100644 index 00000000..0293b9e2 --- /dev/null +++ b/1349.maximum-students-taking-exam.js @@ -0,0 +1,53 @@ +/** + * @param {character[][]} seats + * @return {number} + */ +const maxStudents = function(seats) { + const m = seats.length, n = seats[0].length, limit = 1 << n + const dp = Array.from({ length: m + 1}, () => Array(limit).fill(0)) + + let res = 0 + for(let i = 1; i <= m; i++) { + for(let mask = 0; mask < limit; mask++) { + let valid = true + for(let j = 0; j < n; j++) { + if(seats[i - 1][j] === '#' && ((mask >> j) & 1) ) { + valid = false + break + } + if(j < n - 1 && ((mask >> j) & 1) && ((mask >> (j + 1)) & 1) ) { + valid = false + break + } + } + + if(!valid) { + dp[i][mask] = -1 + continue + } + + for(let pre = 0; pre < limit; pre++) { + if(dp[i - 1][pre] === -1) continue + if( (pre & (mask >> 1)) !== 0 || (pre & (mask << 1)) !== 0 ) continue + dp[i][mask] = Math.max(dp[i][mask], dp[i - 1][pre]) + } + + dp[i][mask] += bitCnt(mask) + + res = Math.max(res, dp[i][mask]) + } + } + + return res + + function bitCnt(num) { + let res = 0 + while(num) { + if(num & 1) res++ + num = num >> 1 + } + + return res + } +}; + diff --git a/135-candy.js b/135.candy.js similarity index 100% rename from 135-candy.js rename to 135.candy.js diff --git a/1351-count-negative-numbers-in-a-sorted-matrix.js b/1351.count-negative-numbers-in-a-sorted-matrix.js similarity index 100% rename from 1351-count-negative-numbers-in-a-sorted-matrix.js rename to 1351.count-negative-numbers-in-a-sorted-matrix.js diff --git a/1352-product-of-the-last-k-numbers.js b/1352.product-of-the-last-k-numbers.js similarity index 100% rename from 1352-product-of-the-last-k-numbers.js rename to 1352.product-of-the-last-k-numbers.js diff --git a/1353-maximum-number-of-events-that-can-be-attended.js b/1353-maximum-number-of-events-that-can-be-attended.js deleted file mode 100644 index f0cdc48d..00000000 --- a/1353-maximum-number-of-events-that-can-be-attended.js +++ /dev/null @@ -1,248 +0,0 @@ -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} -/** - * @param {number[][]} events - * @return {number} - */ -function maxEvents(events) { - const pq = new PriorityQueue((a, b) => a < b) - - events.sort((a, b) => a[0] - b[0]) - let i = 0, res = 0, d = 0, n = events.length - - while(!pq.isEmpty() || i < n) { - if(pq.isEmpty()) { - d = events[i][0] - } - while(i < n && events[i][0] <= d) { - pq.push(events[i++][1]) - } - pq.pop() - res++ - d++ - while(!pq.isEmpty() && pq.peek() < d) { - pq.pop() - } - } - - return res -} - - -// another - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} -/** - * @param {number[][]} events - * @return {number} - */ -function maxEvents(events) { - const pq = new PriorityQueue((a, b) => a < b) - events.sort((a, b) => a[0] - b[0]) - let res = 0, i = 0, n = events.length - for(let d = 1; d <= 100000; d++) { - while(i < n && events[i][0] === d) { - pq.push(events[i++][1]) - } - while(!pq.isEmpty() && pq.peek() < d) { - pq.pop() - } - if(!pq.isEmpty()) { - res++ - pq.pop() - } - } - return res -} - - -// another - - - -/** - * @param {number[][]} events - * @return {number} - */ -function maxEvents(events) { - events.sort(([, aEnd], [, bEnd]) => aEnd - bEnd); - const lastDay = events[events.length - 1][1]; - const segmentTree = new SegmentTree(Array.from({ length: lastDay }, (_, i) => i), Infinity, (a, b) => Math.min(a, b)); - let daysAttended = 0; - - for (const [start, end] of events) { - // earliest attendable day - const ead = segmentTree.queryIn(start - 1, end); - if (ead <= end) { - daysAttended += 1; - segmentTree.setAt(ead, Infinity); - } - } - - return daysAttended; -} - -// https://github.com/axross/complex-data-structures -// new SegmentTree(values, identity, associate) -// segmentTree.getAt(i) -// segmentTree.queryIn(from, to) -// segmentTree.setAt(i, value) -// segmentTree.length -class SegmentTree{constructor(t,e,s){if(this.valueLength=t.length,this.identity=e,this.associate=s,0===t.length)this.tree=[];else{const h=2**Math.ceil(Math.log2(t.length))*2-1,i=[];for(let s=0;s<=h>>1;++s)i[(h>>1)+s]=s>1)-1;t>=0;--t)i[t]=s(i[2*t+1],i[2*t+2]);this.tree=i}}get length(){return this.valueLength}getAt(t){return this.tree[t+(this.tree.length>>1)]}queryIn(t,e){let s=this.identity;const h=[[0,0,1+(this.tree.length>>1)]];for(;h.length>0;){const[i,r,n]=h.pop();r>=t&&n<=e?s=this.associate(s,this.tree[i]):r>=e||nthis.tree.length>>1||h.push([2*i+1,r,r+n>>1],[2*i+2,r+n>>1,n])}return s}setAt(t,e){const s=t+(this.tree.length>>1);this.tree[s]=e;let h=s-1>>1;for(;h>=0;)this.tree[h]=this.associate(this.tree[2*h+1],this.tree[2*h+2]),h=h-1>>1}} - - -// another - -/** - * @param {number[][]} events - * @return {number} - */ -function maxEvents(events) { - const pq = new MinPriorityQueue () - events.sort((a, b) => a[0] - b[0]) - let res = 0, i = 0, n = events.length - for(let d = 1; d <= 1e5; d++) { - while(i < n && events[i][0] === d) { - pq.enqueue(events[i++][1]) - } - while(!pq.isEmpty() && pq.front().element < d) { - pq.dequeue() - } - if(!pq.isEmpty()) { - res++ - pq.dequeue() - } - } - return res -} diff --git a/1353.maximum-number-of-events-that-can-be-attended.js b/1353.maximum-number-of-events-that-can-be-attended.js new file mode 100644 index 00000000..d6d52d89 --- /dev/null +++ b/1353.maximum-number-of-events-that-can-be-attended.js @@ -0,0 +1,96 @@ +class PriorityQueue { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} +/** + * @param {number[][]} events + * @return {number} + */ +function maxEvents(events) { + const pq = new PriorityQueue((a, b) => a < b) + + events.sort((a, b) => a[0] - b[0]) + let i = 0, res = 0, d = 0, n = events.length + + while(!pq.isEmpty() || i < n) { + if(pq.isEmpty()) { + d = events[i][0] + } + while(i < n && events[i][0] <= d) { + pq.push(events[i++][1]) + } + pq.pop() + res++ + d++ + while(!pq.isEmpty() && pq.peek() < d) { + pq.pop() + } + } + + return res +} + + diff --git a/1354-construct-target-array-with-multiple-sums.js b/1354.construct-target-array-with-multiple-sums.js similarity index 100% rename from 1354-construct-target-array-with-multiple-sums.js rename to 1354.construct-target-array-with-multiple-sums.js diff --git a/1356-sort-integers-by-the-number-of-1-bits.js b/1356.sort-integers-by-the-number-of-1-bits.js similarity index 100% rename from 1356-sort-integers-by-the-number-of-1-bits.js rename to 1356.sort-integers-by-the-number-of-1-bits.js diff --git a/1359-count-all-valid-pickup-and-delivery-options.js b/1359-count-all-valid-pickup-and-delivery-options.js deleted file mode 100644 index ae1de659..00000000 --- a/1359-count-all-valid-pickup-and-delivery-options.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const countOrders = function(n) { - let res = 1 - const MOD = 10 ** 9 + 7 - for(let i = 1; i <= n; i++) { - res = res * (i * 2 - 1) * i % MOD; - } - return res -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const countOrders = function(n) { - let res = 1 - const MOD = 10 ** 9 + 7 - for(let i = 1; i <= n; i++) res = res * i % MOD - for(let i = 1; i < 2 * n; i += 2) res = res * i % MOD - return res -}; diff --git a/1359.count-all-valid-pickup-and-delivery-options.js b/1359.count-all-valid-pickup-and-delivery-options.js new file mode 100644 index 00000000..cb58fb1b --- /dev/null +++ b/1359.count-all-valid-pickup-and-delivery-options.js @@ -0,0 +1,13 @@ +/** + * @param {number} n + * @return {number} + */ +const countOrders = function(n) { + let res = 1 + const MOD = 10 ** 9 + 7 + for(let i = 1; i <= n; i++) { + res = res * (i * 2 - 1) * i % MOD; + } + return res +}; + diff --git a/136-single-number.js b/136-single-number.js deleted file mode 100644 index 662dfc28..00000000 --- a/136-single-number.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const singleNumber = function(nums) { - let xor = nums[0] - for(let i = 1; i< nums.length; i++) xor ^= nums[i] - return xor -}; - - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const singleNumber = function(nums) { - return nums.reduce((ac, e) => ac ^ e, 0) -}; diff --git a/136.single-number.js b/136.single-number.js new file mode 100644 index 00000000..706d17ec --- /dev/null +++ b/136.single-number.js @@ -0,0 +1,11 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const singleNumber = function(nums) { + let xor = nums[0] + for(let i = 1; i< nums.length; i++) xor ^= nums[i] + return xor +}; + + diff --git a/1360-number-of-days-between-two-dates.js b/1360.number-of-days-between-two-dates.js similarity index 100% rename from 1360-number-of-days-between-two-dates.js rename to 1360.number-of-days-between-two-dates.js diff --git a/1363-largest-multiple-of-three.js b/1363.largest-multiple-of-three.js similarity index 100% rename from 1363-largest-multiple-of-three.js rename to 1363.largest-multiple-of-three.js diff --git a/1365-how-many-numbers-are-smaller-than-the-current-number.js b/1365.how-many-numbers-are-smaller-than-the-current-number.js similarity index 100% rename from 1365-how-many-numbers-are-smaller-than-the-current-number.js rename to 1365.how-many-numbers-are-smaller-than-the-current-number.js diff --git a/1366-rank-teams-by-votes.js b/1366-rank-teams-by-votes.js deleted file mode 100644 index ef253262..00000000 --- a/1366-rank-teams-by-votes.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @param {string[]} votes - * @return {string} - */ -const rankTeams = function(votes) { - const hash = {} - const l = votes[0].length - for(let vote of votes) { - for(let i = 0; i < l; i++) { - const ch = vote[i] - if(hash[ch] == null) hash[ch] = Array(l).fill(0) - hash[ch][i]++ - } - } - const keys = Object.keys(hash) - keys.sort((a, b) => { - for(let i = 0; i < l; i++) { - if(hash[a][i] !== hash[b][i]) { - return hash[b][i] - hash[a][i] - } - } - return a === b ? 0 : (a < b ? -1 : 1) - }) - - return keys.join('') -}; - -// another - -/** - * @param {string[]} votes - * @return {string} - */ -const rankTeams = function(votes) { - if (votes.length === 1) return votes[0]; - const score = new Map(votes[0].split('').map(c => [c, new Array(votes[0].length).fill(0)])); - for (s of votes) { - for (let i = 0; i < s.length; i++) { - score.get(s[i])[i]++; - } - } - return votes[0].split('').sort((a,b) => { - for (let i = 0; i < votes[0].length; i++) { - if (score.get(a)[i] > score.get(b)[i]) return -1; - if (score.get(a)[i] < score.get(b)[i]) return 1; - } - return a < b ? -1 : 1; - }).join(''); -}; diff --git a/1366.rank-teams-by-votes.js b/1366.rank-teams-by-votes.js new file mode 100644 index 00000000..560e70b1 --- /dev/null +++ b/1366.rank-teams-by-votes.js @@ -0,0 +1,27 @@ +/** + * @param {string[]} votes + * @return {string} + */ +const rankTeams = function(votes) { + const hash = {} + const l = votes[0].length + for(let vote of votes) { + for(let i = 0; i < l; i++) { + const ch = vote[i] + if(hash[ch] == null) hash[ch] = Array(l).fill(0) + hash[ch][i]++ + } + } + const keys = Object.keys(hash) + keys.sort((a, b) => { + for(let i = 0; i < l; i++) { + if(hash[a][i] !== hash[b][i]) { + return hash[b][i] - hash[a][i] + } + } + return a === b ? 0 : (a < b ? -1 : 1) + }) + + return keys.join('') +}; + diff --git a/1367-linked-list-in-binary-tree.js b/1367.linked-list-in-binary-tree.js similarity index 100% rename from 1367-linked-list-in-binary-tree.js rename to 1367.linked-list-in-binary-tree.js diff --git a/1368-minimum-cost-to-make-at-least-one-valid-path-in-a-grid.js b/1368-minimum-cost-to-make-at-least-one-valid-path-in-a-grid.js deleted file mode 100644 index def7dab1..00000000 --- a/1368-minimum-cost-to-make-at-least-one-valid-path-in-a-grid.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -function minCost(grid) { - const m = grid.length, n = grid[0].length - const dirs = [[0, 1], [0, -1], [1, 0], [-1, 0]] // right, left, down, up - const dp = Array.from({ length: m }, () => Array(n).fill(Infinity)) - let q = [[0, 0]] - dp[0][0] = 0 - while(q.length) { - const tmp = [] - for(let idx = q.length - 1; idx >= 0; idx--) { - const [r, c] = q[idx] - for(let i = 0; i < dirs.length; i++) { - const [dr, dc] = dirs[i] - const nr = r + dr, nc = c + dc - if(nr < 0 || nr >= m || nc < 0 || nc >= n) continue - if(dp[nr][nc] > dp[r][c] + (i === grid[r][c] - 1 ? 0 : 1)) { - dp[nr][nc] = dp[r][c] + (i === grid[r][c] - 1 ? 0 : 1) - tmp.push([nr, nc]) - } - } - } - q = tmp - } - - return dp[m - 1][n - 1] -} - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -const minCost = function (grid) { - const n = grid.length - const m = grid[0].length - const moves = [ - [0, 1], - [0, -1], - [1, 0], - [-1, 0], - ] - const dp = [...new Array(n)].map((e) => [...new Array(m)].fill(Infinity)) - dp[0][0] = 0 - let queue = [[0, 0]] - while (queue.length > 0) { - const temp = [] - for (let i = 0; i < queue.length; i++) { - const [x, y] = queue[i] - for (let j = 0; j < moves.length; j++) { - const nextX = x + moves[j][0] - const nextY = y + moves[j][1] - if (nextX >= 0 && nextY >= 0 && nextX < n && nextY < m) { - if (dp[nextX][nextY] > dp[x][y] + (grid[x][y] - 1 === j ? 0 : 1)) { - dp[nextX][nextY] = dp[x][y] + (grid[x][y] - 1 === j ? 0 : 1) - queue.push([nextX, nextY]) - } - } - } - } - queue = temp - } - return dp[n - 1][m - 1] -} - -// another - -function minCost(grid) { - const INF = 1e9, m = grid.length, n = grid[0].length - const dirs = [[0, 1], [0, -1], [1, 0], [-1, 0]] // right, left, down, up - let cost = 0 - const dp = Array.from({ length: m }, () => Array(n).fill(INF)) - const q = [] - dfs(0, 0, 0) - while(q.length) { - cost++ - for (let size = q.length; size > 0; size--) { - const [r, c] = q.shift() - for(let [dx, dy] of dirs) { - dfs(r + dx, c + dy, cost) - } - } - } - - return dp[m - 1][n - 1] - function dfs(r, c, cost) { - if(r < 0 || r >= m || c < 0 || c >= n || dp[r][c] !== INF) return - dp[r][c] = cost - q.push([r, c]) - const nextDir = grid[r][c] - 1 - const [dx, dy] = dirs[nextDir] - dfs(r + dx, c + dy, cost) - } -} - diff --git a/1368.minimum-cost-to-make-at-least-one-valid-path-in-a-grid.js b/1368.minimum-cost-to-make-at-least-one-valid-path-in-a-grid.js new file mode 100644 index 00000000..7bf13c9d --- /dev/null +++ b/1368.minimum-cost-to-make-at-least-one-valid-path-in-a-grid.js @@ -0,0 +1,30 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +function minCost(grid) { + const m = grid.length, n = grid[0].length + const dirs = [[0, 1], [0, -1], [1, 0], [-1, 0]] // right, left, down, up + const dp = Array.from({ length: m }, () => Array(n).fill(Infinity)) + let q = [[0, 0]] + dp[0][0] = 0 + while(q.length) { + const tmp = [] + for(let idx = q.length - 1; idx >= 0; idx--) { + const [r, c] = q[idx] + for(let i = 0; i < dirs.length; i++) { + const [dr, dc] = dirs[i] + const nr = r + dr, nc = c + dc + if(nr < 0 || nr >= m || nc < 0 || nc >= n) continue + if(dp[nr][nc] > dp[r][c] + (i === grid[r][c] - 1 ? 0 : 1)) { + dp[nr][nc] = dp[r][c] + (i === grid[r][c] - 1 ? 0 : 1) + tmp.push([nr, nc]) + } + } + } + q = tmp + } + + return dp[m - 1][n - 1] +} + diff --git a/137-single-number-ii.js b/137-single-number-ii.js deleted file mode 100644 index 64249683..00000000 --- a/137-single-number-ii.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const singleNumber = function(nums) { - const hash = {} - - nums.forEach(el => { - hash[el] = (hash[el] && hash[el] + 1) || 1 - }) - - for(let el in hash) { - if(hash[el] === 1) return +el - } -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const singleNumber = (nums)=> { - let one=0, two=0; - for (let i=0; i { - // Initialize result - let result = 0; - let x, sum; - const n = nums.length - // Iterate through every bit - for (let i = 0; i < 32; i++) { - // Find sum of set bits at ith position in all - // array elements - sum = 0; - x = (1 << i); - for (let j = 0; j < n; j++ ) { - if (nums[j] & x) sum++; - } - // The bits with sum not multiple of 3, are the - // bits of element with single occurrence. - if (sum % 3) result |= x; - } - return result; -} diff --git a/137.single-number-ii.js b/137.single-number-ii.js new file mode 100644 index 00000000..746731bd --- /dev/null +++ b/137.single-number-ii.js @@ -0,0 +1,16 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const singleNumber = function(nums) { + const hash = {} + + nums.forEach(el => { + hash[el] = (hash[el] && hash[el] + 1) || 1 + }) + + for(let el in hash) { + if(hash[el] === 1) return +el + } +}; + diff --git a/1370-increasing-decreasing-string.js b/1370.increasing-decreasing-string.js similarity index 100% rename from 1370-increasing-decreasing-string.js rename to 1370.increasing-decreasing-string.js diff --git a/1371-find-the-longest-substring-containing-vowels-in-even-counts.js b/1371-find-the-longest-substring-containing-vowels-in-even-counts.js deleted file mode 100644 index 9b9130d8..00000000 --- a/1371-find-the-longest-substring-containing-vowels-in-even-counts.js +++ /dev/null @@ -1,126 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const findTheLongestSubstring = function(s) { - const n = s.length - let res = 0, mask = 0 - const map = new Map([[0, -1]]) - - for(let i = 0; i < n; i++) { - const ch = s[i] - const idx = 'aeiou'.indexOf(ch) - if(idx !== -1) { - mask ^= (1 << idx) - } - if(map.has(mask)) { - res = Math.max(res, i - map.get(mask)) - } else { - map.set(mask, i) - } - } - - return res -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const findTheLongestSubstring = function(s) { - const n = s.length - let res = 0, mask = 0 - const map = new Map([[0, -1]]) - - for(let i = 0; i < n; i++) { - const ch = s[i] - const idx = 'aeiou'.indexOf(ch) - if(idx !== -1) { - mask ^= (1 << idx) - if(map.has(mask)) { - res = Math.max(res, i - map.get(mask)) - } else { - map.set(mask, i) - } - } else { - res = Math.max(res, i - map.get(mask)) - } - } - - return res -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const findTheLongestSubstring = function(s) { - const n = s.length - const ch2num = ch => { - const idx = 'aeiou'.indexOf(ch) - return idx === -1 ? 0 : (1 << idx) - } - let res = 0 - let mask = 0 - const hash = new Map([[0, -1]]) - for (let i = 0; i < n; i++) { - mask ^= ch2num(s[i]) - const first = hash.has(mask) ? hash.get(mask) : i - if (!hash.has(mask)) hash.set(mask, i) - res = Math.max(res, i - first) - } - - return res -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -var findTheLongestSubstring = function (s, V = 'aeiou', max = 0) { - let encode = (c) => { - let i = V.indexOf(c) - return i == -1 ? 0 : 1 << i - } - let N = s.length - let A = Array(N + 1).fill(0) - let seen = new Map([[0, 0]]) - for (let i = 1; i <= N; ++i) { - A[i] = A[i - 1] ^ encode(s[i - 1]) - let first = seen.has(A[i]) ? seen.get(A[i]) : i - if (first == i) seen.set(A[i], i) // first seen A[i] index - max = Math.max(max, i - first) // max of i-th index minus first seen A[i] index - } - return max -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const findTheLongestSubstring = function(s) { - const n = s.length - const ch2num = ch => { - const idx = 'aeiou'.indexOf(ch) - return idx === -1 ? 0 : (1 << idx) - } - let res = 0 - let mask = 0 - const hash = new Map([[0, 0]]) - for (let i = 1; i <= n; i++) { - mask ^= ch2num(s[i - 1]) - const first = hash.has(mask) ? hash.get(mask) : i - if (!hash.has(mask)) hash.set(mask, i) - res = Math.max(res, i - first) - } - - return res -}; diff --git a/1371.find-the-longest-substring-containing-vowels-in-even-counts.js b/1371.find-the-longest-substring-containing-vowels-in-even-counts.js new file mode 100644 index 00000000..b4f77385 --- /dev/null +++ b/1371.find-the-longest-substring-containing-vowels-in-even-counts.js @@ -0,0 +1,25 @@ +/** + * @param {string} s + * @return {number} + */ +const findTheLongestSubstring = function(s) { + const n = s.length + let res = 0, mask = 0 + const map = new Map([[0, -1]]) + + for(let i = 0; i < n; i++) { + const ch = s[i] + const idx = 'aeiou'.indexOf(ch) + if(idx !== -1) { + mask ^= (1 << idx) + } + if(map.has(mask)) { + res = Math.max(res, i - map.get(mask)) + } else { + map.set(mask, i) + } + } + + return res +}; + diff --git a/1373-maximum-sum-bst-in-binary-tree.js b/1373.maximum-sum-bst-in-binary-tree.js similarity index 100% rename from 1373-maximum-sum-bst-in-binary-tree.js rename to 1373.maximum-sum-bst-in-binary-tree.js diff --git a/1374-generate-a-string-with-characters-that-have-odd-counts.js b/1374.generate-a-string-with-characters-that-have-odd-counts.js similarity index 100% rename from 1374-generate-a-string-with-characters-that-have-odd-counts.js rename to 1374.generate-a-string-with-characters-that-have-odd-counts.js diff --git a/1375-number-of-times-binary-string-is-prefix-aligned.js b/1375.number-of-times-binary-string-is-prefix-aligned.js similarity index 100% rename from 1375-number-of-times-binary-string-is-prefix-aligned.js rename to 1375.number-of-times-binary-string-is-prefix-aligned.js diff --git a/1376-time-needed-to-inform-all-employees.js b/1376.time-needed-to-inform-all-employees.js similarity index 100% rename from 1376-time-needed-to-inform-all-employees.js rename to 1376.time-needed-to-inform-all-employees.js diff --git a/1377-frog-position-after-t-seconds.js b/1377-frog-position-after-t-seconds.js deleted file mode 100644 index dd3dabc6..00000000 --- a/1377-frog-position-after-t-seconds.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} edges - * @param {number} t - * @param {number} target - * @return {number} - */ -const frogPosition = function (n, edges, t, target) { - const m = new Map() - for(let e of edges) { - const [from, to] = e - if(!m.has(from - 1)) m.set(from - 1, []) - if(!m.has(to - 1)) m.set(to - 1, []) - m.get(from - 1).push(to - 1) - m.get(to - 1).push(from - 1) - } - const visited = new Set() - visited.add(0) - const q = [0] - const res = [1] - while(q.length && t-- > 0) { - for(let size = q.length; size > 0 ; size--) { - const u = q.shift() - let count = 0 - for(let e of (m.get(u) || [])) { - if(!visited.has(e)) count++ - } - for(let e of (m.get(u) || [])) { - if(visited.has(e)) continue - q.push(e) - visited.add(e) - res[e] = res[u] / count - } - if(count > 0) res[u] = 0 - } - } - return res[target - 1] || 0 -} - -// another - -/** - * @param {number} n - * @param {number[][]} edges - * @param {number} t - * @param {number} target - * @return {number} - */ -const frogPosition = function (n, edges, t, target) { - const graph = { 1: new Set() } - for (let [from, to] of edges) { - if (graph[from]) graph[from].add(to) - else graph[from] = new Set([to]) - if (graph[to]) graph[to].add(from) - else graph[to] = new Set([from]) - } - - // dfs through the graph storing the vetices you've visited, number of jumps, and current vertice - const dfs = (from, numJumps, visited) => { - // if the count equals t then return 1 if the vertice is the target - if (numJumps === t) return from === target ? 1 : 0 - - // average out all the next results - let numEdgesCanJump = 0 - let total = 0 - for (let to of graph[from]) { - if (visited.has(to)) continue - visited.add(to) - total += dfs(to, numJumps + 1, visited) - visited.delete(to) - numEdgesCanJump++ - } - - // if we can jump, average all the next results - // otherwise we can't jump anywhere and return 1 if we are at the target - // if we are not at the target return 0 - if (numEdgesCanJump > 0) { - return total / numEdgesCanJump - } - return from === target ? 1 : 0 - } - return dfs(1, 0, new Set([1])) -} diff --git a/1377.frog-position-after-t-seconds.js b/1377.frog-position-after-t-seconds.js new file mode 100644 index 00000000..cf0f8829 --- /dev/null +++ b/1377.frog-position-after-t-seconds.js @@ -0,0 +1,39 @@ +/** + * @param {number} n + * @param {number[][]} edges + * @param {number} t + * @param {number} target + * @return {number} + */ +const frogPosition = function (n, edges, t, target) { + const m = new Map() + for(let e of edges) { + const [from, to] = e + if(!m.has(from - 1)) m.set(from - 1, []) + if(!m.has(to - 1)) m.set(to - 1, []) + m.get(from - 1).push(to - 1) + m.get(to - 1).push(from - 1) + } + const visited = new Set() + visited.add(0) + const q = [0] + const res = [1] + while(q.length && t-- > 0) { + for(let size = q.length; size > 0 ; size--) { + const u = q.shift() + let count = 0 + for(let e of (m.get(u) || [])) { + if(!visited.has(e)) count++ + } + for(let e of (m.get(u) || [])) { + if(visited.has(e)) continue + q.push(e) + visited.add(e) + res[e] = res[u] / count + } + if(count > 0) res[u] = 0 + } + } + return res[target - 1] || 0 +} + diff --git a/138-copy-list-with-random-pointer.js b/138.copy-list-with-random-pointer.js similarity index 100% rename from 138-copy-list-with-random-pointer.js rename to 138.copy-list-with-random-pointer.js diff --git a/1380-lucky-numbers-in-a-matrix.js b/1380.lucky-numbers-in-a-matrix.js similarity index 100% rename from 1380-lucky-numbers-in-a-matrix.js rename to 1380.lucky-numbers-in-a-matrix.js diff --git a/1381-design-a-stack-with-increment-operation.js b/1381.design-a-stack-with-increment-operation.js similarity index 100% rename from 1381-design-a-stack-with-increment-operation.js rename to 1381.design-a-stack-with-increment-operation.js diff --git a/1382-balance-a-binary-search-tree.js b/1382.balance-a-binary-search-tree.js similarity index 100% rename from 1382-balance-a-binary-search-tree.js rename to 1382.balance-a-binary-search-tree.js diff --git a/1383-maximum-performance-of-a-team.js b/1383-maximum-performance-of-a-team.js deleted file mode 100644 index e741a417..00000000 --- a/1383-maximum-performance-of-a-team.js +++ /dev/null @@ -1,160 +0,0 @@ -/** - * @param {number} n - * @param {number[]} speed - * @param {number[]} efficiency - * @param {number} k - * @return {number} - */ -const maxPerformance = function (n, speed, efficiency, k) { - const arr = zip(speed, efficiency) - arr.sort((a, b) => b[1] - a[1]) - const pq = new PriorityQueue({ - comparator: (a, b) => a <= b, - }) - const M = BigInt(10 ** 9 + 7) - let sumOfSpeed = BigInt(0) - let max = BigInt(0) - for (const [s, e] of arr) { - pq.enqueue(s) - sumOfSpeed += s - if (pq.length > k) { - sumOfSpeed -= pq.dequeue() - } - const tmp = sumOfSpeed * BigInt(e) - if(tmp > max) max = tmp - } - return max % M -} - -function zip(arr1, arr2) { - const arr = [] - for (let i = 0; i < arr1.length; i++) { - arr.push([BigInt(arr1[i]), arr2[i]]) - } - return arr -} - -class PriorityQueue { - constructor({ comparator }) { - this.arr = [] - this.comparator = comparator - } - - enqueue(val) { - this.arr.push(val) - moveUp(this.arr, this.arr.length - 1, this.comparator) - } - - dequeue() { - const output = this.arr[0] - this.arr[0] = this.arr[this.arr.length - 1] - this.arr.pop() - moveDown(this.arr, 0, this.comparator) - return output - } - - get length() { - return this.arr.length - } -} - -function moveUp(arr, i, comparator) { - const p = Math.floor((i - 1) / 2) - const isValid = p < 0 || comparator(arr[p], arr[i]) - if (!isValid) { - ;[arr[i], arr[p]] = [arr[p], arr[i]] - moveUp(arr, p, comparator) - } -} - -function moveDown(arr, i, comparator) { - const left = 2 * i + 1 - const right = 2 * i + 2 - const isValid = - (left >= arr.length || comparator(arr[i], arr[left])) && - (right >= arr.length || comparator(arr[i], arr[right])) - if (!isValid) { - const next = - right >= arr.length || comparator(arr[left], arr[right]) ? left : right - ;[arr[i], arr[next]] = [arr[next], arr[i]] - moveDown(arr, next, comparator) - } -} - -// another - -const MinHeap = () => { - const list = [] - const parent = (index) => Math.floor((index - 1) / 2) - const left = (index) => 2 * index + 1 - const right = (index) => 2 * index + 2 - - const swap = (a, b) => { - const temp = list[a] - list[a] = list[b] - list[b] = temp - } - const insert = (x) => { - list.push(x) - let currentIndex = list.length - 1 - let parentIndex = parent(currentIndex) - while (list[parentIndex] > list[currentIndex]) { - swap(parentIndex, currentIndex) - currentIndex = parentIndex - parentIndex = parent(parentIndex) - } - } - const sink = (index) => { - let minIndex = index - const leftIndex = left(index) - const rightIndex = right(index) - if (list[leftIndex] < list[minIndex]) { - minIndex = leftIndex - } - if (list[rightIndex] < list[minIndex]) { - minIndex = rightIndex - } - if (minIndex !== index) { - swap(minIndex, index) - sink(minIndex) - } - } - const size = () => list.length - const extract = () => { - swap(0, size() - 1) - const min = list.pop() - sink(0) - return min - } - return { - insert, - size, - extract, - } -} - -/** Heap Greedy - * @param {number} n - * @param {number[]} speed - * @param {number[]} efficiency - * @param {number} k - * @return {number} - */ -const maxPerformance = function (n, speed, efficiency, k) { - const works = speed.map((s, index) => [s, efficiency[index]]) - works.sort((a, b) => b[1] - a[1]) - let totalSpeed = 0 - let max = 0 - const minHeap = MinHeap() - for (const work of works) { - if (minHeap.size() >= k) { - const minSpeed = minHeap.extract() - totalSpeed -= minSpeed - } - minHeap.insert(work[0]) - totalSpeed += work[0] - max = Math.max(max, totalSpeed * work[1]) - } - const result = max % (10 ** 9 + 7) - return result === 301574163 ? result + 1 : result -} diff --git a/1383.maximum-performance-of-a-team.js b/1383.maximum-performance-of-a-team.js new file mode 100644 index 00000000..a2e43d08 --- /dev/null +++ b/1383.maximum-performance-of-a-team.js @@ -0,0 +1,83 @@ +/** + * @param {number} n + * @param {number[]} speed + * @param {number[]} efficiency + * @param {number} k + * @return {number} + */ +const maxPerformance = function (n, speed, efficiency, k) { + const arr = zip(speed, efficiency) + arr.sort((a, b) => b[1] - a[1]) + const pq = new PriorityQueue({ + comparator: (a, b) => a <= b, + }) + const M = BigInt(10 ** 9 + 7) + let sumOfSpeed = BigInt(0) + let max = BigInt(0) + for (const [s, e] of arr) { + pq.enqueue(s) + sumOfSpeed += s + if (pq.length > k) { + sumOfSpeed -= pq.dequeue() + } + const tmp = sumOfSpeed * BigInt(e) + if(tmp > max) max = tmp + } + return max % M +} + +function zip(arr1, arr2) { + const arr = [] + for (let i = 0; i < arr1.length; i++) { + arr.push([BigInt(arr1[i]), arr2[i]]) + } + return arr +} + +class PriorityQueue { + constructor({ comparator }) { + this.arr = [] + this.comparator = comparator + } + + enqueue(val) { + this.arr.push(val) + moveUp(this.arr, this.arr.length - 1, this.comparator) + } + + dequeue() { + const output = this.arr[0] + this.arr[0] = this.arr[this.arr.length - 1] + this.arr.pop() + moveDown(this.arr, 0, this.comparator) + return output + } + + get length() { + return this.arr.length + } +} + +function moveUp(arr, i, comparator) { + const p = Math.floor((i - 1) / 2) + const isValid = p < 0 || comparator(arr[p], arr[i]) + if (!isValid) { + ;[arr[i], arr[p]] = [arr[p], arr[i]] + moveUp(arr, p, comparator) + } +} + +function moveDown(arr, i, comparator) { + const left = 2 * i + 1 + const right = 2 * i + 2 + const isValid = + (left >= arr.length || comparator(arr[i], arr[left])) && + (right >= arr.length || comparator(arr[i], arr[right])) + if (!isValid) { + const next = + right >= arr.length || comparator(arr[left], arr[right]) ? left : right + ;[arr[i], arr[next]] = [arr[next], arr[i]] + moveDown(arr, next, comparator) + } +} + diff --git a/1385-find-the-distance-value-between-two-arrays.js b/1385.find-the-distance-value-between-two-arrays.js similarity index 100% rename from 1385-find-the-distance-value-between-two-arrays.js rename to 1385.find-the-distance-value-between-two-arrays.js diff --git a/1387-sort-integers-by-the-power-value.js b/1387.sort-integers-by-the-power-value.js similarity index 100% rename from 1387-sort-integers-by-the-power-value.js rename to 1387.sort-integers-by-the-power-value.js diff --git a/1388-pizza-with-3n-slices.js b/1388-pizza-with-3n-slices.js deleted file mode 100644 index 5b214871..00000000 --- a/1388-pizza-with-3n-slices.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @param {number[]} slices - * @return {number} - */ -const maxSizeSlices = function (slices) { - const m = slices.length, - n = (m / 3) >> 0 - const slices1 = slices.slice(0, m - 1) - const slices2 = slices.slice(1, m) - return Math.max(maxSum(slices1, n), maxSum(slices2, n)) -} - -function maxSum(arr, n) { - // max sum when pick `n` non-adjacent elements from `arr` - const m = arr.length - // dp[i][j] is maximum sum which we pick `j` elements from linear array `i` elements - const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)) - // Case j = 0 (pick 0 elements): dp[i][0] = 0 - // Case i = 0 (array is empty): dp[0][j] = 0 - for (let i = 1; i <= m; ++i) { - for (let j = 1; j <= n; ++j) { - if (i === 1) { - // array has only 1 element - // pick that element - dp[i][j] = arr[0] - } else { - dp[i][j] = Math.max( - // don't pick element `ith` - dp[i - 1][j], - // pick element `ith` -> dp[i-2][j-1] means choose `j-1` elements from array `i-2` elements - // because we exclude adjacent element `(i-1)th` - dp[i - 2][j - 1] + arr[i - 1] - ) - } - } - } - return dp[m][n] -} - - -// another - -/** - * @param {number[]} slices - * @return {number} - */ -const maxSizeSlices = function (slices) { - const n = slices.length, m = ~~(n / 3) - const arr1 = slices.slice(1), arr2 = slices.slice(0, n - 1) - return Math.max(helper(arr1, m), helper(arr2, m)) - function helper(arr, k) { - const len = arr.length - const dp = Array.from({ length: len + 1 }, () => Array(k + 1).fill(0)) - for(let i = 1; i <= len; i++) { - for(let j = 1; j <= k; j++) { - if(i === 1) dp[i][j] = arr[i - 1] - else { - dp[i][j] = Math.max( - dp[i - 1][j], - dp[i - 2][j - 1] + arr[i - 1] - ) - } - } - } - return dp[len][k] - } -} diff --git a/1388.pizza-with-3n-slices.js b/1388.pizza-with-3n-slices.js new file mode 100644 index 00000000..1bc445e7 --- /dev/null +++ b/1388.pizza-with-3n-slices.js @@ -0,0 +1,40 @@ +/** + * @param {number[]} slices + * @return {number} + */ +const maxSizeSlices = function (slices) { + const m = slices.length, + n = (m / 3) >> 0 + const slices1 = slices.slice(0, m - 1) + const slices2 = slices.slice(1, m) + return Math.max(maxSum(slices1, n), maxSum(slices2, n)) +} + +function maxSum(arr, n) { + // max sum when pick `n` non-adjacent elements from `arr` + const m = arr.length + // dp[i][j] is maximum sum which we pick `j` elements from linear array `i` elements + const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)) + // Case j = 0 (pick 0 elements): dp[i][0] = 0 + // Case i = 0 (array is empty): dp[0][j] = 0 + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + if (i === 1) { + // array has only 1 element + // pick that element + dp[i][j] = arr[0] + } else { + dp[i][j] = Math.max( + // don't pick element `ith` + dp[i - 1][j], + // pick element `ith` -> dp[i-2][j-1] means choose `j-1` elements from array `i-2` elements + // because we exclude adjacent element `(i-1)th` + dp[i - 2][j - 1] + arr[i - 1] + ) + } + } + } + return dp[m][n] +} + + diff --git a/1389-create-target-array-in-the-given-order.js b/1389.create-target-array-in-the-given-order.js similarity index 100% rename from 1389-create-target-array-in-the-given-order.js rename to 1389.create-target-array-in-the-given-order.js diff --git a/139-word-break.js b/139-word-break.js deleted file mode 100644 index ad37fdf0..00000000 --- a/139-word-break.js +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @param {string} s - * @param {string[]} wordDict - * @return {boolean} - */ -const wordBreak = function(s, wordDict) { - const map = new Map() - return helper(s, 0, new Set(wordDict), map) -}; - -function helper(str, idx, set, map) { - if(idx === str.length) return true - if(map.has(idx)) return map.get(idx) - let res = false - for(let i = idx; i < str.length; i++) { - const tmp = str.slice(idx, i + 1) - if(set.has(tmp)) { - const bool = helper(str, i + 1, set, map) - if(bool) { - res = true - break - } - } - } - map.set(idx, res) - return res -} - -// another - - -/** - * @param {string} s - * @param {string[]} wordDict - * @return {boolean} - */ -const wordBreak = function(s, wordDict) { - const len = s.length; - const dp = new Array(len).fill(false); - - for (let i = 0; i < len; i++) { - for (let word of wordDict) { - if (word.length <= i + 1 - && s.substring(i - word.length + 1, i + 1) === word) { - let index = i - word.length; - if (index < 0) { - dp[i] = true; - } else { - dp[i] = dp[index]; - } - if(dp[i]) break; - } - } - } - - return dp[len - 1]; -}; - -// another - -/** - * @param {string} s - * @param {string[]} wordDict - * @return {boolean} - */ -const wordBreak = function(s, wordDict) { - const len = s.length; - const f = new Array(len + 1).fill(false); - - f[0] = true; - - for(let i = 1; i <= len; i++){ - for(let str of wordDict){ - if(str.length <= i - && f[i - str.length] - && s.slice(i - str.length, i) === str){ - f[i] = true; - break; - } - } - } - - return f[len]; -}; - - -// another - -/** - * @param {string} s - * @param {string[]} wordDict - * @return {boolean} - */ -const wordBreak = function(s, wordDict) { - const set = new Set(wordDict) - const dp = Array(s.length + 1).fill(false) - dp[0] = true - for(let i = 1; i <= s.length; i++) { - for(let j = 0; j < i; j++) { - if(dp[j] && set.has(s.slice(j, i))) { - dp[i] = true - break - } - } - } - - return dp[s.length] -}; - diff --git a/139.word-break.js b/139.word-break.js new file mode 100644 index 00000000..7dfc1501 --- /dev/null +++ b/139.word-break.js @@ -0,0 +1,28 @@ +/** + * @param {string} s + * @param {string[]} wordDict + * @return {boolean} + */ +const wordBreak = function(s, wordDict) { + const map = new Map() + return helper(s, 0, new Set(wordDict), map) +}; + +function helper(str, idx, set, map) { + if(idx === str.length) return true + if(map.has(idx)) return map.get(idx) + let res = false + for(let i = idx; i < str.length; i++) { + const tmp = str.slice(idx, i + 1) + if(set.has(tmp)) { + const bool = helper(str, i + 1, set, map) + if(bool) { + res = true + break + } + } + } + map.set(idx, res) + return res +} + diff --git a/1390-four-divisors.js b/1390.four-divisors.js similarity index 100% rename from 1390-four-divisors.js rename to 1390.four-divisors.js diff --git a/1392-longest-happy-prefix.js b/1392.longest-happy-prefix.js similarity index 100% rename from 1392-longest-happy-prefix.js rename to 1392.longest-happy-prefix.js diff --git a/1394-find-lucky-integer-in-an-array.js b/1394.find-lucky-integer-in-an-array.js similarity index 100% rename from 1394-find-lucky-integer-in-an-array.js rename to 1394.find-lucky-integer-in-an-array.js diff --git a/1395-count-number-of-teams.js b/1395-count-number-of-teams.js deleted file mode 100644 index 076cd0ff..00000000 --- a/1395-count-number-of-teams.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @param {number[]} rating - * @return {number} - */ -const numTeams = function(rating) { - let res = 0 - for(let i = 1, n = rating.length; i < n - 1; i++) { - const less = Array(2).fill(0), greater = Array(2).fill(0) - for(let j = 0; j < n; j++) { - if(rating[i] > rating[j]) { - less[j < i ? 0 : 1]++ - } - if(rating[i] < rating[j]) { - greater[j > i ? 0 : 1]++ - } - } - res += less[0] * greater[0] + less[1] * greater[1] - } - return res -}; - - -// another - -/** - * @param {number[]} rating - * @return {number} - */ -const numTeams = function(rating) { - if(rating.length < 3) return 0 - const n = rating.length - const leftTree = Array(1e5 + 1).fill(0) - const rightTree = Array(1e5 + 1).fill(0) - for(let r of rating) update(rightTree, r, 1) - let res = 0 - for(let r of rating) { - update(rightTree, r, -1) - res += getPrefixSum(leftTree, r - 1) * getSuffixSum(rightTree, r + 1) - res += getSuffixSum(leftTree, r + 1) * getPrefixSum(rightTree, r - 1) - update(leftTree, r, 1) - } - - return res -}; - -function update(bit, index, val) { - while(index < bit.length) { - bit[index] += val - index += index & (-index) - } -} - -function getPrefixSum(bit, index) { - let res = 0 - while(index > 0) { - res += bit[index] - index -= index & (-index) - } - return res -} - -function getSuffixSum(bit, index) { - return getPrefixSum(bit, 1e5) - getPrefixSum(bit, index - 1) -} diff --git a/1395.count-number-of-teams.js b/1395.count-number-of-teams.js new file mode 100644 index 00000000..6bb67762 --- /dev/null +++ b/1395.count-number-of-teams.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} rating + * @return {number} + */ +const numTeams = function(rating) { + let res = 0 + for(let i = 1, n = rating.length; i < n - 1; i++) { + const less = Array(2).fill(0), greater = Array(2).fill(0) + for(let j = 0; j < n; j++) { + if(rating[i] > rating[j]) { + less[j < i ? 0 : 1]++ + } + if(rating[i] < rating[j]) { + greater[j > i ? 0 : 1]++ + } + } + res += less[0] * greater[0] + less[1] * greater[1] + } + return res +}; + + diff --git a/1396-count-number-of-teams.js b/1396.count-number-of-teams.js similarity index 100% rename from 1396-count-number-of-teams.js rename to 1396.count-number-of-teams.js diff --git a/1396-design-underground-system.js b/1396.design-underground-system.js similarity index 100% rename from 1396-design-underground-system.js rename to 1396.design-underground-system.js diff --git a/1397-find-all-good-strings.js b/1397.find-all-good-strings.js similarity index 100% rename from 1397-find-all-good-strings.js rename to 1397.find-all-good-strings.js diff --git a/1399-count-largest-group.js b/1399.count-largest-group.js similarity index 100% rename from 1399-count-largest-group.js rename to 1399.count-largest-group.js diff --git a/14-longest-common-prefix.js b/14-longest-common-prefix.js deleted file mode 100755 index e3d757f2..00000000 --- a/14-longest-common-prefix.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @param {string[]} strs - * @return {string} - */ -const longestCommonPrefix = function(strs) { - const A = strs.concat().sort(), - a1 = A[0] || "", - a2 = A[A.length - 1] || "", - L = a1.length, - i = 0; - while (i < L && a1.charAt(i) === a2.charAt(i)) i++; - return a1.substring(0, i); -}; diff --git a/14.longest-common-prefix.js b/14.longest-common-prefix.js new file mode 100644 index 00000000..29f07093 --- /dev/null +++ b/14.longest-common-prefix.js @@ -0,0 +1,13 @@ +/** + * @param {string[]} strs + * @return {string} + */ +const longestCommonPrefix = function(strs) { + const A = strs.concat().sort(), + a1 = A[0] || "", + a2 = A[A.length - 1] || "", + L = a1.length, + i = 0; + while (i < L && a1.charAt(i) === a2.charAt(i)) i++; + return a1.substring(0, i); +}; diff --git a/140-word-break-ii.js b/140-word-break-ii.js deleted file mode 100644 index 36070c6a..00000000 --- a/140-word-break-ii.js +++ /dev/null @@ -1,122 +0,0 @@ -/** - * @param {string} s - * @param {string[]} wordDict - * @return {string[]} - */ -const wordBreak = function(s, wordDict) { - const set = new Set(wordDict) - const map = new Map() - return helper(s, 0, set, map) -}; - -function helper(str, idx, set, map) { - if(idx === str.length) return [] - if(map.has(idx)) return map.get(idx) - const res = [] - for(let i = idx; i < str.length; i++) { - const tmp = str.slice(idx, i + 1) - if(set.has(tmp)) { - const arr = helper(str, i + 1, set, map) - if(i === str.length - 1) res.push(tmp) - for(let item of arr) { - res.push(`${tmp} ${item}`) - } - } - } - map.set(idx, res) - return res -} -// another - - -/** - * @param {string} s - * @param {string[]} wordDict - * @return {string[]} - */ -const wordBreak = function(s, wordDict) { - return backTrack(s, wordDict, {}) -}; - -function backTrack(s, wordDict, mem) { - if(mem.hasOwnProperty(s)) return mem[s] - const result = [] - for(let word of wordDict) { - if(s.startsWith(word)) { - let next = s.slice(word.length) - if(next.length === 0) result.push(word) - else { - for(let sub of backTrack(next, wordDict, mem)) { - result.push(word+ ' '+sub) - } - } - } - } - mem[s] = result - return result -} - -// another - -/** - * @param {string} s - * @param {string[]} wordDict - * @return {string[]} - */ -const wordBreak = function (s, wordDict) { - const dictSet = new Set(wordDict) - const memo = {} - function dfs(start) { - if (start > s.length - 1) { - return [[]] - } - if (memo[start] !== undefined) { - return memo[start] - } - const out = [] - for (let i = start; i < s.length; i++) { - const substr = s.substring(start, i + 1) - if (dictSet.has(substr)) { - let next = dfs(i + 1) - for (let n of next) { - out.push([substr, ...n]) - } - } - } - return (memo[start] = out) - } - const res = dfs(0) - return res.filter((a) => a.join('') === s).map((a) => a.join(' ')) -} - -// another - -/** - * @param {string} s - * @param {string[]} wordDict - * @return {string[]} - */ - -const wordBreak = (s, wordDict) => { - const set = new Set(wordDict) - return helper(s, 0, set) -} - -function helper(s, idx, dict) { - if(idx === s.length) return [] - const res = [] - for(let i = idx; i < s.length; i++) { - const tmp = s.slice(idx, i + 1) - if(dict.has(tmp)) { - const arr = helper(s, i + 1, dict) - if(i + 1 >= s.length) { - res.push(tmp) - } else if(arr.length) { - for(let e of arr) { - res.push(tmp + ' ' + e) - } - } - } - } - return res -} diff --git a/140.word-break-ii.js b/140.word-break-ii.js new file mode 100644 index 00000000..9ad89448 --- /dev/null +++ b/140.word-break-ii.js @@ -0,0 +1,28 @@ +/** + * @param {string} s + * @param {string[]} wordDict + * @return {string[]} + */ +const wordBreak = function(s, wordDict) { + const set = new Set(wordDict) + const map = new Map() + return helper(s, 0, set, map) +}; + +function helper(str, idx, set, map) { + if(idx === str.length) return [] + if(map.has(idx)) return map.get(idx) + const res = [] + for(let i = idx; i < str.length; i++) { + const tmp = str.slice(idx, i + 1) + if(set.has(tmp)) { + const arr = helper(str, i + 1, set, map) + if(i === str.length - 1) res.push(tmp) + for(let item of arr) { + res.push(`${tmp} ${item}`) + } + } + } + map.set(idx, res) + return res +} diff --git a/1402-reducing-dishes.js b/1402.reducing-dishes.js similarity index 100% rename from 1402-reducing-dishes.js rename to 1402.reducing-dishes.js diff --git a/1404-number-of-steps-to-reduce-a-number-in-binary-representation-to-one.js b/1404.number-of-steps-to-reduce-a-number-in-binary-representation-to-one.js similarity index 100% rename from 1404-number-of-steps-to-reduce-a-number-in-binary-representation-to-one.js rename to 1404.number-of-steps-to-reduce-a-number-in-binary-representation-to-one.js diff --git a/1405-longest-happy-string.js b/1405-longest-happy-string.js deleted file mode 100644 index d86f669f..00000000 --- a/1405-longest-happy-string.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * @param {number} a - * @param {number} b - * @param {number} c - * @return {string} - */ -const longestDiverseString = function (a, b, c) { - const arr = [['a', a], ['b', b], ['c', c]] - - let res = '' - while(true) { - arr.sort((a, b) => b[1] - a[1]) - if(res.length >= 2 && arr[0][0] === res[res.length - 1] && arr[0][0] === res[res.length - 2]) { - if(arr[1][1] > 0) { - res += arr[1][0] - arr[1][1]-- - } else break - } else { - if(arr[0][1] > 0) { - res += arr[0][0] - arr[0][1]-- - } else break - } - } - - return res -}; - - -// another - - -/** - * @param {number} a - * @param {number} b - * @param {number} c - * @return {string} - */ -const longestDiverseString = function (a, b, c) { - return generate(a, b, c, "a", "b", "c"); -}; - -function generate(a, b, c, ac, bc, cc) { - if (a < b) return generate(b, a, c, bc, ac, cc); - if (b < c) return generate(a, c, b, ac, cc, bc); - if (b === 0) return ac.repeat(Math.min(2, a)); - let use_a = Math.min(2, a), - use_b = a - use_a >= b ? 1 : 0; - return ( - ac.repeat(use_a) + - bc.repeat(use_b) + - generate(a - use_a, b - use_b, c, ac, bc, cc) - ); -} - -// another - -/** - * @param {number} a - * @param {number} b - * @param {number} c - * @return {string} - */ -const longestDiverseString = function (a, b, c) { - const n = a + b + c - let res = '' - let A = 0, B = 0, C = 0 - for(let i = 0; i < n; i++) { - if((a >= c && a >= b && A !== 2) || (B === 2 && a > 0) || (C === 2 && a > 0)) { - A++ - res += 'a' - a-- - B = 0 - C = 0 - } else if((b >= c && b >= a && B !== 2) || (A === 2 && b > 0) || (C === 2 && b)) { - B++ - res += 'b' - b-- - A = 0 - C = 0 - } else if((c >= a && c >= b && C !== 2) || (A === 2 && c) || (B === 2 && c)) { - C++ - res += 'c' - c-- - A = 0 - B = 0 - } - } - - return res -}; - - diff --git a/1405.longest-happy-string.js b/1405.longest-happy-string.js new file mode 100644 index 00000000..dde37d90 --- /dev/null +++ b/1405.longest-happy-string.js @@ -0,0 +1,29 @@ +/** + * @param {number} a + * @param {number} b + * @param {number} c + * @return {string} + */ +const longestDiverseString = function (a, b, c) { + const arr = [['a', a], ['b', b], ['c', c]] + + let res = '' + while(true) { + arr.sort((a, b) => b[1] - a[1]) + if(res.length >= 2 && arr[0][0] === res[res.length - 1] && arr[0][0] === res[res.length - 2]) { + if(arr[1][1] > 0) { + res += arr[1][0] + arr[1][1]-- + } else break + } else { + if(arr[0][1] > 0) { + res += arr[0][0] + arr[0][1]-- + } else break + } + } + + return res +}; + + diff --git a/1406-stone-game-iii.js b/1406-stone-game-iii.js deleted file mode 100644 index d837f6f5..00000000 --- a/1406-stone-game-iii.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @param {number[]} stoneValue - * @return {string} - */ -const stoneGameIII = function (stoneValue) { - const n = stoneValue.length - const suffixSum = new Array(n + 1) - const dp = new Array(n + 1) - suffixSum[n] = 0 - dp[n] = 0 - for (let i = n - 1; i >= 0; i--) - suffixSum[i] = suffixSum[i + 1] + stoneValue[i] - for (let i = n - 1; i >= 0; i--) { - dp[i] = stoneValue[i] + suffixSum[i + 1] - dp[i + 1] - for (let k = i + 1; k < i + 3 && k < n; k++) { - dp[i] = Math.max(dp[i], suffixSum[i] - dp[k + 1]) - } - } - if (dp[0] * 2 === suffixSum[0]) return 'Tie' - else if (dp[0] * 2 > suffixSum[0]) return 'Alice' - else return 'Bob' -} - -// another - -/** - * @param {number[]} stoneValue - * @return {string} - */ -const stoneGameIII = function (stoneValue) { - const n = stoneValue.length, - dp = new Array(4).fill(0) - for (let i = n - 1; i >= 0; --i) { - dp[i % 4] = -Infinity - for (let k = 0, take = 0; k < 3 && i + k < n; ++k) { - take += stoneValue[i + k] - dp[i % 4] = Math.max(dp[i % 4], take - dp[(i + k + 1) % 4]) - } - } - if (dp[0] > 0) return 'Alice' - if (dp[0] < 0) return 'Bob' - return 'Tie' -} diff --git a/1406.stone-game-iii.js b/1406.stone-game-iii.js new file mode 100644 index 00000000..d06be7de --- /dev/null +++ b/1406.stone-game-iii.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} stoneValue + * @return {string} + */ +const stoneGameIII = function (stoneValue) { + const n = stoneValue.length + const suffixSum = new Array(n + 1) + const dp = new Array(n + 1) + suffixSum[n] = 0 + dp[n] = 0 + for (let i = n - 1; i >= 0; i--) + suffixSum[i] = suffixSum[i + 1] + stoneValue[i] + for (let i = n - 1; i >= 0; i--) { + dp[i] = stoneValue[i] + suffixSum[i + 1] - dp[i + 1] + for (let k = i + 1; k < i + 3 && k < n; k++) { + dp[i] = Math.max(dp[i], suffixSum[i] - dp[k + 1]) + } + } + if (dp[0] * 2 === suffixSum[0]) return 'Tie' + else if (dp[0] * 2 > suffixSum[0]) return 'Alice' + else return 'Bob' +} + diff --git a/1408-string-matching-in-an-array.js b/1408.string-matching-in-an-array.js similarity index 100% rename from 1408-string-matching-in-an-array.js rename to 1408.string-matching-in-an-array.js diff --git a/1409-queries-on-a-permutation-with-key.js b/1409.queries-on-a-permutation-with-key.js similarity index 100% rename from 1409-queries-on-a-permutation-with-key.js rename to 1409.queries-on-a-permutation-with-key.js diff --git a/141-linked-list-cycle.js b/141.linked-list-cycle.js similarity index 100% rename from 141-linked-list-cycle.js rename to 141.linked-list-cycle.js diff --git a/1410-html-entity-parser.js b/1410.html-entity-parser.js similarity index 100% rename from 1410-html-entity-parser.js rename to 1410.html-entity-parser.js diff --git a/1411-number-of-ways-to-paint-n-3-grid.js b/1411-number-of-ways-to-paint-n-3-grid.js deleted file mode 100644 index 199a4a5b..00000000 --- a/1411-number-of-ways-to-paint-n-3-grid.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const numOfWays = function(n) { - const mod = 1e9 + 7 - let colors3 = 6, colors2 = 6 - - for(let i = 1; i < n; i++) { - const colors3Tmp = colors3 - colors3 = (2 * colors3 + 2 * colors2) % mod - colors2 = (2 * colors3Tmp + 3 * colors2) % mod - } - - - return (colors2 + colors3) % mod -}; - -// another - - -/** - * @param {number} n - * @return {number} - */ -const numOfWays = function (n) { - let a121 = 6, - a123 = 6, - b121, - b123, - mod = 1e9 + 7 - for (let i = 1; i < n; ++i) { - b121 = a121 * 3 + a123 * 2 - b123 = a121 * 2 + a123 * 2 - a121 = b121 % mod - a123 = b123 % mod - } - return (a121 + a123) % mod -} diff --git a/1411.number-of-ways-to-paint-n-3-grid.js b/1411.number-of-ways-to-paint-n-3-grid.js new file mode 100644 index 00000000..116340bb --- /dev/null +++ b/1411.number-of-ways-to-paint-n-3-grid.js @@ -0,0 +1,18 @@ +/** + * @param {number} n + * @return {number} + */ +const numOfWays = function(n) { + const mod = 1e9 + 7 + let colors3 = 6, colors2 = 6 + + for(let i = 1; i < n; i++) { + const colors3Tmp = colors3 + colors3 = (2 * colors3 + 2 * colors2) % mod + colors2 = (2 * colors3Tmp + 3 * colors2) % mod + } + + + return (colors2 + colors3) % mod +}; + diff --git a/1413-minimum-value-to-get-positive-step-by-step-sum.js b/1413.minimum-value-to-get-positive-step-by-step-sum.js similarity index 100% rename from 1413-minimum-value-to-get-positive-step-by-step-sum.js rename to 1413.minimum-value-to-get-positive-step-by-step-sum.js diff --git a/1415-the-k-th-lexicographical-string-of-all-happy-strings-of-length-n.js b/1415-the-k-th-lexicographical-string-of-all-happy-strings-of-length-n.js deleted file mode 100644 index e5568823..00000000 --- a/1415-the-k-th-lexicographical-string-of-all-happy-strings-of-length-n.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @param {number} n - * @param {number} k - * @return {string} - */ -const getHappyString = function(n, k) { - const hash = {a: 'bc', b: 'ac', c: 'ab'} - const q = ['a', 'b', 'c'] - while(q[0].length !== n) { - const e = q.shift() - const last = e.charAt(e.length - 1) - for(const ch of hash[last]) { - q.push(e + ch) - } - } - if(q.length >= k && q[k - 1].length === n) { - return q[k - 1] - } - - return '' -}; - -// another - -/** - * @param {number} n - * @param {number} k - * @return {string} - */ -const getHappyString = function(n, k) { - const hash = {a: 'bc', b: 'ac', c: 'ab'} - const q = ['a', 'b', 'c'] - while(q[0].length !== n) { - const pre = q.shift() - for(const ch of hash[pre[pre.length - 1]]) { - q.push(pre + ch) - } - } - - return q.length >= k ? q[k - 1] : '' -}; - -// another - -/** - * @param {number} n - * @param {number} k - * @return {string} - */ -var getHappyString = function(n, k) { - const res = [] - dfs() - return res.length === k ? res[res.length - 1] : '' - function dfs(path = '') { - if(res.length === k) return - if(path.length === n) { - res.push(path) - return - } - for(const e of 'abc') { - if(path === '' || e !== path[path.length - 1]) { - dfs(path + e) - } - } - } -}; diff --git a/1415.the-k-th-lexicographical-string-of-all-happy-strings-of-length-n.js b/1415.the-k-th-lexicographical-string-of-all-happy-strings-of-length-n.js new file mode 100644 index 00000000..aef031fe --- /dev/null +++ b/1415.the-k-th-lexicographical-string-of-all-happy-strings-of-length-n.js @@ -0,0 +1,22 @@ +/** + * @param {number} n + * @param {number} k + * @return {string} + */ +const getHappyString = function(n, k) { + const hash = {a: 'bc', b: 'ac', c: 'ab'} + const q = ['a', 'b', 'c'] + while(q[0].length !== n) { + const e = q.shift() + const last = e.charAt(e.length - 1) + for(const ch of hash[last]) { + q.push(e + ch) + } + } + if(q.length >= k && q[k - 1].length === n) { + return q[k - 1] + } + + return '' +}; + diff --git a/1416-restore-the-array.js b/1416-restore-the-array.js deleted file mode 100644 index de517075..00000000 --- a/1416-restore-the-array.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @param {string} s - * @param {number} k - * @return {number} - */ -const numberOfArrays = function (s, k) { - const n = s.length - // dp[i] is number of ways to print valid arrays from string s start at i - const dp = Array(n) - return dfs(s, k, 0, dp) -} - -function dfs(s, k, i, dp) { - const mod = 10 ** 9 + 7 - // base case -> Found a valid way - if (i === s.length) return 1 - // all numbers are in range [1, k] and there are no leading zeros - // So numbers starting with 0 mean invalid! - if (s.charAt(i) === '0') return 0 - if (dp[i] != null) return dp[i] - let ans = 0 - let num = 0 - for (let j = i; j < s.length; j++) { - // num is the value of the substring s[i..j] - num = num * 10 + (+s.charAt(j)) - // num must be in range [1, k] - if (num > k) break - ans += dfs(s, k, j + 1, dp) - ans %= mod - } - return (dp[i] = ans) -} - -// another - -/** - * @param {string} s - * @param {number} k - * @return {number} - */ -const numberOfArrays = function (s, k) { - const mod = 10 ** 9 + 7 - const n = s.length - const dp = new Array(n + 1).fill(0) - dp[n] = 1 - for (let i = n - 1; i >= 0; i--) { - if (s[i] === '0') continue - else { - let temp = s[i] - for (let j = i + 1; j <= n; j++) { - if (temp > k) break - dp[i] = (dp[i] + dp[j]) % mod - if (j < n) { - temp = temp * 10 + parseInt(s[j]) - } - } - } - } - return parseInt(dp[0]) -} - diff --git a/1416.restore-the-array.js b/1416.restore-the-array.js new file mode 100644 index 00000000..ce0c845c --- /dev/null +++ b/1416.restore-the-array.js @@ -0,0 +1,33 @@ +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +const numberOfArrays = function (s, k) { + const n = s.length + // dp[i] is number of ways to print valid arrays from string s start at i + const dp = Array(n) + return dfs(s, k, 0, dp) +} + +function dfs(s, k, i, dp) { + const mod = 10 ** 9 + 7 + // base case -> Found a valid way + if (i === s.length) return 1 + // all numbers are in range [1, k] and there are no leading zeros + // So numbers starting with 0 mean invalid! + if (s.charAt(i) === '0') return 0 + if (dp[i] != null) return dp[i] + let ans = 0 + let num = 0 + for (let j = i; j < s.length; j++) { + // num is the value of the substring s[i..j] + num = num * 10 + (+s.charAt(j)) + // num must be in range [1, k] + if (num > k) break + ans += dfs(s, k, j + 1, dp) + ans %= mod + } + return (dp[i] = ans) +} + diff --git a/1417-reformat-the-string.js b/1417.reformat-the-string.js similarity index 100% rename from 1417-reformat-the-string.js rename to 1417.reformat-the-string.js diff --git a/142-linked-list-cycle-ii.js b/142-linked-list-cycle-ii.js deleted file mode 100644 index ec8083fb..00000000 --- a/142-linked-list-cycle-ii.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ - -/** - * @param {ListNode} head - * @return {ListNode} - */ -const detectCycle = function(head) { - if(head === null || head.next === null) return null - let fast = head - let slow = head - let start = head - while(fast !== null && fast.next !== null) { - fast = fast.next.next - slow = slow.next - if(fast === slow) { - while(slow !== start) { - slow = slow.next - start = start.next - } - return start - } - } - return null -}; - -// another method - -/** - * @param {ListNode} head - * @return {ListNode} - */ -const detectCycle = (head) => { - if (!head) return head; - let currentNode = head; - let previousNode = true; - while (currentNode) { - if (currentNode.previous) return currentNode - if (!currentNode.previous) { - currentNode.previous = previousNode; - previousNode = currentNode; - currentNode = currentNode.next; - } - } - return null; -}; diff --git a/142.linked-list-cycle-ii.js b/142.linked-list-cycle-ii.js new file mode 100644 index 00000000..78130812 --- /dev/null +++ b/142.linked-list-cycle-ii.js @@ -0,0 +1,31 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ + +/** + * @param {ListNode} head + * @return {ListNode} + */ +const detectCycle = function(head) { + if(head === null || head.next === null) return null + let fast = head + let slow = head + let start = head + while(fast !== null && fast.next !== null) { + fast = fast.next.next + slow = slow.next + if(fast === slow) { + while(slow !== start) { + slow = slow.next + start = start.next + } + return start + } + } + return null +}; + diff --git a/1422-maximum-score-after-splitting-a-string.js b/1422-maximum-score-after-splitting-a-string.js deleted file mode 100644 index 916bae85..00000000 --- a/1422-maximum-score-after-splitting-a-string.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const maxScore = function(s) { - const n = s.length - let res = 0, numOfOne = 0 - for(let ch of s) { - if(ch === '1') numOfOne++ - } - for(let i = 0, one = 0; i < n - 1; i++) { - if(s[i] === '1') one++ - res = Math.max(res, (i + 1 - one) + (numOfOne - one)) - } - - return res -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const maxScore = function(s) { - const n = s.length - let res = -Infinity, one = 0, zero = 0 - for(let i = 0; i < n; i++) { - s[i] === '0' ? zero++ : one++ - if(i !== n - 1) res = Math.max(res, zero - one) - } - - return res + one -}; diff --git a/1422.maximum-score-after-splitting-a-string.js b/1422.maximum-score-after-splitting-a-string.js new file mode 100644 index 00000000..42a56b61 --- /dev/null +++ b/1422.maximum-score-after-splitting-a-string.js @@ -0,0 +1,18 @@ +/** + * @param {string} s + * @return {number} + */ +const maxScore = function(s) { + const n = s.length + let res = 0, numOfOne = 0 + for(let ch of s) { + if(ch === '1') numOfOne++ + } + for(let i = 0, one = 0; i < n - 1; i++) { + if(s[i] === '1') one++ + res = Math.max(res, (i + 1 - one) + (numOfOne - one)) + } + + return res +}; + diff --git a/1424-diagonal-traverse-ii.js b/1424.diagonal-traverse-ii.js similarity index 100% rename from 1424-diagonal-traverse-ii.js rename to 1424.diagonal-traverse-ii.js diff --git a/1425-constrained-subsequence-sum.js b/1425-constrained-subsequence-sum.js deleted file mode 100644 index 81ac967e..00000000 --- a/1425-constrained-subsequence-sum.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const constrainedSubsetSum = function(nums, k) { - const window = [[0,nums[0]]]; - let max = nums[0]; - for(let i=1; i0 && window[window.length-1][1] < sum){ - window.pop(); - } - window.push([i,sum]); - } - return max; -}; - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const constrainedSubsetSum = function (nums, k) { - const dll = new DLL() - dll.push([0, nums[0]]) - let max = nums[0] - for (let i = 1; i < nums.length; i++) { - if (!dll.isEmpty() && i - dll.peek().val[0] > k) { - dll.shift() - } - const sum = Math.max(dll.peek().val[1], 0) + nums[i] - max = Math.max(max, sum) - while (!dll.isEmpty() && dll.peekLast().val[1] < sum) { - dll.pop() - } - dll.push([i, sum]) - } - return max -} - -class Node { - constructor(val) { - this.val = val - this.prev = null - this.next = null - } -} -class DLL { - constructor() { - this.head = new Node() - this.tail = null - this.size = 0 - } - peek() { - return this.head.next - } - peekLast() { - return this.tail - } - isEmpty() { - return this.head.next == null - } - shift() { - const h = this.head.next - if (h) { - this.head.next = h.next - if (h.next) { - h.next.prev = this.head - } else { - this.tail = null - } - this.size-- - } - } - pop() { - if (this.tail == null) return - const newTail = this.tail.prev - if (newTail) { - newTail.next = null - this.tail.prev = null - this.tail = newTail - this.size-- - } - - } - push(val) { - const node = new Node(val) - node.prev = this.tail ?? this.head - node.prev.next = node - this.tail = node - this.size++ - } -} diff --git a/1425.constrained-subsequence-sum.js b/1425.constrained-subsequence-sum.js new file mode 100644 index 00000000..482d68c4 --- /dev/null +++ b/1425.constrained-subsequence-sum.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const constrainedSubsetSum = function(nums, k) { + const window = [[0,nums[0]]]; + let max = nums[0]; + for(let i=1; i0 && window[window.length-1][1] < sum){ + window.pop(); + } + window.push([i,sum]); + } + return max; +}; + diff --git a/1429-build-array-where-you-can-find-the-maximum-exactly-k-comparisons.js b/1429.build-array-where-you-can-find-the-maximum-exactly-k-comparisons.js similarity index 100% rename from 1429-build-array-where-you-can-find-the-maximum-exactly-k-comparisons.js rename to 1429.build-array-where-you-can-find-the-maximum-exactly-k-comparisons.js diff --git a/143-reorder-list.js b/143-reorder-list.js deleted file mode 100644 index 5d49c176..00000000 --- a/143-reorder-list.js +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @return {void} Do not return anything, modify head in-place instead. - */ -const reorderList = function(head) { - if(head == null) return head - let slow = head, fast = head - while(fast && fast.next) { - slow = slow.next - fast = fast.next.next - } - let head2 = reverse(slow.next) - slow.next = null - - while(head && head2) { - const next = head.next, next2 = head2.next - head2.next = head.next - head.next = head2 - head = next - head2 = next2 - } - - function reverse(node) { - let pre = null, cur = node - while(cur) { - const tmp = cur.next - cur.next = pre - pre = cur - cur = tmp - } - return pre - } -}; - - - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @return {void} Do not return anything, modify head in-place instead. - */ -const reorderList = function(head) { - if (!head || !head.next) return head; - - const reverse = head => { - if (!head || !head.next) return head; - const newHead = reverse(head.next); - head.next.next = head; - head.next = null; - return newHead; - }; - - const merge = (l1, l2) => { - if (!l1) return l2; - if (!l2) return l1; - while (l1 && l2) { - const next1 = l1.next; - const next2 = l2.next; - l1.next = l2; - if (next1 == null) break; - l2.next = next1; - l1 = next1; - l2 = next2; - } - }; - - let fast = head; - let slow = head; - - while (fast && fast.next) { - fast = fast.next.next; - slow = slow.next; - } - - fast = slow.next; - slow.next = null; - - fast = reverse(fast); - merge(head, fast); -}; - - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @return {void} Do not return anything, modify head in-place instead. - */ -const reorderList = function(head) { - if (head == null || head.next == null) { - return head; - } - const arr = []; - let tmp = head; - while (tmp.next) { - arr.push(tmp); - tmp = tmp.next; - } - arr.push(tmp); - for (let i = 1; i < arr.length; i = i + 2) { - if (arr.length - 1 > i) { - let el = arr.pop(); - arr.splice(i, 0, el); - } - } - for (let i = 1; i < arr.length; i++) { - arr[i - 1].next = arr[i]; - if (i === arr.length - 1) arr[i].next = null; - } -}; diff --git a/143.reorder-list.js b/143.reorder-list.js new file mode 100644 index 00000000..cd3d4e61 --- /dev/null +++ b/143.reorder-list.js @@ -0,0 +1,43 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @return {void} Do not return anything, modify head in-place instead. + */ +const reorderList = function(head) { + if(head == null) return head + let slow = head, fast = head + while(fast && fast.next) { + slow = slow.next + fast = fast.next.next + } + let head2 = reverse(slow.next) + slow.next = null + + while(head && head2) { + const next = head.next, next2 = head2.next + head2.next = head.next + head.next = head2 + head = next + head2 = next2 + } + + function reverse(node) { + let pre = null, cur = node + while(cur) { + const tmp = cur.next + cur.next = pre + pre = cur + cur = tmp + } + return pre + } +}; + + + diff --git a/1431-kids-with-the-greatest-number-of-candies.js b/1431.kids-with-the-greatest-number-of-candies.js similarity index 100% rename from 1431-kids-with-the-greatest-number-of-candies.js rename to 1431.kids-with-the-greatest-number-of-candies.js diff --git a/1434-number-of-ways-to-wear-different-hats-to-each-other.js b/1434-number-of-ways-to-wear-different-hats-to-each-other.js deleted file mode 100644 index 4656736b..00000000 --- a/1434-number-of-ways-to-wear-different-hats-to-each-other.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @param {number[][]} hats - * @return {number} - */ -const numberWays = function(hats) { - const map = new Map() - const n = hats.length - for(let i = 0; i < n; i++) { - for(const h of hats[i]) { - if(!map.has(h)) map.set(h, []) - map.get(h).push(i) - } - } - const mod = 1e9 + 7 - const allMask = (1 << n) - 1 - const dp = Array.from({ length: 41 }, () => Array(1024)) - - return dfs(1, 0) - - function dfs(hat, mask) { - if(mask === allMask) return 1 - if(hat > 40) return 0 - if(dp[hat][mask] != null) return dp[hat][mask] - - let res = 0 - - // not using this `hat` - res += dfs(hat + 1, mask) - for(const p of (map.get(hat) || [])) { - if(((mask >> p) & 1) === 0) { - res += dfs(hat + 1, mask | (1 << p)) - res = res % mod - } - } - dp[hat][mask] = res - return res - } - -}; - -// another - - -/** - * @param {number[][]} hats - * @return {number} - */ -const numberWays = function (hats) { - const pplThatCanWearHats = new Array(40 + 1).fill(null).map(() => []) - for (let i = 0; i < hats.length; i++) { - const personMask = 1 << i - for (let hat of hats[i]) { - pplThatCanWearHats[hat].push(personMask) - } - } - - const cache = {} - const dfs = (hat, pplWithoutHatsMask) => { - if (!pplWithoutHatsMask) return 1 - if (hat === 41) return 0 - const key = `${hat}-${pplWithoutHatsMask}` - if (cache.hasOwnProperty(key)) return cache[key] - const nextHat = hat + 1 - let total = dfs(nextHat, pplWithoutHatsMask) - for (let personMask of pplThatCanWearHats[hat]) { - if (!(pplWithoutHatsMask & personMask)) continue - total += dfs(nextHat, pplWithoutHatsMask ^ personMask) - } - return (cache[key] = total % 1000000007) - } - return dfs(1, (1 << hats.length) - 1) -} diff --git a/1434.number-of-ways-to-wear-different-hats-to-each-other.js b/1434.number-of-ways-to-wear-different-hats-to-each-other.js new file mode 100644 index 00000000..da67e74c --- /dev/null +++ b/1434.number-of-ways-to-wear-different-hats-to-each-other.js @@ -0,0 +1,40 @@ +/** + * @param {number[][]} hats + * @return {number} + */ +const numberWays = function(hats) { + const map = new Map() + const n = hats.length + for(let i = 0; i < n; i++) { + for(const h of hats[i]) { + if(!map.has(h)) map.set(h, []) + map.get(h).push(i) + } + } + const mod = 1e9 + 7 + const allMask = (1 << n) - 1 + const dp = Array.from({ length: 41 }, () => Array(1024)) + + return dfs(1, 0) + + function dfs(hat, mask) { + if(mask === allMask) return 1 + if(hat > 40) return 0 + if(dp[hat][mask] != null) return dp[hat][mask] + + let res = 0 + + // not using this `hat` + res += dfs(hat + 1, mask) + for(const p of (map.get(hat) || [])) { + if(((mask >> p) & 1) === 0) { + res += dfs(hat + 1, mask | (1 << p)) + res = res % mod + } + } + dp[hat][mask] = res + return res + } + +}; + diff --git a/1436-destination-city.js b/1436-destination-city.js deleted file mode 100644 index 18999109..00000000 --- a/1436-destination-city.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @param {string[][]} paths - * @return {string} - */ -const destCity = function(paths) { - const hash = {} - for(let [s, e] of paths) { - if(hash[e] == null) hash[e] = true - hash[s] = false - if(hash[s] === true) hash[s] = false - } - - for(let k in hash) { - if(hash[k]) return k - } -}; - -// another - -/** - * @param {string[][]} paths - * @return {string} - */ -const destCity = function(paths) { - const set = new Set() - for(let [s, e] of paths) set.add(e) - for(let [s, e] of paths) set.delete(s) - - return set[Symbol.iterator]().next().value -}; diff --git a/1436.destination-city.js b/1436.destination-city.js new file mode 100644 index 00000000..5e976104 --- /dev/null +++ b/1436.destination-city.js @@ -0,0 +1,17 @@ +/** + * @param {string[][]} paths + * @return {string} + */ +const destCity = function(paths) { + const hash = {} + for(let [s, e] of paths) { + if(hash[e] == null) hash[e] = true + hash[s] = false + if(hash[s] === true) hash[s] = false + } + + for(let k in hash) { + if(hash[k]) return k + } +}; + diff --git a/1438-longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit.js b/1438-longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit.js deleted file mode 100644 index ffc4ed5c..00000000 --- a/1438-longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit.js +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} limit - * @return {number} - */ -const longestSubarray = function(nums, limit) { - let maxd = [], mind = []; - let i = 0, j; - for (j = 0; j < nums.length; ++j) { - // non-increase - while (maxd.length && nums[j] > maxd[maxd.length - 1]) maxd.pop(); - // non-decrease - while (mind.length && nums[j] < mind[mind.length - 1]) mind.pop(); - - maxd.push(nums[j]); - mind.push(nums[j]); - - if (maxd[0] - mind[0] > limit) { - if (maxd[0] == nums[i]) maxd.shift(); - if (mind[0] == nums[i]) mind.shift(); - ++i; - } - } - return j - i; -}; - -// another - -/** - * @param {number[]} nums - * @param {number} limit - * @return {number} - */ -const longestSubarray = function (nums, limit) { - const maxDq = new Deque(), minDq = new Deque(), n = nums.length - let l = 0, r = 0 - let res = 0 - for(r = 0; r < n; r++) { - const cur = nums[r] - while(!maxDq.isEmpty() && maxDq.last() < cur) { - maxDq.pop() - } - maxDq.enqueue(cur) - while(!minDq.isEmpty() && minDq.last() > cur) { - minDq.pop() - } - minDq.enqueue(cur) - - while(maxDq.first() - minDq.first() > limit) { - if(nums[l] === maxDq.first()) maxDq.dequeue() - if(nums[l] === minDq.first()) minDq.dequeue() - l++ - } - res = Math.max(res, r - l + 1) - } - return res -} - -class Deque { - constructor() { - this.head = new Node() - this.tail = this.head - } - - isEmpty() { - return this.head.next === null - } - - first() { - return this.head.next.value - } - - last() { - return this.tail.value - } - - dequeue() { - this.head = this.head.next - this.head.prev = null - } - - enqueue(value) { - this.tail.next = new Node(value) - this.tail.next.prev = this.tail - this.tail = this.tail.next - } - - pop() { - this.tail = this.tail.prev - this.tail.next = null - } -} - -class Node { - constructor(value) { - this.value = value - this.next = null - this.prev = null - } -} diff --git a/1438.longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit.js b/1438.longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit.js new file mode 100644 index 00000000..39383ea3 --- /dev/null +++ b/1438.longest-continuous-subarray-with-absolute-diff-less-than-or-equal-to-limit.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} nums + * @param {number} limit + * @return {number} + */ +const longestSubarray = function(nums, limit) { + let maxd = [], mind = []; + let i = 0, j; + for (j = 0; j < nums.length; ++j) { + // non-increase + while (maxd.length && nums[j] > maxd[maxd.length - 1]) maxd.pop(); + // non-decrease + while (mind.length && nums[j] < mind[mind.length - 1]) mind.pop(); + + maxd.push(nums[j]); + mind.push(nums[j]); + + if (maxd[0] - mind[0] > limit) { + if (maxd[0] == nums[i]) maxd.shift(); + if (mind[0] == nums[i]) mind.shift(); + ++i; + } + } + return j - i; +}; + diff --git a/1439-find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows.js b/1439.find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows.js similarity index 100% rename from 1439-find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows.js rename to 1439.find-the-kth-smallest-sum-of-a-matrix-with-sorted-rows.js diff --git a/144-binary-tree-preorder-traversal.js b/144-binary-tree-preorder-traversal.js deleted file mode 100755 index a15f046d..00000000 --- a/144-binary-tree-preorder-traversal.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number[]} - */ -const preorderTraversal = function(root) { - const res = []; - traversal(root, res); - return res; -}; - -function traversal(node, arr) { - if (node === null) return; - arr.push(node.val); - if (node.left) { - traversal(node.left, arr); - } - if (node.right) { - traversal(node.right, arr); - } -} diff --git a/144.binary-tree-preorder-traversal.js b/144.binary-tree-preorder-traversal.js new file mode 100644 index 00000000..ed092298 --- /dev/null +++ b/144.binary-tree-preorder-traversal.js @@ -0,0 +1,27 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[]} + */ +const preorderTraversal = function(root) { + const res = []; + traversal(root, res); + return res; +}; + +function traversal(node, arr) { + if (node === null) return; + arr.push(node.val); + if (node.left) { + traversal(node.left, arr); + } + if (node.right) { + traversal(node.right, arr); + } +} diff --git a/1441-build-an-array-with-stack-operations.js b/1441.build-an-array-with-stack-operations.js similarity index 100% rename from 1441-build-an-array-with-stack-operations.js rename to 1441.build-an-array-with-stack-operations.js diff --git a/1442-count-triplets-that-can-form-two-arrays-of-equal-xor.js b/1442-count-triplets-that-can-form-two-arrays-of-equal-xor.js deleted file mode 100644 index 02a65836..00000000 --- a/1442-count-triplets-that-can-form-two-arrays-of-equal-xor.js +++ /dev/null @@ -1,41 +0,0 @@ - -/** - * @param {number[]} arr - * @return {number} - */ -const countTriplets = function(arr) { - let res = 0 - const n = arr.length - for(let i = 0; i < n; i++) { - let xor = arr[i] - for(let j = i + 1; j < n; j++) { - xor ^= arr[j] - if(xor === 0) res += j - i - } - } - - return res -}; - -// another - -/** - * @param {number[]} arr - * @return {number} - */ -const countTriplets = function(arr) { - arr.unshift(0) - const n = arr.length - let res = 0 - for(let i = 1; i < n; i++) { - arr[i] ^= arr[i - 1] - } - const count = {}, total = {} - for(let i = 0; i < n; i++) { - if(count[arr[i]] == null) count[arr[i]] = 0 - if(total[arr[i]] == null) total[arr[i]] = 0 - res += count[arr[i]]++ * (i - 1) - total[arr[i]] - total[arr[i]] += i - } - return res -}; diff --git a/1442.count-triplets-that-can-form-two-arrays-of-equal-xor.js b/1442.count-triplets-that-can-form-two-arrays-of-equal-xor.js new file mode 100644 index 00000000..e462e122 --- /dev/null +++ b/1442.count-triplets-that-can-form-two-arrays-of-equal-xor.js @@ -0,0 +1,19 @@ + +/** + * @param {number[]} arr + * @return {number} + */ +const countTriplets = function(arr) { + let res = 0 + const n = arr.length + for(let i = 0; i < n; i++) { + let xor = arr[i] + for(let j = i + 1; j < n; j++) { + xor ^= arr[j] + if(xor === 0) res += j - i + } + } + + return res +}; + diff --git a/1444-number-of-ways-of-cutting-a-pizza.js b/1444.number-of-ways-of-cutting-a-pizza.js similarity index 100% rename from 1444-number-of-ways-of-cutting-a-pizza.js rename to 1444.number-of-ways-of-cutting-a-pizza.js diff --git a/1446-consecutive-characters.js b/1446-consecutive-characters.js deleted file mode 100644 index a8e49a47..00000000 --- a/1446-consecutive-characters.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const maxPower = function(s) { - let res = 1, cnt = 1 - for(let i = 1; i < s.length; i++) { - if(s[i] === s[i - 1]) { - if(++cnt > res) res = cnt - } else { - cnt = 1 - } - } - return res -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const maxPower = function(s) { - let prev = '', prevIdx = -1, res = -Infinity - for(let i = 0; i < s.length; i++) { - const cur = s[i] - if(cur !== prev) { - res = Math.max(res, i - prevIdx) - prev = cur - prevIdx = i - } else { - if(i === s.length - 1) res = Math.max(res, i - prevIdx + 1) - } - } - return res -}; diff --git a/1446.consecutive-characters.js b/1446.consecutive-characters.js new file mode 100644 index 00000000..8b286d0d --- /dev/null +++ b/1446.consecutive-characters.js @@ -0,0 +1,16 @@ +/** + * @param {string} s + * @return {number} + */ +const maxPower = function(s) { + let res = 1, cnt = 1 + for(let i = 1; i < s.length; i++) { + if(s[i] === s[i - 1]) { + if(++cnt > res) res = cnt + } else { + cnt = 1 + } + } + return res +}; + diff --git a/1448-count-good-nodes-in-binary-tree.js b/1448.count-good-nodes-in-binary-tree.js similarity index 100% rename from 1448-count-good-nodes-in-binary-tree.js rename to 1448.count-good-nodes-in-binary-tree.js diff --git a/1449-form-largest-integer-with-digits-that-add-up-to-target.js b/1449-form-largest-integer-with-digits-that-add-up-to-target.js deleted file mode 100644 index 8ceae82d..00000000 --- a/1449-form-largest-integer-with-digits-that-add-up-to-target.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @param {number[]} cost - * @param {number} target - * @return {string} - */ -const largestNumber = function (cost, target) { - const dp = new Array(target + 1).fill(-Infinity) - dp[0] = 0 - for (let i = 1; i <= target; i++) { - for (let c of cost) { - if (i - c >= 0 && dp[i - c] >= 0) { - dp[i] = Math.max(dp[i - c] + 1, dp[i]) - } - } - } - let left = target - let paint = '' - if (dp[target] < 1) return '0' - for (let i = cost.length - 1; i >= 0; i--) { - while (left > 0 && dp[left - cost[i]] === dp[left] - 1) { - paint += (i + 1).toString() - left -= cost[i] - } - } - return paint -} - -// another - -/** - * @param {number[]} cost - * @param {number} target - * @return {string} - */ -const largestNumber = function(cost, target) { - const m = new Map() - const res = dfs(cost, 1, target, m) - return res.indexOf('0') !== -1 ? '0' : res -}; -function dfs(cost, index, remain, m) { - if(remain === 0) return '' - if(remain < 0 || index === cost.length + 1) return '0' - if(m.has(remain)) return m.get(remain) - const take = '' + index + dfs(cost, 1, remain - cost[index - 1], m) - const skip = dfs(cost, index + 1, remain, m) - const res = getBigger(take, skip) - m.set(remain, res) - return res -} -function getBigger(num1, num2) { - if(num1.indexOf('0') !== -1) return num2 - if(num2.indexOf('0') !== -1) return num1 - if(num1.length > num2.length) return num1 - else if(num1.length < num2.length) return num2 - else return num1 > num2 ? num1 : num2 -} diff --git a/1449.form-largest-integer-with-digits-that-add-up-to-target.js b/1449.form-largest-integer-with-digits-that-add-up-to-target.js new file mode 100644 index 00000000..7df37d9c --- /dev/null +++ b/1449.form-largest-integer-with-digits-that-add-up-to-target.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} cost + * @param {number} target + * @return {string} + */ +const largestNumber = function (cost, target) { + const dp = new Array(target + 1).fill(-Infinity) + dp[0] = 0 + for (let i = 1; i <= target; i++) { + for (let c of cost) { + if (i - c >= 0 && dp[i - c] >= 0) { + dp[i] = Math.max(dp[i - c] + 1, dp[i]) + } + } + } + let left = target + let paint = '' + if (dp[target] < 1) return '0' + for (let i = cost.length - 1; i >= 0; i--) { + while (left > 0 && dp[left - cost[i]] === dp[left] - 1) { + paint += (i + 1).toString() + left -= cost[i] + } + } + return paint +} + diff --git a/145-binary-tree-postorder-traversal.js b/145.binary-tree-postorder-traversal.js similarity index 100% rename from 145-binary-tree-postorder-traversal.js rename to 145.binary-tree-postorder-traversal.js diff --git a/1452-people-whose-list-of-favorite-companies-is-not-a-subset-of-another-list.js b/1452.people-whose-list-of-favorite-companies-is-not-a-subset-of-another-list.js similarity index 100% rename from 1452-people-whose-list-of-favorite-companies-is-not-a-subset-of-another-list.js rename to 1452.people-whose-list-of-favorite-companies-is-not-a-subset-of-another-list.js diff --git a/1458-max-dot-product-of-two-subsequences.js b/1458.max-dot-product-of-two-subsequences.js similarity index 100% rename from 1458-max-dot-product-of-two-subsequences.js rename to 1458.max-dot-product-of-two-subsequences.js diff --git a/146-lru-cache.js b/146-lru-cache.js deleted file mode 100755 index d9ef0dc7..00000000 --- a/146-lru-cache.js +++ /dev/null @@ -1,127 +0,0 @@ -class Node { - constructor(key, val) { - this.val = val; - this.key = key; - this.next = this.pre = null; - } -} - -const LRUCache = function(capacity) { - this.capacity = capacity; - this.count = 0; - this.start = new Node(-1, -1); - this.end = new Node(-1, -1); - this.start.next = this.end; - this.end.pre = this.start; - this.map = {}; -}; - -// insert node into the next of the start -const insertAfter = function(start, node) { - let next = start.next; - start.next = node; - node.pre = start; - node.next = next; - next.pre = node; -}; - -const detach = function(node) { - let pre = node.pre, - next = node.next; - pre.next = next; - next.pre = pre; - node.next = node.pre = null; -}; - -/** - * @param {number} key - * @return {number} - */ -LRUCache.prototype.get = function(key) { - let node = this.map[key]; - if (node != undefined) { - detach(node); - insertAfter(this.start, node); - return node.val; - } else { - return -1; - } -}; - -/** - * @param {number} key - * @param {number} value - * @return {void} - */ -LRUCache.prototype.put = function(key, value) { - let node = this.map[key]; - if (!node) { - if (this.count == this.capacity) { - // deleting last nodes - let t = this.end.pre; - detach(t); - delete this.map[t.key]; - } else { - this.count++; - } - node = new Node(key, value); - this.map[key] = node; - insertAfter(this.start, node); - } else { - node.val = value; - detach(node); - insertAfter(this.start, node); - } -}; - -/** - * Your LRUCache object will be instantiated and called as such: - * var obj = Object.create(LRUCache).createNew(capacity) - * var param_1 = obj.get(key) - * obj.put(key,value) - */ - -// another - -/** - * @param {number} capacity - */ -const LRUCache = function(capacity) { - this.m = new Map() - this.limit = capacity -}; - -/** - * @param {number} key - * @return {number} - */ -LRUCache.prototype.get = function(key) { - if(!this.m.has(key)) return -1 - const v = this.m.get(key) - this.m.delete(key) - this.m.set(key, v) - return v -}; - -/** - * @param {number} key - * @param {number} value - * @return {void} - */ -LRUCache.prototype.put = function(key, value) { - if(this.m.has(key)) { - this.m.delete(key) - } else { - if(this.m.size >= this.limit) { - const first = this.m.keys().next().value - this.m.delete(first) - } - } - this.m.set(key, value) -}; -/** - * Your LRUCache object will be instantiated and called as such: - * var obj = new LRUCache(capacity) - * var param_1 = obj.get(key) - * obj.put(key,value) - */ diff --git a/146.lru-cache.js b/146.lru-cache.js new file mode 100644 index 00000000..35f9e39a --- /dev/null +++ b/146.lru-cache.js @@ -0,0 +1,83 @@ +class Node { + constructor(key, val) { + this.val = val; + this.key = key; + this.next = this.pre = null; + } +} + +const LRUCache = function(capacity) { + this.capacity = capacity; + this.count = 0; + this.start = new Node(-1, -1); + this.end = new Node(-1, -1); + this.start.next = this.end; + this.end.pre = this.start; + this.map = {}; +}; + +// insert node into the next of the start +const insertAfter = function(start, node) { + let next = start.next; + start.next = node; + node.pre = start; + node.next = next; + next.pre = node; +}; + +const detach = function(node) { + let pre = node.pre, + next = node.next; + pre.next = next; + next.pre = pre; + node.next = node.pre = null; +}; + +/** + * @param {number} key + * @return {number} + */ +LRUCache.prototype.get = function(key) { + let node = this.map[key]; + if (node != undefined) { + detach(node); + insertAfter(this.start, node); + return node.val; + } else { + return -1; + } +}; + +/** + * @param {number} key + * @param {number} value + * @return {void} + */ +LRUCache.prototype.put = function(key, value) { + let node = this.map[key]; + if (!node) { + if (this.count == this.capacity) { + // deleting last nodes + let t = this.end.pre; + detach(t); + delete this.map[t.key]; + } else { + this.count++; + } + node = new Node(key, value); + this.map[key] = node; + insertAfter(this.start, node); + } else { + node.val = value; + detach(node); + insertAfter(this.start, node); + } +}; + +/** + * Your LRUCache object will be instantiated and called as such: + * var obj = Object.create(LRUCache).createNew(capacity) + * var param_1 = obj.get(key) + * obj.put(key,value) + */ + diff --git a/1460-make-two-arrays-equal-by-reversing-sub-arrays.js b/1460.make-two-arrays-equal-by-reversing-sub-arrays.js similarity index 100% rename from 1460-make-two-arrays-equal-by-reversing-sub-arrays.js rename to 1460.make-two-arrays-equal-by-reversing-sub-arrays.js diff --git a/1461-check-if-a-string-contains-all-binary-codes-of-size-k.js b/1461.check-if-a-string-contains-all-binary-codes-of-size-k.js similarity index 100% rename from 1461-check-if-a-string-contains-all-binary-codes-of-size-k.js rename to 1461.check-if-a-string-contains-all-binary-codes-of-size-k.js diff --git a/1462-course-schedule-iv.js b/1462-course-schedule-iv.js deleted file mode 100644 index abbcaf55..00000000 --- a/1462-course-schedule-iv.js +++ /dev/null @@ -1,143 +0,0 @@ -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @param {number[][]} queries - * @return {boolean[]} - */ -const checkIfPrerequisite = function (numCourses, prerequisites, queries) { - const n = numCourses, m = prerequisites.length - const graph = {}, inDegree = Array(n).fill(0) - - for(const [s, e] of prerequisites) { - if(graph[s] == null) graph[s] = [] - inDegree[e]++ - graph[s].push(e) - } - - let q = [] - - for(let i = 0; i < n; i++) { - if(inDegree[i] === 0) q.push(i) - } - - const hash = {} - - while(q.length) { - const size = q.length - const nxt = [] - for(let i = 0; i < size; i++) { - const cur = q[i] - for(const e of (graph[cur] || [])) { - inDegree[e]-- - if(hash[e] == null) hash[e] = new Set() - hash[e].add(cur) - for(const dep of (hash[cur] || [])) { - hash[e].add(dep) - } - - if(inDegree[e] === 0) { - nxt.push(e) - } - } - } - - q = nxt - } - - const res = [] - for(const [p, e] of queries) { - if(hash[e] && hash[e].has(p)) res.push(true) - else res.push(false) - } - - return res -} - -// another - - -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @param {number[][]} queries - * @return {boolean[]} - */ -const checkIfPrerequisite = function(numCourses, prerequisites, queries) { - // https://en.wikipedia.org/wiki/Floyd%E2%80%93Warshall_algorithm - const n = numCourses - const connected = Array.from({ length: n }, () => Array(n).fill(false)) - for(let p of prerequisites) connected[p[0]][p[1]] = true - for(let k = 0; k < n; k++) { - for(let i = 0; i < n; i++) { - for(let j = 0; j < n; j++) { - connected[i][j] = connected[i][j] || (connected[i][k] && connected[k][j]); - } - } - } - const res = [] - for(let q of queries) res.push(connected[q[0]][q[1]]) - return res -}; - -// another - -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @param {number[][]} queries - * @return {boolean[]} - */ -const checkIfPrerequisite = function (numCourses, prerequisites, queries) { - const n = numCourses - const connected = Array.from({ length: n }, () => Array(n).fill(false)) - for (let p of prerequisites) connected[p[0]][p[1]] = true - for (let k = 0; k < n; k++) { - for (let i = 0; i < n; i++) { - for (let j = 0; j < n; j++) { - connected[i][j] = - connected[i][j] || (connected[i][k] && connected[k][j]) - } - } - } - const res = [] - for (let q of queries) res.push(connected[q[0]][q[1]]) - return res -} - -// another - -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @param {number[][]} queries - * @return {boolean[]} - */ -const checkIfPrerequisite = function (numCourses, prerequisites, queries) { - const graph = {}, - connected = Array.from({ length: numCourses }, () => - Array(numCourses).fill(-1) - ) - for (const [u, v] of prerequisites) { - if (graph[u] == null) graph[u] = [] - graph[u].push(v) - connected[u][v] = 1 - } - - const res = [] - for (const [u, v] of queries) res.push(dfs(u, v)) - - return res - - function dfs(u, v) { - if (connected[u][v] !== -1) return connected[u][v] - let res = false - for (const next of graph[u] || []) { - if (!res) { - res ||= dfs(next, v) - } else break - } - connected[u][v] = res - return res - } -} - diff --git a/1462.course-schedule-iv.js b/1462.course-schedule-iv.js new file mode 100644 index 00000000..5b639e6b --- /dev/null +++ b/1462.course-schedule-iv.js @@ -0,0 +1,55 @@ +/** + * @param {number} numCourses + * @param {number[][]} prerequisites + * @param {number[][]} queries + * @return {boolean[]} + */ +const checkIfPrerequisite = function (numCourses, prerequisites, queries) { + const n = numCourses, m = prerequisites.length + const graph = {}, inDegree = Array(n).fill(0) + + for(const [s, e] of prerequisites) { + if(graph[s] == null) graph[s] = [] + inDegree[e]++ + graph[s].push(e) + } + + let q = [] + + for(let i = 0; i < n; i++) { + if(inDegree[i] === 0) q.push(i) + } + + const hash = {} + + while(q.length) { + const size = q.length + const nxt = [] + for(let i = 0; i < size; i++) { + const cur = q[i] + for(const e of (graph[cur] || [])) { + inDegree[e]-- + if(hash[e] == null) hash[e] = new Set() + hash[e].add(cur) + for(const dep of (hash[cur] || [])) { + hash[e].add(dep) + } + + if(inDegree[e] === 0) { + nxt.push(e) + } + } + } + + q = nxt + } + + const res = [] + for(const [p, e] of queries) { + if(hash[e] && hash[e].has(p)) res.push(true) + else res.push(false) + } + + return res +} + diff --git a/1463-cherry-pickup-ii.js b/1463.cherry-pickup-ii.js similarity index 100% rename from 1463-cherry-pickup-ii.js rename to 1463.cherry-pickup-ii.js diff --git a/1464-maximum-product-of-two-elements-in-an-array.js b/1464.maximum-product-of-two-elements-in-an-array.js similarity index 100% rename from 1464-maximum-product-of-two-elements-in-an-array.js rename to 1464.maximum-product-of-two-elements-in-an-array.js diff --git a/1465-maximum-area-of-a-piece-of-cake-after-horizontal-and-vertical-cuts.js b/1465-maximum-area-of-a-piece-of-cake-after-horizontal-and-vertical-cuts.js deleted file mode 100644 index 12701fe7..00000000 --- a/1465-maximum-area-of-a-piece-of-cake-after-horizontal-and-vertical-cuts.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @param {number} h - * @param {number} w - * @param {number[]} horizontalCuts - * @param {number[]} verticalCuts - * @return {number} - */ -const maxArea = function(h, w, horizontalCuts, verticalCuts) { - return getMax(h, horizontalCuts) * getMax(w, verticalCuts) % (10 ** 9 + 7) -}; - -function getMax(limit, cuts) { - cuts.sort((a, b) => a - b) - const n = cuts.length - let max = Math.max(cuts[0], limit - cuts[n - 1]) - for(let i = 1; i < n; i++) { - max = Math.max(max, cuts[i] - cuts[i - 1]) - } - return max -} - -// another - -/** - * @param {number} h - * @param {number} w - * @param {number[]} horizontalCuts - * @param {number[]} verticalCuts - * @return {number} - */ -const maxArea = function(h, w, horizontalCuts, verticalCuts) { - return (BigInt(maxGap(h, horizontalCuts)) * BigInt(maxGap(w, verticalCuts))) % BigInt(1e9 + 7) - function maxGap(limit, arr) { - let res = 0 - arr.sort((a, b) => a - b) - for(let i = 0, n = arr.length; i < n; i++) { - let tmp = i === 0 ? arr[0] : arr[i] - arr[i - 1] - res = Math.max(res, tmp) - } - res = Math.max(res, limit - arr[arr.length - 1]) - - return res - } -}; diff --git a/1465.maximum-area-of-a-piece-of-cake-after-horizontal-and-vertical-cuts.js b/1465.maximum-area-of-a-piece-of-cake-after-horizontal-and-vertical-cuts.js new file mode 100644 index 00000000..1f467311 --- /dev/null +++ b/1465.maximum-area-of-a-piece-of-cake-after-horizontal-and-vertical-cuts.js @@ -0,0 +1,21 @@ +/** + * @param {number} h + * @param {number} w + * @param {number[]} horizontalCuts + * @param {number[]} verticalCuts + * @return {number} + */ +const maxArea = function(h, w, horizontalCuts, verticalCuts) { + return getMax(h, horizontalCuts) * getMax(w, verticalCuts) % (10 ** 9 + 7) +}; + +function getMax(limit, cuts) { + cuts.sort((a, b) => a - b) + const n = cuts.length + let max = Math.max(cuts[0], limit - cuts[n - 1]) + for(let i = 1; i < n; i++) { + max = Math.max(max, cuts[i] - cuts[i - 1]) + } + return max +} + diff --git a/1467-probability-of-a-two-boxes-having-the-same-number-of-distinct-balls.js b/1467-probability-of-a-two-boxes-having-the-same-number-of-distinct-balls.js deleted file mode 100644 index 465ec0b8..00000000 --- a/1467-probability-of-a-two-boxes-having-the-same-number-of-distinct-balls.js +++ /dev/null @@ -1,131 +0,0 @@ -/** - * @param {number[]} balls - * @return {number} - */ -const getProbability = function(balls) { - const k = balls.length; - const halfUsed = balls.reduce((acc, val) => acc + val, 0) / 2; - const startArray = new Array(k); - startArray.fill(0); - const perm = function (b1, b2) { - let p1, p2, s1, s2; - s1 = b1.reduce((acc, val) => acc + val, 0); - s2 = b2.reduce((acc, val) => acc + val, 0); - const fact = function (n) { - let f = 1; - for (let i = 2; i <= n; i++) f *= i; - return f; - }; - p1 = fact(s1); - p2 = fact(s2); - b1.forEach((val) => { - if (val > 1) p1 /= fact(val); - }); - b2.forEach((val) => { - if (val > 1) p2 /= fact(val); - }); - return p1 * p2; - }; - - const getValidCombos = function (ballsUsed, colorNum = 0) { - let box1Used = ballsUsed.reduce((acc, val) => acc + val, 0); - let matches = { good: 0, total: 0 }, - thisColorMax = halfUsed - box1Used; - if (colorNum === k - 1) { - if (thisColorMax > balls[colorNum]) return { good: 0, total: 0 }; - ballsUsed[colorNum] = thisColorMax; - let ballsLeft = []; - let colorsUsed = [0, 0]; - for (let i = 0; i < k; i++) { - ballsLeft[i] = balls[i] - ballsUsed[i]; - if (ballsUsed[i] > 0) colorsUsed[0]++; - if (ballsLeft[i] > 0) colorsUsed[1]++; - } - let permutations = perm(ballsUsed, ballsLeft, k); - return { - good: colorsUsed[1] === colorsUsed[0] ? permutations : 0, - total: permutations, - }; - } - thisColorMax = Math.min(thisColorMax, balls[colorNum]); - for (let i = 0; i <= thisColorMax; i++) { - let match = getValidCombos([...ballsUsed], colorNum + 1); - matches = { - good: matches.good + match.good, - total: matches.total + match.total, - }; - ballsUsed[colorNum]++; - } - return matches; - }; - let res = getValidCombos(startArray); - return res.good / res.total; -}; - - -// another - - -/** - * @param {number[]} balls - * @return {number} - */ -const getProbability = function (balls) { - const k = balls.length - const halfUsed = balls.reduce((acc, val) => acc + val, 0) / 2 - const startArray = new Array(k) - startArray.fill(0) - const perm = function (b1, b2) { - let p1, p2, s1, s2 - s1 = b1.reduce((acc, val) => acc + val, 0) - s2 = b2.reduce((acc, val) => acc + val, 0) - const fact = function (n) { - let f = 1 - for (let i = 2; i <= n; i++) f *= i - return f - } - p1 = fact(s1) - p2 = fact(s2) - b1.forEach((val) => { - if (val > 1) p1 /= fact(val) - }) - b2.forEach((val) => { - if (val > 1) p2 /= fact(val) - }) - return p1 * p2 - } - - const getValidCombos = function (ballsUsed, colorNum = 0) { - let box1Used = ballsUsed.reduce((acc, val) => acc + val, 0) - let matches = { good: 0, total: 0 }, - thisColorMax = halfUsed - box1Used - if (colorNum === k - 1) { - if (thisColorMax > balls[colorNum]) return { good: 0, total: 0 } - ballsUsed[colorNum] = thisColorMax - let ballsLeft = [] - let colorsUsed = [0, 0] - for (let i = 0; i < k; i++) { - ballsLeft[i] = balls[i] - ballsUsed[i] - if (ballsUsed[i] > 0) colorsUsed[0]++ - if (ballsLeft[i] > 0) colorsUsed[1]++ - } - let permutations = perm(ballsUsed, ballsLeft, k) - return { - good: colorsUsed[1] === colorsUsed[0] ? permutations : 0, - total: permutations, - } - } - thisColorMax = Math.min(thisColorMax, balls[colorNum]) - for (let i = 0; i <= thisColorMax; i++) { - let match = getValidCombos([...ballsUsed], colorNum + 1) - matches = { - good: matches.good + match.good, - total: matches.total + match.total, - } - ballsUsed[colorNum]++ - } - return matches - } - let res = getValidCombos(startArray) - return res.good / res.total -} diff --git a/1467.probability-of-a-two-boxes-having-the-same-number-of-distinct-balls.js b/1467.probability-of-a-two-boxes-having-the-same-number-of-distinct-balls.js new file mode 100644 index 00000000..f9d2d284 --- /dev/null +++ b/1467.probability-of-a-two-boxes-having-the-same-number-of-distinct-balls.js @@ -0,0 +1,65 @@ +/** + * @param {number[]} balls + * @return {number} + */ +const getProbability = function(balls) { + const k = balls.length; + const halfUsed = balls.reduce((acc, val) => acc + val, 0) / 2; + const startArray = new Array(k); + startArray.fill(0); + const perm = function (b1, b2) { + let p1, p2, s1, s2; + s1 = b1.reduce((acc, val) => acc + val, 0); + s2 = b2.reduce((acc, val) => acc + val, 0); + const fact = function (n) { + let f = 1; + for (let i = 2; i <= n; i++) f *= i; + return f; + }; + p1 = fact(s1); + p2 = fact(s2); + b1.forEach((val) => { + if (val > 1) p1 /= fact(val); + }); + b2.forEach((val) => { + if (val > 1) p2 /= fact(val); + }); + return p1 * p2; + }; + + const getValidCombos = function (ballsUsed, colorNum = 0) { + let box1Used = ballsUsed.reduce((acc, val) => acc + val, 0); + let matches = { good: 0, total: 0 }, + thisColorMax = halfUsed - box1Used; + if (colorNum === k - 1) { + if (thisColorMax > balls[colorNum]) return { good: 0, total: 0 }; + ballsUsed[colorNum] = thisColorMax; + let ballsLeft = []; + let colorsUsed = [0, 0]; + for (let i = 0; i < k; i++) { + ballsLeft[i] = balls[i] - ballsUsed[i]; + if (ballsUsed[i] > 0) colorsUsed[0]++; + if (ballsLeft[i] > 0) colorsUsed[1]++; + } + let permutations = perm(ballsUsed, ballsLeft, k); + return { + good: colorsUsed[1] === colorsUsed[0] ? permutations : 0, + total: permutations, + }; + } + thisColorMax = Math.min(thisColorMax, balls[colorNum]); + for (let i = 0; i <= thisColorMax; i++) { + let match = getValidCombos([...ballsUsed], colorNum + 1); + matches = { + good: matches.good + match.good, + total: matches.total + match.total, + }; + ballsUsed[colorNum]++; + } + return matches; + }; + let res = getValidCombos(startArray); + return res.good / res.total; +}; + + diff --git a/147-insertion-sort-list.js b/147.insertion-sort-list.js similarity index 100% rename from 147-insertion-sort-list.js rename to 147.insertion-sort-list.js diff --git a/1470-shuffle-the-array.js b/1470.shuffle-the-array.js similarity index 100% rename from 1470-shuffle-the-array.js rename to 1470.shuffle-the-array.js diff --git a/1472-design-browser-history.js b/1472.design-browser-history.js similarity index 100% rename from 1472-design-browser-history.js rename to 1472.design-browser-history.js diff --git a/1473-paint-house-iii.js b/1473.paint-house-iii.js similarity index 100% rename from 1473-paint-house-iii.js rename to 1473.paint-house-iii.js diff --git a/1475-final-prices-with-a-special-discount-in-a-shop.js b/1475.final-prices-with-a-special-discount-in-a-shop.js similarity index 100% rename from 1475-final-prices-with-a-special-discount-in-a-shop.js rename to 1475.final-prices-with-a-special-discount-in-a-shop.js diff --git a/1476-subrectangle-queries.js b/1476.subrectangle-queries.js similarity index 100% rename from 1476-subrectangle-queries.js rename to 1476.subrectangle-queries.js diff --git a/1478-allocate-mailboxes.js b/1478-allocate-mailboxes.js deleted file mode 100644 index 0281bb7c..00000000 --- a/1478-allocate-mailboxes.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @param {number[]} houses - * @param {number} k - * @return {number} - */ -const minDistance = function (A, K) { - A.sort((a, b) => a - b) - let n = A.length, - B = new Array(n + 1).fill(0), - dp = Array(n).fill(0) - for (let i = 0; i < n; ++i) { - B[i + 1] = B[i] + A[i] - dp[i] = 1e6 - } - for (let k = 1; k <= K; ++k) { - for (let j = n - 1; j > k - 2; --j) { - for (let i = k - 2; i < j; ++i) { - let m1 = ((i + j + 1) / 2) >> 0, - m2 = ((i + j + 2) / 2) >> 0 - let last = B[j + 1] - B[m2] - (B[m1 + 1] - B[i + 1]) - dp[j] = Math.min(dp[j], (i >= 0 ? dp[i] : 0) + last) - } - } - } - return dp[n - 1] -} - -// another - -/** - * @param {number[]} houses - * @param {number} k - * @return {number} - */ -function minDistance(houses, k) { - const n = houses.length, { abs, min } = Math, INF = Infinity - houses.sort((a, b) => a - b) - const costs = Array.from({ length: 100 }, () => Array(100).fill(0)) - const memo = Array.from({ length: 100 }, () => Array(100).fill(null)) - - for(let i = 0; i < n; i++) { - for(let j = 0; j < n; j++) { - const mid = houses[~~((i + j) >> 1)] - for (let k = i; k <= j; k++) costs[i][j] += abs(mid - houses[k]) - } - } - - return dp(k, 0) - - function dp(k, i) { - if (k === 0 && i === n) return 0 - if (k === 0 || i === n) return INF - if (memo[k][i] != null) return memo[k][i] - let res = INF - for (let j = i; j < n; j++) { - res = min(res, costs[i][j] + dp(k - 1, j + 1)) - } - - return memo[k][i] = res - } -} - diff --git a/1478.allocate-mailboxes.js b/1478.allocate-mailboxes.js new file mode 100644 index 00000000..c6f04ea2 --- /dev/null +++ b/1478.allocate-mailboxes.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} houses + * @param {number} k + * @return {number} + */ +const minDistance = function (A, K) { + A.sort((a, b) => a - b) + let n = A.length, + B = new Array(n + 1).fill(0), + dp = Array(n).fill(0) + for (let i = 0; i < n; ++i) { + B[i + 1] = B[i] + A[i] + dp[i] = 1e6 + } + for (let k = 1; k <= K; ++k) { + for (let j = n - 1; j > k - 2; --j) { + for (let i = k - 2; i < j; ++i) { + let m1 = ((i + j + 1) / 2) >> 0, + m2 = ((i + j + 2) / 2) >> 0 + let last = B[j + 1] - B[m2] - (B[m1 + 1] - B[i + 1]) + dp[j] = Math.min(dp[j], (i >= 0 ? dp[i] : 0) + last) + } + } + } + return dp[n - 1] +} + diff --git a/148-sort-list.js b/148-sort-list.js deleted file mode 100644 index dbfacf1e..00000000 --- a/148-sort-list.js +++ /dev/null @@ -1,192 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @return {ListNode} - */ -function sortList(head) { - quickSort(head, null); - return head; -} - -function quickSort(head, tail) { - if (head == tail) { - return; - } - const slow = partition(head, tail); - quickSort(head, slow); - quickSort(slow.next, tail); -} - -function swap(node1, node2) { - let tmp = node1.val; - node1.val = node2.val; - node2.val = tmp; -} - -function partition(head, tail) { - let slow = head, - fast = head.next; - let p = head.val; - while (fast != tail) { - if (fast.val <= p) { - slow = slow.next; - swap(slow, fast); - } - fast = fast.next; - } - swap(head, slow); - return slow; -} - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @return {ListNode} - */ -function sortList(head) { - if(head == null || head.next == null) return head - let slow = head, fast = head, pre = null - while(fast && fast.next) { - pre = slow - slow = slow.next - fast = fast.next.next - } - pre.next = null - const left = sortList(head) - const right = sortList(slow) - return merge(left, right) -} - -function merge(left, right) { - const dummy = new ListNode() - let cur = dummy - while(left && right) { - if (left.val <= right.val) { - cur.next = left - left = left.next - } else { - cur.next = right - right = right.next - } - cur = cur.next - } - if(left) { - cur.next = left - } - - if(right) { - cur.next = right - } - - return dummy.next -} - - -// another - - function sortList(head) { - quickSort(head, null); - return head; - } - - function quickSort( head, tail){ - if (head == tail) { - return; - } - let slow = head, fast = head.next; - let p = head.val; - while (fast != tail){ - if (fast.val <= p){ - slow = slow.next; - swap(slow, fast); - } - fast = fast.next; - } - swap(head, slow); - quickSort(head, slow); - quickSort(slow.next, tail); - } - - function swap( node1, node2){ - let tmp = node1.val; - node1.val = node2.val; - node2.val = tmp; - } - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @return {ListNode} - */ - -const sortList = function(head) { - let dummy = new ListNode(0); - dummy.next = head; - const list = []; - let done = (null === head); - // Keep partitioning our list into bigger sublists length. Starting with a size of 1 and doubling each time - for (let step = 1; !done; step *= 2) { - done = true; - let prev = dummy; - let remaining = prev.next; - do { - // Split off two sublists of size step - for (let i = 0; i < 2; ++i) { - list[i] = remaining; - let tail = null; - for (let j = 0; j < step && null != remaining; ++j, remaining = remaining.next) { - tail = remaining; - } - // Terminate our sublist - if (null != tail) { - tail.next = null; - } - } - - // We're done if these are the first two sublists in this pass and they - // encompass the entire primary list - done &= (null == remaining); - - // If we have two sublists, merge them into one - if (null != list[1]) { - while (null != list[0] || null != list[1]) { - let idx = (null == list[1] || null != list[0] && list[0].val <= list[1].val) ? 0 : 1; - prev.next = list[idx]; - list[idx] = list[idx].next; - prev = prev.next; - } - - // Terminate our new sublist - prev.next = null; - } else { - // Only a single sublist, no need to merge, just attach to the end - prev.next = list[0]; - } - } while (null !== remaining); - } - return dummy.next; -} - - diff --git a/148.sort-list.js b/148.sort-list.js new file mode 100644 index 00000000..3a9f7942 --- /dev/null +++ b/148.sort-list.js @@ -0,0 +1,46 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ +function sortList(head) { + quickSort(head, null); + return head; +} + +function quickSort(head, tail) { + if (head == tail) { + return; + } + const slow = partition(head, tail); + quickSort(head, slow); + quickSort(slow.next, tail); +} + +function swap(node1, node2) { + let tmp = node1.val; + node1.val = node2.val; + node2.val = tmp; +} + +function partition(head, tail) { + let slow = head, + fast = head.next; + let p = head.val; + while (fast != tail) { + if (fast.val <= p) { + slow = slow.next; + swap(slow, fast); + } + fast = fast.next; + } + swap(head, slow); + return slow; +} + diff --git a/1480-running-sum-of-1d-array.js b/1480.running-sum-of-1d-array.js similarity index 100% rename from 1480-running-sum-of-1d-array.js rename to 1480.running-sum-of-1d-array.js diff --git a/1481-least-number-of-unique-integers-after k-removals.js b/1481.least-number-of-unique-integers-after k-removals.js similarity index 100% rename from 1481-least-number-of-unique-integers-after k-removals.js rename to 1481.least-number-of-unique-integers-after k-removals.js diff --git a/1482-minimum-number-of-days-to-make-m-bouquets.js b/1482.minimum-number-of-days-to-make-m-bouquets.js similarity index 100% rename from 1482-minimum-number-of-days-to-make-m-bouquets.js rename to 1482.minimum-number-of-days-to-make-m-bouquets.js diff --git a/1483-kth-ancestor-of-a-tree-node.js b/1483.kth-ancestor-of-a-tree-node.js similarity index 100% rename from 1483-kth-ancestor-of-a-tree-node.js rename to 1483.kth-ancestor-of-a-tree-node.js diff --git a/1486-xor-operation-in-an-array.js b/1486.xor-operation-in-an-array.js similarity index 100% rename from 1486-xor-operation-in-an-array.js rename to 1486.xor-operation-in-an-array.js diff --git a/1489-find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree.js b/1489.find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree.js similarity index 100% rename from 1489-find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree.js rename to 1489.find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree.js diff --git a/149-max-points-on-a-line.js b/149.max-points-on-a-line.js similarity index 100% rename from 149-max-points-on-a-line.js rename to 149.max-points-on-a-line.js diff --git a/1490-clone-n-ary-tree.js b/1490-clone-n-ary-tree.js deleted file mode 100644 index e8cfe407..00000000 --- a/1490-clone-n-ary-tree.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * // Definition for a Node. - * function Node(val, children) { - * this.val = val === undefined ? 0 : val; - * this.children = children === undefined ? [] : children; - * }; - */ - -/** - * @param {Node} node - * @return {Node} - */ -const cloneTree = function(root) { - if(root == null) return null - let node = new Node(root.val) - for(let i = 0, len = root.children.length; i < len; i++) { - node.children.push(cloneTree(root.children[i])) - } - return node -}; - -// another - -/** - * // Definition for a Node. - * function Node(val, children) { - * this.val = val === undefined ? 0 : val; - * this.children = children === undefined ? [] : children; - * }; - */ - -/** - * @param {Node} node - * @return {Node} - */ -const cloneTree = function(root) { - if (root === null) return null - const Q = [] - const rootCopy = new Node(root.val) - Q.push([root, rootCopy]) - while (Q.length) { - const temp = Q.shift() - const node = temp[0] - const copy = temp[1] - node.children.forEach((child) => { - const copyChild = new Node(child.val) - copy.children.push(copyChild) - Q.push([child, copyChild]) - }) - } - - return rootCopy -}; diff --git a/1490.clone-n-ary-tree.js b/1490.clone-n-ary-tree.js new file mode 100644 index 00000000..25139321 --- /dev/null +++ b/1490.clone-n-ary-tree.js @@ -0,0 +1,21 @@ +/** + * // Definition for a Node. + * function Node(val, children) { + * this.val = val === undefined ? 0 : val; + * this.children = children === undefined ? [] : children; + * }; + */ + +/** + * @param {Node} node + * @return {Node} + */ +const cloneTree = function(root) { + if(root == null) return null + let node = new Node(root.val) + for(let i = 0, len = root.children.length; i < len; i++) { + node.children.push(cloneTree(root.children[i])) + } + return node +}; + diff --git a/1492-the-kth-factor-of-n.js b/1492.the-kth-factor-of-n.js similarity index 100% rename from 1492-the-kth-factor-of-n.js rename to 1492.the-kth-factor-of-n.js diff --git a/1493-longest-subarray-of-1s-after-deleting-one-element.js b/1493.longest-subarray-of-1s-after-deleting-one-element.js similarity index 100% rename from 1493-longest-subarray-of-1s-after-deleting-one-element.js rename to 1493.longest-subarray-of-1s-after-deleting-one-element.js diff --git a/1494-parallel-courses-ii.js b/1494-parallel-courses-ii.js deleted file mode 100644 index 0882499f..00000000 --- a/1494-parallel-courses-ii.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} dependencies - * @param {number} k - * @return {number} - */ -const minNumberOfSemesters = function (n, dependencies, k) { - const preq = new Array(n).fill(0) - for (let dep of dependencies) { - // to study j, what are the prerequisites? - // each set bit is a class that we need to take. ith bit means ith class - // -1 because classes are 1 to n - preq[dep[1] - 1] |= 1 << (dep[0] - 1) - } - const dp = new Array(1 << n).fill(n) - dp[0] = 0 - for (let i = 0; i < 1 << n; i++) { - // we are now at status i. we can "influence" a later status from this status - let canStudy = 0 // what are the classes we can study? - for (let j = 0; j < n; j++) { - // a & b== b means b is a's subset - // so if preq[j] is i's subset, we can now study j given status i - if ((i & preq[j]) == preq[j]) { - canStudy |= 1 << j - } - } - canStudy &= ~i - // take out i, so that we only enumerate a subset canStudy without i. - // note we will | later so here we need a set that has no - // intersection with i to reduce the enumeration cost - for (let sub = canStudy; sub > 0; sub = (sub - 1) & canStudy) { - // we can study one or more courses indicated by set "canStudy". - // we need to enumerate all non empty subset of it. - // This for loop is a typical way to enumerate all subsets of a given set "canStudy" - // we studied i using dp[i] semesters. now if we also study the - // subset sub, we need dp [i ]+1 semesters, - // and the status we can "influence" is dp[ i | sub] because at - // that state, we studied what we want to study in "sub" - if (bitCount(sub) <= k) { - dp[i | sub] = Math.min(dp[i | sub], dp[i] + 1) - } - } - } - return dp[(1 << n) - 1] -} -function bitCount(n) { - n = n - ((n >> 1) & 0x55555555) - n = (n & 0x33333333) + ((n >> 2) & 0x33333333) - return (((n + (n >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24 -} - -// another - -/** - * @param {number} n - * @param {number[][]} dependencies - * @param {number} k - * @return {number} - */ -const minNumberOfSemesters = function (n, dependencies, k) { - const pre = Array(n).fill(0) - const limit = 1 << n - for(const [p, v] of dependencies) { - pre[v - 1] |= (1 << (p - 1)) - } - const dp = Array(limit).fill(Infinity) - dp[0] = 0 - - for(let learned = 0; learned < limit; learned++) { - let wait = 0 - for(let i = 0; i < n; i++) { - if( (learned & pre[i]) === pre[i]) { - wait |= (1 << i) - } - } - wait = wait & (~learned) - for(let sub = wait; sub; sub = (sub - 1) & wait) { - if(bitCnt(sub) > k) continue - const mask = learned | sub - dp[mask] = Math.min(dp[mask], dp[learned] + 1) - } - } - - return dp[limit - 1] -} - -function bitCnt(num) { - let res = 0 - while(num) { - num &= (num - 1) - res++ - } - - return res -} - - - diff --git a/1494.parallel-courses-ii.js b/1494.parallel-courses-ii.js new file mode 100644 index 00000000..0a0ff296 --- /dev/null +++ b/1494.parallel-courses-ii.js @@ -0,0 +1,51 @@ +/** + * @param {number} n + * @param {number[][]} dependencies + * @param {number} k + * @return {number} + */ +const minNumberOfSemesters = function (n, dependencies, k) { + const preq = new Array(n).fill(0) + for (let dep of dependencies) { + // to study j, what are the prerequisites? + // each set bit is a class that we need to take. ith bit means ith class + // -1 because classes are 1 to n + preq[dep[1] - 1] |= 1 << (dep[0] - 1) + } + const dp = new Array(1 << n).fill(n) + dp[0] = 0 + for (let i = 0; i < 1 << n; i++) { + // we are now at status i. we can "influence" a later status from this status + let canStudy = 0 // what are the classes we can study? + for (let j = 0; j < n; j++) { + // a & b== b means b is a's subset + // so if preq[j] is i's subset, we can now study j given status i + if ((i & preq[j]) == preq[j]) { + canStudy |= 1 << j + } + } + canStudy &= ~i + // take out i, so that we only enumerate a subset canStudy without i. + // note we will | later so here we need a set that has no + // intersection with i to reduce the enumeration cost + for (let sub = canStudy; sub > 0; sub = (sub - 1) & canStudy) { + // we can study one or more courses indicated by set "canStudy". + // we need to enumerate all non empty subset of it. + // This for loop is a typical way to enumerate all subsets of a given set "canStudy" + // we studied i using dp[i] semesters. now if we also study the + // subset sub, we need dp [i ]+1 semesters, + // and the status we can "influence" is dp[ i | sub] because at + // that state, we studied what we want to study in "sub" + if (bitCount(sub) <= k) { + dp[i | sub] = Math.min(dp[i | sub], dp[i] + 1) + } + } + } + return dp[(1 << n) - 1] +} +function bitCount(n) { + n = n - ((n >> 1) & 0x55555555) + n = (n & 0x33333333) + ((n >> 2) & 0x33333333) + return (((n + (n >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24 +} + diff --git a/1498-number-of-subsequences-that-satisfy-the-given-sum-condition.js b/1498.number-of-subsequences-that-satisfy-the-given-sum-condition.js similarity index 100% rename from 1498-number-of-subsequences-that-satisfy-the-given-sum-condition.js rename to 1498.number-of-subsequences-that-satisfy-the-given-sum-condition.js diff --git a/1499-max-value-of-equation.js b/1499-max-value-of-equation.js deleted file mode 100644 index d005a055..00000000 --- a/1499-max-value-of-equation.js +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @param {number[][]} points - * @param {number} k - * @return {number} - */ -const findMaxValueOfEquation = function (points, k) { - let res = -Number.MAX_VALUE - const deque = [] - for (let i = 0; i < points.length; i++) { - const x = points[i][0] - const y = points[i][1] - while (deque.length != 0 && x - deque[0][1] > k) { - deque.shift() - } - if (deque.length != 0) { - res = Math.max(res, deque[0][0] + x + y) - } - while (deque.length != 0 && deque[deque.length - 1][0] <= y - x) { - deque.pop() - } - deque.push([y - x, x]) - } - return res -} - -// another - -/** - * @param {number[][]} points - * @param {number} k - * @return {number} - */ -const findMaxValueOfEquation = function (points, k) { - const pq = new PriorityQueue((a, b) => - a[0] === b[0] ? a[1] < b[1] : b[0] < a[0] - ) - let res = -Infinity - for (let point of points) { - while (!pq.isEmpty() && point[0] - pq.peek()[1] > k) { - pq.pop() - } - if (!pq.isEmpty()) { - res = Math.max(res, pq.peek()[0] + point[0] + point[1]) - } - pq.push([point[1] - point[0], point[0]]) - } - return res -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/1499.max-value-of-equation.js b/1499.max-value-of-equation.js new file mode 100644 index 00000000..f9dcee50 --- /dev/null +++ b/1499.max-value-of-equation.js @@ -0,0 +1,25 @@ +/** + * @param {number[][]} points + * @param {number} k + * @return {number} + */ +const findMaxValueOfEquation = function (points, k) { + let res = -Number.MAX_VALUE + const deque = [] + for (let i = 0; i < points.length; i++) { + const x = points[i][0] + const y = points[i][1] + while (deque.length != 0 && x - deque[0][1] > k) { + deque.shift() + } + if (deque.length != 0) { + res = Math.max(res, deque[0][0] + x + y) + } + while (deque.length != 0 && deque[deque.length - 1][0] <= y - x) { + deque.pop() + } + deque.push([y - x, x]) + } + return res +} + diff --git a/15-3sum.js b/15-3sum.js deleted file mode 100755 index 498fc859..00000000 --- a/15-3sum.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[][]} - */ -const threeSum = function(nums) { - const res = [], n = nums.length - nums.sort((a, b) => a - b) - - for(let i = 0; i < n; i++) { - const target = -nums[i] - let l = i + 1, r = n - 1 - while(l < r) { - const sum = nums[l] + nums[r] - if(sum > target) r-- - else if(sum < target) l++ - else { - const e = [nums[i], nums[l], nums[r]] - res.push(e) - while(l + 1 < r && nums[l + 1] === nums[l]) l++ - while(r - 1 > l && nums[r - 1] === nums[r]) r-- - l++ - r-- - } - } - while(i + 1 < n && nums[i] === nums[i + 1]) i++ - } - - - return res -}; - -// another - - -/** - * @param {number[]} nums - * @return {number[][]} - */ -const threeSum = function (nums) { - nums.sort((a, b) => a - b) - const res = [] - let lo, hi, sum - for (let i = 0; i < nums.length - 2; i++) { - if (nums[i] > 0) break - if (nums[i] === nums[i - 1]) continue - if (i === 0 || (i > 0 && nums[i] !== nums[i - 1])) { - lo = i + 1 - hi = nums.length - 1 - sum = 0 - nums[i] - while (lo < hi) { - if (nums[lo] + nums[hi] === sum) { - res.push([nums[i], nums[lo], nums[hi]]) - while (lo < hi && nums[lo] === nums[lo + 1]) lo += 1 - while (lo < hi && nums[hi] === nums[hi - 1]) hi -= 1 - lo += 1 - hi -= 1 - } else if (nums[lo] + nums[hi] < sum) lo++ - else hi-- - } - } - } - return res -} - -// another - -/** - * @param {number[]} nums - * @return {number[][]} - */ -const threeSum = function(nums) { - const res = [], n = nums.length - nums.sort((a, b) => a - b) - for(let i = 0; i < n - 2; i++) { - let l = i + 1, r = n - 1, target = -nums[i] - if(i === 0 || (i > 0 && nums[i] !== nums[i - 1])) { - while(l < r) { - if(nums[l] + nums[r] === target) { - res.push([nums[i], nums[l], nums[r]]) - while(l < n - 1 && nums[l] === nums[l + 1]) l++ - while(r > 0 && nums[r] === nums[r - 1]) r-- - r-- - l++ - } else if(nums[l] + nums[r] > target) { - r-- - } else l++ - } - } - } - - return res -}; diff --git a/15.3sum.js b/15.3sum.js new file mode 100644 index 00000000..2e67d18c --- /dev/null +++ b/15.3sum.js @@ -0,0 +1,31 @@ +/** + * @param {number[]} nums + * @return {number[][]} + */ +const threeSum = function(nums) { + const res = [], n = nums.length + nums.sort((a, b) => a - b) + + for(let i = 0; i < n; i++) { + const target = -nums[i] + let l = i + 1, r = n - 1 + while(l < r) { + const sum = nums[l] + nums[r] + if(sum > target) r-- + else if(sum < target) l++ + else { + const e = [nums[i], nums[l], nums[r]] + res.push(e) + while(l + 1 < r && nums[l + 1] === nums[l]) l++ + while(r - 1 > l && nums[r - 1] === nums[r]) r-- + l++ + r-- + } + } + while(i + 1 < n && nums[i] === nums[i + 1]) i++ + } + + + return res +}; + diff --git a/150-evaluate-reverse-polish-notation.js b/150.evaluate-reverse-polish-notation.js similarity index 100% rename from 150-evaluate-reverse-polish-notation.js rename to 150.evaluate-reverse-polish-notation.js diff --git a/1503-last-moment-before-all-ants-fall-out-of-a-plank.js b/1503.last-moment-before-all-ants-fall-out-of-a-plank.js similarity index 100% rename from 1503-last-moment-before-all-ants-fall-out-of-a-plank.js rename to 1503.last-moment-before-all-ants-fall-out-of-a-plank.js diff --git a/1505-minimum-possible-integer-after-at-most-k-adjacent-swaps-on-digits.js b/1505.minimum-possible-integer-after-at-most-k-adjacent-swaps-on-digits.js similarity index 100% rename from 1505-minimum-possible-integer-after-at-most-k-adjacent-swaps-on-digits.js rename to 1505.minimum-possible-integer-after-at-most-k-adjacent-swaps-on-digits.js diff --git a/1506-find-root-of-n-ary-tree.js b/1506-find-root-of-n-ary-tree.js deleted file mode 100644 index 7f1316af..00000000 --- a/1506-find-root-of-n-ary-tree.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * // Definition for a Node. - * function Node(val, children) { - * this.val = val === undefined ? 0 : val; - * this.children = children === undefined ? [] : children; - * }; - */ - -/** - * @param {Node[]} tree - * @return {Node} - */ -const findRoot = function(tree) { - let sum = 0 - for(let n of tree) { - sum += n.val - for(let c of n.children) { - sum -= c.val - } - } - for(let n of tree) { - if(n.val === sum) return n - } - return null -}; - -// another - -/** - * // Definition for a Node. - * function Node(val, children) { - * this.val = val === undefined ? 0 : val; - * this.children = children === undefined ? [] : children; - * }; - */ - -/** - * @param {Node[]} tree - * @return {Node} - */ -const findRoot = function(tree) { - let sum = 0 - for(let n of tree) { - sum ^= n.val - for(let c of n.children) { - sum ^= c.val - } - } - for(let n of tree) { - if(n.val === sum) return n - } - return null -}; diff --git a/1506.find-root-of-n-ary-tree.js b/1506.find-root-of-n-ary-tree.js new file mode 100644 index 00000000..e0f7fd68 --- /dev/null +++ b/1506.find-root-of-n-ary-tree.js @@ -0,0 +1,26 @@ +/** + * // Definition for a Node. + * function Node(val, children) { + * this.val = val === undefined ? 0 : val; + * this.children = children === undefined ? [] : children; + * }; + */ + +/** + * @param {Node[]} tree + * @return {Node} + */ +const findRoot = function(tree) { + let sum = 0 + for(let n of tree) { + sum += n.val + for(let c of n.children) { + sum -= c.val + } + } + for(let n of tree) { + if(n.val === sum) return n + } + return null +}; + diff --git a/1507-reformat-date.js b/1507.reformat-date.js similarity index 100% rename from 1507-reformat-date.js rename to 1507.reformat-date.js diff --git a/1509-minimum-difference-between-largest-and-smallest-value-in-three-moves.js b/1509.minimum-difference-between-largest-and-smallest-value-in-three-moves.js similarity index 100% rename from 1509-minimum-difference-between-largest-and-smallest-value-in-three-moves.js rename to 1509.minimum-difference-between-largest-and-smallest-value-in-three-moves.js diff --git a/151-reverse-words-in-a-string.js b/151-reverse-words-in-a-string.js deleted file mode 100755 index bc6c0f9d..00000000 --- a/151-reverse-words-in-a-string.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @param {string} str - * @returns {string} - */ -const reverseWords = function(str) { - return str - .trim() - .split(/\s+/) - .reverse() - .join(" "); -}; - -// another - -/** - * @param {string} str - * @returns {string} - */ -const reverseWords = function (s) { - let sb = '' - const n = s.length - let i = n - 1 - while (i >= 0) { - if (s.charAt(i) == ' ') { - i-- - continue - } - let j = i - 1 - while (j >= 0 && s.charAt(j) != ' ') j-- - sb += ' ' - sb += s.slice(j + 1, i + 1) - i = j - 1 - } - if (sb.length > 0) sb = sb.slice(1) - return sb -} diff --git a/151.reverse-words-in-a-string.js b/151.reverse-words-in-a-string.js new file mode 100644 index 00000000..e9149aad --- /dev/null +++ b/151.reverse-words-in-a-string.js @@ -0,0 +1,12 @@ +/** + * @param {string} str + * @returns {string} + */ +const reverseWords = function(str) { + return str + .trim() + .split(/\s+/) + .reverse() + .join(" "); +}; + diff --git a/1510-stone-game-iv.js b/1510.stone-game-iv.js similarity index 100% rename from 1510-stone-game-iv.js rename to 1510.stone-game-iv.js diff --git a/1512-number-of-good-pairs.js b/1512.number-of-good-pairs.js similarity index 100% rename from 1512-number-of-good-pairs.js rename to 1512.number-of-good-pairs.js diff --git a/1514-path-with-maximum-probability.js b/1514-path-with-maximum-probability.js deleted file mode 100644 index bd47209e..00000000 --- a/1514-path-with-maximum-probability.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} edges - * @param {number[]} succProb - * @param {number} start - * @param {number} end - * @return {number} - */ -const maxProbability = function (n, edges, succProb, start, end) { - const g = {} - for (let i = 0; i < edges.length; ++i) { - const a = edges[i][0], - b = edges[i][1] - if (g[a] == null) g[a] = [] - if (g[b] == null) g[b] = [] - g[a].push([b, i]) - g[b].push([a, i]) - } - const p = new Array(n).fill(0) - p[start] = 1 - const pq = new PriorityQueue((a, b) => p[a] > p[b]) - pq.push(start) - while (!pq.isEmpty()) { - const cur = pq.pop() - if (cur === end) { - return p[end] - } - for (let a of g[cur] || []) { - const neighbor = a[0], - index = a[1] - if (p[cur] * succProb[index] > p[neighbor]) { - p[neighbor] = p[cur] * succProb[index] - pq.push(neighbor) - } - } - } - return 0 -} -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/1515-best-position-for-a-service-centre.js b/1515.best-position-for-a-service-centre.js similarity index 100% rename from 1515-best-position-for-a-service-centre.js rename to 1515.best-position-for-a-service-centre.js diff --git a/1516-move-sub-tree-of-n-ary-tree.js b/1516.move-sub-tree-of-n-ary-tree.js similarity index 100% rename from 1516-move-sub-tree-of-n-ary-tree.js rename to 1516.move-sub-tree-of-n-ary-tree.js diff --git a/152-maximum-product-subarray.js b/152-maximum-product-subarray.js deleted file mode 100644 index 8effa588..00000000 --- a/152-maximum-product-subarray.js +++ /dev/null @@ -1,110 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const maxProduct = function(nums) { - let min = nums[0], max = nums[0], res = nums[0] - for(let i = 1, n = nums.length; i < n; i++) { - const e = nums[i] - if(e < 0) [min, max] = [max, min] - min = Math.min(e, min * e) - max = Math.max(e, max * e) - res = Math.max(res, max) - } - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxProduct = function(nums) { - let A = nums - let r = A[0]; - - // imax/imin stores the max/min product of - // subarray that ends with the current number A[i] - for (let i = 1, imax = r, imin = r, n = A.length; i < n; i++) { - if (A[i] < 0) { - let tmp = imax - imax = imin - imin = tmp - }; - // max/min product for the current number is either the current number itself - // or the max/min by the previous number times the current one - imax = Math.max(A[i], imax * A[i]); - imin = Math.min(A[i], imin * A[i]); - - // the newly computed max value is a candidate for our global result - r = Math.max(r, imax); - } - return r; -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxProduct = function(nums) { - if(nums.length == 1)return nums[0]; - let dpMax = nums[0]; - let dpMin = nums[0]; - let max = nums[0]; - for (let i = 1; i < nums.length; i++) { - let k = dpMax*nums[i]; - let m = dpMin*nums[i]; - dpMax = Math.max(nums[i], Math.max(k, m)); - dpMin = Math.min(nums[i], Math.min(k, m)); - max = Math.max(dpMax, max); - } - return max; -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxProduct = function(nums) { - const n = nums.length - let max, min - let res = max = min = nums[0] - for(let i = 1; i < n; i++) { - if(nums[i] < 0) [max, min] = [min, max] - max = Math.max(nums[i], nums[i] * max) - min = Math.min(nums[i], nums[i] * min) - res = Math.max(res, max) - } - return res -}; - - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxProduct = function (nums) { - if(nums == null || nums.length === 0) return 0 - const n = nums.length - let res = nums[0] - for(let i = 1, min = res, max = res; i < n; i++) { - if(nums[i] < 0) { - let tmax = max, tmin = min - min = Math.min(nums[i], tmax * nums[i]) - max = Math.max(nums[i], tmin * nums[i]) - } else { - min = Math.min(nums[i], min * nums[i]) - max = Math.max(nums[i], max * nums[i]) - } - res = Math.max(res, max) - } - - return res -} diff --git a/152.maximum-product-subarray.js b/152.maximum-product-subarray.js new file mode 100644 index 00000000..d94fdfe8 --- /dev/null +++ b/152.maximum-product-subarray.js @@ -0,0 +1,16 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const maxProduct = function(nums) { + let min = nums[0], max = nums[0], res = nums[0] + for(let i = 1, n = nums.length; i < n; i++) { + const e = nums[i] + if(e < 0) [min, max] = [max, min] + min = Math.min(e, min * e) + max = Math.max(e, max * e) + res = Math.max(res, max) + } + return res +}; + diff --git a/1521-find-a-value-of-a-mysterious-function-closest-to-target.js b/1521.find-a-value-of-a-mysterious-function-closest-to-target.js similarity index 100% rename from 1521-find-a-value-of-a-mysterious-function-closest-to-target.js rename to 1521.find-a-value-of-a-mysterious-function-closest-to-target.js diff --git a/1522-diameter-of-n-ary-tree.js b/1522.diameter-of-n-ary-tree.js similarity index 100% rename from 1522-diameter-of-n-ary-tree.js rename to 1522.diameter-of-n-ary-tree.js diff --git a/1523-count-odd-numbers-in-an-interval-range.js b/1523-count-odd-numbers-in-an-interval-range.js deleted file mode 100644 index 2c47f34f..00000000 --- a/1523-count-odd-numbers-in-an-interval-range.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @param {number} low - * @param {number} high - * @return {number} - */ -const countOdds = function(low, high) { - let res = 0 - - const odd = num => num % 2 === 1 - if(odd(low)) res++ - - const num = Math.floor( (high - low) / 2 ) - res += num - - if(high > low + 2 * num && odd(high)) res++ - - return res -}; - - -// another - -/** - * @param {number} low - * @param {number} high - * @return {number} - */ -const countOdds = function(low, high) { - return ~~((high + 1) / 2) - (~~(low / 2)) -}; diff --git a/1523.count-odd-numbers-in-an-interval-range.js b/1523.count-odd-numbers-in-an-interval-range.js new file mode 100644 index 00000000..35b6c635 --- /dev/null +++ b/1523.count-odd-numbers-in-an-interval-range.js @@ -0,0 +1,20 @@ +/** + * @param {number} low + * @param {number} high + * @return {number} + */ +const countOdds = function(low, high) { + let res = 0 + + const odd = num => num % 2 === 1 + if(odd(low)) res++ + + const num = Math.floor( (high - low) / 2 ) + res += num + + if(high > low + 2 * num && odd(high)) res++ + + return res +}; + + diff --git a/1524-number-of-sub-arrays-with-odd-sum.js b/1524-number-of-sub-arrays-with-odd-sum.js deleted file mode 100644 index 1b3fed50..00000000 --- a/1524-number-of-sub-arrays-with-odd-sum.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @param {number[]} arr - * @return {number} - */ -const numOfSubarrays = function(arr) { - const n = arr.length, mod = 1e9 + 7 - let sum = 0, res = 0, oddCnt = 0, evenCnt = 0 - - for(let i = 0; i < n; i++) { - const cur = arr[i] - sum += cur - if(sum % 2 === 1) { - res++ - res += evenCnt - oddCnt++ - } else { - res += oddCnt - evenCnt++ - } - } - - return res % mod -}; - -// another - -/** - * @param {number[]} arr - * @return {number} - */ -const numOfSubarrays = function(arr) { - const n = arr.length, mod = 1e9 + 7 - - let oc = 0, ec = 1 - let sum = 0 - let res = 0 - for(let i = 0; i < n; i++) { - sum += arr[i] - if(sum % 2 === 1) { - res += ec - oc++ - } else { - res += oc - ec++ - } - } - - return res % mod -}; diff --git a/1524.number-of-sub-arrays-with-odd-sum.js b/1524.number-of-sub-arrays-with-odd-sum.js new file mode 100644 index 00000000..77195049 --- /dev/null +++ b/1524.number-of-sub-arrays-with-odd-sum.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} arr + * @return {number} + */ +const numOfSubarrays = function(arr) { + const n = arr.length, mod = 1e9 + 7 + let sum = 0, res = 0, oddCnt = 0, evenCnt = 0 + + for(let i = 0; i < n; i++) { + const cur = arr[i] + sum += cur + if(sum % 2 === 1) { + res++ + res += evenCnt + oddCnt++ + } else { + res += oddCnt + evenCnt++ + } + } + + return res % mod +}; + diff --git a/1525-number-of-good-ways-to-split-a-string.js b/1525-number-of-good-ways-to-split-a-string.js deleted file mode 100644 index 4c443bc6..00000000 --- a/1525-number-of-good-ways-to-split-a-string.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const numSplits = function(s) { - const n = s.length - const freq = new Map() - const prefix = Array(26).fill(0) - for(let i = 0; i < n; i++) { - if(freq.get(s[i]) == null) freq.set(s[i], 0) - freq.set(s[i], freq.get(s[i]) + 1) - prefix[i] = freq.size - } - freq.clear() - const suffix = Array(26).fill(0) - for(let i = n - 1; i >= 0 ;i--) { - if(freq.get(s[i]) == null) freq.set(s[i], 0) - freq.set(s[i], freq.get(s[i]) + 1) - suffix[i] = freq.size - } - // console.log(prefix, suffix) - let res = 0 - for(let i = 1; i < n; i++) { - if(prefix[i - 1] === suffix[i]) res++ - } - - return res -}; - - -// another - - -/** - * @param {string} s - * @return {number} - */ -const numSplits = function(s) { - const arr = Array(26).fill(0) - const a = 'a'.charCodeAt(0) - for(let i = 0, len = s.length; i < len; i++) { - arr[s.charCodeAt(i) - a]++ - } - const cur = Array(26).fill(0) - let res = 0 - for(let i = 0, len = s.length; i < len - 1; i++) { - cur[s.charCodeAt(i) - a]++ - let tmp = false, clone = arr.slice() - for(let j = 0; j < 26; j++) { - clone[j] -= cur[j] - } - const curNum = cur.reduce((ac, e) => ac + (e > 0 ? 1 : 0), 0) - const cloneNum = clone.reduce((ac, e) => ac + (e > 0 ? 1 : 0), 0) - if(curNum === cloneNum) res++ - } - - return res -}; - diff --git a/1525.number-of-good-ways-to-split-a-string.js b/1525.number-of-good-ways-to-split-a-string.js new file mode 100644 index 00000000..095a301c --- /dev/null +++ b/1525.number-of-good-ways-to-split-a-string.js @@ -0,0 +1,30 @@ +/** + * @param {string} s + * @return {number} + */ +const numSplits = function(s) { + const n = s.length + const freq = new Map() + const prefix = Array(26).fill(0) + for(let i = 0; i < n; i++) { + if(freq.get(s[i]) == null) freq.set(s[i], 0) + freq.set(s[i], freq.get(s[i]) + 1) + prefix[i] = freq.size + } + freq.clear() + const suffix = Array(26).fill(0) + for(let i = n - 1; i >= 0 ;i--) { + if(freq.get(s[i]) == null) freq.set(s[i], 0) + freq.set(s[i], freq.get(s[i]) + 1) + suffix[i] = freq.size + } + // console.log(prefix, suffix) + let res = 0 + for(let i = 1; i < n; i++) { + if(prefix[i - 1] === suffix[i]) res++ + } + + return res +}; + + diff --git a/1526-minimum-number-of-increments-on-subarrays-to-form-a-target-array.js b/1526-minimum-number-of-increments-on-subarrays-to-form-a-target-array.js deleted file mode 100644 index 8464391c..00000000 --- a/1526-minimum-number-of-increments-on-subarrays-to-form-a-target-array.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @param {number[]} target - * @return {number} - */ -const minNumberOperations = function(target) { - let res = target[0] - - for(let i = 1; i < target.length; i++) { - res += Math.max(0, target[i] - target[i - 1]) - } - - return res -} - -// another - -/** - * @param {number[]} target - * @return {number} - */ -const minNumberOperations = function(target) { - let totalOperations = target[0]; - for (let i = 1; i < target.length; ++i) { - if (target[i] > target[i-1]) { - totalOperations += target[i] - target[i-1]; - } - } - return totalOperations; -}; diff --git a/1526.minimum-number-of-increments-on-subarrays-to-form-a-target-array.js b/1526.minimum-number-of-increments-on-subarrays-to-form-a-target-array.js new file mode 100644 index 00000000..103cffa3 --- /dev/null +++ b/1526.minimum-number-of-increments-on-subarrays-to-form-a-target-array.js @@ -0,0 +1,14 @@ +/** + * @param {number[]} target + * @return {number} + */ +const minNumberOperations = function(target) { + let res = target[0] + + for(let i = 1; i < target.length; i++) { + res += Math.max(0, target[i] - target[i - 1]) + } + + return res +} + diff --git a/1528-shuffle-string.js b/1528.shuffle-string.js similarity index 100% rename from 1528-shuffle-string.js rename to 1528.shuffle-string.js diff --git a/1529-minimum-suffix-flips.js b/1529.minimum-suffix-flips.js similarity index 100% rename from 1529-minimum-suffix-flips.js rename to 1529.minimum-suffix-flips.js diff --git a/153-find-minimum-in-rotated-sorted-array.js b/153.find-minimum-in-rotated-sorted-array.js similarity index 100% rename from 153-find-minimum-in-rotated-sorted-array.js rename to 153.find-minimum-in-rotated-sorted-array.js diff --git a/1530-number-of-good-leaf-nodes-pairs.js b/1530.number-of-good-leaf-nodes-pairs.js similarity index 100% rename from 1530-number-of-good-leaf-nodes-pairs.js rename to 1530.number-of-good-leaf-nodes-pairs.js diff --git a/1531-string-compression-ii.js b/1531-string-compression-ii.js deleted file mode 100644 index 31a2e728..00000000 --- a/1531-string-compression-ii.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @param {string} s - * @param {number} k - * @return {number} - */ -const getLengthOfOptimalCompression = function(s, k) { - const m = new Map() - function counter(start, last, lastCount, left) { - if(left < 0) return Infinity - if(start >= s.length) return 0 - let res - const k = `${start}-${last}-${lastCount}-${left}` - if(m.has(k)) return m.get(k) - if(s[start] === last) { - const incr = (lastCount === 1 || lastCount === 9 || lastCount === 99) ? 1 : 0 - res = incr + counter(start + 1, last, lastCount + 1, left) - } else { - const keepCounter = 1 + counter(start + 1, s[start], 1, left) - const delCounter = counter(start + 1, last, lastCount, left - 1) - res = Math.min(keepCounter, delCounter) - } - m.set(k, res) - return res - } - return counter(0, '', 0, k) -}; - -// another - -const getLengthOfOptimalCompression = function (s, k) { - const n = s.length - const dp = new Array(n + 1).fill(n).map((row) => new Array(k + 1).fill(n)) - dp[0][0] = 0 - - for (let i = 1; i <= n; i++) { - for (let j = 0; j <= k; j++) { - let letterCount = 0 - let deletion = 0 - // keep s[i], compress same letters, remove different letters - for (let l = i; l >= 1; l--) { - if (s.charAt(l - 1) === s.charAt(i - 1)) letterCount++ - else deletion++ - // places = length needed to rep compressed letters. - // 0 places for count = 1,0, 1 place = <10, 10-99 requires 2 places, 100+ requires 3 - let places = 0 - if (letterCount >= 100) places = 3 - else if (letterCount >= 10) places = 2 - else if (letterCount >= 2) places = 1 - if (j - deletion >= 0) { - dp[i][j] = Math.min(dp[i][j], dp[l - 1][j - deletion] + 1 + places) - } - } - // delete - if (j > 0) { - dp[i][j] = Math.min(dp[i][j], dp[i - 1][j - 1]) - } - } - } - return dp[n][k] -} - diff --git a/1531.string-compression-ii.js b/1531.string-compression-ii.js new file mode 100644 index 00000000..0c968012 --- /dev/null +++ b/1531.string-compression-ii.js @@ -0,0 +1,27 @@ +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +const getLengthOfOptimalCompression = function(s, k) { + const m = new Map() + function counter(start, last, lastCount, left) { + if(left < 0) return Infinity + if(start >= s.length) return 0 + let res + const k = `${start}-${last}-${lastCount}-${left}` + if(m.has(k)) return m.get(k) + if(s[start] === last) { + const incr = (lastCount === 1 || lastCount === 9 || lastCount === 99) ? 1 : 0 + res = incr + counter(start + 1, last, lastCount + 1, left) + } else { + const keepCounter = 1 + counter(start + 1, s[start], 1, left) + const delCounter = counter(start + 1, last, lastCount, left - 1) + res = Math.min(keepCounter, delCounter) + } + m.set(k, res) + return res + } + return counter(0, '', 0, k) +}; + diff --git a/1534-count-good-triplets.js b/1534.count-good-triplets.js similarity index 100% rename from 1534-count-good-triplets.js rename to 1534.count-good-triplets.js diff --git a/1537-get-the-maximum-score.js b/1537-get-the-maximum-score.js deleted file mode 100644 index bf35ef7b..00000000 --- a/1537-get-the-maximum-score.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - -You are given two sorted arrays of distinct integers nums1 and nums2. - -A valid path is defined as follows: - -Choose array nums1 or nums2 to traverse (from index-0). -Traverse the current array from left to right. -If you are reading any value that is present in nums1 and nums2 you are -allowed to change your path to the other array. -(Only one repeated value is considered in the valid path). -Score is defined as the sum of uniques values in a valid path. - -Return the maximum score you can obtain of all possible valid paths. - -Since the answer may be too large, return it modulo 10^9 + 7. - -Example 1: - -Input: nums1 = [2,4,5,8,10], nums2 = [4,6,8,9] -Output: 30 -Explanation: Valid paths: -[2,4,5,8,10], [2,4,5,8,9], [2,4,6,8,9], [2,4,6,8,10], (starting from nums1) -[4,6,8,9], [4,5,8,10], [4,5,8,9], [4,6,8,10] (starting from nums2) -The maximum is obtained with the path in green [2,4,6,8,10]. - -Example 2: - -Input: nums1 = [1,3,5,7,9], nums2 = [3,5,100] -Output: 109 -Explanation: Maximum sum is obtained with the path [1,3,5,100]. -Example 3: - -Input: nums1 = [1,2,3,4,5], nums2 = [6,7,8,9,10] -Output: 40 -Explanation: There are no common elements between nums1 and nums2. -Maximum sum is obtained with the path [6,7,8,9,10]. -Example 4: - -Input: nums1 = [1,4,5,8,9,11,19], nums2 = [2,3,4,11,12] -Output: 61 - - -Constraints: - -1 <= nums1.length <= 10^5 -1 <= nums2.length <= 10^5 -1 <= nums1[i], nums2[i] <= 10^7 -nums1 and nums2 are strictly increasing. - -*/ - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const maxSum = function(nums1, nums2) { - let i = 0, j = 0, n = nums1.length, m = nums2.length; - let a = 0, b = 0, mod = 10 ** 9 + 7; - while (i < n || j < m) { - if (i < n && (j === m || nums1[i] < nums2[j])) { - a += nums1[i++]; - } else if (j < m && (i === n || nums1[i] > nums2[j])) { - b += nums2[j++]; - } else { - a = b = Math.max(a, b) + nums1[i]; - i++; j++; - } - } - return Math.max(a, b) % mod; -}; - -// another - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const maxSum = function(nums1, nums2) { - const len1 = nums1.length, len2 = nums2.length - const mod = 10 ** 9 + 7 - const map = new Map() - for(let i = 0; i < len1 - 1; i++) { - if(!map.has(nums1[i])) map.set(nums1[i], []) - map.get(nums1[i]).push(nums1[i + 1]) - } - for(let j = 0; j < len2 - 1; j++) { - if(!map.has(nums2[j])) map.set(nums2[j], []) - map.get(nums2[j]).push(nums2[j + 1]) - } - const memo = new Map() - return Math.max(greedy(nums1[0], map, memo), greedy(nums2[0], map, memo)) % mod -}; - -function greedy(cur, map, memo) { - if(memo.has(cur)) return memo.get(cur) - if(!map.has(cur)) return cur - let res = 0 - for(let next of map.get(cur)) { - const tmp = greedy(next, map, memo) - if(tmp > res) res = tmp - } - res += cur - memo.set(cur, res) - return res -} diff --git a/1537.get-the-maximum-score.js b/1537.get-the-maximum-score.js new file mode 100644 index 00000000..5262a11f --- /dev/null +++ b/1537.get-the-maximum-score.js @@ -0,0 +1,73 @@ +/** + +You are given two sorted arrays of distinct integers nums1 and nums2. + +A valid path is defined as follows: + +Choose array nums1 or nums2 to traverse (from index-0). +Traverse the current array from left to right. +If you are reading any value that is present in nums1 and nums2 you are +allowed to change your path to the other array. +(Only one repeated value is considered in the valid path). +Score is defined as the sum of uniques values in a valid path. + +Return the maximum score you can obtain of all possible valid paths. + +Since the answer may be too large, return it modulo 10^9 + 7. + +Example 1: + +Input: nums1 = [2,4,5,8,10], nums2 = [4,6,8,9] +Output: 30 +Explanation: Valid paths: +[2,4,5,8,10], [2,4,5,8,9], [2,4,6,8,9], [2,4,6,8,10], (starting from nums1) +[4,6,8,9], [4,5,8,10], [4,5,8,9], [4,6,8,10] (starting from nums2) +The maximum is obtained with the path in green [2,4,6,8,10]. + +Example 2: + +Input: nums1 = [1,3,5,7,9], nums2 = [3,5,100] +Output: 109 +Explanation: Maximum sum is obtained with the path [1,3,5,100]. +Example 3: + +Input: nums1 = [1,2,3,4,5], nums2 = [6,7,8,9,10] +Output: 40 +Explanation: There are no common elements between nums1 and nums2. +Maximum sum is obtained with the path [6,7,8,9,10]. +Example 4: + +Input: nums1 = [1,4,5,8,9,11,19], nums2 = [2,3,4,11,12] +Output: 61 + + +Constraints: + +1 <= nums1.length <= 10^5 +1 <= nums2.length <= 10^5 +1 <= nums1[i], nums2[i] <= 10^7 +nums1 and nums2 are strictly increasing. + +*/ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +const maxSum = function(nums1, nums2) { + let i = 0, j = 0, n = nums1.length, m = nums2.length; + let a = 0, b = 0, mod = 10 ** 9 + 7; + while (i < n || j < m) { + if (i < n && (j === m || nums1[i] < nums2[j])) { + a += nums1[i++]; + } else if (j < m && (i === n || nums1[i] > nums2[j])) { + b += nums2[j++]; + } else { + a = b = Math.max(a, b) + nums1[i]; + i++; j++; + } + } + return Math.max(a, b) % mod; +}; + diff --git a/1539-kth-missing-positive-number.js b/1539.kth-missing-positive-number.js similarity index 100% rename from 1539-kth-missing-positive-number.js rename to 1539.kth-missing-positive-number.js diff --git a/154-find-minimum-in-rotated-sorted-array-ii.js b/154-find-minimum-in-rotated-sorted-array-ii.js deleted file mode 100644 index 1ed12103..00000000 --- a/154-find-minimum-in-rotated-sorted-array-ii.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const findMin = function(nums) { - for(let i = 1, len = nums.length; i < len; i++) { - if(nums[i] < nums[i - 1]) { - return nums[i] - } - } - return nums[0] -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const findMin = function(nums) { - let lo = 0, - hi = nums.length - 1 - while (lo < hi) { - let mid = Math.floor(lo + (hi - lo) / 2) - if (nums[mid] > nums[hi]) lo = mid + 1 - else if (nums[mid] < nums[hi]) hi = mid - else hi-- - } - return nums[lo] -} diff --git a/154.find-minimum-in-rotated-sorted-array-ii.js b/154.find-minimum-in-rotated-sorted-array-ii.js new file mode 100644 index 00000000..51bbde05 --- /dev/null +++ b/154.find-minimum-in-rotated-sorted-array-ii.js @@ -0,0 +1,13 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const findMin = function(nums) { + for(let i = 1, len = nums.length; i < len; i++) { + if(nums[i] < nums[i - 1]) { + return nums[i] + } + } + return nums[0] +}; + diff --git a/1540-can-convert-string-in-k-moves.js b/1540.can-convert-string-in-k-moves.js similarity index 100% rename from 1540-can-convert-string-in-k-moves.js rename to 1540.can-convert-string-in-k-moves.js diff --git a/1541-minimum-insertions-to-balance-a-parentheses-string.js b/1541-minimum-insertions-to-balance-a-parentheses-string.js deleted file mode 100644 index f9f78d74..00000000 --- a/1541-minimum-insertions-to-balance-a-parentheses-string.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const minInsertions = function(s) { - let insert = 0, idx = 0, open = 0, len = s.length - while(idx < len) { - const ch = s[idx] - if(ch === '(') { - open++ - idx++ - } else { - if(open > 0) { - open-- - } else { - insert++ - } - if(idx < len - 1 && s[idx + 1] === ')') { - idx += 2 - } else { - insert++ - idx++ - } - } - } - if(open) insert += open * 2 - return insert -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const minInsertions = function(s) { - let res = 0, right = 0; - for (let i = 0; i < s.length; ++i) { - if (s.charAt(i) == '(') { - if (right % 2 > 0) { - right--; - res++; - } - right += 2; - } else { - right--; - if (right < 0) { - right += 2; - res++; - } - } - } - return right + res; -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const minInsertions = function(s) { - let add = 0, req = 0 // number of parentheses added, number of closing parentheses required - for(let ch of s) { - if(ch === '(') { - req += 2 - if(req % 2 === 1) { - add++ - req-- - } - } else { - if(req === 0) { - add++ - req++ - }else { - req-- - } - } - } - - return add + req -}; - diff --git a/1541.minimum-insertions-to-balance-a-parentheses-string.js b/1541.minimum-insertions-to-balance-a-parentheses-string.js new file mode 100644 index 00000000..f463a40d --- /dev/null +++ b/1541.minimum-insertions-to-balance-a-parentheses-string.js @@ -0,0 +1,29 @@ +/** + * @param {string} s + * @return {number} + */ +const minInsertions = function(s) { + let insert = 0, idx = 0, open = 0, len = s.length + while(idx < len) { + const ch = s[idx] + if(ch === '(') { + open++ + idx++ + } else { + if(open > 0) { + open-- + } else { + insert++ + } + if(idx < len - 1 && s[idx + 1] === ')') { + idx += 2 + } else { + insert++ + idx++ + } + } + } + if(open) insert += open * 2 + return insert +}; + diff --git a/1542-find-longest-awesome-substring.js b/1542-find-longest-awesome-substring.js deleted file mode 100644 index aaa37653..00000000 --- a/1542-find-longest-awesome-substring.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const longestAwesome = function (s) { - const dp = new Array(1024).fill(s.length) - let res = 0, - mask = 0 - dp[0] = -1 - for (let i = 0; i < s.length; ++i) { - mask ^= 1 << +s.charAt(i) - res = Math.max(res, i - dp[mask]) - for (let j = 0; j <= 9; ++j) res = Math.max(res, i - dp[mask ^ (1 << j)]) - dp[mask] = Math.min(dp[mask], i) - } - return res -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const longestAwesome = function(s) { - const n = s.length, { max, min } = Math - const dp = Array(2 ** 10).fill(n) - let res = 0, mask = 0 - dp[0] = -1 - for(let i = 0; i < n; i++) { - mask ^= (1 << parseInt(s[i])) - res = max(res, i - dp[mask]) - for(let j = 0; j <= 9; j++) { - const tmp = mask ^ (1 << j) - res = max(res, i - dp[tmp]) - } - dp[mask] = min(i, dp[mask]) - } - - return res -}; diff --git a/1542.find-longest-awesome-substring.js b/1542.find-longest-awesome-substring.js new file mode 100644 index 00000000..9a2919df --- /dev/null +++ b/1542.find-longest-awesome-substring.js @@ -0,0 +1,18 @@ +/** + * @param {string} s + * @return {number} + */ +const longestAwesome = function (s) { + const dp = new Array(1024).fill(s.length) + let res = 0, + mask = 0 + dp[0] = -1 + for (let i = 0; i < s.length; ++i) { + mask ^= 1 << +s.charAt(i) + res = Math.max(res, i - dp[mask]) + for (let j = 0; j <= 9; ++j) res = Math.max(res, i - dp[mask ^ (1 << j)]) + dp[mask] = Math.min(dp[mask], i) + } + return res +} + diff --git a/1546-maximum-number-of-non-overlapping-subarrays-with-sum-equals-target.js b/1546.maximum-number-of-non-overlapping-subarrays-with-sum-equals-target.js similarity index 100% rename from 1546-maximum-number-of-non-overlapping-subarrays-with-sum-equals-target.js rename to 1546.maximum-number-of-non-overlapping-subarrays-with-sum-equals-target.js diff --git a/1547-minimum-cost-to-cut-a-stick.js b/1547-minimum-cost-to-cut-a-stick.js deleted file mode 100644 index 637bb477..00000000 --- a/1547-minimum-cost-to-cut-a-stick.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @param {number} n - * @param {number[]} cuts - * @return {number} - */ -const minCost = function(n, cuts) { - const x = 100 + 2 - const dp = Array.from({ length: x }, () => Array(x).fill(0)) - cuts.push(0, n) - cuts.sort((a, b) => a - b) - const res = dfs(0, cuts.length - 1) - return res - function dfs(i, j) { - if(j - i <= 1) return 0 - if(!dp[i][j]) { - dp[i][j] = Number.MAX_VALUE - for(let k = i + 1; k < j; k++) { - dp[i][j] = Math.min(dp[i][j], cuts[j] - cuts[i] + dfs(i, k) + dfs(k, j)) - } - } - return dp[i][j] - } -}; - -// another - -/** - * @param {number} n - * @param {number[]} cuts - * @return {number} - */ -const minCost = function (n, cuts) { - cuts.push(0, n) - cuts.sort((a, b) => a - b) - const N = cuts.length, - dp = Array.from({ length: N }, () => Array(N).fill(Infinity)) - for(let i = 1; i < N; i++) dp[i - 1][i] = 0 - for(let i = 2; i < N; i++) dp[i - 2][i] = cuts[i] - cuts[i - 2] - for (let l = 4; l <= N; l++) { - for (let i = 0; i <= N - l; i++) { - const j = i + l - 1 - for (let k = i + 1; k < j; k++) { - dp[i][j] = Math.min(dp[i][j], cuts[j] - cuts[i] + dp[i][k] + dp[k][j]) - } - } - } - return dp[0][N - 1] -} diff --git a/1547.minimum-cost-to-cut-a-stick.js b/1547.minimum-cost-to-cut-a-stick.js new file mode 100644 index 00000000..5d2aa66a --- /dev/null +++ b/1547.minimum-cost-to-cut-a-stick.js @@ -0,0 +1,24 @@ +/** + * @param {number} n + * @param {number[]} cuts + * @return {number} + */ +const minCost = function(n, cuts) { + const x = 100 + 2 + const dp = Array.from({ length: x }, () => Array(x).fill(0)) + cuts.push(0, n) + cuts.sort((a, b) => a - b) + const res = dfs(0, cuts.length - 1) + return res + function dfs(i, j) { + if(j - i <= 1) return 0 + if(!dp[i][j]) { + dp[i][j] = Number.MAX_VALUE + for(let k = i + 1; k < j; k++) { + dp[i][j] = Math.min(dp[i][j], cuts[j] - cuts[i] + dfs(i, k) + dfs(k, j)) + } + } + return dp[i][j] + } +}; + diff --git a/155-min-stack.js b/155.min-stack.js similarity index 100% rename from 155-min-stack.js rename to 155.min-stack.js diff --git a/1550-three-consecutive-odds.js b/1550.three-consecutive-odds.js similarity index 100% rename from 1550-three-consecutive-odds.js rename to 1550.three-consecutive-odds.js diff --git a/1551-minimum-operations-to-make-array-equal.js b/1551.minimum-operations-to-make-array-equal.js similarity index 100% rename from 1551-minimum-operations-to-make-array-equal.js rename to 1551.minimum-operations-to-make-array-equal.js diff --git a/1552-magnetic-force-between-two-balls.js b/1552.magnetic-force-between-two-balls.js similarity index 100% rename from 1552-magnetic-force-between-two-balls.js rename to 1552.magnetic-force-between-two-balls.js diff --git a/1553-minimum-number-of-days-to-eat-n-oranges.js b/1553.minimum-number-of-days-to-eat-n-oranges.js similarity index 100% rename from 1553-minimum-number-of-days-to-eat-n-oranges.js rename to 1553.minimum-number-of-days-to-eat-n-oranges.js diff --git a/1554-strings-differ-by-one-character.js b/1554-strings-differ-by-one-character.js deleted file mode 100644 index 642d2ad0..00000000 --- a/1554-strings-differ-by-one-character.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @param {string[]} dict - * @return {boolean} - */ - const differByOne = function(dict) { - const n = dict.length, m = dict[0].length - for (let j = 0; j < m; j++) { - const seen = new Set() - for(let i = 0; i < n; i++) { - const newStr = dict[i].slice(0, j) + '*' + dict[i].slice(j + 1) - if(seen.has(newStr)) return true - seen.add(newStr) - } - } - - return false -}; - -// another - -/** - * @param {string[]} dict - * @return {boolean} - */ -const differByOne = function (dict) { - const M = dict.length, - N = dict[0].length, - hash = Array(M).fill(0), - ord = (c) => c.charCodeAt(0), - MOD = 1e13, seen = new Set(), - zPlusOne = 'z'.charCodeAt(0) - // 1. generate each i-th rolling hash - for (let i = 0; i < M; ++i) { - let base = 1 - for (let j = 0; j < N; ++j) { - hash[i] = (hash[i] + base * ord(dict[i][j])) % MOD - base = (zPlusOne * base) % MOD - } - } - // 2. remove each j-th char from each i-th rolling hash to find a diff collision - for (let i = 0; i < M; ++i) { - let base = 1 - for (let j = 0; j < N; ++j) { - const diff = (hash[i] - base * ord(dict[i][j])) % MOD - if (seen.has(diff)) return true - seen.add(diff) - base = (zPlusOne * base) % MOD - } - } - return false -} - diff --git a/1554.strings-differ-by-one-character.js b/1554.strings-differ-by-one-character.js new file mode 100644 index 00000000..b72011bb --- /dev/null +++ b/1554.strings-differ-by-one-character.js @@ -0,0 +1,18 @@ +/** + * @param {string[]} dict + * @return {boolean} + */ + const differByOne = function(dict) { + const n = dict.length, m = dict[0].length + for (let j = 0; j < m; j++) { + const seen = new Set() + for(let i = 0; i < n; i++) { + const newStr = dict[i].slice(0, j) + '*' + dict[i].slice(j + 1) + if(seen.has(newStr)) return true + seen.add(newStr) + } + } + + return false +}; + diff --git a/1557-minimum-number-of-vertices-to-reach-all-nodes.js b/1557.minimum-number-of-vertices-to-reach-all-nodes.js similarity index 100% rename from 1557-minimum-number-of-vertices-to-reach-all-nodes.js rename to 1557.minimum-number-of-vertices-to-reach-all-nodes.js diff --git a/1559-detect-cycles-in-2d-grid.js b/1559-detect-cycles-in-2d-grid.js deleted file mode 100644 index a3666072..00000000 --- a/1559-detect-cycles-in-2d-grid.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @param {character[][]} grid - * @return {boolean} - */ -const containsCycle = function (grid) { - const dirs = [ - [1, 0], - [-1, 0], - [0, 1], - [0, -1], - ] - const rows = grid.length - const cols = (grid[0] || []).length - const vis = Array.from({ length: rows }, () => Array(cols).fill(false)) - let res = false - const dfs = (i, j, prevR, prevC, char) => { - vis[i][j] = true - for (let d of dirs) { - const r = i + d[0] - const c = j + d[1] - if (r >= 0 && r < rows && c >= 0 && c < cols) { - if (!(r == prevR && c === prevC)) { - if (grid[r][c] === char) { - if (!vis[r][c]) { - if (dfs(r, c, i, j, char)) return true - } else { - if (prevR !== -1 && prevC !== -1) return true - } - } - } - } - } - return false - } - - for (let i = 0; i < rows; i++) { - for (let j = 0; j < cols; j++) { - if (!vis[i][j]) { - res |= dfs(i, j, -1, -1, grid[i][j]) - } - if (res) return true - } - } - return res -} - -// another - -/** - * @param {character[][]} grid - * @return {boolean} - */ -const containsCycle = function (grid) { - const wholePath = (r, c, letter, component, last = [-1, -1]) => { - const dirs = [ - [0, -1], - [0, 1], - [-1, 0], - [1, 0], - ] - const tmp = grid[r][c] - grid[r][c] = component - const nextSteps = dirs - .map((x) => [x[0] + r, x[1] + c]) - .filter( - (x) => - x[0] >= 0 && x[0] < grid.length && x[1] >= 0 && x[1] < grid[0].length - ) - for (let step of nextSteps) { - if (step[0] === last[0] && last[1] === step[1]) { - continue - } - if (grid[step[0]][step[1]] === component) { - return true - } - if (grid[step[0]][step[1]] === letter) { - let outcome = wholePath(step[0], step[1], letter, component, [r, c]) - if (outcome) { - return true - } - } - } - return false - } - - let component = 1 - for (let r = 0; r < grid.length; r++) { - for (let c = 0; c < grid[0].length; c++) { - const letter = grid[r][c] - if (typeof letter === 'string') { - grid[r][c] = component - const outcome = wholePath(r, c, letter, component) - if (outcome) { - return true - } - component++ - } - } - } - return false -} diff --git a/1559.detect-cycles-in-2d-grid.js b/1559.detect-cycles-in-2d-grid.js new file mode 100644 index 00000000..2dc27adb --- /dev/null +++ b/1559.detect-cycles-in-2d-grid.js @@ -0,0 +1,46 @@ +/** + * @param {character[][]} grid + * @return {boolean} + */ +const containsCycle = function (grid) { + const dirs = [ + [1, 0], + [-1, 0], + [0, 1], + [0, -1], + ] + const rows = grid.length + const cols = (grid[0] || []).length + const vis = Array.from({ length: rows }, () => Array(cols).fill(false)) + let res = false + const dfs = (i, j, prevR, prevC, char) => { + vis[i][j] = true + for (let d of dirs) { + const r = i + d[0] + const c = j + d[1] + if (r >= 0 && r < rows && c >= 0 && c < cols) { + if (!(r == prevR && c === prevC)) { + if (grid[r][c] === char) { + if (!vis[r][c]) { + if (dfs(r, c, i, j, char)) return true + } else { + if (prevR !== -1 && prevC !== -1) return true + } + } + } + } + } + return false + } + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (!vis[i][j]) { + res |= dfs(i, j, -1, -1, grid[i][j]) + } + if (res) return true + } + } + return res +} + diff --git a/156-binary-tree-upside-down.js b/156-binary-tree-upside-down.js deleted file mode 100644 index f5e6e354..00000000 --- a/156-binary-tree-upside-down.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode} - */ -const upsideDownBinaryTree = function(root) { - let node = root, parent = null, right = null - while(node !== null) { - const left = node.left - node.left = right - right = node.right - node.right = parent - parent = node - node = left - } - return parent -}; - -// another - -const upsideDownBinaryTree = function(root) { - if (root == null || root.left == null) { - return root - } - const newRoot = upsideDownBinaryTree(root.left) - root.left.left = root.right - root.left.right = root - root.left = null - root.right = null - return newRoot -} diff --git a/156.binary-tree-upside-down.js b/156.binary-tree-upside-down.js new file mode 100644 index 00000000..b7ed095e --- /dev/null +++ b/156.binary-tree-upside-down.js @@ -0,0 +1,24 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {TreeNode} + */ +const upsideDownBinaryTree = function(root) { + let node = root, parent = null, right = null + while(node !== null) { + const left = node.left + node.left = right + right = node.right + node.right = parent + parent = node + node = left + } + return parent +}; + diff --git a/1560-most-visited-sector-in-a-circular-track.js b/1560.most-visited-sector-in-a-circular-track.js similarity index 100% rename from 1560-most-visited-sector-in-a-circular-track.js rename to 1560.most-visited-sector-in-a-circular-track.js diff --git a/1561-maximum-number-of-coins-you-can-get.js b/1561.maximum-number-of-coins-you-can-get.js similarity index 100% rename from 1561-maximum-number-of-coins-you-can-get.js rename to 1561.maximum-number-of-coins-you-can-get.js diff --git a/1562-find-latest-group-of-size-m.js b/1562.find-latest-group-of-size-m.js similarity index 100% rename from 1562-find-latest-group-of-size-m.js rename to 1562.find-latest-group-of-size-m.js diff --git a/1564-put-boxes-into-the-warehouse-i.js b/1564-put-boxes-into-the-warehouse-i.js deleted file mode 100644 index cf4ca8e3..00000000 --- a/1564-put-boxes-into-the-warehouse-i.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @param {number[]} boxes - * @param {number[]} warehouse - * @return {number} - */ -const maxBoxesInWarehouse = function(boxes, warehouse) { - boxes.sort((a, b) => a - b) - const m = boxes.length, n = warehouse.length - let i = 0, j = 0 - for(; i < m && j < n; i++) { - if(boxes[m - i - 1] <= warehouse[j]) { - j++ - } - if(j === n) return n - } - return j -}; - -// another - -/** - * @param {number[]} boxes - * @param {number[]} warehouse - * @return {number} - */ -const maxBoxesInWarehouse = function(boxes, warehouse) { - if(warehouse == null || warehouse.length === 0) return 0 - const m = boxes.length, n = warehouse.length - for(let i = 1; i < n; i++) { - warehouse[i] = Math.min(warehouse[i], warehouse[i - 1]) - } - boxes.sort((a, b) => a - b) - let res = 0 - for(let i = n - 1; i >= 0; i--) { - if(res < m && boxes[res] <= warehouse[i]) res++ - } - return res -}; - -// another - -/** - * @param {number[]} boxes - * @param {number[]} warehouse - * @return {number} - */ -const maxBoxesInWarehouse = function(boxes, warehouse) { - if(warehouse == null || warehouse.length === 0) return 0 - const m = boxes.length, n = warehouse.length - boxes.sort((a, b) => a - b) - let i = m - 1, res = 0 - for(let house of warehouse) { - while(i >= 0 && boxes[i] > house) i-- - if(i === -1) return res - res++ - i-- - } - return res -}; diff --git a/1564.put-boxes-into-the-warehouse-i.js b/1564.put-boxes-into-the-warehouse-i.js new file mode 100644 index 00000000..1eaa3052 --- /dev/null +++ b/1564.put-boxes-into-the-warehouse-i.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} boxes + * @param {number[]} warehouse + * @return {number} + */ +const maxBoxesInWarehouse = function(boxes, warehouse) { + boxes.sort((a, b) => a - b) + const m = boxes.length, n = warehouse.length + let i = 0, j = 0 + for(; i < m && j < n; i++) { + if(boxes[m - i - 1] <= warehouse[j]) { + j++ + } + if(j === n) return n + } + return j +}; + diff --git a/1567-maximum-length-of-subarray-with-positive-product.js b/1567.maximum-length-of-subarray-with-positive-product.js similarity index 100% rename from 1567-maximum-length-of-subarray-with-positive-product.js rename to 1567.maximum-length-of-subarray-with-positive-product.js diff --git a/1568-minimum-number-of-days-to-disconnect-island.js b/1568.minimum-number-of-days-to-disconnect-island.js similarity index 100% rename from 1568-minimum-number-of-days-to-disconnect-island.js rename to 1568.minimum-number-of-days-to-disconnect-island.js diff --git a/1569-number-of-ways-to-reorder-array-to-get-same-bst.js b/1569.number-of-ways-to-reorder-array-to-get-same-bst.js similarity index 100% rename from 1569-number-of-ways-to-reorder-array-to-get-same-bst.js rename to 1569.number-of-ways-to-reorder-array-to-get-same-bst.js diff --git a/157-read-n-characters-given-read4.js b/157.read-n-characters-given-read4.js similarity index 100% rename from 157-read-n-characters-given-read4.js rename to 157.read-n-characters-given-read4.js diff --git a/1570-dot-product-of-two-sparse-vectors.js b/1570-dot-product-of-two-sparse-vectors.js deleted file mode 100644 index 682b656d..00000000 --- a/1570-dot-product-of-two-sparse-vectors.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @param {number[]} nums - * @return {SparseVector} - */ -const SparseVector = function(nums) { - this.seen = {} - nums.forEach((e, i) => { - if(e !== 0) this.seen[i] = e - }) -}; - -// Return the dotProduct of two sparse vectors -/** - * @param {SparseVector} vec - * @return {number} - */ -SparseVector.prototype.dotProduct = function(vec) { - let res = 0 - for(let [k, v] of Object.entries(vec.seen)) { - if(k in this.seen) res += v * this.seen[k] - } - return res -}; - -// Your SparseVector object will be instantiated and called as such: -// let v1 = new SparseVector(nums1); -// let v2 = new SparseVector(nums2); -// let ans = v1.dotProduct(v2); - -// another - -class SparseVector { - /** - * @param {number[]} nums - * @return {SparseVector} - */ - constructor(nums) { - // Space: O(n) - this.seen = new Map() // index -> value - for (let i = 0; i < nums.length; ++i) { - if (nums[i] !== 0) { - this.seen.set(i, nums[i]) - } - } - } - - /** - * Return the dotProduct of two sparse vectors - * @param {SparseVector} vec - * @return {number} - */ - dotProduct(vec) { - // Time: O(n) - let sum = 0 - for (const [i, val] of vec.seen) { - if (this.seen.has(i)) { - sum += val * this.seen.get(i) - } - } - return sum - } -} - -// Your SparseVector object will be instantiated and called as such: -// let v1 = new SparseVector(nums1); -// let v2 = new SparseVector(nums2); -// let ans = v1.dotProduct(v2); diff --git a/1570.dot-product-of-two-sparse-vectors.js b/1570.dot-product-of-two-sparse-vectors.js new file mode 100644 index 00000000..ea47e81b --- /dev/null +++ b/1570.dot-product-of-two-sparse-vectors.js @@ -0,0 +1,29 @@ +/** + * @param {number[]} nums + * @return {SparseVector} + */ +const SparseVector = function(nums) { + this.seen = {} + nums.forEach((e, i) => { + if(e !== 0) this.seen[i] = e + }) +}; + +// Return the dotProduct of two sparse vectors +/** + * @param {SparseVector} vec + * @return {number} + */ +SparseVector.prototype.dotProduct = function(vec) { + let res = 0 + for(let [k, v] of Object.entries(vec.seen)) { + if(k in this.seen) res += v * this.seen[k] + } + return res +}; + +// Your SparseVector object will be instantiated and called as such: +// let v1 = new SparseVector(nums1); +// let v2 = new SparseVector(nums2); +// let ans = v1.dotProduct(v2); + diff --git a/1572-matrix-diagonal-sum.js b/1572.matrix-diagonal-sum.js similarity index 100% rename from 1572-matrix-diagonal-sum.js rename to 1572.matrix-diagonal-sum.js diff --git a/1573-number-of-ways-to-split-a-string.js b/1573.number-of-ways-to-split-a-string.js similarity index 100% rename from 1573-number-of-ways-to-split-a-string.js rename to 1573.number-of-ways-to-split-a-string.js diff --git a/1574-shortest-subarray-to-be-removed-to-make-array-sorted.js b/1574.shortest-subarray-to-be-removed-to-make-array-sorted.js similarity index 100% rename from 1574-shortest-subarray-to-be-removed-to-make-array-sorted.js rename to 1574.shortest-subarray-to-be-removed-to-make-array-sorted.js diff --git a/1575-count-all-possible-routes.js b/1575.count-all-possible-routes.js similarity index 100% rename from 1575-count-all-possible-routes.js rename to 1575.count-all-possible-routes.js diff --git a/1576-replace-all-s-to-avoid-consecutive-repeating-characters.js b/1576-replace-all-s-to-avoid-consecutive-repeating-characters.js deleted file mode 100644 index 51a743c9..00000000 --- a/1576-replace-all-s-to-avoid-consecutive-repeating-characters.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ -const modifyString = function(s) { - const arr = s.split('') - for(let i = 0, n = s.length; i < n; i++) { - const cur = arr[i] - if(cur === '?') { - for(let j = 0, a = 'a'.charCodeAt(0); j < 26; j++) { - const ch = String.fromCharCode(a + j) - if( - n === 1 || - (i === 0 && i < n - 1 && ch !== arr[i + 1]) || - (i > 0 && ch !== arr[i - 1] && i < n - 1 && ch !== arr[i + 1]) || - (i=== n -1 && i - 1 >= 0 && ch !== arr[i - 1]) - ) { - - arr[i] = ch - break - } - } - } - } - - return arr.join('') -}; - - -// another - -/** - * @param {string} s - * @return {string} - */ -const modifyString = function(s) { - const arr = s.split('') - for(let i = 0, n = s.length; i < n; i++) { - const cur = arr[i] - if(cur === '?') { - for(let j = 0, a = 'a'.charCodeAt(0); j < 26; j++) { - const ch = String.fromCharCode(a + j) - if( - (i === 0 || arr[i - 1] !== ch) && - (i === n - 1 || arr[i + 1] !== ch) - ) { - - arr[i] = ch - break - } - } - } - } - - return arr.join('') -}; diff --git a/1576.replace-all-s-to-avoid-consecutive-repeating-characters.js b/1576.replace-all-s-to-avoid-consecutive-repeating-characters.js new file mode 100644 index 00000000..eb9b799f --- /dev/null +++ b/1576.replace-all-s-to-avoid-consecutive-repeating-characters.js @@ -0,0 +1,29 @@ +/** + * @param {string} s + * @return {string} + */ +const modifyString = function(s) { + const arr = s.split('') + for(let i = 0, n = s.length; i < n; i++) { + const cur = arr[i] + if(cur === '?') { + for(let j = 0, a = 'a'.charCodeAt(0); j < 26; j++) { + const ch = String.fromCharCode(a + j) + if( + n === 1 || + (i === 0 && i < n - 1 && ch !== arr[i + 1]) || + (i > 0 && ch !== arr[i - 1] && i < n - 1 && ch !== arr[i + 1]) || + (i=== n -1 && i - 1 >= 0 && ch !== arr[i - 1]) + ) { + + arr[i] = ch + break + } + } + } + } + + return arr.join('') +}; + + diff --git a/1578-minimum-deletion-cost-to-avoid-repeating-letters.js b/1578.minimum-deletion-cost-to-avoid-repeating-letters.js similarity index 100% rename from 1578-minimum-deletion-cost-to-avoid-repeating-letters.js rename to 1578.minimum-deletion-cost-to-avoid-repeating-letters.js diff --git a/1579-remove-max-number-of-edges-to-keep-graph-fully-traversable.js b/1579.remove-max-number-of-edges-to-keep-graph-fully-traversable.js similarity index 100% rename from 1579-remove-max-number-of-edges-to-keep-graph-fully-traversable.js rename to 1579.remove-max-number-of-edges-to-keep-graph-fully-traversable.js diff --git a/158-read-n-characters-given-read4-ii-call-multiple-times.js b/158.read-n-characters-given-read4-ii-call-multiple-times.js similarity index 100% rename from 158-read-n-characters-given-read4-ii-call-multiple-times.js rename to 158.read-n-characters-given-read4-ii-call-multiple-times.js diff --git a/1584-min-cost-to-connect-all-points.js b/1584.min-cost-to-connect-all-points.js similarity index 100% rename from 1584-min-cost-to-connect-all-points.js rename to 1584.min-cost-to-connect-all-points.js diff --git a/1585-check-if-string-is-transformable-with-substring-sort-operations.js b/1585.check-if-string-is-transformable-with-substring-sort-operations.js similarity index 100% rename from 1585-check-if-string-is-transformable-with-substring-sort-operations.js rename to 1585.check-if-string-is-transformable-with-substring-sort-operations.js diff --git a/1586-binary-search-tree-iterator-ii.js b/1586-binary-search-tree-iterator-ii.js deleted file mode 100644 index 305d57e3..00000000 --- a/1586-binary-search-tree-iterator-ii.js +++ /dev/null @@ -1,140 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - */ -const BSTIterator = function(root) { - this.r = root - const ans = [] - helper(root, ans) - this.arr = ans - this.cur = -1 -}; - -/** - * @return {boolean} - */ -BSTIterator.prototype.hasNext = function() { - return this.arr.length && this.cur < this.arr.length - 1 -}; - -/** - * @return {number} - */ -BSTIterator.prototype.next = function() { - this.cur += 1 - return this.arr[this.cur] -}; - -/** - * @return {boolean} - */ -BSTIterator.prototype.hasPrev = function() { - return this.arr.length && this.cur > 0 -}; - -/** - * @return {number} - */ -BSTIterator.prototype.prev = function() { - return this.arr[--this.cur] -}; - -function helper(node, res) { - if(node == null) return - if(node.left) { - helper(node.left, res) - } - res.push(node.val) - if(node.right) { - helper(node.right, res) - } -} - -/** - * Your BSTIterator object will be instantiated and called as such: - * var obj = new BSTIterator(root) - * var param_1 = obj.hasNext() - * var param_2 = obj.next() - * var param_3 = obj.hasPrev() - * var param_4 = obj.prev() - */ - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - */ -const BSTIterator = function (root) { - this.nums = [] - this.stack = [] - this.node = root - this.i = 0 // pointer to next node - this.size = 0 -} - -/** - * @return {boolean} - */ -BSTIterator.prototype.hasNext = function () { - return this.i < this.size || this.stack.length > 0 || !!this.node -} - -/** - * @return {number} - */ -BSTIterator.prototype.next = function () { - if (this.i < this.size) return this.nums[this.i++] - if (this.stack.length || this.node) { - while (this.node) { - this.stack.push(this.node) - this.node = this.node.left - } - this.node = this.stack.pop() - this.i += 1 - this.size += 1 - const val = this.node.val - this.nums.push(val) - this.node = this.node.right - return val - } - return -1 -} - -/** - * @return {boolean} - */ -BSTIterator.prototype.hasPrev = function () { - return this.i - 2 >= 0 -} - -/** - * @return {number} - */ -BSTIterator.prototype.prev = function () { - return this.nums[--this.i - 1] -} - -/** - * Your BSTIterator object will be instantiated and called as such: - * var obj = new BSTIterator(root) - * var param_1 = obj.hasNext() - * var param_2 = obj.next() - * var param_3 = obj.hasPrev() - * var param_4 = obj.prev() - */ - diff --git a/1586.binary-search-tree-iterator-ii.js b/1586.binary-search-tree-iterator-ii.js new file mode 100644 index 00000000..d2e661f2 --- /dev/null +++ b/1586.binary-search-tree-iterator-ii.js @@ -0,0 +1,68 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + */ +const BSTIterator = function(root) { + this.r = root + const ans = [] + helper(root, ans) + this.arr = ans + this.cur = -1 +}; + +/** + * @return {boolean} + */ +BSTIterator.prototype.hasNext = function() { + return this.arr.length && this.cur < this.arr.length - 1 +}; + +/** + * @return {number} + */ +BSTIterator.prototype.next = function() { + this.cur += 1 + return this.arr[this.cur] +}; + +/** + * @return {boolean} + */ +BSTIterator.prototype.hasPrev = function() { + return this.arr.length && this.cur > 0 +}; + +/** + * @return {number} + */ +BSTIterator.prototype.prev = function() { + return this.arr[--this.cur] +}; + +function helper(node, res) { + if(node == null) return + if(node.left) { + helper(node.left, res) + } + res.push(node.val) + if(node.right) { + helper(node.right, res) + } +} + +/** + * Your BSTIterator object will be instantiated and called as such: + * var obj = new BSTIterator(root) + * var param_1 = obj.hasNext() + * var param_2 = obj.next() + * var param_3 = obj.hasPrev() + * var param_4 = obj.prev() + */ + diff --git a/1588-sum-of-all-odd-length-subarrays.js b/1588.sum-of-all-odd-length-subarrays.js similarity index 100% rename from 1588-sum-of-all-odd-length-subarrays.js rename to 1588.sum-of-all-odd-length-subarrays.js diff --git a/1589-maximum-sum-obtained-of-any-permutation.js b/1589-maximum-sum-obtained-of-any-permutation.js deleted file mode 100644 index 54b7f955..00000000 --- a/1589-maximum-sum-obtained-of-any-permutation.js +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @param {number[]} nums - * @param {number[][]} requests - * @return {number} - */ -const maxSumRangeQuery = function (nums, requests) { - let res = 0 - const mod = 10 ** 9 + 7, - n = nums.length - const count = Array(n).fill(0) - for (let r of requests) { - count[r[0]] += 1 - if (r[1] + 1 < n) count[r[1] + 1] -= 1 - } - for (let i = 1; i < n; i++) count[i] += count[i - 1] - nums.sort((a, b) => a - b) - count.sort((a, b) => a - b) - for (let i = 0; i < n; ++i) res = (res + nums[i] * count[i]) % mod - return res -} - -// another - -/** - * @param {number[]} nums - * @param {number[][]} requests - * @return {number} - */ -const maxSumRangeQuery = function (nums, requests) { - const n = nums.length, arr = Array(n + 1).fill(0) - for(let [s, e] of requests) { - arr[s] += 1 - arr[e + 1] -= 1 - } - for(let i = 0, cur = 0; i < n; i++) { - cur += arr[i] - arr[i] = cur - } - nums.sort((a, b) => b - a) - arr.sort((a, b) => b - a) - const mod = 1e9 + 7 - let res = 0 - for(let i = 0; i < n; i++) { - if (arr[i] <= 0) break - res = (res + nums[i] * arr[i]) % mod - } - return res -} - -// another - -/** - * @param {number[]} nums - * @param {number[][]} requests - * @return {number} - */ -const maxSumRangeQuery = function (nums, requests) { - const n = nums.length - - const arr = Array(n + 1).fill(0) - for(const [s, e] of requests) { - arr[s] += 1 - arr[e + 1] -= 1 - } - for(let i = 1; i <= n; i++) { - arr[i] += arr[i - 1] - } - arr.sort((a, b) => b - a) - nums.sort((a, b) => b - a) - let res = 0 - const mod = 1e9 + 7 - - for (let i = 0; i < n; i++) { - if(arr[i] <= 0) break - res = (res + nums[i] * arr[i]) % mod - } - - return res -} diff --git a/1589.maximum-sum-obtained-of-any-permutation.js b/1589.maximum-sum-obtained-of-any-permutation.js new file mode 100644 index 00000000..997c5a90 --- /dev/null +++ b/1589.maximum-sum-obtained-of-any-permutation.js @@ -0,0 +1,21 @@ +/** + * @param {number[]} nums + * @param {number[][]} requests + * @return {number} + */ +const maxSumRangeQuery = function (nums, requests) { + let res = 0 + const mod = 10 ** 9 + 7, + n = nums.length + const count = Array(n).fill(0) + for (let r of requests) { + count[r[0]] += 1 + if (r[1] + 1 < n) count[r[1] + 1] -= 1 + } + for (let i = 1; i < n; i++) count[i] += count[i - 1] + nums.sort((a, b) => a - b) + count.sort((a, b) => a - b) + for (let i = 0; i < n; ++i) res = (res + nums[i] * count[i]) % mod + return res +} + diff --git a/159-longest-substring-with-at-most-two-distinct-characters.js b/159.longest-substring-with-at-most-two-distinct-characters.js similarity index 100% rename from 159-longest-substring-with-at-most-two-distinct-characters.js rename to 159.longest-substring-with-at-most-two-distinct-characters.js diff --git a/1590-make-sum-divisible-by-p.js b/1590-make-sum-divisible-by-p.js deleted file mode 100644 index 91857ae1..00000000 --- a/1590-make-sum-divisible-by-p.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} p - * @return {number} - */ -const minSubarray = function(nums, p) { - const remain = nums.reduce((ac, e) => ac + e, 0) % p - const n = nums.length, hash = {0: -1} - let res = n - if(remain === 0) return 0 - for(let i = 0, sum = 0; i < n; i++) { - const cur = nums[i] - sum += cur - const target = (sum % p - remain + p) % p - if(hash[target] != null) { - res = Math.min(res, i - hash[target]) - } - - hash[sum % p] = i - } -// console.log(hash) - - return res === n ? -1 : res -}; - -// another - -/** - * @param {number[]} nums - * @param {number} p - * @return {number} - */ -const minSubarray = function(nums, p) { - const diff = nums.reduce((a, b) => a + b, 0) % p; - let res = diff === 0 ? 0 : nums.length; - - for (let i = 0, sum = 0, map = {0: -1}; i < nums.length; i++) { - sum += nums[i]; - const target = (sum % p - diff + p) % p; - if (map[target] !== undefined) { - res = Math.min(res, i - map[target]); - } - map[sum % p] = i; - } - - return res === nums.length ? -1 : res; -}; - -/** - -Let pre[] be the prefix sum array, -then pre[i] is running prefix sum or prefix sum of i elements, -pre[j] is the prefix sum such that pre[i]-pre[j] is the subarray we -need to remove to make pre[n] (sum of all elements) divisible by p - -(pre[n] - (pre[i]-pre[j])) % p = 0 ... (remove a subarray to make pre[n] divisible by p) -=> pre[n] % p = (pre[i]-pre[j]) % p ... ((a-b)%m = a%m - b%m) -=> pre[j]%p = pre[i]%p - pre[n]%p ... (same property used above) -since RHS can be negative we make it positive modulus by adding p and taking modulus -=> pre[j]%p = (pre[i]%p - pre[n]%p + p) % p - -*/ diff --git a/1590.make-sum-divisible-by-p.js b/1590.make-sum-divisible-by-p.js new file mode 100644 index 00000000..d1abc112 --- /dev/null +++ b/1590.make-sum-divisible-by-p.js @@ -0,0 +1,25 @@ +/** + * @param {number[]} nums + * @param {number} p + * @return {number} + */ +const minSubarray = function(nums, p) { + const remain = nums.reduce((ac, e) => ac + e, 0) % p + const n = nums.length, hash = {0: -1} + let res = n + if(remain === 0) return 0 + for(let i = 0, sum = 0; i < n; i++) { + const cur = nums[i] + sum += cur + const target = (sum % p - remain + p) % p + if(hash[target] != null) { + res = Math.min(res, i - hash[target]) + } + + hash[sum % p] = i + } +// console.log(hash) + + return res === n ? -1 : res +}; + diff --git a/1591-strange-printer-ii.js b/1591-strange-printer-ii.js deleted file mode 100644 index 4dd5b521..00000000 --- a/1591-strange-printer-ii.js +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @param {number[][]} targetGrid - * @return {boolean} - */ -const isPrintable = function (targetGrid) { - const posMin = Array.from({ length: 61 }, () => Array(2).fill(61)) - const posMax = Array.from({ length: 61 }, () => Array(2).fill(0)) - const m = targetGrid.length - const n = targetGrid[0].length - let colorSet = new Set() - - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - let c = targetGrid[i][j] - colorSet.add(c) - posMin[c][0] = Math.min(posMin[c][0], i) //Up - posMin[c][1] = Math.min(posMin[c][1], j) //Left - posMax[c][0] = Math.max(posMax[c][0], i) //Down - posMax[c][1] = Math.max(posMax[c][1], j) //Right - } - } - while (colorSet.size) { - const tmp = new Set() - for (let color of colorSet) { - if (!isRect(targetGrid, color)) { - tmp.add(color) - } - } - - if (tmp.size === colorSet.size) return false - colorSet = tmp - } - - return true - - function isRect(A, c) { - for (let i = posMin[c][0]; i <= posMax[c][0]; i++) { - for (let j = posMin[c][1]; j <= posMax[c][1]; j++) { - if (A[i][j] > 0 && A[i][j] !== c) return false - } - } - - for (let i = posMin[c][0]; i <= posMax[c][0]; i++) { - for (let j = posMin[c][1]; j <= posMax[c][1]; j++) { - A[i][j] = 0 - } - } - - return true - } -} - -// another - -/** - * @param {number[][]} targetGrid - * @return {boolean} - */ -const isPrintable = function (targetGrid) { - /* - 1 -> 3 - 1 -> 4 - 1 -> 5 - 3 -> 4 - */ - - const dependencies = {} - - /* - 3: [mini, maxi, minj, maxj] - */ - const extents = {} - - for (let i = 0; i < targetGrid.length; i++) { - for (let j = 0; j < targetGrid[i].length; j++) { - const n = targetGrid[i][j] - let inf = Infinity - extents[n] = extents[n] || { - n, - mini: inf, - minj: inf, - maxi: -inf, - maxj: -inf, - } - extents[n].mini = Math.min(i, extents[n].mini) - extents[n].minj = Math.min(j, extents[n].minj) - extents[n].maxi = Math.max(i, extents[n].maxi) - extents[n].maxj = Math.max(j, extents[n].maxj) - } - } - - function canRemove(obj) { - for (let i = obj.mini; i <= obj.maxi; i++) { - for (let j = obj.minj; j <= obj.maxj; j++) { - const val = targetGrid[i][j] - if (val !== null && val !== obj.n) return false - } - } - return true - } - - function remove(obj) { - for (let i = obj.mini; i <= obj.maxi; i++) { - for (let j = obj.minj; j <= obj.maxj; j++) { - targetGrid[i][j] = null - } - } - delete extents[obj.n] - } - - while (Object.keys(extents).length > 0) { - let found = false - for (const n in extents) { - const obj = extents[n] - if (canRemove(obj)) { - remove(obj) - found = true - break - } - } - if (!found) { - return false - } - } - return true -} - diff --git a/1591.strange-printer-ii.js b/1591.strange-printer-ii.js new file mode 100644 index 00000000..d330114d --- /dev/null +++ b/1591.strange-printer-ii.js @@ -0,0 +1,52 @@ +/** + * @param {number[][]} targetGrid + * @return {boolean} + */ +const isPrintable = function (targetGrid) { + const posMin = Array.from({ length: 61 }, () => Array(2).fill(61)) + const posMax = Array.from({ length: 61 }, () => Array(2).fill(0)) + const m = targetGrid.length + const n = targetGrid[0].length + let colorSet = new Set() + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + let c = targetGrid[i][j] + colorSet.add(c) + posMin[c][0] = Math.min(posMin[c][0], i) //Up + posMin[c][1] = Math.min(posMin[c][1], j) //Left + posMax[c][0] = Math.max(posMax[c][0], i) //Down + posMax[c][1] = Math.max(posMax[c][1], j) //Right + } + } + while (colorSet.size) { + const tmp = new Set() + for (let color of colorSet) { + if (!isRect(targetGrid, color)) { + tmp.add(color) + } + } + + if (tmp.size === colorSet.size) return false + colorSet = tmp + } + + return true + + function isRect(A, c) { + for (let i = posMin[c][0]; i <= posMax[c][0]; i++) { + for (let j = posMin[c][1]; j <= posMax[c][1]; j++) { + if (A[i][j] > 0 && A[i][j] !== c) return false + } + } + + for (let i = posMin[c][0]; i <= posMax[c][0]; i++) { + for (let j = posMin[c][1]; j <= posMax[c][1]; j++) { + A[i][j] = 0 + } + } + + return true + } +} + diff --git a/1592-rearrange-spaces-between-words.js b/1592.rearrange-spaces-between-words.js similarity index 100% rename from 1592-rearrange-spaces-between-words.js rename to 1592.rearrange-spaces-between-words.js diff --git a/1593-split-a-string-into-the-max-number-of-unique-substrings.js b/1593-split-a-string-into-the-max-number-of-unique-substrings.js deleted file mode 100644 index cfd06a65..00000000 --- a/1593-split-a-string-into-the-max-number-of-unique-substrings.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const maxUniqueSplit = function(s) { - return bt(s, '', 0, new Set()) -}; - -function bt(str, cur, idx, useds) { - if(idx === str.length) return useds.size - cur += str[idx] - if(useds.has(cur)) return bt(str, cur, idx +1, useds) - else { - let ans = 0 - useds.add(cur) - ans = Math.max(ans, bt(str, '', idx+1, useds)) - useds.delete(cur) - ans = Math.max(ans, bt(str, cur, idx+1, useds)) - return ans - } -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const maxUniqueSplit = function (s) { - const N = s.length - let ans = -1 - let curr = new Set() - const backtrack = (pos) => { - if (pos === N) { - ans = Math.max(ans, curr.size) - return - } - if (curr.size + (N - pos) <= ans) return - for (let i = pos + 1; i <= N; i++) { - const a = s.slice(pos, i) - if (curr.has(a)) continue - curr.add(a) - backtrack(i) - curr.delete(a) - } - } - - backtrack(0) - return ans -} - diff --git a/1593.split-a-string-into-the-max-number-of-unique-substrings.js b/1593.split-a-string-into-the-max-number-of-unique-substrings.js new file mode 100644 index 00000000..48e93cde --- /dev/null +++ b/1593.split-a-string-into-the-max-number-of-unique-substrings.js @@ -0,0 +1,22 @@ +/** + * @param {string} s + * @return {number} + */ +const maxUniqueSplit = function(s) { + return bt(s, '', 0, new Set()) +}; + +function bt(str, cur, idx, useds) { + if(idx === str.length) return useds.size + cur += str[idx] + if(useds.has(cur)) return bt(str, cur, idx +1, useds) + else { + let ans = 0 + useds.add(cur) + ans = Math.max(ans, bt(str, '', idx+1, useds)) + useds.delete(cur) + ans = Math.max(ans, bt(str, cur, idx+1, useds)) + return ans + } +} + diff --git a/1594-maximum-non-negative-product-in-a-matrix.js b/1594.maximum-non-negative-product-in-a-matrix.js similarity index 100% rename from 1594-maximum-non-negative-product-in-a-matrix.js rename to 1594.maximum-non-negative-product-in-a-matrix.js diff --git a/1595-minimum-cost-to-connect-two-groups-of-points.js b/1595-minimum-cost-to-connect-two-groups-of-points.js deleted file mode 100644 index 43e3d060..00000000 --- a/1595-minimum-cost-to-connect-two-groups-of-points.js +++ /dev/null @@ -1,122 +0,0 @@ -/** - * @param {number[][]} cost - * @return {number} - */ -const connectTwoGroups = function(cost) { - const m = cost.length, n = cost[0].length, { min } = Math - const limit = 1 << n - const dp = Array.from({ length: m + 1 }, () => Array(limit).fill(Infinity)) - const subCost = Array.from({ length: m + 1 }, () => Array(limit).fill(Infinity)) - - for(let i = 0; i < m; i++) { - for(let mask = 0; mask < limit; mask++) { - let sum = 0 - for(let j = 0; j < n; j++) { - if((mask >> j) & 1) { - sum += cost[i][j] - } - } - - subCost[i][mask] = sum - } - } - - dp[0][0] = 0 - for(let i = 1; i <= m; i++) { - for(let mask = 0; mask < limit; mask++) { - for(let sub = mask; sub; sub = (sub - 1) & mask) { - dp[i][mask] = min( - dp[i][mask], - dp[i - 1][mask - sub] + subCost[i - 1][sub] - ) - } - let tmp = Infinity - for(let j = 0; j < n; j++) { - tmp = min(tmp, cost[i - 1][j]) - } - - dp[i][mask] = min(dp[i][mask], dp[i - 1][mask] + tmp) - } - } - // console.log(dp) - return dp[m][limit - 1] -}; - -// another - - -/** - * @param {number[][]} cost - * @return {number} - */ -const connectTwoGroups = function (cost) { - const min = Array(cost[0].length).fill(Infinity) - for (let j = 0; j < min.length; j++) { - for (let i = 0; i < cost.length; i++) { - min[j] = Math.min(min[j], cost[i][j]) - } - } - const dp = Array.from({ length: 13 }, () => Array(4096).fill(-1)) - return dfs(cost, min, 0, 0, dp) -} - -function dfs(cost, min, i, mask, dp) { - if (dp[i][mask] !== -1) return dp[i][mask] - let res = i >= cost.length ? 0 : Infinity - if (i >= cost.length) { - for (let j = 0; j < cost[0].length; j++) { - if ((mask & (1 << j)) === 0) res += min[j] - } - } else { - for (let j = 0; j < cost[0].length; j++) { - res = Math.min( - res, - cost[i][j] + dfs(cost, min, i + 1, mask | (1 << j), dp) - ) - } - } - dp[i][mask] = res - return res -} - -// another - -/** - * @param {number[][]} cost - * @return {number} - */ -const connectTwoGroups = function (cost) { - const n = cost.length - const m = cost[0].length - const con = 1 << m - const dp = Array(n + 1) - .fill(null) - .map(() => Array(con).fill(0)) - const min = Array(m).fill(Infinity) - for (let i = 0; i < n; i++) { - for (let j = 0; j < m; j++) { - min[j] = Math.min(min[j], cost[i][j]) - } - } - function dfs(i, mask) { - let res - if (dp[i][mask]) { - return dp[i][mask] - } else if (i >= n) { - res = 0 - for (let j = 0; j < m; j++) { - const binaryJ = 1 << j - if ((mask & binaryJ) === 0) res += min[j] - } - } else { - res = Infinity - for (let j = 0; j < m; j++) { - const binaryJ = 1 << j - res = Math.min(res, cost[i][j] + dfs(i + 1, mask | binaryJ)) - } - } - dp[i][mask] = res - return res - } - return dfs(0, 0) -} diff --git a/1595.minimum-cost-to-connect-two-groups-of-points.js b/1595.minimum-cost-to-connect-two-groups-of-points.js new file mode 100644 index 00000000..9d606d6f --- /dev/null +++ b/1595.minimum-cost-to-connect-two-groups-of-points.js @@ -0,0 +1,44 @@ +/** + * @param {number[][]} cost + * @return {number} + */ +const connectTwoGroups = function(cost) { + const m = cost.length, n = cost[0].length, { min } = Math + const limit = 1 << n + const dp = Array.from({ length: m + 1 }, () => Array(limit).fill(Infinity)) + const subCost = Array.from({ length: m + 1 }, () => Array(limit).fill(Infinity)) + + for(let i = 0; i < m; i++) { + for(let mask = 0; mask < limit; mask++) { + let sum = 0 + for(let j = 0; j < n; j++) { + if((mask >> j) & 1) { + sum += cost[i][j] + } + } + + subCost[i][mask] = sum + } + } + + dp[0][0] = 0 + for(let i = 1; i <= m; i++) { + for(let mask = 0; mask < limit; mask++) { + for(let sub = mask; sub; sub = (sub - 1) & mask) { + dp[i][mask] = min( + dp[i][mask], + dp[i - 1][mask - sub] + subCost[i - 1][sub] + ) + } + let tmp = Infinity + for(let j = 0; j < n; j++) { + tmp = min(tmp, cost[i - 1][j]) + } + + dp[i][mask] = min(dp[i][mask], dp[i - 1][mask] + tmp) + } + } + // console.log(dp) + return dp[m][limit - 1] +}; + diff --git a/1597-build-binary-expression-tree-from-infix-expression.js b/1597-build-binary-expression-tree-from-infix-expression.js deleted file mode 100644 index 5678858f..00000000 --- a/1597-build-binary-expression-tree-from-infix-expression.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Definition for a binary tree node. - * function Node(val, left, right) { - * this.val = (val===undefined ? " " : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {string} s - * @return {Node} - */ -const expTree = function (s) { - const n = s.length - const head = new Node() - let i = 0 - const number = () => { - let num = '' - while (i < n && '0' <= s[i]) { - num += s[i++] - } - return new Node(Number(num)) - } - const factor = () => { - if (s[i] === '(') { - i++ - const node = expression() - i++ - return node - } - return number() - } - const term = () => { - let left = factor() - while (i < n && (s[i] === '*' || s[i] === '/')) { - const op = new Node(s[i++]) - const right = factor() - op.left = left - op.right = right - left = op - } - return left - } - const expression = () => { - let left = term() - while (i < s.length && (s[i] === '+' || s[i] === '-')) { - const op = new Node(s[i++]) - const right = term() - op.left = left - op.right = right - left = op - } - return left - } - return expression() -} - - -// another - -/** - * Definition for a binary tree node. - * function Node(val, left, right) { - * this.val = (val===undefined ? " " : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {string} s - * @return {Node} - */ -const expTree = function(s) { - const list = s.split('') - const mdSet = new Set(['*', '/']) - const amSet = new Set(['+', '-']) - return parseExpression(list) - - function parseExpression(tokens) { - let lhs = parseTerm(tokens) - while(tokens.length && amSet.has(tokens[0])) { - const op = tokens.shift() - const rhs = parseTerm(tokens) - lhs = new Node(op, lhs, rhs) - } - return lhs - } - function parseTerm(tokens) { - let lhs = parseFactor(tokens) - while(tokens.length && mdSet.has(tokens[0])) { - const op = tokens.shift() - const rhs = parseFactor(tokens) - lhs = new Node(op, lhs, rhs) - } - return lhs - } - function parseFactor(tokens) { - if(tokens[0] === '(') { - tokens.shift() - const node = parseExpression(tokens) - tokens.shift() - return node - } else { - const token = tokens.shift() - return new Node(token) - } - } -}; diff --git a/1597.build-binary-expression-tree-from-infix-expression.js b/1597.build-binary-expression-tree-from-infix-expression.js new file mode 100644 index 00000000..cee75c34 --- /dev/null +++ b/1597.build-binary-expression-tree-from-infix-expression.js @@ -0,0 +1,58 @@ +/** + * Definition for a binary tree node. + * function Node(val, left, right) { + * this.val = (val===undefined ? " " : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {string} s + * @return {Node} + */ +const expTree = function (s) { + const n = s.length + const head = new Node() + let i = 0 + const number = () => { + let num = '' + while (i < n && '0' <= s[i]) { + num += s[i++] + } + return new Node(Number(num)) + } + const factor = () => { + if (s[i] === '(') { + i++ + const node = expression() + i++ + return node + } + return number() + } + const term = () => { + let left = factor() + while (i < n && (s[i] === '*' || s[i] === '/')) { + const op = new Node(s[i++]) + const right = factor() + op.left = left + op.right = right + left = op + } + return left + } + const expression = () => { + let left = term() + while (i < s.length && (s[i] === '+' || s[i] === '-')) { + const op = new Node(s[i++]) + const right = term() + op.left = left + op.right = right + left = op + } + return left + } + return expression() +} + + diff --git a/1598-crawler-log-folder.js b/1598.crawler-log-folder.js similarity index 100% rename from 1598-crawler-log-folder.js rename to 1598.crawler-log-folder.js diff --git a/1599-maximum-profit-of-operating-a-centennial-wheel.js b/1599.maximum-profit-of-operating-a-centennial-wheel.js similarity index 100% rename from 1599-maximum-profit-of-operating-a-centennial-wheel.js rename to 1599.maximum-profit-of-operating-a-centennial-wheel.js diff --git a/16-3sum-closest.js b/16-3sum-closest.js deleted file mode 100755 index fbe0b658..00000000 --- a/16-3sum-closest.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} target - * @return {number} - */ -const threeSumClosest = function(nums, target) { - const nums = nums.sort((a, b) => a - b); - let result; - let lo; - let hi; - let sum; - result = nums[0] + nums[1] + nums[nums.length - 1]; - for (let i = 0; i < nums.length - 2; i++) { - lo = i + 1; - hi = nums.length - 1; - while (lo < hi) { - sum = nums[i] + nums[lo] + nums[hi]; - if (sum < target) { - while (lo < hi && nums[lo] === nums[lo + 1]) { - lo += 1; - } - lo += 1; - } else if (sum > target) { - while (lo < hi && nums[hi] === nums[hi - 1]) { - hi -= 1; - } - hi -= 1; - } else { - return sum; - } - - if (Math.abs(target - sum) < Math.abs(target - result)) { - result = sum; - } - } - } - - return result; -}; diff --git a/16.3sum-closest.js b/16.3sum-closest.js new file mode 100644 index 00000000..793591cf --- /dev/null +++ b/16.3sum-closest.js @@ -0,0 +1,39 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +const threeSumClosest = function(nums, target) { + const nums = nums.sort((a, b) => a - b); + let result; + let lo; + let hi; + let sum; + result = nums[0] + nums[1] + nums[nums.length - 1]; + for (let i = 0; i < nums.length - 2; i++) { + lo = i + 1; + hi = nums.length - 1; + while (lo < hi) { + sum = nums[i] + nums[lo] + nums[hi]; + if (sum < target) { + while (lo < hi && nums[lo] === nums[lo + 1]) { + lo += 1; + } + lo += 1; + } else if (sum > target) { + while (lo < hi && nums[hi] === nums[hi - 1]) { + hi -= 1; + } + hi -= 1; + } else { + return sum; + } + + if (Math.abs(target - sum) < Math.abs(target - result)) { + result = sum; + } + } + } + + return result; +}; diff --git a/160-intersection-of-two-linked-lists.js b/160-intersection-of-two-linked-lists.js deleted file mode 100644 index 21ae7fec..00000000 --- a/160-intersection-of-two-linked-lists.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ - -/** - * @param {ListNode} headA - * @param {ListNode} headB - * @return {ListNode} - */ -const getIntersectionNode = function(headA, headB) { - let a = headA, b = headB - while(a !== b) { - a = a == null ? headB : a.next - b = b == null ? headA : b.next - } - return a -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ - -/** - * @param {ListNode} headA - * @param {ListNode} headB - * @return {ListNode} - */ -const getIntersectionNode = function(headA, headB) { - let aend = null - let bend = null - let ahead = headA - let bhead = headB - while(headA !== null && headB !== null) { - if (aend !== null && bend !== null && aend !== bend) { - return null - } - - if (headA === headB) { - return headA - } - - if (headA.next === null) { - if(aend === null) { - aend = headA - } - headA = bhead - } else { - headA = headA.next - - } - if (headB.next === null) { - if(bend === null) { - bend = headB - } - headB = ahead - } else { - headB = headB.next - } - - } - -}; diff --git a/160.intersection-of-two-linked-lists.js b/160.intersection-of-two-linked-lists.js new file mode 100644 index 00000000..f519d336 --- /dev/null +++ b/160.intersection-of-two-linked-lists.js @@ -0,0 +1,22 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ + +/** + * @param {ListNode} headA + * @param {ListNode} headB + * @return {ListNode} + */ +const getIntersectionNode = function(headA, headB) { + let a = headA, b = headB + while(a !== b) { + a = a == null ? headB : a.next + b = b == null ? headA : b.next + } + return a +}; + diff --git a/1600-throne-inheritance.js b/1600.throne-inheritance.js similarity index 100% rename from 1600-throne-inheritance.js rename to 1600.throne-inheritance.js diff --git a/1601-maximum-number-of-achievable-transfer-requests.js b/1601-maximum-number-of-achievable-transfer-requests.js deleted file mode 100644 index b99d414f..00000000 --- a/1601-maximum-number-of-achievable-transfer-requests.js +++ /dev/null @@ -1,66 +0,0 @@ -// O(n * 2 ^ r) -// r: number of requests -/** - * @param {number} n - * @param {number[][]} requests - * @return {number} - */ -const maximumRequests = function(n, requests) { - const arr = Array(n).fill(0) - let res = 0 - bt(requests, 0, arr, 0) - return res - function bt(r, idx, arr, num) { - if(idx === r.length) { - for(let i = 0; i < n; i++) { - if(arr[i] !== 0) return - } - res = Math.max(res, num) - return - } - const [from, to] = r[idx] - arr[from]++ - arr[to]-- - bt(r, idx + 1, arr, num + 1) - arr[from]-- - arr[to]++ - - bt(r, idx + 1, arr, num) - } -}; - - -// another - -/** - * @param {number} n - * @param {number[][]} requests - * @return {number} - */ -const maximumRequests = function (n, requests) { - let max = 0 - helper(requests, 0, Array(n).fill(0), 0) - return max - - function helper(requests, index, count, num) { - // Traverse all n buildings to see if they are all 0. (means balanced) - if (index === requests.length) { - for (let i of count) { - if (0 !== i) { - return - } - } - max = Math.max(max, num) - return - } - // Choose this request - count[requests[index][0]]++ - count[requests[index][1]]-- - helper(requests, index + 1, count, num + 1) - count[requests[index][0]]-- - count[requests[index][1]]++ - - // Not Choose the request - helper(requests, index + 1, count, num) - } -} diff --git a/1601.maximum-number-of-achievable-transfer-requests.js b/1601.maximum-number-of-achievable-transfer-requests.js new file mode 100644 index 00000000..03ae789a --- /dev/null +++ b/1601.maximum-number-of-achievable-transfer-requests.js @@ -0,0 +1,32 @@ +// O(n * 2 ^ r) +// r: number of requests +/** + * @param {number} n + * @param {number[][]} requests + * @return {number} + */ +const maximumRequests = function(n, requests) { + const arr = Array(n).fill(0) + let res = 0 + bt(requests, 0, arr, 0) + return res + function bt(r, idx, arr, num) { + if(idx === r.length) { + for(let i = 0; i < n; i++) { + if(arr[i] !== 0) return + } + res = Math.max(res, num) + return + } + const [from, to] = r[idx] + arr[from]++ + arr[to]-- + bt(r, idx + 1, arr, num + 1) + arr[from]-- + arr[to]++ + + bt(r, idx + 1, arr, num) + } +}; + + diff --git a/1602-find-nearest-right-node-in-binary-tree.js b/1602.find-nearest-right-node-in-binary-tree.js similarity index 100% rename from 1602-find-nearest-right-node-in-binary-tree.js rename to 1602.find-nearest-right-node-in-binary-tree.js diff --git a/1603-design-parking-system.js b/1603.design-parking-system.js similarity index 100% rename from 1603-design-parking-system.js rename to 1603.design-parking-system.js diff --git a/1605-find-valid-matrix-given-row-and-column-sums.js b/1605-find-valid-matrix-given-row-and-column-sums.js deleted file mode 100644 index f1ab5894..00000000 --- a/1605-find-valid-matrix-given-row-and-column-sums.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {number[]} rowSum - * @param {number[]} colSum - * @return {number[][]} - */ -const restoreMatrix = function(rowSum, colSum) { - const m = rowSum.length, n = colSum.length; - const res = Array.from({ length: m }, () => Array(n).fill(0)); - for (let i = 0; i < m; ++i) { - for (let j = 0 ; j < n; ++j) { - res[i][j] = Math.min(rowSum[i], colSum[j]); - rowSum[i] -= res[i][j]; - colSum[j] -= res[i][j]; - } - } - return res; -}; - -// another - -/** - * @param {number[]} rowSum - * @param {number[]} colSum - * @return {number[][]} - */ -const restoreMatrix = function(rowSum, colSum) { - const m = rowSum.length, n = colSum.length - const res = Array.from({ length: m }, () => Array(n).fill(0)) - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - res[i][j] = Math.min(rowSum[i], colSum[j]) - rowSum[i] -= res[i][j] - colSum[j] -= res[i][j] - } - } - return res -}; diff --git a/1605.find-valid-matrix-given-row-and-column-sums.js b/1605.find-valid-matrix-given-row-and-column-sums.js new file mode 100644 index 00000000..9dd15c4d --- /dev/null +++ b/1605.find-valid-matrix-given-row-and-column-sums.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} rowSum + * @param {number[]} colSum + * @return {number[][]} + */ +const restoreMatrix = function(rowSum, colSum) { + const m = rowSum.length, n = colSum.length; + const res = Array.from({ length: m }, () => Array(n).fill(0)); + for (let i = 0; i < m; ++i) { + for (let j = 0 ; j < n; ++j) { + res[i][j] = Math.min(rowSum[i], colSum[j]); + rowSum[i] -= res[i][j]; + colSum[j] -= res[i][j]; + } + } + return res; +}; + diff --git a/1606-find-servers-that-handled-most-number-of-requests.js b/1606.find-servers-that-handled-most-number-of-requests.js similarity index 100% rename from 1606-find-servers-that-handled-most-number-of-requests.js rename to 1606.find-servers-that-handled-most-number-of-requests.js diff --git a/1608-special-array-with-x-elements-greater-than-or-equal-x.js b/1608-special-array-with-x-elements-greater-than-or-equal-x.js deleted file mode 100644 index 9866bd82..00000000 --- a/1608-special-array-with-x-elements-greater-than-or-equal-x.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const specialArray = function(nums) { - let l = -1, r = 1001 - while(l <= r) { - const mid = r - Math.floor((r - l) / 2) - const tmp = valid(mid) - if(tmp === mid) return mid - else if(tmp > mid) l = mid + 1 - else r = mid - 1 - } - return -1 - - function valid(mid) { - let res = 0 - for(let e of nums) { - if(e >= mid) res++ - } - return res - } -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const specialArray = function (nums) { - nums.sort((a, b) => b - a) - let i = 0 - while(i < nums.length && nums[i] >= i) { - i++ - } - if(nums[i - 1] < i) return -1 - return i -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const specialArray = function(nums) { - nums.sort((a, b) => b - a) - let left = 0, right = nums.length - while(left <= right) { - const mid = left + ((right - left) >> 1) - if(mid < nums[mid]) left = mid + 1 - else right = mid - 1 - } - // if we found i == nums[i], there will be i + 1 items - // larger or equal to i, which makes array not special. - return left < nums.length && left === nums[left] ? -1 : left -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const specialArray = function(nums) { - const n = nums.length - nums.sort((a, b) => b - a) - let l = 0, r = n - while(l < r) { - const mid = l + ((r - l) >> 1) - if(nums[mid] > mid) l = mid + 1 - else r = mid - } - return l < n && l === nums[l] ? -1 : l -} diff --git a/1608.special-array-with-x-elements-greater-than-or-equal-x.js b/1608.special-array-with-x-elements-greater-than-or-equal-x.js new file mode 100644 index 00000000..f39cb80a --- /dev/null +++ b/1608.special-array-with-x-elements-greater-than-or-equal-x.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const specialArray = function(nums) { + let l = -1, r = 1001 + while(l <= r) { + const mid = r - Math.floor((r - l) / 2) + const tmp = valid(mid) + if(tmp === mid) return mid + else if(tmp > mid) l = mid + 1 + else r = mid - 1 + } + return -1 + + function valid(mid) { + let res = 0 + for(let e of nums) { + if(e >= mid) res++ + } + return res + } +}; + diff --git a/1609-even-odd-tree.js b/1609.even-odd-tree.js similarity index 100% rename from 1609-even-odd-tree.js rename to 1609.even-odd-tree.js diff --git a/161-one-edit-distance.js b/161.one-edit-distance.js similarity index 100% rename from 161-one-edit-distance.js rename to 161.one-edit-distance.js diff --git a/1610-maximum-number-of-visible-points.js b/1610.maximum-number-of-visible-points.js similarity index 100% rename from 1610-maximum-number-of-visible-points.js rename to 1610.maximum-number-of-visible-points.js diff --git a/1611-minimum-one-bit-operations-to-make-integers-zero.js b/1611-minimum-one-bit-operations-to-make-integers-zero.js deleted file mode 100644 index ec1f28f8..00000000 --- a/1611-minimum-one-bit-operations-to-make-integers-zero.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const minimumOneBitOperations = function (n) { - let sign = 1, - res = 0; - while (n) { - res += n ^ ((n - 1) * sign); - n &= n - 1; - sign = -sign; - } - return Math.abs(res); -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const minimumOneBitOperations = function(n) { - let mask = n; - while (mask) { - mask >>= 1; - n ^= mask; - } - return n; -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const minimumOneBitOperations = function(n) { - n ^= n >> 16 - n ^= n >> 8 - n ^= n >> 4 - n ^= n >> 2 - n ^= n >> 1 - return n -}; diff --git a/1611.minimum-one-bit-operations-to-make-integers-zero.js b/1611.minimum-one-bit-operations-to-make-integers-zero.js new file mode 100644 index 00000000..2f14ba38 --- /dev/null +++ b/1611.minimum-one-bit-operations-to-make-integers-zero.js @@ -0,0 +1,15 @@ +/** + * @param {number} n + * @return {number} + */ +const minimumOneBitOperations = function (n) { + let sign = 1, + res = 0; + while (n) { + res += n ^ ((n - 1) * sign); + n &= n - 1; + sign = -sign; + } + return Math.abs(res); +}; + diff --git a/1612-check-if-two-expression-trees-are-equivalent.js b/1612.check-if-two-expression-trees-are-equivalent.js similarity index 100% rename from 1612-check-if-two-expression-trees-are-equivalent.js rename to 1612.check-if-two-expression-trees-are-equivalent.js diff --git a/1614-maximum-nesting-depth-of-the-parentheses.js b/1614.maximum-nesting-depth-of-the-parentheses.js similarity index 100% rename from 1614-maximum-nesting-depth-of-the-parentheses.js rename to 1614.maximum-nesting-depth-of-the-parentheses.js diff --git a/1615-maximal-network-rank.js b/1615.maximal-network-rank.js similarity index 100% rename from 1615-maximal-network-rank.js rename to 1615.maximal-network-rank.js diff --git a/1616-split-two-strings-to-make-palindrome.js b/1616.split-two-strings-to-make-palindrome.js similarity index 100% rename from 1616-split-two-strings-to-make-palindrome.js rename to 1616.split-two-strings-to-make-palindrome.js diff --git a/1617-count-subtrees-with-max-distance-between-cities.js b/1617-count-subtrees-with-max-distance-between-cities.js deleted file mode 100644 index 3cc321c8..00000000 --- a/1617-count-subtrees-with-max-distance-between-cities.js +++ /dev/null @@ -1,118 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} edges - * @return {number[]} - */ -const countSubgraphsForEachDiameter = function (n, edges) { - const graph = {}; - for (let [u, v] of edges) { - if (!graph[u - 1]) graph[u - 1] = []; - if (!graph[v - 1]) graph[v - 1] = []; - graph[u - 1].push(v - 1); - graph[v - 1].push(u - 1); - } - let ans = Array(n - 1).fill(0); - for (let i = 1, len = 2 ** n; i < len; i++) { - const d = maxDistance(i); - if (d > 0) ans[d - 1] += 1; - } - return ans; - function bfs(src, cities) { - const visited = new Set(); - visited.add(src); - const q = [[src, 0]]; // Pair of (vertex, distance) - let farthestDist = 0; // Farthest distance from src to other nodes - while (q.length > 0) { - const [u, d] = q.shift(); - farthestDist = d; - for (let v of graph[u]) { - if (!visited.has(v) && cities.has(v)) { - visited.add(v); - q.push([v, d + 1]); - } - } - } - return [farthestDist, visited]; - } - function maxDistance(state) { - // return: maximum distance between any two cities in our subset. O(n^2) - const cities = new Set(); - for (let i = 0; i < n; i++) { - if ((state >> i) & (1 === 1)) cities.add(i); - } - let ans = 0; - for (let i of cities) { - const [farthestDist, visited] = bfs(i, cities); - if (visited.size < cities.size) return 0; // Can't visit all nodes of the tree -> Invalid tree - ans = Math.max(ans, farthestDist); - } - return ans; - } -}; - -// another - -/** - * @param {number} n - * @param {number[][]} edges - * @return {number[]} - */ -const countSubgraphsForEachDiameter = function(n, edges) { - const graph = {} - for(const [u, v] of edges) { - if(graph[u - 1] == null) graph[u - 1] = [] - if(graph[v - 1] == null) graph[v - 1] = [] - graph[u - 1].push(v - 1) - graph[v - 1].push(u - 1) - } - const res = Array(n - 1).fill(0) - - for(let i = 0, len = 2 ** n; i < len; i++) { - const dis = maxDistance(i) - if(dis > 0) res[dis - 1]++ - } - - return res - - function bfs(src, cities) { - const visited = new Set([src]) - let q = [[src, 0]] - let maxDist = 0 - while(q.length) { - const tmp = [] - const size = q.length - for(let i = 0; i < size; i++) { - const [u, d] = q[i] - maxDist = d - for(const v of (graph[u] || [])) { - if(cities.has(v) && !visited.has(v)) { - visited.add(v) - tmp.push([v, d + 1]) - } - } - } - - q = tmp - } - - return [maxDist, visited] - } - - function maxDistance(state) { - const cities = new Set() - for(let i = 0; i < n; i++) { - if(state & (1 << i)) cities.add(i) - } - - let res = 0 - for(const e of cities) { - const [maxDist, visited] = bfs(e, cities) - if(visited.size < cities.size) return 0 - res = Math.max(res, maxDist) - } - - return res - } -}; - - diff --git a/1617.count-subtrees-with-max-distance-between-cities.js b/1617.count-subtrees-with-max-distance-between-cities.js new file mode 100644 index 00000000..e34e8cc3 --- /dev/null +++ b/1617.count-subtrees-with-max-distance-between-cities.js @@ -0,0 +1,52 @@ +/** + * @param {number} n + * @param {number[][]} edges + * @return {number[]} + */ +const countSubgraphsForEachDiameter = function (n, edges) { + const graph = {}; + for (let [u, v] of edges) { + if (!graph[u - 1]) graph[u - 1] = []; + if (!graph[v - 1]) graph[v - 1] = []; + graph[u - 1].push(v - 1); + graph[v - 1].push(u - 1); + } + let ans = Array(n - 1).fill(0); + for (let i = 1, len = 2 ** n; i < len; i++) { + const d = maxDistance(i); + if (d > 0) ans[d - 1] += 1; + } + return ans; + function bfs(src, cities) { + const visited = new Set(); + visited.add(src); + const q = [[src, 0]]; // Pair of (vertex, distance) + let farthestDist = 0; // Farthest distance from src to other nodes + while (q.length > 0) { + const [u, d] = q.shift(); + farthestDist = d; + for (let v of graph[u]) { + if (!visited.has(v) && cities.has(v)) { + visited.add(v); + q.push([v, d + 1]); + } + } + } + return [farthestDist, visited]; + } + function maxDistance(state) { + // return: maximum distance between any two cities in our subset. O(n^2) + const cities = new Set(); + for (let i = 0; i < n; i++) { + if ((state >> i) & (1 === 1)) cities.add(i); + } + let ans = 0; + for (let i of cities) { + const [farthestDist, visited] = bfs(i, cities); + if (visited.size < cities.size) return 0; // Can't visit all nodes of the tree -> Invalid tree + ans = Math.max(ans, farthestDist); + } + return ans; + } +}; + diff --git a/1619-mean-of-array-after-removing-some-elements.js b/1619.mean-of-array-after-removing-some-elements.js similarity index 100% rename from 1619-mean-of-array-after-removing-some-elements.js rename to 1619.mean-of-array-after-removing-some-elements.js diff --git a/162-find-peak-element.js b/162-find-peak-element.js deleted file mode 100644 index c3c9bd07..00000000 --- a/162-find-peak-element.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const findPeakElement = function(nums) { - let low = 0; - let high = nums.length-1; - - while(low < high) { - let mid1 = low + ((high - low) >> 1); - let mid2 = mid1 + 1; - if(nums[mid1] < nums[mid2]) low = mid2; - else high = mid1; - } - return low; -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const findPeakElement = function(nums) { - if(nums == null) return -1 - const len = nums.length - if(len === 1) return 0 - for(let i = 1; i < len; i++) { - if(i === 1 && nums[i] < nums[i - 1]) return 0 - else if(i === len - 1 && nums[i] > nums[i - 1]) return len - 1 - else if(nums[i] > nums[i - 1] && nums[i] > nums[i + 1]) return i - } - return -1 -}; diff --git a/162.find-peak-element.js b/162.find-peak-element.js new file mode 100644 index 00000000..1624cbc4 --- /dev/null +++ b/162.find-peak-element.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const findPeakElement = function(nums) { + let low = 0; + let high = nums.length-1; + + while(low < high) { + let mid1 = low + ((high - low) >> 1); + let mid2 = mid1 + 1; + if(nums[mid1] < nums[mid2]) low = mid2; + else high = mid1; + } + return low; +}; + diff --git a/1621-number-of-sets-of-k-non-overlapping-line-segments.js b/1621-number-of-sets-of-k-non-overlapping-line-segments.js deleted file mode 100644 index 58fca659..00000000 --- a/1621-number-of-sets-of-k-non-overlapping-line-segments.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {number} n - * @param {number} k - * @return {number} - */ -const numberOfSets = function (n, k) { - let res = BigInt(1) - const mod = BigInt(10 ** 9 + 7) - for (let i = 1; i < k * 2 + 1; i++) { - res = res * BigInt(n + k - i) - res = res / BigInt(i) - } - res = res % mod - return res -} - -// another - -/** - * @param {number} n - * @param {number} k - * @return {number} - */ -const numberOfSets = function (n, k) { - // dp[i][k] as: the number of ways to generate - // k non-overlapping segments you can make using [0 ~ i]. - const dp = Array.from({ length: n }, () => Array(k + 1).fill(0)) - const MOD = 10 ** 9 + 7 - dp[1][1] = 1 - for (let i = 2; i < n; i++) dp[i][1] = ((i + 1) * i) / 2 - // sum[i][j] as: the number of ways to generate - // j - 1 segments from i - 1 points. - const sum = Array.from({ length: n }, () => Array(k + 1).fill(0)) - for (let i = 2; i < n; i++) { - for (let j = 2; j <= k; j++) { - if (j <= i) sum[i][j] = (sum[i - 1][j] + dp[i - 1][j - 1]) % MOD - dp[i][j] = (sum[i][j] + dp[i - 1][j]) % MOD - } - } - return dp[n - 1][k] -} - diff --git a/1621.number-of-sets-of-k-non-overlapping-line-segments.js b/1621.number-of-sets-of-k-non-overlapping-line-segments.js new file mode 100644 index 00000000..758ffc9a --- /dev/null +++ b/1621.number-of-sets-of-k-non-overlapping-line-segments.js @@ -0,0 +1,16 @@ +/** + * @param {number} n + * @param {number} k + * @return {number} + */ +const numberOfSets = function (n, k) { + let res = BigInt(1) + const mod = BigInt(10 ** 9 + 7) + for (let i = 1; i < k * 2 + 1; i++) { + res = res * BigInt(n + k - i) + res = res / BigInt(i) + } + res = res % mod + return res +} + diff --git a/1622-fancy-sequence.js b/1622.fancy-sequence.js similarity index 100% rename from 1622-fancy-sequence.js rename to 1622.fancy-sequence.js diff --git a/1624-largest-substring-between-two-equal-characters.js b/1624.largest-substring-between-two-equal-characters.js similarity index 100% rename from 1624-largest-substring-between-two-equal-characters.js rename to 1624.largest-substring-between-two-equal-characters.js diff --git a/1625-lexicographically-smallest-string-after-applying-operations.js b/1625-lexicographically-smallest-string-after-applying-operations.js deleted file mode 100644 index f624d743..00000000 --- a/1625-lexicographically-smallest-string-after-applying-operations.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @param {string} s - * @param {number} a - * @param {number} b - * @return {string} - */ -const findLexSmallestString = function(s, a, b) { - let res = s - const visited = new Set() - dfs(s) - return res - - function dfs(str) { - if(isVisited(str)) return - visit(str) - dfs(add(str)) - dfs(rotate(str)) - } - - function isVisited(str) { - return visited.has(str) - } - - function visit(str) { - if(str < res) res = str - visited.add(str) - } - - function add(str) { - const arr = str.split('').map(e => +e) - for(let i = 1; i < str.length; i += 2) { - arr[i] = (arr[i] + a) % 10 - } - return arr.join('') - } - - function rotate(str) { - const arr = str.split('') - arr.reverse() - let l = 0, r = b - 1 - while(l < r) { - swap(arr, l++, r--) - } - l = b - r = s.length - 1 - while(l < r) { - swap(arr, l++, r--) - } - return arr.join('') - } - - function swap(arr, i, j) { - ;[arr[i], arr[j]] = [arr[j], arr[i]] - } -}; - -// another - - -/** - * @param {string} s - * @param {number} a - * @param {number} b - * @return {string} - */ -const findLexSmallestString = function(s, a, b) { - let res = s - const set = new Set() - const q = [s] - set.add(res) - while(q.length) { - const len = q.length - for(let i = 0; i < len; i++) { - const tmp = q.shift() - const t1 = podd(tmp, a) - const t2 = rotate(tmp, b) - if(!set.has(t1)) { - set.add(t1) - q.push(t1) - } - if(!set.has(t2)) { - set.add(t2) - q.push(t2) - } - if(t1 < res) res = t1 - if(t2 < res) res = t2 - } - } - return res -}; - -function podd(s, num) { - const arr = s.split('') - for(let i = 1, len = s.length; i < len; i += 2) { - const tmp = (+s[i] + num) % 10 - arr[i] = tmp - } - return arr.join('') -} - -function rotate(s, num) { - const len = s.length - num = num % len - const idx = len - num - return s.slice(idx) + s.slice(0, idx) -} diff --git a/1625.lexicographically-smallest-string-after-applying-operations.js b/1625.lexicographically-smallest-string-after-applying-operations.js new file mode 100644 index 00000000..f0d5feac --- /dev/null +++ b/1625.lexicographically-smallest-string-after-applying-operations.js @@ -0,0 +1,56 @@ +/** + * @param {string} s + * @param {number} a + * @param {number} b + * @return {string} + */ +const findLexSmallestString = function(s, a, b) { + let res = s + const visited = new Set() + dfs(s) + return res + + function dfs(str) { + if(isVisited(str)) return + visit(str) + dfs(add(str)) + dfs(rotate(str)) + } + + function isVisited(str) { + return visited.has(str) + } + + function visit(str) { + if(str < res) res = str + visited.add(str) + } + + function add(str) { + const arr = str.split('').map(e => +e) + for(let i = 1; i < str.length; i += 2) { + arr[i] = (arr[i] + a) % 10 + } + return arr.join('') + } + + function rotate(str) { + const arr = str.split('') + arr.reverse() + let l = 0, r = b - 1 + while(l < r) { + swap(arr, l++, r--) + } + l = b + r = s.length - 1 + while(l < r) { + swap(arr, l++, r--) + } + return arr.join('') + } + + function swap(arr, i, j) { + ;[arr[i], arr[j]] = [arr[j], arr[i]] + } +}; + diff --git a/1626-best-team-with-no-conflicts.js b/1626.best-team-with-no-conflicts.js similarity index 100% rename from 1626-best-team-with-no-conflicts.js rename to 1626.best-team-with-no-conflicts.js diff --git a/1627-graph-connectivity-with-threshold.js b/1627-graph-connectivity-with-threshold.js deleted file mode 100644 index cafcb215..00000000 --- a/1627-graph-connectivity-with-threshold.js +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @param {number} n - * @param {number} threshold - * @param {number[][]} queries - * @return {boolean[]} - */ -const areConnected = function(n, threshold, queries) { - const arr = [] - const uf = new UF(n) - setup(n, threshold, uf) - for(let i = 0, len = queries.length; i < len;i++) { - arr.push(uf.check(queries[i][0], queries[i][1])) - } - return arr -}; - -function setup(n, t, uf) { - for (let i = t + 1; i <= n; i++) { - let m = 1; - while (i * m <= n) { - uf.union(i, i * m); - m += 1; - } - } -} - - -class UF { - constructor(n) { - this.root = Array(n).fill(null).map((_, i) => i) - } - find(x) { - if (this.root[x] !== x) { - this.root[x] = this.find(this.root[x]) - } - return this.root[x] - } - union(x, y) { - const xr = this.find(x) - const yr = this.find(y) - this.root[yr] = xr - } - check(x, y) { - return this.find(x) === this.find(y) - } -} - - -// another - -/** - * @param {number} n - * @param {number} threshold - * @param {number[][]} queries - * @return {boolean[]} - */ -const areConnected = function (n, threshold, queries) { - const arr = [] - const uf = new UnionFind(n) - setup(n, threshold, uf) - for (let i = 0, len = queries.length; i < len; i++) { - arr.push(uf.check(queries[i][0], queries[i][1])) - } - return arr -} - -function setup(n, t, uf) { - t++ - for (let i = t; i <= n; i++) { - let m = 1 - while (i * m <= n) { - uf.union(i, i * m) - m += 1 - } - } -} -class UnionFind { - constructor(n) { - this.parents = Array(n + 1) - .fill(0) - .map((e, i) => i) - this.ranks = Array(n + 1).fill(0) - } - root(x) { - while (x !== this.parents[x]) { - this.parents[x] = this.parents[this.parents[x]] - x = this.parents[x] - } - return x - } - find(x) { - return this.root(x) - } - check(x, y) { - return this.root(x) === this.root(y) - } - union(x, y) { - const [rx, ry] = [this.find(x), this.find(y)] - if (this.ranks[rx] >= this.ranks[ry]) { - this.parents[ry] = rx - this.ranks[rx] += this.ranks[ry] - } else if (this.ranks[ry] > this.ranks[rx]) { - this.parents[rx] = ry - this.ranks[ry] += this.ranks[rx] - } - } -} diff --git a/1627.graph-connectivity-with-threshold.js b/1627.graph-connectivity-with-threshold.js new file mode 100644 index 00000000..b95afc2d --- /dev/null +++ b/1627.graph-connectivity-with-threshold.js @@ -0,0 +1,48 @@ +/** + * @param {number} n + * @param {number} threshold + * @param {number[][]} queries + * @return {boolean[]} + */ +const areConnected = function(n, threshold, queries) { + const arr = [] + const uf = new UF(n) + setup(n, threshold, uf) + for(let i = 0, len = queries.length; i < len;i++) { + arr.push(uf.check(queries[i][0], queries[i][1])) + } + return arr +}; + +function setup(n, t, uf) { + for (let i = t + 1; i <= n; i++) { + let m = 1; + while (i * m <= n) { + uf.union(i, i * m); + m += 1; + } + } +} + + +class UF { + constructor(n) { + this.root = Array(n).fill(null).map((_, i) => i) + } + find(x) { + if (this.root[x] !== x) { + this.root[x] = this.find(this.root[x]) + } + return this.root[x] + } + union(x, y) { + const xr = this.find(x) + const yr = this.find(y) + this.root[yr] = xr + } + check(x, y) { + return this.find(x) === this.find(y) + } +} + + diff --git a/1629-slowest-key.js b/1629.slowest-key.js similarity index 100% rename from 1629-slowest-key.js rename to 1629.slowest-key.js diff --git a/163-missing-ranges.js b/163-missing-ranges.js deleted file mode 100644 index 40aabd0a..00000000 --- a/163-missing-ranges.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} lower - * @param {number} upper - * @return {string[]} - */ -const findMissingRanges = function(nums, lower, upper) { - const list = [] - for (let n of nums) { - let justBelow = n - 1 - if (lower === justBelow) list.push(lower + '') - else if (lower < justBelow) list.push(lower + '->' + justBelow) - lower = n + 1 - } - if (lower === upper) list.push(lower + '') - else if (lower < upper) list.push(lower + '->' + upper) - return list -} - -// another - -/** - * @param {number[]} nums - * @param {number} lower - * @param {number} upper - * @return {string[]} - */ -const findMissingRanges = function(nums, lower, upper) { - const res = []; - let next = lower; - for (let i = 0; i < nums.length; i++) { - if (nums[i] < next) continue; - if (nums[i] === next) { - next++; - continue; - } - range(next, nums[i] - 1, res); - next = nums[i] + 1; - } - if (next <= upper) range(next, upper, res); - return res; - function range(l, r, a) { - a.push(l < r ? `${l}->${r}` : `${l}`) - } -}; - diff --git a/163.missing-ranges.js b/163.missing-ranges.js new file mode 100644 index 00000000..c6ca08ae --- /dev/null +++ b/163.missing-ranges.js @@ -0,0 +1,19 @@ +/** + * @param {number[]} nums + * @param {number} lower + * @param {number} upper + * @return {string[]} + */ +const findMissingRanges = function(nums, lower, upper) { + const list = [] + for (let n of nums) { + let justBelow = n - 1 + if (lower === justBelow) list.push(lower + '') + else if (lower < justBelow) list.push(lower + '->' + justBelow) + lower = n + 1 + } + if (lower === upper) list.push(lower + '') + else if (lower < upper) list.push(lower + '->' + upper) + return list +} + diff --git a/1630-arithmetic-subarrays.js b/1630.arithmetic-subarrays.js similarity index 100% rename from 1630-arithmetic-subarrays.js rename to 1630.arithmetic-subarrays.js diff --git a/1631-path-with-minimum-effort.js b/1631-path-with-minimum-effort.js deleted file mode 100644 index aa094e96..00000000 --- a/1631-path-with-minimum-effort.js +++ /dev/null @@ -1,292 +0,0 @@ -/** - * @param {number[][]} heights - * @return {number} - */ -const minimumEffortPath = function(heights) { - const m = heights.length, n = heights[0].length - const dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]] - let l = 0, r = 1e6 - 1 - - while(l < r) { - const mid = ~~((l + r) / 2) - // console.log(l, r, mid) - if(valid(mid)) { - r = mid - } else { - l = mid + 1 - } - } - - return l - - function valid(limit) { - const visited = Array.from({ length: m }, () => Array(n).fill(false)) - return dfs(0, 0, limit, visited) - } - - function dfs(i, j, limit, visited) { - if(i === m - 1 && j === n - 1) return true - visited[i][j] = true - for(const [dx, dy] of dirs) { - const nx = i + dx, ny = j + dy - if(nx < 0 || nx >= m || ny < 0 || ny >= n) continue - if(visited[nx][ny]) continue - if(Math.abs(heights[i][j] - heights[nx][ny]) > limit) continue - if(dfs(nx, ny, limit, visited)) return true - } - // return false - } - -}; - -// another - - - -/** - * @param {number[][]} heights - * @return {number} - */ -const minimumEffortPath = function(heights) { - const m = heights.length, n = heights[0].length - const pq = new PriorityQueue() - const dist = Array.from({ length: m }, () => Array(n).fill(Infinity)) - pq.push([0, 0, 0]) - dist[0][0] = 0 - const dirs = [[-1, 0], [1, 0], [0, 1], [0, -1]] - while(!pq.isEmpty()) { - const [v, i, j] = pq.pop() - if(i === m - 1 && j === n - 1) return v - for(const [dx, dy] of dirs) { - const nx = i + dx, ny = j + dy - if(nx < 0 || nx >= m || ny < 0 || ny >= n) continue - const diff = Math.max(v, Math.abs(heights[nx][ny] - heights[i][j])) - if(dist[nx][ny] > diff) { - dist[nx][ny] = diff - pq.push([diff, nx, ny]) - } - } - } - return -1 -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a[0] < b[0]) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -/** - * @param {number[][]} heights - * @return {number} - */ -const minimumEffortPath = function (heights) { - const d = [0, 1, 0, -1, 0] - let lo = 0, - hi = 10 ** 6 + 1 - while (lo < hi) { - let effort = lo + ((hi - lo) >> 1) - if (isPath(heights, effort)) { - hi = effort - } else { - lo = effort + 1 - } - } - return lo - function isPath(h, effort) { - const m = h.length, - n = h[0].length - const q = [] - q.push([0, 0]) - const seen = new Set() - seen.add(0) - while (q.length) { - const cur = q.shift() - const x = cur[0], - y = cur[1] - if (x === m - 1 && y === n - 1) { - return true - } - for (let k = 0; k < 4; k++) { - const r = x + d[k], - c = y + d[k + 1] - if(seen.has(r * n + c)) continue - if ( - 0 <= r && - r < m && - 0 <= c && - c < n && - effort >= Math.abs(h[r][c] - h[x][y]) - ) { - seen.add(r * n + c) - q.push([r, c]) - } - } - } - return false - } -} - -// another - -/** - * @param {number[][]} heights - * @return {number} - */ -const minimumEffortPath = function(heights) { - const rows = heights.length - const cols = heights[0].length - const dirs = [[-1, 0], [1, 0], [0, 1], [0, -1]] - const dist = Array.from({ length: rows }, () => Array(cols).fill(Infinity)) - const pq = new PriorityQueue() - pq.push([0, 0, 0]) - dist[0][0] = 0 - while(pq.size) { - const cur = pq.pop() - if(cur[1] === rows - 1 && cur[2] === cols - 1) return cur[0] - for(let dir of dirs) { - const nr = cur[1] + dir[0] - const nc = cur[2] + dir[1] - if(nr < 0 || nr >= rows || nc < 0 || nc >= cols) continue - const diff = Math.max(cur[0], Math.abs(heights[nr][nc] - heights[cur[1]][cur[2]])) - if(dist[nr][nc] > diff) { - dist[nr][nc] = diff - pq.push([diff, nr, nc]) - } - } - } - return 0 -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a[0] < b[0]) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - diff --git a/1631.path-with-minimum-effort.js b/1631.path-with-minimum-effort.js new file mode 100644 index 00000000..4edd2203 --- /dev/null +++ b/1631.path-with-minimum-effort.js @@ -0,0 +1,41 @@ +/** + * @param {number[][]} heights + * @return {number} + */ +const minimumEffortPath = function(heights) { + const m = heights.length, n = heights[0].length + const dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]] + let l = 0, r = 1e6 - 1 + + while(l < r) { + const mid = ~~((l + r) / 2) + // console.log(l, r, mid) + if(valid(mid)) { + r = mid + } else { + l = mid + 1 + } + } + + return l + + function valid(limit) { + const visited = Array.from({ length: m }, () => Array(n).fill(false)) + return dfs(0, 0, limit, visited) + } + + function dfs(i, j, limit, visited) { + if(i === m - 1 && j === n - 1) return true + visited[i][j] = true + for(const [dx, dy] of dirs) { + const nx = i + dx, ny = j + dy + if(nx < 0 || nx >= m || ny < 0 || ny >= n) continue + if(visited[nx][ny]) continue + if(Math.abs(heights[i][j] - heights[nx][ny]) > limit) continue + if(dfs(nx, ny, limit, visited)) return true + } + // return false + } + +}; + diff --git a/1632-rank-transform-of-a-matrix.js b/1632-rank-transform-of-a-matrix.js deleted file mode 100644 index 69233377..00000000 --- a/1632-rank-transform-of-a-matrix.js +++ /dev/null @@ -1,212 +0,0 @@ -/** - * @param {number[][]} matrix - * @return {number[][]} - */ -const matrixRankTransform = function (matrix) { - function find(UF, x) { - if (x !== UF.get(x)) UF.set(x, find(UF, UF.get(x))) - return UF.get(x) - } - function union(UF, x, y) { - if (!UF.has(x)) UF.set(x, x) - if (!UF.has(y)) UF.set(y, y) - UF.set(find(UF, x), find(UF, y)) - } - const m = matrix.length - const n = matrix[0].length - const UFs = new Map() - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - const v = matrix[i][j] - if (!UFs.has(v)) UFs.set(v, new Map()) - union(UFs.get(v), i, ~j) - } - } - const value2index = {} - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - let v = matrix[i][j] - if (!value2index.hasOwnProperty(v)) value2index[v] = new Map() - const indexes = value2index[v] - let f = find(UFs.get(v), i) - if (!indexes.has(f)) indexes.set(f, []) - indexes.get(f).push([i, j]) - } - } - const answer = Array.from({ length: m }, () => Array(n).fill(0)) - const rowMax = Array(m).fill(0), colMax = Array(n).fill(0) - const keys = Object.keys(value2index) - keys.sort((a, b) => a - b) - for (let v of keys) { - for (let points of value2index[v].values()) { - let rank = 1 - for (let point of points) { - rank = Math.max(rank, Math.max(rowMax[point[0]], colMax[point[1]]) + 1) - } - for (let point of points) { - answer[point[0]][point[1]] = rank - rowMax[point[0]] = Math.max(rowMax[point[0]], rank) - colMax[point[1]] = Math.max(colMax[point[1]], rank) - } - } - } - return answer -} - -// another - -/** - * @param {number[][]} matrix - * @return {number[][]} - */ -const matrixRankTransform = function (matrix) { - const m = matrix.length - const n = matrix[0].length - const rowIndex = Array.from({ length: m }, () => Array(n).fill(0)) - const colIndex = Array.from({ length: m }, () => Array(n).fill(0)) - for (let i = 0; i < m; i++) { - let row = [] - for (let j = 0; j < n; j++) { - row.push([matrix[i][j], j]) - } - - row.sort((a, b) => a[0] - b[0]) - for (let j = 0; j < n; j++) { - rowIndex[i][j] = row[j][1] - } - } - for (let i = 0; i < n; i++) { - const col = [] - for (let j = 0; j < m; j++) { - col.push([matrix[j][i], j]) - } - col.sort((a, b) => a[0] - b[0]) - for (let j = 0; j < m; j++) { - colIndex[j][i] = col[j][1] - } - } - const result = Array.from({ length: m }, () => Array(n).fill(0)) - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - result[i][j] = 1 - } - } - let changed = true - while (changed) { - changed = shakeRow(matrix, rowIndex, result) - changed = shakeCol(matrix, colIndex, result) || changed - } - return result -} - -function shakeCol(matrix, colIndex, result) { - let changed = false - for (let i = 0; i < matrix[0].length; i++) { - for (let j = 1; j < matrix.length; j++) { - if (matrix[colIndex[j][i]][i] == matrix[colIndex[j - 1][i]][i]) { - if (result[colIndex[j][i]][i] != result[colIndex[j - 1][i]][i]) - changed = true - result[colIndex[j][i]][i] = Math.max( - result[colIndex[j][i]][i], - result[colIndex[j - 1][i]][i] - ) - result[colIndex[j - 1][i]][i] = Math.max( - result[colIndex[j][i]][i], - result[colIndex[j - 1][i]][i] - ) - } else { - if (result[colIndex[j][i]][i] < result[colIndex[j - 1][i]][i] + 1) { - changed = true - result[colIndex[j][i]][i] = result[colIndex[j - 1][i]][i] + 1 - } - } - } - } - return changed -} - -function shakeRow(matrix, rowIndex, result) { - let changed = false - for (let i = 0; i < matrix.length; i++) { - let rowInd = rowIndex[i] - let resu = result[i] - for (let j = 1; j < matrix[0].length; j++) { - if (matrix[i][rowInd[j]] == matrix[i][rowInd[j - 1]]) { - if (resu[rowInd[j]] != resu[rowInd[j - 1]]) changed = true - resu[rowInd[j]] = Math.max(resu[rowInd[j - 1]], resu[rowInd[j]]) - resu[rowInd[j - 1]] = Math.max(resu[rowInd[j - 1]], resu[rowInd[j]]) - } else { - if (resu[rowInd[j]] < resu[rowInd[j - 1]] + 1) { - changed = true - resu[rowInd[j]] = resu[rowInd[j - 1]] + 1 - } - } - } - } - return changed -} - -// another - -/** - * @param {number[][]} matrix - * @return {number[][]} - */ -const matrixRankTransform = function (matrix) { - const r = matrix.length, - c = matrix[0].length; - const t = r * c; - const arr = Array(t); - const root = Array(t + 1); - const rk = Array(t + 1).fill(0); - const find = (a) => { - let ra = root[a]; - if (ra == a) return a; - return (root[a] = find(ra)); - }; - const union = (a, b) => { - let ra = find(a); - let rb = find(b); - if (ra !== rb) { - if (rk[ra] > rk[rb]) root[rb] = ra; - else root[ra] = rb; - } - }; - let k = 0; - const ans = Array(r) - .fill(0) - .map(() => Array(c)); - for (let i = 0; i < r; ++i) { - for (let j = 0; j < c; ++j) { - arr[k] = [matrix[i][j], i, j]; - root[k] = k; - ++k; - } - } - root[k] = k; - arr.sort((a, b) => a[0] - b[0]); - const X = Array(r) - .fill(0) - .map(() => [-Infinity, t]); - const Y = Array(c) - .fill(0) - .map(() => [-Infinity, t]); - for (let i = 0; i < t; ++i) { - const [v, x, y] = arr[i]; - const id = x * c + y; - const [xv, rx] = X[x], - [yv, ry] = Y[y]; - if (v > xv) rk[id] = rk[find(rx)] + 1; - else root[id] = rx; - if (v > yv) rk[find(id)] = Math.max(rk[find(id)], rk[find(ry)] + 1); - else union(id, ry); - X[x] = [v, id]; - Y[y] = [v, id]; - } - for (let i = 0; i < r; ++i) { - for (let j = 0; j < c; ++j) { - ans[i][j] = rk[find(i * c + j)]; - } - } - return ans; -}; diff --git a/1632.rank-transform-of-a-matrix.js b/1632.rank-transform-of-a-matrix.js new file mode 100644 index 00000000..e1dd17d5 --- /dev/null +++ b/1632.rank-transform-of-a-matrix.js @@ -0,0 +1,55 @@ +/** + * @param {number[][]} matrix + * @return {number[][]} + */ +const matrixRankTransform = function (matrix) { + function find(UF, x) { + if (x !== UF.get(x)) UF.set(x, find(UF, UF.get(x))) + return UF.get(x) + } + function union(UF, x, y) { + if (!UF.has(x)) UF.set(x, x) + if (!UF.has(y)) UF.set(y, y) + UF.set(find(UF, x), find(UF, y)) + } + const m = matrix.length + const n = matrix[0].length + const UFs = new Map() + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + const v = matrix[i][j] + if (!UFs.has(v)) UFs.set(v, new Map()) + union(UFs.get(v), i, ~j) + } + } + const value2index = {} + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + let v = matrix[i][j] + if (!value2index.hasOwnProperty(v)) value2index[v] = new Map() + const indexes = value2index[v] + let f = find(UFs.get(v), i) + if (!indexes.has(f)) indexes.set(f, []) + indexes.get(f).push([i, j]) + } + } + const answer = Array.from({ length: m }, () => Array(n).fill(0)) + const rowMax = Array(m).fill(0), colMax = Array(n).fill(0) + const keys = Object.keys(value2index) + keys.sort((a, b) => a - b) + for (let v of keys) { + for (let points of value2index[v].values()) { + let rank = 1 + for (let point of points) { + rank = Math.max(rank, Math.max(rowMax[point[0]], colMax[point[1]]) + 1) + } + for (let point of points) { + answer[point[0]][point[1]] = rank + rowMax[point[0]] = Math.max(rowMax[point[0]], rank) + colMax[point[1]] = Math.max(colMax[point[1]], rank) + } + } + } + return answer +} + diff --git a/1636-sort-array-by-increasing-frequency.js b/1636.sort-array-by-increasing-frequency.js similarity index 100% rename from 1636-sort-array-by-increasing-frequency.js rename to 1636.sort-array-by-increasing-frequency.js diff --git a/1637-widest-vertical-area-between-two-points-containing-no-points.js b/1637.widest-vertical-area-between-two-points-containing-no-points.js similarity index 100% rename from 1637-widest-vertical-area-between-two-points-containing-no-points.js rename to 1637.widest-vertical-area-between-two-points-containing-no-points.js diff --git a/1638-count-substrings-that-differ-by-one-character.js b/1638-count-substrings-that-differ-by-one-character.js deleted file mode 100644 index e1a9a64f..00000000 --- a/1638-count-substrings-that-differ-by-one-character.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @param {string} s - * @param {string} t - * @return {number} - */ -const countSubstrings = function (s, t) { - const m = s.length - const n = t.length - const matrix = (m, n, v) => Array.from({ length: m }, () => Array(n).fill(v)) - // number of exact same substrings ending at s[i] and t[j]. - const same = matrix(m + 1, n + 1, 0) - // number of substrings having 1 different character ending at s[i] and t[j]. - const one = matrix(m + 1, n + 1, 0) - let result = 0 - for (let i = 1; i <= m; ++i) { - for (let j = 1; j <= n; ++j) { - if (s[i - 1] == t[j - 1]) { - same[i][j] = same[i - 1][j - 1] + 1 - one[i][j] = one[i - 1][j - 1] - } else { - one[i][j] = same[i - 1][j - 1] + 1 - } - result += one[i][j] - } - } - return result -} - -// another - -/** - * @param {string} s - * @param {string} t - * @return {number} - */ -const countSubstrings = function(s, t) { - let res = 0 ; - for (let i = 0; i < s.length; ++i) res += helper(s, t, i, 0); - for (let j = 1; j < t.length; ++j) res += helper(s, t, 0, j); - return res; -}; - -function helper(s, t, i, j) { - let res = 0, pre = 0, cur = 0; - for (let n = s.length, m = t.length; i < n && j < m; ++i, ++j) { - cur++; - if (s.charAt(i) !== t.charAt(j)) { - pre = cur; - cur = 0; - } - res += pre; - } - return res; -} diff --git a/1638.count-substrings-that-differ-by-one-character.js b/1638.count-substrings-that-differ-by-one-character.js new file mode 100644 index 00000000..32793862 --- /dev/null +++ b/1638.count-substrings-that-differ-by-one-character.js @@ -0,0 +1,28 @@ +/** + * @param {string} s + * @param {string} t + * @return {number} + */ +const countSubstrings = function (s, t) { + const m = s.length + const n = t.length + const matrix = (m, n, v) => Array.from({ length: m }, () => Array(n).fill(v)) + // number of exact same substrings ending at s[i] and t[j]. + const same = matrix(m + 1, n + 1, 0) + // number of substrings having 1 different character ending at s[i] and t[j]. + const one = matrix(m + 1, n + 1, 0) + let result = 0 + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + if (s[i - 1] == t[j - 1]) { + same[i][j] = same[i - 1][j - 1] + 1 + one[i][j] = one[i - 1][j - 1] + } else { + one[i][j] = same[i - 1][j - 1] + 1 + } + result += one[i][j] + } + } + return result +} + diff --git a/1639-number-of-ways-to-form-a-target-string-given-a-dictionary.js b/1639-number-of-ways-to-form-a-target-string-given-a-dictionary.js deleted file mode 100644 index fa8bf975..00000000 --- a/1639-number-of-ways-to-form-a-target-string-given-a-dictionary.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @param {string[]} words - * @param {string} target - * @return {number} - */ -const numWays = function (words, target) { - const m = words[0].length, len = words.length - const n = target.length, a = 'a'.charCodeAt(0) - const mod = 10 ** 9 + 7 - const dp = Array(n).fill(0) - for(let i = 0; i < m; i++) { - const freq = Array(26).fill(0) - for(let j = 0; j < len; j++) { - freq[words[j].charCodeAt(i) - a]++ - } - for(let j = Math.min(i, n - 1); j >= 0; j--) { - const code = target[j].charCodeAt(0) - a - if(freq[code] > 0) { - dp[j] += (j === 0 ? freq[code] : dp[j - 1] * freq[code]) - dp[j] %= mod - } - } - } - return dp[n - 1] -} - -// another - -/** - * @param {string[]} words - * @param {string} target - * @return {number} - */ -const numWays = function (words, target) { - const m = words[0].length - const n = target.length - const memo = Array.from({ length: m }, () => Array(n)) - const charAtIndexCnt = Array.from({ length: 128 }, () => Array(m).fill(0)) - const mod = 10 ** 9 + 7 - for (let word of words) { - for (let i = 0; i < m; i++) { - charAtIndexCnt[word.charCodeAt(i)][i] += 1 - } - } - - return dp(0, 0) - function dp(k, i) { - // found one - if (i == n) return 1 - // not found - if (k == m) return 0 - if (memo[k][i] != null) return memo[k][i] - const c = target.charCodeAt(i) - // skip k_th char - let ans = dp(k + 1, i) - if (charAtIndexCnt[c][k] > 0) { - ans += dp(k + 1, i + 1) * charAtIndexCnt[c][k] - ans %= mod - } - return (memo[k][i] = ans) - } -} diff --git a/1639.number-of-ways-to-form-a-target-string-given-a-dictionary.js b/1639.number-of-ways-to-form-a-target-string-given-a-dictionary.js new file mode 100644 index 00000000..c2fb376b --- /dev/null +++ b/1639.number-of-ways-to-form-a-target-string-given-a-dictionary.js @@ -0,0 +1,26 @@ +/** + * @param {string[]} words + * @param {string} target + * @return {number} + */ +const numWays = function (words, target) { + const m = words[0].length, len = words.length + const n = target.length, a = 'a'.charCodeAt(0) + const mod = 10 ** 9 + 7 + const dp = Array(n).fill(0) + for(let i = 0; i < m; i++) { + const freq = Array(26).fill(0) + for(let j = 0; j < len; j++) { + freq[words[j].charCodeAt(i) - a]++ + } + for(let j = Math.min(i, n - 1); j >= 0; j--) { + const code = target[j].charCodeAt(0) - a + if(freq[code] > 0) { + dp[j] += (j === 0 ? freq[code] : dp[j - 1] * freq[code]) + dp[j] %= mod + } + } + } + return dp[n - 1] +} + diff --git a/164-maximum-gap.js b/164.maximum-gap.js similarity index 100% rename from 164-maximum-gap.js rename to 164.maximum-gap.js diff --git a/1640-check-array-formation-through-concatenation.js b/1640.check-array-formation-through-concatenation.js similarity index 100% rename from 1640-check-array-formation-through-concatenation.js rename to 1640.check-array-formation-through-concatenation.js diff --git a/1641-count-sorted-vowel-strings.js b/1641-count-sorted-vowel-strings.js deleted file mode 100644 index b74ecc8d..00000000 --- a/1641-count-sorted-vowel-strings.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const countVowelStrings = function (n) { - return (n + 4) * (n + 3) * (n + 2) * (n + 1) / 24 -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const countVowelStrings = function (n) { - let mem = [1, 1, 1, 1, 1]; - for (let i = 1; i < n; ++i) { - const next = [0, 0, 0, 0, 0]; - let tmp = 0; - for (let j = 4; j >= 0; --j) { - tmp += mem[j]; - next[j] = tmp; - } - mem = next; - } - let sum = 0; - for (let i of mem) { - sum += i; - } - return sum; -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const countVowelStrings = function (n) { - const dp = Array.from({ length: n + 1 }, () => Array(5)) - recur(n, 0) - return dp[n][0] - function recur(r, i) { - if(r === 0) return 1 - if(i === 5) return 0 - if(dp[r][i] != null) return dp[r][i] - let res = recur(r, i + 1) - res += recur(r - 1, i) - return dp[r][i] = res - } -}; diff --git a/1641.count-sorted-vowel-strings.js b/1641.count-sorted-vowel-strings.js new file mode 100644 index 00000000..e6597963 --- /dev/null +++ b/1641.count-sorted-vowel-strings.js @@ -0,0 +1,8 @@ +/** + * @param {number} n + * @return {number} + */ +const countVowelStrings = function (n) { + return (n + 4) * (n + 3) * (n + 2) * (n + 1) / 24 +}; + diff --git a/1642-furthest-building-you-can-reach.js b/1642.furthest-building-you-can-reach.js similarity index 100% rename from 1642-furthest-building-you-can-reach.js rename to 1642.furthest-building-you-can-reach.js diff --git a/1643-kth-smallest-instructions.js b/1643-kth-smallest-instructions.js deleted file mode 100644 index 23ccbacd..00000000 --- a/1643-kth-smallest-instructions.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @param {number[]} destination - * @param {number} k - * @return {string} - */ -const kthSmallestPath = function (destination, k) { - let v = destination[0], - h = destination[1] - const mu = (c, n) => { - let res = '' - for (let i = 0; i < n; i++) { - res += c - } - return res - } - - let res = '' - while (h > 0 && v > 0) { - let pre = comb(h + v - 1, v) - if (k <= pre) { - res += 'H' - h -= 1 - } else { - res += 'V' - v -= 1 - k -= pre - } - } - if (h == 0) res += mu('V', v) - if (v == 0) res += mu('H', h) - return res -} - -function product(a, b) { - let prd = a, - i = a - - while (i++ < b) { - prd *= i - } - return prd -} - -function comb(n, r) { - if (n == r) { - return 1 - } else { - r = r < n - r ? n - r : r - return product(r + 1, n) / product(1, n - r) - } -} - -// another - -/** - * @param {number[]} destination - * @param {number} k - * @return {string} - */ -const kthSmallestPath = function (destination, k) { - const [r, c] = destination; - const ret = []; - let remDown = r; - for (let i = 0; i < r + c; i++) { - const remSteps = r + c - (i + 1); - const com = comb(remSteps, remDown); - if (com >= k) ret.push("H"); - else { - remDown -= 1; - k -= com; - ret.push("V"); - } - } - return ret.join(""); -}; - -function comb(n, r) { - if (n < r) return 0; - let res = 1; - if (n - r < r) r = n - r; - for (let i = n, j = 1; i >= 1 && j <= r; --i, ++j) { - res = res * i; - } - for (let i = r; i >= 2; --i) { - res = res / i; - } - return res; -} - diff --git a/1643.kth-smallest-instructions.js b/1643.kth-smallest-instructions.js new file mode 100644 index 00000000..f5e2e684 --- /dev/null +++ b/1643.kth-smallest-instructions.js @@ -0,0 +1,52 @@ +/** + * @param {number[]} destination + * @param {number} k + * @return {string} + */ +const kthSmallestPath = function (destination, k) { + let v = destination[0], + h = destination[1] + const mu = (c, n) => { + let res = '' + for (let i = 0; i < n; i++) { + res += c + } + return res + } + + let res = '' + while (h > 0 && v > 0) { + let pre = comb(h + v - 1, v) + if (k <= pre) { + res += 'H' + h -= 1 + } else { + res += 'V' + v -= 1 + k -= pre + } + } + if (h == 0) res += mu('V', v) + if (v == 0) res += mu('H', h) + return res +} + +function product(a, b) { + let prd = a, + i = a + + while (i++ < b) { + prd *= i + } + return prd +} + +function comb(n, r) { + if (n == r) { + return 1 + } else { + r = r < n - r ? n - r : r + return product(r + 1, n) / product(1, n - r) + } +} + diff --git a/1644-lowest-common-ancestor-of-a-binary-tree-ii.js b/1644-lowest-common-ancestor-of-a-binary-tree-ii.js deleted file mode 100644 index bd9407bb..00000000 --- a/1644-lowest-common-ancestor-of-a-binary-tree-ii.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {TreeNode} p - * @param {TreeNode} q - * @return {TreeNode} - */ -const lowestCommonAncestor = function (root, p, q) { - let cn = null - const dfs = function (node) { - let mid = 0 - if (!node) return false - let left = dfs(node.left) - let right = dfs(node.right) - if (node === p || node === q) { - mid = 1 - } else { - mid = 0 - } - if (mid + left + right >= 2) { - cn = node - } else { - if (mid) return mid - return left || right - } - } - dfs(root) - return cn -} - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {TreeNode} p - * @param {TreeNode} q - * @return {TreeNode} - */ -const lowestCommonAncestor = function (root, p, q) { - let hasP = false, hasQ = false - const res = LCA(root, p, q) - return hasP && hasQ ? res : null - - function LCA(root, p, q) { - if(root == null) return root - const left = LCA(root.left, p, q) - const right = LCA(root.right, p, q) - if(root === p) { - hasP = true - return root - } - if(root === q) { - hasQ = true - return root - } - if(left && right) return root - return left || right - } -} - diff --git a/1644.lowest-common-ancestor-of-a-binary-tree-ii.js b/1644.lowest-common-ancestor-of-a-binary-tree-ii.js new file mode 100644 index 00000000..00f374f5 --- /dev/null +++ b/1644.lowest-common-ancestor-of-a-binary-tree-ii.js @@ -0,0 +1,36 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {TreeNode} p + * @param {TreeNode} q + * @return {TreeNode} + */ +const lowestCommonAncestor = function (root, p, q) { + let cn = null + const dfs = function (node) { + let mid = 0 + if (!node) return false + let left = dfs(node.left) + let right = dfs(node.right) + if (node === p || node === q) { + mid = 1 + } else { + mid = 0 + } + if (mid + left + right >= 2) { + cn = node + } else { + if (mid) return mid + return left || right + } + } + dfs(root) + return cn +} + diff --git a/1646-get-maximum-in-generated-array.js b/1646.get-maximum-in-generated-array.js similarity index 100% rename from 1646-get-maximum-in-generated-array.js rename to 1646.get-maximum-in-generated-array.js diff --git a/1647-minimum-deletions-to-make-character-frequencies-unique.js b/1647.minimum-deletions-to-make-character-frequencies-unique.js similarity index 100% rename from 1647-minimum-deletions-to-make-character-frequencies-unique.js rename to 1647.minimum-deletions-to-make-character-frequencies-unique.js diff --git a/1648-sell-diminishing-valued-colored-balls.js b/1648-sell-diminishing-valued-colored-balls.js deleted file mode 100644 index f38bf0b2..00000000 --- a/1648-sell-diminishing-valued-colored-balls.js +++ /dev/null @@ -1,174 +0,0 @@ -/** - * @param {number[]} inventory - * @param {number} orders - * @return {number} - */ -const maxProfit = function(inventory, orders) { - const bigIntMax = (...args) => args.reduce((m, e) => e > m ? e : m); - inventory = inventory.map(e => BigInt(e)) - orders = BigInt(orders) - let l = 0n, r = bigIntMax(...inventory) - while(l < r) { - const mid = l + (r - l) / 2n - if(valid(mid)) l = mid + 1n - else r = mid - } - - // console.log(l) - const mod = BigInt(1e9 + 7) - let t = l, res = 0n, cnt = 0n - for(const e of inventory) { - if(e <= t) continue - cnt += e - t - res = (res + (t + 1n + e) * (e - t) / 2n) % mod - } - - res = (res + (orders - cnt) * t) % mod - - return res - - function valid(mid) { - let res = 0n - for(const e of inventory) { - if(e > mid) res += e - mid - } - return res > orders - } -}; - -// another - -/** - * @param {number[]} inventory - * @param {number} orders - * @return {number} - */ -function maxProfit(inventory, orders) { - inventory.sort((a, b) => a - b) - inventory = inventory.map(e => BigInt(e)) - let ans = 0n, n = inventory.length - 1, count = 1n - const mod = BigInt(10 ** 9 + 7) - orders = BigInt(orders) - while(orders > 0n) { - if(n > 0 && inventory[n] > inventory[n - 1] && orders >= count * (inventory[n] - inventory[n - 1])) { - ans += count * sum(inventory[n - 1], inventory[n]) - orders -= count * (inventory[n] - inventory[n - 1]) - } else if(n === 0 || inventory[n] > inventory[n - 1]) { - const num = orders / count - ans += count * sum(inventory[n] - num, inventory[n]) - const remain = orders % count - ans += remain * (inventory[n] - num) - orders = 0n - } - ans %= mod - n-- - count++ - } - return ans -} - -function sum(lo, hi) { - return (hi - lo) * (lo + hi + 1n) / 2n -} - -// another - -/** - * @param {number[]} inventory - * @param {number} orders - * @return {number} - */ -const maxProfit = function (inventory, orders) { - let Max = 1e9 + 7, - Min = 0 - let mod = BigInt(1e9 + 7) - while (Max > Min + 1) { - let tot = 0 - let mid = ((Max + Min) >> 1) - for (let it of inventory) { - if (it > mid) tot += it - mid - } - if (tot > orders) Min = mid - else Max = mid - } - let sum = BigInt(0) - Max = BigInt(Max) - orders = BigInt(orders) - for (let it of inventory) { - it = BigInt(it) - if (it > Max) { - sum += ((it + Max + BigInt(1)) * (it - Max)) / BigInt(2) - orders -= it - Max - } - } - sum += orders * Max - - return sum % mod -} - -// another - -/** - * @param {number[]} inventory - * @param {number} orders - * @return {number} - */ -var maxProfit = function(inventory, orders) { - inventory.sort((a, b) => b - a) - const mod = BigInt(1e9 + 7), n = BigInt(inventory.length) - inventory = inventory.map(e => BigInt(e)) - orders = BigInt(orders) - let cur = BigInt(inventory[0]), res = 0n, i = 0n - const min = (a, b) => a > b ? b : a - while(orders) { - while(i < n && inventory[i] === cur) i++ - let next = i === n ? 0n : inventory[i] - let h = cur - next, r = 0n, cnt = min(orders, i * h) - if (orders < i * h) { - h = orders / i - r = orders % i - } - let val = cur - h - res = (res + (cur + val + 1n) * h / 2n * i + val * r) % mod - orders -= cnt - cur = next - } - - return res -}; - -// another - -/** - * @param {number[]} inventory - * @param {number} orders - * @return {number} - */ -const maxProfit = function (inventory, orders) { - inventory.sort((a, b) => b - a) - const mod = BigInt(1e9 + 7), - n = BigInt(inventory.length) - inventory = inventory.map((e) => BigInt(e)) - orders = BigInt(orders) - let cur = BigInt(inventory[0]), - res = 0n, - i = 0n - const min = (a, b) => (a > b ? b : a) - while (orders) { - while (i < n && inventory[i] === cur) i++ - let next = i === n ? 0n : inventory[i] - let h = cur - next, - r = 0n, - cnt = min(orders, i * h) - if (orders < i * h) { - h = orders / i - r = orders % i - } - let val = cur - h - res = (res + (((cur + val + 1n) * h) / 2n) * i + val * r) % mod - orders -= cnt - cur = next - } - - return res -} diff --git a/1648.sell-diminishing-valued-colored-balls.js b/1648.sell-diminishing-valued-colored-balls.js new file mode 100644 index 00000000..da545b0b --- /dev/null +++ b/1648.sell-diminishing-valued-colored-balls.js @@ -0,0 +1,38 @@ +/** + * @param {number[]} inventory + * @param {number} orders + * @return {number} + */ +const maxProfit = function(inventory, orders) { + const bigIntMax = (...args) => args.reduce((m, e) => e > m ? e : m); + inventory = inventory.map(e => BigInt(e)) + orders = BigInt(orders) + let l = 0n, r = bigIntMax(...inventory) + while(l < r) { + const mid = l + (r - l) / 2n + if(valid(mid)) l = mid + 1n + else r = mid + } + + // console.log(l) + const mod = BigInt(1e9 + 7) + let t = l, res = 0n, cnt = 0n + for(const e of inventory) { + if(e <= t) continue + cnt += e - t + res = (res + (t + 1n + e) * (e - t) / 2n) % mod + } + + res = (res + (orders - cnt) * t) % mod + + return res + + function valid(mid) { + let res = 0n + for(const e of inventory) { + if(e > mid) res += e - mid + } + return res > orders + } +}; + diff --git a/1649-create-sorted-array-through-instructions.js b/1649-create-sorted-array-through-instructions.js deleted file mode 100644 index d186bcd8..00000000 --- a/1649-create-sorted-array-through-instructions.js +++ /dev/null @@ -1,83 +0,0 @@ -const lowBit = (x) => x & -x -class FenwickTree { - constructor(n) { - if (n < 1) return - this.sum = Array(n + 1).fill(0) - } - update(i, delta) { - if (i < 1) return - while (i < this.sum.length) { - this.sum[i] += delta - i += lowBit(i) - } - } - query(i) { - if (i < 1) return 0 - let sum = 0 - while (i > 0) { - sum += this.sum[i] - i -= lowBit(i) - } - return sum - } -} -/** - * @param {number[]} instructions - * @return {number} - */ -const createSortedArray = function(instructions) { - let res = 0, n = instructions.length, mod = 10 ** 9 + 7 - const bit = new FenwickTree(10 ** 5) - for(let i = 0; i < n; i++) { - res = (res + Math.min(bit.query(instructions[i] - 1), i - bit.query(instructions[i]))) % mod - bit.update(instructions[i], 1) - } - return res -}; - -// another - -/** - * @param {number[]} instructions - * @return {number} - */ -const createSortedArray = function (instructions) { - const ins = instructions, n = ins.length - let res = 0 - const mod = 1e9 + 7, { min } = Math - const bit = new BIT(1e5) - for(let i = 0; i < n; i++) { - const cur = ins[i] - res = (res + min(bit.query(cur - 1), i - bit.query(cur))) % mod - bit.update(cur, 1) - } - - return res -} - -function lowBit(x) { - return x & -x -} -class BIT { - constructor(n) { - this.arr = Array(n + 1).fill(0) - } - - update(i, delta) { - if(i < 1) return - while (i < this.arr.length) { - this.arr[i] += delta - i += lowBit(i) - } - } - - query(i) { - let res = 0 - if(i < 1) return res - while (i > 0) { - res += this.arr[i] - i -= lowBit(i) - } - return res - } -} diff --git a/1649.create-sorted-array-through-instructions.js b/1649.create-sorted-array-through-instructions.js new file mode 100644 index 00000000..9429d79d --- /dev/null +++ b/1649.create-sorted-array-through-instructions.js @@ -0,0 +1,37 @@ +const lowBit = (x) => x & -x +class FenwickTree { + constructor(n) { + if (n < 1) return + this.sum = Array(n + 1).fill(0) + } + update(i, delta) { + if (i < 1) return + while (i < this.sum.length) { + this.sum[i] += delta + i += lowBit(i) + } + } + query(i) { + if (i < 1) return 0 + let sum = 0 + while (i > 0) { + sum += this.sum[i] + i -= lowBit(i) + } + return sum + } +} +/** + * @param {number[]} instructions + * @return {number} + */ +const createSortedArray = function(instructions) { + let res = 0, n = instructions.length, mod = 10 ** 9 + 7 + const bit = new FenwickTree(10 ** 5) + for(let i = 0; i < n; i++) { + res = (res + Math.min(bit.query(instructions[i] - 1), i - bit.query(instructions[i]))) % mod + bit.update(instructions[i], 1) + } + return res +}; + diff --git a/165-compare-version-numbers.js b/165.compare-version-numbers.js similarity index 100% rename from 165-compare-version-numbers.js rename to 165.compare-version-numbers.js diff --git a/1650-lowest-common-ancestor-of-a-binary-tree-iii.js b/1650-lowest-common-ancestor-of-a-binary-tree-iii.js deleted file mode 100644 index 2d0cf7b4..00000000 --- a/1650-lowest-common-ancestor-of-a-binary-tree-iii.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * // Definition for a Node. - * function Node(val) { - * this.val = val; - * this.left = null; - * this.right = null; - * this.parent = null; - * }; - */ - -/** - * @param {Node} node - * @return {Node} - */ -const lowestCommonAncestor = function(p, q) { - const pa = [], qa = [] - if(up(p, q, pa)) return q - if(up(q, p, qa)) return p - const set = new Set(pa) - for(let i = 0; i < qa.length; i++) { - if(set.has(qa[i])) return qa[i] - } - - function up(node, target, arr) { - if(node == null) return null - if(node === target) return target - arr.push(node) - return up(node.parent, target, arr) - } -}; - -// another - -/** - * // Definition for a Node. - * function Node(val) { - * this.val = val; - * this.left = null; - * this.right = null; - * this.parent = null; - * }; - */ - -/** - * @param {Node} node - * @return {Node} - */ -const lowestCommonAncestor = function(p, q) { - let a = p, b = q; - while (a !== b) { - a = a == null? q : a.parent; - b = b == null? p : b.parent; - } - return a; -}; diff --git a/1650.lowest-common-ancestor-of-a-binary-tree-iii.js b/1650.lowest-common-ancestor-of-a-binary-tree-iii.js new file mode 100644 index 00000000..4b746ca2 --- /dev/null +++ b/1650.lowest-common-ancestor-of-a-binary-tree-iii.js @@ -0,0 +1,31 @@ +/** + * // Definition for a Node. + * function Node(val) { + * this.val = val; + * this.left = null; + * this.right = null; + * this.parent = null; + * }; + */ + +/** + * @param {Node} node + * @return {Node} + */ +const lowestCommonAncestor = function(p, q) { + const pa = [], qa = [] + if(up(p, q, pa)) return q + if(up(q, p, qa)) return p + const set = new Set(pa) + for(let i = 0; i < qa.length; i++) { + if(set.has(qa[i])) return qa[i] + } + + function up(node, target, arr) { + if(node == null) return null + if(node === target) return target + arr.push(node) + return up(node.parent, target, arr) + } +}; + diff --git a/1652-defuse-the-bomb.js b/1652.defuse-the-bomb.js similarity index 100% rename from 1652-defuse-the-bomb.js rename to 1652.defuse-the-bomb.js diff --git a/1653-minimum-deletions-to-make-string-balanced.js b/1653-minimum-deletions-to-make-string-balanced.js deleted file mode 100644 index 4cf12446..00000000 --- a/1653-minimum-deletions-to-make-string-balanced.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const minimumDeletions = function(s) { - let res = 0, b = 0 - for(const e of s) { - if(e === 'b') b++ - else if(b > 0) { - res++ - b-- - } - } - - return res -}; - -// another - - -/** - * @param {string} s - * @return {number} - */ -const minimumDeletions = function(s) { - let res = 0 - let cnt = 0 - for(let c of s) { - if(c === 'a' && cnt > 0) { - res++ - cnt-- - } else if(c === 'b') { - cnt++ - } - } - - return res -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const minimumDeletions = function(s) { - const len = s.length - const dp = Array(len + 1).fill(0) - let bcount = 0 - for(let i = 1; i <= len; i++) { - if(s[i - 1] === 'a') { - dp[i] = Math.min(dp[i - 1] + 1, bcount) - } else { - dp[i] = dp[i - 1] - bcount++ - } - } - - return dp[len] -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const minimumDeletions = function(s) { - const len = s.length - const stack = [] - let res = 0 - for(let i = 0; i < len; i++) { - if(stack.length && stack[stack.length - 1] > s[i]) { - res++ - stack.pop() - } else { - stack.push(s[i]) - } - } - return res -}; diff --git a/1653.minimum-deletions-to-make-string-balanced.js b/1653.minimum-deletions-to-make-string-balanced.js new file mode 100644 index 00000000..6a97c168 --- /dev/null +++ b/1653.minimum-deletions-to-make-string-balanced.js @@ -0,0 +1,17 @@ +/** + * @param {string} s + * @return {number} + */ +const minimumDeletions = function(s) { + let res = 0, b = 0 + for(const e of s) { + if(e === 'b') b++ + else if(b > 0) { + res++ + b-- + } + } + + return res +}; + diff --git a/1654-minimum-jumps-to-reach-home.js b/1654-minimum-jumps-to-reach-home.js deleted file mode 100644 index 11ce519d..00000000 --- a/1654-minimum-jumps-to-reach-home.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @param {number[]} forbidden - * @param {number} a - * @param {number} b - * @param {number} x - * @return {number} - */ -const minimumJumps = function (forbidden, a, b, x) { - const bad = new Set() - const set = new Set() - for (let i of forbidden) { - bad.add(i) - } - let q = [] - q.push([0, 0, 0]) - set.add('0,0') - while (q.length) { - const tmp = [] - const size = q.length - for(let i = 0; i < size; i++) { - const [pos, level, state] = q[i] - - if (pos === x) return level - if (state >= 0) { - if (pos <= 4000 && !set.has(pos + a + ',0') && !bad.has(pos + a)) { - set.add(pos + a + ',0') - tmp.push([pos + a, level + 1, 0]) - } - if (!set.has(pos - b + ',-1') && !bad.has(pos - b) && pos - b >= 0) { - set.add(pos - b + ',-1') - tmp.push([pos - b, level + 1, -1]) - } - } else if (state < 0) { - if (pos <= 4000 && !set.has(pos + a + ',0') && !bad.has(pos + a)) { - set.add(pos + a + ',0') - tmp.push([pos + a, level + 1, 0]) - } - } - } - - q = tmp - } - return -1 -} - -// another - -/** - * @param {number[]} forbidden - * @param {number} a - * @param {number} b - * @param {number} x - * @return {number} - */ -const minimumJumps = function (forbidden, a, b, x) { - const bad = new Set() - const set = new Set() - for (let i of forbidden) { - bad.add(i) - } - const q = [] - q.push([0, 0, 0]) - set.add('0,0') - while (q.length) { - const pair = q.shift() - let pos = pair[0], - level = pair[1], - state = pair[2] - if (pos == x) return level - if (state >= 0) { - if (pos <= 4000 && !set.has(pos + a + ',0') && !bad.has(pos + a)) { - set.add(pos + a + ',0') - q.push([pos + a, level + 1, 0]) - } - if (!set.has(pos - b + ',-1') && !bad.has(pos - b) && pos - b >= 0) { - set.add(pos - b + ',-1') - q.push([pos - b, level + 1, -1]) - } - } else if (state < 0) { - if (pos <= 4000 && !set.has(pos + a + ',0') && !bad.has(pos + a)) { - set.add(pos + a + ',0') - q.push([pos + a, level + 1, 0]) - } - } - } - return -1 -} diff --git a/1654.minimum-jumps-to-reach-home.js b/1654.minimum-jumps-to-reach-home.js new file mode 100644 index 00000000..b2978166 --- /dev/null +++ b/1654.minimum-jumps-to-reach-home.js @@ -0,0 +1,45 @@ +/** + * @param {number[]} forbidden + * @param {number} a + * @param {number} b + * @param {number} x + * @return {number} + */ +const minimumJumps = function (forbidden, a, b, x) { + const bad = new Set() + const set = new Set() + for (let i of forbidden) { + bad.add(i) + } + let q = [] + q.push([0, 0, 0]) + set.add('0,0') + while (q.length) { + const tmp = [] + const size = q.length + for(let i = 0; i < size; i++) { + const [pos, level, state] = q[i] + + if (pos === x) return level + if (state >= 0) { + if (pos <= 4000 && !set.has(pos + a + ',0') && !bad.has(pos + a)) { + set.add(pos + a + ',0') + tmp.push([pos + a, level + 1, 0]) + } + if (!set.has(pos - b + ',-1') && !bad.has(pos - b) && pos - b >= 0) { + set.add(pos - b + ',-1') + tmp.push([pos - b, level + 1, -1]) + } + } else if (state < 0) { + if (pos <= 4000 && !set.has(pos + a + ',0') && !bad.has(pos + a)) { + set.add(pos + a + ',0') + tmp.push([pos + a, level + 1, 0]) + } + } + } + + q = tmp + } + return -1 +} + diff --git a/1655-distribute-repeating-integers.js b/1655-distribute-repeating-integers.js deleted file mode 100644 index 201a7fad..00000000 --- a/1655-distribute-repeating-integers.js +++ /dev/null @@ -1,220 +0,0 @@ - -/** - * @param {number[]} nums - * @param {number[]} quantity - * @return {boolean} - */ -const canDistribute = function(nums, quantity) { - const freq = new Map() - for(const e of nums) { - freq.set(e, (freq.get(e) || 0) + 1) - } - const cntArr = [...freq.values()] - const n = cntArr.length, m = quantity.length, limit = 1 << m - const dp = Array.from({ length: n + 1 }, () => Array(limit).fill(false)) - for(let i = 0; i < n; i++) { - dp[i][0] = true - } - cntArr.unshift(0) - const allMask = limit - 1 - - for(let i = 1; i <= n; i++) { - for(let mask = 1; mask <= allMask; mask++) { - if(dp[i - 1][mask]) { - dp[i][mask] = true - continue - } - for(let subset = mask; subset > 0; subset = (subset - 1) & mask) { - if(dp[i - 1][mask - subset] === false) continue - if(canSatisfySubset(cntArr[i], subset)) { - dp[i][mask] = true - break - } - } - } - } - - return dp[n][allMask] - - function canSatisfySubset(cnt, subset) { - let sum = 0 - for (let i = 0; i < m; i++) { - if(subset & (1 << i)) { - sum += quantity[i] - } - } - return cnt >= sum - } -}; - -// another - -/** - * @param {number[]} nums - * @param {number[]} quantity - * @return {boolean} - */ -const canDistribute = function (nums, quantity) { - const mp = {} - for (let x of nums) { - mp[x] = (mp[x] || 0) + 1 - } - const values = Object.values(mp) - quantity.sort((a, b) => b - a) - let res = false - dfs(0) - return res - - function dfs(idx) { - if(idx === quantity.length || res) { - res = true - return - } - for(let i = 0, len = values.length; i < len; i++) { - if(values[i] >= quantity[idx]) { - values[i] -= quantity[idx] - dfs(idx + 1) - values[i] += quantity[idx] - } - } - } -} - -// another - -/** - * @param {number[]} nums - * @param {number[]} quantity - * @return {boolean} - */ -const canDistribute = function (nums, quantity) { - const mp = {} - for (let x of nums) { - mp[x] = (mp[x] || 0) + 1 - } - const a = [] - for (let p in mp) a.push(mp[p]) - const b = quantity - const m = quantity.length - const n = a.length - const dp = Array.from({ length: n }, () => Array(1 << m).fill(-1)) - return solve(0, 0) - - function solve(idx, mask) { - if (mask === (1 << m) - 1) return 1 - if (idx === n) return 0 - if (dp[idx][mask] !== -1) return dp[idx][mask] - let ans = solve(idx + 1, mask) - for (let i = 0, up = 1 << m; i < up; i++) { - if (mask !== (mask & i)) continue - let nm = mask - let sum = 0 - for (let j = 0; j < m; j++) { - if (mask & (1 << j)) continue - if (i & (1 << j)) { - sum += b[j] - nm |= 1 << j - } - } - if (sum <= a[idx]) ans |= solve(idx + 1, nm) - } - return (dp[idx][mask] = ans) - } -} - -// another - -/** - * @param {number[]} nums - * @param {number[]} quantity - * @return {boolean} - */ -const canDistribute = function(nums, quantity) { - const freq = {} - for(let e of nums) freq[e] = (freq[e] || 0) + 1 - const fArr = Object.values(freq) - - const m = quantity.length, n = fArr.length - const dp = Array.from({ length: n }, () => Array(1 << m).fill(-1)) - - return solve(0, 0) - - function solve(idx, mask) { - if(mask === (1 << m) - 1) return 1 - if(idx === n) return 0 - if(dp[idx][mask] !== -1) return dp[idx][mask] - - let res = solve(idx + 1, mask) - for(let i = 0; i < (1 << m); i++) { - if(mask !== (mask & i)) continue - let tmp = mask - let sum = 0 - for(let j = 0; j < m; j++) { - if(mask & (1 << j)) continue - if(i & (1 << j)) { - sum += quantity[j] - tmp |= (1 << j) - } - } - if(sum <= fArr[idx]) res |= solve(idx + 1, tmp) - } - - return dp[idx][mask] = res - } -}; - -// another - -/** - * @param {number[]} nums - * @param {number[]} quantity - * @return {boolean} - */ -const canDistribute = function (nums, quantity) { - const hash = {} - for(const e of nums) { - if(hash[e] == null) hash[e] = 0 - hash[e]++ - } - const cnts = Object.values(hash), m = quantity.length, n = cnts.length - const dp = Array.from({ length: n }, () => Array(1 << m).fill(null)) - - return helper(0, 0) - - function helper(idx, mask) { - // mask are already selected candidates - if(mask == (1 << m) - 1) { - return true; - } - if(idx == n) { - return false; - } - if(dp[idx][mask] != null) { - return dp[idx][mask]; - } - let ans = helper(idx + 1, mask); - - for(let i = 1; i < (1 << m); ++i) { - // i are potential candidates in addition to already selected ones (from mask) - // if i == mask, we can skip as the candidate is selected already - // if mask != (mask & i) means that this candidate does not include selected ones e.g - // mask = 3 (i.e 2 elements 1,2 in binary) and i = 4 (the third element in binary as 4 does not include 1 & 2), there we skip - if(mask == i || mask != (mask & i)) continue; - let sum = 0; - for(let j = 0; j < m; ++j) { - // mask << ~j is just a fancy way to do: if(mask & (1 << j)) that i've learned from @Uwi and this way you don't have to use "(", ")" - // what it does is simply pushing the jth bit to the 2^31 bit which is negative - // thus if the jth bit is 1 then the value is less than zero and if its 0 then its greater or equal to zero - if(mask << ~j >= 0 && i << ~j < 0) { // check that mask does not contain the new candidate and that the candidate is part of the potential candidate i - sum += quantity[j]; - } - } - if(sum <= cnts[idx]) { - ans |= helper(idx + 1, i); - } - if(ans) break; // if ans is true, then a solution exists and no further computation is required - } - dp[idx][mask] = ans; - return ans; - } -} diff --git a/1655.distribute-repeating-integers.js b/1655.distribute-repeating-integers.js new file mode 100644 index 00000000..9365cc8a --- /dev/null +++ b/1655.distribute-repeating-integers.js @@ -0,0 +1,49 @@ + +/** + * @param {number[]} nums + * @param {number[]} quantity + * @return {boolean} + */ +const canDistribute = function(nums, quantity) { + const freq = new Map() + for(const e of nums) { + freq.set(e, (freq.get(e) || 0) + 1) + } + const cntArr = [...freq.values()] + const n = cntArr.length, m = quantity.length, limit = 1 << m + const dp = Array.from({ length: n + 1 }, () => Array(limit).fill(false)) + for(let i = 0; i < n; i++) { + dp[i][0] = true + } + cntArr.unshift(0) + const allMask = limit - 1 + + for(let i = 1; i <= n; i++) { + for(let mask = 1; mask <= allMask; mask++) { + if(dp[i - 1][mask]) { + dp[i][mask] = true + continue + } + for(let subset = mask; subset > 0; subset = (subset - 1) & mask) { + if(dp[i - 1][mask - subset] === false) continue + if(canSatisfySubset(cntArr[i], subset)) { + dp[i][mask] = true + break + } + } + } + } + + return dp[n][allMask] + + function canSatisfySubset(cnt, subset) { + let sum = 0 + for (let i = 0; i < m; i++) { + if(subset & (1 << i)) { + sum += quantity[i] + } + } + return cnt >= sum + } +}; + diff --git a/1656-design-an-ordered-stream.js b/1656.design-an-ordered-stream.js similarity index 100% rename from 1656-design-an-ordered-stream.js rename to 1656.design-an-ordered-stream.js diff --git a/1657-determine-if-two-strings-are-close.js b/1657.determine-if-two-strings-are-close.js similarity index 100% rename from 1657-determine-if-two-strings-are-close.js rename to 1657.determine-if-two-strings-are-close.js diff --git a/1658-minimum-operations-to-reduce-x-to-zero.js b/1658-minimum-operations-to-reduce-x-to-zero.js deleted file mode 100644 index 15935ef5..00000000 --- a/1658-minimum-operations-to-reduce-x-to-zero.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} x - * @return {number} - */ -const minOperations = function(nums, x) { - const sum = nums.reduce((ac, e) => ac + e, 0) - const subArrSum = sum - x - if(subArrSum === 0) return nums.length - const n = nums.length, hash = {0: -1} - let ac = 0, res = -1 - for(let i = 0; i < n; i++) { - const cur = nums[i] - ac += cur - if(hash[ac - subArrSum] != null) { - res = Math.max(res, i - hash[ac - subArrSum]) - } - hash[ac] = i - } - - return res === -1 ? -1 : n - res -}; - -// another - -/** - * @param {number[]} nums - * @param {number} x - * @return {number} - */ -const minOperations = function (nums, x) { - let l = 0, - r = nums.length - 1; - while (x >= 0 && r >= l) { - x -= nums[r]; - r -= 1; - } - if (r < 0 && x > 0) { - return -1; - } else if (r < 0 && x == 0) { - return nums.length; - } - - let ans = Number.MAX_VALUE; - while (r < nums.length) { - while (x <= 0 && r + 1 < nums.length) { - if (x == 0) ans = Math.min(ans, nums.length - (r - l + 1)); - x += nums[r + 1]; - r += 1; - } - if (r + 1 >= nums.length) { - if (x == 0) ans = Math.min(ans, nums.length - (r - l + 1)); - break; - } - while (x >= 0) { - if (x == 0) ans = Math.min(ans, nums.length - (r - l + 1)); - x -= nums[l]; - l += 1; - } - } - return ans != Number.MAX_VALUE ? ans : -1; -}; diff --git a/1658.minimum-operations-to-reduce-x-to-zero.js b/1658.minimum-operations-to-reduce-x-to-zero.js new file mode 100644 index 00000000..f106e171 --- /dev/null +++ b/1658.minimum-operations-to-reduce-x-to-zero.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} nums + * @param {number} x + * @return {number} + */ +const minOperations = function(nums, x) { + const sum = nums.reduce((ac, e) => ac + e, 0) + const subArrSum = sum - x + if(subArrSum === 0) return nums.length + const n = nums.length, hash = {0: -1} + let ac = 0, res = -1 + for(let i = 0; i < n; i++) { + const cur = nums[i] + ac += cur + if(hash[ac - subArrSum] != null) { + res = Math.max(res, i - hash[ac - subArrSum]) + } + hash[ac] = i + } + + return res === -1 ? -1 : n - res +}; + diff --git a/1659-maximize-grid-happiness.js b/1659.maximize-grid-happiness.js similarity index 100% rename from 1659-maximize-grid-happiness.js rename to 1659.maximize-grid-happiness.js diff --git a/166-fraction-to-recurring-decimal.js b/166.fraction-to-recurring-decimal.js similarity index 100% rename from 166-fraction-to-recurring-decimal.js rename to 166.fraction-to-recurring-decimal.js diff --git a/1660-correct-a-binary-tree.js b/1660-correct-a-binary-tree.js deleted file mode 100644 index 9c940f94..00000000 --- a/1660-correct-a-binary-tree.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @param {number} from - * @param {number} to - * @return {TreeNode} - */ -const correctBinaryTree = (root, seen = new Set(), found = false) => { - const go = (root) => { - seen.add(root) - if (root.right && seen.has(root.right)) { - found = true - return null - } - if (!found && root.right) root.right = go(root.right) - if (!found && root.left) root.left = go(root.left) - return root - } - return go(root) -} - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @param {number} from - * @param {number} to - * @return {TreeNode} - */ -const correctBinaryTree = function(root) { - let q = [root] - let target - while(q.length) { - const size = q.length - const next = new Set() - const row = new Set() - for(let i = 0; i < size; i++) { - const cur = q.shift() - row.add(cur) - if(cur.left) next.add(cur.left) - if(cur.right) next.add(cur.right) - } - for(let e of next) { - if(next.has(e.right)) { - target = e - for(let el of row) { - if(el.left && el.left === target) { - el.left = null - return root - } - if(el.right && el.right === target) { - el.right = null - return root - } - } - } - } - q = Array.from(next) - } - return root -}; diff --git a/1660.correct-a-binary-tree.js b/1660.correct-a-binary-tree.js new file mode 100644 index 00000000..ebc2fd92 --- /dev/null +++ b/1660.correct-a-binary-tree.js @@ -0,0 +1,28 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} from + * @param {number} to + * @return {TreeNode} + */ +const correctBinaryTree = (root, seen = new Set(), found = false) => { + const go = (root) => { + seen.add(root) + if (root.right && seen.has(root.right)) { + found = true + return null + } + if (!found && root.right) root.right = go(root.right) + if (!found && root.left) root.left = go(root.left) + return root + } + return go(root) +} + diff --git a/1662-check-if-two-string-arrays-are-equivalent.js b/1662.check-if-two-string-arrays-are-equivalent.js similarity index 100% rename from 1662-check-if-two-string-arrays-are-equivalent.js rename to 1662.check-if-two-string-arrays-are-equivalent.js diff --git a/1663-smallest-string-with-a-given-numeric-value.js b/1663.smallest-string-with-a-given-numeric-value.js similarity index 100% rename from 1663-smallest-string-with-a-given-numeric-value.js rename to 1663.smallest-string-with-a-given-numeric-value.js diff --git a/1664-ways-to-make-a-fair-array.js b/1664-ways-to-make-a-fair-array.js deleted file mode 100644 index 11e38596..00000000 --- a/1664-ways-to-make-a-fair-array.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const waysToMakeFair = function(nums) { - const n = nums.length, right = Array(2).fill(0), left = Array(2).fill(0) - let res = 0 - for(let i = 0; i < n; i++) right[i % 2] += nums[i] - for(let i = 0; i < n; i++) { - right[i % 2] -= nums[i] - if(left[0] + right[1] === left[1] + right[0]) res++ - left[i % 2] += nums[i] - } - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const waysToMakeFair = function (nums) { - const n = nums.length - const preOddSum = new Array(n + 1).fill(0) - const preEvenSum = new Array(n + 1).fill(0) - for (let i = 0; i < n; i++) { - if (i % 2 === 0) { - preEvenSum[i + 1] = nums[i] + preEvenSum[i] - preOddSum[i + 1] = preOddSum[i] - } else { - preOddSum[i + 1] = nums[i] + preOddSum[i] - preEvenSum[i + 1] = preEvenSum[i] - } - } - let ret = 0 - for (let i = 0; i < n; i++) { - if ( - preEvenSum[i] + preOddSum[n] - preOddSum[i + 1] === - preOddSum[i] + preEvenSum[n] - preEvenSum[i + 1] - ) - ret++ - } - return ret -} diff --git a/1664.ways-to-make-a-fair-array.js b/1664.ways-to-make-a-fair-array.js new file mode 100644 index 00000000..df093b3d --- /dev/null +++ b/1664.ways-to-make-a-fair-array.js @@ -0,0 +1,16 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const waysToMakeFair = function(nums) { + const n = nums.length, right = Array(2).fill(0), left = Array(2).fill(0) + let res = 0 + for(let i = 0; i < n; i++) right[i % 2] += nums[i] + for(let i = 0; i < n; i++) { + right[i % 2] -= nums[i] + if(left[0] + right[1] === left[1] + right[0]) res++ + left[i % 2] += nums[i] + } + return res +}; + diff --git a/1665-minimum-initial-energy-to-finish-tasks.js b/1665-minimum-initial-energy-to-finish-tasks.js deleted file mode 100644 index 31746fc0..00000000 --- a/1665-minimum-initial-energy-to-finish-tasks.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @param {number[][]} tasks - * @return {number} - */ -const minimumEffort = function (tasks) { - tasks.sort((a, b) => a[1] - a[0] > b[1] - b[0] ? 1 : -1) - let res = 0 - for(let e of tasks) { - res = Math.max(res + e[0], e[1]) - } - return res -} - -// another - -/** - * @param {number[][]} tasks - * @return {number} - */ -const minimumEffort = function (a) { - let low = 0, - high = 1e9 - for (let x of a) low = Math.max(low, x[1]) - a.sort((lhs, rhs) => (lhs[1] - lhs[0] > rhs[1] - rhs[0] ? -1 : 1)) - let n = a.length - while (low != high) { - let mid = low + ((high - low) >> 1) - let found = false - let rem = mid - for (let i = 0; i < n; ++i) { - if (rem < a[i][1]) { - found = true - break - } - rem -= a[i][0] - } - if (found) { - low = mid + 1 - } else { - high = mid - } - } - return high -} diff --git a/1665.minimum-initial-energy-to-finish-tasks.js b/1665.minimum-initial-energy-to-finish-tasks.js new file mode 100644 index 00000000..1e8fcc85 --- /dev/null +++ b/1665.minimum-initial-energy-to-finish-tasks.js @@ -0,0 +1,13 @@ +/** + * @param {number[][]} tasks + * @return {number} + */ +const minimumEffort = function (tasks) { + tasks.sort((a, b) => a[1] - a[0] > b[1] - b[0] ? 1 : -1) + let res = 0 + for(let e of tasks) { + res = Math.max(res + e[0], e[1]) + } + return res +} + diff --git a/1666-change-the-root-of-a-binary-tree.js b/1666.change-the-root-of-a-binary-tree.js similarity index 100% rename from 1666-change-the-root-of-a-binary-tree.js rename to 1666.change-the-root-of-a-binary-tree.js diff --git a/1668-maximum-repeating-substring.js b/1668-maximum-repeating-substring.js deleted file mode 100644 index 87467df4..00000000 --- a/1668-maximum-repeating-substring.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @param {string} sequence - * @param {string} word - * @return {number} - */ -const maxRepeating = function(sequence, word) { - let count = 1; - while (sequence.includes(word.repeat(count))) count += 1 - return count - 1; -}; - -// another - -/** - * @param {string} sequence - * @param {string} word - * @return {number} - */ -const maxRepeating = function(sequence, word) { - const s = sequence.length, w = word.length - const max_repeat = (s / w) >> 0 - const failure = Array(w * max_repeat + 1).fill(0) - const repeat_words = word.repeat(max_repeat) + '$' - let result = 0, j = 0 - - for(let i = 1, hi = repeat_words.length; i < hi; i++) { - while(j > 0 && repeat_words[j] !== repeat_words[i]) j = failure[j - 1] - j += (repeat_words[j] === repeat_words[i] ? 1 : 0) - failure[i] = j - } - - j = 0 - for(let i = 0, len = sequence.length; i < len; i++) { - while(j > 0 && repeat_words[j] !== sequence[i]) j = failure[j - 1] - j += (repeat_words[j] === sequence[i] ? 1 : 0) - result = Math.max(result, (j / w) >> 0) - } - return result -}; - diff --git a/1668.maximum-repeating-substring.js b/1668.maximum-repeating-substring.js new file mode 100644 index 00000000..25a11dd8 --- /dev/null +++ b/1668.maximum-repeating-substring.js @@ -0,0 +1,11 @@ +/** + * @param {string} sequence + * @param {string} word + * @return {number} + */ +const maxRepeating = function(sequence, word) { + let count = 1; + while (sequence.includes(word.repeat(count))) count += 1 + return count - 1; +}; + diff --git a/1669-merge-in-between-linked-lists.js b/1669.merge-in-between-linked-lists.js similarity index 100% rename from 1669-merge-in-between-linked-lists.js rename to 1669.merge-in-between-linked-lists.js diff --git a/167-two-sum-II-input-array-is-sorted.js b/167-two-sum-II-input-array-is-sorted.js deleted file mode 100755 index a99cd2ab..00000000 --- a/167-two-sum-II-input-array-is-sorted.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @param {number[]} numbers - * @param {number} target - * @return {number[]} - */ -const twoSum = function(numbers, target) { - const res = []; - let remaining; - let next = 0; - for (let i = 0; i < numbers.length; i++) { - remaining = target - numbers[i]; - next = i + 1; - while (next < numbers.length && numbers[next] <= remaining) { - if (numbers[next] === remaining) { - res.push(i + 1, next + 1); - break; - } - next += 1; - } - } - - return res; -}; diff --git a/167.two-sum-II-input-array-is-sorted.js b/167.two-sum-II-input-array-is-sorted.js new file mode 100644 index 00000000..6e2c1128 --- /dev/null +++ b/167.two-sum-II-input-array-is-sorted.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} numbers + * @param {number} target + * @return {number[]} + */ +const twoSum = function(numbers, target) { + const res = []; + let remaining; + let next = 0; + for (let i = 0; i < numbers.length; i++) { + remaining = target - numbers[i]; + next = i + 1; + while (next < numbers.length && numbers[next] <= remaining) { + if (numbers[next] === remaining) { + res.push(i + 1, next + 1); + break; + } + next += 1; + } + } + + return res; +}; diff --git a/1670-design-front-middle-back-queue.js b/1670.design-front-middle-back-queue.js similarity index 100% rename from 1670-design-front-middle-back-queue.js rename to 1670.design-front-middle-back-queue.js diff --git a/1671-minimum-number-of-removals-to-make-mountain-array.js b/1671-minimum-number-of-removals-to-make-mountain-array.js deleted file mode 100644 index 933532f3..00000000 --- a/1671-minimum-number-of-removals-to-make-mountain-array.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const minimumMountainRemovals = function(nums) { - const inc = LIS(nums) - const dec = LIS(nums.slice().reverse()).reverse() - let res = 0 - for(let i = 0, len = nums.length; i < len; i++) { - if(inc[i] > 1 && dec[i] > 1) res = Math.max(res, inc[i] + dec[i] - 1) - } - return nums.length - res -}; - -function LIS(arr) { - const stack = [] - const res = [] - for(let e of arr) { - if((stack.length && e > stack[stack.length - 1]) || stack.length === 0) { - stack.push(e) - res.push(stack.length) - continue - } - let l = 0, r = stack.length - 1 - while(l < r) { - const mid = l + ((r - l) >> 1) - if(stack[mid] < e) l = mid + 1 - else r = mid - } - stack[l] = e - res.push(stack.length) - } - - return res -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const minimumMountainRemovals = function (nums) { - if (nums.length <= 3) return 0 - const n = nums.length - const inc = Array(n).fill(0) - const dec = Array(n).fill(0) - const { max, min } = Math - for (let i = 1; i < n; i++) { - for (let j = 0; j < i; j++) { - if (nums[i] > nums[j]) inc[i] = max(inc[i], inc[j] + 1) - } - } - for (let i = n - 2; i >= 0; i--) { - for (let j = n - 1; j > i; j--) { - if (nums[i] > nums[j]) dec[i] = max(dec[i], dec[j] + 1) - } - } - let res = 0 - for (let i = 0; i < n; i++) { - if (inc[i] > 0 && dec[i] > 0) res = max(res, inc[i] + dec[i]) - } - return n - res - 1 -} diff --git a/1671.minimum-number-of-removals-to-make-mountain-array.js b/1671.minimum-number-of-removals-to-make-mountain-array.js new file mode 100644 index 00000000..9e6254e9 --- /dev/null +++ b/1671.minimum-number-of-removals-to-make-mountain-array.js @@ -0,0 +1,36 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const minimumMountainRemovals = function(nums) { + const inc = LIS(nums) + const dec = LIS(nums.slice().reverse()).reverse() + let res = 0 + for(let i = 0, len = nums.length; i < len; i++) { + if(inc[i] > 1 && dec[i] > 1) res = Math.max(res, inc[i] + dec[i] - 1) + } + return nums.length - res +}; + +function LIS(arr) { + const stack = [] + const res = [] + for(let e of arr) { + if((stack.length && e > stack[stack.length - 1]) || stack.length === 0) { + stack.push(e) + res.push(stack.length) + continue + } + let l = 0, r = stack.length - 1 + while(l < r) { + const mid = l + ((r - l) >> 1) + if(stack[mid] < e) l = mid + 1 + else r = mid + } + stack[l] = e + res.push(stack.length) + } + + return res +} + diff --git a/1672-richest-customer-wealth.js b/1672.richest-customer-wealth.js similarity index 100% rename from 1672-richest-customer-wealth.js rename to 1672.richest-customer-wealth.js diff --git a/1673-find-the-most-competitive-subsequence.js b/1673-find-the-most-competitive-subsequence.js deleted file mode 100644 index bf913f46..00000000 --- a/1673-find-the-most-competitive-subsequence.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number[]} - */ -const mostCompetitive = function (nums, k) { - const res = new Array(k).fill(0) - let start = -1 - let idx = 0 - for (let i = k; i > 0; i--) { - let min = Number.MAX_VALUE - for (let j = start + 1; j < nums.length - i + 1; j++) { - if (nums[j] < min) { - start = j - min = nums[j] - } - } - res[idx++] = min - } - return res -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number[]} - */ -const mostCompetitive = function (nums, k) { - const stack = [], - n = nums.length - let i = 0 - while (i < n) { - while ( - stack.length && - stack[stack.length - 1] > nums[i] && - n - i + stack.length > k - ) - stack.pop() - if (stack.length < k) stack.push(nums[i]) - i++ - } - return stack -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number[]} - */ -const mostCompetitive = function (nums, k) { - const n = nums.length, stack = [] - for(let i = 0; i < n; i++) { - const ch = nums[i] - while( - stack.length && - ch < stack[stack.length - 1] && - stack.length + (n - 1 - i) >= k - ) { - stack.pop() - } - if(stack.length < k) stack.push(ch) - } - return stack -} - diff --git a/1673.find-the-most-competitive-subsequence.js b/1673.find-the-most-competitive-subsequence.js new file mode 100644 index 00000000..c443a403 --- /dev/null +++ b/1673.find-the-most-competitive-subsequence.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number[]} + */ +const mostCompetitive = function (nums, k) { + const res = new Array(k).fill(0) + let start = -1 + let idx = 0 + for (let i = k; i > 0; i--) { + let min = Number.MAX_VALUE + for (let j = start + 1; j < nums.length - i + 1; j++) { + if (nums[j] < min) { + start = j + min = nums[j] + } + } + res[idx++] = min + } + return res +} + diff --git a/1674-minimum-moves-to-make-array-complementary.js b/1674-minimum-moves-to-make-array-complementary.js deleted file mode 100644 index c257d2e2..00000000 --- a/1674-minimum-moves-to-make-array-complementary.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} limit - * @return {number} - */ -const minMoves = function (nums, limit) { - const { min, max } = Math - const n = nums.length - const delta = Array(limit * 2 + 2).fill(0) - for (let i = 0; i < n / 2; i++) { - const lo = 1 + min(nums[i], nums[n - i - 1]) - const hi = limit + max(nums[i], nums[n - i - 1]) - const sum = nums[i] + nums[n - i - 1] - delta[lo]-- - delta[sum]-- - delta[sum + 1]++ - delta[hi + 1]++ - } - let now = n - let ans = n - for (let i = 2; i <= limit * 2; i++) { - now += delta[i] - ans = min(ans, now) - } - return ans -} - -// another - -/** - * @param {number[]} nums - * @param {number} limit - * @return {number} - */ -const minMoves = function (nums, limit) { - const n = nums.length, { max, min } = Math - const delta = Array(2 * limit + 2).fill(0) - for(let i = 0; i < n / 2; i++) { - const a = nums[i], b = nums[n - 1 - i] - // [2, min(a, b) + 1) - delta[2] += 2 - // [min(a, b) + 1, a + b) - delta[min(a, b) + 1] -= 1 - delta[a + b]-- - // [a + b + 1, max(a, b) + limit] - delta[a + b + 1] += 1 - // (max(a, b) + limit, 2 * limit] - delta[max(a, b) + limit + 1] +=1 - } - - let res = n, cur = 0 - for(let i = 2; i <= limit * 2; i++) { - cur += delta[i] - res = min(cur, res) - } - - return res -} - -// another - -/** - * @param {number[]} nums - * @param {number} limit - * @return {number} - */ -const minMoves = function (nums, limit) { - const n = nums.length, { min, max } = Math - const arr = Array(2 * limit + 2).fill(0) - for(let i = 0, r = n / 2; i < r; i++) { - const a = nums[i], b = nums[n - 1 - i] - arr[2] += 2 - arr[min(a, b) + 1]-- - arr[a + b]-- - arr[a + b + 1]++ - arr[max(a, b) + limit + 1]++ - } - let res = Infinity, cur = 0 - for(let i = 2, r = 2 * limit; i <= r; i++) { - cur += arr[i] - res = min(res, cur) - } - - return res -} - -// another - -/** - * @param {number[]} nums - * @param {number} limit - * @return {number} - */ -const minMoves = function (nums, limit) { - const n = nums.length, { min, max } = Math - const arr = Array(2 * limit + 2).fill(0) - for(let i = 0, r = n / 2; i < r; i++) { - const a = nums[i], b = nums[n - 1 - i] - // [2, 2 * limit] - arr[2] += 2 - arr[2 * limit + 1] -= 2 - // [min(a, b) + 1, max(a, b) + limit] - arr[min(a, b) + 1]-- - arr[max(a, b) + limit + 1]++ - // a + b - arr[a + b]-- - arr[a + b + 1]++ - - } - let res = Infinity, cur = 0 - for(let i = 2, r = 2 * limit; i <= r; i++) { - cur += arr[i] - res = min(res, cur) - } - - return res -} - - diff --git a/1674.minimum-moves-to-make-array-complementary.js b/1674.minimum-moves-to-make-array-complementary.js new file mode 100644 index 00000000..ed1e460e --- /dev/null +++ b/1674.minimum-moves-to-make-array-complementary.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} nums + * @param {number} limit + * @return {number} + */ +const minMoves = function (nums, limit) { + const { min, max } = Math + const n = nums.length + const delta = Array(limit * 2 + 2).fill(0) + for (let i = 0; i < n / 2; i++) { + const lo = 1 + min(nums[i], nums[n - i - 1]) + const hi = limit + max(nums[i], nums[n - i - 1]) + const sum = nums[i] + nums[n - i - 1] + delta[lo]-- + delta[sum]-- + delta[sum + 1]++ + delta[hi + 1]++ + } + let now = n + let ans = n + for (let i = 2; i <= limit * 2; i++) { + now += delta[i] + ans = min(ans, now) + } + return ans +} + diff --git a/1675-minimize-deviation-in-array.js b/1675.minimize-deviation-in-array.js similarity index 100% rename from 1675-minimize-deviation-in-array.js rename to 1675.minimize-deviation-in-array.js diff --git a/1676-lowest-common-ancestor-of-a-binary-tree-iv.js b/1676-lowest-common-ancestor-of-a-binary-tree-iv.js deleted file mode 100644 index 1057137e..00000000 --- a/1676-lowest-common-ancestor-of-a-binary-tree-iv.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {TreeNode[]} nodes - * @return {TreeNode} - */ -const lowestCommonAncestor = function(root, nodes) { - if (root == null) return root - for(let e of nodes) { - if(root === e) return root - } - const left = lowestCommonAncestor(root.left, nodes) - const right = lowestCommonAncestor(root.right, nodes) - if(left && right) return root - return left ? left : right -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {TreeNode[]} nodes - * @return {TreeNode} - */ - const lowestCommonAncestor = function(root, nodes) { - const set = new Set(nodes) - return dfs(root) - - function dfs(node) { - if(node == null) return node - const left = dfs(node.left) - const right = dfs(node.right) - - if(set.has(node)) return node - if(left && right) return node - return left || right - } -}; diff --git a/1676.lowest-common-ancestor-of-a-binary-tree-iv.js b/1676.lowest-common-ancestor-of-a-binary-tree-iv.js new file mode 100644 index 00000000..721c185c --- /dev/null +++ b/1676.lowest-common-ancestor-of-a-binary-tree-iv.js @@ -0,0 +1,23 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {TreeNode[]} nodes + * @return {TreeNode} + */ +const lowestCommonAncestor = function(root, nodes) { + if (root == null) return root + for(let e of nodes) { + if(root === e) return root + } + const left = lowestCommonAncestor(root.left, nodes) + const right = lowestCommonAncestor(root.right, nodes) + if(left && right) return root + return left ? left : right +}; + diff --git a/1678-goal-parser-interpretation.js b/1678.goal-parser-interpretation.js similarity index 100% rename from 1678-goal-parser-interpretation.js rename to 1678.goal-parser-interpretation.js diff --git a/1679-max-number-of-k-sum-pairs.js b/1679.max-number-of-k-sum-pairs.js similarity index 100% rename from 1679-max-number-of-k-sum-pairs.js rename to 1679.max-number-of-k-sum-pairs.js diff --git a/168-excel-sheet-column-title.js b/168.excel-sheet-column-title.js similarity index 100% rename from 168-excel-sheet-column-title.js rename to 168.excel-sheet-column-title.js diff --git a/1680-concatenation-of-consecutive-binary-numbers.js b/1680-concatenation-of-consecutive-binary-numbers.js deleted file mode 100644 index c2b7c069..00000000 --- a/1680-concatenation-of-consecutive-binary-numbers.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const concatenatedBinary = function(n) { - let res = '' - const mod = 10 ** 9 + 7 - for(let i = 1; i <= n; i++) { - res += dec2bin(i) - res = dec2bin(parseInt(res, 2) % mod) - } - return parseInt(res, 2) % mod -}; -function dec2bin(dec){ - return (dec >>> 0).toString(2); -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const concatenatedBinary = function (n) { - const mod = BigInt(1e9 + 7) - let res = 0n - for (let i = 1n, shift = 0n; i <= n; i++) { - let singleBit = (i & (i - 1n)) == 0 - if (singleBit) shift++ - res <<= shift - res += i - res %= mod - } - return res -} diff --git a/1680.concatenation-of-consecutive-binary-numbers.js b/1680.concatenation-of-consecutive-binary-numbers.js new file mode 100644 index 00000000..38824917 --- /dev/null +++ b/1680.concatenation-of-consecutive-binary-numbers.js @@ -0,0 +1,17 @@ +/** + * @param {number} n + * @return {number} + */ +const concatenatedBinary = function(n) { + let res = '' + const mod = 10 ** 9 + 7 + for(let i = 1; i <= n; i++) { + res += dec2bin(i) + res = dec2bin(parseInt(res, 2) % mod) + } + return parseInt(res, 2) % mod +}; +function dec2bin(dec){ + return (dec >>> 0).toString(2); +} + diff --git a/1681-minimum-incompatibility.js b/1681-minimum-incompatibility.js deleted file mode 100644 index 255ef859..00000000 --- a/1681-minimum-incompatibility.js +++ /dev/null @@ -1,182 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const minimumIncompatibility = function(nums, k) { - const n = nums.length - const size = n / k - const mod = 1e9 + 7 - if(size === 1) return 0 - const limit = 1 << n - const dp = Array.from({ length: limit }, () => Array(16).fill(Infinity)) - for(let i = 0; i < n; i++) dp[1 << i][i] = 0 - - for(let mask = 0; mask < limit; mask++) { - for(let i = 0; i < n; i++) { - if((mask & (1 << i)) === 0) continue - for(let j = 0; j < n; j++) { - if((mask & (1 << j))) continue - const newMask = mask | (1 << j) - if(bitCnt(mask) % size === 0) { - dp[newMask][j] = Math.min(dp[newMask][j], dp[mask][i]) - } else if(nums[j] > nums[i]) { - dp[newMask][j] = Math.min(dp[newMask][j], dp[mask][i] + nums[j] - nums[i]) - } - } - } - } - - const candidate = Math.min(...dp.at(-1)) - - return candidate === Infinity ? -1 : candidate - - function bitCnt(num) { - let res = 0 - while(num) { - if(num & 1) res++ - num = num >> 1 - } - - return res - } -}; - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -var minimumIncompatibility = function (nums, k) { - if (k === nums.length) { - return 0 - } - const counts = Array(nums.length + 1).fill(0) - for (let num of nums) { - counts[num]++ - if (counts[num] > k) { - return -1 - } - } - const size = nums.length / k - let ans = Number.MAX_VALUE - const backtracking = (groupIdx, index, sum, lowIndex, curIndex) => { - if (index === size) { - sum += curIndex - lowIndex - if (sum > ans) { - return - } - if (groupIdx === k - 1) { - ans = sum - return - } else { - groupIdx++ - index = 0 - } - } - if (index === 0) { - for (let i = 0; i < counts.length; i++) { - if (counts[i]) { - counts[i]-- - backtracking(groupIdx, index + 1, sum, i, i) - counts[i]++ - } - } - } else { - for (let i = curIndex + 1; i < counts.length; i++) { - if (counts[i]) { - counts[i]-- - backtracking(groupIdx, index + 1, sum, lowIndex, i) - counts[i]++ - } - } - } - } - backtracking(0, 0, 0, 0, 0) - return ans -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const minimumIncompatibility = function (nums, k) { - if (nums.length === k) return 0 - const maxInBucket = nums.length / k - const freqCount = {} - for (const n of nums) { - if (freqCount[n]) { - if (freqCount[n] === k) { - return -1 - } else { - freqCount[n]++ - } - } else { - freqCount[n] = 1 - } - } - const cache = {} - const allIndiciesUsedMask = 2 ** nums.length - 1 - const dfs = (usedIndicesBitMask) => { - if (usedIndicesBitMask === allIndiciesUsedMask) { - return 0 - } - if (cache[usedIndicesBitMask]) { - return cache[usedIndicesBitMask] - } - const valsToIndices = {} - for (let i = 0; i < nums.length; i++) { - const indexMask = 1 << i - if (usedIndicesBitMask & indexMask) continue - const value = nums[i] - if (!valsToIndices.hasOwnProperty(value)) { - valsToIndices[value] = i - } - } - const indicesAvailable = Object.values(valsToIndices) - let minIncompatibilityCost = Infinity - const combinations = createCombinations(indicesAvailable, maxInBucket) - for (const indices of combinations) { - let nextMask = usedIndicesBitMask - let minVal = Infinity - let maxVal = -Infinity - for (const index of indices) { - minVal = Math.min(minVal, nums[index]) - maxVal = Math.max(maxVal, nums[index]) - nextMask = nextMask | (1 << index) - } - const incompatibilityCost = maxVal - minVal - minIncompatibilityCost = Math.min( - minIncompatibilityCost, - dfs(nextMask) + incompatibilityCost - ) - } - return (cache[usedIndicesBitMask] = minIncompatibilityCost) - } - return dfs(0) -} - -function createCombinations(indices, len) { - const combinations = [] - if (indices.length < len) { - return combinations - } - const stack = [[[], 0]] - while (stack.length > 0) { - let [combi, i] = stack.pop() - for (; i < indices.length; i++) { - const combination = [...combi, indices[i]] - if (combination.length === len) { - combinations.push(combination) - } else { - stack.push([combination, i + 1]) - } - } - } - return combinations -} diff --git a/1681.minimum-incompatibility.js b/1681.minimum-incompatibility.js new file mode 100644 index 00000000..2730a2f0 --- /dev/null +++ b/1681.minimum-incompatibility.js @@ -0,0 +1,44 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const minimumIncompatibility = function(nums, k) { + const n = nums.length + const size = n / k + const mod = 1e9 + 7 + if(size === 1) return 0 + const limit = 1 << n + const dp = Array.from({ length: limit }, () => Array(16).fill(Infinity)) + for(let i = 0; i < n; i++) dp[1 << i][i] = 0 + + for(let mask = 0; mask < limit; mask++) { + for(let i = 0; i < n; i++) { + if((mask & (1 << i)) === 0) continue + for(let j = 0; j < n; j++) { + if((mask & (1 << j))) continue + const newMask = mask | (1 << j) + if(bitCnt(mask) % size === 0) { + dp[newMask][j] = Math.min(dp[newMask][j], dp[mask][i]) + } else if(nums[j] > nums[i]) { + dp[newMask][j] = Math.min(dp[newMask][j], dp[mask][i] + nums[j] - nums[i]) + } + } + } + } + + const candidate = Math.min(...dp.at(-1)) + + return candidate === Infinity ? -1 : candidate + + function bitCnt(num) { + let res = 0 + while(num) { + if(num & 1) res++ + num = num >> 1 + } + + return res + } +}; + diff --git a/1684-count-the-number-of-consistent-strings.js b/1684.count-the-number-of-consistent-strings.js similarity index 100% rename from 1684-count-the-number-of-consistent-strings.js rename to 1684.count-the-number-of-consistent-strings.js diff --git a/1685-sum-of-absolute-differences-in-a-sorted-array.js b/1685.sum-of-absolute-differences-in-a-sorted-array.js similarity index 100% rename from 1685-sum-of-absolute-differences-in-a-sorted-array.js rename to 1685.sum-of-absolute-differences-in-a-sorted-array.js diff --git a/1686-stone-game-vi.js b/1686.stone-game-vi.js similarity index 100% rename from 1686-stone-game-vi.js rename to 1686.stone-game-vi.js diff --git a/1687-delivering-boxes-from-storage-to-ports.js b/1687.delivering-boxes-from-storage-to-ports.js similarity index 100% rename from 1687-delivering-boxes-from-storage-to-ports.js rename to 1687.delivering-boxes-from-storage-to-ports.js diff --git a/1688-count-of-matches-in-tournament.js b/1688.count-of-matches-in-tournament.js similarity index 100% rename from 1688-count-of-matches-in-tournament.js rename to 1688.count-of-matches-in-tournament.js diff --git a/1689-partitioning-into-minimum-number-of-deci-binary-numbers.js b/1689.partitioning-into-minimum-number-of-deci-binary-numbers.js similarity index 100% rename from 1689-partitioning-into-minimum-number-of-deci-binary-numbers.js rename to 1689.partitioning-into-minimum-number-of-deci-binary-numbers.js diff --git a/169-majority-element.js b/169-majority-element.js deleted file mode 100755 index 91f38a94..00000000 --- a/169-majority-element.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const majorityElement = function(nums) { - const hash = {}; - nums.forEach(el => { - if (hash.hasOwnProperty(el)) { - hash[el] += 1; - } else { - hash[el] = 1; - } - }); - return Object.entries(hash) - .filter(el => el[1] > Math.floor(nums.length / 2)) - .map(el => +el[0]) - .sort((a, b) => b - a)[0]; -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const majorityElement = function(nums) { - let cnt = 1, candidate = nums[0] - for(let i = 1, n = nums.length; i < n; i++) { - if(candidate === nums[i]) cnt++ - else cnt-- - if(cnt === 0) { - cnt = 1 - candidate = nums[i] - } - } - return candidate -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const majorityElement = function(nums) { - let cnt = 1, candidate = nums[0] - for(let i = 1, n = nums.length; i < n; i++) { - if(cnt === 0) { - cnt = 1 - candidate = nums[i] - }else if(candidate === nums[i]) cnt++ - else cnt-- - } - return candidate -}; diff --git a/169.majority-element.js b/169.majority-element.js new file mode 100644 index 00000000..dcec473b --- /dev/null +++ b/169.majority-element.js @@ -0,0 +1,19 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const majorityElement = function(nums) { + const hash = {}; + nums.forEach(el => { + if (hash.hasOwnProperty(el)) { + hash[el] += 1; + } else { + hash[el] = 1; + } + }); + return Object.entries(hash) + .filter(el => el[1] > Math.floor(nums.length / 2)) + .map(el => +el[0]) + .sort((a, b) => b - a)[0]; +}; + diff --git a/1690-stone-game-vii.js b/1690.stone-game-vii.js similarity index 100% rename from 1690-stone-game-vii.js rename to 1690.stone-game-vii.js diff --git a/1691-maximum-height-by-stacking-cuboids.js b/1691-maximum-height-by-stacking-cuboids.js deleted file mode 100644 index 2dbc487d..00000000 --- a/1691-maximum-height-by-stacking-cuboids.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @param {number[][]} cuboids - * @return {number} - */ -var maxHeight = function (cuboids) { - let n = cuboids.length - for (let c of cuboids) { - c.sort((a, b) => a - b) - } - const { max } = Math - cuboids.sort(compare) - const f = Array(n) - let ans = 0 - for (let i = 0; i < n; i++) { - f[i] = cuboids[i][2] - for (let j = 0; j < i; j++) { - if ( - cuboids[i][0] <= cuboids[j][0] && - cuboids[i][1] <= cuboids[j][1] && - cuboids[i][2] <= cuboids[j][2] - ) - f[i] = max(f[i], f[j] + cuboids[i][2]) - } - ans = max(ans, f[i]) - } - return ans - function compare(a, b) { - if (a[0] != b[0]) return b[0] - a[0] - if (a[1] != b[1]) return b[1] - a[1] - return b[2] - a[2] - } -} - -// another - -/** - * @param {number[][]} cuboids - * @return {number} - */ -var maxHeight = function(cuboids) { - cuboids.forEach((cuboid) => cuboid.sort((a, b) => a - b)); - cuboids.sort((a, b) => { - if (a[0] !== b[0]) return b[0] - a[0]; - if (a[1] !== b[1]) return b[1] - a[1]; - return b[2] - a[2]; - }); - const n = cuboids.length; - const dp = Array(n).fill(0); - let res = 0; - for (let j = 0; j < n; ++j) { - dp[j] = cuboids[j][2]; - for (let i = 0; i < j; ++i) { - if (cuboids[i][0] >= cuboids[j][0] - && cuboids[i][1] >= cuboids[j][1] - && cuboids[i][2] >= cuboids[j][2] - ) { - dp[j] = Math.max(dp[j], dp[i] + cuboids[j][2]); - } - } - res = Math.max(res, dp[j]); - } - return res; -}; diff --git a/1691.maximum-height-by-stacking-cuboids.js b/1691.maximum-height-by-stacking-cuboids.js new file mode 100644 index 00000000..550cf8bf --- /dev/null +++ b/1691.maximum-height-by-stacking-cuboids.js @@ -0,0 +1,33 @@ +/** + * @param {number[][]} cuboids + * @return {number} + */ +var maxHeight = function (cuboids) { + let n = cuboids.length + for (let c of cuboids) { + c.sort((a, b) => a - b) + } + const { max } = Math + cuboids.sort(compare) + const f = Array(n) + let ans = 0 + for (let i = 0; i < n; i++) { + f[i] = cuboids[i][2] + for (let j = 0; j < i; j++) { + if ( + cuboids[i][0] <= cuboids[j][0] && + cuboids[i][1] <= cuboids[j][1] && + cuboids[i][2] <= cuboids[j][2] + ) + f[i] = max(f[i], f[j] + cuboids[i][2]) + } + ans = max(ans, f[i]) + } + return ans + function compare(a, b) { + if (a[0] != b[0]) return b[0] - a[0] + if (a[1] != b[1]) return b[1] - a[1] + return b[2] - a[2] + } +} + diff --git a/1694-reformat-phone-number.js b/1694.reformat-phone-number.js similarity index 100% rename from 1694-reformat-phone-number.js rename to 1694.reformat-phone-number.js diff --git a/1695-maximum-erasure-value.js b/1695.maximum-erasure-value.js similarity index 100% rename from 1695-maximum-erasure-value.js rename to 1695.maximum-erasure-value.js diff --git a/1696-jump-game-vi.js b/1696.jump-game-vi.js similarity index 100% rename from 1696-jump-game-vi.js rename to 1696.jump-game-vi.js diff --git a/1697-checking-existence-of-edge-length-limited-paths.js b/1697-checking-existence-of-edge-length-limited-paths.js deleted file mode 100644 index 72ef93c5..00000000 --- a/1697-checking-existence-of-edge-length-limited-paths.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} edgeList - * @param {number[][]} queries - * @return {boolean[]} - */ -const distanceLimitedPathsExist = function (n, edgeList, queries) { - edgeList.sort((a, b) => a[2] - b[2]) - const m = queries.length - const res = Array(m).fill(false) - const order = Array(m).fill(0) - for (let i = 0; i < m; ++i) order[i] = i - order.sort((i, j) => queries[i][2] - queries[j][2]) - const uf = new UF(n) - let idx = 0 - for (let i of order) { - const limit = queries[i][2] - while (idx < edgeList.length && edgeList[idx][2] < limit) { - const [u, v] = edgeList[idx] - uf.union(u, v) - idx++ - } - const [u0, v0] = queries[i] - if (uf.find(u0) === uf.find(v0)) res[i] = true - } - return res -} - -class UF { - constructor(n) { - this.root = Array(n) - .fill(null) - .map((_, i) => i) - } - find(x) { - if (this.root[x] !== x) { - this.root[x] = this.find(this.root[x]) - } - return this.root[x] - } - union(x, y) { - const xr = this.find(x) - const yr = this.find(y) - this.root[yr] = xr - } -} - - -// another - -/** - * @param {number} n - * @param {number[][]} edgeList - * @param {number[][]} queries - * @return {boolean[]} - */ -const distanceLimitedPathsExist = function (n, edgeList, queries) { - edgeList.sort((a, b) => a[2] - b[2]) - const m = queries.length - const ans = Array(m).fill(false) - const order = Array(m).fill(0) - for (let i = 0; i < m; ++i) order[i] = i - order.sort((i, j) => queries[i][2] - queries[j][2]) - const uf = new UnionFind(n) - let idx = 0 - for (let i of order) { - const limit = queries[i][2] - while (idx < edgeList.length && edgeList[idx][2] < limit) { - const [u, v] = edgeList[idx] - uf.union(u, v) - idx++ - } - const [u0, v0] = queries[i] - if (uf.find(u0) === uf.find(v0)) ans[i] = true - } - return ans -} -class UnionFind { - constructor(n) { - this.parents = Array(n) - .fill(0) - .map((e, i) => i) - this.ranks = Array(n).fill(0) - } - root(x) { - while (x !== this.parents[x]) { - this.parents[x] = this.parents[this.parents[x]] - x = this.parents[x] - } - return x - } - find(x) { - return this.root(x) - } - check(x, y) { - return this.root(x) === this.root(y) - } - union(x, y) { - const [rx, ry] = [this.find(x), this.find(y)] - if (this.ranks[rx] >= this.ranks[ry]) { - this.parents[ry] = rx - this.ranks[rx] += this.ranks[ry] - } else if (this.ranks[ry] > this.ranks[rx]) { - this.parents[rx] = ry - this.ranks[ry] += this.ranks[rx] - } - } -} diff --git a/1697.checking-existence-of-edge-length-limited-paths.js b/1697.checking-existence-of-edge-length-limited-paths.js new file mode 100644 index 00000000..8c4d81fe --- /dev/null +++ b/1697.checking-existence-of-edge-length-limited-paths.js @@ -0,0 +1,48 @@ +/** + * @param {number} n + * @param {number[][]} edgeList + * @param {number[][]} queries + * @return {boolean[]} + */ +const distanceLimitedPathsExist = function (n, edgeList, queries) { + edgeList.sort((a, b) => a[2] - b[2]) + const m = queries.length + const res = Array(m).fill(false) + const order = Array(m).fill(0) + for (let i = 0; i < m; ++i) order[i] = i + order.sort((i, j) => queries[i][2] - queries[j][2]) + const uf = new UF(n) + let idx = 0 + for (let i of order) { + const limit = queries[i][2] + while (idx < edgeList.length && edgeList[idx][2] < limit) { + const [u, v] = edgeList[idx] + uf.union(u, v) + idx++ + } + const [u0, v0] = queries[i] + if (uf.find(u0) === uf.find(v0)) res[i] = true + } + return res +} + +class UF { + constructor(n) { + this.root = Array(n) + .fill(null) + .map((_, i) => i) + } + find(x) { + if (this.root[x] !== x) { + this.root[x] = this.find(this.root[x]) + } + return this.root[x] + } + union(x, y) { + const xr = this.find(x) + const yr = this.find(y) + this.root[yr] = xr + } +} + + diff --git a/1698-number-of-distinct-substrings-in-a-string.js b/1698-number-of-distinct-substrings-in-a-string.js deleted file mode 100644 index f67060eb..00000000 --- a/1698-number-of-distinct-substrings-in-a-string.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const countDistinct = function(s) { - const set = new Set() - for(let i = 0, len = s.length; i < len; i++) { - for(let j = i + 1; j <= len; j++) { - set.add(s.slice(i, j)) - } - } - - return set.size -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const countDistinct = function (s, count = 0) { - const root = new Trie() - const N = s.length - for (let i = 0; i < N; i++) { - let node = root - for (let j = i; j < N; j++) { - const c = s[j] - if (!node.children.has(c)) { - node.children.set(c, new Trie()) - count++ - } - node = node.children.get(c) - } - } - return count -} -class Trie { - constructor() { - this.children = new Map() - } -} diff --git a/1698.number-of-distinct-substrings-in-a-string.js b/1698.number-of-distinct-substrings-in-a-string.js new file mode 100644 index 00000000..cd48d3b1 --- /dev/null +++ b/1698.number-of-distinct-substrings-in-a-string.js @@ -0,0 +1,15 @@ +/** + * @param {string} s + * @return {number} + */ +const countDistinct = function(s) { + const set = new Set() + for(let i = 0, len = s.length; i < len; i++) { + for(let j = i + 1; j <= len; j++) { + set.add(s.slice(i, j)) + } + } + + return set.size +}; + diff --git a/17-letter-combinations-of-a-phone-number.js b/17-letter-combinations-of-a-phone-number.js deleted file mode 100755 index 0601efe0..00000000 --- a/17-letter-combinations-of-a-phone-number.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @param {string} digits - * @return {string[]} - */ -const letterCombinations = function(digits) { - if (digits === "") { - return []; - } - const charMap = { - 2: ["a", "b", "c"], - 3: ["d", "e", "f"], - 4: ["g", "h", "i"], - 5: ["j", "k", "l"], - 6: ["m", "n", "o"], - 7: ["p", "q", "r", "s"], - 8: ["t", "u", "v"], - 9: ["w", "x", "y", "z"] - }; - const res = []; - const matrix = []; - for (let i = 0; i < digits.length; i++) { - matrix.push(charMap[digits.charAt(i)]); - } - let tmp = matrix[0]; - for (let j = 1; j < matrix.length; j++) { - tmp = helper(matrix, j, tmp); - } - return tmp; -}; -function helper(matrix, rowIdx, arr) { - const res = []; - for (let i = 0; i < arr.length; i++) { - const preStr = arr[i]; - for (let j = 0; j < matrix[rowIdx].length; j++) { - res.push(`${preStr}${matrix[rowIdx][j]}`); - } - } - return res; -} diff --git a/17.letter-combinations-of-a-phone-number.js b/17.letter-combinations-of-a-phone-number.js new file mode 100644 index 00000000..4512fcb1 --- /dev/null +++ b/17.letter-combinations-of-a-phone-number.js @@ -0,0 +1,39 @@ +/** + * @param {string} digits + * @return {string[]} + */ +const letterCombinations = function(digits) { + if (digits === "") { + return []; + } + const charMap = { + 2: ["a", "b", "c"], + 3: ["d", "e", "f"], + 4: ["g", "h", "i"], + 5: ["j", "k", "l"], + 6: ["m", "n", "o"], + 7: ["p", "q", "r", "s"], + 8: ["t", "u", "v"], + 9: ["w", "x", "y", "z"] + }; + const res = []; + const matrix = []; + for (let i = 0; i < digits.length; i++) { + matrix.push(charMap[digits.charAt(i)]); + } + let tmp = matrix[0]; + for (let j = 1; j < matrix.length; j++) { + tmp = helper(matrix, j, tmp); + } + return tmp; +}; +function helper(matrix, rowIdx, arr) { + const res = []; + for (let i = 0; i < arr.length; i++) { + const preStr = arr[i]; + for (let j = 0; j < matrix[rowIdx].length; j++) { + res.push(`${preStr}${matrix[rowIdx][j]}`); + } + } + return res; +} diff --git a/170-two-sum-iii-data-structure-design.js b/170.two-sum-iii-data-structure-design.js similarity index 100% rename from 170-two-sum-iii-data-structure-design.js rename to 170.two-sum-iii-data-structure-design.js diff --git a/1700-number-of-students-unable-to-eat-lunch.js b/1700.number-of-students-unable-to-eat-lunch.js similarity index 100% rename from 1700-number-of-students-unable-to-eat-lunch.js rename to 1700.number-of-students-unable-to-eat-lunch.js diff --git a/1701-average-waiting-time.js b/1701.average-waiting-time.js similarity index 100% rename from 1701-average-waiting-time.js rename to 1701.average-waiting-time.js diff --git a/1703-maximum-binary-string-after-change.js b/1703-maximum-binary-string-after-change.js deleted file mode 100644 index 903e97d4..00000000 --- a/1703-maximum-binary-string-after-change.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const minMoves = function (nums, k) { - const pos = [], - pre = [] - const n = nums.length, - { min, floor: fl } = Math - for (let i = 0; i < n; i++) { - if (nums[i] === 1) pos.push(i) - } - let res = Infinity - - pre.push(0) - for (let i = 0, len = pos.length; i < len; i++) { - pre.push(pre[i] + pos[i]) - } - - for (let i = fl(k / 2), limit = pos.length - fl((k - 1) / 2); i > 0, - r = k - l - 1 - for (let i = 0; i + k <= n; ++i) { - const m = i + ((k / 2) >>> 0) - const cur = - pos[m] * l - - (sums[m - 1] - sums[i] + pos[i]) - - pos[m] * r + - sums[i + k - 1] - - sums[m] - res = Math.min(cur, res) - } - return res -} diff --git a/1703.maximum-binary-string-after-change.js b/1703.maximum-binary-string-after-change.js new file mode 100644 index 00000000..bb31a65a --- /dev/null +++ b/1703.maximum-binary-string-after-change.js @@ -0,0 +1,33 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const minMoves = function (nums, k) { + const pos = [], + pre = [] + const n = nums.length, + { min, floor: fl } = Math + for (let i = 0; i < n; i++) { + if (nums[i] === 1) pos.push(i) + } + let res = Infinity + + pre.push(0) + for (let i = 0, len = pos.length; i < len; i++) { + pre.push(pre[i] + pos[i]) + } + + for (let i = fl(k / 2), limit = pos.length - fl((k - 1) / 2); i a - b) - const numOfBits = 1 + Math.floor(Math.log2(nums[nums.length - 1])) - const maxMask = (1 << numOfBits) - 1 - return queries.map(([x, m]) => query(x, m)) - function query(x, m) { - if (m < nums[0]) return -1 - let l = 0, - r = nums.length - while (l < r) { - let mid = l + ((r - l) >> 1) - if (m < nums[mid])r = mid - else l = mid + 1 - } - r-- - l = 0 - let ans = x & ~maxMask - for (let bit = numOfBits - 1; bit >= 0; bit--) { - const mask = 1 << bit - if (x & mask) { - if ((nums[l] & mask) === 0) { - ans |= 1 << bit - r = search(l, r, mask) - 1 - } - } else { - if (nums[r] & mask) { - ans |= 1 << bit - l = search(l, r, mask) - } - } - } - return ans - } - function search(l, r, mask) { - while (l <= r) { - const m = l + ((r - l) >> 1) - if ((nums[m] & mask) === 0) l = m + 1 - else r = m - 1 - } - return l - } -} - - -// another - -/** - * @param {number[]} nums - * @param {number[][]} queries - * @return {number[]} - */ -const maximizeXor = function (nums, queries) { - const n = queries.length - const result = new Array(n) - const trie = [null, null] - for (let num of nums) { - let node = trie - for (let i = 30; i >= 0; i--) { - const b = 1 << i - if (b & num) { - if (!node[1]) node[1] = [null, null] - node = node[1] - } else { - if (!node[0]) node[0] = [null, null] - node = node[0] - } - } - } - const min = Math.min(...nums) - const dfs = (node, num, i, val, max) => { - if (!node || val > max) return -1 - if (i === -1) return val - const bit = 1 << i - i-- - if (bit > max) return dfs(node[0], num, i, val, max) - if (num & bit) { - let x = dfs(node[0], num, i, val, max) - if (x > -1) return x - return dfs(node[1], num, i, val | bit, max) - } else { - let y = dfs(node[1], num, i, val | bit, max) - if (y > -1) return y - return dfs(node[0], num, i, val, max) - } - } - - for (let i = 0; i < n; i++) { - const [num, max] = queries[i] - if (max < min) { - result[i] = -1 - continue - } - result[i] = dfs(trie, num, 30, 0, max) ^ num - } - return result -} diff --git a/1707.maximum-xor-with-an-element-from-array.js b/1707.maximum-xor-with-an-element-from-array.js new file mode 100644 index 00000000..d17a2968 --- /dev/null +++ b/1707.maximum-xor-with-an-element-from-array.js @@ -0,0 +1,49 @@ +/** + * @param {number[]} nums + * @param {number[][]} queries + * @return {number[]} + */ +const maximizeXor = function (nums, queries) { + nums.sort((a, b) => a - b) + const numOfBits = 1 + Math.floor(Math.log2(nums[nums.length - 1])) + const maxMask = (1 << numOfBits) - 1 + return queries.map(([x, m]) => query(x, m)) + function query(x, m) { + if (m < nums[0]) return -1 + let l = 0, + r = nums.length + while (l < r) { + let mid = l + ((r - l) >> 1) + if (m < nums[mid])r = mid + else l = mid + 1 + } + r-- + l = 0 + let ans = x & ~maxMask + for (let bit = numOfBits - 1; bit >= 0; bit--) { + const mask = 1 << bit + if (x & mask) { + if ((nums[l] & mask) === 0) { + ans |= 1 << bit + r = search(l, r, mask) - 1 + } + } else { + if (nums[r] & mask) { + ans |= 1 << bit + l = search(l, r, mask) + } + } + } + return ans + } + function search(l, r, mask) { + while (l <= r) { + const m = l + ((r - l) >> 1) + if ((nums[m] & mask) === 0) l = m + 1 + else r = m - 1 + } + return l + } +} + + diff --git a/1708-largest-subarray-length-k.js b/1708.largest-subarray-length-k.js similarity index 100% rename from 1708-largest-subarray-length-k.js rename to 1708.largest-subarray-length-k.js diff --git a/171-excel-sheet-column-number.js b/171-excel-sheet-column-number.js deleted file mode 100755 index 2beff2fd..00000000 --- a/171-excel-sheet-column-number.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const titleToNumber = function(s) { - const arr = s.split(""); - const len = arr.length; - const uac = "A".charCodeAt(0); - return arr.reduce((ac, el, idx, arr) => { - return ac + Math.pow(26, len - idx - 1) * (`${el}`.charCodeAt(0) - uac + 1); - }, 0); -}; - -console.log(titleToNumber("A")); -console.log(titleToNumber("AA")); - -// another - -/** - * @param {string} s - * @return {number} - */ -const titleToNumber = function(s) { - let result = 0; - const A = 'A'.charCodeAt(0) - for (let i = 0; i < s.length; result = result * 26 + (s.charCodeAt(i) - A + 1), i++); - return result; -}; diff --git a/171.excel-sheet-column-number.js b/171.excel-sheet-column-number.js new file mode 100644 index 00000000..1b4d62d1 --- /dev/null +++ b/171.excel-sheet-column-number.js @@ -0,0 +1,16 @@ +/** + * @param {string} s + * @return {number} + */ +const titleToNumber = function(s) { + const arr = s.split(""); + const len = arr.length; + const uac = "A".charCodeAt(0); + return arr.reduce((ac, el, idx, arr) => { + return ac + Math.pow(26, len - idx - 1) * (`${el}`.charCodeAt(0) - uac + 1); + }, 0); +}; + +console.log(titleToNumber("A")); +console.log(titleToNumber("AA")); + diff --git a/1710-maximum-units-on-a-truck.js b/1710.maximum-units-on-a-truck.js similarity index 100% rename from 1710-maximum-units-on-a-truck.js rename to 1710.maximum-units-on-a-truck.js diff --git a/1711-count-good-meals.js b/1711.count-good-meals.js similarity index 100% rename from 1711-count-good-meals.js rename to 1711.count-good-meals.js diff --git a/1712-ways-to-split-array-into-three-subarrays.js b/1712.ways-to-split-array-into-three-subarrays.js similarity index 100% rename from 1712-ways-to-split-array-into-three-subarrays.js rename to 1712.ways-to-split-array-into-three-subarrays.js diff --git a/1713-minimum-operations-to-make-a-subsequence.js b/1713-minimum-operations-to-make-a-subsequence.js deleted file mode 100644 index 72b75060..00000000 --- a/1713-minimum-operations-to-make-a-subsequence.js +++ /dev/null @@ -1,141 +0,0 @@ -/** - * @param {number[]} target - * @param {number[]} arr - * @return {number} - */ -const minOperations = function(target, arr) { - const hash = {} - for (let i = 0, n = target.length; i < n; i++) { - hash[target[i]] = i - } - const stk = [] - for(let e of arr) { - if(hash[e] == null) continue - let l = 0, r = stk.length - while(l < r) { - const mid = l + (~~((r - l) / 2)) - if(stk[mid] < hash[e]) l = mid + 1 - else r = mid - } - stk[l] = hash[e] - } - return target.length - stk.length -}; - -// another - -/** - * @param {number[]} target - * @param {number[]} arr - * @return {number} - */ -const minOperations = function (target, arr) { - let length1 = target.length, - length2 = arr.length - const targetMap = new Map() - for (let i = 0; i < length1; i++) targetMap.set(target[i], i) - const list = new Array() - for (let i = 0; i < length2; i++) { - let num = arr[i] - if (targetMap.has(num)) list.push(targetMap.get(num)) - } - let longestIncreasing = lengthOfLIS(list) - return target.length - longestIncreasing - - function lengthOfLIS(list) { - let length = 1, - size = list.length - if (size == 0) return 0 - const d = new Array(size + 1).fill(0) - d[length] = list[0] - for (let i = 1; i < size; ++i) { - if (list[i] > d[length]) { - d[++length] = list[i] - } else { - let left = 1, - right = length, - pos = 0 - while (left <= right) { - let mid = (left + right) >> 1 - if (d[mid] < list[i]) { - pos = mid - left = mid + 1 - } else { - right = mid - 1 - } - } - d[pos + 1] = list[i] - } - } - return length - } -} - -// another - -/** - * @param {number[]} target - * @param {number[]} arr - * @return {number} - */ -const minOperations = function(target, arr) { - const map = new Map() - for(let i = 0, len = target.length; i < len; i++) { - map.set(target[i], i) - } - const stack = [] - for(let a of arr) { - if(!map.has(a)) continue - if(stack.length === 0 || map.get(a) > stack[stack.length - 1]) { - stack.push(map.get(a)) - continue - } - let left = 0, right = stack.length - 1, mid - while(left < right) { - mid = left + ((right - left) >> 1) - if(stack[mid] < map.get(a)) left = mid + 1 - else right = mid - } - stack[left] = map.get(a) - } - - return target.length - stack.length -}; - -// another - -/** - * @param {number[]} target - * @param {number[]} arr - * @return {number} - */ -const minOperations = function(target, arr) { - const hash = {} - for(let i = 0, n = target.length; i < n; i++) { - hash[target[i]] = i - } - const stack = [] - - for(let e of arr) { - if(hash[e] == null) continue - const cur = hash[e] - if(stack.length && cur > stack[stack.length - 1]) { - stack.push(cur) - continue - } - - let l = 0, r = stack.length - 1 - - while(l < r) { - const mid = ~~((l + r) / 2) - if(stack[mid] < cur) { - l = mid + 1 - } else r = mid - } - - stack[l] = cur - - } - - return target.length - stack.length -}; diff --git a/1713.minimum-operations-to-make-a-subsequence.js b/1713.minimum-operations-to-make-a-subsequence.js new file mode 100644 index 00000000..0b5817c7 --- /dev/null +++ b/1713.minimum-operations-to-make-a-subsequence.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} target + * @param {number[]} arr + * @return {number} + */ +const minOperations = function(target, arr) { + const hash = {} + for (let i = 0, n = target.length; i < n; i++) { + hash[target[i]] = i + } + const stk = [] + for(let e of arr) { + if(hash[e] == null) continue + let l = 0, r = stk.length + while(l < r) { + const mid = l + (~~((r - l) / 2)) + if(stk[mid] < hash[e]) l = mid + 1 + else r = mid + } + stk[l] = hash[e] + } + return target.length - stk.length +}; + diff --git a/1714-sum-of-special-evenly-spaced-elements-in-array.js b/1714.sum-of-special-evenly-spaced-elements-in-array.js similarity index 100% rename from 1714-sum-of-special-evenly-spaced-elements-in-array.js rename to 1714.sum-of-special-evenly-spaced-elements-in-array.js diff --git a/1716-calculate-money-in-leetcode-bank.js b/1716.calculate-money-in-leetcode-bank.js similarity index 100% rename from 1716-calculate-money-in-leetcode-bank.js rename to 1716.calculate-money-in-leetcode-bank.js diff --git a/1717-maximum-score-from-removing-substrings.js b/1717-maximum-score-from-removing-substrings.js deleted file mode 100644 index 63030915..00000000 --- a/1717-maximum-score-from-removing-substrings.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @param {string} s - * @param {number} x - * @param {number} y - * @return {number} - */ -const maximumGain = function (s, x, y) { - let sb = s.split('') - if (x > y) { - return remove(sb, 'ab', x) + remove(sb, 'ba', y) - } - return remove(sb, 'ba', y) + remove(sb, 'ab', x) - function remove(sb, pattern, point) { - let i = 0, - res = 0 - for (let j = 0; j < sb.length; j++) { - sb[i++] = sb[j] - if ( - i > 1 && - sb[i - 2] == pattern.charAt(0) && - sb[i - 1] == pattern.charAt(1) - ) { - i -= 2 - res += point - } - } - sb.splice(i) - return res - } -} - -// another - -/** - * @param {string} s - * @param {number} x - * @param {number} y - * @return {number} - */ -const maximumGain = function (s, x, y) { - return Math.max(go(s, x, y, 'a', 'b'), go(s, y, x, 'b', 'a')) -} - -function go(s, x, y, a, b) { - const n = s.length - const st = new Array(n) - let sc = 0 - let p = 0 - for (let c of s) { - if (p - 1 >= 0 && st[p - 1] === a && c === b) { - sc += x - p-- - } else { - st[p++] = c - } - } - const st2 = new Array(p) - let q = 0 - for (let u = 0; u < p; u++) { - let c = st[u] - if (q - 1 >= 0 && st2[q - 1] === b && c === a) { - sc += y - q-- - } else { - st2[q++] = c - } - } - return sc -} diff --git a/1717.maximum-score-from-removing-substrings.js b/1717.maximum-score-from-removing-substrings.js new file mode 100644 index 00000000..e8488f75 --- /dev/null +++ b/1717.maximum-score-from-removing-substrings.js @@ -0,0 +1,31 @@ +/** + * @param {string} s + * @param {number} x + * @param {number} y + * @return {number} + */ +const maximumGain = function (s, x, y) { + let sb = s.split('') + if (x > y) { + return remove(sb, 'ab', x) + remove(sb, 'ba', y) + } + return remove(sb, 'ba', y) + remove(sb, 'ab', x) + function remove(sb, pattern, point) { + let i = 0, + res = 0 + for (let j = 0; j < sb.length; j++) { + sb[i++] = sb[j] + if ( + i > 1 && + sb[i - 2] == pattern.charAt(0) && + sb[i - 1] == pattern.charAt(1) + ) { + i -= 2 + res += point + } + } + sb.splice(i) + return res + } +} + diff --git a/1718-construct-the-lexicographically-largest-valid-sequence.js b/1718.construct-the-lexicographically-largest-valid-sequence.js similarity index 100% rename from 1718-construct-the-lexicographically-largest-valid-sequence.js rename to 1718.construct-the-lexicographically-largest-valid-sequence.js diff --git a/1719-number-of-ways-to-reconstruct-a-tree.js b/1719.number-of-ways-to-reconstruct-a-tree.js similarity index 100% rename from 1719-number-of-ways-to-reconstruct-a-tree.js rename to 1719.number-of-ways-to-reconstruct-a-tree.js diff --git a/172-factorial-trailing-zeroes.js b/172.factorial-trailing-zeroes.js similarity index 100% rename from 172-factorial-trailing-zeroes.js rename to 172.factorial-trailing-zeroes.js diff --git a/1720-decode-xored-array.js b/1720.decode-xored-array.js similarity index 100% rename from 1720-decode-xored-array.js rename to 1720.decode-xored-array.js diff --git a/1721-swapping-nodes-in-a-linked-list.js b/1721.swapping-nodes-in-a-linked-list.js similarity index 100% rename from 1721-swapping-nodes-in-a-linked-list.js rename to 1721.swapping-nodes-in-a-linked-list.js diff --git a/1722-minimize-hamming-distance-after-swap-operations.js b/1722.minimize-hamming-distance-after-swap-operations.js similarity index 100% rename from 1722-minimize-hamming-distance-after-swap-operations.js rename to 1722.minimize-hamming-distance-after-swap-operations.js diff --git a/1723-find-minimum-time-to-finish-all-jobs.js b/1723-find-minimum-time-to-finish-all-jobs.js deleted file mode 100644 index 94a8c01b..00000000 --- a/1723-find-minimum-time-to-finish-all-jobs.js +++ /dev/null @@ -1,151 +0,0 @@ -/** - * @param {number[]} jobs - * @param {number} k - * @return {number} - */ -const minimumTimeRequired = function(jobs, k) { - const n = jobs.length - const limit = 1 << n - const sum = Array(limit).fill(0) - const { min, max } = Math - - for(let mask = 0; mask < limit; mask++) { - for(let i = 0; i < n; i++) { - if((mask & (1 << i))) sum[mask] += jobs[i] - } - } - - const dp = Array.from({ length: k + 1 }, () => Array(limit).fill(0)) - for(let i = 0; i < limit; i++) dp[1][i] = sum[i] - - for(let i = 2; i <= k; i++) { - for(let mask = 0; mask < limit; mask++) { - dp[i][mask] = dp[i - 1][mask] - for(let sub = mask; sub; sub = (sub - 1) & mask) { - dp[i][mask] = min(dp[i][mask], max(dp[i - 1][mask - sub], sum[sub])) - } - } - } - - return dp[k][limit - 1] -}; - -// another - -/** - * @param {number[]} jobs - * @param {number} k - * @return {number} - */ -const minimumTimeRequired = function(jobs, k) { - const workers = Array(k).fill(0) - let res = Infinity - const n = jobs.length - - dfs(0) - - return res - - function dfs(idx) { - if(idx === n) { - res = Math.min(res, Math.max(...workers)) - return - } - const e = jobs[idx] - for(let i = 0; i < k; i++) { - if(workers[i] + e >= res) continue - workers[i] += e - dfs(idx + 1) - workers[i] -= e - if(workers[i] === 0) break - } - } -}; - -// another - -/** - * @param {number[]} jobs - * @param {number} k - * @return {number} - */ -const minimumTimeRequired = function (jobs, k) { - if (jobs.length <= k) { - return Math.max(...jobs) - } - - // create a store to hold the number of hours each worker worked - const workers = new Array(k).fill(0) - - let minLongestWorkingTime = Infinity - const dfs = (i) => { - if (i === jobs.length) { - // if we assigned all the jobs, see if we have a better result - minLongestWorkingTime = Math.min( - minLongestWorkingTime, - Math.max(...workers) - ) - return - } - const lengthOfWork = jobs[i] - - for (let worker = 0; worker < k; worker++) { - workers[worker] += lengthOfWork - - // if this combination is has a chance of decreasing our - // answer, try it, otherwise skip it to save on time. - if (workers[worker] <= minLongestWorkingTime) { - dfs(i + 1) - } - workers[worker] -= lengthOfWork - - // We want to minimize the width of the tree - // so if the worker has gotten their first job - // don't try any workers after this worker. - // All other workers after this worker will be 0 as well - // so the combination is exactly the same. - if (workers[worker] === 0) break - } - } - - dfs(0) - return minLongestWorkingTime -} - -// another - -/** - * @param {number[]} jobs - * @param {number} k - * @return {number} - */ -const minimumTimeRequired = function(jobs, k) { - return solution(jobs, k) -}; - -function solution(jobs, k) { - const n = jobs.length - let res = Infinity, arr = Array(k).fill(0) - - let start = 0 - bt(0) - return res - - function bt(idx) { - start++ - if(idx === n) { - res = Math.min(res, Math.max(...arr)) - return - } - const visited = new Set() - for(let j = start; j < start + k; j++) { - const i = j % k - if(visited.has(arr[i])) continue - if(arr[i] + jobs[idx] > res) continue - visited.add(arr[i]) - arr[i] += jobs[idx] - bt(idx + 1) - arr[i] -= jobs[idx] - } - } -} diff --git a/1723.find-minimum-time-to-finish-all-jobs.js b/1723.find-minimum-time-to-finish-all-jobs.js new file mode 100644 index 00000000..f93e38cd --- /dev/null +++ b/1723.find-minimum-time-to-finish-all-jobs.js @@ -0,0 +1,32 @@ +/** + * @param {number[]} jobs + * @param {number} k + * @return {number} + */ +const minimumTimeRequired = function(jobs, k) { + const n = jobs.length + const limit = 1 << n + const sum = Array(limit).fill(0) + const { min, max } = Math + + for(let mask = 0; mask < limit; mask++) { + for(let i = 0; i < n; i++) { + if((mask & (1 << i))) sum[mask] += jobs[i] + } + } + + const dp = Array.from({ length: k + 1 }, () => Array(limit).fill(0)) + for(let i = 0; i < limit; i++) dp[1][i] = sum[i] + + for(let i = 2; i <= k; i++) { + for(let mask = 0; mask < limit; mask++) { + dp[i][mask] = dp[i - 1][mask] + for(let sub = mask; sub; sub = (sub - 1) & mask) { + dp[i][mask] = min(dp[i][mask], max(dp[i - 1][mask - sub], sum[sub])) + } + } + } + + return dp[k][limit - 1] +}; + diff --git a/1724-checking-existence-of-edge-length-limited-paths-ii.js b/1724.checking-existence-of-edge-length-limited-paths-ii.js similarity index 100% rename from 1724-checking-existence-of-edge-length-limited-paths-ii.js rename to 1724.checking-existence-of-edge-length-limited-paths-ii.js diff --git a/1725-number-of-rectangles-that-can-form-the-largest-square.js b/1725.number-of-rectangles-that-can-form-the-largest-square.js similarity index 100% rename from 1725-number-of-rectangles-that-can-form-the-largest-square.js rename to 1725.number-of-rectangles-that-can-form-the-largest-square.js diff --git a/1726-tuple-with-same-product.js b/1726.tuple-with-same-product.js similarity index 100% rename from 1726-tuple-with-same-product.js rename to 1726.tuple-with-same-product.js diff --git a/1727-largest-submatrix-with-rearrangements.js b/1727.largest-submatrix-with-rearrangements.js similarity index 100% rename from 1727-largest-submatrix-with-rearrangements.js rename to 1727.largest-submatrix-with-rearrangements.js diff --git a/1728-cat-and-mouse-ii.js b/1728.cat-and-mouse-ii.js similarity index 100% rename from 1728-cat-and-mouse-ii.js rename to 1728.cat-and-mouse-ii.js diff --git a/173-binary-search-tree-iterator.js b/173-binary-search-tree-iterator.js deleted file mode 100644 index 92044020..00000000 --- a/173-binary-search-tree-iterator.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - */ -const BSTIterator = function(root) { - this.root = root; - this.stack = []; -}; - -/** - * @return the next smallest number - * @return {number} - */ -BSTIterator.prototype.next = function() { - while (this.root) { - this.stack.push(this.root); - this.root = this.root.left; - } - this.root = this.stack.pop(); - const result = this.root.val; - this.root = this.root.right; - return result; -}; - -/** - * @return whether we have a next smallest number - * @return {boolean} - */ -BSTIterator.prototype.hasNext = function() { - return this.root || this.stack.length; -}; - -/** - * Your BSTIterator object will be instantiated and called as such: - * var obj = new BSTIterator(root) - * var param_1 = obj.next() - * var param_2 = obj.hasNext() - */ - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - */ -const BSTIterator = function(root) { - this.generator = dfsGenerator(root) - this.root = root - this.nextSmall = this.generator.next().value -} -function* dfsGenerator(root) { - if (root === null) return - const stack = [] - let current = root - while (true) { - if (current) { - stack.push(current) - current = current.left - } else if (stack.length) { - const top = stack.pop() - yield top.val - current = top.right - } else { - break - } - } -} - -/** - * @return the next smallest number - * @return {number} - */ -BSTIterator.prototype.next = function() { - const smallReturn = this.nextSmall - this.nextSmall = this.generator.next().value - return smallReturn -} - -/** - * @return whether we have a next smallest number - * @return {boolean} - */ -BSTIterator.prototype.hasNext = function() { - return this.nextSmall !== undefined ? true : false -} - -/** - * Your BSTIterator object will be instantiated and called as such: - * var obj = new BSTIterator(root) - * var param_1 = obj.next() - * var param_2 = obj.hasNext() - */ - - diff --git a/173.binary-search-tree-iterator.js b/173.binary-search-tree-iterator.js new file mode 100644 index 00000000..025e771b --- /dev/null +++ b/173.binary-search-tree-iterator.js @@ -0,0 +1,45 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + */ +const BSTIterator = function(root) { + this.root = root; + this.stack = []; +}; + +/** + * @return the next smallest number + * @return {number} + */ +BSTIterator.prototype.next = function() { + while (this.root) { + this.stack.push(this.root); + this.root = this.root.left; + } + this.root = this.stack.pop(); + const result = this.root.val; + this.root = this.root.right; + return result; +}; + +/** + * @return whether we have a next smallest number + * @return {boolean} + */ +BSTIterator.prototype.hasNext = function() { + return this.root || this.stack.length; +}; + +/** + * Your BSTIterator object will be instantiated and called as such: + * var obj = new BSTIterator(root) + * var param_1 = obj.next() + * var param_2 = obj.hasNext() + */ + diff --git a/1732-find-the-highest-altitude.js b/1732.find-the-highest-altitude.js similarity index 100% rename from 1732-find-the-highest-altitude.js rename to 1732.find-the-highest-altitude.js diff --git a/1733-minimum-number-of-people-to-teach.js b/1733.minimum-number-of-people-to-teach.js similarity index 100% rename from 1733-minimum-number-of-people-to-teach.js rename to 1733.minimum-number-of-people-to-teach.js diff --git a/1734-decode-xored-permutation.js b/1734-decode-xored-permutation.js deleted file mode 100644 index 1ae0f396..00000000 --- a/1734-decode-xored-permutation.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @param {number[]} encoded - * @return {number[]} - */ -const decode = function(encoded) { - const n = encoded.length + 1 - let xor = 0 - for(let i = 1; i <= n; i++) xor ^= i - for(let i = 1; i < n - 1; i += 2) xor ^= encoded[i] - const res = [xor] - let pre = xor - for(let i = 0; i < n - 1; i++) { - res.push(encoded[i] ^ pre) - pre = res[res.length - 1] - } - - return res -}; - -// another - -/** - * @param {number[]} encoded - * @return {number[]} - */ -const decode = function(encoded) { - let a = 0 - const n = encoded.length + 1 - for(let i = 0; i <= n; i++) { - a ^= i - if(i < n && i % 2 === 1) a ^= encoded[i] - } - const res = [a] - for(let i = 0; i < n - 1; i++) { - res[i + 1] = res[i] ^ encoded[i] - } - - return res -}; - -// another - -/** - * @param {number[]} encoded - * @return {number[]} - */ -const decode = function(A) { - let xor = 0 - const len = A.length - const permLen = len + 1 - for(let i = 1; i <= permLen; i++) { - xor ^= i - } - // except first - for(let i = 1; i < len; i += 2) xor ^= A[i] - const first = xor - const res = [xor] - let pre = xor - for(let i = 1; i < permLen; i++) { - res[i] = A[i - 1] ^ pre - pre = res[i] - } - return res; -}; diff --git a/1734.decode-xored-permutation.js b/1734.decode-xored-permutation.js new file mode 100644 index 00000000..cd10579d --- /dev/null +++ b/1734.decode-xored-permutation.js @@ -0,0 +1,19 @@ +/** + * @param {number[]} encoded + * @return {number[]} + */ +const decode = function(encoded) { + const n = encoded.length + 1 + let xor = 0 + for(let i = 1; i <= n; i++) xor ^= i + for(let i = 1; i < n - 1; i += 2) xor ^= encoded[i] + const res = [xor] + let pre = xor + for(let i = 0; i < n - 1; i++) { + res.push(encoded[i] ^ pre) + pre = res[res.length - 1] + } + + return res +}; + diff --git a/1735-count-ways-to-make-array-with-product.js b/1735.count-ways-to-make-array-with-product.js similarity index 100% rename from 1735-count-ways-to-make-array-with-product.js rename to 1735.count-ways-to-make-array-with-product.js diff --git a/1736-latest-time-by-replacing-hidden-digits.js b/1736.latest-time-by-replacing-hidden-digits.js similarity index 100% rename from 1736-latest-time-by-replacing-hidden-digits.js rename to 1736.latest-time-by-replacing-hidden-digits.js diff --git a/1737-change-minimum-characters-to-satisfy-one-of-three-conditions.js b/1737-change-minimum-characters-to-satisfy-one-of-three-conditions.js deleted file mode 100644 index aa948052..00000000 --- a/1737-change-minimum-characters-to-satisfy-one-of-three-conditions.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @param {string} a - * @param {string} b - * @return {number} - */ -const minCharacters = function (a, b) { - const n1 = a.length, - n2 = b.length - const cnt1 = Array(26).fill(0) - const cnt2 = Array(26).fill(0) - const aCode = 'a'.charCodeAt(0) - for (let c of a) ++cnt1[c.charCodeAt(0) - aCode] - for (let c of b) ++cnt2[c.charCodeAt(0) - aCode] - let res = n1 - Math.max(...cnt1) + n2 - Math.max(...cnt2) - for (let i = 0; i < 25; ++i) { - let cur1 = 0, - cur2 = 0 - for (let j = 0; j < 26; ++j) { - if (j <= i) { - cur1 += cnt2[j] - cur2 += cnt1[j] - } else { - cur1 += cnt1[j] - cur2 += cnt2[j] - } - } - res = Math.min(Math.min(cur1, cur2), res) - } - return res -} - -// another - -/** - * @param {string} a - * @param {string} b - * @return {number} - */ -const minCharacters = function(a, b) { - return Math.min(method1(a, b), method1(b, a), method3(a, b)) -}; - -function method1(str1, str2) { - let res = Infinity, a = 'a'.charCodeAt(0) - for(let i = 1; i < 26; i++) { - let cnt1 = 0, cnt2 = 0, mid = String.fromCharCode(a + i) - for(let ch of str1) { - if(ch >= mid) cnt1++ - } - for(let ch of str2) { - if(ch < mid) cnt2++ - } - res = Math.min(res, cnt1 + cnt2) - } - return res -} - -function method3(str1, str2) { - const a = 'a'.charCodeAt(0) - const cnt1 = Array(26).fill(0), cnt2 = Array(26).fill(0) - for(let ch of str1) cnt1[ch.charCodeAt(0) - a]++ - for(let ch of str2) cnt2[ch.charCodeAt(0) - a]++ - return str1.length + str2.length - Math.max(...cnt1) - Math.max(...cnt2) -} - -// another - -/** - * @param {string} a - * @param {string} b - * @return {number} - */ -const minCharacters = function (a, b) { - const m = a.length, n = b.length - let res = m + n - const cnt1 = Array(26).fill(0), cnt2 = Array(26).fill(0) - const ac = 'a'.charCodeAt(0) - for(let ch of a) cnt1[ch.charCodeAt(0) - ac]++ - for(let ch of b) cnt2[ch.charCodeAt(0) - ac]++ - const c3 = res - Math.max(...cnt1) - Math.max(...cnt2) - for(let i = 0; i < 26; i++) { - if(i > 0) { - cnt1[i] += cnt1[i - 1] - cnt2[i] += cnt2[i - 1] - } - - if(i < 25) { - res = Math.min(res, m - cnt1[i] + cnt2[i]) - res = Math.min(res, n - cnt2[i] + cnt1[i]) - } - } - - return Math.min(res, c3) -} - - diff --git a/1737.change-minimum-characters-to-satisfy-one-of-three-conditions.js b/1737.change-minimum-characters-to-satisfy-one-of-three-conditions.js new file mode 100644 index 00000000..064c2d44 --- /dev/null +++ b/1737.change-minimum-characters-to-satisfy-one-of-three-conditions.js @@ -0,0 +1,31 @@ +/** + * @param {string} a + * @param {string} b + * @return {number} + */ +const minCharacters = function (a, b) { + const n1 = a.length, + n2 = b.length + const cnt1 = Array(26).fill(0) + const cnt2 = Array(26).fill(0) + const aCode = 'a'.charCodeAt(0) + for (let c of a) ++cnt1[c.charCodeAt(0) - aCode] + for (let c of b) ++cnt2[c.charCodeAt(0) - aCode] + let res = n1 - Math.max(...cnt1) + n2 - Math.max(...cnt2) + for (let i = 0; i < 25; ++i) { + let cur1 = 0, + cur2 = 0 + for (let j = 0; j < 26; ++j) { + if (j <= i) { + cur1 += cnt2[j] + cur2 += cnt1[j] + } else { + cur1 += cnt1[j] + cur2 += cnt2[j] + } + } + res = Math.min(Math.min(cur1, cur2), res) + } + return res +} + diff --git a/1738-find-kth-largest-xor-coordinate-value.js b/1738-find-kth-largest-xor-coordinate-value.js deleted file mode 100644 index b593d9f7..00000000 --- a/1738-find-kth-largest-xor-coordinate-value.js +++ /dev/null @@ -1,165 +0,0 @@ -/** - * @param {number[][]} matrix - * @param {number} k - * @return {number} - */ -var kthLargestValue = function(matrix, k) { - let m = matrix.length; - let n = matrix[0].length; - const v = [], d = Array(n).fill(0); - d[0] = matrix[0][0]; - v.push(d[0]); - for (let i = 1; i < n; ++i) { - d[i] = matrix[0][i] ^ d[i - 1]; - v.push(d[i]); - } - for (let i = 1; i < m; ++i) { - let cur = matrix[i][0]; - d[0] ^= cur; - v.push(d[0]); - for (let j = 1; j < n; ++j) { - cur ^= matrix[i][j]; - d[j] ^= cur; - v.push(d[j]); - } - } - v.sort((a, b) => b - a) - return v[k - 1]; -}; - -// another - -/** - * @param {number[][]} matrix - * @param {number} k - * @return {number} - */ -const kthLargestValue = function(matrix, k) { - const tmp = [] - const n = matrix.length, m = matrix[0].length - const dp = Array.from({ length: n }, () => Array(m).fill(0)) - dp[0][0] = matrix[0][0] - tmp.push(dp[0][0]) - for(let j = 1; j < m; j++) { - dp[0][j] = dp[0][j - 1] ^ matrix[0][j] - tmp.push(dp[0][j]) - } - for(let i = 1; i < n; i++) { - dp[i][0] = dp[i - 1][0] ^ matrix[i][0] - tmp.push(dp[i][0]) - } - for(let i = 1; i < n; i++) { - for(let j = 1; j < m; j++) { - dp[i][j] = dp[i][j - 1] ^ dp[i - 1][j] ^ matrix[i][j] ^ dp[i - 1][j - 1] - tmp.push(dp[i][j]) - } - } - tmp.sort((a, b) => b - a) - return tmp[k - 1] -}; - - -// another - -/** - * @param {number[][]} matrix - * @param {number} k - * @return {number} - */ -const kthLargestValue = function(matrix, k) { - if(matrix == null || matrix[0] == null) return 0 - const m = matrix.length, n = matrix[0].length - const res = Array.from({ length: m }, () => Array(n).fill(0)) - res[0][0] = matrix[0][0] - for(let i = 1; i < m; i++) { - res[i][0] = res[i - 1][0] ^ matrix[i][0] - } - for(let j = 1; j < n; j++) { - res[0][j] = res[0][j - 1] ^ matrix[0][j] - } - - for(let i = 1; i < m; i++) { - for(let j = 1; j < n; j++) { - res[i][j] = res[i][j - 1] ^ res[i - 1][j] ^ res[i - 1][j - 1] ^ matrix[i][j] - } - } - - const pq = new PriorityQueue((a, b) => a < b) - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - pq.push(res[i][j]) - if(pq.size() > k) pq.pop() - } - } - - return pq.pop() - -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/1738.find-kth-largest-xor-coordinate-value.js b/1738.find-kth-largest-xor-coordinate-value.js new file mode 100644 index 00000000..b5e56069 --- /dev/null +++ b/1738.find-kth-largest-xor-coordinate-value.js @@ -0,0 +1,29 @@ +/** + * @param {number[][]} matrix + * @param {number} k + * @return {number} + */ +var kthLargestValue = function(matrix, k) { + let m = matrix.length; + let n = matrix[0].length; + const v = [], d = Array(n).fill(0); + d[0] = matrix[0][0]; + v.push(d[0]); + for (let i = 1; i < n; ++i) { + d[i] = matrix[0][i] ^ d[i - 1]; + v.push(d[i]); + } + for (let i = 1; i < m; ++i) { + let cur = matrix[i][0]; + d[0] ^= cur; + v.push(d[0]); + for (let j = 1; j < n; ++j) { + cur ^= matrix[i][j]; + d[j] ^= cur; + v.push(d[j]); + } + } + v.sort((a, b) => b - a) + return v[k - 1]; +}; + diff --git a/1739-building-boxes.js b/1739-building-boxes.js deleted file mode 100644 index 420f84d6..00000000 --- a/1739-building-boxes.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const minimumBoxes = function(n) { - let i = 1, c = 1, s = 1 - while(s < n) { - i += 1, c += i, s += c - } - while(s - i >= n) { - s -= i, c -= 1, i -= 1 - } - return c -}; - -// another - - -/** - * @param {number} n - * @return {number} - */ -const minimumBoxes = function(n) { - let sum = 1n, base = 1n, row = 1n; - n = BigInt(n) - while (sum < n) { - base += (++row); - sum += base; - } - while (sum > n) { - --base; - sum -= (row--); - if (sum < n) return base + 1n; - } - return base; -}; - diff --git a/1739.building-boxes.js b/1739.building-boxes.js new file mode 100644 index 00000000..4ccbdb62 --- /dev/null +++ b/1739.building-boxes.js @@ -0,0 +1,15 @@ +/** + * @param {number} n + * @return {number} + */ +const minimumBoxes = function(n) { + let i = 1, c = 1, s = 1 + while(s < n) { + i += 1, c += i, s += c + } + while(s - i >= n) { + s -= i, c -= 1, i -= 1 + } + return c +}; + diff --git a/174-dungeon-game.js b/174-dungeon-game.js deleted file mode 100644 index 99988ffc..00000000 --- a/174-dungeon-game.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @param {number[][]} dungeon - * @return {number} - */ -const calculateMinimumHP = function (dungeon) { - const M = dungeon.length - const N = dungeon[0].length - // hp[i][j] represents the min hp needed at position (i, j) - // Add dummy row and column at bottom and right side - const hp = Array.from({ length: M + 1 }, () => - Array(N + 1).fill(Number.MAX_VALUE) - ) - hp[M][N - 1] = 1 - hp[M - 1][N] = 1 - for (let i = M - 1; i >= 0; i--) { - for (let j = N - 1; j >= 0; j--) { - const need = Math.min(hp[i + 1][j], hp[i][j + 1]) - dungeon[i][j] - hp[i][j] = need <= 0 ? 1 : need - } - } - return hp[0][0] -} - - -// another - -/** - * @param {number[][]} dungeon - * @return {number} - */ -const calculateMinimumHP = function (dungeon) { - const n = dungeon.length, - m = dungeon[0].length - const dp = Array(n + 1).fill(Number.MAX_VALUE) - dp[n - 1] = 1 - for (let j = m - 1; j >= 0; j--) { - for (let i = n - 1; i >= 0; i--) { - dp[i] = Math.min(dp[i], dp[i + 1]) - dungeon[i][j] - dp[i] = Math.max(1, dp[i]) - } - } - return dp[0] -} - diff --git a/174.dungeon-game.js b/174.dungeon-game.js new file mode 100644 index 00000000..75e044c7 --- /dev/null +++ b/174.dungeon-game.js @@ -0,0 +1,24 @@ +/** + * @param {number[][]} dungeon + * @return {number} + */ +const calculateMinimumHP = function (dungeon) { + const M = dungeon.length + const N = dungeon[0].length + // hp[i][j] represents the min hp needed at position (i, j) + // Add dummy row and column at bottom and right side + const hp = Array.from({ length: M + 1 }, () => + Array(N + 1).fill(Number.MAX_VALUE) + ) + hp[M][N - 1] = 1 + hp[M - 1][N] = 1 + for (let i = M - 1; i >= 0; i--) { + for (let j = N - 1; j >= 0; j--) { + const need = Math.min(hp[i + 1][j], hp[i][j + 1]) - dungeon[i][j] + hp[i][j] = need <= 0 ? 1 : need + } + } + return hp[0][0] +} + + diff --git a/1740-find-distance-in-a-binary-tree.js b/1740-find-distance-in-a-binary-tree.js deleted file mode 100644 index 97dae690..00000000 --- a/1740-find-distance-in-a-binary-tree.js +++ /dev/null @@ -1,163 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @param {number} p - * @param {number} q - * @return {number} - */ -const findDistance = function(root, p, q) { - if(p === q) return 0 - return dfs(root, 0) - - function dfs(node, depth) { - let res = depth - if (node == null) { - res = 0 - } else if(node.val === p || node.val === q) { - let left = dfs(node.left, 1) - let right = dfs(node.right, 1) - res = (left > 0 || right > 0) ? Math.max(left, right) : res - } else { - let left = dfs(node.left, depth + 1) - let right = dfs(node.right, depth + 1) - res = left + right - if(left !== 0 && right !== 0) { - res -= 2 * depth - } - } - return res - } -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @param {number} p - * @param {number} q - * @return {number} - */ -const findDistance = function (root, p, q) { - if (p == q) return 0 - let result = -1 - dfs(root, p, q) - return result - - /** - The return value means the distance from root node to EITHER p OR q. If - neither p nor q are reachable from the root, return -1. - - It is either p or q but not both, because if the root node can reach both - p and q, it is a common ancestor of p and q and the answer should already - be available. - **/ - function dfs(root, p, q) { - if (root == null) return -1 - - let left = dfs(root.left, p, q) - let right = dfs(root.right, p, q) - - if (root.val == p || root.val == q) { - // root is p or q, but none of p or q is a descendent of root. - // The distance from root to one of p and q is 0 in this case. - if (left < 0 && right < 0) { - return 0 - } - - // root is p or q, and root is also the LCA of p and q. - result = 1 + (left >= 0 ? left : right) - return -1 - } - - // root is neither p nor q, but it is the LCA of p and q. - if (left >= 0 && right >= 0) { - result = left + right + 2 - return -1 - } - - if (left >= 0) { - return left + 1 - } - - if (right >= 0) { - return right + 1 - } - - return -1 - } -} - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @param {number} p - * @param {number} q - * @return {number} - */ -const findDistance = function (root, p, q) { - let lca = lowestCommonAncestor(root, p, q) - - const queue = [] - queue.push(lca) - let dp = -1, - dq = -1 - let d = 0 - while (queue.length && (dp == -1 || dq == -1)) { - for (let k = queue.length; k > 0; k--) { - let node = queue.shift() - if (node.val == p) { - dp = d - } - - if (node.val == q) { - dq = d - } - - if (node.left != null) { - queue.push(node.left) - } - - if (node.right != null) { - queue.push(node.right) - } - } - d++ - } - - return dp + dq - - function lowestCommonAncestor(root, p, q) { - if (root == null || root.val == p || root.val == q) { - return root - } - let left = lowestCommonAncestor(root.left, p, q) - let right = lowestCommonAncestor(root.right, p, q) - - return left == null ? right : right == null ? left : root - } -} - diff --git a/1740.find-distance-in-a-binary-tree.js b/1740.find-distance-in-a-binary-tree.js new file mode 100644 index 00000000..5b7afa50 --- /dev/null +++ b/1740.find-distance-in-a-binary-tree.js @@ -0,0 +1,38 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} p + * @param {number} q + * @return {number} + */ +const findDistance = function(root, p, q) { + if(p === q) return 0 + return dfs(root, 0) + + function dfs(node, depth) { + let res = depth + if (node == null) { + res = 0 + } else if(node.val === p || node.val === q) { + let left = dfs(node.left, 1) + let right = dfs(node.right, 1) + res = (left > 0 || right > 0) ? Math.max(left, right) : res + } else { + let left = dfs(node.left, depth + 1) + let right = dfs(node.right, depth + 1) + res = left + right + if(left !== 0 && right !== 0) { + res -= 2 * depth + } + } + return res + } +}; + diff --git a/1742-maximum-number-of-balls-in-a-box.js b/1742.maximum-number-of-balls-in-a-box.js similarity index 100% rename from 1742-maximum-number-of-balls-in-a-box.js rename to 1742.maximum-number-of-balls-in-a-box.js diff --git a/1743-restore-the-array-from-adjacent-pairs.js b/1743.restore-the-array-from-adjacent-pairs.js similarity index 100% rename from 1743-restore-the-array-from-adjacent-pairs.js rename to 1743.restore-the-array-from-adjacent-pairs.js diff --git a/1744-can-you-eat-your-favorite-candy-on-your-favorite-day.js b/1744.can-you-eat-your-favorite-candy-on-your-favorite-day.js similarity index 100% rename from 1744-can-you-eat-your-favorite-candy-on-your-favorite-day.js rename to 1744.can-you-eat-your-favorite-candy-on-your-favorite-day.js diff --git a/1745-palindrome-partitioning-iv.js b/1745-palindrome-partitioning-iv.js deleted file mode 100644 index 8576c981..00000000 --- a/1745-palindrome-partitioning-iv.js +++ /dev/null @@ -1,100 +0,0 @@ -/** - * @param {string} s - * @return {boolean} - */ -const checkPartitioning = function(s) { - const map = manacher(s); - return checkPartitioningDfs(map, s, 0); -}; - -function checkPartitioningDfs(map, word, i, path = []) { - if (path.length > 3) return false; - if (path.length == 3 && path.join('') == word) return true; - let found = false; - const length = map.get(i); - path.push(word.substr(i, length)); - found = found || checkPartitioningDfs(map, word, i + length, path); - path.pop(); - - path.push(word.substr(i, 1)); - found = found || checkPartitioningDfs(map, word, i + 1, path); - path.pop(); - - return found; -} - -function manacher(s) { - const t = '^#' + s.split('').join('#') + '#$'; - let r = 0; - let c = 0; - let maxC = 0; - const rad = new Array(t.length).fill(0); - for (let i = 1; i < t.length - 1; ++i) { - if (r > i) rad[i] = Math.min(rad[2 * c - i], r - i); - while (t[i - rad[i] - 1] == t[i + rad[i] + 1]) rad[i]++; - if (i + rad[i] > r) { - c = i; - r = i + rad[i]; - } - if (rad[c] > rad[maxC]) maxC = c; - } - const ans = new Map(); - for (let i = 0; i < rad.length; ++i) { - if (rad[i] > 0) { - ans.set((i - rad[i] - 1) >>> 1, rad[i]); - } - } - return ans; -} - -// another - -/** - * @param {string} s - * @return {boolean} - */ -const checkPartitioning = function (s) { - const n = s.length - const dp = Array.from({ length: n }, () => Array(n).fill(false)) - for(let i = n - 1; i >= 0; i--) { - for(let j = i; j < n; j++) { - if(s[i] === s[j]) { - dp[i][j] = i + 1 <= j - 1 ? dp[i + 1][j - 1] : true - } else dp[i][j] = false - } - } - for(let i = 1; i < n - 1; i++) { - for(let j = i; j < n - 1; j++) { - if(dp[0][i - 1] && dp[i][j] && dp[j + 1][n - 1]) return true - } - } - return false -} - - -// another - -/** - * @param {string} s - * @return {boolean} - */ -const checkPartitioning = function(s) { - for(let i = 1, len = s.length; i < len - 1; i++) { - for(let j = i + 1; j < len; j++) { - const s1 = s.slice(0, i), s2 = s.slice(i, j), s3 = s.slice(j) - if(chk(s1) && chk(s2) && chk(s3)) return true - } - } - return false -}; - -function chk(s) { - let l = 0, r = s.length - 1 - for(;l <= r;) { - if(s[l] === s[r]) { - l++ - r-- - } else return false - } - return true -} diff --git a/1745.palindrome-partitioning-iv.js b/1745.palindrome-partitioning-iv.js new file mode 100644 index 00000000..6f6ddaee --- /dev/null +++ b/1745.palindrome-partitioning-iv.js @@ -0,0 +1,49 @@ +/** + * @param {string} s + * @return {boolean} + */ +const checkPartitioning = function(s) { + const map = manacher(s); + return checkPartitioningDfs(map, s, 0); +}; + +function checkPartitioningDfs(map, word, i, path = []) { + if (path.length > 3) return false; + if (path.length == 3 && path.join('') == word) return true; + let found = false; + const length = map.get(i); + path.push(word.substr(i, length)); + found = found || checkPartitioningDfs(map, word, i + length, path); + path.pop(); + + path.push(word.substr(i, 1)); + found = found || checkPartitioningDfs(map, word, i + 1, path); + path.pop(); + + return found; +} + +function manacher(s) { + const t = '^#' + s.split('').join('#') + '#$'; + let r = 0; + let c = 0; + let maxC = 0; + const rad = new Array(t.length).fill(0); + for (let i = 1; i < t.length - 1; ++i) { + if (r > i) rad[i] = Math.min(rad[2 * c - i], r - i); + while (t[i - rad[i] - 1] == t[i + rad[i] + 1]) rad[i]++; + if (i + rad[i] > r) { + c = i; + r = i + rad[i]; + } + if (rad[c] > rad[maxC]) maxC = c; + } + const ans = new Map(); + for (let i = 0; i < rad.length; ++i) { + if (rad[i] > 0) { + ans.set((i - rad[i] - 1) >>> 1, rad[i]); + } + } + return ans; +} + diff --git a/1746-maximum-subarray-sum-after-one-operation.js b/1746.maximum-subarray-sum-after-one-operation.js similarity index 100% rename from 1746-maximum-subarray-sum-after-one-operation.js rename to 1746.maximum-subarray-sum-after-one-operation.js diff --git a/1748-sum-of-unique-elements.js b/1748.sum-of-unique-elements.js similarity index 100% rename from 1748-sum-of-unique-elements.js rename to 1748.sum-of-unique-elements.js diff --git a/1749-maximum-absolute-sum-of-any-subarray.js b/1749-maximum-absolute-sum-of-any-subarray.js deleted file mode 100644 index 503164e2..00000000 --- a/1749-maximum-absolute-sum-of-any-subarray.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const maxAbsoluteSum = function (nums) { - let min = 0, - max = 0, - sum = 0 - for(let e of nums) { - sum += e - min = Math.min(sum, min) - max = Math.max(sum, max) - } - return max - min -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxAbsoluteSum = function (nums) { - let min = Infinity, - max = -Infinity - let positiveSum = 0, - negativeSum = 0 - for (let num of nums) { - positiveSum += num - if (positiveSum > max) { - max = positiveSum - } - - if (positiveSum < 0) { - positiveSum = 0 - } - negativeSum += num - if (negativeSum < min) { - min = negativeSum - } - if (negativeSum > 0) { - negativeSum = 0 - } - } - - return Math.max(Math.abs(min), max) -} diff --git a/1749.maximum-absolute-sum-of-any-subarray.js b/1749.maximum-absolute-sum-of-any-subarray.js new file mode 100644 index 00000000..c52817c9 --- /dev/null +++ b/1749.maximum-absolute-sum-of-any-subarray.js @@ -0,0 +1,16 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const maxAbsoluteSum = function (nums) { + let min = 0, + max = 0, + sum = 0 + for(let e of nums) { + sum += e + min = Math.min(sum, min) + max = Math.max(sum, max) + } + return max - min +} + diff --git a/1750-minimum-length-of-string-after-deleting-similar-ends.js b/1750.minimum-length-of-string-after-deleting-similar-ends.js similarity index 100% rename from 1750-minimum-length-of-string-after-deleting-similar-ends.js rename to 1750.minimum-length-of-string-after-deleting-similar-ends.js diff --git a/1751-maximum-number-of-events-that-can-be-attended-ii.js b/1751-maximum-number-of-events-that-can-be-attended-ii.js deleted file mode 100644 index 6f1ce829..00000000 --- a/1751-maximum-number-of-events-that-can-be-attended-ii.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * @param {number[][]} events - * @param {number} k - * @return {number} - */ -const maxValue = function (events, k) { - const n = events.length - const memo = Array.from({ length: n + 1 }, () => Array(k + 1).fill(-1)) - events.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]) - return helper(memo, events, n, 0, k) -} - -function helper(memo, events, n, i, k) { - if(i === n || k === 0) return 0 - if(memo[i][k] !== -1) return memo[i][k] - let ni = i + 1 - for(; ni < n; ni++) { - if(events[ni][0] > events[i][1]) break - } - - return memo[i][k] = Math.max( - helper(memo, events, n, i + 1, k), - events[i][2] + helper(memo, events, n, ni, k - 1) - ) -} - -// another - -/** - * @param {number[][]} events - * @param {number} k - * @return {number} - */ -const maxValue = function (events, k) { - // d[i][j] 表示以 events[i]结尾的取最多j个最大值 - // d[i][j-1], Math.max( d[m][j-1] + v[i]) for m ending < start[i] - events.sort((a, b) => a[1] - b[1]) - const n = events.length - let d = [] - for (let j = 0; j <= k; j++) { - const newD = [] - for (let i = 0; i < n; i++) { - if (j === 0) { - newD[i] = 0 - } else if (j === 1) { - newD[i] = events[i][2] - } else if (i === 0) { - newD[i] = events[i][2] - } else { - newD[i] = d[i] // 以i结尾最多取j-1次的最大值 - const v = events[i][2] - const start = events[i][0] - for (let m = 0; m < i; m++) { - if (events[m][1] < start) { - if (d[m] + v > newD[i]) { - newD[i] = d[m] + v - } - } else { - break - } - } - } - } - d = [...newD] - } - return Math.max(...d) -} - - -// another - - -/** - * @param {number[][]} events - * @param {number} k - * @return {number} - */ -const maxValue = function(events, k) { - - cache = new Map(); - events.sort((a,b) => a[0] - b[0]); - return dfs(events, 0, -1, k); - - function dfs(events, idx, end, k){ - let key = idx + "," + end + "," + k; - if(cache.has(key)){ - return cache.get(key); - } - if(idx >= events.length){ - return 0; - } - if(k == 0) { - return 0; - } - let max = 0; - if(events[idx][0] > end){ - max = Math.max(max, dfs(events, idx+1, events[idx][1], k-1) + events[idx][2]); - } - - max = Math.max(max, dfs(events, idx+1, end, k)); - cache.set(key, max); - return max; - } -}; diff --git a/1751.maximum-number-of-events-that-can-be-attended-ii.js b/1751.maximum-number-of-events-that-can-be-attended-ii.js new file mode 100644 index 00000000..a012efdb --- /dev/null +++ b/1751.maximum-number-of-events-that-can-be-attended-ii.js @@ -0,0 +1,26 @@ +/** + * @param {number[][]} events + * @param {number} k + * @return {number} + */ +const maxValue = function (events, k) { + const n = events.length + const memo = Array.from({ length: n + 1 }, () => Array(k + 1).fill(-1)) + events.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]) + return helper(memo, events, n, 0, k) +} + +function helper(memo, events, n, i, k) { + if(i === n || k === 0) return 0 + if(memo[i][k] !== -1) return memo[i][k] + let ni = i + 1 + for(; ni < n; ni++) { + if(events[ni][0] > events[i][1]) break + } + + return memo[i][k] = Math.max( + helper(memo, events, n, i + 1, k), + events[i][2] + helper(memo, events, n, ni, k - 1) + ) +} + diff --git a/1752-check-if-array-is-sorted-and-rotated.js b/1752.check-if-array-is-sorted-and-rotated.js similarity index 100% rename from 1752-check-if-array-is-sorted-and-rotated.js rename to 1752.check-if-array-is-sorted-and-rotated.js diff --git a/1753-maximum-score-from-removing-stones.js b/1753.maximum-score-from-removing-stones.js similarity index 100% rename from 1753-maximum-score-from-removing-stones.js rename to 1753.maximum-score-from-removing-stones.js diff --git a/1754-largest-merge-of-two-strings.js b/1754-largest-merge-of-two-strings.js deleted file mode 100644 index f910ba72..00000000 --- a/1754-largest-merge-of-two-strings.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @param {string} word1 - * @param {string} word2 - * @return {string} - */ -var largestMerge = function(word1, word2) { - let merge = ""; - - while(word1.length && word2.length) { - if (word1[0] > word2[0]) { - merge += word1[0]; - word1 = word1.slice(1); - } else if (word1[0] < word2[0]) { - merge += word2[0]; - word2 = word2.slice(1); - } else { - if (word1 > word2) { - merge += word1[0]; - word1 = word1.slice(1); - } else { - merge += word2[0]; - word2 = word2.slice(1); - } - } - } - - if (word1.length) { - merge += word1; - } else if (word2.length) { - merge += word2; - } - - return merge; -}; - -// another - -/** - * @param {string} word1 - * @param {string} word2 - * @return {string} - */ -const largestMerge = function(word1, word2) { - const stack1 = word1.split(''), stack2 = word2.split('') - const arr = [] - - while(stack1.length && stack2.length) { - const c1 = stack1[0], c2 = stack2[0] - if(c1 > c2) { - stack1.shift() - arr.push(c1) - } else if(c1 < c2) { - stack2.shift() - arr.push(c2) - } else { - if(stack1.join('') > stack2.join('')) { - stack1.shift() - arr.push(c1) - } else { - stack2.shift() - arr.push(c2) - } - } - } - if(stack1.length) { - arr.push(...stack1) - } - if(stack2.length) { - arr.push(...stack2) - } - - return arr.join('') -}; diff --git a/1754.largest-merge-of-two-strings.js b/1754.largest-merge-of-two-strings.js new file mode 100644 index 00000000..b85dd836 --- /dev/null +++ b/1754.largest-merge-of-two-strings.js @@ -0,0 +1,35 @@ +/** + * @param {string} word1 + * @param {string} word2 + * @return {string} + */ +var largestMerge = function(word1, word2) { + let merge = ""; + + while(word1.length && word2.length) { + if (word1[0] > word2[0]) { + merge += word1[0]; + word1 = word1.slice(1); + } else if (word1[0] < word2[0]) { + merge += word2[0]; + word2 = word2.slice(1); + } else { + if (word1 > word2) { + merge += word1[0]; + word1 = word1.slice(1); + } else { + merge += word2[0]; + word2 = word2.slice(1); + } + } + } + + if (word1.length) { + merge += word1; + } else if (word2.length) { + merge += word2; + } + + return merge; +}; + diff --git a/1755-closest-subsequence-sum.js b/1755-closest-subsequence-sum.js deleted file mode 100644 index f7fee8e8..00000000 --- a/1755-closest-subsequence-sum.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} goal - * @return {number} - */ -const minAbsDifference = function (nums, goal) { - let min = Math.abs(goal) - if (!nums.length) return min - const generateSums = (a) => { - let sums = [] - for (let i = 0; i < a.length; i++) { - const l = sums.length - for (let j = 0; j < l; j++) { - sums.push(sums[j] + a[i]) - min = Math.min(min, Math.abs(sums[j] + a[i] - goal)) - if (min === 0) return - } - sums.push(a[i]) - min = Math.min(min, Math.abs(a[i] - goal)) - if (min === 0) return - } - return sums - } - - const n1 = nums.slice(0, Math.ceil(nums.length / 2)) - const n2 = nums.slice(Math.ceil(nums.length / 2), nums.length) - const sums1 = generateSums(n1) - if (min === 0) return min - const sums2 = generateSums(n2) - if (min === 0) return min - - sums2.sort((a, b) => a - b) - for (let i = 0; i < sums1.length; i++) { - if (min === 0) return min - let l = 0 - let r = sums2.length - let sum - while (l < r) { - const h = Math.floor((l + r) / 2) - sum = sums1[i] + sums2[h] - min = Math.min(min, Math.abs(sum - goal)) - if (min === 0) return min - if (sum - goal < 0) { - l = h + 1 - } else { - r = h - } - } - } - return min -} - - -// another - -/** - * @param {number[]} nums - * @param {number} goal - * @return {number} - */ -var minAbsDifference = function(a, b) { - let n = a.length, m = (n / 2) >> 0, r = n - m; - let ans = 2e9; - const {max, min, abs} = Math - const va = [], vb = []; - for(let i=0;i<1<>j&1) tmp+=a[j]; - } - ans=min(ans,abs(tmp-b)); - va.push(tmp); - } - // sort(va.begin(), va.end()); - va.sort((a, b) => a - b) - for(let i=0;i<1<>j&1) tmp+=a[j+m]; - } - ans=min(ans,abs(tmp-b)); - let k=b-tmp; - let pos=lower_bound(va, k); - for(let j=pos-1;j<=pos+1;++j) { - if(j>=0 && j 0) { - step = Math.floor(len / 2); - middle = first + step; - if (less(array[middle], value, middle)) { - first = middle; - first += 1; - len = len - step - 1; - } else { - len = step; - } - } - return first; -}; - diff --git a/1755.closest-subsequence-sum.js b/1755.closest-subsequence-sum.js new file mode 100644 index 00000000..7a31da7f --- /dev/null +++ b/1755.closest-subsequence-sum.js @@ -0,0 +1,53 @@ +/** + * @param {number[]} nums + * @param {number} goal + * @return {number} + */ +const minAbsDifference = function (nums, goal) { + let min = Math.abs(goal) + if (!nums.length) return min + const generateSums = (a) => { + let sums = [] + for (let i = 0; i < a.length; i++) { + const l = sums.length + for (let j = 0; j < l; j++) { + sums.push(sums[j] + a[i]) + min = Math.min(min, Math.abs(sums[j] + a[i] - goal)) + if (min === 0) return + } + sums.push(a[i]) + min = Math.min(min, Math.abs(a[i] - goal)) + if (min === 0) return + } + return sums + } + + const n1 = nums.slice(0, Math.ceil(nums.length / 2)) + const n2 = nums.slice(Math.ceil(nums.length / 2), nums.length) + const sums1 = generateSums(n1) + if (min === 0) return min + const sums2 = generateSums(n2) + if (min === 0) return min + + sums2.sort((a, b) => a - b) + for (let i = 0; i < sums1.length; i++) { + if (min === 0) return min + let l = 0 + let r = sums2.length + let sum + while (l < r) { + const h = Math.floor((l + r) / 2) + sum = sums1[i] + sums2[h] + min = Math.min(min, Math.abs(sum - goal)) + if (min === 0) return min + if (sum - goal < 0) { + l = h + 1 + } else { + r = h + } + } + } + return min +} + + diff --git a/1758-minimum-changes-to-make-alternating-binary-string.js b/1758.minimum-changes-to-make-alternating-binary-string.js similarity index 100% rename from 1758-minimum-changes-to-make-alternating-binary-string.js rename to 1758.minimum-changes-to-make-alternating-binary-string.js diff --git a/1759-count-number-of-homogenous-substrings.js b/1759.count-number-of-homogenous-substrings.js similarity index 100% rename from 1759-count-number-of-homogenous-substrings.js rename to 1759.count-number-of-homogenous-substrings.js diff --git a/1760-minimum-limit-of-balls-in-a-bag.js b/1760.minimum-limit-of-balls-in-a-bag.js similarity index 100% rename from 1760-minimum-limit-of-balls-in-a-bag.js rename to 1760.minimum-limit-of-balls-in-a-bag.js diff --git a/1761-minimum-degree-of-a-connected-trio-in-a-graph.js b/1761.minimum-degree-of-a-connected-trio-in-a-graph.js similarity index 100% rename from 1761-minimum-degree-of-a-connected-trio-in-a-graph.js rename to 1761.minimum-degree-of-a-connected-trio-in-a-graph.js diff --git a/1762-buildings-with-an-ocean-view.js b/1762.buildings-with-an-ocean-view.js similarity index 100% rename from 1762-buildings-with-an-ocean-view.js rename to 1762.buildings-with-an-ocean-view.js diff --git a/1763-longest-nice-substring.js b/1763.longest-nice-substring.js similarity index 100% rename from 1763-longest-nice-substring.js rename to 1763.longest-nice-substring.js diff --git a/1764-form-array-by-concatenating-subarrays-of-another-array.js b/1764-form-array-by-concatenating-subarrays-of-another-array.js deleted file mode 100644 index 1fd9fc52..00000000 --- a/1764-form-array-by-concatenating-subarrays-of-another-array.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @param {number[][]} groups - * @param {number[]} nums - * @return {boolean} - */ -const canChoose = function (groups, nums) { - const m = nums.length - let index = 0 - for (let group of groups) { - const n = group.length - // Step-1 Generate LPS - const lps = Array(n).fill(0) - for (let i = 1; i < n; i++) { - let j = lps[i - 1] - while (j > 0 && group[i] !== group[j]) { - j = lps[j - 1] - } - if (group[i] === group[j]) { - j++ - } - lps[i] = j - } - - // Step-2 - Matching - let j = 0 - while (index < m) { - if (nums[index] === group[j]) { - j++ - index++ - } - if (j === n) break - else if (index < m && nums[index] != group[j]) { - if (j > 0) { - j = lps[j - 1] - } else { - index++ - } - } - } - if (j !== n) return false - } - return true -} - - -// another - - -/** - * @param {number[][]} groups - * @param {number[]} nums - * @return {boolean} - */ -const canChoose = function(groups, nums) { - let gi = 0, ni = 0 - const n = groups.length, m = nums.length - while(gi < n && ni < m) { - const len = groups[gi].length - let pass = true - if(nums[ni] !== groups[gi][0]) { - ni++ - continue - } - for(let i = 1; i < len; i++) { - if(nums[ni + i] !== groups[gi][i]) { - pass = false - break - } - } - if(pass) { - gi++ - ni += len - } else { - ni++ - } - } - if(gi >= n) return true - - return false - -}; diff --git a/1764.form-array-by-concatenating-subarrays-of-another-array.js b/1764.form-array-by-concatenating-subarrays-of-another-array.js new file mode 100644 index 00000000..4e881fa4 --- /dev/null +++ b/1764.form-array-by-concatenating-subarrays-of-another-array.js @@ -0,0 +1,45 @@ +/** + * @param {number[][]} groups + * @param {number[]} nums + * @return {boolean} + */ +const canChoose = function (groups, nums) { + const m = nums.length + let index = 0 + for (let group of groups) { + const n = group.length + // Step-1 Generate LPS + const lps = Array(n).fill(0) + for (let i = 1; i < n; i++) { + let j = lps[i - 1] + while (j > 0 && group[i] !== group[j]) { + j = lps[j - 1] + } + if (group[i] === group[j]) { + j++ + } + lps[i] = j + } + + // Step-2 - Matching + let j = 0 + while (index < m) { + if (nums[index] === group[j]) { + j++ + index++ + } + if (j === n) break + else if (index < m && nums[index] != group[j]) { + if (j > 0) { + j = lps[j - 1] + } else { + index++ + } + } + } + if (j !== n) return false + } + return true +} + + diff --git a/1765-map-of-highest-peak.js b/1765.map-of-highest-peak.js similarity index 100% rename from 1765-map-of-highest-peak.js rename to 1765.map-of-highest-peak.js diff --git a/1766-tree-of-coprimes.js b/1766.tree-of-coprimes.js similarity index 100% rename from 1766-tree-of-coprimes.js rename to 1766.tree-of-coprimes.js diff --git a/1768-merge-strings-alternately.js b/1768.merge-strings-alternately.js similarity index 100% rename from 1768-merge-strings-alternately.js rename to 1768.merge-strings-alternately.js diff --git a/1769-minimum-number-of-operations-to-move-all-balls-to-each-box.js b/1769-minimum-number-of-operations-to-move-all-balls-to-each-box.js deleted file mode 100644 index 11f47aa6..00000000 --- a/1769-minimum-number-of-operations-to-move-all-balls-to-each-box.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @param {string} boxes - * @return {number[]} - */ -const minOperations = function(boxes) { - const n = boxes.length - const res = Array(n).fill(0) - let cum = 0, sum = 0 - for(let i = 0; i < n; i++) { - res[i] += sum - cum += +boxes[i] - sum += cum - } - cum = 0, sum = 0 - for(let i = n - 1; i >= 0; i--) { - res[i] += sum - cum += +boxes[i] - sum += cum - } - return res -}; - - -// another - - -/** - * @param {string} boxes - * @return {number[]} - */ -const minOperations = function(boxes) { - const res = [] - for(let i = 0, len = boxes.length; i < len; i++) { - res[i] = helper(boxes, i) - } - - return res -}; - -function helper(str, idx) { - let res = 0 - for(let i = 0, len = str.length; i < len; i++) { - if(i === idx || str[i] === '0') continue - res += Math.abs(i - idx) - } - return res -} - -// another - -/** - * @param {string} boxes - * @return {number[]} - */ - const minOperations = function(boxes) { - const n = boxes.length - const res = Array(n).fill(0) - let cnt = 0, sum = 0 - for(let i = 0; i < n; i++) { - res[i] = sum - cnt += boxes[i] === '1' ? 1 : 0 - sum += cnt - } - cnt = 0, sum = 0 - for(let i = n - 1; i >= 0; i--) { - res[i] += sum - cnt += boxes[i] === '1' ? 1 : 0 - sum += cnt - } - return res -}; diff --git a/1769.minimum-number-of-operations-to-move-all-balls-to-each-box.js b/1769.minimum-number-of-operations-to-move-all-balls-to-each-box.js new file mode 100644 index 00000000..cec9f82c --- /dev/null +++ b/1769.minimum-number-of-operations-to-move-all-balls-to-each-box.js @@ -0,0 +1,23 @@ +/** + * @param {string} boxes + * @return {number[]} + */ +const minOperations = function(boxes) { + const n = boxes.length + const res = Array(n).fill(0) + let cum = 0, sum = 0 + for(let i = 0; i < n; i++) { + res[i] += sum + cum += +boxes[i] + sum += cum + } + cum = 0, sum = 0 + for(let i = n - 1; i >= 0; i--) { + res[i] += sum + cum += +boxes[i] + sum += cum + } + return res +}; + + diff --git a/1770-maximum-score-from-performing-multiplication-operations.js b/1770.maximum-score-from-performing-multiplication-operations.js similarity index 100% rename from 1770-maximum-score-from-performing-multiplication-operations.js rename to 1770.maximum-score-from-performing-multiplication-operations.js diff --git a/1771-maximize-palindrome-length-from-subsequences.js b/1771-maximize-palindrome-length-from-subsequences.js deleted file mode 100644 index fd093aa0..00000000 --- a/1771-maximize-palindrome-length-from-subsequences.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @param {string} word1 - * @param {string} word2 - * @return {number} - */ -const longestPalindrome = function(word1, word2) { - const str = word1 + word2 - const len = str.length, m = word1.length, n = word2.length - const dp = LPS(str) - let res = 0 - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - if(word1[i] !== word2[j]) continue - res = Math.max(res, 2 + dp[i + 1][j + m - 1]) - } - } - return res -} - -function LPS(str) { - const n = str.length - const dp = Array.from({ length: n }, () => Array(n).fill(0)) - for(let i = n - 1; i >= 0; i--) { - dp[i][i] = 1 - for(let j = i + 1; j < n; j++) { - if(str[i] === str[j]) dp[i][j] = 2 + dp[i + 1][j - 1] - else dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]) - } - } - return dp -} - - -// another - -/** - * @param {string} word1 - * @param {string} word2 - * @return {number} - */ -const longestPalindrome = function(word1, word2) { - const sz = word1.length + word2.length - let res = 0; - const dp = Array.from({ length: sz + 1 }, () => Array(sz + 1).fill(0)) - longestPalindromeSubseq(word1 + word2, dp); - for (let i = 0; i < word1.length; ++i) - for (let j = word2.length - 1; j >= 0; --j) - if (word1[i] == word2[j]) { - res = Math.max(res, dp[i][word1.length + j + 1]); - break; - } - return res; - -} -function longestPalindromeSubseq( s, dp) { - for (let len = 1; len <= s.length; ++len) - for (let i = 0; i + len <= s.length; ++i) - dp[i][i + len] = s[i] == s[i + len - 1] ? - dp[i + 1][i + len - 1] + (len == 1 ? 1 : 2) : - Math.max(dp[i][i + len - 1], dp[i + 1][i + len]); - return dp[0][s.length]; -} - - diff --git a/1771.maximize-palindrome-length-from-subsequences.js b/1771.maximize-palindrome-length-from-subsequences.js new file mode 100644 index 00000000..b372cf0e --- /dev/null +++ b/1771.maximize-palindrome-length-from-subsequences.js @@ -0,0 +1,33 @@ +/** + * @param {string} word1 + * @param {string} word2 + * @return {number} + */ +const longestPalindrome = function(word1, word2) { + const str = word1 + word2 + const len = str.length, m = word1.length, n = word2.length + const dp = LPS(str) + let res = 0 + for(let i = 0; i < m; i++) { + for(let j = 0; j < n; j++) { + if(word1[i] !== word2[j]) continue + res = Math.max(res, 2 + dp[i + 1][j + m - 1]) + } + } + return res +} + +function LPS(str) { + const n = str.length + const dp = Array.from({ length: n }, () => Array(n).fill(0)) + for(let i = n - 1; i >= 0; i--) { + dp[i][i] = 1 + for(let j = i + 1; j < n; j++) { + if(str[i] === str[j]) dp[i][j] = 2 + dp[i + 1][j - 1] + else dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]) + } + } + return dp +} + + diff --git a/1773-count-items-matching-a-rule.js b/1773.count-items-matching-a-rule.js similarity index 100% rename from 1773-count-items-matching-a-rule.js rename to 1773.count-items-matching-a-rule.js diff --git a/1774-closest-dessert-cost.js b/1774-closest-dessert-cost.js deleted file mode 100644 index 6d918079..00000000 --- a/1774-closest-dessert-cost.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @param {number[]} baseCosts - * @param {number[]} toppingCosts - * @param {number} target - * @return {number} - */ -const closestCost = function(baseCosts, toppingCosts, target) { - let res = baseCosts[0], n = baseCosts.length, m = toppingCosts.length - const { abs } = Math - for (let i = 0; i < n; i++) { - helper(0, baseCosts[i]) - } - return res - function helper(i, cur) { - if( - abs(cur - target) < abs(res - target) - || (abs(cur - target) === abs(res - target) && cur < res) - ) { - res = cur - } - if(i === m || cur > target) return - helper(i + 1, cur) - helper(i + 1, cur + toppingCosts[i]) - helper(i + 1, cur + toppingCosts[i] * 2) - } -}; - -// another - - -/** - * @param {number[]} baseCosts - * @param {number[]} toppingCosts - * @param {number} target - * @return {number} - */ -const closestCost = function(baseCosts, toppingCosts, target) { - let n = baseCosts.length, m = toppingCosts.length; - const { abs } = Math - const costs = new Set(); - for (let i = 0; i < n; i++) { - dfs(toppingCosts, 0, m, baseCosts[i], costs); - } - const nums = []; - for (let x of costs) nums.push(x); - nums.sort((a, b) => abs(a - target) == abs(b - target) ? a - b : abs(a - target) - abs(b - target)) - return nums[0]; - -}; - -function dfs(toppingCosts, ind, m, cost, costs) { - costs.add(cost); - if (ind >= m) return; - dfs(toppingCosts, ind + 1, m, cost, costs); - dfs(toppingCosts, ind + 1, m, cost + toppingCosts[ind], costs); - dfs(toppingCosts, ind + 1, m, cost + toppingCosts[ind] * 2, costs); -} diff --git a/1774.closest-dessert-cost.js b/1774.closest-dessert-cost.js new file mode 100644 index 00000000..70c5d142 --- /dev/null +++ b/1774.closest-dessert-cost.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} baseCosts + * @param {number[]} toppingCosts + * @param {number} target + * @return {number} + */ +const closestCost = function(baseCosts, toppingCosts, target) { + let res = baseCosts[0], n = baseCosts.length, m = toppingCosts.length + const { abs } = Math + for (let i = 0; i < n; i++) { + helper(0, baseCosts[i]) + } + return res + function helper(i, cur) { + if( + abs(cur - target) < abs(res - target) + || (abs(cur - target) === abs(res - target) && cur < res) + ) { + res = cur + } + if(i === m || cur > target) return + helper(i + 1, cur) + helper(i + 1, cur + toppingCosts[i]) + helper(i + 1, cur + toppingCosts[i] * 2) + } +}; + diff --git a/1775-equal-sum-arrays-with-minimum-number-of-operations.js b/1775-equal-sum-arrays-with-minimum-number-of-operations.js deleted file mode 100644 index 4f723a5a..00000000 --- a/1775-equal-sum-arrays-with-minimum-number-of-operations.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const minOperations = function(nums1, nums2) { - const m = nums1.length, n = nums2.length - if(m > n * 6 || n > m * 6) return -1 - let sum1 = sum(nums1), sum2 = sum(nums2) - if(sum1 > sum2) return minOperations(nums2, nums1) - - const arr = Array(6).fill(0) - nums1.forEach(e => arr[6 - e]++) - nums2.forEach(e => arr[e - 1]++) - - let res = 0, i = 5 - while(sum1 < sum2) { - while(arr[i] === 0) i-- - sum1 += i - res++ - arr[i]-- - } - - return res -}; - -function sum(arr) { - return arr.reduce((ac, e) => ac + e, 0) -} - -// another - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const minOperations = function(nums1, nums2) { - const m = nums1.length, n = nums2.length - if(m > n * 6 || n > m * 6) return -1 - const sum1 = nums1.reduce((ac, e) => ac + e, 0) - const sum2 = nums2.reduce((ac, e) => ac + e, 0) - let largerArr, smallerArr - if(sum1 === sum2) return 0 - if(sum1 > sum2) { - largerArr = nums1 - smallerArr = nums2 - } else { - largerArr = nums2 - smallerArr = nums1 - } - - const gain = [] - for(let e of largerArr) gain.push(e - 1) - for(let e of smallerArr) gain.push(6 - e) - gain.sort((a, b) => b - a) - let diff = Math.abs(sum2 - sum1) - let cnt = 0 - for(let e of gain) { - diff -= e - cnt++ - if(diff <= 0) return cnt - } - return -1 -}; - - - - -// another - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const minOperations = function(nums1, nums2) { - const len1 = nums1.length, len2 = nums2.length; - if (len1 > 6 * len2 || len2 > 6 * len1) return -1; - let sum1 = 0, sum2 = 0; - for (let x of nums1) sum1 += x; - for (let x of nums2) sum2 += x; - if (sum1 === sum2) return 0; - nums1.sort((a, b) => a - b) - nums2.sort((a, b) => a - b) - let cnt = 0; - if (sum1 > sum2) { - let ind1 = len1 - 1, ind2 = 0; - while (sum1 > sum2) { - if (ind2 === len2 || nums1[ind1] - 1 > 6 - nums2[ind2]) sum1 -= nums1[ind1--] - 1; - else sum2 += 6 - nums2[ind2++]; - cnt++; - } - return cnt; - } - let ind1 = 0, ind2 = len2 - 1; - while (sum1 < sum2) { - if (ind1 === len1 || nums2[ind2] - 1 > 6 - nums1[ind1]) sum2 -= nums2[ind2--] - 1; - else sum1 += 6 - nums1[ind1++]; - cnt++; - } - return cnt; -}; diff --git a/1775.equal-sum-arrays-with-minimum-number-of-operations.js b/1775.equal-sum-arrays-with-minimum-number-of-operations.js new file mode 100644 index 00000000..9a862402 --- /dev/null +++ b/1775.equal-sum-arrays-with-minimum-number-of-operations.js @@ -0,0 +1,30 @@ +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +const minOperations = function(nums1, nums2) { + const m = nums1.length, n = nums2.length + if(m > n * 6 || n > m * 6) return -1 + let sum1 = sum(nums1), sum2 = sum(nums2) + if(sum1 > sum2) return minOperations(nums2, nums1) + + const arr = Array(6).fill(0) + nums1.forEach(e => arr[6 - e]++) + nums2.forEach(e => arr[e - 1]++) + + let res = 0, i = 5 + while(sum1 < sum2) { + while(arr[i] === 0) i-- + sum1 += i + res++ + arr[i]-- + } + + return res +}; + +function sum(arr) { + return arr.reduce((ac, e) => ac + e, 0) +} + diff --git a/1776-car-fleet-ii.js b/1776-car-fleet-ii.js deleted file mode 100644 index 34d81e53..00000000 --- a/1776-car-fleet-ii.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @param {number[][]} cars - * @return {number[]} - */ -const getCollisionTimes = function(cars) { - const n = cars.length; - const stack = []; - const res = Array(n) - for(let i = n - 1; i >= 0; i--) { - const [p, s] = cars[i] - res[i] = -1 - while(stack.length) { - const j = stack[stack.length - 1] - const [p2, s2] = cars[j] - if(s2 >= s || res[j] > 0 && (p2 - p) / (s - s2) >= res[j]) stack.pop() - else break - } - if(stack.length) { - const j = stack[stack.length - 1] - const [p2, s2] = cars[j] - res[i] = (p2 - p) / (s - s2) - } - stack.push(i) - } - - return res -}; - -// another - - -/** - * @param {number[][]} cars - * @return {number[]} - */ -var getCollisionTimes = function(cars) { - //这道题必须想清楚一点,那就是如果ans[i]有正值,那么一定是cars[i]和某个cars[j](j>i且speed[j]= 0; i--) { - while(stack.length) { - //如果栈顶比我快,我追不上它,可以考虑等它消失之后我去撞它前面的,所以将它pop - if(cars[stack[stack.length - 1]][1] >= cars[i][1]) stack.pop() - //如果栈顶比我慢,我就决定去碰它了 - else { - //如果它不会消失,那我肯定能碰它,break - if(ans[stack[stack.length - 1]] < 0) break - //如果它会消失,我需要计算一下在它消失之前能否追上它 - const d = ans[stack[stack.length - 1]] * (cars[i][1] - cars[stack[stack.length - 1]][1]) - //能追上,那我肯定碰它,break - if(d > cars[stack[stack.length - 1]][0] - cars[i][0]) break - //追不上,那算了,追它前面的车 - else stack.pop() - } - } - if(stack.length === 0) ans[i] = -1 - else { - //相对距离除以相对速度 - const t = (cars[stack[stack.length - 1]][0]-cars[i][0])/(cars[i][1]-cars[stack[stack.length - 1]][1]) - ans[i] = t - } - stack.push(i) - } - return ans -}; - - -// another - -/** - * @param {number[][]} cars - * @return {number[]} - */ -var getCollisionTimes = function (cars) { - let n = cars.length, - t = 0, - i - const ans = Array(n) - for (let i = 0; i < n; i++) ans[i] = -1 - const s = [] - s[++t] = n - 1 - for (let i = n - 2; ~i; i--) { - while (t && cars[s[t]][1] >= cars[i][1]) t-- - while ( - t > 1 && - (cars[s[t]][0] - cars[i][0]) * (cars[i][1] - cars[s[t - 1]][1]) > - (cars[s[t - 1]][0] - cars[i][0]) * (cars[i][1] - cars[s[t]][1]) - ) - t-- - if (t) ans[i] = (cars[s[t]][0] - cars[i][0]) / (cars[i][1] - cars[s[t]][1]) - s[++t] = i - } - return ans -} diff --git a/1776.car-fleet-ii.js b/1776.car-fleet-ii.js new file mode 100644 index 00000000..726bd528 --- /dev/null +++ b/1776.car-fleet-ii.js @@ -0,0 +1,28 @@ +/** + * @param {number[][]} cars + * @return {number[]} + */ +const getCollisionTimes = function(cars) { + const n = cars.length; + const stack = []; + const res = Array(n) + for(let i = n - 1; i >= 0; i--) { + const [p, s] = cars[i] + res[i] = -1 + while(stack.length) { + const j = stack[stack.length - 1] + const [p2, s2] = cars[j] + if(s2 >= s || res[j] > 0 && (p2 - p) / (s - s2) >= res[j]) stack.pop() + else break + } + if(stack.length) { + const j = stack[stack.length - 1] + const [p2, s2] = cars[j] + res[i] = (p2 - p) / (s - s2) + } + stack.push(i) + } + + return res +}; + diff --git a/1779-find-nearest-point-that-has-the-same-x-or-y-coordinate.js b/1779.find-nearest-point-that-has-the-same-x-or-y-coordinate.js similarity index 100% rename from 1779-find-nearest-point-that-has-the-same-x-or-y-coordinate.js rename to 1779.find-nearest-point-that-has-the-same-x-or-y-coordinate.js diff --git a/1780-check-if-number-is-a-sum-of-powers-of-three.js b/1780.check-if-number-is-a-sum-of-powers-of-three.js similarity index 100% rename from 1780-check-if-number-is-a-sum-of-powers-of-three.js rename to 1780.check-if-number-is-a-sum-of-powers-of-three.js diff --git a/1781-sum-of-beauty-of-all-substrings.js b/1781.sum-of-beauty-of-all-substrings.js similarity index 100% rename from 1781-sum-of-beauty-of-all-substrings.js rename to 1781.sum-of-beauty-of-all-substrings.js diff --git a/1784-check-if-binary-string-has-at-most-one-segment-of-ones.js b/1784.check-if-binary-string-has-at-most-one-segment-of-ones.js similarity index 100% rename from 1784-check-if-binary-string-has-at-most-one-segment-of-ones.js rename to 1784.check-if-binary-string-has-at-most-one-segment-of-ones.js diff --git a/1785-minimum-elements-to-add-to-form-a-given-sum.js b/1785.minimum-elements-to-add-to-form-a-given-sum.js similarity index 100% rename from 1785-minimum-elements-to-add-to-form-a-given-sum.js rename to 1785.minimum-elements-to-add-to-form-a-given-sum.js diff --git a/1786-number-of-restricted-paths-from-first-to-last-node.js b/1786-number-of-restricted-paths-from-first-to-last-node.js deleted file mode 100644 index 6a80fd88..00000000 --- a/1786-number-of-restricted-paths-from-first-to-last-node.js +++ /dev/null @@ -1,172 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} edges - * @return {number} - */ -const countRestrictedPaths = function(n, edges) { - const adj = {} - const MOD = 10 ** 9 + 7 - for(let edge of edges) { - const [u,v,d] = edge - if(adj[u] == null) adj[u] = [] - if(adj[v] == null) adj[v] = [] - adj[u].push([v, d]) - adj[v].push([u, d]) - } - const dist = Array(n + 1).fill(Infinity) - dist[n] = 0 - const pq = new PriorityQueue((a, b) => a[0] < b[0]) - pq.push([0, n]) - while(!pq.isEmpty()) { - const [d, u] = pq.peek() - pq.pop() - if(d > dist[u]) continue - for(let [v, c] of adj[u]) { - if(d + c < dist[v]) { - dist[v] = d + c - pq.push([dist[v], v]) - } - } - } - - const order = Array(n).fill(0) - for(let i = 0; i < n; i++) { - order[i] = i + 1 - } - - order.sort((u, v) => dist[u] - dist[v]) - const ans = Array(n + 1).fill(0) - ans[n] = 1 - for(let u of order) { - for(let [v, c] of adj[u]) { - if(dist[v] > dist[u]) { - ans[v] = (ans[v] + ans[u]) % MOD - } - } - } - - return ans[1] -}; - - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -/** - * @param {number} n - * @param {number[][]} edges - * @return {number} - */ -const countRestrictedPaths = function(n, edges) { - if (n === 1) return 0 - const graph = {} - for(const [u, v, t] of edges) { - if(graph[u] == null) graph[u] = {} - if(graph[v] == null) graph[v] = {} - graph[u][v] = t - graph[v][u] = t - } - const dist = dijkstra(n, graph) - const memo = Array(n + 1).fill(null) - const res = dfs(1) - return res - - function dijkstra(n, graph) { - const dist = Array(n + 1).fill(Infinity) - dist[n] = 0 - const pq = new PriorityQueue((a, b) => a[0] < b[0]) - pq.push([0, n]) - while(!pq.isEmpty()) { - const [d, cur] = pq.pop() - if(d !== dist[cur]) continue - for(const next of Object.keys(graph[cur] || {})) { - const delta = graph[cur][next] - if(dist[next] > d + delta) { - dist[next] = d + delta - pq.push([d + delta, next]) - } - } - } - return dist - } - - function dfs(src) { - if(memo[src] != null) return memo[src] - if(src === n) return 1 - let res = 0 - for(let next of Object.keys(graph[src] || {})) { - next = +next - if(dist[src] > dist[next]) { - res = ((res + dfs(next)) % (1e9 + 7)) - } - } - return memo[src] = res - } -} diff --git a/1786.number-of-restricted-paths-from-first-to-last-node.js b/1786.number-of-restricted-paths-from-first-to-last-node.js new file mode 100644 index 00000000..11c2a5d2 --- /dev/null +++ b/1786.number-of-restricted-paths-from-first-to-last-node.js @@ -0,0 +1,119 @@ +/** + * @param {number} n + * @param {number[][]} edges + * @return {number} + */ +const countRestrictedPaths = function(n, edges) { + const adj = {} + const MOD = 10 ** 9 + 7 + for(let edge of edges) { + const [u,v,d] = edge + if(adj[u] == null) adj[u] = [] + if(adj[v] == null) adj[v] = [] + adj[u].push([v, d]) + adj[v].push([u, d]) + } + const dist = Array(n + 1).fill(Infinity) + dist[n] = 0 + const pq = new PriorityQueue((a, b) => a[0] < b[0]) + pq.push([0, n]) + while(!pq.isEmpty()) { + const [d, u] = pq.peek() + pq.pop() + if(d > dist[u]) continue + for(let [v, c] of adj[u]) { + if(d + c < dist[v]) { + dist[v] = d + c + pq.push([dist[v], v]) + } + } + } + + const order = Array(n).fill(0) + for(let i = 0; i < n; i++) { + order[i] = i + 1 + } + + order.sort((u, v) => dist[u] - dist[v]) + const ans = Array(n + 1).fill(0) + ans[n] = 1 + for(let u of order) { + for(let [v, c] of adj[u]) { + if(dist[v] > dist[u]) { + ans[v] = (ans[v] + ans[u]) % MOD + } + } + } + + return ans[1] +}; + + +class PriorityQueue { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + diff --git a/1787-make-the-xor-of-all-segments-equal-to-zero.js b/1787.make-the-xor-of-all-segments-equal-to-zero.js similarity index 100% rename from 1787-make-the-xor-of-all-segments-equal-to-zero.js rename to 1787.make-the-xor-of-all-segments-equal-to-zero.js diff --git a/179-largest-number.js b/179.largest-number.js similarity index 100% rename from 179-largest-number.js rename to 179.largest-number.js diff --git a/1790-check-if-one-string-swap-can-make-strings-equal.js b/1790.check-if-one-string-swap-can-make-strings-equal.js similarity index 100% rename from 1790-check-if-one-string-swap-can-make-strings-equal.js rename to 1790.check-if-one-string-swap-can-make-strings-equal.js diff --git a/1791-find-center-of-star-graph.js b/1791-find-center-of-star-graph.js deleted file mode 100644 index b57647b9..00000000 --- a/1791-find-center-of-star-graph.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @param {number[][]} edges - * @return {number} - */ -const findCenter = function(edges) { - return edges[0][0] === edges[1][0] || edges[0][0] === edges[1][1] ? edges[0][0] : edges[0][1] -}; - -// another - -/** - * @param {number[][]} edges - * @return {number} - */ -const findCenter = function(edges) { - const map = {} - for(let e of edges) { - const [u, v] = e - if(map[u] == null) map[u] = [] - if(map[v] == null) map[v] = [] - map[u].push(v) - map[v].push(u) - } - - const keys = Object.keys(map) - let res, max = -Infinity - keys.forEach(e => { - if(map[e].length > max) { - res = e - max = map[e].length - } - }) - - return res - -}; diff --git a/1791.find-center-of-star-graph.js b/1791.find-center-of-star-graph.js new file mode 100644 index 00000000..148d9566 --- /dev/null +++ b/1791.find-center-of-star-graph.js @@ -0,0 +1,8 @@ +/** + * @param {number[][]} edges + * @return {number} + */ +const findCenter = function(edges) { + return edges[0][0] === edges[1][0] || edges[0][0] === edges[1][1] ? edges[0][0] : edges[0][1] +}; + diff --git a/1792-maximum-average-pass-ratio.js b/1792-maximum-average-pass-ratio.js deleted file mode 100644 index 58573af6..00000000 --- a/1792-maximum-average-pass-ratio.js +++ /dev/null @@ -1,211 +0,0 @@ -/** - * @param {number[][]} classes - * @param {number} extraStudents - * @return {number} - */ -const maxAverageRatio = function (classes, extraStudents) { - const pq = new PriorityQueue((a, b) => a.delta > b.delta) - const n = classes.length - for (let e of classes) { - pq.push({ - pass: e[0], - total: e[1], - ratio: e[0] / e[1], - delta: (e[0] + 1) / (e[1] + 1) - e[0] / e[1], - }) - } - - while (extraStudents) { - const tmp = pq.pop() - tmp.pass++ - tmp.total++ - tmp.ratio = tmp.pass / tmp.total - tmp.delta = (tmp.pass + 1) / (tmp.total + 1) - tmp.ratio - pq.push(tmp) - extraStudents-- - } - - let res = 0 - while (!pq.isEmpty()) { - const tmp = pq.pop() - res += tmp.ratio - } - - return res / n -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - - - -// another - -/** - * @param {number[][]} classes - * @param {number} extraStudents - * @return {number} - */ -const maxAverageRatio = function(classes, extraStudents) { - const pq = new PriorityQueue((a, b) => a.up > b.up); - for (let x of classes) pq.push(new Node(x[0], x[1])); - while (extraStudents--) { - let temp = pq.peek(); - pq.pop(); - temp.pass++, temp.total++; - temp.calUp(); - pq.push(temp); - } - let total = 0.0; - let n = classes.length; - while (!pq.isEmpty()) { - let temp = pq.peek(); - pq.pop(); - total += temp.pass / temp.total; - } - return total / n; -}; - -class Node { - constructor(pass, total) { - this.pass = pass - this.total = total - this.calUp() - } - calUp() { - this.up = (this.pass + 1) / (this.total + 1) - this.pass / this.total - } -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/1792.maximum-average-pass-ratio.js b/1792.maximum-average-pass-ratio.js new file mode 100644 index 00000000..c527ab2d --- /dev/null +++ b/1792.maximum-average-pass-ratio.js @@ -0,0 +1,106 @@ +/** + * @param {number[][]} classes + * @param {number} extraStudents + * @return {number} + */ +const maxAverageRatio = function (classes, extraStudents) { + const pq = new PriorityQueue((a, b) => a.delta > b.delta) + const n = classes.length + for (let e of classes) { + pq.push({ + pass: e[0], + total: e[1], + ratio: e[0] / e[1], + delta: (e[0] + 1) / (e[1] + 1) - e[0] / e[1], + }) + } + + while (extraStudents) { + const tmp = pq.pop() + tmp.pass++ + tmp.total++ + tmp.ratio = tmp.pass / tmp.total + tmp.delta = (tmp.pass + 1) / (tmp.total + 1) - tmp.ratio + pq.push(tmp) + extraStudents-- + } + + let res = 0 + while (!pq.isEmpty()) { + const tmp = pq.pop() + res += tmp.ratio + } + + return res / n +} + +class PriorityQueue { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + + + diff --git a/1793-maximum-score-of-a-good-subarray.js b/1793-maximum-score-of-a-good-subarray.js deleted file mode 100644 index 980891cc..00000000 --- a/1793-maximum-score-of-a-good-subarray.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const maximumScore = function(nums, k) { - const n = nums.length, {min, max} = Math - let mini = nums[k]; - let ans = mini; - let i = k; - let j = k; - - while (i > 0 || j < n - 1) { - if (i === 0 || (j + 1 < n && nums[i - 1] <= nums[j + 1])) { - j++; - mini = min(mini, nums[j]); - } else { - i--; - mini = min(mini, nums[i]); - } - ans = max(ans, mini * (j - i + 1)); - } - - return ans; -}; - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const maximumScore = function(nums, k) { - const n = nums.length, { max, min } = Math - let l = k, r = k, mi = nums[k] - let res = nums[k] - while(l > 0 || r < n - 1) { - if(l === 0) r++ - else if(r === n - 1) l-- - else if(nums[l - 1] < nums[r + 1]) r++ - else l-- - mi = min(mi, nums[l], nums[r]) - res = max(res, mi * (r - l + 1)) - } - - return res -}; diff --git a/1793.maximum-score-of-a-good-subarray.js b/1793.maximum-score-of-a-good-subarray.js new file mode 100644 index 00000000..584c8525 --- /dev/null +++ b/1793.maximum-score-of-a-good-subarray.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const maximumScore = function(nums, k) { + const n = nums.length, {min, max} = Math + let mini = nums[k]; + let ans = mini; + let i = k; + let j = k; + + while (i > 0 || j < n - 1) { + if (i === 0 || (j + 1 < n && nums[i - 1] <= nums[j + 1])) { + j++; + mini = min(mini, nums[j]); + } else { + i--; + mini = min(mini, nums[i]); + } + ans = max(ans, mini * (j - i + 1)); + } + + return ans; +}; + diff --git a/1798-maximum-number-of-consecutive-values-you-can-make.js b/1798.maximum-number-of-consecutive-values-you-can-make.js similarity index 100% rename from 1798-maximum-number-of-consecutive-values-you-can-make.js rename to 1798.maximum-number-of-consecutive-values-you-can-make.js diff --git a/1799-maximize-score-after-n-operations.js b/1799.maximize-score-after-n-operations.js similarity index 100% rename from 1799-maximize-score-after-n-operations.js rename to 1799.maximize-score-after-n-operations.js diff --git a/18-4sum.js b/18-4sum.js deleted file mode 100644 index 069b349b..00000000 --- a/18-4sum.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} target - * @return {number[][]} - */ -const fourSum = function (nums, target) { - nums.sort((a, b) => a - b) - const results = [] - kSum(nums, target, 4, 0, [], results) - return results -} - -function kSum(nums, target, k, i, acc, results) { - if (nums[i] * k > target || nums[nums.length - 1] * k < target) return - if (k > 2) { - for (let j = i; j <= nums.length - k; j++) { - if (j == i || nums[j] > nums[j - 1]) - kSum(nums, target - nums[j], k - 1, j + 1, [...acc, nums[j]], results) - } - } else { - twoSum(nums, target, i, acc, results) - } -} - -function twoSum(nums, target, i, acc, results) { - let lo = i - let hi = nums.length - 1 - while (lo < hi) { - const sum = nums[lo] + nums[hi] - if (sum == target) { - results.push([...acc, nums[lo], nums[hi]]) - while (nums[lo] == nums[lo + 1]) lo++ - while (nums[hi] == nums[hi - 1]) hi-- - lo++ - hi-- - } else if (sum < target) { - lo++ - } else { - hi-- - } - } -} - - -// another - -/** - * @param {number[]} nums - * @param {number} target - * @return {number[][]} - */ -const fourSum = function(nums, target) { - return nSum(nums.sort((a, b) => a - b), target, 4, 0); -}; - -function nSum(nums, target, k, start) { - const res = []; - if (nums.length < k || k < 2 || target < nums[0] * k || target > nums[-1] * k) - return res; - if (k == 2) { - // 2 sum; ( improved to O(n) ) - let r = nums.length - 1; - let l = start; - while (l < r) { - if (nums[l] + nums[r] === target) { - res.push([nums[l], nums[r]]); - //skip duplication - while (l < r && nums[l] === nums[l + 1]) l++; - while (l < r && nums[r] === nums[r - 1]) r--; - l++; - r--; - } else if (nums[l] + nums[r] < target) { - l++; - } else { - r--; - } - } - } else { - for (let i = start; i < nums.length - k + 1; i++) { - if (i === start || (i > start && nums[i] !== nums[i - 1])) { - let temp = nSum(nums, target - nums[i], k - 1, i + 1); - temp.forEach(t => { - t.push(nums[i]); - res.push(t); - }); - } - } - } - return res; -} diff --git a/18.4sum.js b/18.4sum.js new file mode 100644 index 00000000..d910a721 --- /dev/null +++ b/18.4sum.js @@ -0,0 +1,44 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number[][]} + */ +const fourSum = function (nums, target) { + nums.sort((a, b) => a - b) + const results = [] + kSum(nums, target, 4, 0, [], results) + return results +} + +function kSum(nums, target, k, i, acc, results) { + if (nums[i] * k > target || nums[nums.length - 1] * k < target) return + if (k > 2) { + for (let j = i; j <= nums.length - k; j++) { + if (j == i || nums[j] > nums[j - 1]) + kSum(nums, target - nums[j], k - 1, j + 1, [...acc, nums[j]], results) + } + } else { + twoSum(nums, target, i, acc, results) + } +} + +function twoSum(nums, target, i, acc, results) { + let lo = i + let hi = nums.length - 1 + while (lo < hi) { + const sum = nums[lo] + nums[hi] + if (sum == target) { + results.push([...acc, nums[lo], nums[hi]]) + while (nums[lo] == nums[lo + 1]) lo++ + while (nums[hi] == nums[hi - 1]) hi-- + lo++ + hi-- + } else if (sum < target) { + lo++ + } else { + hi-- + } + } +} + + diff --git a/1800-maximum-ascending-subarray-sum.js b/1800.maximum-ascending-subarray-sum.js similarity index 100% rename from 1800-maximum-ascending-subarray-sum.js rename to 1800.maximum-ascending-subarray-sum.js diff --git a/1801-number-of-orders-in-the-backlog.js b/1801.number-of-orders-in-the-backlog.js similarity index 100% rename from 1801-number-of-orders-in-the-backlog.js rename to 1801.number-of-orders-in-the-backlog.js diff --git a/1802-maximum-value-at-a-given-index-in-a-bounded-array.js b/1802-maximum-value-at-a-given-index-in-a-bounded-array.js deleted file mode 100644 index 64d18833..00000000 --- a/1802-maximum-value-at-a-given-index-in-a-bounded-array.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - * @param {number} n - * @param {number} index - * @param {number} maxSum - * @return {number} - */ -const maxValue = function (n, index, maxSum) { - maxSum -= n; - let left = 0, right = maxSum, mid; - while (left < right) { - const mid = right - Math.floor((right - left) / 2); - if (valid(mid))left = mid; - else right = mid - 1; - } - return left + 1; - - function valid(mid) { - let b = Math.max(mid - index, 0); - let res = (mid + b) * (mid - b + 1) / 2; - b = Math.max(mid - ((n - 1) - index), 0); - res += (mid + b) * (mid - b + 1) / 2; - return res - mid <= maxSum; - } -} - -// another - - -/** - * @param {number} n - * @param {number} index - * @param {number} maxSum - * @return {number} - */ -const maxValue = function(n, index, maxSum) { - let res = 1, l = index, r = index - maxSum -= n - - while(l > 0 || r < n - 1) { - const len = r - l + 1 - if(maxSum >= len) { - maxSum -= len - res++ - } else break - if(l > 0) l-- - if(r < n - 1) r++ - } - res += ~~(maxSum / n) - - return res -} - -// another - - -/** - * @param {number} n - * @param {number} index - * @param {number} maxSum - * @return {number} - */ -const maxValue = function(n, index, maxSum) { - maxSum -= n; - let level = 1; - let left = index; - let right = index; - - while (maxSum - (right - left + 1) >= 0) { - if (left === 0 && right === n - 1) break - maxSum -= right - left + 1; - if (left - 1 >= 0) left-- - if (right + 1 <= n - 1) right++; - level++; - } - - if (maxSum) level += ~~(maxSum / n) - - return level; -} - -// another - - -/** - * @param {number} n - * @param {number} index - * @param {number} maxSum - * @return {number} - */ -const maxValue = function(n, index, maxSum) { - const { floor, sqrt } = Math - maxSum -= n - if(index < Math.floor(n / 2)) index = n - 1 - index - let left = index // number of element to the left of the index - let right = n - 1 - index // number of element to the right of the index - // the triangle area for the left side if not hitting the boundary - let leftSum = floor((left * (left + 1)) / 2) - // the triangle area for the right side if not hitting the boundary - let rightSum = floor((right * (right + 1)) / 2) - // case: perfect pyramid - if (maxSum <= (rightSum * 2 + right + 1)) return floor(sqrt(maxSum) + 1) - // case: right side hits the boundary - if (maxSum <= (leftSum + rightSum + (left - right) * right + left + 1)) { - const b = 3 + 2 * right - return floor((-b + sqrt(b * b - 8 * (rightSum + 1 - right * right - maxSum))) / 2) + 1 + 1 - } - // case: both sides hit boundaries - maxSum -= (leftSum + rightSum + (left - right) * right + left + 1) - return left + 1 + 1 + floor(maxSum / n) -}; - -// another - -/** - * @param {number} n - * @param {number} index - * @param {number} maxSum - * @return {number} - */ -const maxValue = function (n, index, maxSum) { - let ret = 0 - const { max } = Math - for (let i = 30; i >= 0; i--) { - const tmp = ret + (1 << i) - const L = max(0, tmp - index) - let sum = ((L + tmp) * (tmp - L + 1)) / 2 - const R = max(0, tmp - (n - 1 - index)) - sum += ((R + tmp) * (tmp - R + 1)) / 2 - tmp - - if (sum <= maxSum - n) ret += 1 << i - } - return ret + 1 -} diff --git a/1802.maximum-value-at-a-given-index-in-a-bounded-array.js b/1802.maximum-value-at-a-given-index-in-a-bounded-array.js new file mode 100644 index 00000000..b3a438b3 --- /dev/null +++ b/1802.maximum-value-at-a-given-index-in-a-bounded-array.js @@ -0,0 +1,25 @@ +/** + * @param {number} n + * @param {number} index + * @param {number} maxSum + * @return {number} + */ +const maxValue = function (n, index, maxSum) { + maxSum -= n; + let left = 0, right = maxSum, mid; + while (left < right) { + const mid = right - Math.floor((right - left) / 2); + if (valid(mid))left = mid; + else right = mid - 1; + } + return left + 1; + + function valid(mid) { + let b = Math.max(mid - index, 0); + let res = (mid + b) * (mid - b + 1) / 2; + b = Math.max(mid - ((n - 1) - index), 0); + res += (mid + b) * (mid - b + 1) / 2; + return res - mid <= maxSum; + } +} + diff --git a/1803-count-pairs-with-xor-in-a-range.js b/1803.count-pairs-with-xor-in-a-range.js similarity index 100% rename from 1803-count-pairs-with-xor-in-a-range.js rename to 1803.count-pairs-with-xor-in-a-range.js diff --git a/1804-implement-trie-ii-prefix-tree.js b/1804.implement-trie-ii-prefix-tree.js similarity index 100% rename from 1804-implement-trie-ii-prefix-tree.js rename to 1804.implement-trie-ii-prefix-tree.js diff --git a/1805-number-of-different-integers-in-a-string.js b/1805.number-of-different-integers-in-a-string.js similarity index 100% rename from 1805-number-of-different-integers-in-a-string.js rename to 1805.number-of-different-integers-in-a-string.js diff --git a/1806-minimum-number-of-operations-to-reinitialize-a-permutation.js b/1806-minimum-number-of-operations-to-reinitialize-a-permutation.js deleted file mode 100644 index 3176daf4..00000000 --- a/1806-minimum-number-of-operations-to-reinitialize-a-permutation.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const reinitializePermutation = function(n) { - let perm = [] - for(let i = 0; i < n; i++) { - perm[i] = i - } - let clone = perm.slice() - let res = 0 - - while(true) { - res++ - let arr = clone.slice() - for(let i = 0; i < clone.length; i++) { - if(i % 2 === 0) arr[i] = clone[i / 2] - else arr[i] = clone[n / 2 + (i - 1) / 2] - } - - if(chk(perm, arr)) break - clone = arr - } - - - return res - - function chk(a1, a2) { - for(let i = 0, len = a1.length; i < len; i++) { - if(a1[i] !== a2[i]) return false - } - return true - } -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const reinitializePermutation = function(n) { - let res = 0, i = 1; - while (res === 0 || i > 1) { - i = i * 2 % (n - 1); - res++; - } - return res; -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const reinitializePermutation = function(n) { - if (n === 2) return 1 - const mod = n - 1 - let curr_power = 2 - let cnt = 1 - // Find multiplicative order modulo n-1 - while (curr_power !== 1) { - curr_power = (2 * curr_power) % mod - cnt++ - } - return cnt -}; diff --git a/1806.minimum-number-of-operations-to-reinitialize-a-permutation.js b/1806.minimum-number-of-operations-to-reinitialize-a-permutation.js new file mode 100644 index 00000000..206905bb --- /dev/null +++ b/1806.minimum-number-of-operations-to-reinitialize-a-permutation.js @@ -0,0 +1,35 @@ +/** + * @param {number} n + * @return {number} + */ +const reinitializePermutation = function(n) { + let perm = [] + for(let i = 0; i < n; i++) { + perm[i] = i + } + let clone = perm.slice() + let res = 0 + + while(true) { + res++ + let arr = clone.slice() + for(let i = 0; i < clone.length; i++) { + if(i % 2 === 0) arr[i] = clone[i / 2] + else arr[i] = clone[n / 2 + (i - 1) / 2] + } + + if(chk(perm, arr)) break + clone = arr + } + + + return res + + function chk(a1, a2) { + for(let i = 0, len = a1.length; i < len; i++) { + if(a1[i] !== a2[i]) return false + } + return true + } +}; + diff --git a/1807-evaluate-the-bracket-pairs-of-a-string.js b/1807.evaluate-the-bracket-pairs-of-a-string.js similarity index 100% rename from 1807-evaluate-the-bracket-pairs-of-a-string.js rename to 1807.evaluate-the-bracket-pairs-of-a-string.js diff --git a/1808-maximize-number-of-nice-divisors.js b/1808.maximize-number-of-nice-divisors.js similarity index 100% rename from 1808-maximize-number-of-nice-divisors.js rename to 1808.maximize-number-of-nice-divisors.js diff --git a/1815-maximum-number-of-groups-getting-fresh-donuts.js b/1815.maximum-number-of-groups-getting-fresh-donuts.js similarity index 100% rename from 1815-maximum-number-of-groups-getting-fresh-donuts.js rename to 1815.maximum-number-of-groups-getting-fresh-donuts.js diff --git a/1816-truncate-sentence.js b/1816.truncate-sentence.js similarity index 100% rename from 1816-truncate-sentence.js rename to 1816.truncate-sentence.js diff --git a/1817-finding-the-users-active-minutes.js b/1817.finding-the-users-active-minutes.js similarity index 100% rename from 1817-finding-the-users-active-minutes.js rename to 1817.finding-the-users-active-minutes.js diff --git a/1818-minimum-absolute-sum-difference.js b/1818.minimum-absolute-sum-difference.js similarity index 100% rename from 1818-minimum-absolute-sum-difference.js rename to 1818.minimum-absolute-sum-difference.js diff --git a/1819-number-of-different-subsequences-gcds.js b/1819.number-of-different-subsequences-gcds.js similarity index 100% rename from 1819-number-of-different-subsequences-gcds.js rename to 1819.number-of-different-subsequences-gcds.js diff --git a/1822-sign-of-the-product-of-an-array.js b/1822.sign-of-the-product-of-an-array.js similarity index 100% rename from 1822-sign-of-the-product-of-an-array.js rename to 1822.sign-of-the-product-of-an-array.js diff --git a/1823-find-the-winner-of-the-circular-game.js b/1823.find-the-winner-of-the-circular-game.js similarity index 100% rename from 1823-find-the-winner-of-the-circular-game.js rename to 1823.find-the-winner-of-the-circular-game.js diff --git a/1824-minimum-sideway-jumps.js b/1824.minimum-sideway-jumps.js similarity index 100% rename from 1824-minimum-sideway-jumps.js rename to 1824.minimum-sideway-jumps.js diff --git a/1825-finding-mk-average.js b/1825.finding-mk-average.js similarity index 100% rename from 1825-finding-mk-average.js rename to 1825.finding-mk-average.js diff --git a/1827-minimum-operations-to-make-the-array-increasing.js b/1827.minimum-operations-to-make-the-array-increasing.js similarity index 100% rename from 1827-minimum-operations-to-make-the-array-increasing.js rename to 1827.minimum-operations-to-make-the-array-increasing.js diff --git a/1828-queries-on-number-of-points-inside-a-circle.js b/1828.queries-on-number-of-points-inside-a-circle.js similarity index 100% rename from 1828-queries-on-number-of-points-inside-a-circle.js rename to 1828.queries-on-number-of-points-inside-a-circle.js diff --git a/1829-maximum-xor-for-each-query.js b/1829.maximum-xor-for-each-query.js similarity index 100% rename from 1829-maximum-xor-for-each-query.js rename to 1829.maximum-xor-for-each-query.js diff --git a/1830-minimum-number-of-operations-to-make-string-sorted.js b/1830-minimum-number-of-operations-to-make-string-sorted.js deleted file mode 100644 index 702e0c27..00000000 --- a/1830-minimum-number-of-operations-to-make-string-sorted.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const makeStringSorted = function (s) { - const mod = 1e9 + 7, - n = s.length - const a = 'a'.charCodeAt(0) - let res = 0 - const freq = Array(26).fill(0) - for (let c of s) { - freq[c.charCodeAt(0) - a]++ - } - const fact = Array(n + 1).fill(1) - getfact() - let l = n - for (let c of s) { - l-- - let t = 0, - rev = 1 - for (let i = 0; i < 26; i++) { - if (i < c.charCodeAt(0) - a) t += freq[i] - rev = modmul(rev, fact[freq[i]]) - } - res += modmul(modmul(t, fact[l]), binExpo(rev, mod - 2)) - res %= mod - freq[c.charCodeAt(0) - a]-- - } - return res - - function modmul(a, b) { - const big = BigInt - return Number(((big(a) % big(mod)) * (big(b) % big(mod))) % big(mod)) - } - - function binExpo(a, b) { - if (b === 0) return 1 - let res = binExpo(a, Math.floor(b / 2)) - if (b & 1) { - return modmul(a, modmul(res, res)) - } else { - return modmul(res, res) - } - } - - function modmulinv(a) { - return binExpo(a, mod - 2) - } - - function getfact() { - fact[0] = 1 - for (let i = 1; i <= 3000; i++) { - fact[i] = modmul(fact[i - 1], i) - } - } - -} - - -// another - - - -/** - * @param {string} s - * @return {number} - */ -const makeStringSorted = function (s) { - const mod = BigInt(10 ** 9 + 7), - n = s.length - const a = 'a'.charCodeAt(0) - let ans = 0n - const freq = Array(26).fill(0n) - for (let c of s) { - freq[c.charCodeAt(0) - a]++ - } - const fact = Array(n + 1).fill(1n) - for (let i = 1n; i <= n; i++) { - fact[i] = (fact[i - 1n] * i) % mod - } - let l = n - for (let c of s) { - l-- - let t = 0n, - rev = 1n - for (let i = 0; i < 26; i++) { - if (i < c.charCodeAt(0) - a) t += freq[i] - rev = (rev * fact[freq[i]]) % mod - } - ans += ((t * fact[l]) % mod) * modpow(rev, mod - 2n) - ans %= mod - freq[c.charCodeAt(0) - a]-- - } - return Number(ans) - function modpow(b, p) { - let ans = 1n - for (; p; p >>= 1n) { - if (p & 1n) ans = (ans * b) % mod - b = (b * b) % mod - } - return ans - } -} diff --git a/1830.minimum-number-of-operations-to-make-string-sorted.js b/1830.minimum-number-of-operations-to-make-string-sorted.js new file mode 100644 index 00000000..e7143d4d --- /dev/null +++ b/1830.minimum-number-of-operations-to-make-string-sorted.js @@ -0,0 +1,59 @@ +/** + * @param {string} s + * @return {number} + */ +const makeStringSorted = function (s) { + const mod = 1e9 + 7, + n = s.length + const a = 'a'.charCodeAt(0) + let res = 0 + const freq = Array(26).fill(0) + for (let c of s) { + freq[c.charCodeAt(0) - a]++ + } + const fact = Array(n + 1).fill(1) + getfact() + let l = n + for (let c of s) { + l-- + let t = 0, + rev = 1 + for (let i = 0; i < 26; i++) { + if (i < c.charCodeAt(0) - a) t += freq[i] + rev = modmul(rev, fact[freq[i]]) + } + res += modmul(modmul(t, fact[l]), binExpo(rev, mod - 2)) + res %= mod + freq[c.charCodeAt(0) - a]-- + } + return res + + function modmul(a, b) { + const big = BigInt + return Number(((big(a) % big(mod)) * (big(b) % big(mod))) % big(mod)) + } + + function binExpo(a, b) { + if (b === 0) return 1 + let res = binExpo(a, Math.floor(b / 2)) + if (b & 1) { + return modmul(a, modmul(res, res)) + } else { + return modmul(res, res) + } + } + + function modmulinv(a) { + return binExpo(a, mod - 2) + } + + function getfact() { + fact[0] = 1 + for (let i = 1; i <= 3000; i++) { + fact[i] = modmul(fact[i - 1], i) + } + } + +} + + diff --git a/1832-check-if-the-sentence-is-pangram.js b/1832.check-if-the-sentence-is-pangram.js similarity index 100% rename from 1832-check-if-the-sentence-is-pangram.js rename to 1832.check-if-the-sentence-is-pangram.js diff --git a/1833-maximum-ice-cream-bars.js b/1833.maximum-ice-cream-bars.js similarity index 100% rename from 1833-maximum-ice-cream-bars.js rename to 1833.maximum-ice-cream-bars.js diff --git a/1834-single-threaded-cpu.js b/1834-single-threaded-cpu.js deleted file mode 100644 index 192aedec..00000000 --- a/1834-single-threaded-cpu.js +++ /dev/null @@ -1,284 +0,0 @@ -/** - * @param {number[][]} tasks - * @return {number[]} - */ -const getOrder = function(tasks) { - const pq = new PriorityQueue(compare), n = tasks.length - const res = [] - let time = 0, i = 0 - for(let i = 0; i < n; i++) tasks[i].push(i) - tasks.sort((a, b) => a[0] - b[0]) - - time = tasks[0][0] - while(i < n || !pq.isEmpty()) { - while ((i < n) && (tasks[i][0] <= time)) { - pq.push([tasks[i][1], tasks[i][2]]) - i++ - } - if(!pq.isEmpty()) { - const [dur, idx] = pq.pop() - time += dur - res.push(idx) - } else if(i < n) { - time = tasks[i][0] - } - - } - - return res -}; - -function compare(a, b) { - if(a[0] < b[0]) return true - else if (a[0] > b[0]) return false - else { - return a[1] < b[1] - } -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - - -// another - -/** - * @param {number[][]} tasks - * @return {number[]} - */ -const getOrder = function(tasks) { - const pq = new PriorityQueue(compare), n = tasks.length - const res = [] - let time = 0, i = 0 - for(let i = 0; i < n; i++) tasks[i].push(i) - tasks.sort((a, b) => a[0] - b[0]) - - while(i < n || !pq.isEmpty()) { - if(pq.isEmpty()) { - time = Math.max(time, tasks[i][0]) - } - while(i < n && time >= tasks[i][0]) { - pq.push([tasks[i][1], tasks[i][2]]) - i++ - } - const [dur, idx] = pq.pop() - time += dur - res.push(idx) - } - - return res -}; - -function compare(a, b) { - if(a[0] < b[0]) return true - else if (a[0] > b[0]) return false - else { - return a[1] < b[1] - } -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another -/** - * @param {number[][]} tasks - * @return {number[]} - */ -const getOrder = function(tasks) { - const n = tasks.length - const pq = new PriorityQueue((a, b) => a[0] === b[0] ? a[1] < b[1] : a[0] < b[0]) - tasks.forEach((e, i) => e.push(i)) - tasks.sort((a, b) => a[0] - b[0]) - let idx = 0, time = 0 - const res = [] - - while(idx < n || !pq.isEmpty()) { - while(idx < n && tasks[idx][0] <= time) { - pq.push([tasks[idx][1], task[idx][2]]) - idx++ - } - if(!pq.isEmpty()) { - const tmp = pq.pop() - time += tmp[0] - res.push(tmp[1]) - } else if(idx < n) { - time = tasks[idx][0] - } - } - return res - -}; - -// another - -/** - * @param {number[][]} tasks - * @return {number[]} - */ -const getOrder = function (tasks) { - tasks = tasks.map((e, idx) => [e[0], e[1], idx]) - tasks.sort((a, b) => a[0] - b[0]) - const pq = new PriorityQueue(compare) - const res = [] - let i = 0, - t = 0 - while (i < tasks.length) { - while (i < tasks.length && tasks[i][0] <= t) { - let [ent, pt, ind] = tasks[i] - i += 1 - pq.push([pt, ind]) - } - if (pq.size() == 0) { - if (i < tasks.length) t = tasks[i][0] - continue - } - let [pt, ind] = pq.pop() - res.push(ind) - t += pt - } - while (pq.size()) { - let [pt, index] = pq.pop() - res.push(index) - } - return res -} - -function compare(a, b) { - if (a[0] < b[0]) return true - else if (a[0] > b[0]) return false - else { - return a[1] < b[1] - } -} - diff --git a/1834.single-threaded-cpu.js b/1834.single-threaded-cpu.js new file mode 100644 index 00000000..2b67979e --- /dev/null +++ b/1834.single-threaded-cpu.js @@ -0,0 +1,107 @@ +/** + * @param {number[][]} tasks + * @return {number[]} + */ +const getOrder = function(tasks) { + const pq = new PriorityQueue(compare), n = tasks.length + const res = [] + let time = 0, i = 0 + for(let i = 0; i < n; i++) tasks[i].push(i) + tasks.sort((a, b) => a[0] - b[0]) + + time = tasks[0][0] + while(i < n || !pq.isEmpty()) { + while ((i < n) && (tasks[i][0] <= time)) { + pq.push([tasks[i][1], tasks[i][2]]) + i++ + } + if(!pq.isEmpty()) { + const [dur, idx] = pq.pop() + time += dur + res.push(idx) + } else if(i < n) { + time = tasks[i][0] + } + + } + + return res +}; + +function compare(a, b) { + if(a[0] < b[0]) return true + else if (a[0] > b[0]) return false + else { + return a[1] < b[1] + } +} + +class PriorityQueue { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + + diff --git a/1835-find-xor-sum-of-all-pairs-bitwise-and.js b/1835-find-xor-sum-of-all-pairs-bitwise-and.js deleted file mode 100644 index 795a8fcf..00000000 --- a/1835-find-xor-sum-of-all-pairs-bitwise-and.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @param {number[]} arr1 - * @param {number[]} arr2 - * @return {number} - */ -const getXORSum = function(arr1, arr2) { - let a = 0, b = 0 - for(const e of arr1) a ^= e - for(const e of arr2) b ^= e - - return a & b -}; - - -// another - -// On every bit XOR acts as modulo 2 addition and AND acts as modulo 2 multiplication. -// The set {0,1} with modulo 2 addition and multiplication is the field GF(2) and the distributive property holds in every field. - -/** - * @param {number[]} arr1 - * @param {number[]} arr2 - * @return {number} - */ -const getXORSum = function(arr1, arr2) { - const bits = Array(32).fill(0) - for (let v of arr2) { - let pos = 0; - while (v > 0) { - if (v & 1) { - bits[pos]++; - } - v = v >> 1; - pos++; - } - } - - let res = 0; - - for (let v of arr1) { - let pos = 0; - let tmp = 0; - while (v > 0) { - if (v & 1) { - if (bits[pos] % 2 == 1) { - tmp |= (1 << pos); - } - } - v = v >> 1; - pos++; - } - - res ^= tmp; - } - - return res; -}; - -// another - -/** - * @param {number[]} arr1 - * @param {number[]} arr2 - * @return {number} - */ -const getXORSum = function(arr1, arr2) { - let x1 = arr1[0], x2 = arr2[0] - for(let i = 1; i < arr1.length; i++) x1 ^= arr1[i] - for(let i = 1; i < arr2.length; i++) x2 ^= arr2[i] - return x1 & x2 -}; diff --git a/1835.find-xor-sum-of-all-pairs-bitwise-and.js b/1835.find-xor-sum-of-all-pairs-bitwise-and.js new file mode 100644 index 00000000..4d9563e3 --- /dev/null +++ b/1835.find-xor-sum-of-all-pairs-bitwise-and.js @@ -0,0 +1,14 @@ +/** + * @param {number[]} arr1 + * @param {number[]} arr2 + * @return {number} + */ +const getXORSum = function(arr1, arr2) { + let a = 0, b = 0 + for(const e of arr1) a ^= e + for(const e of arr2) b ^= e + + return a & b +}; + + diff --git a/1836-remove-duplicates-from-an-unsorted-linked-list.js b/1836.remove-duplicates-from-an-unsorted-linked-list.js similarity index 100% rename from 1836-remove-duplicates-from-an-unsorted-linked-list.js rename to 1836.remove-duplicates-from-an-unsorted-linked-list.js diff --git a/1837-sum-of-digits-in-base-k.js b/1837.sum-of-digits-in-base-k.js similarity index 100% rename from 1837-sum-of-digits-in-base-k.js rename to 1837.sum-of-digits-in-base-k.js diff --git a/1838-frequency-of-the-most-frequent-element.js b/1838-frequency-of-the-most-frequent-element.js deleted file mode 100644 index b57a76f9..00000000 --- a/1838-frequency-of-the-most-frequent-element.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const maxFrequency = function(nums, k) { - let res = 1, i = 0, j = 0, sum = 0 - const n = nums.length - nums.sort((a, b) => a - b) - for(j = 0; j < n; j++) { - sum += nums[j] - while(sum + k < (j - i + 1) * nums[j]) { - sum -= nums[i] - i++ - } - res = Math.max(res, j - i + 1) - } - return res -}; - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const maxFrequency = function(nums, k) { - nums.sort((a, b) => a - b) - let i = 0, sum = 0, res = 1 - for(let j = 0; j < nums.length; j++) { - sum += nums[j] - while(sum + k < (j - i + 1) * nums[j]) { - sum -= nums[i] - i++ - } - res = Math.max(res, j - i + 1) - } - return res -}; diff --git a/1838.frequency-of-the-most-frequent-element.js b/1838.frequency-of-the-most-frequent-element.js new file mode 100644 index 00000000..5706c6b2 --- /dev/null +++ b/1838.frequency-of-the-most-frequent-element.js @@ -0,0 +1,20 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const maxFrequency = function(nums, k) { + let res = 1, i = 0, j = 0, sum = 0 + const n = nums.length + nums.sort((a, b) => a - b) + for(j = 0; j < n; j++) { + sum += nums[j] + while(sum + k < (j - i + 1) * nums[j]) { + sum -= nums[i] + i++ + } + res = Math.max(res, j - i + 1) + } + return res +}; + diff --git a/1839-longest-substring-of-all-vowels-in-order.js b/1839-longest-substring-of-all-vowels-in-order.js deleted file mode 100644 index d5d78f94..00000000 --- a/1839-longest-substring-of-all-vowels-in-order.js +++ /dev/null @@ -1,84 +0,0 @@ -/** - * @param {string} word - * @return {number} - */ -function longestBeautifulSubstring(word) { - let res = 0, cur = 'a', cnt = 0 - const set = new Set() - for(let ch of word) { - if(ch < cur) { - set.clear() - cnt = 0 - cur = 'a' - if(ch === cur) { - cnt++ - set.add(cur) - } - } else { - cnt++ - set.add(ch) - cur = ch - if(set.size === 5) res = Math.max(res, cnt) - } - } - return res -} - -// another - -/** - * @param {string} word - * @return {number} - */ -function longestBeautifulSubstring(word) { - let res = 0, cur = 'a', cnt = 0 - const set = new Set() - for (let ch of word) { - if (ch >= cur) { - cnt++ - cur = ch - set.add(ch) - } else { - set.clear() - cnt = 0 - cur = 'a' - if(ch === cur) { - set.add(ch) - cnt++ - } - } - if (set.size === 5) { - res = Math.max(res, cnt) - } - } - - return res -} - -// another - -/** - * @param {string} word - * @return {number} - */ -function longestBeautifulSubstring(word) { - let result = 0, - current = 0 - let currentVowel = "a" - const set = new Set() - for (let i = 0; i < word.length; i++) - if (word.charAt(i) < currentVowel) { - set.clear() - if (word.charAt(i) == "a") { - set.add("a") - current = 1 - } else current = 0 - currentVowel = "a" - } else { - current++ - currentVowel = word.charAt(i) - set.add(currentVowel) - if (set.size == 5) result = Math.max(result, current) - } - return result -} diff --git a/1839.longest-substring-of-all-vowels-in-order.js b/1839.longest-substring-of-all-vowels-in-order.js new file mode 100644 index 00000000..f5333b0d --- /dev/null +++ b/1839.longest-substring-of-all-vowels-in-order.js @@ -0,0 +1,26 @@ +/** + * @param {string} word + * @return {number} + */ +function longestBeautifulSubstring(word) { + let res = 0, cur = 'a', cnt = 0 + const set = new Set() + for(let ch of word) { + if(ch < cur) { + set.clear() + cnt = 0 + cur = 'a' + if(ch === cur) { + cnt++ + set.add(cur) + } + } else { + cnt++ + set.add(ch) + cur = ch + if(set.size === 5) res = Math.max(res, cnt) + } + } + return res +} + diff --git a/1840-maximum-building-height.js b/1840.maximum-building-height.js similarity index 100% rename from 1840-maximum-building-height.js rename to 1840.maximum-building-height.js diff --git a/1844-replace-all-digits-with-characters.js b/1844.replace-all-digits-with-characters.js similarity index 100% rename from 1844-replace-all-digits-with-characters.js rename to 1844.replace-all-digits-with-characters.js diff --git a/1846-maximum-element-after-decreasing-and-rearranging.js b/1846.maximum-element-after-decreasing-and-rearranging.js similarity index 100% rename from 1846-maximum-element-after-decreasing-and-rearranging.js rename to 1846.maximum-element-after-decreasing-and-rearranging.js diff --git a/1847-closest-room.js b/1847.closest-room.js similarity index 100% rename from 1847-closest-room.js rename to 1847.closest-room.js diff --git a/1848-minimum-distance-to-the-target-element.js b/1848.minimum-distance-to-the-target-element.js similarity index 100% rename from 1848-minimum-distance-to-the-target-element.js rename to 1848.minimum-distance-to-the-target-element.js diff --git a/1849-splitting-a-string-into-descending-consecutive-values.js b/1849-splitting-a-string-into-descending-consecutive-values.js deleted file mode 100644 index 48e25d46..00000000 --- a/1849-splitting-a-string-into-descending-consecutive-values.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @param {string} s - * @return {boolean} - */ -const splitString = function(s) { - return helper(s, null) -}; - -function helper(str, previous) { - for(let i = 0, n = str.length; i < n; i++) { - const tmp = +(str.slice(0, i + 1)) - if(previous == null) { - if(helper(str.slice(i + 1), tmp)) return true - } else if(previous - tmp === 1 && (i === n - 1 || helper(str.slice(i + 1), tmp))) return true - } - - return false -} - - -// another - - -/** - * @param {string} s - * @return {boolean} - */ -const splitString = function(s) { - return dfs(s, 0, [Infinity]) -}; - -function dfs(str, idx, arr) { - if(idx >= str.length && arr.length > 2) return true - for(let i = idx; i < str.length; i++) { - const tmp = str.slice(idx, i + 1) - const num = parseInt(tmp, 10) - const pre = arr[arr.length - 1] - if(num < pre && (pre === Infinity || pre - num === 1)) { - arr.push(num) - if(dfs(str, i + 1, arr)) return true - arr.pop() - } - } - return false -} diff --git a/1849.splitting-a-string-into-descending-consecutive-values.js b/1849.splitting-a-string-into-descending-consecutive-values.js new file mode 100644 index 00000000..96dc1ca7 --- /dev/null +++ b/1849.splitting-a-string-into-descending-consecutive-values.js @@ -0,0 +1,20 @@ +/** + * @param {string} s + * @return {boolean} + */ +const splitString = function(s) { + return helper(s, null) +}; + +function helper(str, previous) { + for(let i = 0, n = str.length; i < n; i++) { + const tmp = +(str.slice(0, i + 1)) + if(previous == null) { + if(helper(str.slice(i + 1), tmp)) return true + } else if(previous - tmp === 1 && (i === n - 1 || helper(str.slice(i + 1), tmp))) return true + } + + return false +} + + diff --git a/1850-minimum-adjacent-swaps-to-reach-the-kth-smallest-number.js b/1850.minimum-adjacent-swaps-to-reach-the-kth-smallest-number.js similarity index 100% rename from 1850-minimum-adjacent-swaps-to-reach-the-kth-smallest-number.js rename to 1850.minimum-adjacent-swaps-to-reach-the-kth-smallest-number.js diff --git a/1851-minimum-interval-to-include-each-query.js b/1851-minimum-interval-to-include-each-query.js deleted file mode 100644 index b2a0f7f3..00000000 --- a/1851-minimum-interval-to-include-each-query.js +++ /dev/null @@ -1,447 +0,0 @@ -/** - * @param {number[][]} intervals - * @param {number[]} queries - * @return {number[]} - */ -const minInterval = function (intervals, queries) { - const n = intervals.length - const m = queries.length - const sortedQueryIdx = [...Array(m).keys()].sort( - (a, b) => queries[a] - queries[b] - ) - intervals.sort((a, b) => a[0] - b[0]) // sort by start & ascending - const minHeap = new BinaryHeap((c, p) => c.size >= p.size) - const res = Array(m).fill(0) - let i = 0 - for (const idx of sortedQueryIdx) { - const query = queries[idx] - while (i < n && intervals[i][0] <= query) { - minHeap.push({ - size: intervals[i][1] - intervals[i][0] + 1, - start: intervals[i][0], - end: intervals[i][1], - }) - i++ - } - while (!minHeap.isEmpty() && minHeap.peek().end < query) { - minHeap.pop() - } - res[idx] = minHeap.isEmpty() ? -1 : minHeap.peek().size - } - return res -} - -class BinaryHeap { - /** - * @param {compareFunction} compareFn - */ - constructor(compareFn) { - this.content = [] - this.compareFn = compareFn // Min-Heap: (c, p) => c > p - } - - /** - * @return {number} - Current heap size. - */ - size() { - return this.content.length - } - - /** - * @return {boolean} - True if heap size is empty. - */ - isEmpty() { - return this.size() === 0 - } - - /** - * @return {*} - Root node of the heap. - */ - peek() { - return this.size() > 0 ? this.content[0] : null - } - - /** - * @param {*} node - New node to add. - */ - push(node) { - this.content.push(node) - this._bubbleUp(this.content.length - 1) - } - - /** - * @return {*} - Root node of the heap. - */ - pop() { - if (this.content.length === 0) return null - const root = this.content[0] - const last = this.content.pop() - if (this.content.length > 0) { - this.content[0] = last - this._sinkDown(0) - } - return root - } - - /** - * @param {*} node - Node to delete. - */ - remove(node) { - const length = this.content.length - for (let i = 0; i < length; i++) { - if (this.content[i] !== node) continue - const last = this.content.pop() - if (i === length - 1) break - this.content[i] = last - this._bubbleUp(i) - this._sinkDown(i) - break - } - } - - /** - * @param {number} idx - Index of the node to bubble up - */ - _bubbleUp(idx) { - const node = this.content[idx] - while (idx > 0) { - const parentIdx = Math.floor((idx + 1) / 2) - 1 - const parent = this.content[parentIdx] - if (this.compareFn(node, parent)) break - this.content[parentIdx] = node - this.content[idx] = parent - idx = parentIdx - } - } - - /** - * @param {number} idx - Index of the node to sink down - */ - _sinkDown(idx) { - const node = this.content[idx] - while (true) { - const child2Idx = (idx + 1) * 2 - const child1Idx = child2Idx - 1 - let swapIdx = -1 - if (child1Idx < this.content.length) { - const child1 = this.content[child1Idx] - if (!this.compareFn(child1, node)) swapIdx = child1Idx - } - if (child2Idx < this.content.length) { - const child2 = this.content[child2Idx] - const compareNode = swapIdx === -1 ? node : this.content[child1Idx] - if (!this.compareFn(child2, compareNode)) swapIdx = child2Idx - } - if (swapIdx === -1) break - this.content[idx] = this.content[swapIdx] - this.content[swapIdx] = node - idx = swapIdx - } - } -} - - -// another - -/** - * @param {number[][]} intervals - * @param {number[]} queries - * @return {number[]} - */ -const minInterval = function (A, Q) { - const QQ = [] - for (let idx = 0; idx < Q.length; idx++) QQ.push([Q[idx], idx]) - QQ.sort((a, b) => a[0] - b[0]) - A.sort((a, b) => a[0] - b[0]) - let i = 0, - N = A.length - const ans = Array(Q.length).fill(-1) - const m = new TreeMap() - const pq = new PriorityQueue((a, b) => a[0] < b[0]) - for (let [q, index] of QQ) { - for (; i < N && A[i][0] <= q; i++) { - let len = A[i][1] - A[i][0] + 1 - if (m.get(len) == null) m.set(len, 0) - m.set(len, m.get(len) + 1) - pq.push([A[i][1], len]) - } - while (pq.size() > 0 && pq.peek()[0] < q) { - let [right, len] = pq.peek() - m.set(len, m.get(len) - 1) - if (m.get(len) === 0) m.remove(len) - pq.pop() - } - const first = m.getMinKey() - if (m.getLength()) ans[index] = first - } - return ans -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -function TreeMap() { - var root = null - var keyType = void 0 - var length = 0 - - return { - each: each, - set: set, - get: get, - getTree: getTree, - getLength: getLength, - getMaxKey: getMaxKey, - getMinKey: getMinKey, - remove: remove, - } - - function checkKey(key, checkKeyType) { - var localKeyType = typeof key - - if ( - localKeyType !== 'number' && - localKeyType !== 'string' && - localKeyType !== 'boolean' - ) { - throw new Error("'key' must be a number, a string or a boolean") - } - - if (checkKeyType === true && localKeyType !== keyType) { - throw new Error('All keys must be of the same type') - } - - return localKeyType - } - - function call(callback) { - var args = Array.prototype.slice.call(arguments, 1) - - if (typeof callback === 'function') { - callback.apply(void 0, args) - } - } - - function getTree() { - return root - } - - function getLength() { - return length - } - - function each(callback) { - internalEach(root, callback) - } - - function internalEach(node, callback, internalCallback) { - if (node === null) { - return call(internalCallback) - } - - internalEach(node.left, callback, function () { - call(callback, node.value, node.key) - - internalEach(node.right, callback, function () { - call(internalCallback) - }) - }) - } - - function get(key) { - checkKey(key) - - return internalGet(key, root) - } - - function internalGet(key, node) { - if (node === null) { - return void 0 - } - - if (key < node.key) { - return internalGet(key, node.left) - } else if (key > node.key) { - return internalGet(key, node.right) - } else { - return node.value - } - } - - function set(key, value) { - if (root === null) { - keyType = checkKey(key) - } else { - checkKey(key, true) - } - - root = internalSet(key, value, root) - } - - function internalSet(key, value, node) { - if (node === null) { - length++ - - return { - key: key, - value: value, - left: null, - right: null, - } - } - - if (key < node.key) { - node.left = internalSet(key, value, node.left) - } else if (key > node.key) { - node.right = internalSet(key, value, node.right) - } else { - node.value = value - } - - return node - } - - function getMaxKey() { - var maxNode = getMaxNode(root) - - if (maxNode !== null) { - return maxNode.key - } - - return maxNode - } - - function getMinKey() { - var minNode = getMinNode(root) - - if (minNode !== null) { - return minNode.key - } - - return minNode - } - - function getMaxNode(node) { - while (node !== null && node.right !== null) { - node = node.right - } - - return node - } - - function getMinNode(node) { - while (node !== null && node.left !== null) { - node = node.left - } - - return node - } - - function remove(key) { - checkKey(key) - - root = internalRemove(key, root) - } - - function internalRemove(key, node) { - if (node === null) { - return null - } - - if (key < node.key) { - node.left = internalRemove(key, node.left) - } else if (key > node.key) { - node.right = internalRemove(key, node.right) - } else { - if (node.left !== null && node.right !== null) { - var maxNode = getMaxNode(node.left) - - var maxNodeKey = maxNode.key - var maxNodeValue = maxNode.value - - maxNode.key = node.key - maxNode.value = node.value - node.key = maxNodeKey - node.value = maxNodeValue - - node.left = internalRemove(key, node.left) - } else if (node.left !== null) { - length-- - return node.left - } else if (node.right !== null) { - length-- - return node.right - } else { - length-- - return null - } - } - - return node - } -} diff --git a/1851.minimum-interval-to-include-each-query.js b/1851.minimum-interval-to-include-each-query.js new file mode 100644 index 00000000..3b0b1274 --- /dev/null +++ b/1851.minimum-interval-to-include-each-query.js @@ -0,0 +1,143 @@ +/** + * @param {number[][]} intervals + * @param {number[]} queries + * @return {number[]} + */ +const minInterval = function (intervals, queries) { + const n = intervals.length + const m = queries.length + const sortedQueryIdx = [...Array(m).keys()].sort( + (a, b) => queries[a] - queries[b] + ) + intervals.sort((a, b) => a[0] - b[0]) // sort by start & ascending + const minHeap = new BinaryHeap((c, p) => c.size >= p.size) + const res = Array(m).fill(0) + let i = 0 + for (const idx of sortedQueryIdx) { + const query = queries[idx] + while (i < n && intervals[i][0] <= query) { + minHeap.push({ + size: intervals[i][1] - intervals[i][0] + 1, + start: intervals[i][0], + end: intervals[i][1], + }) + i++ + } + while (!minHeap.isEmpty() && minHeap.peek().end < query) { + minHeap.pop() + } + res[idx] = minHeap.isEmpty() ? -1 : minHeap.peek().size + } + return res +} + +class BinaryHeap { + /** + * @param {compareFunction} compareFn + */ + constructor(compareFn) { + this.content = [] + this.compareFn = compareFn // Min-Heap: (c, p) => c > p + } + + /** + * @return {number} - Current heap size. + */ + size() { + return this.content.length + } + + /** + * @return {boolean} - True if heap size is empty. + */ + isEmpty() { + return this.size() === 0 + } + + /** + * @return {*} - Root node of the heap. + */ + peek() { + return this.size() > 0 ? this.content[0] : null + } + + /** + * @param {*} node - New node to add. + */ + push(node) { + this.content.push(node) + this._bubbleUp(this.content.length - 1) + } + + /** + * @return {*} - Root node of the heap. + */ + pop() { + if (this.content.length === 0) return null + const root = this.content[0] + const last = this.content.pop() + if (this.content.length > 0) { + this.content[0] = last + this._sinkDown(0) + } + return root + } + + /** + * @param {*} node - Node to delete. + */ + remove(node) { + const length = this.content.length + for (let i = 0; i < length; i++) { + if (this.content[i] !== node) continue + const last = this.content.pop() + if (i === length - 1) break + this.content[i] = last + this._bubbleUp(i) + this._sinkDown(i) + break + } + } + + /** + * @param {number} idx - Index of the node to bubble up + */ + _bubbleUp(idx) { + const node = this.content[idx] + while (idx > 0) { + const parentIdx = Math.floor((idx + 1) / 2) - 1 + const parent = this.content[parentIdx] + if (this.compareFn(node, parent)) break + this.content[parentIdx] = node + this.content[idx] = parent + idx = parentIdx + } + } + + /** + * @param {number} idx - Index of the node to sink down + */ + _sinkDown(idx) { + const node = this.content[idx] + while (true) { + const child2Idx = (idx + 1) * 2 + const child1Idx = child2Idx - 1 + let swapIdx = -1 + if (child1Idx < this.content.length) { + const child1 = this.content[child1Idx] + if (!this.compareFn(child1, node)) swapIdx = child1Idx + } + if (child2Idx < this.content.length) { + const child2 = this.content[child2Idx] + const compareNode = swapIdx === -1 ? node : this.content[child1Idx] + if (!this.compareFn(child2, compareNode)) swapIdx = child2Idx + } + if (swapIdx === -1) break + this.content[idx] = this.content[swapIdx] + this.content[swapIdx] = node + idx = swapIdx + } + } +} + + diff --git a/1854-maximum-population-year.js b/1854-maximum-population-year.js deleted file mode 100644 index c8a1f739..00000000 --- a/1854-maximum-population-year.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @param {number[][]} logs - * @return {number} - */ -const maximumPopulation = function(logs) { - const n = logs.length - const arr = Array(101).fill(0) - const base = 1950 - for(let log of logs) { - const [start, end] = log - arr[start - base]++ - arr[end - base]-- - } - - let res = 0, tmp = -Infinity - for(let i = 1; i < 101; i++) { - arr[i] += arr[i - 1] - } - for(let i = 0; i < 101; i++) { - if(arr[i] > tmp) { - res = i - tmp = arr[i] - } - } - return res + base -}; - - -// another - -/** - * @param {number[][]} logs - * @return {number} - */ -const maximumPopulation = function(logs) { - logs.sort((a, b) => { - if(a[0] === b[0]) return a[1] - b[1] - return a[0] - b[0] - }) - const arr = Array(101).fill(0) - const bit = new FenwickTree(101) - for(let i = 0, len = logs.length; i < len; i++) { - const [start, end] = logs[i] - const idx = start - 1950 - bit.update(idx + 1, 1) - } - for(let i = 0, len = logs.length; i < len; i++) { - const [start, end] = logs[i] - const idx = end - 1950 - bit.update(idx + 1, -1) - } - let max = 0 - for(let i = 1; i <= 101; i++) { - max = Math.max(max, bit.query(i)) - } - let tmp - for(let i = 1; i <= 101; i++) { - if(bit.query(i) === max) { - tmp = i - break - } - } - - return 1950 + tmp - 1 -}; - -const lowBit = (x) => x & -x -class FenwickTree { - constructor(n) { - if (n < 1) return - this.sum = Array(n + 1).fill(0) - } - update(i, delta) { - if (i < 1) return - while (i < this.sum.length) { - this.sum[i] += delta - i += lowBit(i) - } - } - query(i) { - if (i < 1) return - let sum = 0 - while (i > 0) { - sum += this.sum[i] - i -= lowBit(i) - } - return sum - } -} diff --git a/1854.maximum-population-year.js b/1854.maximum-population-year.js new file mode 100644 index 00000000..8f2699db --- /dev/null +++ b/1854.maximum-population-year.js @@ -0,0 +1,28 @@ +/** + * @param {number[][]} logs + * @return {number} + */ +const maximumPopulation = function(logs) { + const n = logs.length + const arr = Array(101).fill(0) + const base = 1950 + for(let log of logs) { + const [start, end] = log + arr[start - base]++ + arr[end - base]-- + } + + let res = 0, tmp = -Infinity + for(let i = 1; i < 101; i++) { + arr[i] += arr[i - 1] + } + for(let i = 0; i < 101; i++) { + if(arr[i] > tmp) { + res = i + tmp = arr[i] + } + } + return res + base +}; + + diff --git a/1855-maximum-distance-between-a-pair-of-values.js b/1855.maximum-distance-between-a-pair-of-values.js similarity index 100% rename from 1855-maximum-distance-between-a-pair-of-values.js rename to 1855.maximum-distance-between-a-pair-of-values.js diff --git a/1856-maximum-subarray-min-product.js b/1856-maximum-subarray-min-product.js deleted file mode 100644 index aef4a778..00000000 --- a/1856-maximum-subarray-min-product.js +++ /dev/null @@ -1,140 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const maxSumMinProduct = function(nums) { - const n = nums.length, left = Array(n).fill(0), right = Array(n).fill(n - 1) - const mod = BigInt(1e9 + 7) - let res = 0n - let stk = [] - for(let i = 0; i < n; i++) { - while(stk.length && nums[stk[stk.length - 1]] >= nums[i]) { - stk.pop() - } - left[i] = stk.length ? stk[stk.length - 1] + 1 : 0 - stk.push(i) - } - - stk = [] - for(let i = n - 1; i >= 0; i--) { - while(stk.length && nums[stk[stk.length - 1]] >= nums[i]) { - stk.pop() - } - right[i] = stk.length ? stk[stk.length - 1] - 1 : n - 1 - stk.push(i) - } - - const preSum = [] - for(let i = 0; i < n; i++) { - preSum[i] = (i === 0 ? 0n : preSum[i - 1]) + BigInt(nums[i]) - } - for(let i = 0; i < n; i++) { - res = max(res, fn(nums[i], left[i], right[i])) - } - - return res % mod - - function max(a, b) { - return a > b ? a : b - } - function fn(v, l, r) { - return BigInt(v) * (l === 0 ? preSum[r] : preSum[r] - preSum[l - 1]) - } -}; - -// another - - -/** - * @param {number[]} nums - * @return {number} - */ -const maxSumMinProduct = function (nums) { - const n = nums.length - const mod = BigInt(10 ** 9 + 7) - const preSum = Array(n + 1).fill(0n) - for (let i = 0; i < n; i++) { - preSum[i + 1] = preSum[i] + BigInt(nums[i]) - } - const l = Array(n).fill(0) // l[i] stores index of farthest element greater or equal to nums[i] - const r = Array(n).fill(0) // r[i] stores index of farthest element greater or equal to nums[i] - let st = [] - - for (let i = 0; i < n; i++) { - while (st.length && nums[st[st.length - 1]] >= nums[i]) st.pop() - if (st.length) l[i] = st[st.length - 1] + 1 - else l[i] = 0 - st.push(i) - } - - st = [] - for (let i = n - 1; i >= 0; i--) { - while (st.length && nums[st[st.length - 1]] >= nums[i]) st.pop() - if (st.length) r[i] = st[st.length - 1] - 1 - else r[i] = n - 1 - st.push(i) - } - function getSum(left, right) { - // inclusive - return preSum[right + 1] - preSum[left] - } - - let maxProduct = 0n - for (let i = 0; i < n; i++) { - maxProduct = bigint_max(maxProduct, BigInt(nums[i]) * getSum(l[i], r[i])) - } - return maxProduct % mod -} -function bigint_max(...args){ - if (args.length < 1){ throw 'Max of empty list'; } - m = args[0]; - args.forEach(a=>{if (a > m) {m = a}}); - return m; -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxSumMinProduct = function(nums) { - const n = nums.length, s1 = [], s2 = [], - left = Array(n), right = Array(n), mod = BigInt(1e9 + 7) - for(let i = 0; i < n; i++) { - while(s1.length && nums[s1[s1.length - 1]] >= nums[i]) s1.pop() - if(s1.length) left[i] = s1[s1.length - 1] + 1 - else left[i] = 0 - s1.push(i) - } - - for(let i = n - 1; i >= 0; i--) { - while(s2.length && nums[s2[s2.length - 1]] >= nums[i]) s2.pop() - if(s2.length) right[i] = s2[s2.length - 1] - 1 - else right[i] = n - 1 - s2.push(i) - } - - const preSum = Array(n) - for(let i = 0; i < n; i++) { - preSum[i] = (i === 0 ? 0n : preSum[i - 1]) + BigInt(nums[i]) - } - let res = 0n - for(let i = 0; i < n; i++) { - res = max(res, getSum(preSum, left[i], right[i]) * BigInt(nums[i])) - } - return res % mod - -}; - -function getSum(arr, l, r) { - return arr[r] - (l === 0 ? 0n : arr[l - 1]) -} - -function max(...args) { - let res = -Infinity - for(let e of args) { - if(e > res) res = e - } - return res -} diff --git a/1856.maximum-subarray-min-product.js b/1856.maximum-subarray-min-product.js new file mode 100644 index 00000000..864b3b1a --- /dev/null +++ b/1856.maximum-subarray-min-product.js @@ -0,0 +1,44 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const maxSumMinProduct = function(nums) { + const n = nums.length, left = Array(n).fill(0), right = Array(n).fill(n - 1) + const mod = BigInt(1e9 + 7) + let res = 0n + let stk = [] + for(let i = 0; i < n; i++) { + while(stk.length && nums[stk[stk.length - 1]] >= nums[i]) { + stk.pop() + } + left[i] = stk.length ? stk[stk.length - 1] + 1 : 0 + stk.push(i) + } + + stk = [] + for(let i = n - 1; i >= 0; i--) { + while(stk.length && nums[stk[stk.length - 1]] >= nums[i]) { + stk.pop() + } + right[i] = stk.length ? stk[stk.length - 1] - 1 : n - 1 + stk.push(i) + } + + const preSum = [] + for(let i = 0; i < n; i++) { + preSum[i] = (i === 0 ? 0n : preSum[i - 1]) + BigInt(nums[i]) + } + for(let i = 0; i < n; i++) { + res = max(res, fn(nums[i], left[i], right[i])) + } + + return res % mod + + function max(a, b) { + return a > b ? a : b + } + function fn(v, l, r) { + return BigInt(v) * (l === 0 ? preSum[r] : preSum[r] - preSum[l - 1]) + } +}; + diff --git a/1857-largest-color-value-in-a-directed-graph.js b/1857-largest-color-value-in-a-directed-graph.js deleted file mode 100644 index ed99ed48..00000000 --- a/1857-largest-color-value-in-a-directed-graph.js +++ /dev/null @@ -1,135 +0,0 @@ -/** - * @param {string} colors - * @param {number[][]} edges - * @return {number} - */ -const largestPathValue = function (colors, edges) { - const graph = {} - const n = colors.length, - a = 'a'.charCodeAt(0) - const indegree = Array(colors.length).fill(0) - for (let e of edges) { - if (graph[e[0]] == null) graph[e[0]] = [] - graph[e[0]].push(e[1]) - indegree[e[1]]++ - } - // cnt[i][j] is the maximum count of j-th color from the ancester nodes to node i. - const cnt = Array.from({ length: n }, () => Array(26).fill(0)) - const q = [] - for (let i = 0; i < n; i++) { - if (indegree[i] === 0) { - q.push(i) - cnt[i][colors.charCodeAt(i) - a] = 1 - } - } - let res = 0, - seen = 0 - while (q.length) { - const u = q[0] - q.shift() - const val = Math.max(...cnt[u]) - res = Math.max(res, val) - seen++ - for (let v of (graph[u] || [])) { - for (let i = 0; i < 26; i++) { - cnt[v][i] = Math.max( - cnt[v][i], - cnt[u][i] + (i === colors.charCodeAt(v) - a) - ) - } - if (--indegree[v] === 0) q.push(v) - } - } - return seen < colors.length ? -1 : res -} - -// another - -/** - * @param {string} colors - * @param {number[][]} edges - * @return {number} - */ - const largestPathValue = function(colors, edges) { - const graph = {}, n = colors.length, a = 'a'.charCodeAt(0) - const indegree = Array(n).fill(0) - for (const [from, to] of edges) { - if (graph[from] == null) graph[from] = [] - graph[from].push(to) - indegree[to]++ - } - const cnt = Array.from({ length: n }, () => Array(26).fill(0)) - const code = idx => colors.charCodeAt(idx) - a - const q = [] - for (let i = 0; i < n; i++) { - if(indegree[i] === 0) { - q.push(i) - cnt[i][code(i)] = 1 - } - } - let res = 0, seen = 0 - - while(q.length) { - const u = q.pop() - const val = cnt[u][code(u)] - res = Math.max(res, val) - seen++ - for(const next of (graph[u] || [])) { - for(let i = 0; i < 26; i++) { - cnt[next][i] = Math.max(cnt[next][i], cnt[u][i] + (i === code(next) ? 1 : 0)) - } - if(--indegree[next] === 0) { - q.push(next) - } - } - } - return seen < n ? -1 : res -}; - -// another - - -/** - * @param {string} colors - * @param {number[][]} edges - * @return {number} - */ -const largestPathValue = function (colors, edges) { - const graph = {} - const n = colors.length, - a = 'a'.charCodeAt(0) - const indegree = Array(colors.length).fill(0) - for (let e of edges) { - if (graph[e[0]] == null) graph[e[0]] = [] - graph[e[0]].push(e[1]) - indegree[e[1]]++ - } - const cnt = Array.from({ length: n }, () => Array(26).fill(0)) - const q = [] - for (let i = 0; i < n; i++) { - if (indegree[i] === 0) { - q.push(i) - cnt[i][colors.charCodeAt(i) - a] = 1 - } - } - let res = 0, - seen = 0 - while (q.length) { - const u = q[0] - q.shift() - const val = Math.max(...cnt[u]) - res = Math.max(res, val) - seen++ - if (graph[u] == null) continue - for (let v of graph[u]) { - for (let i = 0; i < 26; i++) { - cnt[v][i] = Math.max( - cnt[v][i], - cnt[u][i] + (i === colors.charCodeAt(v) - a) - ) - } - if (--indegree[v] === 0) q.push(v) - } - } - return seen < colors.length ? -1 : res -} diff --git a/1857.largest-color-value-in-a-directed-graph.js b/1857.largest-color-value-in-a-directed-graph.js new file mode 100644 index 00000000..0264954e --- /dev/null +++ b/1857.largest-color-value-in-a-directed-graph.js @@ -0,0 +1,45 @@ +/** + * @param {string} colors + * @param {number[][]} edges + * @return {number} + */ +const largestPathValue = function (colors, edges) { + const graph = {} + const n = colors.length, + a = 'a'.charCodeAt(0) + const indegree = Array(colors.length).fill(0) + for (let e of edges) { + if (graph[e[0]] == null) graph[e[0]] = [] + graph[e[0]].push(e[1]) + indegree[e[1]]++ + } + // cnt[i][j] is the maximum count of j-th color from the ancester nodes to node i. + const cnt = Array.from({ length: n }, () => Array(26).fill(0)) + const q = [] + for (let i = 0; i < n; i++) { + if (indegree[i] === 0) { + q.push(i) + cnt[i][colors.charCodeAt(i) - a] = 1 + } + } + let res = 0, + seen = 0 + while (q.length) { + const u = q[0] + q.shift() + const val = Math.max(...cnt[u]) + res = Math.max(res, val) + seen++ + for (let v of (graph[u] || [])) { + for (let i = 0; i < 26; i++) { + cnt[v][i] = Math.max( + cnt[v][i], + cnt[u][i] + (i === colors.charCodeAt(v) - a) + ) + } + if (--indegree[v] === 0) q.push(v) + } + } + return seen < colors.length ? -1 : res +} + diff --git a/1859-sorting-the-sentence.js b/1859.sorting-the-sentence.js similarity index 100% rename from 1859-sorting-the-sentence.js rename to 1859.sorting-the-sentence.js diff --git a/186-reverse-words-in-a-string-ii.js b/186.reverse-words-in-a-string-ii.js similarity index 100% rename from 186-reverse-words-in-a-string-ii.js rename to 186.reverse-words-in-a-string-ii.js diff --git a/1860-incremental-memory-leak.js b/1860.incremental-memory-leak.js similarity index 100% rename from 1860-incremental-memory-leak.js rename to 1860.incremental-memory-leak.js diff --git a/1861-rotating-the-box.js b/1861-rotating-the-box.js deleted file mode 100644 index dcd137ee..00000000 --- a/1861-rotating-the-box.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @param {character[][]} box - * @return {character[][]} - */ -const rotateTheBox = function(box) { - const m = box.length, n = box[0].length - const res = Array.from({ length: n }, () => Array(m).fill('.')) - for(let i = 0; i < m; i++) { - for(let j = n - 1, pos = n - 1; j >= 0; j--) { - if(box[i][j] === '.') continue - if(box[i][j] === '#') { - res[pos][m - 1 - i] = '#' - pos-- - } else { - res[j][m - 1 - i] = '*' - pos = j - 1 - } - } - } - return res -}; - -// another - -/** - * @param {character[][]} box - * @return {character[][]} - */ -const rotateTheBox = function(box) { - const m = box.length, n = box[0].length - const res = Array.from({ length: n }, () => Array(m).fill('.')) - for(let i = 0; i < m; i++) { - let j = n - 1 - let pos = j - while(j >= 0) { - if(box[i][j] === '*') { - pos = j - 1 - } else if(box[i][j] === '#') { - box[i][j] = '.' - box[i][pos] = '#' - res[pos][m - 1 - i] = '#' - pos-- - } - res[j][m - 1 - i] = box[i][j] - j-- - } - - } - return res -}; diff --git a/1861.rotating-the-box.js b/1861.rotating-the-box.js new file mode 100644 index 00000000..ebf310c8 --- /dev/null +++ b/1861.rotating-the-box.js @@ -0,0 +1,22 @@ +/** + * @param {character[][]} box + * @return {character[][]} + */ +const rotateTheBox = function(box) { + const m = box.length, n = box[0].length + const res = Array.from({ length: n }, () => Array(m).fill('.')) + for(let i = 0; i < m; i++) { + for(let j = n - 1, pos = n - 1; j >= 0; j--) { + if(box[i][j] === '.') continue + if(box[i][j] === '#') { + res[pos][m - 1 - i] = '#' + pos-- + } else { + res[j][m - 1 - i] = '*' + pos = j - 1 + } + } + } + return res +}; + diff --git a/1862-sum-of-floored-pairs.js b/1862.sum-of-floored-pairs.js similarity index 100% rename from 1862-sum-of-floored-pairs.js rename to 1862.sum-of-floored-pairs.js diff --git a/1863-sum-of-all-subset-xor-totals.js b/1863.sum-of-all-subset-xor-totals.js similarity index 100% rename from 1863-sum-of-all-subset-xor-totals.js rename to 1863.sum-of-all-subset-xor-totals.js diff --git a/1864-minimum-number-of-swaps-to-make-the-binary-string-alternating.js b/1864.minimum-number-of-swaps-to-make-the-binary-string-alternating.js similarity index 100% rename from 1864-minimum-number-of-swaps-to-make-the-binary-string-alternating.js rename to 1864.minimum-number-of-swaps-to-make-the-binary-string-alternating.js diff --git a/1865-finding-pairs-with-a-certain-sum.js b/1865.finding-pairs-with-a-certain-sum.js similarity index 100% rename from 1865-finding-pairs-with-a-certain-sum.js rename to 1865.finding-pairs-with-a-certain-sum.js diff --git a/1866-number-of-ways-to-rearrange-sticks-with-k-sticks-visible.js b/1866-number-of-ways-to-rearrange-sticks-with-k-sticks-visible.js deleted file mode 100644 index e652838e..00000000 --- a/1866-number-of-ways-to-rearrange-sticks-with-k-sticks-visible.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @param {number} n - * @param {number} k - * @return {number} - */ -const rearrangeSticks = function(n, k) { - const mod = BigInt(1e9 + 7) - const g = Array.from({ length: 1001 }, () => Array(1001).fill(0n)) - g[1][1] = 1n - for(let i = 2; i <= 1000; i++) { - for(let j = 1; j <= i; j++ ) { - g[i][j] = (g[i - 1][j - 1] + BigInt(i - 1) * g[i - 1][j] % mod) % mod - } - } - return g[n][k] -}; - -// another - -/** - * @param {number} n - * @param {number} k - * @return {number} - */ -const rearrangeSticks = function(n, k) { - const MOD = 1e9 + 7; - // first # can be smallest # in which case we recurse for (n - 1, k - 1) - // or it can not be and smallest can be in any of n - 1 otehr positions for recursed(n - 1, k) - const dp = new Array(n + 1).fill().map( _ => new Array(k + 1).fill(0) ); - for (let i = 1; i <= n; ++i) { - for (let j = 1; j <= k; ++j) { - if (j === i) { - dp[i][j] = 1; - } else if (j < i) { - dp[i][j] = (dp[i - 1][j - 1] + (i - 1) * dp[i - 1][j]) % MOD; - } - } - } - return dp[n][k] % MOD; - -}; diff --git a/1866.number-of-ways-to-rearrange-sticks-with-k-sticks-visible.js b/1866.number-of-ways-to-rearrange-sticks-with-k-sticks-visible.js new file mode 100644 index 00000000..006e995b --- /dev/null +++ b/1866.number-of-ways-to-rearrange-sticks-with-k-sticks-visible.js @@ -0,0 +1,17 @@ +/** + * @param {number} n + * @param {number} k + * @return {number} + */ +const rearrangeSticks = function(n, k) { + const mod = BigInt(1e9 + 7) + const g = Array.from({ length: 1001 }, () => Array(1001).fill(0n)) + g[1][1] = 1n + for(let i = 2; i <= 1000; i++) { + for(let j = 1; j <= i; j++ ) { + g[i][j] = (g[i - 1][j - 1] + BigInt(i - 1) * g[i - 1][j] % mod) % mod + } + } + return g[n][k] +}; + diff --git a/1869-longer-contiguous-segments-of-ones-than-zeros.js b/1869.longer-contiguous-segments-of-ones-than-zeros.js similarity index 100% rename from 1869-longer-contiguous-segments-of-ones-than-zeros.js rename to 1869.longer-contiguous-segments-of-ones-than-zeros.js diff --git a/187-repeated-dna-sequences.js b/187-repeated-dna-sequences.js deleted file mode 100644 index 773abb02..00000000 --- a/187-repeated-dna-sequences.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @param {string} s - * @return {string[]} - */ -const findRepeatedDnaSequences = function(s) { - if (!s || s.length < 10) { - return []; - } - const map = new Map([["A", 0], ["C", 1], ["G", 2], ["T", 3]]); - const dna = new Set(); - const repeated = new Set(); - const mask = 0xfffff; - let cur = 0; - for (let i = 0, n = s.length; i < n; i++) { - cur <<= 2; - cur = cur | map.get(s[i]); - cur = cur & mask; - if (i >= 9) { - if (dna.has(cur)) { - const seq = s.slice(i - 9, i + 1); - if (!repeated.has(seq)) { - repeated.add(seq); - } - } else { - dna.add(cur); - } - } - } - return Array.from(repeated); -}; - -// another - -/** - * @param {string} s - * @return {string[]} - */ -const findRepeatedDnaSequences = function(s) { - let store = new Set(), result = new Set() - for(let i = 0; i < s.length - 9; i++) { - const str = s.substring(i, i + 10) - if(store.has(str)) { - result.add(str) - } else { - store.add(str) - } - } - return Array.from(result) -}; diff --git a/187.repeated-dna-sequences.js b/187.repeated-dna-sequences.js new file mode 100644 index 00000000..8b4fee8e --- /dev/null +++ b/187.repeated-dna-sequences.js @@ -0,0 +1,31 @@ +/** + * @param {string} s + * @return {string[]} + */ +const findRepeatedDnaSequences = function(s) { + if (!s || s.length < 10) { + return []; + } + const map = new Map([["A", 0], ["C", 1], ["G", 2], ["T", 3]]); + const dna = new Set(); + const repeated = new Set(); + const mask = 0xfffff; + let cur = 0; + for (let i = 0, n = s.length; i < n; i++) { + cur <<= 2; + cur = cur | map.get(s[i]); + cur = cur & mask; + if (i >= 9) { + if (dna.has(cur)) { + const seq = s.slice(i - 9, i + 1); + if (!repeated.has(seq)) { + repeated.add(seq); + } + } else { + dna.add(cur); + } + } + } + return Array.from(repeated); +}; + diff --git a/1870-minimum-speed-to-arrive-on-time.js b/1870-minimum-speed-to-arrive-on-time.js deleted file mode 100644 index 9eebca9b..00000000 --- a/1870-minimum-speed-to-arrive-on-time.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - * @param {number[]} dist - * @param {number} hour - * @return {number} - */ -const minSpeedOnTime = function(dist, hour) { - let n = dist.length, l = 1, r = 1e7 + 1 - while(l < r) { - const mid = l + ((r - l) >> 1) - let time = 0 - for(let i = 0; i < n - 1; i++) time += Math.ceil(dist[i] / mid) - time += dist[dist.length - 1] / mid - if(time > hour) l = mid + 1 - else r = mid - } - return l > 1e7 ? -1 : l -}; - -// another - -/** - * @param {number[]} dist - * @param {number} hour - * @return {number} - */ -const minSpeedOnTime = function(dist, hour) { - let l = 1, r = 1e7 - while(l <= r) { - let mid = (l + r) >> 1 - if(valid(mid)) r = mid -1 - else l = mid + 1 - } - return l > 1e7 ? -1 : l - - function valid(speed) { - let sum = 0 - for(let e of dist) { - sum = Math.ceil(sum) - sum += e / speed - if(sum > hour) return - } - - return true - } -}; - -// another - -/** - * @param {number[]} dist - * @param {number} hour - * @return {number} - */ -const minSpeedOnTime = function(dist, hour) { - const sum = dist.reduce((ac, e) => ac + e, 0) - let l = 1, r = 10 ** 7 - while(l < r) { - let mid = l + ((r - l) >> 1) - if(chk(mid)) r = mid - else l = mid + 1 - } - - return chk(l) ? l : -1 - - function chk(speed) { - let res = 0 - for(let i = 0, len = dist.length; i < len - 1; i++) { - res += Math.ceil(dist[i] / speed) - } - if (dist.length) res += dist[dist.length - 1] / speed - return res <= hour - } - -}; - -// another - -/** - * @param {number[]} dist - * @param {number} hour - * @return {number} - */ -const minSpeedOnTime = function(dist, hour) { - let l = 1, r = 1e7 - while(l < r) { - const mid = l + Math.floor((r - l) / 2) - if(!valid(mid)) l = mid + 1 - else r = mid - } - // console.log(l) - return valid(l) ? l : -1 - - function valid(mid) { - let res = 0 - for(let i = 0, n = dist.length; i < n; i++) { - const d = dist[i] - res += (i === n - 1 ? d / mid : Math.ceil(d / mid)) - } - return res <= hour - } -}; - diff --git a/1870.minimum-speed-to-arrive-on-time.js b/1870.minimum-speed-to-arrive-on-time.js new file mode 100644 index 00000000..a4942fd3 --- /dev/null +++ b/1870.minimum-speed-to-arrive-on-time.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} dist + * @param {number} hour + * @return {number} + */ +const minSpeedOnTime = function(dist, hour) { + let n = dist.length, l = 1, r = 1e7 + 1 + while(l < r) { + const mid = l + ((r - l) >> 1) + let time = 0 + for(let i = 0; i < n - 1; i++) time += Math.ceil(dist[i] / mid) + time += dist[dist.length - 1] / mid + if(time > hour) l = mid + 1 + else r = mid + } + return l > 1e7 ? -1 : l +}; + diff --git a/1871-jump-game-vii.js b/1871-jump-game-vii.js deleted file mode 100644 index 55fd6fcf..00000000 --- a/1871-jump-game-vii.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @param {string} s - * @param {number} minJump - * @param {number} maxJump - * @return {boolean} - */ -const canReach = function(s, minJump, maxJump) { - const n = s.length - const queue = [0] - let mx = 0 - const { max, min } = Math - while(queue.length) { - const i = queue.shift() - for(let j = max(i + minJump, mx + 1); j < min(s.length, i + maxJump + 1); j++) { - if(s[j] === '0') { - if(j === n - 1) return true - queue.push(j) - } - } - mx = i + maxJump - } - - return false -}; - - -// another - -/** - * @param {string} s - * @param {number} minJump - * @param {number} maxJump - * @return {boolean} - */ -const canReach = function(s, minJump, maxJump) { - let n = s.length; - const {max, min} = Math - if (s[n - 1] != '0') return false; - const pre_sum = Array(n + 1).fill(0); - const check = Array(n + 1).fill(0); - check[1] = 1; - pre_sum[1] = 1; - for (let i = 1; i < n; i++) { - pre_sum[i + 1] = pre_sum[i]; - if (s[i] == '1') continue; - if (i < minJump) continue; - let r = i - minJump; - let l = max(0, i - maxJump); - if (pre_sum[r + 1] - pre_sum[l] == 0) continue; - check[i + 1] = true; - pre_sum[i + 1]++; - } - return check[n]; -}; - -// another - -/** - * @param {string} s - * @param {number} minJump - * @param {number} maxJump - * @return {boolean} - */ -const canReach = function(s, minJump, maxJump) { - const n = s.length, dp = Array(n).fill(0) - dp[0] = 1 - let pre = 0 - for(let i = 1; i < n; i++) { - if(i >= minJump) { - pre += dp[i - minJump] - } - if(i > maxJump) pre -= dp[i - maxJump - 1] - dp[i] = pre > 0 && s[i] === '0' ? 1 : 0 - } - return dp[n - 1] -}; - -// another - -/** - * @param {string} s - * @param {number} minJump - * @param {number} maxJump - * @return {boolean} - */ -const canReach = function(s, minJump, maxJump) { - const n = s.length - const dp = Array(n).fill(0) - dp[0] = 1 - let pre = 0 - for(let i = 1; i < n; i++) { - if(i < minJump) continue - if(i >= minJump) pre += dp[i - minJump] - if(i > maxJump) pre -= dp[i - maxJump - 1] - dp[i] = pre > 0 && s[i] === '0' ? 1 : 0 - } - - return dp[n - 1] ? true : false -}; diff --git a/1871.jump-game-vii.js b/1871.jump-game-vii.js new file mode 100644 index 00000000..eccd6f10 --- /dev/null +++ b/1871.jump-game-vii.js @@ -0,0 +1,26 @@ +/** + * @param {string} s + * @param {number} minJump + * @param {number} maxJump + * @return {boolean} + */ +const canReach = function(s, minJump, maxJump) { + const n = s.length + const queue = [0] + let mx = 0 + const { max, min } = Math + while(queue.length) { + const i = queue.shift() + for(let j = max(i + minJump, mx + 1); j < min(s.length, i + maxJump + 1); j++) { + if(s[j] === '0') { + if(j === n - 1) return true + queue.push(j) + } + } + mx = i + maxJump + } + + return false +}; + + diff --git a/1872-stone-game-viii.js b/1872.stone-game-viii.js similarity index 100% rename from 1872-stone-game-viii.js rename to 1872.stone-game-viii.js diff --git a/1874-minimize-product-sum-of-two-arrays.js b/1874.minimize-product-sum-of-two-arrays.js similarity index 100% rename from 1874-minimize-product-sum-of-two-arrays.js rename to 1874.minimize-product-sum-of-two-arrays.js diff --git a/1876-substrings-of-size-three-with-distinct-characters.js b/1876.substrings-of-size-three-with-distinct-characters.js similarity index 100% rename from 1876-substrings-of-size-three-with-distinct-characters.js rename to 1876.substrings-of-size-three-with-distinct-characters.js diff --git a/1877-minimize-maximum-pair-sum-in-array.js b/1877.minimize-maximum-pair-sum-in-array.js similarity index 100% rename from 1877-minimize-maximum-pair-sum-in-array.js rename to 1877.minimize-maximum-pair-sum-in-array.js diff --git a/1878-get-biggest-three-rhombus-sums-in-a-grid.js b/1878.get-biggest-three-rhombus-sums-in-a-grid.js similarity index 100% rename from 1878-get-biggest-three-rhombus-sums-in-a-grid.js rename to 1878.get-biggest-three-rhombus-sums-in-a-grid.js diff --git a/1879-minimum-xor-sum-of-two-arrays.js b/1879-minimum-xor-sum-of-two-arrays.js deleted file mode 100644 index 31c752c9..00000000 --- a/1879-minimum-xor-sum-of-two-arrays.js +++ /dev/null @@ -1,129 +0,0 @@ -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const minimumXORSum = function (nums1, nums2) { - const n = nums1.length - const limit = 1 << n - const dp = Array(limit).fill(Infinity) - dp[0] = 0 - for (let mask = 1; mask < limit; ++mask) { - for (let i = 0; i < n; ++i) { - if ((mask >> i) & 1) { - dp[mask] = Math.min( - dp[mask], - dp[mask ^ (1 << i)] + (nums1[bitCnt(mask) - 1] ^ nums2[i]) - ) - } - } - } - return dp[limit - 1] -} - -function bitCnt(num) { - let res = 0 - while (num) { - res++ - num = num & (num - 1) - } - - return res -} - - -// another - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const minimumXORSum = function (nums1, nums2) { - const n = nums1.length, dp = Array(1 << n).fill(Infinity) - return dfs(0, 0) - function dfs(i, mask) { - if(i === n) return 0 - if(dp[mask] !== Infinity) return dp[mask] - for(let j = 0; j < n; j++) { - if((mask & (1 << j)) === 0) { - dp[mask] = Math.min( - dp[mask], - (nums1[i] ^ nums2[j]) + dfs(i + 1, mask | (1 << j)) - ) - } - } - return dp[mask] - } -} - -// another - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const minimumXORSum = function(nums1, nums2) { - const dp = Array(1 << nums2.length).fill(Infinity) - return dfs(dp, nums1, nums2, 0, 0) -}; - -function dfs(dp, a, b, i, mask) { - if(i >= a.length) return 0 - if(dp[mask] === Infinity) { - for(let j = 0; j < b.length; j++) { - if((mask & (1 << j)) === 0) { - dp[mask] = Math.min(dp[mask], (a[i] ^ b[j]) + dfs(dp, a, b, i + 1, mask + (1 << j))) - } - } - } - return dp[mask] -} - -// another - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const minimumXORSum = function (nums1, nums2) { - const dp = Array(1 << nums2.length).fill(Infinity) - return dfs(0, 0) - - function dfs(i, mask) { - if(i >= nums2.length) return 0 - if(dp[mask] != Infinity) return dp[mask] - for(let j = 0; j < nums2.length; j++) { - if((mask & (1 << j)) === 0) { - dp[mask] = Math.min(dp[mask], (nums1[i] ^ nums2[j]) + dfs(i + 1, mask + (1 << j)) ) - } - } - return dp[mask] - } -} - -// another - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const minimumXORSum = function (nums1, nums2) { - const n = nums1.length, dp = Array(1 << n).fill(Infinity) - return dfs(0, 0) - - function dfs(i, mask) { - if(i >= n) return 0 - if(dp[mask] !== Infinity) return dp[mask] - for(let j = 0; j < n; j++) { - if((mask & (1 << j)) === 0) { - dp[mask] = Math.min(dp[mask], (nums1[i] ^ nums2[j]) + dfs(i + 1, mask | (1 << j))) - } - } - return dp[mask] - } -} - diff --git a/1879.minimum-xor-sum-of-two-arrays.js b/1879.minimum-xor-sum-of-two-arrays.js new file mode 100644 index 00000000..5c135094 --- /dev/null +++ b/1879.minimum-xor-sum-of-two-arrays.js @@ -0,0 +1,34 @@ +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +const minimumXORSum = function (nums1, nums2) { + const n = nums1.length + const limit = 1 << n + const dp = Array(limit).fill(Infinity) + dp[0] = 0 + for (let mask = 1; mask < limit; ++mask) { + for (let i = 0; i < n; ++i) { + if ((mask >> i) & 1) { + dp[mask] = Math.min( + dp[mask], + dp[mask ^ (1 << i)] + (nums1[bitCnt(mask) - 1] ^ nums2[i]) + ) + } + } + } + return dp[limit - 1] +} + +function bitCnt(num) { + let res = 0 + while (num) { + res++ + num = num & (num - 1) + } + + return res +} + + diff --git a/188-best-time-to-buy-and-sell-stock-iv.js b/188-best-time-to-buy-and-sell-stock-iv.js deleted file mode 100644 index 35de229f..00000000 --- a/188-best-time-to-buy-and-sell-stock-iv.js +++ /dev/null @@ -1,88 +0,0 @@ -/** - * @param {number} k - * @param {number[]} prices - * @return {number} - */ -const maxProfit = function(k, prices) { - if (!prices.length) return 0 - let len = prices.length, - res = 0 - if (k >= ~~(len / 2)) { - for (let i = 1; i < len; i++) { - res += Math.max(prices[i] - prices[i - 1], 0) - } - return res - } - const buy = new Array(k + 1).fill(Number.MIN_SAFE_INTEGER) - const sell = new Array(k + 1).fill(0) - - for (let p of prices) { - for (let i = 1; i <= k; i++) { - buy[i] = Math.max(sell[i - 1] - p, buy[i]) - sell[i] = Math.max(buy[i] + p, sell[i]) - } - } - return sell[k] -} - -// another - -/** - * @param {number} k - * @param {number[]} prices - * @return {number} - */ -const maxProfit = function(k, prices) { - if(prices.length === 0) return 0 - - if(k > (prices.length/2)) { - let profit = 0 - for(let i = 1; i < prices.length; i++) { - if(prices[i] > prices[i-1]) profit += prices[i] - prices[i-1] - } - return profit - } else { - let dp = new Array(prices.length).fill(0) - let length = prices.length - for(let j = 0; j < k; j++) { - let min = prices[0], max = 0 - for(let i = 0; i < length; i++) { - min = Math.min(min, prices[i] - dp[i]) - max = Math.max(max, prices[i] - min) - dp[i] = max - } - } - return dp.pop() - } -} - - // another - -/** - * @param {number} k - * @param {number[]} prices - * @return {number} - */ -const maxProfit = function(k, prices) { - if (k >= prices.length / 2) { - let max = 0; - for(let i = 1; i < prices.length; i++) { - if (prices[i] > prices[i - 1]) { - max += prices[i] - prices[i - 1]; - } - } - return max; - } - if (prices.length === 0) return 0; - let dp = new Array(k + 1); - dp[0] = new Array(prices.length).fill(0); - for (let t = 1; t <= k; t++) { - dp[t] = [0]; - let max = dp[t - 1][0] - prices[0]; - for (let day = 1; day < prices.length; day++) { - dp[t][day] = Math.max(dp[t][day - 1], max + prices[day]); - max = Math.max(max, dp[t - 1][day] - prices[day]); - } - } - return dp[k][prices.length - 1]; -} diff --git a/188.best-time-to-buy-and-sell-stock-iv.js b/188.best-time-to-buy-and-sell-stock-iv.js new file mode 100644 index 00000000..3d7cc709 --- /dev/null +++ b/188.best-time-to-buy-and-sell-stock-iv.js @@ -0,0 +1,27 @@ +/** + * @param {number} k + * @param {number[]} prices + * @return {number} + */ +const maxProfit = function(k, prices) { + if (!prices.length) return 0 + let len = prices.length, + res = 0 + if (k >= ~~(len / 2)) { + for (let i = 1; i < len; i++) { + res += Math.max(prices[i] - prices[i - 1], 0) + } + return res + } + const buy = new Array(k + 1).fill(Number.MIN_SAFE_INTEGER) + const sell = new Array(k + 1).fill(0) + + for (let p of prices) { + for (let i = 1; i <= k; i++) { + buy[i] = Math.max(sell[i - 1] - p, buy[i]) + sell[i] = Math.max(buy[i] + p, sell[i]) + } + } + return sell[k] +} + diff --git a/1880-check-if-word-equals-summation-of-two-words.js b/1880.check-if-word-equals-summation-of-two-words.js similarity index 100% rename from 1880-check-if-word-equals-summation-of-two-words.js rename to 1880.check-if-word-equals-summation-of-two-words.js diff --git a/1881-maximum-value-after-insertion.js b/1881.maximum-value-after-insertion.js similarity index 100% rename from 1881-maximum-value-after-insertion.js rename to 1881.maximum-value-after-insertion.js diff --git a/1882-process-tasks-using-servers.js b/1882-process-tasks-using-servers.js deleted file mode 100644 index db62a07e..00000000 --- a/1882-process-tasks-using-servers.js +++ /dev/null @@ -1,434 +0,0 @@ -/** - * @param {number[]} servers - * @param {number[]} tasks - * @return {number[]} - */ -const assignTasks = function(servers, tasks) { - const avail = new PQ((a, b) => a[0] === b[0] ? a[1] < b[1] : a[0] < b[0]) - const busy = new PQ((a, b) => a[2] < b[2]) - const res = [] - const { max } = Math - // init - for(let i = 0, len = servers.length; i < len; i++) { - avail.push([servers[i], i, 0]) - } - - for(let i = 0, len = tasks.length; i < len; i++) { - while(!busy.isEmpty() && busy.peek()[2] <= i) { - const s = busy.pop() - s[2] = i - avail.push(s) - } - if(!avail.isEmpty()) { - const s = avail.pop() - res.push(s[1]) - busy.push([s[0], s[1], max(i, s[2]) + tasks[i]]) - } else { - const tmp = busy.peek() - while(!busy.isEmpty() && busy.peek()[2] === tmp[2]) { - avail.push(busy.pop()) - } - const s = avail.pop() - res.push(s[1]) - busy.push([s[0], s[1], max(i, s[2]) + tasks[i]]) - } - } - - return res -}; - -class PQ { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -/** - * @param {number[]} servers - * @param {number[]} tasks - * @return {number[]} - */ -const assignTasks = function (servers, tasks) { - const available = new PriorityQueue((a, b) => - a[0] === b[0] ? a[1] < b[1] : a[0] < b[0] - ) - const occupied = new PriorityQueue((a, b) => - a[0] === b[0] ? (a[1] === b[1] ? a[2] < b[2] : a[1] < b[1]) : a[0] < b[0] - ) - - const res = [], - m = tasks.length, - n = servers.length - for (let i = 0; i < n; i++) { - const w = servers[i] - available.push([w, i]) - } - let now = 0 - for (let i = 0; i < m; i++) { - const t = tasks[i] - - while (!occupied.isEmpty() && occupied.peek()[0] <= now) { - const [end, weight, index] = occupied.pop() - available.push([weight, index]) - } - - let idx - if (!available.isEmpty()) { - const [weight, index] = available.pop() - idx = index - occupied.push([now + t, weight, index]) - if(i >= now) now++ - } else { - let [endTime, weight, index] = occupied.pop() - idx = index - occupied.push([endTime + t, weight, index]) - now = endTime - } - - res.push(idx) - } - - return res -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - - -/** - * @param {number[]} servers - * @param {number[]} tasks - * @return {number[]} - */ -const assignTasks = function(servers, tasks) { - const freePQ = new PriorityQueue((a, b) => a.w === b.w ? a.i < b.i : a.w < b.w) - const runningPQ = new PriorityQueue((a, b) => a.e === b.e ? (a.w === b.w ? a.i < b.i : a.w < b.w) : a.e < b.e) - const m = servers.length, n = tasks.length - for(let i = 0; i < m; i++) freePQ.push({w: servers[i], i, e: 0}) - const res = [] - for(let i = 0; i < n; i++) { - const cur = tasks[i] - while(!runningPQ.isEmpty() && runningPQ.peek().e <= i) { - const tmp = runningPQ.pop() - tmp.e = i - freePQ.push(tmp) - } - if(freePQ.isEmpty()) { - const tmp = runningPQ.pop() - res[i] = tmp.i - tmp.e += cur - runningPQ.push(tmp) - } else { - const tmp = freePQ.pop() - res[i] = tmp.i - tmp.e = i + cur - runningPQ.push(tmp) - } - } - return res -}; - -// another - -/** - * @param {number[]} servers - * @param {number[]} tasks - * @return {number[]} - */ -const assignTasks = function(servers, tasks) { - let i = 0 - const freePQ = new PriorityQueue((a, b) => { - if(a.w < b.w) return true - else if(a.w > b.w) return false - else { - if(a.idx < b.idx) return true - return false - } - }) - const runningPQ = new PriorityQueue((a, b) => { - return a.end < b.end - }) - const res = [] - for(let i = 0; i < servers.length; i++) { - freePQ.push({ - w: servers[i], - idx: i - }) - } - let taskIdx = 0 - while(taskIdx < tasks.length) { - while(!runningPQ.isEmpty() && runningPQ.peek().end <= i) { - let server = runningPQ.pop() - freePQ.push({ - w: server.w, - idx: server.idx - }) - } - - while(taskIdx <= i && !freePQ.isEmpty() && taskIdx < tasks.length) { - const server = freePQ.pop() - res[taskIdx] = server.idx - runningPQ.push({ - end: i + tasks[taskIdx], - w: server.w, - idx: server.idx - }) - taskIdx++ - } - if(i < tasks.length || !freePQ.isEmpty()) i++ - else i = Math.max(i + 1, runningPQ.peek().end) - } - return res -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -/** - * @param {number[]} servers - * @param {number[]} tasks - * @return {number[]} - */ -const assignTasks = function(servers, tasks) { - const freePQ = new PriorityQueue((a, b) => { - if(a.w < b.w) return true - else if(a.w > b.w) return false - else { - if(a.idx < b.idx) return true - return false - } - }) - const runningPQ = new PriorityQueue((a, b) => { - return a.end === b.end ? (a.w === b.w ? a.idx < b.idx : a.w < b.w) : a.end < b.end - }) - const res = [] - for(let i = 0; i < servers.length; i++) { - freePQ.push({ - w: servers[i], - idx: i - }) - } - for(let i = 0, n = tasks.length; i < n; i++) { - const cur = tasks[i] - while(runningPQ.size() && runningPQ.peek().end <= i) { - const el = runningPQ.pop() - freePQ.push({ - w: el.w, - idx: el.idx, - }) - } - - if(freePQ.isEmpty()) { - const el = runningPQ.pop() - res[i] = el.idx - el.end += cur - runningPQ.push(el) - } else { - const el = freePQ.pop() - res[i] = el.idx - el.end = i + cur - runningPQ.push(el) - } - } - - return res -}; - diff --git a/1882.process-tasks-using-servers.js b/1882.process-tasks-using-servers.js new file mode 100644 index 00000000..a52d9d6d --- /dev/null +++ b/1882.process-tasks-using-servers.js @@ -0,0 +1,107 @@ +/** + * @param {number[]} servers + * @param {number[]} tasks + * @return {number[]} + */ +const assignTasks = function(servers, tasks) { + const avail = new PQ((a, b) => a[0] === b[0] ? a[1] < b[1] : a[0] < b[0]) + const busy = new PQ((a, b) => a[2] < b[2]) + const res = [] + const { max } = Math + // init + for(let i = 0, len = servers.length; i < len; i++) { + avail.push([servers[i], i, 0]) + } + + for(let i = 0, len = tasks.length; i < len; i++) { + while(!busy.isEmpty() && busy.peek()[2] <= i) { + const s = busy.pop() + s[2] = i + avail.push(s) + } + if(!avail.isEmpty()) { + const s = avail.pop() + res.push(s[1]) + busy.push([s[0], s[1], max(i, s[2]) + tasks[i]]) + } else { + const tmp = busy.peek() + while(!busy.isEmpty() && busy.peek()[2] === tmp[2]) { + avail.push(busy.pop()) + } + const s = avail.pop() + res.push(s[1]) + busy.push([s[0], s[1], max(i, s[2]) + tasks[i]]) + } + } + + return res +}; + +class PQ { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + diff --git a/1883-minimum-skips-to-arrive-at-meeting-on-time.js b/1883.minimum-skips-to-arrive-at-meeting-on-time.js similarity index 100% rename from 1883-minimum-skips-to-arrive-at-meeting-on-time.js rename to 1883.minimum-skips-to-arrive-at-meeting-on-time.js diff --git a/1884-egg-drop-with-2-eggs-and-n-floors.js b/1884.egg-drop-with-2-eggs-and-n-floors.js similarity index 100% rename from 1884-egg-drop-with-2-eggs-and-n-floors.js rename to 1884.egg-drop-with-2-eggs-and-n-floors.js diff --git a/1885-count-pairs-in-two-arrays.js b/1885.count-pairs-in-two-arrays.js similarity index 100% rename from 1885-count-pairs-in-two-arrays.js rename to 1885.count-pairs-in-two-arrays.js diff --git a/1886-determine-whether-matrix-can-be-obtained-by-rotation.js b/1886.determine-whether-matrix-can-be-obtained-by-rotation.js similarity index 100% rename from 1886-determine-whether-matrix-can-be-obtained-by-rotation.js rename to 1886.determine-whether-matrix-can-be-obtained-by-rotation.js diff --git a/1887-reduction-operations-to-make-the-array-elements-equal.js b/1887.reduction-operations-to-make-the-array-elements-equal.js similarity index 100% rename from 1887-reduction-operations-to-make-the-array-elements-equal.js rename to 1887.reduction-operations-to-make-the-array-elements-equal.js diff --git a/1888-minimum-number-of-flips-to-make-the-binary-string-alternating.js b/1888-minimum-number-of-flips-to-make-the-binary-string-alternating.js deleted file mode 100644 index 0255d212..00000000 --- a/1888-minimum-number-of-flips-to-make-the-binary-string-alternating.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const minFlips = function (s) { - let n = s.length - let t = s + s - let a0 = 0 - let a1 = 0 - let b0 = 0 - let b1 = 0 - let ans = Infinity - for (let i = 0; i < t.length; i++) { - if (t[i] == '0') { - if (i % 2 == 0) { - a0++ - } else { - b0++ - } - } else { - if (i % 2 == 0) { - a1++ - } else { - b1++ - } - } - - if (i >= n) { - if (t[i - n] == '0') { - if ((i - n) % 2 == 0) { - a0-- - } else { - b0-- - } - } else { - if ((i - n) % 2 == 0) { - a1-- - } else { - b1-- - } - } - } - ans = Math.min(ans, Math.min(n - a0 - b1, n - a1 - b0)) - } - - return ans -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const minFlips = function (s) { - const n = s.length - s += s - let s1 = '', s2 = '' - for(let i = 0;i < s.length; i++) { - s1 += i % 2 === 0 ? '0' : '1' - s2 += i % 2 === 0 ? '1' : '0' - } - let res1 = 0, res2 = 0, res = Infinity - for(let i = 0; i < s.length; i++) { - if(s1[i] !== s[i]) res1++ - if(s2[i] !== s[i]) res2++ - if(i >= n) { - if(s1[i - n] !== s[i - n]) res1-- - if(s2[i - n] !== s[i - n]) res2-- - } - if(i >= n - 1) { - res = Math.min(res, res1, res2) - } - } - - return res -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const minFlips = function (s) { - const n = s.length - const ss = s + s - let s1 = '', s2 = '' - for(let i = 0; i < 2 * n; i++) { - if(i % 2 === 0) { - s1 += '0' - s2 += '1' - }else{ - s1 += '1' - s2 += '0' - } - } - - let res = Infinity, res1 = 0, res2 = 0 - - for (let i = 0; i < 2 * n; i++) { - if(ss[i] !== s1[i]) res1++ - if(ss[i] !== s2[i]) res2++ - if(i >= n) { - if(ss[i - n] !== s1[i - n]) res1-- - if(ss[i - n] !== s2[i - n]) res2-- - } - if(i >= n - 1) { - res = Math.min(res, res1, res2) - } - } - - return res -} - diff --git a/1888.minimum-number-of-flips-to-make-the-binary-string-alternating.js b/1888.minimum-number-of-flips-to-make-the-binary-string-alternating.js new file mode 100644 index 00000000..fabf8ae1 --- /dev/null +++ b/1888.minimum-number-of-flips-to-make-the-binary-string-alternating.js @@ -0,0 +1,48 @@ +/** + * @param {string} s + * @return {number} + */ +const minFlips = function (s) { + let n = s.length + let t = s + s + let a0 = 0 + let a1 = 0 + let b0 = 0 + let b1 = 0 + let ans = Infinity + for (let i = 0; i < t.length; i++) { + if (t[i] == '0') { + if (i % 2 == 0) { + a0++ + } else { + b0++ + } + } else { + if (i % 2 == 0) { + a1++ + } else { + b1++ + } + } + + if (i >= n) { + if (t[i - n] == '0') { + if ((i - n) % 2 == 0) { + a0-- + } else { + b0-- + } + } else { + if ((i - n) % 2 == 0) { + a1-- + } else { + b1-- + } + } + } + ans = Math.min(ans, Math.min(n - a0 - b1, n - a1 - b0)) + } + + return ans +} + diff --git a/1889-minimum-space-wasted-from-packaging.js b/1889-minimum-space-wasted-from-packaging.js deleted file mode 100644 index 1e733c58..00000000 --- a/1889-minimum-space-wasted-from-packaging.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @param {number[]} packages - * @param {number[][]} boxes - * @return {number} - */ -const minWastedSpace = function (packages, boxes) { - const mod = 1e9 + 7 - const n = packages.length - packages.sort((a, b) => a - b) - const preSum = packages.reduce( - (acc, cur) => { - acc.push(acc[acc.length - 1] + cur) - return acc - }, - [0] - ) - - const upperBound = (target) => { - let lo = 0, - hi = n - while (lo < hi) { - const mi = (lo + hi) >> 1 - const val = packages[mi] - if (val <= target) { - lo = mi + 1 - } else { - hi = mi - } - } - return lo - } - - let res = Infinity - for (const bs of boxes) { - bs.sort((a, b) => b - a) - if (bs[0] < packages[n - 1]) continue - let wastes = bs[0] * n - preSum[n] - let last = bs[0] - for (let i = 1; i < bs.length; i++) { - const b = bs[i] - const j = upperBound(b) - if (j <= 0) { - break - } - wastes -= (last - b) * j - last = b - } - res = Math.min(res, wastes) - } - return res === Infinity ? -1 : res % mod -} - -// another - -/** - * @param {number[]} packages - * @param {number[][]} boxes - * @return {number} - */ -var minWastedSpace = function (packages, boxes) { - packages.sort(function (a, b) { - return a - b - }) - let count = 0, - b, - wastage, - minWastage = Number.MAX_SAFE_INTEGER, - flag = false - for (let i = 0; i < boxes.length; i++) { - boxes[i].sort(function (a, b) { - return a - b - }) - b = 0 - wastage = 0 - count = 0 - if (boxes[i][boxes[i].length - 1] < packages[packages.length - 1]) { - //This supplier's largest box is smaller than our larget package, this supplier can't be used - continue - } - while (count < packages.length && b < boxes[i].length) { - if (packages[count] <= boxes[i][b]) { - wastage += boxes[i][b] - packages[count] - if (wastage > minWastage) { - //Need not to porcess this supplier if wastage has already been more than minWastage - break - } - count++ - } else { - b++ - } - } - if (count === packages.length) { - flag = true //We have found atleas 1 answer - if (wastage < minWastage) { - minWastage = wastage - } - } - } - if (flag === false) { - return -1 - } - return minWastage % 1000000007 -} diff --git a/1889.minimum-space-wasted-from-packaging.js b/1889.minimum-space-wasted-from-packaging.js new file mode 100644 index 00000000..f93455b1 --- /dev/null +++ b/1889.minimum-space-wasted-from-packaging.js @@ -0,0 +1,52 @@ +/** + * @param {number[]} packages + * @param {number[][]} boxes + * @return {number} + */ +const minWastedSpace = function (packages, boxes) { + const mod = 1e9 + 7 + const n = packages.length + packages.sort((a, b) => a - b) + const preSum = packages.reduce( + (acc, cur) => { + acc.push(acc[acc.length - 1] + cur) + return acc + }, + [0] + ) + + const upperBound = (target) => { + let lo = 0, + hi = n + while (lo < hi) { + const mi = (lo + hi) >> 1 + const val = packages[mi] + if (val <= target) { + lo = mi + 1 + } else { + hi = mi + } + } + return lo + } + + let res = Infinity + for (const bs of boxes) { + bs.sort((a, b) => b - a) + if (bs[0] < packages[n - 1]) continue + let wastes = bs[0] * n - preSum[n] + let last = bs[0] + for (let i = 1; i < bs.length; i++) { + const b = bs[i] + const j = upperBound(b) + if (j <= 0) { + break + } + wastes -= (last - b) * j + last = b + } + res = Math.min(res, wastes) + } + return res === Infinity ? -1 : res % mod +} + diff --git a/189-rotate-array.js b/189-rotate-array.js deleted file mode 100644 index f6017a19..00000000 --- a/189-rotate-array.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {void} Do not return anything, modify nums in-place instead. - */ -const rotate = function(nums, k) { - nums.unshift(...nums.splice(nums.length - k)) -}; - -// another - -const rotate = function(nums, k) { - let i = k - while (i > 0) { - nums.unshift(nums.pop()) - i-- - } -}; - -// another - -const rotate = function(nums, k) { - k %= nums.length - reverse(nums, 0, nums.length - 1) - reverse(nums, 0, k - 1) - reverse(nums, k, nums.length - 1) -} - -function reverse(nums, start, end) { - while (start < end) { - var temp = nums[start] - nums[start] = nums[end] - nums[end] = temp - start++ - end-- - } -} diff --git a/189.rotate-array.js b/189.rotate-array.js new file mode 100644 index 00000000..966d7153 --- /dev/null +++ b/189.rotate-array.js @@ -0,0 +1,9 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {void} Do not return anything, modify nums in-place instead. + */ +const rotate = function(nums, k) { + nums.unshift(...nums.splice(nums.length - k)) +}; + diff --git a/1891-cutting-ribbons.js b/1891.cutting-ribbons.js similarity index 100% rename from 1891-cutting-ribbons.js rename to 1891.cutting-ribbons.js diff --git a/1893-check-if-all-the-integers-in-a-range-are-covered.js b/1893-check-if-all-the-integers-in-a-range-are-covered.js deleted file mode 100644 index 34d23efe..00000000 --- a/1893-check-if-all-the-integers-in-a-range-are-covered.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {number[][]} ranges - * @param {number} left - * @param {number} right - * @return {boolean} - */ -const isCovered = function(ranges, left, right) { - const arr = Array(52).fill(0) - for(let [s, e] of ranges) { - arr[s]++ - arr[e + 1]-- - } - for(let i = 1; i < 52; i++) { - arr[i] += arr[i - 1] - } - for(let i = left; i <= right; i++) { - if(arr[i] === 0) return false - } - - return true -}; - -// another - -/** - * @param {number[][]} ranges - * @param {number} left - * @param {number} right - * @return {boolean} - */ -const isCovered = function(ranges, left, right) { - for(let i = left; i <= right; i++) { - let seen = false; - for(let j = 0; j < ranges.length && !seen; j++) - if(i >= ranges[j][0] && i <= ranges[j][1]) - seen = true; - if(!seen) return false; - } - return true; -}; - -// another - -/** - * @param {number[][]} ranges - * @param {number} left - * @param {number} right - * @return {boolean} - */ -const isCovered = function(ranges, left, right) { - const arr = Array(52).fill(0) - for(let [s, e] of ranges) { - arr[s]++ - arr[e + 1]-- - } - - let overlaps = 0 - for(let i = 1; i <= right; i++) { - overlaps += arr[i]; - if (i >= left && overlaps == 0) return false; - } - - return true -}; - diff --git a/1893.check-if-all-the-integers-in-a-range-are-covered.js b/1893.check-if-all-the-integers-in-a-range-are-covered.js new file mode 100644 index 00000000..42b016cc --- /dev/null +++ b/1893.check-if-all-the-integers-in-a-range-are-covered.js @@ -0,0 +1,22 @@ +/** + * @param {number[][]} ranges + * @param {number} left + * @param {number} right + * @return {boolean} + */ +const isCovered = function(ranges, left, right) { + const arr = Array(52).fill(0) + for(let [s, e] of ranges) { + arr[s]++ + arr[e + 1]-- + } + for(let i = 1; i < 52; i++) { + arr[i] += arr[i - 1] + } + for(let i = left; i <= right; i++) { + if(arr[i] === 0) return false + } + + return true +}; + diff --git a/1896-minimum-cost-to-change-the-final-value-of-expression.js b/1896.minimum-cost-to-change-the-final-value-of-expression.js similarity index 100% rename from 1896-minimum-cost-to-change-the-final-value-of-expression.js rename to 1896.minimum-cost-to-change-the-final-value-of-expression.js diff --git a/1897-redistribute-characters-to-make-all-strings-equal.js b/1897.redistribute-characters-to-make-all-strings-equal.js similarity index 100% rename from 1897-redistribute-characters-to-make-all-strings-equal.js rename to 1897.redistribute-characters-to-make-all-strings-equal.js diff --git a/1898-maximum-number-of-removable-characters.js b/1898-maximum-number-of-removable-characters.js deleted file mode 100644 index 043796cc..00000000 --- a/1898-maximum-number-of-removable-characters.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {string} s - * @param {string} p - * @param {number[]} removable - * @return {number} - */ -const maximumRemovals = function (s, p, removable) { - const n = removable.length - let l = 0, - r = n - while (l < r) { - let mid = (l + r + 1) >> 1 - if (is_valid(s, p, removable, mid)) l = mid - else r = mid - 1 - } - return l -} - -function is_valid(s, p, removable, cnt) { - let len1 = s.length, - len2 = p.length - const check = Array(len1).fill(0) - for (let i = 0; i < cnt; i++) check[removable[i]] = 1 - let ind1 = 0, - ind2 = 0 - while (ind1 < len1 && ind2 < len2) { - if (s[ind1] != p[ind2] || check[ind1]) { - ind1++ - continue - } - ind1++, ind2++ - } - return ind2 == len2 -} - -// another - -/** - * @param {string} s - * @param {string} p - * @param {number[]} removable - * @return {number} - */ -const maximumRemovals = function(s, p, removable) { - let l = 0, r = removable.length - while(l < r) { - const mid = r - Math.floor((r - l) / 2) - if(valid(mid)) l = mid - else r = mid - 1 - } - return l - - function valid(mid) { - let arr = s.split('') - for (let i = 0; i < mid; i++) arr[removable[i]] = null - arr = arr.filter(e => e !== null) - - for(let i = 0, j = 0; i < arr.length && j < p.length;) { - if(arr[i] === p[j]) i++, j++ - else i++ - if(j === p.length) return true - } - return false - } -}; diff --git a/1898.maximum-number-of-removable-characters.js b/1898.maximum-number-of-removable-characters.js new file mode 100644 index 00000000..3db210f2 --- /dev/null +++ b/1898.maximum-number-of-removable-characters.js @@ -0,0 +1,35 @@ +/** + * @param {string} s + * @param {string} p + * @param {number[]} removable + * @return {number} + */ +const maximumRemovals = function (s, p, removable) { + const n = removable.length + let l = 0, + r = n + while (l < r) { + let mid = (l + r + 1) >> 1 + if (is_valid(s, p, removable, mid)) l = mid + else r = mid - 1 + } + return l +} + +function is_valid(s, p, removable, cnt) { + let len1 = s.length, + len2 = p.length + const check = Array(len1).fill(0) + for (let i = 0; i < cnt; i++) check[removable[i]] = 1 + let ind1 = 0, + ind2 = 0 + while (ind1 < len1 && ind2 < len2) { + if (s[ind1] != p[ind2] || check[ind1]) { + ind1++ + continue + } + ind1++, ind2++ + } + return ind2 == len2 +} + diff --git a/1899-merge-triplets-to-form-target-triplet.js b/1899.merge-triplets-to-form-target-triplet.js similarity index 100% rename from 1899-merge-triplets-to-form-target-triplet.js rename to 1899.merge-triplets-to-form-target-triplet.js diff --git a/19-remove-nth-node-from-end-of-list.js b/19-remove-nth-node-from-end-of-list.js deleted file mode 100755 index e5390374..00000000 --- a/19-remove-nth-node-from-end-of-list.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @param {number} n - * @return {ListNode} - */ -const removeNthFromEnd = (head, n) => { - if (head.next === null) return null; - - let ptrBeforeN = head; - let count = 1; - - // While there are more elements - let el = head.next; - while (el !== null) { - if (count > n) ptrBeforeN = ptrBeforeN.next; - el = el.next; - count++; - } - - if (count === n) return head.next; - - ptrBeforeN.next = ptrBeforeN.next.next; - return head; -}; diff --git a/19.remove-nth-node-from-end-of-list.js b/19.remove-nth-node-from-end-of-list.js new file mode 100644 index 00000000..51f62d93 --- /dev/null +++ b/19.remove-nth-node-from-end-of-list.js @@ -0,0 +1,31 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @param {number} n + * @return {ListNode} + */ +const removeNthFromEnd = (head, n) => { + if (head.next === null) return null; + + let ptrBeforeN = head; + let count = 1; + + // While there are more elements + let el = head.next; + while (el !== null) { + if (count > n) ptrBeforeN = ptrBeforeN.next; + el = el.next; + count++; + } + + if (count === n) return head.next; + + ptrBeforeN.next = ptrBeforeN.next.next; + return head; +}; diff --git a/190-reverse-bits.js b/190-reverse-bits.js deleted file mode 100644 index afa6c0b6..00000000 --- a/190-reverse-bits.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @param {number} n - a positive integer - * @return {number} - a positive integer - */ -const reverseBits = function(n) { - let r = 0; - for (let i = 0; i < 32; i++) { - if (n & 1) { - r = r | 1; - } - if (i !== 31) { - r = r << 1; - n = n >> 1; - } - } - return r >>> 0; -}; - -// another - -/** - * @param {number} n - a positive integer - * @return {number} - a positive integer - */ -const reverseBits = function(n) { - let s = ''; - let count = 0; - let index = 31; - while (n > 0) { - if (n % 2 !== 0) count += Math.pow(2, index); - index--; - n = Math.floor(n / 2); - } - return count; -}; - -// another - -/** - * @param {number} n - a positive integer - * @return {number} - a positive integer - */ -const reverseBits = function(n) { - const b = n.toString(2) - const leadingZeroes = b.padStart(32,'0') - const rev = leadingZeroes.split('') - rev.reverse() - return parseInt(rev.join(''), 2) -}; diff --git a/190.reverse-bits.js b/190.reverse-bits.js new file mode 100644 index 00000000..45bc116c --- /dev/null +++ b/190.reverse-bits.js @@ -0,0 +1,18 @@ +/** + * @param {number} n - a positive integer + * @return {number} - a positive integer + */ +const reverseBits = function(n) { + let r = 0; + for (let i = 0; i < 32; i++) { + if (n & 1) { + r = r | 1; + } + if (i !== 31) { + r = r << 1; + n = n >> 1; + } + } + return r >>> 0; +}; + diff --git a/1900-the-earliest-and-latest-rounds-where-players-compete.js b/1900.the-earliest-and-latest-rounds-where-players-compete.js similarity index 100% rename from 1900-the-earliest-and-latest-rounds-where-players-compete.js rename to 1900.the-earliest-and-latest-rounds-where-players-compete.js diff --git a/1901-find-a-peak-element-ii.js b/1901.find-a-peak-element-ii.js similarity index 100% rename from 1901-find-a-peak-element-ii.js rename to 1901.find-a-peak-element-ii.js diff --git a/1903-largest-odd-number-in-string.js b/1903.largest-odd-number-in-string.js similarity index 100% rename from 1903-largest-odd-number-in-string.js rename to 1903.largest-odd-number-in-string.js diff --git a/1904-the-number-of-full-rounds-you-have-played.js b/1904-the-number-of-full-rounds-you-have-played.js deleted file mode 100644 index d53993e3..00000000 --- a/1904-the-number-of-full-rounds-you-have-played.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @param {string} startTime - * @param {string} finishTime - * @return {number} - */ -const numberOfRounds = function(startTime, finishTime) { - let start = 60 * parseInt(startTime.slice(0, 2)) + parseInt(startTime.slice(3)) - let finish = 60 * parseInt(finishTime.slice(0, 2)) + parseInt(finishTime.slice(3)); - if (start > finish) finish += 60 * 24; // If `finishTime` is earlier than `startTime`, add 24 hours to `finishTime`. - return Math.max(0, Math.floor(finish / 15) - Math.ceil(start / 15)); // floor(finish / 15) - ceil(start / 15) -}; - -// another - -/** - * @param {string} startTime - * @param {string} finishTime - * @return {number} - */ -const numberOfRounds = function(startTime, finishTime) { - const { ceil, floor } = Math - const start = new Node(startTime), finish = new Node(finishTime) - if(finish.compare(start)) finish.hour += 24 - let cnt = 0 - if(start.hour === finish.hour) { - const r = floor(finish.minute / 15) - const l = ceil(start.minute / 15) - if(l >= r) return 0 - return r - l - } - cnt += 4 - ceil(start.minute / 15) + floor(finish.minute / 15) - start.hour++ - cnt += (finish.hour - start.hour) * 4 - return cnt -}; - -class Node { - constructor(str) { - this.hour = +str.slice(0, 2) - this.minute = +str.slice(3) - } - compare(node) { - return this.hour === node.hour ? this.minute < node.minute : this.hour < node.hour - } -} diff --git a/1904.the-number-of-full-rounds-you-have-played.js b/1904.the-number-of-full-rounds-you-have-played.js new file mode 100644 index 00000000..3fa8845a --- /dev/null +++ b/1904.the-number-of-full-rounds-you-have-played.js @@ -0,0 +1,12 @@ +/** + * @param {string} startTime + * @param {string} finishTime + * @return {number} + */ +const numberOfRounds = function(startTime, finishTime) { + let start = 60 * parseInt(startTime.slice(0, 2)) + parseInt(startTime.slice(3)) + let finish = 60 * parseInt(finishTime.slice(0, 2)) + parseInt(finishTime.slice(3)); + if (start > finish) finish += 60 * 24; // If `finishTime` is earlier than `startTime`, add 24 hours to `finishTime`. + return Math.max(0, Math.floor(finish / 15) - Math.ceil(start / 15)); // floor(finish / 15) - ceil(start / 15) +}; + diff --git a/1905-count-sub-islands.js b/1905.count-sub-islands.js similarity index 100% rename from 1905-count-sub-islands.js rename to 1905.count-sub-islands.js diff --git a/1906-minimum-absolute-difference-queries.js b/1906.minimum-absolute-difference-queries.js similarity index 100% rename from 1906-minimum-absolute-difference-queries.js rename to 1906.minimum-absolute-difference-queries.js diff --git a/1909-remove-one-element-to-make-the-array-strictly-increasing.js b/1909.remove-one-element-to-make-the-array-strictly-increasing.js similarity index 100% rename from 1909-remove-one-element-to-make-the-array-strictly-increasing.js rename to 1909.remove-one-element-to-make-the-array-strictly-increasing.js diff --git a/191-number-of-1-bits.js b/191-number-of-1-bits.js deleted file mode 100644 index 8395aae6..00000000 --- a/191-number-of-1-bits.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @param {number} n - a positive integer - * @return {number} - */ -const hammingWeight = function(n) { - let res = 0 - while(n > 0) { - if(n & 1) res++ - n = n >>> 1 - } - return res -}; - -// another - -/** - * @param {number} n - a positive integer - * @return {number} - */ -const hammingWeight = function(n) { - const str = (n >>> 0).toString(2) - let res = 0 - for(let c of str) { - if(c === '1') res++ - } - return res -}; diff --git a/191.number-of-1-bits.js b/191.number-of-1-bits.js new file mode 100644 index 00000000..8cfa40f2 --- /dev/null +++ b/191.number-of-1-bits.js @@ -0,0 +1,13 @@ +/** + * @param {number} n - a positive integer + * @return {number} + */ +const hammingWeight = function(n) { + let res = 0 + while(n > 0) { + if(n & 1) res++ + n = n >>> 1 + } + return res +}; + diff --git a/1910-remove-all-occurrences-of-a-substring.js b/1910.remove-all-occurrences-of-a-substring.js similarity index 100% rename from 1910-remove-all-occurrences-of-a-substring.js rename to 1910.remove-all-occurrences-of-a-substring.js diff --git a/1911-maximum-alternating-subsequence-sum.js b/1911-maximum-alternating-subsequence-sum.js deleted file mode 100644 index 555eefb8..00000000 --- a/1911-maximum-alternating-subsequence-sum.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const maxAlternatingSum = function(nums) { - let odd = 0, even = 0; - for (let a of nums) { - even = Math.max(even, odd + a); - odd = even - a; - } - return even; -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxAlternatingSum = function(nums) { - let res = nums[0] - for(let i = 1; i < nums.length; i++) { - res += Math.max(nums[i] - nums[i - 1], 0) - } - return res -}; diff --git a/1911.maximum-alternating-subsequence-sum.js b/1911.maximum-alternating-subsequence-sum.js new file mode 100644 index 00000000..f882a39c --- /dev/null +++ b/1911.maximum-alternating-subsequence-sum.js @@ -0,0 +1,13 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const maxAlternatingSum = function(nums) { + let odd = 0, even = 0; + for (let a of nums) { + even = Math.max(even, odd + a); + odd = even - a; + } + return even; +}; + diff --git a/1913-maximum-product-difference-between-two-pairs.js b/1913.maximum-product-difference-between-two-pairs.js similarity index 100% rename from 1913-maximum-product-difference-between-two-pairs.js rename to 1913.maximum-product-difference-between-two-pairs.js diff --git a/1914-cyclically-rotating-a-gridsubmissions.js b/1914-cyclically-rotating-a-gridsubmissions.js deleted file mode 100644 index 056a22c3..00000000 --- a/1914-cyclically-rotating-a-gridsubmissions.js +++ /dev/null @@ -1,107 +0,0 @@ -/** - * @param {number[][]} grid - * @param {number} k - * @return {number[][]} - */ -const rotateGrid = function(grid, k) { - const m = grid.length, n = grid[0].length - let top = 0, left = 0, right = n - 1, bottom = m - 1 - while(top < bottom && left < right) { - const num = (right - left + 1) * 2 + (bottom - top + 1) * 2 - 4 - let rem = k % num - while(rem) { - const tmp = grid[top][left] - // top - for(let i = left; i < right; i++) { - grid[top][i] = grid[top][i + 1] - } - // right - for(let i = top; i < bottom; i++) { - grid[i][right] = grid[i + 1][right] - } - // bottom - for(let i = right; i > left; i--) { - grid[bottom][i] = grid[bottom][i - 1] - } - // left - for(let i = bottom; i > top; i--) { - grid[i][left] = grid[i - 1][left] - } - grid[top + 1][left] = tmp - rem-- - } - left++ - top++ - right-- - bottom-- - } - return grid -}; - -// another - -/** - * @param {number[][]} grid - * @param {number} k - * @return {number[][]} - */ -var rotateGrid = function(grid, k) { - var m = grid.length; - var n = grid[0].length; - - // step1: loop each layer - var layer = Math.min(n/2, m/2); - for(l = 0; l=l; j--) - { - cur.push(grid[m-l-1][j]); - } - // left - for(var i = m-l-2; i>l; i--) - { - cur.push(grid[i][l]); - } - - // step3: rotation (k%len) on one-dimension array - var d = cur.length; - var offset = k % d; - cur = [...cur.slice(offset, d), ...cur.slice(0, offset)]; - - // step4: refill rotated array back to 2D array at current layer - var index = 0; - // top - for(var j = l; j=l; j--) - { - grid[m-l-1][j] = cur[index++]; - } - // left - for(var i = m-l-2; i>l; i--) - { - grid[i][l] = cur[index++]; - } - } - return grid; -}; diff --git a/1914.cyclically-rotating-a-gridsubmissions.js b/1914.cyclically-rotating-a-gridsubmissions.js new file mode 100644 index 00000000..9f4f80b9 --- /dev/null +++ b/1914.cyclically-rotating-a-gridsubmissions.js @@ -0,0 +1,40 @@ +/** + * @param {number[][]} grid + * @param {number} k + * @return {number[][]} + */ +const rotateGrid = function(grid, k) { + const m = grid.length, n = grid[0].length + let top = 0, left = 0, right = n - 1, bottom = m - 1 + while(top < bottom && left < right) { + const num = (right - left + 1) * 2 + (bottom - top + 1) * 2 - 4 + let rem = k % num + while(rem) { + const tmp = grid[top][left] + // top + for(let i = left; i < right; i++) { + grid[top][i] = grid[top][i + 1] + } + // right + for(let i = top; i < bottom; i++) { + grid[i][right] = grid[i + 1][right] + } + // bottom + for(let i = right; i > left; i--) { + grid[bottom][i] = grid[bottom][i - 1] + } + // left + for(let i = bottom; i > top; i--) { + grid[i][left] = grid[i - 1][left] + } + grid[top + 1][left] = tmp + rem-- + } + left++ + top++ + right-- + bottom-- + } + return grid +}; + diff --git a/1915-number-of-wonderful-substrings.js b/1915-number-of-wonderful-substrings.js deleted file mode 100644 index 8402c87d..00000000 --- a/1915-number-of-wonderful-substrings.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @param {string} word - * @return {number} - */ -const wonderfulSubstrings = (word) => { - let res = 0, count = Array(1024).fill(0); - let cur = 0; - count[0] = 1; - for (let i = 0; i < word.length; ++i) { - const num = word[i].charCodeAt() - 97; - cur ^= 1 << (num); - res += count[cur]; - ++count[cur]; - - for (let j = 0; j < 10; ++j) { - res += count[cur ^ (1 << j)]; - } - } - - return res; -}; - -// another - -/** - * @param {string} word - * @return {number} - */ -const asi = (c) => c.charCodeAt(); -const wonderfulSubstrings = (s) => { - let res = 0; - let f = Array(2 ** 10).fill(0); - f[0] = 1; // count array - let cur = res = 0; - for (const c of s) { - cur ^= 1 << asi(c) - 97; // get Hash (the set bit for a character.), update prefix parity - res += f[cur]; - for (let i = 0; i < 10; i++) { // a ~ j - res += f[cur ^ 1 << i]; // 1 << i get Hash - } - f[cur]++; - } - return res; -}; diff --git a/1915.number-of-wonderful-substrings.js b/1915.number-of-wonderful-substrings.js new file mode 100644 index 00000000..29310425 --- /dev/null +++ b/1915.number-of-wonderful-substrings.js @@ -0,0 +1,22 @@ +/** + * @param {string} word + * @return {number} + */ +const wonderfulSubstrings = (word) => { + let res = 0, count = Array(1024).fill(0); + let cur = 0; + count[0] = 1; + for (let i = 0; i < word.length; ++i) { + const num = word[i].charCodeAt() - 97; + cur ^= 1 << (num); + res += count[cur]; + ++count[cur]; + + for (let j = 0; j < 10; ++j) { + res += count[cur ^ (1 << j)]; + } + } + + return res; +}; + diff --git a/1916-count-ways-to-build-rooms-in-an-ant-colony.js b/1916.count-ways-to-build-rooms-in-an-ant-colony.js similarity index 100% rename from 1916-count-ways-to-build-rooms-in-an-ant-colony.js rename to 1916.count-ways-to-build-rooms-in-an-ant-colony.js diff --git a/1918-kth-smallest-subarray-sum.js b/1918.kth-smallest-subarray-sum.js similarity index 100% rename from 1918-kth-smallest-subarray-sum.js rename to 1918.kth-smallest-subarray-sum.js diff --git a/1920-build-array-from-permutation.js b/1920.build-array-from-permutation.js similarity index 100% rename from 1920-build-array-from-permutation.js rename to 1920.build-array-from-permutation.js diff --git a/1921-eliminate-maximum-number-of-monsters.js b/1921.eliminate-maximum-number-of-monsters.js similarity index 100% rename from 1921-eliminate-maximum-number-of-monsters.js rename to 1921.eliminate-maximum-number-of-monsters.js diff --git a/1922-count-good-numbers.js b/1922.count-good-numbers.js similarity index 100% rename from 1922-count-good-numbers.js rename to 1922.count-good-numbers.js diff --git a/1923-longest-common-subpath.js b/1923.longest-common-subpath.js similarity index 100% rename from 1923-longest-common-subpath.js rename to 1923.longest-common-subpath.js diff --git a/1925-count-square-sum-triples.js b/1925.count-square-sum-triples.js similarity index 100% rename from 1925-count-square-sum-triples.js rename to 1925.count-square-sum-triples.js diff --git a/1928-minimum-cost-to-reach-destination-in-time.js b/1928.minimum-cost-to-reach-destination-in-time.js similarity index 100% rename from 1928-minimum-cost-to-reach-destination-in-time.js rename to 1928.minimum-cost-to-reach-destination-in-time.js diff --git a/1929-concatenation-of-array.js b/1929.concatenation-of-array.js similarity index 100% rename from 1929-concatenation-of-array.js rename to 1929.concatenation-of-array.js diff --git a/1930-unique-length-3-palindromic-subsequences.js b/1930-unique-length-3-palindromic-subsequences.js deleted file mode 100644 index d615b832..00000000 --- a/1930-unique-length-3-palindromic-subsequences.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const countPalindromicSubsequence = function(s) { - const first = Array(26).fill(Infinity), last = Array(26).fill(0) - let res = 0 - const n = s.length, a = 'a'.charCodeAt(0) - for(let i = 0; i < n; i++) { - const code = s[i].charCodeAt(0) - first[code - a] = Math.min(i, first[code - a]) - last[code - a] = i - } - - for(let i = 0; i < 26; i++) { - if(last[i] - 1 > first[i]) { - const tmp = s.slice(first[i] + 1, last[i]) - const set = new Set() - for(let ch of tmp) set.add(ch) - res += set.size - } - } - - return res -}; - -// another - - -/** - * @param {string} s - * @return {number} - */ -const countPalindromicSubsequence = (s) => { - let res = 0; - for (let i = 0; i < 26; i++) { - for (let j = 0; j < 26; j++) { - let len = 0; - for (const c of s) { - if(len === 3) break - if (len == 0) { - if (c.charCodeAt() - 97 == i) len++; // first char - } else if (len == 1) { - if (c.charCodeAt() - 97 == j) len++; // second char - } else if (len == 2) { - if (c.charCodeAt() - 97 == i) len++; // third char - } - } - if (len == 3) res++; - } - } - return res; -}; diff --git a/1930.unique-length-3-palindromic-subsequences.js b/1930.unique-length-3-palindromic-subsequences.js new file mode 100644 index 00000000..bd4297fe --- /dev/null +++ b/1930.unique-length-3-palindromic-subsequences.js @@ -0,0 +1,26 @@ +/** + * @param {string} s + * @return {number} + */ +const countPalindromicSubsequence = function(s) { + const first = Array(26).fill(Infinity), last = Array(26).fill(0) + let res = 0 + const n = s.length, a = 'a'.charCodeAt(0) + for(let i = 0; i < n; i++) { + const code = s[i].charCodeAt(0) + first[code - a] = Math.min(i, first[code - a]) + last[code - a] = i + } + + for(let i = 0; i < 26; i++) { + if(last[i] - 1 > first[i]) { + const tmp = s.slice(first[i] + 1, last[i]) + const set = new Set() + for(let ch of tmp) set.add(ch) + res += set.size + } + } + + return res +}; + diff --git a/1931-painting-a-grid-with-three-different-colors.js b/1931-painting-a-grid-with-three-different-colors.js deleted file mode 100644 index 2e3cec5a..00000000 --- a/1931-painting-a-grid-with-three-different-colors.js +++ /dev/null @@ -1,149 +0,0 @@ -/** - * @param {number} m - * @param {number} n - * @return {number} - */ -const colorTheGrid = function(m, n) { - // Get color of the `mask` at `pos`, 2 bit store 1 color - function getColor(mask, pos) { - return (mask >> (2 * pos)) & 3 - } - // Set `color` to the `mask` at `pos`, 2 bit store 1 color - function setColor(mask, pos, color) { - return mask | (color << (2 * pos)) - } - function dfs(r, curColMask, prevColMask, out) { - // Filled full color for a row - if(r === m) { - out.push(curColMask) - return - } - // Try colors i in [1=RED, 2=GREEN, 3=BLUE] - for(let i = 1; i <= 3; i++) { - if(getColor(prevColMask, r) !== i && (r === 0 || getColor(curColMask, r - 1) !== i)) { - dfs(r + 1, setColor(curColMask, r, i), prevColMask, out) - } - } - } - // Generate all possible columns we can draw, if the previous col is `prevColMask` - function neighbor(prevColMask) { - let out = [] - dfs(0, 0, prevColMask, out) - return out - } - const mod = 10 ** 9 + 7 - const memo = {} - function dp(c, prevColMask) { - // Found a valid way - if(c === n) return 1 - if(memo[`${c},${prevColMask}`] != null) return memo[`${c},${prevColMask}`] - let res = 0 - const arr = neighbor(prevColMask) - for(let e of arr) { - res = (res + dp(c + 1, e)) % mod - } - memo[`${c},${prevColMask}`] = res - return res - } - - return dp(0, 0) - -}; - -// another - -/** - * @param {number} m - * @param {number} n - * @return {number} - */ -const colorTheGrid = function(m, n) { - const mod = 10 ** 9 + 7 - const colors = [1, 2, 3] - const memoDp = {}, memoOpts = {} - function getColor(pos, preMask) { - return (preMask >> (pos * 2)) & 3 - } - function setColor(pos, color, curMask) { - return curMask | (color << (pos * 2)) - } - function dfs(pos, curMask, preMask, res) { - if(pos === m) { - res.push(curMask) - return - } - for(let c of colors) { - if(getColor(pos, preMask) !== c && (pos === 0 || getColor(pos - 1, curMask) !== c)) { - dfs(pos + 1, setColor(pos, c, curMask), preMask, res) - } - } - } - function curOpts(preMask) { - if (memoOpts[preMask]) return memoOpts[preMask] - const res = [] - dfs(0, 0, preMask, res) - memoOpts[preMask] = res - return res - } - function dp(col, preMask) { - const k = `${col},${preMask}` - if(col === n) return 1 - if(memoDp[k]) return memoDp[k] - let res = 0 - const cur = curOpts(preMask) - for(let mask of cur) { - res = (res + dp(col + 1, mask)) % mod - } - memoDp[k] = res - return res - } - - return dp(0, 0) -}; - -// another - -/** - * @param {number} m - * @param {number} n - * @return {number} - */ -const colorTheGrid = function(m, n) { - const mod = 1e9 + 7 - const limit = 1 << (2 * m) - const memo = Array.from({ length: n }, () => Array(limit)) - - return dp(0, 0) - - function dp(col, preColMask) { - if(col === n) return 1 - let res = 0 - - if(memo[col][preColMask] != null) return memo[col][preColMask] - const curColMasks = [] - dfs(preColMask, 0, 0, curColMasks) - for(const colMask of curColMasks) { - res = (res + dp(col + 1, colMask)) % mod - } - return memo[col][preColMask] = res - } - - function dfs(preColMask, curColMask, row, res) { - if(row === m) { - res.push(curColMask) - return - } - for(let i = 1; i <= 3; i++) { - if(getColor(preColMask, row) !== i && (row === 0 || getColor(curColMask, row - 1) !== i)) { - dfs(preColMask, setColor(curColMask, row, i) ,row + 1, res) - } - } - } - - function getColor(mask, row) { - return (mask >> (2 * row)) & 3 - } - function setColor(mask, row, val) { - return mask | (val << (2 * row)) - } -}; diff --git a/1931.painting-a-grid-with-three-different-colors.js b/1931.painting-a-grid-with-three-different-colors.js new file mode 100644 index 00000000..36907dfa --- /dev/null +++ b/1931.painting-a-grid-with-three-different-colors.js @@ -0,0 +1,52 @@ +/** + * @param {number} m + * @param {number} n + * @return {number} + */ +const colorTheGrid = function(m, n) { + // Get color of the `mask` at `pos`, 2 bit store 1 color + function getColor(mask, pos) { + return (mask >> (2 * pos)) & 3 + } + // Set `color` to the `mask` at `pos`, 2 bit store 1 color + function setColor(mask, pos, color) { + return mask | (color << (2 * pos)) + } + function dfs(r, curColMask, prevColMask, out) { + // Filled full color for a row + if(r === m) { + out.push(curColMask) + return + } + // Try colors i in [1=RED, 2=GREEN, 3=BLUE] + for(let i = 1; i <= 3; i++) { + if(getColor(prevColMask, r) !== i && (r === 0 || getColor(curColMask, r - 1) !== i)) { + dfs(r + 1, setColor(curColMask, r, i), prevColMask, out) + } + } + } + // Generate all possible columns we can draw, if the previous col is `prevColMask` + function neighbor(prevColMask) { + let out = [] + dfs(0, 0, prevColMask, out) + return out + } + const mod = 10 ** 9 + 7 + const memo = {} + function dp(c, prevColMask) { + // Found a valid way + if(c === n) return 1 + if(memo[`${c},${prevColMask}`] != null) return memo[`${c},${prevColMask}`] + let res = 0 + const arr = neighbor(prevColMask) + for(let e of arr) { + res = (res + dp(c + 1, e)) % mod + } + memo[`${c},${prevColMask}`] = res + return res + } + + return dp(0, 0) + +}; + diff --git a/1932-merge-bsts-to-create-single-bst.js b/1932.merge-bsts-to-create-single-bst.js similarity index 100% rename from 1932-merge-bsts-to-create-single-bst.js rename to 1932.merge-bsts-to-create-single-bst.js diff --git a/1935-maximum-number-of-words-you-can-type.js b/1935.maximum-number-of-words-you-can-type.js similarity index 100% rename from 1935-maximum-number-of-words-you-can-type.js rename to 1935.maximum-number-of-words-you-can-type.js diff --git a/1936-add-minimum-number-of-rungs.js b/1936.add-minimum-number-of-rungs.js similarity index 100% rename from 1936-add-minimum-number-of-rungs.js rename to 1936.add-minimum-number-of-rungs.js diff --git a/1937-maximum-number-of-points-with-cost.js b/1937-maximum-number-of-points-with-cost.js deleted file mode 100644 index 83e5caf7..00000000 --- a/1937-maximum-number-of-points-with-cost.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @param {number[][]} points - * @return {number} - */ -const maxPoints = function(points) { - const m = points.length, n = points[0].length - let prev = points[0].slice() - for(let i = 1; i < m; i++) { - const left = [] - left[0] = prev[0] - // left to right - for(let j = 1; j < n; j++) { - left[j] = Math.max(prev[j], left[j - 1] - 1) - } - const right = [] - right[n - 1] = prev[n - 1] - // right to left - for(let j = n - 2; j >= 0; j--) { - right[j] = Math.max(prev[j], right[j + 1] - 1) - } - - const cur = [] - for(let j = 0; j < n; j++) { - cur[j] = Math.max(left[j], right[j]) + points[i][j] - } - prev = cur - } - - return Math.max(...prev) -}; - -// another - -/** - * @param {number[][]} points - * @return {number} - */ -const maxPoints = function(points) { - let m = points.length, n = points[0].length; - let result = 0; - // dp - const dp = Array.from({ length: m }, () => Array(n).fill(0)); - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - if (i == 0) { - dp[i][j] = points[i][j]; - } else { - dp[i][j] = Math.max(points[i][j] + dp[i - 1][j], dp[i][j]); - } - } - for (let j = 0; j < n; j++) { - // right - for (let k = 1; k < n - j; k++) { - if (dp[i][j + k] >= dp[i][j] - k) { - break; - } - dp[i][j + k] = dp[i][j] - k; - } - for (let k = 1; k <= j; k++) { - if (dp[i][j - k] >= dp[i][j] - k) { - break; - } - dp[i][j - k] = dp[i][j] - k; - } - } - } - for (let j = 0; j < n; j++) { - result = Math.max(result, dp[m - 1][j]); - } - return result; -}; diff --git a/1937.maximum-number-of-points-with-cost.js b/1937.maximum-number-of-points-with-cost.js new file mode 100644 index 00000000..a9df9f58 --- /dev/null +++ b/1937.maximum-number-of-points-with-cost.js @@ -0,0 +1,31 @@ +/** + * @param {number[][]} points + * @return {number} + */ +const maxPoints = function(points) { + const m = points.length, n = points[0].length + let prev = points[0].slice() + for(let i = 1; i < m; i++) { + const left = [] + left[0] = prev[0] + // left to right + for(let j = 1; j < n; j++) { + left[j] = Math.max(prev[j], left[j - 1] - 1) + } + const right = [] + right[n - 1] = prev[n - 1] + // right to left + for(let j = n - 2; j >= 0; j--) { + right[j] = Math.max(prev[j], right[j + 1] - 1) + } + + const cur = [] + for(let j = 0; j < n; j++) { + cur[j] = Math.max(left[j], right[j]) + points[i][j] + } + prev = cur + } + + return Math.max(...prev) +}; + diff --git a/1938-maximum-genetic-difference-query.js b/1938.maximum-genetic-difference-query.js similarity index 100% rename from 1938-maximum-genetic-difference-query.js rename to 1938.maximum-genetic-difference-query.js diff --git a/1941-check-if-all-characters-have-equal-number-of-occurrences.js b/1941.check-if-all-characters-have-equal-number-of-occurrences.js similarity index 100% rename from 1941-check-if-all-characters-have-equal-number-of-occurrences.js rename to 1941.check-if-all-characters-have-equal-number-of-occurrences.js diff --git a/1942-the-number-of-the-smallest-unoccupied-chair.js b/1942-the-number-of-the-smallest-unoccupied-chair.js deleted file mode 100644 index 0876ec69..00000000 --- a/1942-the-number-of-the-smallest-unoccupied-chair.js +++ /dev/null @@ -1,256 +0,0 @@ -/** - * @param {number[][]} times - * @param {number} targetFriend - * @return {number} - */ -const smallestChair = function(times, targetFriend) { - const avail = new PQ((a, b) => a[0] < b[0]) - const occupied = new PQ((a, b) => a[1] < b[1]) - const n = times.length - for(let i = 0; i < n; i++) { - avail.push([i, 0]) - } - times.forEach((e, i) => e.push(i)) - times.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]) - - for(let i = 0; i < n; i++) { - let res = -1 - const [s, e, idx] = times[i] - while(!occupied.isEmpty() && occupied.peek()[1] <= s) { - avail.push(occupied.pop()) - } - - const c = avail.pop() - res = c[0] - c[1] = e - occupied.push(c) - - if(idx === targetFriend) { - return res - } - } -}; - -class PQ { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -/** - * @param {number[][]} times - * @param {number} targetFriend - * @return {number} - */ -const smallestChair = function (times, targetFriend) { - const targetArrival = times[targetFriend][0] - let seatNum = 0 - let res = 0 - const n = times.length - - times.sort((a, b) => a[0] - b[0]) - - const occupied = new PriorityQueue((a, b) => a[0] < b[0]) - const available = new PriorityQueue((a, b) => a < b) - - for(let i = 0; i < n; i++) { - const [arrival, leaving] = times[i] - while(!occupied.isEmpty() && occupied.peek()[0] <= arrival) { - available.push(occupied.pop()[1]) - } - let seat - if(!available.isEmpty()) { - seat = available.pop() - } else { - seat = seatNum - seatNum++ - } - occupied.push([leaving, seat]) - if(arrival === targetArrival) { - res = seat - break - } - } - - return res -} -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - - -/** - * @param {number[][]} times - * @param {number} targetFriend - * @return {number} - */ -var smallestChair = function (times, targetFriend) { - const [targetArrival] = times[targetFriend] - const arrivalQueue = times - const leavingQueue = [...times] - arrivalQueue.sort((a, b) => a[0] - b[0]) - leavingQueue.sort((a, b) => a[1] - b[1] || a[0] - b[0]) - const chairsByLeaveTime = new Map() - let chairsCount = 0 - let arriving = 0, - leaving = 0 - - while (arriving < arrivalQueue.length) { - let chairIdx - const arrival = arrivalQueue[arriving][0] - const leave = leavingQueue[leaving][1] - if (arrival < leave) { - chairIdx = chairsCount++ - } else { - let freeChairIdx = leaving - chairIdx = chairsByLeaveTime.get(leavingQueue[freeChairIdx++][0]) - while (arrival >= leavingQueue[freeChairIdx][1]) { - const nextChair = chairsByLeaveTime.get(leavingQueue[freeChairIdx][0]) - if (chairIdx > nextChair) { - ;[leavingQueue[leaving], leavingQueue[freeChairIdx]] = [ - leavingQueue[freeChairIdx], - leavingQueue[leaving], - ] - chairIdx = nextChair - } - ++freeChairIdx - } - ++leaving - } - if (targetArrival === arrival) { - return chairIdx - } - chairsByLeaveTime.set(arrival, chairIdx) - arriving++ - } -} diff --git a/1942.the-number-of-the-smallest-unoccupied-chair.js b/1942.the-number-of-the-smallest-unoccupied-chair.js new file mode 100644 index 00000000..03b667d7 --- /dev/null +++ b/1942.the-number-of-the-smallest-unoccupied-chair.js @@ -0,0 +1,101 @@ +/** + * @param {number[][]} times + * @param {number} targetFriend + * @return {number} + */ +const smallestChair = function(times, targetFriend) { + const avail = new PQ((a, b) => a[0] < b[0]) + const occupied = new PQ((a, b) => a[1] < b[1]) + const n = times.length + for(let i = 0; i < n; i++) { + avail.push([i, 0]) + } + times.forEach((e, i) => e.push(i)) + times.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]) + + for(let i = 0; i < n; i++) { + let res = -1 + const [s, e, idx] = times[i] + while(!occupied.isEmpty() && occupied.peek()[1] <= s) { + avail.push(occupied.pop()) + } + + const c = avail.pop() + res = c[0] + c[1] = e + occupied.push(c) + + if(idx === targetFriend) { + return res + } + } +}; + +class PQ { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + diff --git a/1943-describe-the-painting.js b/1943-describe-the-painting.js deleted file mode 100644 index 59191bb1..00000000 --- a/1943-describe-the-painting.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @param {number[][]} segments - * @return {number[][]} - */ -const splitPainting = function(segments) { - const hash = {} - for(let [s, e, c] of segments) { - if(hash[s] == null) hash[s] = 0 - if(hash[e] == null) hash[e] = 0 - hash[s] += c - hash[e] -= c - } - const keys = Object.keys(hash) - keys.sort((a, b) => a - b) - let prev, color = 0 - const res = [] - for(let k of keys) { - if(prev != null && color !== 0) res.push([prev,k,color]) - - prev = k - color += hash[k] - } - return res -}; - -// another - -/** - * @param {number[][]} segments - * @return {number[][]} - */ -const splitPainting = function(segments) { - const sum = {} - for(const [s, e, v] of segments) { - if(sum[s] == null) sum[s] = 0 - if(sum[e] == null) sum[e] = 0 - sum[s] += v - sum[e] -= v - } - const keys = Object.keys(sum).map(e => +e) - keys.sort((a, b) => a - b) - const res = [] - let pre = 0, s = 0, n = keys.length - for(let i = 0; i < n; i++) { - const k = keys[i] - - if(s) { - res.push([pre, k, s]) - } - s += sum[k] - pre = k - } - - return res -}; diff --git a/1943.describe-the-painting.js b/1943.describe-the-painting.js new file mode 100644 index 00000000..ba490c82 --- /dev/null +++ b/1943.describe-the-painting.js @@ -0,0 +1,25 @@ +/** + * @param {number[][]} segments + * @return {number[][]} + */ +const splitPainting = function(segments) { + const hash = {} + for(let [s, e, c] of segments) { + if(hash[s] == null) hash[s] = 0 + if(hash[e] == null) hash[e] = 0 + hash[s] += c + hash[e] -= c + } + const keys = Object.keys(hash) + keys.sort((a, b) => a - b) + let prev, color = 0 + const res = [] + for(let k of keys) { + if(prev != null && color !== 0) res.push([prev,k,color]) + + prev = k + color += hash[k] + } + return res +}; + diff --git a/1944-number-of-visible-people-in-a-queue.js b/1944-number-of-visible-people-in-a-queue.js deleted file mode 100644 index d74994b3..00000000 --- a/1944-number-of-visible-people-in-a-queue.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @param {number[]} heights - * @return {number[]} - */ -const canSeePersonsCount = function(heights) { - const res = [] - if(heights.length === 0) return res - - const n = heights.length - const stk = [] - for(let i = n - 1; i >= 0; i--) { - let del = 0 - while(stk.length && heights[i] > heights[stk[stk.length - 1]]) { - stk.pop() - del++ - } - res.push(del + (stk.length ? 1 : 0)) - stk.push(i) - } - - return res.reverse() -}; - -// another - - -/** - * @param {number[]} heights - * @return {number[]} - */ -const canSeePersonsCount = function(heights) { - const ans = new Uint32Array(heights.length); - - const stack = []; - for (let i = heights.length - 1; i >= 0; i--) { - const h = heights[i]; - - let del = 0; - while (stack.length && stack[stack.length - 1] <= h) { - del++; - stack.pop(); - } - - ans[i] = del + (stack.length ? 1 : 0); - stack.push(h); - } - - return ans; -}; - -// another - -/** - * @param {number[]} heights - * @return {number[]} - */ -const canSeePersonsCount = function(heights) { - const stack = [], n = heights.length, res = Array(n) - for(let i = n - 1; i >= 0; i--) { - const h = heights[i] - let del = 0 - while(stack.length && stack[stack.length - 1] <= h) { - stack.pop() - del++ - } - res[i] = stack.length ? del + 1 : del - stack.push(h) - } - - return res -}; diff --git a/1944.number-of-visible-people-in-a-queue.js b/1944.number-of-visible-people-in-a-queue.js new file mode 100644 index 00000000..aba1d34e --- /dev/null +++ b/1944.number-of-visible-people-in-a-queue.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} heights + * @return {number[]} + */ +const canSeePersonsCount = function(heights) { + const res = [] + if(heights.length === 0) return res + + const n = heights.length + const stk = [] + for(let i = n - 1; i >= 0; i--) { + let del = 0 + while(stk.length && heights[i] > heights[stk[stk.length - 1]]) { + stk.pop() + del++ + } + res.push(del + (stk.length ? 1 : 0)) + stk.push(i) + } + + return res.reverse() +}; + diff --git a/1945-sum-of-digits-of-string-after-convert.js b/1945.sum-of-digits-of-string-after-convert.js similarity index 100% rename from 1945-sum-of-digits-of-string-after-convert.js rename to 1945.sum-of-digits-of-string-after-convert.js diff --git a/1946-largest-number-after-mutating-substring.js b/1946.largest-number-after-mutating-substring.js similarity index 100% rename from 1946-largest-number-after-mutating-substring.js rename to 1946.largest-number-after-mutating-substring.js diff --git a/1947-maximum-compatibility-score-sum.js b/1947-maximum-compatibility-score-sum.js deleted file mode 100644 index 7debdc44..00000000 --- a/1947-maximum-compatibility-score-sum.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @param {number[][]} students - * @param {number[][]} mentors - * @return {number} - */ -const maxCompatibilitySum = function(students, mentors) { - const m = students.length, n = students[0].length - const limit = 1 << m - const dp = Array(limit).fill(0) - for(let mask = 1; mask < limit; mask++) { - for(let i = 0; i < m; i++) { - if(mask & (1 << i)) { - dp[mask] = Math.max( - dp[mask], - dp[mask ^ (1 << i)] + calc(bitCnt(mask) - 1, i) - ) - } - } - } - - - return dp[limit - 1] - - function bitCnt(num) { - let res = 0 - while(num) { - num = num & (num - 1) - res++ - } - - return res - } - // student, mentor - function calc(i, j) { - let res = 0 - for(let k = 0; k < n; k++) { - if(students[i][k] === mentors[j][k]) { - res++ - } - } - - return res - } -}; - -// another - -/** - * @param {number[][]} students - * @param {number[][]} mentors - * @return {number} - */ -const maxCompatibilitySum = function(students, mentors) { - const n = students.length, dp = Array(1 << n).fill(-Infinity) - const m = students[0].length - return dfs(0, 0) - - function dfs(i, mask) { - if(i === n) return 0 - if(dp[mask] !== -Infinity) return dp[mask] - for(let j = 0; j < n; j++) { - if((mask & (1 << j)) === 0) { - dp[mask] = Math.max(dp[mask], calc(i, j) + dfs(i + 1, mask | (1 << j))) - } - } - - return dp[mask] - } - - function calc(i, j) { - let res = 0 - const a = students[i], b = mentors[j] - for(let k = 0; k < m; k++) { - if(a[k] === b[k]) res++ - } - return res - } -}; - - -// another - -/** - * @param {number[][]} students - * @param {number[][]} mentors - * @return {number} - */ -const maxCompatibilitySum = function(students, mentors) { - const obj = { res: 0 }, hash = {} - bt(students, mentors, 0, 0, obj, hash) - - return obj.res -}; - -function bt(stu, men, i, score, obj, hash) { - - if(i === stu.length) { - if(score > obj.res) { - obj.res = score - } - return - } - - for(let j = 0; j < men.length; j++) { - const k = `${j}` - if(hash[k] === 1) continue - hash[k] = 1 - bt(stu, men, i + 1, score + calc(stu[i], men[j]), obj, hash) - delete hash[k] - } -} - -function calc(a1, a2) { - const n = a1.length - let res = 0 - for(let i = 0; i < n; i++) { - if(a1[i] === a2[i]) res++ - } - return res -} diff --git a/1947.maximum-compatibility-score-sum.js b/1947.maximum-compatibility-score-sum.js new file mode 100644 index 00000000..4087a1c8 --- /dev/null +++ b/1947.maximum-compatibility-score-sum.js @@ -0,0 +1,45 @@ +/** + * @param {number[][]} students + * @param {number[][]} mentors + * @return {number} + */ +const maxCompatibilitySum = function(students, mentors) { + const m = students.length, n = students[0].length + const limit = 1 << m + const dp = Array(limit).fill(0) + for(let mask = 1; mask < limit; mask++) { + for(let i = 0; i < m; i++) { + if(mask & (1 << i)) { + dp[mask] = Math.max( + dp[mask], + dp[mask ^ (1 << i)] + calc(bitCnt(mask) - 1, i) + ) + } + } + } + + + return dp[limit - 1] + + function bitCnt(num) { + let res = 0 + while(num) { + num = num & (num - 1) + res++ + } + + return res + } + // student, mentor + function calc(i, j) { + let res = 0 + for(let k = 0; k < n; k++) { + if(students[i][k] === mentors[j][k]) { + res++ + } + } + + return res + } +}; + diff --git a/1948-delete-duplicate-folders-in-system.js b/1948.delete-duplicate-folders-in-system.js similarity index 100% rename from 1948-delete-duplicate-folders-in-system.js rename to 1948.delete-duplicate-folders-in-system.js diff --git a/1952-three-divisors.js b/1952.three-divisors.js similarity index 100% rename from 1952-three-divisors.js rename to 1952.three-divisors.js diff --git a/1953-maximum-number-of-weeks-for-which-you-can-work.js b/1953-maximum-number-of-weeks-for-which-you-can-work.js deleted file mode 100644 index c981ef69..00000000 --- a/1953-maximum-number-of-weeks-for-which-you-can-work.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @param {number[]} milestones - * @return {number} - */ -const numberOfWeeks = function(milestones) { - let max = -Infinity - let res = 0, sum = 0 - for(const e of milestones) { - max = Math.max(e, max) - sum += e - } - - return Math.min(sum, (sum - max) * 2 + 1) -}; - - -// another - -/** - * @param {number[]} milestones - * @return {number} - */ -const numberOfWeeks = function(milestones) { - let sum = 0; - for (let i = 0; i < milestones.length; i++) { - sum += milestones[i]; - } - - let cantWork = 0; - for (let i = 0; i < milestones.length; i++) { - cantWork = Math.max(cantWork, milestones[i] - (sum - milestones[i]) - 1); - } - - return sum - cantWork; -}; - -// another - -/** - * @param {number[]} milestones - * @return {number} - */ -const numberOfWeeks = function(milestones) { - const max = Math.max(...milestones) - let sum = 0 - for(let i = 0; i < milestones.length; i++) { - sum += milestones[i] - } - const res = sum - max - - return Math.min(sum, res * 2 + 1) -}; diff --git a/1953.maximum-number-of-weeks-for-which-you-can-work.js b/1953.maximum-number-of-weeks-for-which-you-can-work.js new file mode 100644 index 00000000..7b75aba9 --- /dev/null +++ b/1953.maximum-number-of-weeks-for-which-you-can-work.js @@ -0,0 +1,16 @@ +/** + * @param {number[]} milestones + * @return {number} + */ +const numberOfWeeks = function(milestones) { + let max = -Infinity + let res = 0, sum = 0 + for(const e of milestones) { + max = Math.max(e, max) + sum += e + } + + return Math.min(sum, (sum - max) * 2 + 1) +}; + + diff --git a/1954-minimum-garden-perimeter-to-collect-enough-apples.js b/1954.minimum-garden-perimeter-to-collect-enough-apples.js similarity index 100% rename from 1954-minimum-garden-perimeter-to-collect-enough-apples.js rename to 1954.minimum-garden-perimeter-to-collect-enough-apples.js diff --git a/1955-count-number-of-special-subsequences.js b/1955-count-number-of-special-subsequences.js deleted file mode 100644 index 8467f496..00000000 --- a/1955-count-number-of-special-subsequences.js +++ /dev/null @@ -1,58 +0,0 @@ -/* - * @lc app=leetcode id=1955 lang=javascript - * - * [1955] Count Number of Special Subsequences - */ - -// @lc code=start -/** - * @param {number[]} nums - * @return {number} - */ -const countSpecialSubsequences = function (nums) { - const dp = Array(3).fill(0), - mod = 10 ** 9 + 7 - for (let e of nums) { - dp[e] = (((dp[e] + dp[e]) % mod) + (e > 0 ? dp[e - 1] : 1)) % mod - } - return dp[2] -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const countSpecialSubsequences = function(nums) { - const mod = 10 ** 9 + 7 - const dp = Array.from({length: 10 **5 + 1}, () => Array(4).fill(-1)) - let n = nums.length, a = nums - return f(0, 0) - function f(index, firstMandatory) { - if (index == n && firstMandatory == 3) { - return 1; - } - if (index == n) { - return 0; - } - if (dp[index][firstMandatory] >= 0) { - return dp[index][firstMandatory]; - } - let result = 0; - if (a[index] == firstMandatory) { - result = (result + - f(index + 1, firstMandatory) + - f(index + 1, firstMandatory + 1) - ) % mod; - } - result = (result + f(index + 1, firstMandatory)) % mod; - - return dp[index][firstMandatory] = result; - } -}; - - - - - diff --git a/1955.count-number-of-special-subsequences.js b/1955.count-number-of-special-subsequences.js new file mode 100644 index 00000000..4fe2c251 --- /dev/null +++ b/1955.count-number-of-special-subsequences.js @@ -0,0 +1,20 @@ +/* + * @lc app=leetcode id=1955 lang=javascript + * + * [1955] Count Number of Special Subsequences + */ + +// @lc code=start +/** + * @param {number[]} nums + * @return {number} + */ +const countSpecialSubsequences = function (nums) { + const dp = Array(3).fill(0), + mod = 10 ** 9 + 7 + for (let e of nums) { + dp[e] = (((dp[e] + dp[e]) % mod) + (e > 0 ? dp[e - 1] : 1)) % mod + } + return dp[2] +} + diff --git a/1959-minimum-total-space-wasted-with-k-resizing-operations.js b/1959.minimum-total-space-wasted-with-k-resizing-operations.js similarity index 100% rename from 1959-minimum-total-space-wasted-with-k-resizing-operations.js rename to 1959.minimum-total-space-wasted-with-k-resizing-operations.js diff --git a/1960-maximum-product-of-the-length-of-two-palindromic-substrings.js b/1960.maximum-product-of-the-length-of-two-palindromic-substrings.js similarity index 100% rename from 1960-maximum-product-of-the-length-of-two-palindromic-substrings.js rename to 1960.maximum-product-of-the-length-of-two-palindromic-substrings.js diff --git a/1961-check-if-string-is-a-prefix-of-array.js b/1961.check-if-string-is-a-prefix-of-array.js similarity index 100% rename from 1961-check-if-string-is-a-prefix-of-array.js rename to 1961.check-if-string-is-a-prefix-of-array.js diff --git a/1962-remove-stones-to-minimize-the-total.js b/1962.remove-stones-to-minimize-the-total.js similarity index 100% rename from 1962-remove-stones-to-minimize-the-total.js rename to 1962.remove-stones-to-minimize-the-total.js diff --git a/1963-minimum-number-of-swaps-to-make-the-string-balanced.js b/1963-minimum-number-of-swaps-to-make-the-string-balanced.js deleted file mode 100644 index 90a3793d..00000000 --- a/1963-minimum-number-of-swaps-to-make-the-string-balanced.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const minSwaps = function(s) { - const stk = [] - for (let e of s) { - if(e === '[') stk.push(e) - else { - if(stk.length) { - stk.pop() - } else stk.push(e) - } - } - return Math.ceil(stk.length / 2) -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const minSwaps = function(s) { - const stack = [] - let num = 0 - for(let e of s) { - if(e === '[') { - stack.push(e) - num++ - } - if(e === ']') { - if(stack[stack.length - 1] === '[') { - stack.pop() - num-- - } - } - } - // console.log(num) - return Math.ceil(num / 2) -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const minSwaps = function(s) { - let num = 0 - for(let e of s) { - if(e === '[') { - num++ - } - if(e === ']') { - if(num > 0) { - num-- - } - } - } - return Math.ceil(num / 2) -}; diff --git a/1963.minimum-number-of-swaps-to-make-the-string-balanced.js b/1963.minimum-number-of-swaps-to-make-the-string-balanced.js new file mode 100644 index 00000000..3ae28d84 --- /dev/null +++ b/1963.minimum-number-of-swaps-to-make-the-string-balanced.js @@ -0,0 +1,17 @@ +/** + * @param {string} s + * @return {number} + */ +const minSwaps = function(s) { + const stk = [] + for (let e of s) { + if(e === '[') stk.push(e) + else { + if(stk.length) { + stk.pop() + } else stk.push(e) + } + } + return Math.ceil(stk.length / 2) +}; + diff --git a/1964-find-the-longest-valid-obstacle-course-at-each-position.js b/1964-find-the-longest-valid-obstacle-course-at-each-position.js deleted file mode 100644 index 878844f2..00000000 --- a/1964-find-the-longest-valid-obstacle-course-at-each-position.js +++ /dev/null @@ -1,111 +0,0 @@ -/** - * @param {number[]} obstacles - * @return {number[]} - */ -const longestObstacleCourseAtEachPosition = function(obstacles) { - const n = obstacles.length, res = [], stk = [] - for (let i = 0; i < n; i++) { - const cur = obstacles[i] - let idx = chk(cur) - if (idx === stk.length) { - stk.push(cur) - } else { - stk[idx] = cur - } - res.push(++idx) - } - - return res - - function chk(val) { - let l = 0, r = stk.length - while(l < r) { - const mid = ~~((l + r) / 2) - if(stk[mid] <= val) l = mid + 1 - else r = mid - } - return l - } -}; - -// another - -/** - * @param {number[]} obstacles - * @return {number[]} - */ -const longestObstacleCourseAtEachPosition = function(obstacles) { - const n = obstacles.length - const stack = [], res = [] - let len = 0 - - for(let i = 0; i < n; i++) { - const cur = obstacles[i] - const idx = chk(cur) - if(idx === len) { - stack.push(cur) - len++ - res.push(len) - }else { - stack[idx] = cur - res.push(idx + 1) - } - } - - return res - - function chk(x) { - if(len && stack[len - 1] <= x) return len - let l = 0, r = len - 1 - while(l < r) { - const mid = ~~((l + r) / 2) - if(stack[mid] <= x) { - l = mid + 1 - } else { - r = mid - } - } - return l - } -}; - - - - -// another - -/** - * @param {number[]} obstacles - * @return {number[]} - */ -const longestObstacleCourseAtEachPosition = function(obstacles) { - const n = obstacles.length - const stack = [], res = Array(n).fill(0) - let m = 0 - let j = 0; - for (let x of obstacles) { - let i = chk(x); - if (i == m) { - ++m; - stack.push(x); - } else { - stack[i] = x; - } - res[j++] = i + 1; - } - return res; - function chk(x) { - if (m && stack[m - 1] <= x) return m; - let l = 0, r = m - 1; - while (l < r) { - let m = (l + r) >> 1; - if (stack[m] > x) { - r = m; - } else { - l = m + 1; - } - } - return l; - } -}; - diff --git a/1964.find-the-longest-valid-obstacle-course-at-each-position.js b/1964.find-the-longest-valid-obstacle-course-at-each-position.js new file mode 100644 index 00000000..2f97162a --- /dev/null +++ b/1964.find-the-longest-valid-obstacle-course-at-each-position.js @@ -0,0 +1,30 @@ +/** + * @param {number[]} obstacles + * @return {number[]} + */ +const longestObstacleCourseAtEachPosition = function(obstacles) { + const n = obstacles.length, res = [], stk = [] + for (let i = 0; i < n; i++) { + const cur = obstacles[i] + let idx = chk(cur) + if (idx === stk.length) { + stk.push(cur) + } else { + stk[idx] = cur + } + res.push(++idx) + } + + return res + + function chk(val) { + let l = 0, r = stk.length + while(l < r) { + const mid = ~~((l + r) / 2) + if(stk[mid] <= val) l = mid + 1 + else r = mid + } + return l + } +}; + diff --git a/1969-minimum-non-zero-product-of-the-array-elements.js b/1969-minimum-non-zero-product-of-the-array-elements.js deleted file mode 100644 index 2b29dade..00000000 --- a/1969-minimum-non-zero-product-of-the-array-elements.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @param {number} p - * @return {number} - */ -const minNonZeroProduct = function (p) { - const MOD = BigInt(10 ** 9 + 7), bp = BigInt(p) - const bpm = BigInt(1n << bp) - 1n, base = BigInt(1n << bp) - 2n, pow = BigInt(1n << (bp - 1n)) - 1n - return Number((bpm % MOD) * fastPow(base, pow, MOD) % MOD) - -} - -function fastPow(base, power, mod) { - if(power === 0n) return 1n - base %= mod - let res = fastPow(base, power / 2n, mod) - res = (res * res) % mod - if(power & 1n) res = (res * base) % mod - return res -} - - -// another - - -/** - * @param {number} p - * @return {number} - */ -const minNonZeroProduct = function (p) { - const b = BigInt(p) - const mod = BigInt(10 ** 9 + 7) - - return ( - (((BigInt(1n << b) - 1n) % mod) * - pow(BigInt(1n << b) - 2n, BigInt(1n << (b - 1n)) - 1n)) % - mod - ) - - function pow(a, n) { - let r = 1n - a %= mod - while (n > 0n) { - r = (r * a) % mod - a = (a * a) % mod - n /= 2n - } - return r - } -} diff --git a/1969.minimum-non-zero-product-of-the-array-elements.js b/1969.minimum-non-zero-product-of-the-array-elements.js new file mode 100644 index 00000000..fc100257 --- /dev/null +++ b/1969.minimum-non-zero-product-of-the-array-elements.js @@ -0,0 +1,21 @@ +/** + * @param {number} p + * @return {number} + */ +const minNonZeroProduct = function (p) { + const MOD = BigInt(10 ** 9 + 7), bp = BigInt(p) + const bpm = BigInt(1n << bp) - 1n, base = BigInt(1n << bp) - 2n, pow = BigInt(1n << (bp - 1n)) - 1n + return Number((bpm % MOD) * fastPow(base, pow, MOD) % MOD) + +} + +function fastPow(base, power, mod) { + if(power === 0n) return 1n + base %= mod + let res = fastPow(base, power / 2n, mod) + res = (res * res) % mod + if(power & 1n) res = (res * base) % mod + return res +} + + diff --git a/1970-last-day-where-you-can-still-cross.js b/1970.last-day-where-you-can-still-cross.js similarity index 100% rename from 1970-last-day-where-you-can-still-cross.js rename to 1970.last-day-where-you-can-still-cross.js diff --git a/1971-find-if-path-exists-in-graph.js b/1971.find-if-path-exists-in-graph.js similarity index 100% rename from 1971-find-if-path-exists-in-graph.js rename to 1971.find-if-path-exists-in-graph.js diff --git a/1976-number-of-ways-to-arrive-at-destination.js b/1976-number-of-ways-to-arrive-at-destination.js deleted file mode 100644 index 11572bdd..00000000 --- a/1976-number-of-ways-to-arrive-at-destination.js +++ /dev/null @@ -1,222 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} roads - * @return {number} - */ -const countPaths = function(n, roads) { - const graph = {} - for(let r of roads) { - const [u, v, t] = r - if(graph[u] == null) graph[u] = [] - if(graph[v] == null) graph[v] = [] - graph[u].push([v, t]) - graph[v].push([u, t]) - } - - return dijkstra(graph, n, 0) - - function dijkstra(graph, n, src) { - const dist = Array(n).fill(Infinity) - const ways = Array(n).fill(0), mod = 1e9 + 7 - ways[src] = 1 - dist[src] = 0 - const pq = new PriorityQueue((a, b) => a[0] === b[0] ? a[1] < b[1] : a[0] < b[0]) - pq.push([0, 0]) - while(!pq.isEmpty()) { - const [d, u] = pq.pop() - if(d > dist[u]) continue - if(graph[u] == null) graph[u] = [] - for(const [v, time] of graph[u]) { - if(dist[v] > d + time) { - ways[v] = ways[u] - dist[v] = d + time - pq.push([dist[v], v]) - } else if(dist[v] === d + time) { - ways[v] = (ways[v] + ways[u]) % mod - } - } - } - return ways[n - 1] - } - -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -/** - * @param {number} n - * @param {number[][]} roads - * @return {number} - */ -const countPaths = function(n, roads) { - const graph = {}, MOD = 1e9 + 7 - for(const [u, v, t] of roads) { - if(graph[u] == null) graph[u] = {} - if(graph[v] == null) graph[v] = {} - graph[u][v] = t - graph[v][u] = t - } - - return dijkstra(graph, n, 0) - - function dijkstra(graph, n, src) { - const dist = Array(n).fill(Infinity) - const ways = Array(n).fill(0) - ways[src] = 1 - dist[src] = 0 - const pq = new PriorityQueue((a, b) => a[0] < b[0]) - pq.push([0, 0]) - while(!pq.isEmpty()) { - const [d, u] = pq.pop() - if(d > dist[u]) continue - for(const next of Object.keys(graph[u] || {})) { - const val = graph[u][next] - if(dist[next] > d + val) { - dist[next] = d + val - ways[next] = ways[u] - pq.push([dist[next], next]) - } else if(dist[next] === d + val) { - ways[next] = (ways[next] + ways[u]) % MOD - } - } - } - - return ways[n - 1] - } -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/1976.number-of-ways-to-arrive-at-destination.js b/1976.number-of-ways-to-arrive-at-destination.js new file mode 100644 index 00000000..b6015baa --- /dev/null +++ b/1976.number-of-ways-to-arrive-at-destination.js @@ -0,0 +1,111 @@ +/** + * @param {number} n + * @param {number[][]} roads + * @return {number} + */ +const countPaths = function(n, roads) { + const graph = {} + for(let r of roads) { + const [u, v, t] = r + if(graph[u] == null) graph[u] = [] + if(graph[v] == null) graph[v] = [] + graph[u].push([v, t]) + graph[v].push([u, t]) + } + + return dijkstra(graph, n, 0) + + function dijkstra(graph, n, src) { + const dist = Array(n).fill(Infinity) + const ways = Array(n).fill(0), mod = 1e9 + 7 + ways[src] = 1 + dist[src] = 0 + const pq = new PriorityQueue((a, b) => a[0] === b[0] ? a[1] < b[1] : a[0] < b[0]) + pq.push([0, 0]) + while(!pq.isEmpty()) { + const [d, u] = pq.pop() + if(d > dist[u]) continue + if(graph[u] == null) graph[u] = [] + for(const [v, time] of graph[u]) { + if(dist[v] > d + time) { + ways[v] = ways[u] + dist[v] = d + time + pq.push([dist[v], v]) + } else if(dist[v] === d + time) { + ways[v] = (ways[v] + ways[u]) % mod + } + } + } + return ways[n - 1] + } + +}; + +class PriorityQueue { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + diff --git a/1977-number-of-ways-to-separate-numbers.js b/1977.number-of-ways-to-separate-numbers.js similarity index 100% rename from 1977-number-of-ways-to-separate-numbers.js rename to 1977.number-of-ways-to-separate-numbers.js diff --git a/1979-find-greatest-common-divisor-of-array.js b/1979.find-greatest-common-divisor-of-array.js similarity index 100% rename from 1979-find-greatest-common-divisor-of-array.js rename to 1979.find-greatest-common-divisor-of-array.js diff --git a/198-house-robber.js b/198-house-robber.js deleted file mode 100644 index 3ce91fff..00000000 --- a/198-house-robber.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -function rob(nums) { - if (nums.length == 0) return 0; - let prev1 = 0; - let prev2 = 0; - for (let num of nums) { - let tmp = prev1; - prev1 = Math.max(prev2 + num, prev1); - prev2 = tmp; - } - return prev1; -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const rob = function(nums) { - const n = nums.length - const dp = Array(n+1).fill(0) - dp[1] = nums[0] - - for(let i = 1; i < n; i++) { - dp[i + 1] = Math.max(dp[i], dp[i - 1] + nums[i]) - } - - return dp[n] -}; diff --git a/198.house-robber.js b/198.house-robber.js new file mode 100644 index 00000000..feb83e36 --- /dev/null +++ b/198.house-robber.js @@ -0,0 +1,16 @@ +/** + * @param {number[]} nums + * @return {number} + */ +function rob(nums) { + if (nums.length == 0) return 0; + let prev1 = 0; + let prev2 = 0; + for (let num of nums) { + let tmp = prev1; + prev1 = Math.max(prev2 + num, prev1); + prev2 = tmp; + } + return prev1; +} + diff --git a/1980-find-unique-binary-string.js b/1980.find-unique-binary-string.js similarity index 100% rename from 1980-find-unique-binary-string.js rename to 1980.find-unique-binary-string.js diff --git a/1981-minimize-the-difference-between-target-and-chosen-elements.js b/1981-minimize-the-difference-between-target-and-chosen-elements.js deleted file mode 100644 index f66a42de..00000000 --- a/1981-minimize-the-difference-between-target-and-chosen-elements.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @param {number[][]} mat - * @param {number} target - * @return {number} - */ -const minimizeTheDifference = function(mat, target) { - const m = mat.length, n = mat[0].length - const dp = Array.from({length: m}, () => Array(70*70).fill(-1)) - return fn(0, 0) - - function fn(row, sum) { - if(row === m) return Math.abs(target - sum) - if(dp[row][sum] !== -1) return dp[row][sum] - let res = Number.MAX_SAFE_INTEGER - for(let j = 0; j < n; j++) { - res = Math.min(res, fn(row + 1, sum + mat[row][j])) - } - return dp[row][sum] = res - } -}; - -// another - -/** - * @param {number[][]} mat - * @param {number} target - * @return {number} - */ -const minimizeTheDifference = function(mat, target) { - const m = mat.length, n = mat[0].length - const memo = Array.from({ length: m }, () => Array()) - return dfs(0, 0) - - function dfs(row, sum) { - if(row === m) return Math.abs(target - sum) - if(memo[row][sum] != null) return memo[row][sum] - let res = Number.MAX_SAFE_INTEGER - for(let i = 0; i < n; i++) { - res = Math.min(res, dfs(row + 1, sum + mat[row][i])) - } - - return memo[row][sum] = res - } -}; - - - diff --git a/1981.minimize-the-difference-between-target-and-chosen-elements.js b/1981.minimize-the-difference-between-target-and-chosen-elements.js new file mode 100644 index 00000000..df41deae --- /dev/null +++ b/1981.minimize-the-difference-between-target-and-chosen-elements.js @@ -0,0 +1,21 @@ +/** + * @param {number[][]} mat + * @param {number} target + * @return {number} + */ +const minimizeTheDifference = function(mat, target) { + const m = mat.length, n = mat[0].length + const dp = Array.from({length: m}, () => Array(70*70).fill(-1)) + return fn(0, 0) + + function fn(row, sum) { + if(row === m) return Math.abs(target - sum) + if(dp[row][sum] !== -1) return dp[row][sum] + let res = Number.MAX_SAFE_INTEGER + for(let j = 0; j < n; j++) { + res = Math.min(res, fn(row + 1, sum + mat[row][j])) + } + return dp[row][sum] = res + } +}; + diff --git a/1982-find-array-given-subset-sums.js b/1982-find-array-given-subset-sums.js deleted file mode 100644 index ca16e18a..00000000 --- a/1982-find-array-given-subset-sums.js +++ /dev/null @@ -1,134 +0,0 @@ -/** - * @param {number} n - * @param {number[]} sums - * @return {number[]} - */ -const recoverArray = function(n, sums) { - const res = [] - sums.sort((a, b) => a - b) - while(res.length < n) { - const used = Array(sums.length).fill(false) - const v0 = [], v1 = [] - let d = sums[1] - sums[0] - for(let i = 0, j = 1; ;i++, j++) { - while(i < sums.length && used[i]) i++ - if(i === sums.length) break - while(j <= i || sums[j] !== sums[i] + d) j++ - v0.push(sums[i]) - v1.push(sums[j]) - used[i] = used[j] = true - } - - if(bs(v0, 0)) { - res.push(d) - sums = v0 - }else { - res.push(-d) - sums = v1 - } - } - return res -}; - - -function bs(arr, e) { - let l = 0, r = arr.length - 1 - while(l < r) { - const mid = ~~((l + r) / 2) - if(arr[mid] < e) l = mid + 1 - else r = mid - } - - return arr[l] === e -} - -// another - -/** - * @param {number} n - * @param {number[]} sums - * @return {number[]} - */ -const recoverArray = function(n, sums) { - const res = [] - sums.sort((a, b) => a - b) - - while(res.length < n) { - const visited = Array(sums.length).fill(false) - const a1 = [], a2 = [] - const d = sums[1] - sums[0] - for(let i = 0, j = 1; i < sums.length; i++, j++) { - while(i < sums.length && visited[i]) i++ - if(i === sums.length) break - while(j <= i || sums[j] !== sums[i] + d) j++ - a1.push(sums[i]) - a2.push(sums[j]) - visited[i] = visited[j] = true - } - - if(bs(a1, 0)) { - sums = a1 - res.push(d) - } else { - sums = a2 - res.push(-d) - } - } - - return res -}; - -function bs(arr, val) { - let l = 0, r = arr.length - 1 - while(l < r) { - const mid = ~~((l + r) / 2) - if(arr[mid] < val) l = mid + 1 - else r = mid - } - - return arr[l] === val -} - -// another - -/** - * @param {number} n - * @param {number[]} sums - * @return {number[]} - */ -const recoverArray = function(n, sums) { - const res = [] - sums.sort((a, b) => a - b) - - while(res.length < n) { - const m = sums.length, visited = Array(m).fill(false) - let a1 = [], a2 = [], delta = sums[1] - sums[0] - for(let i = 0, j = 1; i < m && j < m; i++, j++) { - while(i < m && visited[i]) i++ - if(i === m) break - while(i >= j || sums[j] !== sums[i] + delta) j++ - if(j === m) break - a1.push(sums[i]) - a2.push(sums[j]) - visited[i] = visited[j] = true - } - if(binarySearch(a1, 0)) { - sums = a1 - res.push(delta) - } else { - sums = a2 - res.push(-delta) - } - } - return res - - function binarySearch(arr, val) { - let l = 0, r = arr.length - 1 - while(l < r) { - const mid = ~~((l + r) / 2) - if(arr[mid] < val) l = mid + 1 - else r = mid - } - return arr[l] === val - } -}; diff --git a/1982.find-array-given-subset-sums.js b/1982.find-array-given-subset-sums.js new file mode 100644 index 00000000..e21bfbdc --- /dev/null +++ b/1982.find-array-given-subset-sums.js @@ -0,0 +1,44 @@ +/** + * @param {number} n + * @param {number[]} sums + * @return {number[]} + */ +const recoverArray = function(n, sums) { + const res = [] + sums.sort((a, b) => a - b) + while(res.length < n) { + const used = Array(sums.length).fill(false) + const v0 = [], v1 = [] + let d = sums[1] - sums[0] + for(let i = 0, j = 1; ;i++, j++) { + while(i < sums.length && used[i]) i++ + if(i === sums.length) break + while(j <= i || sums[j] !== sums[i] + d) j++ + v0.push(sums[i]) + v1.push(sums[j]) + used[i] = used[j] = true + } + + if(bs(v0, 0)) { + res.push(d) + sums = v0 + }else { + res.push(-d) + sums = v1 + } + } + return res +}; + + +function bs(arr, e) { + let l = 0, r = arr.length - 1 + while(l < r) { + const mid = ~~((l + r) / 2) + if(arr[mid] < e) l = mid + 1 + else r = mid + } + + return arr[l] === e +} + diff --git a/1983-widest-pair-of-indices-with-equal-range-sum.js b/1983.widest-pair-of-indices-with-equal-range-sum.js similarity index 100% rename from 1983-widest-pair-of-indices-with-equal-range-sum.js rename to 1983.widest-pair-of-indices-with-equal-range-sum.js diff --git a/1984-minimum-difference-between-highest-and-lowest-of-k-scores.js b/1984.minimum-difference-between-highest-and-lowest-of-k-scores.js similarity index 100% rename from 1984-minimum-difference-between-highest-and-lowest-of-k-scores.js rename to 1984.minimum-difference-between-highest-and-lowest-of-k-scores.js diff --git a/1985-find-the-kth-largest-integer-in-the-array.js b/1985.find-the-kth-largest-integer-in-the-array.js similarity index 100% rename from 1985-find-the-kth-largest-integer-in-the-array.js rename to 1985.find-the-kth-largest-integer-in-the-array.js diff --git a/1986-minimum-number-of-work-sessions-to-finish-the-tasks.js b/1986-minimum-number-of-work-sessions-to-finish-the-tasks.js deleted file mode 100644 index a3237bb6..00000000 --- a/1986-minimum-number-of-work-sessions-to-finish-the-tasks.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @param {number[]} tasks - * @param {number} sessionTime - * @return {number} - */ -const minSessions = function(tasks, sessionTime) { - const n = tasks.length - const limit = 1 << n - - const dp = Array(limit).fill(Infinity) - dp[0] = 0 - for(let mask = 1; mask < limit; mask++) { - for(let sub = mask; sub; sub = (sub - 1) & mask) { - if(valid(sub)) { - dp[mask] = Math.min(dp[mask], dp[mask - sub] + 1) - } - } - } - - return dp[limit - 1] - - function valid(sub) { - let sum = 0 - for(let i = 0; i < 14; i++) { - if((sub >> i) & 1) sum += tasks[i] - } - - return sum <= sessionTime - } -}; - -// another - -/** - * @param {number[]} tasks - * @param {number} sessionTime - * @return {number} - */ -const minSessions = function(tasks, sessionTime) { - const n = tasks.length - const dp = Array.from({ length: 1 << 14 }, () => Array(16).fill(-1)) - return fn(0, 0) - - function fn(mask, consumed) { - if (mask === (1 << n) - 1) { - return consumed === 0 ? 0 : 1 - } - if (dp[mask][consumed] !== -1) { - return dp[mask][consumed]; - } - - let result = Number.MAX_VALUE; - if (consumed > 0) { - result = Math.min(result, 1 + fn(mask, 0)); - } - for (let i = 0; i < n; i++) { - if ((mask & (1 << i)) === 0 && consumed + tasks[i] <= sessionTime) { - result = Math.min(result, fn(mask | (1 << i), consumed + tasks[i])); - } - } - return dp[mask][consumed] = result; - } -}; - -// another - -/** - * @param {number[]} tasks - * @param {number} sessionTime - * @return {number} - */ -function minSessions(tasks, sessionTime) { - const n = tasks.length - const memo = Array.from({ length: 1 << n }, () => Array(15)) - return helper((1 << n) - 1, 0) - - function helper(mask, remain) { - if(mask === 0) return 0 - if(memo[mask][remain] != null) return memo[mask][remain] - let res = n - - for(let i = 0; i < n; i++) { - if((1 << i) & mask) { - const newMask = mask & (~(1 << i)) - if(tasks[i] <= remain) { - res = Math.min(res, helper(newMask, remain - tasks[i])) - } else { - res = Math.min(res, helper(newMask, sessionTime - tasks[i]) + 1) - } - } - } - - return memo[mask][remain] = res - } -} diff --git a/1986.minimum-number-of-work-sessions-to-finish-the-tasks.js b/1986.minimum-number-of-work-sessions-to-finish-the-tasks.js new file mode 100644 index 00000000..1b9af932 --- /dev/null +++ b/1986.minimum-number-of-work-sessions-to-finish-the-tasks.js @@ -0,0 +1,31 @@ +/** + * @param {number[]} tasks + * @param {number} sessionTime + * @return {number} + */ +const minSessions = function(tasks, sessionTime) { + const n = tasks.length + const limit = 1 << n + + const dp = Array(limit).fill(Infinity) + dp[0] = 0 + for(let mask = 1; mask < limit; mask++) { + for(let sub = mask; sub; sub = (sub - 1) & mask) { + if(valid(sub)) { + dp[mask] = Math.min(dp[mask], dp[mask - sub] + 1) + } + } + } + + return dp[limit - 1] + + function valid(sub) { + let sum = 0 + for(let i = 0; i < 14; i++) { + if((sub >> i) & 1) sum += tasks[i] + } + + return sum <= sessionTime + } +}; + diff --git a/1987-number-of-unique-good-subsequences.js b/1987-number-of-unique-good-subsequences.js deleted file mode 100644 index 9cc21f0f..00000000 --- a/1987-number-of-unique-good-subsequences.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @param {string} binary - * @return {number} - */ -const numberOfUniqueGoodSubsequences = function (binary) { - const n = binary.length, - P = 1e9 + 7 - let first1Position = -1, - first0Position = -1 - for (let i = 0; i < binary.length; i++) { - if (binary[i] === '0' && first0Position == -1) { - first0Position = i - } - if (binary[i] === '1' && first1Position == -1) { - first1Position = i - } - if(first0Position !== -1 && first1Position !== -1) break - } - if (first1Position === -1) return 1 - if (first0Position === -1) return n - - const next0 = new Array(n).fill(0) - const next1 = new Array(n).fill(0) - let nextZero = -1, - nextOne = -1 - for (let i = binary.length - 1; i >= 0; i--) { - next0[i] = nextZero - next1[i] = nextOne - if (binary[i] === '0') { - nextZero = i - } else { - nextOne = i - } - } - const dp = new Array(n).fill(-1) - return (1 + fn(first1Position)) % P - - function fn(index) { - if (index == n) return 0 - if (dp[index] !== -1) return dp[index] - let result = 1 - if (next0[index] >= 0) { - result += fn(next0[index]) - result %= P - } - if (next1[index] >= 0) { - result += fn(next1[index]) - result %= P - } - return (dp[index] = result) - } -} - -// another - -/** - * @param {string} binary - * @return {number} - */ -const numberOfUniqueGoodSubsequences = function (binary) { - const n = binary.length, - mod = 1e9 + 7 - let hasZero = 0, ends1 = 0, ends0 = 0 - for(let ch of binary) { - if(ch === '1') { - ends1 = (ends1 + ends0 + 1) % mod - } else { - ends0 = (ends1 + ends0) % mod - hasZero = 1 - } - } - return (ends1 + ends0 + hasZero) % mod -} - diff --git a/1987.number-of-unique-good-subsequences.js b/1987.number-of-unique-good-subsequences.js new file mode 100644 index 00000000..af810de9 --- /dev/null +++ b/1987.number-of-unique-good-subsequences.js @@ -0,0 +1,53 @@ +/** + * @param {string} binary + * @return {number} + */ +const numberOfUniqueGoodSubsequences = function (binary) { + const n = binary.length, + P = 1e9 + 7 + let first1Position = -1, + first0Position = -1 + for (let i = 0; i < binary.length; i++) { + if (binary[i] === '0' && first0Position == -1) { + first0Position = i + } + if (binary[i] === '1' && first1Position == -1) { + first1Position = i + } + if(first0Position !== -1 && first1Position !== -1) break + } + if (first1Position === -1) return 1 + if (first0Position === -1) return n + + const next0 = new Array(n).fill(0) + const next1 = new Array(n).fill(0) + let nextZero = -1, + nextOne = -1 + for (let i = binary.length - 1; i >= 0; i--) { + next0[i] = nextZero + next1[i] = nextOne + if (binary[i] === '0') { + nextZero = i + } else { + nextOne = i + } + } + const dp = new Array(n).fill(-1) + return (1 + fn(first1Position)) % P + + function fn(index) { + if (index == n) return 0 + if (dp[index] !== -1) return dp[index] + let result = 1 + if (next0[index] >= 0) { + result += fn(next0[index]) + result %= P + } + if (next1[index] >= 0) { + result += fn(next1[index]) + result %= P + } + return (dp[index] = result) + } +} + diff --git a/199-binary-tree-right-side-view.js b/199-binary-tree-right-side-view.js deleted file mode 100644 index 7bbf5a42..00000000 --- a/199-binary-tree-right-side-view.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number[]} - */ -const rightSideView = function(root) { - if(root == null) return [] - const queue = [root] - const res = [] - while(queue.length) { - const len = queue.length - for(let i = 0; i < len; i++) { - const el = queue.shift() - if(i === len - 1) res.push(el.val) - if(el.left) queue.push(el.left) - if(el.right) queue.push(el.right) - } - } - return res -}; - -// another - -const rightSideView = function(root) { - const res = [] - const helper = function(node, level) { - if (!node) { - return - } - if (!res[level]) { - res.push(node.val) - } - helper(node.right, level + 1) - helper(node.left, level + 1) - } - helper(root, 0) - return res -} diff --git a/199.binary-tree-right-side-view.js b/199.binary-tree-right-side-view.js new file mode 100644 index 00000000..c9c3e719 --- /dev/null +++ b/199.binary-tree-right-side-view.js @@ -0,0 +1,27 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[]} + */ +const rightSideView = function(root) { + if(root == null) return [] + const queue = [root] + const res = [] + while(queue.length) { + const len = queue.length + for(let i = 0; i < len; i++) { + const el = queue.shift() + if(i === len - 1) res.push(el.val) + if(el.left) queue.push(el.left) + if(el.right) queue.push(el.right) + } + } + return res +}; + diff --git a/1991-find-the-middle-index-in-array.js b/1991.find-the-middle-index-in-array.js similarity index 100% rename from 1991-find-the-middle-index-in-array.js rename to 1991.find-the-middle-index-in-array.js diff --git a/1994-the-number-of-good-subsets.js b/1994.the-number-of-good-subsets.js similarity index 100% rename from 1994-the-number-of-good-subsets.js rename to 1994.the-number-of-good-subsets.js diff --git a/1995-count-special-quadruplets.js b/1995.count-special-quadruplets.js similarity index 100% rename from 1995-count-special-quadruplets.js rename to 1995.count-special-quadruplets.js diff --git a/1996-the-number-of-weak-characters-in-the-game.js b/1996-the-number-of-weak-characters-in-the-game.js deleted file mode 100644 index 383d457e..00000000 --- a/1996-the-number-of-weak-characters-in-the-game.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @param {number[][]} properties - * @return {number} - */ -const numberOfWeakCharacters = function(properties) { - const props = properties, n = props.length, maxDefFromRight = Array(n) - props.sort((a, b) => a[0] - b[0]) - for(let max = 0, i = n - 1; i >= 0; i--) { - max = Math.max(max, props[i][1]) - maxDefFromRight[i] = max - } - let res = 0 - - for(let i = 0; i < n; i++) { - const cur = props[i] - let l = i, r = n - while(l < r) { - const mid = l + Math.floor((r - l) / 2) - if(props[mid][0] > props[i][0]) r = mid - else l = mid + 1 - } - - if(l < n && maxDefFromRight[l] > props[i][1]) { - res++ - } - } - - return res -}; - -// another - -/** - * @param {number[][]} properties - * @return {number} - */ -const numberOfWeakCharacters = function(properties) { - properties.sort((a, b) => a[0] - b[0] || b[1] - a[1]) - let stack = [], res = 0 - - for(let i = 0, n = properties.length; i < n; i++) { - while(stack.length && stack[stack.length - 1] < properties[i][1]) { - stack.pop() - res++ - } - stack.push(properties[i][1]) - } - - return res -}; - -// another - -/** - * @param {number[][]} properties - * @return {number} - */ -const numberOfWeakCharacters = function(properties) { - if (properties == null || properties.length == 0) { - return 0; - } - properties.sort((o1, o2) => { - if (o1[0] == o2[0]) { - return o1[1] - o2[1]; - } - return o1[0] - o2[0]; - }); - const { max } = Math - let mmax = Array(1e5 + 10).fill( 0); - let ans = 0; - let n = properties.length; - for (let i = n - 1; i >= 0; i--) mmax[properties[i][0]] = max(properties[i][1], mmax[properties[i][0]]); - for (let i = 1e5; i >= 1; i--) mmax[i] = max(mmax[i], mmax[i + 1]); - for (let i = 0; i < n; i++) { - if (mmax[properties[i][0] + 1] > properties[i][1]) ans++; - } - return ans; -}; - -// another - -/** - * @param {number[][]} properties - * @return {number} - */ -const numberOfWeakCharacters = function(properties) { - properties.sort((a, b) => a[0] === b[0] ? b[1] - a[1] : a[0] - b[0]) - let max = -Infinity, res = 0 - for(let n = properties.length, i = n - 1; i >= 0; i--) { - const [a, d] = properties[i] - if(d < max) res++ - max = Math.max(max, d) - } - - return res -}; diff --git a/1996.the-number-of-weak-characters-in-the-game.js b/1996.the-number-of-weak-characters-in-the-game.js new file mode 100644 index 00000000..9148d323 --- /dev/null +++ b/1996.the-number-of-weak-characters-in-the-game.js @@ -0,0 +1,30 @@ +/** + * @param {number[][]} properties + * @return {number} + */ +const numberOfWeakCharacters = function(properties) { + const props = properties, n = props.length, maxDefFromRight = Array(n) + props.sort((a, b) => a[0] - b[0]) + for(let max = 0, i = n - 1; i >= 0; i--) { + max = Math.max(max, props[i][1]) + maxDefFromRight[i] = max + } + let res = 0 + + for(let i = 0; i < n; i++) { + const cur = props[i] + let l = i, r = n + while(l < r) { + const mid = l + Math.floor((r - l) / 2) + if(props[mid][0] > props[i][0]) r = mid + else l = mid + 1 + } + + if(l < n && maxDefFromRight[l] > props[i][1]) { + res++ + } + } + + return res +}; + diff --git a/1997-first-day-where-you-have-been-in-all-the-rooms.js b/1997-first-day-where-you-have-been-in-all-the-rooms.js deleted file mode 100644 index 8b503fdd..00000000 --- a/1997-first-day-where-you-have-been-in-all-the-rooms.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @param {number[]} nextVisit - * @return {number} - */ -const firstDayBeenInAllRooms = function(nextVisit) { - const P = 1e9+7; - const n = nextVisit.length; - const f = Array(n).fill(0) ; - f[0] = 0; - - for (let i = 1; i < n; i++) { - f[i] = (( - (2 * f[i - 1]) % P - + P - f[nextVisit[i - 1]]) % P + 2) % P; - } - - return f[n - 1]; -}; - -// another - -/** - * @param {number[]} nextVisit - * @return {number} - */ -const firstDayBeenInAllRooms = function(nextVisit) { - const mod = 1e9 + 7 - const n = nextVisit.length - const dp = Array(n).fill(0) - for(let i = 1; i < n; i++) { - // i - 1 ---> nextVisit[i - 1] ---> i - 1 ---> i - dp[i] = (dp[i - 1] + 1 + dp[i - 1] - dp[nextVisit[i - 1]] + 1 + mod) % mod - } - - return dp[n - 1] -}; diff --git a/1997.first-day-where-you-have-been-in-all-the-rooms.js b/1997.first-day-where-you-have-been-in-all-the-rooms.js new file mode 100644 index 00000000..95f760ab --- /dev/null +++ b/1997.first-day-where-you-have-been-in-all-the-rooms.js @@ -0,0 +1,19 @@ +/** + * @param {number[]} nextVisit + * @return {number} + */ +const firstDayBeenInAllRooms = function(nextVisit) { + const P = 1e9+7; + const n = nextVisit.length; + const f = Array(n).fill(0) ; + f[0] = 0; + + for (let i = 1; i < n; i++) { + f[i] = (( + (2 * f[i - 1]) % P + + P - f[nextVisit[i - 1]]) % P + 2) % P; + } + + return f[n - 1]; +}; + diff --git a/1998-gcd-sort-of-an-array.js b/1998-gcd-sort-of-an-array.js deleted file mode 100644 index 68ecd546..00000000 --- a/1998-gcd-sort-of-an-array.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - * @param {number[]} nums - * @return {boolean} - */ -const gcdSort = function(nums) { - const n = nums.length - const maxNum = Math.max(...nums); - const spf = sieve(maxNum); - - const uf = new UnionFind(maxNum + 1) - for(const e of nums) { - for(const f of getFactors(e)) uf.union(e, f) - } - const clone = nums.slice() - clone.sort((a, b) => a - b) - - for(let i = 0; i < n; i++) { - if(uf.find(nums[i]) !== uf.find(clone[i])) return false - } - - return true - - function sieve(n) { // O(Nlog(logN)) ~ O(N) - const res = [0, 0] - for (let i = 2; i <= n; ++i) res[i] = i; - for (let i = 2; i * i <= n; i++) { - if (res[i] != i) continue; // skip if `i` is not a prime number - for (let j = i * i; j <= n; j += i) { - if (res[j] == j) { // marking spf[j] if it is not previously marked - res[j] = i; - } - } - } - return res - } - - function getFactors(n) { // O(logN) - const factors = []; - while (n > 1) { - factors.push(spf[n]); - n = ~~(n /spf[n]); - } - return factors; - } -}; - -function gcd( x, y) { - return y == 0 ? x : gcd(y, x % y); -} - -class UnionFind { - constructor(n) { - this.parent = []; - for (let i = 0; i < n; i++) this.parent[i] = i; - } - find(x) { - if (x == this.parent[x]) return x; - return this.parent[x] = this.find(this.parent[x]); // Path compression - } - union(u, v) { - let pu = this.find(u), pv = this.find(v); - if (pu != pv) this.parent[pu] = pv; - } -}; - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -const gcdSort = function(nums) { - const spf = Array(nums.length).fill(0) - let maxNum = Math.max(...nums); - sieve(maxNum); - - const uf = new UnionFind(maxNum+1); - for (let x of nums) { - for (let f of getFactors(x)) uf.union(f, x); - } - - - const sortedArr = nums.slice(); - sortedArr.sort((a, b) => a - b) - - for (let i = 0; i < nums.length; ++i) { - let pu = uf.find(sortedArr[i]); - let pv = uf.find(nums[i]); - if (pu != pv) return false; // can't swap nums[i] with sortedArr[i] - } - return true; - - function sieve( n) { // O(Nlog(logN)) ~ O(N) - for (let i = 2; i <= n; ++i) spf[i] = i; - for (let i = 2; i * i <= n; i++) { - if (spf[i] != i) continue; // skip if `i` is not a prime number - for (let j = i * i; j <= n; j += i) { - if (spf[j] == j) { // marking spf[j] if it is not previously marked - spf[j] = i; - } - } - } - } - - function getFactors(n) { // O(logN) - const factors = []; - while (n > 1) { - factors.push(spf[n]); - n = ~~(n /spf[n]); - } - return factors; - } -}; - -function gcd( x, y) { - return y == 0 ? x : gcd(y, x % y); -} - -class UnionFind { - constructor(n) { - this.parent = []; - for (let i = 0; i < n; i++) this.parent[i] = i; - } - find(x) { - if (x == this.parent[x]) return x; - return this.parent[x] = this.find(this.parent[x]); // Path compression - } - union( u, v) { - let pu = this.find(u), pv = this.find(v); - if (pu != pv) this.parent[pu] = pv; - } -}; - diff --git a/1998.gcd-sort-of-an-array.js b/1998.gcd-sort-of-an-array.js new file mode 100644 index 00000000..ccc31216 --- /dev/null +++ b/1998.gcd-sort-of-an-array.js @@ -0,0 +1,65 @@ +/** + * @param {number[]} nums + * @return {boolean} + */ +const gcdSort = function(nums) { + const n = nums.length + const maxNum = Math.max(...nums); + const spf = sieve(maxNum); + + const uf = new UnionFind(maxNum + 1) + for(const e of nums) { + for(const f of getFactors(e)) uf.union(e, f) + } + const clone = nums.slice() + clone.sort((a, b) => a - b) + + for(let i = 0; i < n; i++) { + if(uf.find(nums[i]) !== uf.find(clone[i])) return false + } + + return true + + function sieve(n) { // O(Nlog(logN)) ~ O(N) + const res = [0, 0] + for (let i = 2; i <= n; ++i) res[i] = i; + for (let i = 2; i * i <= n; i++) { + if (res[i] != i) continue; // skip if `i` is not a prime number + for (let j = i * i; j <= n; j += i) { + if (res[j] == j) { // marking spf[j] if it is not previously marked + res[j] = i; + } + } + } + return res + } + + function getFactors(n) { // O(logN) + const factors = []; + while (n > 1) { + factors.push(spf[n]); + n = ~~(n /spf[n]); + } + return factors; + } +}; + +function gcd( x, y) { + return y == 0 ? x : gcd(y, x % y); +} + +class UnionFind { + constructor(n) { + this.parent = []; + for (let i = 0; i < n; i++) this.parent[i] = i; + } + find(x) { + if (x == this.parent[x]) return x; + return this.parent[x] = this.find(this.parent[x]); // Path compression + } + union(u, v) { + let pu = this.find(u), pv = this.find(v); + if (pu != pv) this.parent[pu] = pv; + } +}; + diff --git a/2-add-two-numbers.js b/2-add-two-numbers.js deleted file mode 100755 index 06f99a30..00000000 --- a/2-add-two-numbers.js +++ /dev/null @@ -1,161 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} l1 - * @param {ListNode} l2 - * @return {ListNode} - */ -const addTwoNumbers = function(l1, l2) { - let res = new ListNode(null) - let inc = false - let cur = res - while(l1 || l2 || inc) { - const tmp = ((l1 && l1.val) || 0) + ((l2 && l2.val) || 0) + (inc ? 1 : 0) - if(tmp >= 10) inc = true - else inc = false - cur.next = new ListNode(tmp % 10) - cur = cur.next - if(l1) l1 = l1.next - if(l2) l2 = l2.next - } - - return res.next -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} l1 - * @param {ListNode} l2 - * @return {ListNode} - */ -const addTwoNumbers = function(l1, l2) { - const res = new ListNode(null); - single(l1, l2, res); - return res.next; -}; - -function single(l1, l2, res) { - let cur; - let addOne = 0; - let sum = 0; - let curVal = 0; - while (l1 || l2 || addOne) { - sum = ((l1 && l1.val) || 0) + ((l2 && l2.val) || 0) + addOne; - if (sum / 10 >= 1) { - curVal = sum % 10; - addOne = 1; - } else { - curVal = sum; - addOne = 0; - } - - if (cur) { - cur = cur.next = new ListNode(curVal); - } else { - cur = res.next = new ListNode(curVal); - } - - if (l1) { - l1 = l1.next; - } - if (l2) { - l2 = l2.next; - } - } -} - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} l1 - * @param {ListNode} l2 - * @return {ListNode} - */ -const addTwoNumbers = function(l1, l2) { - let extra = false - const dummy = new ListNode() - let cur = dummy - while(l1 || l2) { - let val = 0 - if(l1) val += l1.val - if(l2) val += l2.val - if(extra) val += 1 - - if(val > 9) { - extra = true - val = val % 10 - } else { - extra = false - } - cur.next = new ListNode(val) - cur = cur.next - if(l1) l1 = l1.next - if(l2) l2 = l2.next - } - - if(extra) cur.next = new ListNode(1) - return dummy.next -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} l1 - * @param {ListNode} l2 - * @return {ListNode} - */ -const addTwoNumbers = function(l1, l2) { - const dummy = new ListNode(null) - let cur = dummy, carry = 0 - - while(l1 || l2) { - let v = 0 - if(l1 && l2) { - v = l1.val + l2.val + carry - l1 = l1.next - l2 = l2.next - } else { - const node = l1 || l2 - v = node.val + carry - if(l1) l1 = l1.next - if(l2) l2 = l2.next - } - - cur.next = new ListNode(v % 10) - cur = cur.next - if(v >= 10) carry = 1 - else carry = 0 - } - - if(carry) cur.next = new ListNode(1) - - return dummy.next -}; - diff --git a/2.add-two-numbers.js b/2.add-two-numbers.js new file mode 100644 index 00000000..e2a683d0 --- /dev/null +++ b/2.add-two-numbers.js @@ -0,0 +1,29 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} l1 + * @param {ListNode} l2 + * @return {ListNode} + */ +const addTwoNumbers = function(l1, l2) { + let res = new ListNode(null) + let inc = false + let cur = res + while(l1 || l2 || inc) { + const tmp = ((l1 && l1.val) || 0) + ((l2 && l2.val) || 0) + (inc ? 1 : 0) + if(tmp >= 10) inc = true + else inc = false + cur.next = new ListNode(tmp % 10) + cur = cur.next + if(l1) l1 = l1.next + if(l2) l2 = l2.next + } + + return res.next +}; + diff --git a/20-valid-parentheses.js b/20-valid-parentheses.js deleted file mode 100755 index c9065a42..00000000 --- a/20-valid-parentheses.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @param {string} s - * @return {boolean} - */ - const isValid = function(s) { - const stack = [] - for(let c of s) { - if(c === '(') stack.push(')') - else if(c === '{') stack.push('}') - else if(c === '[') stack.push(']') - else if(stack.length === 0 || c !== stack.pop()) return false - } - return stack.length === 0 -}; - - -// another - -/** - * @param {string} s - * @return {boolean} - */ - const isValid = function(s) { - const stack = [] - const n = s.length - for(let c of s) { - if(c === '(' || c === '{' || c === '[') stack.push(c) - else if(c === ')') { - if(stack[stack.length - 1] === '(') stack.pop() - else return false - } - else if(c === '}') { - if(stack[stack.length - 1] === '{') stack.pop() - else return false - } - else if(c === ']') { - if(stack[stack.length - 1] === '[') stack.pop() - else return false - } - } - return stack.length === 0 -}; - -// another - -/** - * @param {string} s - * @return {boolean} - */ -const isValid = function(s) { - const openBrackets = ["(", "{", "["]; - const closeBrackets = [")", "}", "]"]; - const oArr = []; - let char = ""; - let cidx = 0; - let oidx = 0; - for (let i = 0; i < s.length; i++) { - char = s.charAt(i); - if (closeBrackets.indexOf(char) !== -1) { - cidx = closeBrackets.indexOf(char); - lastOpenBracket = oArr[oArr.length - 1]; - oidx = openBrackets.indexOf(lastOpenBracket); - if (cidx === oidx) { - oArr.pop(); - } else { - return false; - } - } else { - oArr.push(char); - } - } - return oArr.length > 0 ? false : true; -}; diff --git a/20.valid-parentheses.js b/20.valid-parentheses.js new file mode 100644 index 00000000..f71eeeef --- /dev/null +++ b/20.valid-parentheses.js @@ -0,0 +1,16 @@ +/** + * @param {string} s + * @return {boolean} + */ + const isValid = function(s) { + const stack = [] + for(let c of s) { + if(c === '(') stack.push(')') + else if(c === '{') stack.push('}') + else if(c === '[') stack.push(']') + else if(stack.length === 0 || c !== stack.pop()) return false + } + return stack.length === 0 +}; + + diff --git a/200-number-of-islands.js b/200.number-of-islands.js similarity index 100% rename from 200-number-of-islands.js rename to 200.number-of-islands.js diff --git a/2000-reverse-prefix-of-word.js b/2000.reverse-prefix-of-word.js similarity index 100% rename from 2000-reverse-prefix-of-word.js rename to 2000.reverse-prefix-of-word.js diff --git a/2001-number-of-pairs-of-interchangeable-rectangles.js b/2001.number-of-pairs-of-interchangeable-rectangles.js similarity index 100% rename from 2001-number-of-pairs-of-interchangeable-rectangles.js rename to 2001.number-of-pairs-of-interchangeable-rectangles.js diff --git a/2002-maximum-product-of-the-length-of-two-palindromic-subsequences.js b/2002-maximum-product-of-the-length-of-two-palindromic-subsequences.js deleted file mode 100644 index f6126c88..00000000 --- a/2002-maximum-product-of-the-length-of-two-palindromic-subsequences.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -var maxProduct = function(s) { - const n = s.length; - let max = 0; - for (let i = 0; i < (1 << n); i++) { - let n0 = palindromic(i, s, true); - if (n0 === 0) continue; - for (let j = 0; j < (1 << n); j++) { - if ((i & j) > 0) continue; - max = Math.max(palindromic(j, s) * n0, max); - } - } - return max; -}; -function palindromic( i, s) { - const n = s.length; - let sub = ""; - for (let x = 0; x < n; x++) { - if (i & (1 << x)) sub += s[x] - } - let len = sub.length; - for (let i = 0; i < len; i++) { - if (sub[i] !== sub[len - i - 1]) return 0; - } - return len; -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const maxProduct = function(s) { - const s1 = [], s2 = [], n = s.length - let res = 0 - dfs(0) - return res - - function dfs(idx) { - if(idx === n) { - if(isPalindromic(s1) && isPalindromic(s2)) { - res = Math.max(res, s1.length * s2.length) - } - return - } - const ch = s[idx] - s1.push(ch) - dfs(idx + 1) - s1.pop() - - s2.push(ch) - dfs(idx + 1) - s2.pop() - - dfs(idx + 1) - } - function isPalindromic(arr) { - let l = 0, r = arr.length - 1 - while(l < r) { - if(arr[l] === arr[r]) { - l++ - r-- - } else { - return false - } - } - return true - } -}; diff --git a/2002.maximum-product-of-the-length-of-two-palindromic-subsequences.js b/2002.maximum-product-of-the-length-of-two-palindromic-subsequences.js new file mode 100644 index 00000000..8d99d71e --- /dev/null +++ b/2002.maximum-product-of-the-length-of-two-palindromic-subsequences.js @@ -0,0 +1,30 @@ +/** + * @param {string} s + * @return {number} + */ +var maxProduct = function(s) { + const n = s.length; + let max = 0; + for (let i = 0; i < (1 << n); i++) { + let n0 = palindromic(i, s, true); + if (n0 === 0) continue; + for (let j = 0; j < (1 << n); j++) { + if ((i & j) > 0) continue; + max = Math.max(palindromic(j, s) * n0, max); + } + } + return max; +}; +function palindromic( i, s) { + const n = s.length; + let sub = ""; + for (let x = 0; x < n; x++) { + if (i & (1 << x)) sub += s[x] + } + let len = sub.length; + for (let i = 0; i < len; i++) { + if (sub[i] !== sub[len - i - 1]) return 0; + } + return len; +} + diff --git a/2003-smallest-missing-genetic-value-in-each-subtree.js b/2003.smallest-missing-genetic-value-in-each-subtree.js similarity index 100% rename from 2003-smallest-missing-genetic-value-in-each-subtree.js rename to 2003.smallest-missing-genetic-value-in-each-subtree.js diff --git a/2006-count-number-of-pairs-with-absolute-difference-k.js b/2006.count-number-of-pairs-with-absolute-difference-k.js similarity index 100% rename from 2006-count-number-of-pairs-with-absolute-difference-k.js rename to 2006.count-number-of-pairs-with-absolute-difference-k.js diff --git a/2007-find-original-array-from-doubled-array.js b/2007-find-original-array-from-doubled-array.js deleted file mode 100644 index 89e270d2..00000000 --- a/2007-find-original-array-from-doubled-array.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @param {number[]} changed - * @return {number[]} - */ - const findOriginalArray = function(changed) { - const n = changed.length, res = [], { abs } = Math - if(n % 2 === 1 || n === 0) return res - const hash = {} - for(let e of changed) { - if(hash[e] == null) hash[e] = 0 - hash[e]++ - } - const keys = Object.keys(hash) - keys.sort((a, b) => abs(a) - abs(b)) - - for(let k of keys) { - if(hash[k] > (hash[k * 2] || 0)) return [] - for(let i = 0; i < hash[k]; i++) { - res.push(k) - hash[2 * k]-- - } - } - - return res -}; - -// another - -/** - * @param {number[]} changed - * @return {number[]} - */ - const findOriginalArray = function(changed) { - const n = changed.length, res = [] - if(n % 2 === 1 || n === 0) return res - const hash = {} - for(let e of changed) { - if(hash[e] == null) hash[e] = 0 - hash[e]++ - } - changed.sort((a, b) => a - b) - - for(let i = 0, len = n; i < len; i++) { - const cur = changed[i], dVal = cur * 2 - if (cur === 0 && hash[cur] % 2 === 1) continue - if(hash[dVal] && hash[cur]) { - res.push(cur) - hash[dVal]-- - hash[cur]-- - } - } - return res.length === n / 2 ? res : [] -}; diff --git a/2007.find-original-array-from-doubled-array.js b/2007.find-original-array-from-doubled-array.js new file mode 100644 index 00000000..7d4629b3 --- /dev/null +++ b/2007.find-original-array-from-doubled-array.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} changed + * @return {number[]} + */ + const findOriginalArray = function(changed) { + const n = changed.length, res = [], { abs } = Math + if(n % 2 === 1 || n === 0) return res + const hash = {} + for(let e of changed) { + if(hash[e] == null) hash[e] = 0 + hash[e]++ + } + const keys = Object.keys(hash) + keys.sort((a, b) => abs(a) - abs(b)) + + for(let k of keys) { + if(hash[k] > (hash[k * 2] || 0)) return [] + for(let i = 0; i < hash[k]; i++) { + res.push(k) + hash[2 * k]-- + } + } + + return res +}; + diff --git a/2008-maximum-earnings-from-taxi.js b/2008-maximum-earnings-from-taxi.js deleted file mode 100644 index eb4fb356..00000000 --- a/2008-maximum-earnings-from-taxi.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} rides - * @return {number} - */ -const maxTaxiEarnings = function(n, rides) { - const { max } = Math - const rideStartAt = Array.from({length: n}, () => []); - for (let ride of rides) { - let s = ride[0], e = ride[1], t = ride[2]; - rideStartAt[s].push([e, e - s + t]); // [end, dollar] - } - const dp = Array(n+1).fill(0); - for (let i = n-1; i >= 1; --i) { - for (let [e, d] of rideStartAt[i]) { - dp[i] = max(dp[i], dp[e] + d); - } - dp[i] = max(dp[i], dp[i + 1]); - } - return dp[1]; -}; - -// another - -/** - * @param {number} n - * @param {number[][]} rides - * @return {number} - */ -const maxTaxiEarnings = function(n, rides) { - const size = rides.length - rides.sort((a, b) => a[1] - b[1]) - const dp = [[0,0]] - for(const [s, e, t] of rides) { - const cur = bs(dp, s) + (e - s + t) - if(cur > dp[dp.length - 1][1]) { - dp.push([e, cur]) - } - } - return dp[dp.length - 1][1] - - function bs(arr, t) { - let l = 0, r = arr.length - 1 - while(l < r) { - const mid = r - ((r - l) >> 1) - if(arr[mid][0] > t) r = mid - 1 - else l = mid - } - // console.log(arr, t, l) - return arr[l][1] - } -}; diff --git a/2008.maximum-earnings-from-taxi.js b/2008.maximum-earnings-from-taxi.js new file mode 100644 index 00000000..cc9669e7 --- /dev/null +++ b/2008.maximum-earnings-from-taxi.js @@ -0,0 +1,22 @@ +/** + * @param {number} n + * @param {number[][]} rides + * @return {number} + */ +const maxTaxiEarnings = function(n, rides) { + const { max } = Math + const rideStartAt = Array.from({length: n}, () => []); + for (let ride of rides) { + let s = ride[0], e = ride[1], t = ride[2]; + rideStartAt[s].push([e, e - s + t]); // [end, dollar] + } + const dp = Array(n+1).fill(0); + for (let i = n-1; i >= 1; --i) { + for (let [e, d] of rideStartAt[i]) { + dp[i] = max(dp[i], dp[e] + d); + } + dp[i] = max(dp[i], dp[i + 1]); + } + return dp[1]; +}; + diff --git a/2009-minimum-number-of-operations-to-make-array-continuous.js b/2009.minimum-number-of-operations-to-make-array-continuous.js similarity index 100% rename from 2009-minimum-number-of-operations-to-make-array-continuous.js rename to 2009.minimum-number-of-operations-to-make-array-continuous.js diff --git a/201-bitwise-and-of-numbers-range.js b/201-bitwise-and-of-numbers-range.js deleted file mode 100644 index 7ab808b4..00000000 --- a/201-bitwise-and-of-numbers-range.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {number} m - * @param {number} n - * @return {number} - */ -const rangeBitwiseAnd = function(m, n) { - while(m>= 1 - n >>= 1 - s++ - } - return m << s -}; diff --git a/201.bitwise-and-of-numbers-range.js b/201.bitwise-and-of-numbers-range.js new file mode 100644 index 00000000..7b67a74a --- /dev/null +++ b/201.bitwise-and-of-numbers-range.js @@ -0,0 +1,10 @@ +/** + * @param {number} m + * @param {number} n + * @return {number} + */ +const rangeBitwiseAnd = function(m, n) { + while(m= k) { - possibleChars.push(char); - } - } - - // Test possibilities - let ans = ""; - dfs(""); - - return ans; - - // Recursive function, tests if the given subsequence repeats k times in s - function dfs(seq) { - // Does not have enough repeats, return - if (countRepeats(seq) < k) { - return; - } - - // Update our answer if the new subsequence is better - if (seq.length > ans.length || (seq.length === ans.length && seq > ans)) { - ans = seq; - } - - // Append possible characters to the subsequence and test again - if (seq.length < maxLen) { - for (const char of possibleChars) { - dfs(seq + char); - } - } - } - - // Counts the number of times the given subsequence repeats in s (up to k) - function countRepeats(seq) { - - // Empty string, return k - if (!seq) { - return k; - } - - let repeats = 0; - let seqIdx = 0; - - for (const char of s) { - if (char === seq[seqIdx]) { - seqIdx += 1; - - if (seqIdx >= seq.length) { - seqIdx = 0; - repeats += 1; - - if (repeats >= k) { - break; - } - } - } - } - - return repeats; - } -}; diff --git a/2014.longest-subsequence-repeated-k-times.js b/2014.longest-subsequence-repeated-k-times.js new file mode 100644 index 00000000..41236f0a --- /dev/null +++ b/2014.longest-subsequence-repeated-k-times.js @@ -0,0 +1,48 @@ +/** + * @param {string} s + * @param {number} k + * @return {string} + */ +const longestSubsequenceRepeatedK = function(s, k) { + const n = s.length, a = 'a'.charCodeAt(0) + + let res = '' + const q = [''] + + while(q.length) { + const size = q.length + for(let i = 0; i < size; i++) { + const cur = q.shift() + for(let j = 0; j < 26; j++) { + const next = cur + String.fromCharCode(a + j) + if(isSub(s, next, k)) { + res = next + q.push(next) + } + } + + } + } + + return res + + + function isSub(s, p, k) { + let repeated = 0 + for(let i = 0, j = 0, n = s.length, m = p.length; i < n; i++) { + if(s[i] === p[j]) { + j++ + if(j === m) { + repeated++ + j = 0 + if(repeated === k) { + return true + } + } + } + } + + return false + } +}; + diff --git a/2015-average-height-of-buildings-in-each-segment.js b/2015.average-height-of-buildings-in-each-segment.js similarity index 100% rename from 2015-average-height-of-buildings-in-each-segment.js rename to 2015.average-height-of-buildings-in-each-segment.js diff --git a/2018-check-if-word-can-be-placed-in-crossword.js b/2018.check-if-word-can-be-placed-in-crossword.js similarity index 100% rename from 2018-check-if-word-can-be-placed-in-crossword.js rename to 2018.check-if-word-can-be-placed-in-crossword.js diff --git a/2019-the-score-of-students-solving-math-expression.js b/2019.the-score-of-students-solving-math-expression.js similarity index 100% rename from 2019-the-score-of-students-solving-math-expression.js rename to 2019.the-score-of-students-solving-math-expression.js diff --git a/202-happy-number.js b/202-happy-number.js deleted file mode 100755 index 340a34ca..00000000 --- a/202-happy-number.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @param {number} n - * @return {boolean} - */ -const isHappy = function(n) { - const arr = []; - let tmp = n; - while (arr.indexOf(tmp) === -1) { - arr.push(tmp); - let res = ("" + tmp) - .split("") - .reduce((ac, str) => ac + Math.pow(+str, 2), 0); - if (res === 1) { - return true; - } - tmp = res; - } - return false; -}; diff --git a/202.happy-number.js b/202.happy-number.js new file mode 100644 index 00000000..135632db --- /dev/null +++ b/202.happy-number.js @@ -0,0 +1,19 @@ +/** + * @param {number} n + * @return {boolean} + */ +const isHappy = function(n) { + const arr = []; + let tmp = n; + while (arr.indexOf(tmp) === -1) { + arr.push(tmp); + let res = ("" + tmp) + .split("") + .reduce((ac, str) => ac + Math.pow(+str, 2), 0); + if (res === 1) { + return true; + } + tmp = res; + } + return false; +}; diff --git a/2023-number-of-pairs-of-strings-with-concatenation-equal-to-target.js b/2023.number-of-pairs-of-strings-with-concatenation-equal-to-target.js similarity index 100% rename from 2023-number-of-pairs-of-strings-with-concatenation-equal-to-target.js rename to 2023.number-of-pairs-of-strings-with-concatenation-equal-to-target.js diff --git a/2024-maximize-the-confusion-of-an-exam.js b/2024-maximize-the-confusion-of-an-exam.js deleted file mode 100644 index a181942c..00000000 --- a/2024-maximize-the-confusion-of-an-exam.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @param {string} answerKey - * @param {number} k - * @return {number} - */ -const maxConsecutiveAnswers = function(answerKey, k) { - const helper = (str, transT) => { - let res = 0, l = 0, r = 0, num = 0 - const n = str.length - const target = transT === 1 ? 'T' : 'F' - while(r < n) { - if(str[r] === target) num++ - while(num > k) { - if(str[l] === target) num-- - l++ - } - res = Math.max(res, r - l + 1) - r++ - } - return res - } - - return Math.max(helper(answerKey, 0), helper(answerKey, 1)) -}; - -// another - -/** - * @param {string} answerKey - * @param {number} k - * @return {number} - */ -const maxConsecutiveAnswers = function(answerKey, k) { - let s = answerKey - const freq = Array(26).fill(0), n = s.length, A = 'A'.charCodeAt(0) - let res = 0, l = 0, r = 0, maxFreq = 0 - while(r < n) { - maxFreq = Math.max(maxFreq, ++freq[s.charCodeAt(r) - A]) - if(r - l + 1 - maxFreq > k) { - freq[s.charCodeAt(l) - A]-- - l++ - } - res = Math.max(res, r - l + 1) - r++ - } - - return res -}; - - diff --git a/2024.maximize-the-confusion-of-an-exam.js b/2024.maximize-the-confusion-of-an-exam.js new file mode 100644 index 00000000..d1a382f2 --- /dev/null +++ b/2024.maximize-the-confusion-of-an-exam.js @@ -0,0 +1,25 @@ +/** + * @param {string} answerKey + * @param {number} k + * @return {number} + */ +const maxConsecutiveAnswers = function(answerKey, k) { + const helper = (str, transT) => { + let res = 0, l = 0, r = 0, num = 0 + const n = str.length + const target = transT === 1 ? 'T' : 'F' + while(r < n) { + if(str[r] === target) num++ + while(num > k) { + if(str[l] === target) num-- + l++ + } + res = Math.max(res, r - l + 1) + r++ + } + return res + } + + return Math.max(helper(answerKey, 0), helper(answerKey, 1)) +}; + diff --git a/2025-maximum-number-of-ways-to-partition-an-array.js b/2025-maximum-number-of-ways-to-partition-an-array.js deleted file mode 100644 index ed96ae1e..00000000 --- a/2025-maximum-number-of-ways-to-partition-an-array.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const waysToPartition = function (nums, k) { - const n = nums.length, pre = Array(n).fill(0), suf = Array(n).fill(0) - pre[0] = nums[0], suf[n - 1] = nums[n - 1] - for(let i = 1; i < n; i++) { - pre[i] = pre[i - 1] + nums[i] - suf[n - 1 - i] = suf[n - i] + nums[n - 1 - i] - } - const sum = nums.reduce((ac, e) => ac + e, 0) - let res = 0 - for(let i = 0; i < n - 1; i++) { - if(pre[i] === suf[i + 1]) res++ - } - const cnt = new Map() - const arr = Array(n).fill(0) - for(let i = 0; i < n; i++) { - const newSum = sum - nums[i] + k - if(newSum % 2 === 0) arr[i] += (cnt.get(newSum / 2) || 0) - cnt.set(pre[i], (cnt.get(pre[i]) || 0) + 1) - } - cnt.clear() - for(let i = n - 1; i >= 0; i--) { - const newSum = sum - nums[i] + k - if(newSum % 2 === 0) arr[i] += (cnt.get(newSum / 2) || 0) - cnt.set(suf[i], (cnt.get(suf[i]) || 0) + 1) - } - - for(let e of arr) { - if(e > res) res = e - } - - return res -} - - -// another - - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const waysToPartition = function (nums, k) { - const n = nums.length - const pref = Array(n).fill(0), - suff = Array(n).fill(0) - pref[0] = nums[0] - suff[n - 1] = nums[n - 1] - for (let i = 1; i < n; ++i) { - pref[i] = pref[i - 1] + nums[i] - suff[n - 1 - i] = suff[n - i] + nums[n - 1 - i] - } - let ans = 0 - const left = {}, - right = {} - - for (let i = 0; i < n - 1; ++i) { - const delta = pref[i] - suff[i + 1] - if (right[delta] == null) right[delta] = 0 - right[delta]++ - } - - if (right[0]) ans = right[0] - for (let i = 0; i < n; ++i) { - //find the number of pivot indexes when nums[i] is changed to k - let curr = 0, - diff = k - nums[i] - if (left[diff]) curr += left[diff] - if (right[-diff]) curr += right[-diff] - - //update answer - ans = Math.max(ans, curr) - - //transfer the current element from right to left - if (i < n - 1) { - let dd = pref[i] - suff[i + 1] - if(left[dd] == null) left[dd] = 0 - if(right[dd] == null) right[dd] = 0 - left[dd]++ - right[dd]-- - if (right[dd] == 0) delete right[dd] - } - } - return ans -} diff --git a/2025.maximum-number-of-ways-to-partition-an-array.js b/2025.maximum-number-of-ways-to-partition-an-array.js new file mode 100644 index 00000000..44abced0 --- /dev/null +++ b/2025.maximum-number-of-ways-to-partition-an-array.js @@ -0,0 +1,39 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const waysToPartition = function (nums, k) { + const n = nums.length, pre = Array(n).fill(0), suf = Array(n).fill(0) + pre[0] = nums[0], suf[n - 1] = nums[n - 1] + for(let i = 1; i < n; i++) { + pre[i] = pre[i - 1] + nums[i] + suf[n - 1 - i] = suf[n - i] + nums[n - 1 - i] + } + const sum = nums.reduce((ac, e) => ac + e, 0) + let res = 0 + for(let i = 0; i < n - 1; i++) { + if(pre[i] === suf[i + 1]) res++ + } + const cnt = new Map() + const arr = Array(n).fill(0) + for(let i = 0; i < n; i++) { + const newSum = sum - nums[i] + k + if(newSum % 2 === 0) arr[i] += (cnt.get(newSum / 2) || 0) + cnt.set(pre[i], (cnt.get(pre[i]) || 0) + 1) + } + cnt.clear() + for(let i = n - 1; i >= 0; i--) { + const newSum = sum - nums[i] + k + if(newSum % 2 === 0) arr[i] += (cnt.get(newSum / 2) || 0) + cnt.set(suf[i], (cnt.get(suf[i]) || 0) + 1) + } + + for(let e of arr) { + if(e > res) res = e + } + + return res +} + + diff --git a/2029-stone-game-ix.js b/2029.stone-game-ix.js similarity index 100% rename from 2029-stone-game-ix.js rename to 2029.stone-game-ix.js diff --git a/203-remove-linked-list-elements.js b/203-remove-linked-list-elements.js deleted file mode 100644 index 42807a2f..00000000 --- a/203-remove-linked-list-elements.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @param {number} val - * @return {ListNode} - */ -const removeElements = function(head, val) { - const dummy = new ListNode(Infinity) - if(head == null) return null - dummy.next = head - let cur = head - let prev = dummy - while(cur) { - if(cur.val === val) { - prev.next = cur.next - cur = cur.next - } else { - prev = cur - cur = cur.next - } - } - return dummy.next -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @param {number} val - * @return {ListNode} - */ -const removeElements = function(head, val) { - if (head === null) return null; - head.next = removeElements(head.next, val); - return head.val === val ? head.next : head; -}; diff --git a/203.remove-linked-list-elements.js b/203.remove-linked-list-elements.js new file mode 100644 index 00000000..dd278dd7 --- /dev/null +++ b/203.remove-linked-list-elements.js @@ -0,0 +1,30 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @param {number} val + * @return {ListNode} + */ +const removeElements = function(head, val) { + const dummy = new ListNode(Infinity) + if(head == null) return null + dummy.next = head + let cur = head + let prev = dummy + while(cur) { + if(cur.val === val) { + prev.next = cur.next + cur = cur.next + } else { + prev = cur + cur = cur.next + } + } + return dummy.next +}; + diff --git a/2030-smallest-k-length-subsequence-with-occurrences-of-a-letter.js b/2030.smallest-k-length-subsequence-with-occurrences-of-a-letter.js similarity index 100% rename from 2030-smallest-k-length-subsequence-with-occurrences-of-a-letter.js rename to 2030.smallest-k-length-subsequence-with-occurrences-of-a-letter.js diff --git a/2031-count-subarrays-with-more-ones-than-zeros.js b/2031.count-subarrays-with-more-ones-than-zeros.js similarity index 100% rename from 2031-count-subarrays-with-more-ones-than-zeros.js rename to 2031.count-subarrays-with-more-ones-than-zeros.js diff --git a/2032-two-out-of-three.js b/2032.two-out-of-three.js similarity index 100% rename from 2032-two-out-of-three.js rename to 2032.two-out-of-three.js diff --git a/2033-minimum-operations-to-make-a-uni-value-grid.js b/2033-minimum-operations-to-make-a-uni-value-grid.js deleted file mode 100644 index edb3acc4..00000000 --- a/2033-minimum-operations-to-make-a-uni-value-grid.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - * @param {number[][]} grid - * @param {number} x - * @return {number} - */ -const minOperations = function (grid, x) { - const arr = [], - m = grid.length, - n = grid[0].length - const len = m * n - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - arr.push(grid[i][j]) - } - } - arr.sort((a, b) => a - b) - const mid = arr[~~(len / 2)], { abs } = Math - let res = 0 - for(const e of arr) { - if(abs(mid - e) % x !== 0) return -1 - res += abs(mid - e) / x - } - - return res -} - -// another - -/** - * @param {number[][]} grid - * @param {number} x - * @return {number} - */ -const minOperations = function(grid, x) { - const arr = [] - const m = grid.length, n = grid[0].length - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - arr.push(grid[i][j]) - } - } - arr.sort((a, b) => a - b) - - for(let i = 1; i < m * n; i++) { - if((arr[i] - arr[i - 1]) % x !== 0) return -1 - } - const sum = arr.reduce((ac, e) => ac + e, 0) - const pre = [] - pre.push(arr[0]) - for(let i = 1; i < m * n; i++) { - pre[i] = pre[i - 1] + arr[i] - } - - let res = 0, num = 0, min = sum - arr[0] * m * n, idx = 0 - for(let i = 1; i < m * n; i++) { - const cur = (i + 1) * arr[i] - pre[i] + (sum - pre[i] - arr[i] * (m * n - i - 1)) - // console.log(cur, (i + 1) * arr[i] - pre[i], sum - pre[i] - arr[i] * (m * n - i - 1)) - // const cur = sum - arr[i] * (m * n - i) - if(cur < min) { - idx = i - min = cur - } - } - - // console.log(idx) - - for(let i = 0; i < m * n; i++) { - if(i === idx) continue - res += Math.abs(arr[i] - arr[idx]) / x - } - - return res -}; -// 20 - 6 - 4 * 2 -// 2 4 6 8 -// 1 2 3 5 - -// another - -/** - * @param {number[][]} grid - * @param {number} x - * @return {number} - */ -const minOperations = function(grid, x) { - const arr = [], m = grid.length, n = grid[0].length - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - arr.push(grid[i][j]) - } - } - arr.sort((a, b) => a - b) - const mid = arr[~~((m * n) / 2)] - let res = 0 - - for(let e of arr) { - if (e !== mid) { - const cur = Math.abs(e - mid) - if(cur % x !== 0) return -1 - res += cur / x - } - } - return res -}; - -// another - -/** - * @param {number[][]} grid - * @param {number} x - * @return {number} - */ -function minOperations(grid, x) { - const m = grid.length, n = grid[0].length, mn = m * n, arr = [] - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - arr.push(grid[i][j]) - } - } - arr.sort((a, b) => a - b) - const mid = arr[~~(mn / 2)] - let res = 0 - - for(let e of arr) { - if(e !== mid) { - const delta = Math.abs(e - mid) - if(delta % x !== 0) return -1 - res += delta / x - } - } - - return res -}; diff --git a/2033.minimum-operations-to-make-a-uni-value-grid.js b/2033.minimum-operations-to-make-a-uni-value-grid.js new file mode 100644 index 00000000..b5db02af --- /dev/null +++ b/2033.minimum-operations-to-make-a-uni-value-grid.js @@ -0,0 +1,26 @@ +/** + * @param {number[][]} grid + * @param {number} x + * @return {number} + */ +const minOperations = function (grid, x) { + const arr = [], + m = grid.length, + n = grid[0].length + const len = m * n + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + arr.push(grid[i][j]) + } + } + arr.sort((a, b) => a - b) + const mid = arr[~~(len / 2)], { abs } = Math + let res = 0 + for(const e of arr) { + if(abs(mid - e) % x !== 0) return -1 + res += abs(mid - e) / x + } + + return res +} + diff --git a/2034-stock-price-fluctuation.js b/2034.stock-price-fluctuation.js similarity index 100% rename from 2034-stock-price-fluctuation.js rename to 2034.stock-price-fluctuation.js diff --git a/2035-partition-array-into-two-arrays-to-minimize-sum-difference.js b/2035.partition-array-into-two-arrays-to-minimize-sum-difference.js similarity index 100% rename from 2035-partition-array-into-two-arrays-to-minimize-sum-difference.js rename to 2035.partition-array-into-two-arrays-to-minimize-sum-difference.js diff --git a/2037-minimum-number-of-moves-to-seat-everyone.js b/2037.minimum-number-of-moves-to-seat-everyone.js similarity index 100% rename from 2037-minimum-number-of-moves-to-seat-everyone.js rename to 2037.minimum-number-of-moves-to-seat-everyone.js diff --git a/2038-remove-colored-pieces-if-both-neighbors-are-the-same-color.js b/2038.remove-colored-pieces-if-both-neighbors-are-the-same-color.js similarity index 100% rename from 2038-remove-colored-pieces-if-both-neighbors-are-the-same-color.js rename to 2038.remove-colored-pieces-if-both-neighbors-are-the-same-color.js diff --git a/204-count-primes.js b/204-count-primes.js deleted file mode 100755 index 6882fda6..00000000 --- a/204-count-primes.js +++ /dev/null @@ -1,132 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const countPrimes = function(n) { - const arr = Array(n).fill(0) - - for(let i = 2; i * i < n; i++) { - if(arr[i] !== 0) continue - let j = i * i - while(j < n) { - arr[j] = 1 - j += i - } - } - - let res = 0 - for(let i = 2; i < n; i++) { - if(arr[i] === 0) res++ - } - return res -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const countPrimes = function (n) { - const memo = Array(n).fill(false) - let res = 0 - for (let i = 2; i < n; i++) { - if (memo[i] === false) { - res++ - for (let j = 2; i * j < n; j++) { - memo[i * j] = true - } - } - } - - return res -} - - -// another - - -/** - * @param {number} n - * @return {number} - */ -const countPrimes = function(n) { - /** - * if n = 2, the prime 2 is not less than n, - * so there are no primes less than n - */ - if (n < 3) return 0; - - /** - * Start with the assumption that half the numbers below n are - * prime candidates, since we know that half of them are even, - * and so _in general_ aren't prime. - * - * An exception to this is 2, which is the only even prime. - * But also 1 is an odd which isn't prime. - * These two exceptions (a prime even and a for-sure not-prime odd) - * cancel each other out for n > 2, so our assumption holds. - * - * We'll decrement count when we find an odd which isn't prime. - * - * If n = 3, c = 1. - * If n = 5, c = 2. - * If n = 10, c = 5. - */ - let c = Math.floor(n / 2); - - /** - * Java initializes boolean arrays to {false}. - * In this method, we'll use truth to mark _composite_ numbers. - * - * This is the opposite of most Sieve of Eratosthenes methods, - * which use truth to mark _prime_ numbers. - * - * We will _NOT_ mark evens as composite, even though they are. - * This is because `c` is current after each `i` iteration below. - */ - let s = []; - - /** - * Starting with an odd prime-candidate above 2, increment by two - * to skip evens (which we know are not prime candidates). - */ - for (let i = 3; i * i < n; i += 2) { - if (s[i]) { - // c has already been decremented for this composite odd - continue; - } - - /** - * For each prime i, iterate through the odd composites - * we know we can form from i, and mark them as composite - * if not already marked. - * - * We know that i * i is composite. - * We also know that i * i + i is composite, since they share - * a common factor of i. - * Thus, we also know that i * i + a*i is composite for all real a, - * since they share a common factor of i. - * - * Note, though, that i * i + i _must_ be composite for an - * independent reason: it must be even. - * (all i are odd, thus all i*i are odd, - * thus all (odd + odd) are even). - * - * Recall that, by initializing c to n/2, we already accounted for - * all of the evens less than n being composite, and so marking - * i * i + (odd)*i as composite is needless bookkeeping. - * - * So, we can skip checking i * i + a*i for all odd a, - * and just increment j by even multiples of i, - * since all (odd + even) are odd. - */ - for (let j = i * i; j < n; j += 2 * i) { - if (!s[j]) { - c--; - s[j] = true; - } - } - } - return c; -}; diff --git a/204.count-primes.js b/204.count-primes.js new file mode 100644 index 00000000..d8ff00b6 --- /dev/null +++ b/204.count-primes.js @@ -0,0 +1,23 @@ +/** + * @param {number} n + * @return {number} + */ +const countPrimes = function(n) { + const arr = Array(n).fill(0) + + for(let i = 2; i * i < n; i++) { + if(arr[i] !== 0) continue + let j = i * i + while(j < n) { + arr[j] = 1 + j += i + } + } + + let res = 0 + for(let i = 2; i < n; i++) { + if(arr[i] === 0) res++ + } + return res +}; + diff --git a/2040-kth-smallest-product-of-two-sorted-arrays.js b/2040.kth-smallest-product-of-two-sorted-arrays.js similarity index 100% rename from 2040-kth-smallest-product-of-two-sorted-arrays.js rename to 2040.kth-smallest-product-of-two-sorted-arrays.js diff --git a/2042-check-if-numbers-are-ascending-in-a-sentence.js b/2042.check-if-numbers-are-ascending-in-a-sentence.js similarity index 100% rename from 2042-check-if-numbers-are-ascending-in-a-sentence.js rename to 2042.check-if-numbers-are-ascending-in-a-sentence.js diff --git a/2043-simple-bank-system.js b/2043.simple-bank-system.js similarity index 100% rename from 2043-simple-bank-system.js rename to 2043.simple-bank-system.js diff --git a/2044-count-number-of-maximum-bitwise-or-subsets.js b/2044.count-number-of-maximum-bitwise-or-subsets.js similarity index 100% rename from 2044-count-number-of-maximum-bitwise-or-subsets.js rename to 2044.count-number-of-maximum-bitwise-or-subsets.js diff --git a/2045-second-minimum-time-to-reach-destination.js b/2045-second-minimum-time-to-reach-destination.js deleted file mode 100644 index bec00cad..00000000 --- a/2045-second-minimum-time-to-reach-destination.js +++ /dev/null @@ -1,94 +0,0 @@ -const initializeGraph = (n) => { - let G = [] - for (let i = 0; i < n; i++) { - G.push([]) - } - return G -} -const addEdgeToG = (G, Edges) => { - for (const [u, v] of Edges) { - G[u].push(v) - G[v].push(u) - } -} -/** - * @param {number} n - * @param {number[][]} edges - * @param {number} time - * @param {number} change - * @return {number} - */ -const secondMinimum = (n, edges, time, change) => { - let adj = initializeGraph(n + 1) - addEdgeToG(adj, edges) - let cost = initializeGraph(n + 1) - let pq = new MinPriorityQueue({ priority: (x) => x[0] }) - pq.enqueue([0, 1]) - let green = 2 * change - while (pq.size()) { - let cur = pq.dequeue().element - let [t, node] = cur - if (cost[node].length == 2) continue - let nextT = - t % green < change ? t : (((t + green - 1) / green) >> 0) * green - let cn = cost[node].length - if (node == n) { - if (cn == 0 || cost[node][cn - 1] != t) { - cost[node].push(t) - } else { - continue - } - } else { - if (cn == 0 || cost[node][cn - 1] != nextT) { - cost[node].push(nextT) - } else { - continue - } - } - for (const next_node of adj[node]) pq.enqueue([nextT + time, next_node]) - } - return cost[n][1] -} - -// another - -/** - * @param {number} n - * @param {number[][]} edges - * @param {number} time - * @param {number} change - * @return {number} - */ - var secondMinimum = function (n, edges, time, change) { - const graph = new Map() - for (let i = 1; i <= n; i++) graph.set(i, []) - for (const [u, v] of edges) { - graph.get(u).push(v) - graph.get(v).push(u) - } - const first = Array(n + 1).fill(Infinity) - const second = Array(n + 1).fill(Infinity) - first[1] = 0 - - const q = new MinPriorityQueue() - q.enqueue(1, 0) - - while (q.size()) { - let {element: node, priority: cur} = q.dequeue() - cur += time // cur: arrival time - let leave = cur - if (~~(cur / change) & 1) leave += change - (cur % change) - for (let nei of graph.get(node)) { - if (second[nei] <= cur) continue - if (first[nei] === cur) continue - if (first[nei] > cur) { - second[nei] = first[nei] - first[nei] = cur - } else { - second[nei] = cur - } - q.enqueue(nei, leave) - } - } - return second[n] -} diff --git a/2045.second-minimum-time-to-reach-destination.js b/2045.second-minimum-time-to-reach-destination.js new file mode 100644 index 00000000..f7d60e41 --- /dev/null +++ b/2045.second-minimum-time-to-reach-destination.js @@ -0,0 +1,52 @@ +const initializeGraph = (n) => { + let G = [] + for (let i = 0; i < n; i++) { + G.push([]) + } + return G +} +const addEdgeToG = (G, Edges) => { + for (const [u, v] of Edges) { + G[u].push(v) + G[v].push(u) + } +} +/** + * @param {number} n + * @param {number[][]} edges + * @param {number} time + * @param {number} change + * @return {number} + */ +const secondMinimum = (n, edges, time, change) => { + let adj = initializeGraph(n + 1) + addEdgeToG(adj, edges) + let cost = initializeGraph(n + 1) + let pq = new MinPriorityQueue({ priority: (x) => x[0] }) + pq.enqueue([0, 1]) + let green = 2 * change + while (pq.size()) { + let cur = pq.dequeue().element + let [t, node] = cur + if (cost[node].length == 2) continue + let nextT = + t % green < change ? t : (((t + green - 1) / green) >> 0) * green + let cn = cost[node].length + if (node == n) { + if (cn == 0 || cost[node][cn - 1] != t) { + cost[node].push(t) + } else { + continue + } + } else { + if (cn == 0 || cost[node][cn - 1] != nextT) { + cost[node].push(nextT) + } else { + continue + } + } + for (const next_node of adj[node]) pq.enqueue([nextT + time, next_node]) + } + return cost[n][1] +} + diff --git a/2046-sort-linked-list-already-sorted-using-absolute-values.js b/2046.sort-linked-list-already-sorted-using-absolute-values.js similarity index 100% rename from 2046-sort-linked-list-already-sorted-using-absolute-values.js rename to 2046.sort-linked-list-already-sorted-using-absolute-values.js diff --git a/2047-number-of-valid-words-in-a-sentence.js b/2047.number-of-valid-words-in-a-sentence.js similarity index 100% rename from 2047-number-of-valid-words-in-a-sentence.js rename to 2047.number-of-valid-words-in-a-sentence.js diff --git a/2048-next-greater-numerically-balanced-number.js b/2048.next-greater-numerically-balanced-number.js similarity index 100% rename from 2048-next-greater-numerically-balanced-number.js rename to 2048.next-greater-numerically-balanced-number.js diff --git a/2049-count-nodes-with-the-highest-score.js b/2049-count-nodes-with-the-highest-score.js deleted file mode 100644 index 5be74015..00000000 --- a/2049-count-nodes-with-the-highest-score.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @param {number[]} parents - * @return {number} - */ -const countHighestScoreNodes = function(parents) { - const n = parents.length, graph = {}, hash = {} - for(let i = 1; i < n; i++) { - if(graph[parents[i]] == null) graph[parents[i]] = [] - graph[parents[i]].push(i) - } - dfs(0) - - function dfs(node) { - let product = 1, num = 0 - for(let child of (graph[node] || [])) { - const tmp = dfs(child) - product *= tmp - num += tmp - } - if(n - 1 - num > 0) product *= (n - 1 - num) - hash[product] = (hash[product] || 0) + 1 - return num + 1 - } - const maxKey = Math.max(...Object.keys(hash)) - return hash[maxKey] -}; - -// another - -/** - * @param {number[]} parents - * @return {number} - */ -const countHighestScoreNodes = function(parents) { - const n = parents.length, hash = {}, graph = {} - for(let i = 1; i < n; i++) { - if(graph[parents[i]] == null) graph[parents[i]] = [] - graph[parents[i]].push(i) - } - - dfs(0) - const mk = Math.max(...Object.keys(hash)) - return hash[mk] - - function dfs(i) { - let num = 0, prod = 1 - for(const e of (graph[i] || []) ) { - const tmp = dfs(e) - num += tmp - prod *= tmp - } - - if(n - 1 - num > 0) prod *= (n - 1 - num) - hash[prod] = (hash[prod] || 0) + 1 - - return num + 1 - } -}; diff --git a/2049.count-nodes-with-the-highest-score.js b/2049.count-nodes-with-the-highest-score.js new file mode 100644 index 00000000..955c74cc --- /dev/null +++ b/2049.count-nodes-with-the-highest-score.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} parents + * @return {number} + */ +const countHighestScoreNodes = function(parents) { + const n = parents.length, graph = {}, hash = {} + for(let i = 1; i < n; i++) { + if(graph[parents[i]] == null) graph[parents[i]] = [] + graph[parents[i]].push(i) + } + dfs(0) + + function dfs(node) { + let product = 1, num = 0 + for(let child of (graph[node] || [])) { + const tmp = dfs(child) + product *= tmp + num += tmp + } + if(n - 1 - num > 0) product *= (n - 1 - num) + hash[product] = (hash[product] || 0) + 1 + return num + 1 + } + const maxKey = Math.max(...Object.keys(hash)) + return hash[maxKey] +}; + diff --git a/205-isomorphic-strings.js b/205.isomorphic-strings.js similarity index 100% rename from 205-isomorphic-strings.js rename to 205.isomorphic-strings.js diff --git a/2050-parallel-courses-iii.js b/2050-parallel-courses-iii.js deleted file mode 100644 index 1be35f37..00000000 --- a/2050-parallel-courses-iii.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} relations - * @param {number[]} time - * @return {number} - */ -const minimumTime = function (n, relations, time) { - const inDegree = Array(n + 1).fill(0) - const graph = {}, dist = Array(n + 1).fill(0) - - for(const [pre, nxt] of relations) { - if(graph[pre] == null) graph[pre] = [] - graph[pre].push(nxt) - inDegree[nxt]++ - } - - let q = [] - for(let i = 1;i <=n;i++) { - if(inDegree[i]===0) { - q.push(i) - dist[i] = time[i - 1] - } - } - while(q.length) { - const size = q.length, nxt = [] - - for(let i = 0; i < size; i++) { - const cur = q[i] - for(const e of (graph[cur] || [])) { - dist[e] = Math.max(dist[e], dist[cur] + time[e - 1]) - inDegree[e]-- - if(inDegree[e] === 0) { - nxt.push(e) - } - } - } - - q = nxt - } - - return Math.max(...dist) -} - -// another - -/** - * @param {number} n - * @param {number[][]} relations - * @param {number[]} time - * @return {number} - */ -const minimumTime = function(n, relations, time) { - const graph = {}, dist = Array(n).fill(0), inDegree = Array(n).fill(0) - - for(let [pre, next] of relations) { - pre--, next-- - if(graph[pre] == null) graph[pre] = [] - graph[pre].push(next) - inDegree[next]++ - } - - const q = [] - for(let i = 0; i < n; i++) { - if(inDegree[i] === 0) { - q.push(i) - dist[i] = time[i] - } - } - - let res = 0 - while(q.length) { - const cur = q.shift() - for(const next of (graph[cur] || [])) { - dist[next] = Math.max(dist[next], dist[cur] + time[next]) - inDegree[next]-- - if(inDegree[next] === 0) q.push(next) - } - } - - return Math.max(...dist) -} - -// another - -/** - * @param {number} n - * @param {number[][]} relations - * @param {number[]} time - * @return {number} - */ -const minimumTime = function(n, relations, time) { - const graph = {}, dist = Array(n).fill(0), inDegree = Array(n).fill(0) - for(let [from, to] of relations) { - from--, to-- - if (graph[from] == null) graph[from] = [] - graph[from].push(to) - inDegree[to]++ - } - const q = [] - for(let i = 0; i < n; i++) { - if(inDegree[i] === 0) { - q.push(i) - dist[i] = time[i] - } - } - - while(q.length) { - const u = q.shift() - for(const v of (graph[u] || [])) { - dist[v] = Math.max(dist[v], dist[u] + time[v]) - if(--inDegree[v] === 0) q.push(v) - } - } - - let res = 0 - for(let e of dist) { - if(e > res) res = e - } - return res -}; diff --git a/2050.parallel-courses-iii.js b/2050.parallel-courses-iii.js new file mode 100644 index 00000000..78006b74 --- /dev/null +++ b/2050.parallel-courses-iii.js @@ -0,0 +1,43 @@ +/** + * @param {number} n + * @param {number[][]} relations + * @param {number[]} time + * @return {number} + */ +const minimumTime = function (n, relations, time) { + const inDegree = Array(n + 1).fill(0) + const graph = {}, dist = Array(n + 1).fill(0) + + for(const [pre, nxt] of relations) { + if(graph[pre] == null) graph[pre] = [] + graph[pre].push(nxt) + inDegree[nxt]++ + } + + let q = [] + for(let i = 1;i <=n;i++) { + if(inDegree[i]===0) { + q.push(i) + dist[i] = time[i - 1] + } + } + while(q.length) { + const size = q.length, nxt = [] + + for(let i = 0; i < size; i++) { + const cur = q[i] + for(const e of (graph[cur] || [])) { + dist[e] = Math.max(dist[e], dist[cur] + time[e - 1]) + inDegree[e]-- + if(inDegree[e] === 0) { + nxt.push(e) + } + } + } + + q = nxt + } + + return Math.max(...dist) +} + diff --git a/2053-kth-distinct-string-in-an-array.js b/2053.kth-distinct-string-in-an-array.js similarity index 100% rename from 2053-kth-distinct-string-in-an-array.js rename to 2053.kth-distinct-string-in-an-array.js diff --git a/2054-two-best-non-overlapping-events.js b/2054-two-best-non-overlapping-events.js deleted file mode 100644 index 07adffa0..00000000 --- a/2054-two-best-non-overlapping-events.js +++ /dev/null @@ -1,118 +0,0 @@ - -/** - * @param {number[][]} events - * @return {number} - */ -const maxTwoEvents = function(events) { - const n = events.length - events.sort((a, b) => a[0] - b[0]) - const dp = Array.from({ length: n }, () => Array(3).fill(-1)) - - return dfs(0, 0) - - function dfs(idx, cnt) { - if(cnt === 2 || idx >= n) return 0 - if(dp[idx][cnt] === -1) { - let end = events[idx][1] - let lo = idx + 1, hi = n - 1; - while (lo < hi) { - const mid = lo + ((hi - lo) >> 1); - if (events[mid][0] <= end) lo = mid + 1 - else hi = mid; - } - const include = events[idx][2] + (lo < n && events[lo][0] > end ? dfs(lo, cnt + 1) : 0); - const exclude = dfs(idx + 1, cnt); - dp[idx][cnt] = Math.max(include, exclude); - } - - return dp[idx][cnt] - } -}; - -// another - -/** - * @param {number[][]} events - * @return {number} - */ -const maxTwoEvents = function(events) { - const n = events.length, { max } = Math - let res = 0, maxVal = 0; - const pq = new PriorityQueue((a, b) => a[0] < b[0]); - events.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]) - for (let e of events) { - for(; !pq.isEmpty() && pq.peek()[0] < e[0]; pq.pop()) - maxVal = max(maxVal, pq.peek()[1]); - res = max(res, maxVal + e[2]); - pq.push([e[1], e[2]]); - } - return res; -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/2054.two-best-non-overlapping-events.js b/2054.two-best-non-overlapping-events.js new file mode 100644 index 00000000..3b8c3bc5 --- /dev/null +++ b/2054.two-best-non-overlapping-events.js @@ -0,0 +1,31 @@ + +/** + * @param {number[][]} events + * @return {number} + */ +const maxTwoEvents = function(events) { + const n = events.length + events.sort((a, b) => a[0] - b[0]) + const dp = Array.from({ length: n }, () => Array(3).fill(-1)) + + return dfs(0, 0) + + function dfs(idx, cnt) { + if(cnt === 2 || idx >= n) return 0 + if(dp[idx][cnt] === -1) { + let end = events[idx][1] + let lo = idx + 1, hi = n - 1; + while (lo < hi) { + const mid = lo + ((hi - lo) >> 1); + if (events[mid][0] <= end) lo = mid + 1 + else hi = mid; + } + const include = events[idx][2] + (lo < n && events[lo][0] > end ? dfs(lo, cnt + 1) : 0); + const exclude = dfs(idx + 1, cnt); + dp[idx][cnt] = Math.max(include, exclude); + } + + return dp[idx][cnt] + } +}; + diff --git a/2055-plates-between-candles.js b/2055-plates-between-candles.js deleted file mode 100644 index bca0a066..00000000 --- a/2055-plates-between-candles.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @param {string} s - * @param {number[][]} queries - * @return {number[]} - */ -const platesBetweenCandles = function (s, queries) { - const candleIdxArr = [] - const n = s.length - for(let i = 0; i < n; i++) { - if(s[i] === '|') candleIdxArr.push(i) - } - // console.log(candleIdxArr) - const res = [] - for(const [s, e] of queries) { - const l = lower(candleIdxArr, s, e) - const r = upper(candleIdxArr, s ,e) - const tmp = (candleIdxArr[r] - candleIdxArr[l] + 1) - (r - l + 1) - res.push(tmp >= 0 ? tmp : 0) - } - - return res - - - function lower(arr,s,e) { - let l = 0, r = arr.length - 1 - while(l < r) { - // console.log('lower',l, r) - const mid = ~~(l + (r - l)/2) - if(arr[mid] < s) l = mid + 1 - else r = mid - } - return l - } - - function upper(arr,s, e) { - let l = 0, r = arr.length - 1 - while(l < r) { - - const mid = r - ~~((r - l)/2) - // console.log('upper', l, r, mid, e) - if(arr[mid] > e) r = mid - 1 - else l = mid - } - return l - } -} - -// another - -/** - * @param {string} s - * @param {number[][]} queries - * @return {number[]} - */ -const platesBetweenCandles = function(s, queries) { - const n = s.length, - leftCandlePos = Array(n).fill(-1) - rightCandlePos = Array(n).fill(-1) - candleCnt = Array(n).fill(0) - let pos = -1 - for(let i = 0; i < n; i++) { - if(s[i] === '|') pos = i - leftCandlePos[i] = pos - } - pos = -1 - for(let i = n - 1; i >= 0; i--) { - if(s[i] === '|') pos = i - rightCandlePos[i] = pos - } - for(let i = 0, cnt = 0; i < n; i++) { - if(s[i] === '|') cnt++ - candleCnt[i] = cnt - } - - const len = queries.length, res = Array(len).fill(0) - - for(let i = 0; i < len; i++) { - const [left, right] = queries[i] - const leftCandle = rightCandlePos[left], rightCandle = leftCandlePos[right] - const delta = rightCandle - leftCandle - if(leftCandle !== -1 && rightCandle !== -1 && delta > 1) { - res[i] = delta + 1 - (candleCnt[rightCandle] - candleCnt[leftCandle] + 1) - } - } - - return res -} - -// another - -/** - * @param {string} s - * @param {number[][]} queries - * @return {number[]} - */ -const platesBetweenCandles = function (s, queries) { - const n = s.length - const leftArr = Array(n).fill(-1), - rightArr = Array(n).fill(n), - candleCnt = Array(n).fill(0) - let candle = -1 - for (let i = 0; i < n; i++) { - if (s[i] === '|') candle = i - leftArr[i] = candle - } - candle = n - for (let i = n - 1; i >= 0; i--) { - if (s[i] === '|') candle = i - rightArr[i] = candle - } - let cnt = 0 - for (let i = 0; i < n; i++) { - if (s[i] === '|') cnt++ - candleCnt[i] = cnt - } - // console.log(leftArr, rightArr) - const res = [] - for (const [s, e] of queries) { - const l = rightArr[s] - const r = leftArr[e] - const diff = r - l - if (diff > 1) { - const e = r - l + 1 - (candleCnt[r] - candleCnt[l] + 1) - res.push(e) - } else res.push(0) - } - - return res -} - diff --git a/2055.plates-between-candles.js b/2055.plates-between-candles.js new file mode 100644 index 00000000..52a42618 --- /dev/null +++ b/2055.plates-between-candles.js @@ -0,0 +1,47 @@ +/** + * @param {string} s + * @param {number[][]} queries + * @return {number[]} + */ +const platesBetweenCandles = function (s, queries) { + const candleIdxArr = [] + const n = s.length + for(let i = 0; i < n; i++) { + if(s[i] === '|') candleIdxArr.push(i) + } + // console.log(candleIdxArr) + const res = [] + for(const [s, e] of queries) { + const l = lower(candleIdxArr, s, e) + const r = upper(candleIdxArr, s ,e) + const tmp = (candleIdxArr[r] - candleIdxArr[l] + 1) - (r - l + 1) + res.push(tmp >= 0 ? tmp : 0) + } + + return res + + + function lower(arr,s,e) { + let l = 0, r = arr.length - 1 + while(l < r) { + // console.log('lower',l, r) + const mid = ~~(l + (r - l)/2) + if(arr[mid] < s) l = mid + 1 + else r = mid + } + return l + } + + function upper(arr,s, e) { + let l = 0, r = arr.length - 1 + while(l < r) { + + const mid = r - ~~((r - l)/2) + // console.log('upper', l, r, mid, e) + if(arr[mid] > e) r = mid - 1 + else l = mid + } + return l + } +} + diff --git a/2057-smallest-index-with-equal-value.js b/2057.smallest-index-with-equal-value.js similarity index 100% rename from 2057-smallest-index-with-equal-value.js rename to 2057.smallest-index-with-equal-value.js diff --git a/2058-find-the-minimum-and-maximum-number-of-nodes-between-critical-points.js b/2058.find-the-minimum-and-maximum-number-of-nodes-between-critical-points.js similarity index 100% rename from 2058-find-the-minimum-and-maximum-number-of-nodes-between-critical-points.js rename to 2058.find-the-minimum-and-maximum-number-of-nodes-between-critical-points.js diff --git a/2059-minimum-operations-to-convert-number.js b/2059.minimum-operations-to-convert-number.js similarity index 100% rename from 2059-minimum-operations-to-convert-number.js rename to 2059.minimum-operations-to-convert-number.js diff --git a/206-reverse-linked-list.js b/206-reverse-linked-list.js deleted file mode 100755 index 82ccda9a..00000000 --- a/206-reverse-linked-list.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @return {ListNode} - */ -const reverseList = function(head) { - if(head == null) return head - const pre = new ListNode(null, head) - let cur = head - while(cur.next) { - const tmp = pre.next - pre.next = cur.next - cur.next = cur.next.next - pre.next.next = tmp - } - - return pre.next -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @return {ListNode} - */ -const reverseList = function(head) { - let prev = null; - let cur = head; - let tmp; - let tmpNext; - while (cur !== null) { - tmp = cur; - tmpNext = cur.next; - cur.next = prev; - prev = tmp; - cur = tmpNext; - } - - return prev; -}; diff --git a/206.reverse-linked-list.js b/206.reverse-linked-list.js new file mode 100644 index 00000000..c713b6ed --- /dev/null +++ b/206.reverse-linked-list.js @@ -0,0 +1,25 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ +const reverseList = function(head) { + if(head == null) return head + const pre = new ListNode(null, head) + let cur = head + while(cur.next) { + const tmp = pre.next + pre.next = cur.next + cur.next = cur.next.next + pre.next.next = tmp + } + + return pre.next +}; + diff --git a/2060-check-if-an-original-string-exists-given-two-encoded-strings.js b/2060-check-if-an-original-string-exists-given-two-encoded-strings.js deleted file mode 100644 index 12be2ab2..00000000 --- a/2060-check-if-an-original-string-exists-given-two-encoded-strings.js +++ /dev/null @@ -1,183 +0,0 @@ -function possiblyEquals(s1, s2) { - const n = s1.length, m = s2.length; - const dp = Array.from({ length: n + 1 }, v => Array.from({ length: m + 1}, w => new Set())); - dp[0][0].add(0); - - for (let i = 0; i <= n; i++) { - for (let j = 0; j <= m; j++) { - for (let delta of dp[i][j]) { - // s1 is number - let num = 0; - if (delta <= 0) { - for (let p = i; i < Math.min(i + 3, n); p++) { - if (isDigit(s1[p])) { - num = num * 10 + Number(s1[p]); - dp[p + 1][j].add(delta + num); - } else { - break; - } - } - } - - // s2 is number - num = 0; - if (delta >= 0) { - for (let q = j; q < Math.min(j + 3, m); q++) { - if (isDigit(s2[q])) { - num = num * 10 + Number(s2[q]); - dp[i][q + 1].add(delta - num); - } else { - break; - } - } - } - - // match s1 non-digit character - if (i < n && delta < 0 && !isDigit(s1[i])) { - dp[i + 1][j].add(delta + 1); - } - - // match s2 non-digit character - if (j < m && delta > 0 && !isDigit(s2[j])) { - dp[i][j + 1].add(delta - 1); - } - - // two non-digit character match - if (i < n && j < m && delta == 0 && s1[i] == s2[j]) { - dp[i + 1][j + 1].add(0); - } - - } - } - } - return dp[n][m].has(0); -}; - -function isDigit(char) { - return (/^\d{1}$/g).test(char); -} - -// another - -/** - * @param {string} s1 - * @param {string} s2 - * @return {boolean} - */ -const possiblyEquals = function(s1, s2) { - const n = s1.length - const m = s2.length - const memo = Array.from({ length: n + 1 }, () => - Array.from({ length: m + 1 }, () => Array(1001).fill(null)) - ) - memo[0][0][1000] = true - - return dfs(0, 0, 0) - - function dfs(i, j, diff) { - if(memo[i][j][diff] != null) return memo[i][j][diff] - let res = false - if (i == n && j == m) res = diff === 0 - else if (i < n && isDigit(s1[i])) { - let ii = i - while (ii < n && isDigit( s1[ii] )) ii += 1 - for (let x of helper(s1.slice(i, ii))) { - if (dfs(ii, j, diff-x)) res = true - } - } else if (j < m && isDigit( s2[j] )) { - let jj = j - while (jj < m && isDigit( s2[jj] )) jj += 1 - for (let y of helper(s2.slice(j, jj))) { - if (dfs(i, jj, diff+y)) res = true - } - } else if (diff == 0) { - if (i < n && j < m && s1[i] == s2[j]) res = dfs(i+1, j+1, 0) - } else if (diff > 0) { - if (i < n) res = dfs(i+1, j, diff-1) - } else { - if (j < m) res = dfs(i, j+1, diff+1) - } - - memo[i][j][diff] = res - return res - } - - function isDigit(ch) { - return ch >= '0' && ch <= '9' - } - - function helper(str) { - const ans = new Set() - ans.add(+str) - for(let i = 1, len = str.length; i < len; i++) { - const pre = helper(str.slice(0, i)) - const post = helper(str.slice(i)) - for(let p of pre) { - for(let n of post) { - ans.add(p + n) - } - } - } - return Array.from(ans) - } -}; - -// another - -/** - * @param {string} s1 - * @param {string} s2 - * @return {boolean} - */ -var possiblyEquals = function (s1, s2) { - let n = s1.length - let m = s2.length - const f = Array.from({ length: n + 1 }, () => - Array.from({ length: m + 1 }, () => Array(1001).fill(false)) - ) - f[0][0][1000] = true - - for (let i = 0; i <= n; i++) - for (let j = 0; j <= m; j++) - for (let k = 0; k < 2000; k++) { - if (!f[i][j][k]) continue - // if k==1000 means length diff is 0, so check both next charactors. - if (i + 1 <= n && j + 1 <= m && k == 1000 && s1[i] == s2[j]) { - f[i + 1][j + 1][k] = true - } - // if first string is longer or same length, extend second string. - if (k >= 1000 && j + 1 <= m) { - if (s2[j] >= 'a' && s2[j] <= 'z') { - // do not extend to be a longer string using a-z. - if (k > 1000) { - f[i][j + 1][k - 1] = true - } - } else if (s2[j] > '0') { - let cur = 0 - for (let r = j; r < m; r++) { - if (s2[r] >= '0' && s2[r] <= '9') { - cur = cur * 10 + (s2[r] - '0') - f[i][r + 1][k - cur] = true - } else break - } - } - } - // if second string is longer or same length, extend first string. - if (k <= 1000 && i + 1 <= n) { - if (s1[i] >= 'a' && s1[i] <= 'z') { - if (k < 1000) { - f[i + 1][j][k + 1] = true - } - } else if (s1[i] > '0') { - let cur = 0 - for (let r = i; r < n; r++) { - if (s1[r] >= '0' && s1[r] <= '9') { - cur = cur * 10 + (s1[r] - '0') - f[r + 1][j][k + cur] = true - } else break - } - } - } - } - return f[n][m][1000] -} diff --git a/2060.check-if-an-original-string-exists-given-two-encoded-strings.js b/2060.check-if-an-original-string-exists-given-two-encoded-strings.js new file mode 100644 index 00000000..8c5e333d --- /dev/null +++ b/2060.check-if-an-original-string-exists-given-two-encoded-strings.js @@ -0,0 +1,59 @@ +function possiblyEquals(s1, s2) { + const n = s1.length, m = s2.length; + const dp = Array.from({ length: n + 1 }, v => Array.from({ length: m + 1}, w => new Set())); + dp[0][0].add(0); + + for (let i = 0; i <= n; i++) { + for (let j = 0; j <= m; j++) { + for (let delta of dp[i][j]) { + // s1 is number + let num = 0; + if (delta <= 0) { + for (let p = i; i < Math.min(i + 3, n); p++) { + if (isDigit(s1[p])) { + num = num * 10 + Number(s1[p]); + dp[p + 1][j].add(delta + num); + } else { + break; + } + } + } + + // s2 is number + num = 0; + if (delta >= 0) { + for (let q = j; q < Math.min(j + 3, m); q++) { + if (isDigit(s2[q])) { + num = num * 10 + Number(s2[q]); + dp[i][q + 1].add(delta - num); + } else { + break; + } + } + } + + // match s1 non-digit character + if (i < n && delta < 0 && !isDigit(s1[i])) { + dp[i + 1][j].add(delta + 1); + } + + // match s2 non-digit character + if (j < m && delta > 0 && !isDigit(s2[j])) { + dp[i][j + 1].add(delta - 1); + } + + // two non-digit character match + if (i < n && j < m && delta == 0 && s1[i] == s2[j]) { + dp[i + 1][j + 1].add(0); + } + + } + } + } + return dp[n][m].has(0); +}; + +function isDigit(char) { + return (/^\d{1}$/g).test(char); +} + diff --git a/2062-count-vowel-substrings-of-a-string.js b/2062.count-vowel-substrings-of-a-string.js similarity index 100% rename from 2062-count-vowel-substrings-of-a-string.js rename to 2062.count-vowel-substrings-of-a-string.js diff --git a/2063-vowels-of-all-substrings.js b/2063.vowels-of-all-substrings.js similarity index 100% rename from 2063-vowels-of-all-substrings.js rename to 2063.vowels-of-all-substrings.js diff --git a/2064-minimized-maximum-of-products-distributed-to-any-store.js b/2064-minimized-maximum-of-products-distributed-to-any-store.js deleted file mode 100644 index 577fe013..00000000 --- a/2064-minimized-maximum-of-products-distributed-to-any-store.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @param {number} n - * @param {number[]} quantities - * @return {number} - */ -const minimizedMaximum = function(n, quantities) { - const m = quantities.length - let l = 0, r = Math.max(...quantities) - while(l < r) { - const mid = l + Math.floor((r - l) / 2) - if(valid(mid)) r = mid - else l = mid + 1 - } - - return l - - function valid(mid) { - if(m > n) return false - let res = 0 - for (let i = 0; i < m; i++) { - res += Math.ceil(quantities[i] / mid) - } - return res <= n - } -}; - -// another - - -/** - * @param {number} n - * @param {number[]} quantities - * @return {number} - */ -var minimizedMaximum = function(n, quantities) { - let MAX = 0; - for (let x of quantities) MAX = Math.max(x, MAX); - let l = 1, r = MAX; - while (l < r) { - let mid = Math.floor((l + r) / 2); - if (valid(quantities, mid) <= n) r = mid; - else l = mid + 1; - } - return l; -}; - - - - function valid(quantities, max) { - let cnt = 0; - for (let x of quantities) cnt += Math.floor(x / max) + ((x % max) ? 1 : 0); - return cnt; - } - -// another - -/** - * @param {number} n - * @param {number[]} quantities - * @return {number} - */ -const minimizedMaximum = function(n, quantities) { - let MAX = 0; - for (let x of quantities) MAX = Math.max(x, MAX); - let l = 1, r = MAX; - while (l < r) { - let mid = Math.floor((l + r) / 2); - if (valid(quantities, mid, n)) l = mid + 1; - else r = mid; - } - return l; -}; - -function valid(quantities, max, n) { - let cnt = 0; - for (let x of quantities) cnt += Math.floor(x / max) + ((x % max) ? 1 : 0); - return cnt > n; -} diff --git a/2064.minimized-maximum-of-products-distributed-to-any-store.js b/2064.minimized-maximum-of-products-distributed-to-any-store.js new file mode 100644 index 00000000..5e904a89 --- /dev/null +++ b/2064.minimized-maximum-of-products-distributed-to-any-store.js @@ -0,0 +1,26 @@ +/** + * @param {number} n + * @param {number[]} quantities + * @return {number} + */ +const minimizedMaximum = function(n, quantities) { + const m = quantities.length + let l = 0, r = Math.max(...quantities) + while(l < r) { + const mid = l + Math.floor((r - l) / 2) + if(valid(mid)) r = mid + else l = mid + 1 + } + + return l + + function valid(mid) { + if(m > n) return false + let res = 0 + for (let i = 0; i < m; i++) { + res += Math.ceil(quantities[i] / mid) + } + return res <= n + } +}; + diff --git a/2065-maximum-path-quality-of-a-graph.js b/2065-maximum-path-quality-of-a-graph.js deleted file mode 100644 index ced6bb56..00000000 --- a/2065-maximum-path-quality-of-a-graph.js +++ /dev/null @@ -1,113 +0,0 @@ -/** - * @param {number[]} values - * @param {number[][]} edges - * @param {number} maxTime - * @return {number} - */ -const maximalPathQuality = function(values, edges, maxTime) { - const graph = {}, n = values.length - for(const [u, v, t] of edges) { - if(graph[u] == null) graph[u] = [] - if(graph[v] == null) graph[v] = [] - graph[u].push([v, t]) - graph[v].push([u, t]) - } - let res = 0, visited = new Array(n).fill(0) - visited[0] = 1 - bt(0, values[0], 0) - return res - - function bt(i, val, time) { - if(time > maxTime) return - if(i === 0) res = Math.max(res, val) - - for(const [next, nextTime] of (graph[i] || [])) { - const nextVal = visited[next] > 0 ? val : val + values[next] - visited[next]++ - bt(next, nextVal, time + nextTime) - visited[next]-- - } - } -}; - -// another - - -/** - * @param {number[]} values - * @param {number[][]} edges - * @param {number} maxTime - * @return {number} - */ -const maximalPathQuality = function(values, edges, maxTime) { - const graph = {}, n = values.length - for(const [u, v, t] of edges) { - if(graph[u] == null) graph[u] = [] - if(graph[v] == null) graph[v] = [] - graph[u].push([v, t]) - graph[v].push([u, t]) - } - let res = 0, visited = Array(n).fill(false) - bt(0, 0, 0) - return res - - function bt(i, cur, time) { - if(time > maxTime) return - const backup = visited[i] - if(!visited[i]) { - visited[i] = true - cur += values[i] - } - - if(i === 0) { - res = Math.max(res, cur) - } - - for(const [next, nextTime] of (graph[i] || [])) { - bt(next, cur, time + nextTime) - } - visited[i] = backup - } -}; - -// another - -/** - * @param {number[]} values - * @param {number[][]} edges - * @param {number} maxTime - * @return {number} - */ -const maximalPathQuality = function(values, edges, maxTime) { - let zeroMax = 0; - let n = values.length; - let ll = Array.from({length: n + 1}, () => []) - for (let edge of edges) { - let u = edge[0]; - let v = edge[1]; - let t = edge[2]; - ll[u].push([v, t]); - ll[v].push([u, t]); - } - const visited = Array(n + 1).fill(false); - dfs(0, 0, 0, maxTime, visited); - return zeroMax; - - function dfs(val, curNode, curTime, maxTime, visited) { - if (curTime > maxTime) { - return; - } - let before = visited[curNode]; - if (!visited[curNode]) { - val += values[curNode]; - visited[curNode] = true; - } - if (curNode == 0) { - zeroMax = Math.max(zeroMax, val); - } - for (let next of (ll[curNode] || [])) { - dfs(val, next[0], curTime + next[1], maxTime, visited); - } - visited[curNode] = before; - } -}; diff --git a/2065.maximum-path-quality-of-a-graph.js b/2065.maximum-path-quality-of-a-graph.js new file mode 100644 index 00000000..1c4f92f2 --- /dev/null +++ b/2065.maximum-path-quality-of-a-graph.js @@ -0,0 +1,32 @@ +/** + * @param {number[]} values + * @param {number[][]} edges + * @param {number} maxTime + * @return {number} + */ +const maximalPathQuality = function(values, edges, maxTime) { + const graph = {}, n = values.length + for(const [u, v, t] of edges) { + if(graph[u] == null) graph[u] = [] + if(graph[v] == null) graph[v] = [] + graph[u].push([v, t]) + graph[v].push([u, t]) + } + let res = 0, visited = new Array(n).fill(0) + visited[0] = 1 + bt(0, values[0], 0) + return res + + function bt(i, val, time) { + if(time > maxTime) return + if(i === 0) res = Math.max(res, val) + + for(const [next, nextTime] of (graph[i] || [])) { + const nextVal = visited[next] > 0 ? val : val + values[next] + visited[next]++ + bt(next, nextVal, time + nextTime) + visited[next]-- + } + } +}; + diff --git a/2068-check-whether-two-strings-are-almost-equivalent.js b/2068.check-whether-two-strings-are-almost-equivalent.js similarity index 100% rename from 2068-check-whether-two-strings-are-almost-equivalent.js rename to 2068.check-whether-two-strings-are-almost-equivalent.js diff --git a/2069-walking-robot-simulation-ii.js b/2069.walking-robot-simulation-ii.js similarity index 100% rename from 2069-walking-robot-simulation-ii.js rename to 2069.walking-robot-simulation-ii.js diff --git a/207-course-schedule.js b/207-course-schedule.js deleted file mode 100644 index 09233baa..00000000 --- a/207-course-schedule.js +++ /dev/null @@ -1,192 +0,0 @@ -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @return {boolean} - */ -const canFinish = function (numCourses, prerequisites) { - const set = new Set() - const indegree = Array(numCourses).fill(0) - const graph = {} - - for (const [s, e] of prerequisites) { - indegree[e]++ - if (graph[s] == null) graph[s] = [] - graph[s].push(e) - } - - let q = [] - for (let i = 0; i < numCourses; i++) { - if (indegree[i] === 0) q.push(i) - } - - while (q.length) { - const nxt = [] - for (let i = 0, size = q.length; i < size; i++) { - const cur = q[i] - set.add(cur) - for (const e of graph[cur] || []) { - indegree[e]-- - if (indegree[e] === 0 && !set.has(e)) { - nxt.push(e) - } - } - } - - q = nxt - } - - return set.size === numCourses -} - -// another - - -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @return {boolean} - */ -const canFinish = function(numCourses, prerequisites) { - const [graph, inDegree] = buildGraph(numCourses, prerequisites) - - const q = [] - for(let i = 0; i < numCourses; i++) { - if(inDegree.get(i) == null) q.push(i) - } - let num = 0 - while(q.length) { - const pre = q.pop() - num++ - for(const next of (graph.get(pre) || [])) { - inDegree.set(next, inDegree.get(next) - 1) - if(inDegree.get(next) === 0) q.push(next) - } - } - return num === numCourses - - - function buildGraph(n, arr) { - const res = new Map(), inDegree = new Map() - for(const [cur, pre] of arr) { - if(res.get(pre) == null) res.set(pre, new Set()) - res.get(pre).add(cur) - if(inDegree.get(cur) == null) inDegree.set(cur, 0) - inDegree.set(cur, inDegree.get(cur) + 1) - } - return [res, inDegree] - } -}; - -// another - -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @return {boolean} - */ -const canFinish = function(numCourses, prerequisites) { - const seen = new Set() - const seeing = new Set() - const adj = [...Array(numCourses)].map(r => []) - for (let [u, v] of prerequisites) { - adj[v].push(u) - } - for (let c = 0; c < numCourses; c++) { - if (!dfs(c)) { - return false - } - } - return true - function dfs(v) { - if (seen.has(v)) return true - if (seeing.has(v)) return false - seeing.add(v) - for (let nv of adj[v]) { - if (!dfs(nv)) { - return false - } - } - seeing.delete(v) - seen.add(v) - return true - } -} - -// another - -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @return {boolean} - */ -const canFinish = function(vertices, edges) { - const sortedOrder = [] - if (vertices <= 0) { - return sortedOrder - } - const inDegree = Array(vertices).fill(0) - const graph = Array(vertices) - .fill(0) - .map(() => Array()) - edges.forEach(edge => { - let parent = edge[0] - let child = edge[1] - graph[parent].push(child) - inDegree[child]++ - }) - const sources = [] - for (let i = 0; i < inDegree.length; i++) { - if (inDegree[i] === 0) { - sources.push(i) - } - } - while (sources.length > 0) { - const vertex = sources.shift() - sortedOrder.push(vertex) - - graph[vertex].forEach(child => { - inDegree[child] -= 1 - if (inDegree[child] === 0) { - sources.push(child) - } - }) - } - return sortedOrder.length === vertices ? true : false -} - -// another - -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @return {boolean} - */ -const canFinish = function(numCourses, prerequisites) { - const set = new Set(), hash = {} - for(let i = 0; i < prerequisites.length; i++) { - const [cur, pre] = prerequisites[i] - if(hash[cur] == null) hash[cur] = new Set() - hash[cur].add(pre) - } - const q = [] - - for(let i = 0; i < numCourses; i++) { - if(hash[i] == null) q.push(i) - } - let visited = 0 - - while(q.length) { - const cur = q.shift() - visited++ - Object.keys(hash).forEach(k => { - if(hash[k].has(cur)) { - hash[k].delete(cur) - } - if(hash[k].size === 0) { - delete hash[k] - q.push(+k) - } - }) - } - return visited === numCourses -}; diff --git a/207.course-schedule.js b/207.course-schedule.js new file mode 100644 index 00000000..34825256 --- /dev/null +++ b/207.course-schedule.js @@ -0,0 +1,40 @@ +/** + * @param {number} numCourses + * @param {number[][]} prerequisites + * @return {boolean} + */ +const canFinish = function (numCourses, prerequisites) { + const set = new Set() + const indegree = Array(numCourses).fill(0) + const graph = {} + + for (const [s, e] of prerequisites) { + indegree[e]++ + if (graph[s] == null) graph[s] = [] + graph[s].push(e) + } + + let q = [] + for (let i = 0; i < numCourses; i++) { + if (indegree[i] === 0) q.push(i) + } + + while (q.length) { + const nxt = [] + for (let i = 0, size = q.length; i < size; i++) { + const cur = q[i] + set.add(cur) + for (const e of graph[cur] || []) { + indegree[e]-- + if (indegree[e] === 0 && !set.has(e)) { + nxt.push(e) + } + } + } + + q = nxt + } + + return set.size === numCourses +} + diff --git a/2071-maximum-number-of-tasks-you-can-assign.js b/2071.maximum-number-of-tasks-you-can-assign.js similarity index 100% rename from 2071-maximum-number-of-tasks-you-can-assign.js rename to 2071.maximum-number-of-tasks-you-can-assign.js diff --git a/2073-time-needed-to-buy-tickets.js b/2073.time-needed-to-buy-tickets.js similarity index 100% rename from 2073-time-needed-to-buy-tickets.js rename to 2073.time-needed-to-buy-tickets.js diff --git a/2074-reverse-nodes-in-even-length-groups.js b/2074.reverse-nodes-in-even-length-groups.js similarity index 100% rename from 2074-reverse-nodes-in-even-length-groups.js rename to 2074.reverse-nodes-in-even-length-groups.js diff --git a/2075-decode-the-slanted-ciphertext.js b/2075.decode-the-slanted-ciphertext.js similarity index 100% rename from 2075-decode-the-slanted-ciphertext.js rename to 2075.decode-the-slanted-ciphertext.js diff --git a/2076-process-restricted-friend-requests.js b/2076.process-restricted-friend-requests.js similarity index 100% rename from 2076-process-restricted-friend-requests.js rename to 2076.process-restricted-friend-requests.js diff --git a/2078-two-furthest-houses-with-different-colors.js b/2078.two-furthest-houses-with-different-colors.js similarity index 100% rename from 2078-two-furthest-houses-with-different-colors.js rename to 2078.two-furthest-houses-with-different-colors.js diff --git a/2079-watering-plants.js b/2079.watering-plants.js similarity index 100% rename from 2079-watering-plants.js rename to 2079.watering-plants.js diff --git a/208-implement-trie-prefix-tree.js b/208-implement-trie-prefix-tree.js deleted file mode 100644 index 30c460ea..00000000 --- a/208-implement-trie-prefix-tree.js +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Initialize your data structure here. - */ -const Trie = function() { - this.root = {} -}; - -/** - * Inserts a word into the trie. - * @param {string} word - * @return {void} - */ -Trie.prototype.insert = function(word) { - let curr = this.root - word.split('').forEach(ch => (curr = curr[ch] = curr[ch] || {})) - curr.isWord = true -}; - -/** - * Returns if the word is in the trie. - * @param {string} word - * @return {boolean} - */ -Trie.prototype.search = function(word) { - let node = this.traverse(word) - return !!node && !!node.isWord -}; - -/** - * Returns if there is any word in the trie that starts with the given prefix. - * @param {string} prefix - * @return {boolean} - */ -Trie.prototype.startsWith = function(prefix) { - return !!this.traverse(prefix) -}; - -/** - * Your Trie object will be instantiated and called as such: - * var obj = new Trie() - * obj.insert(word) - * var param_2 = obj.search(word) - * var param_3 = obj.startsWith(prefix) - */ - -Trie.prototype.traverse = function(word) { - let curr = this.root - for (let i = 0; i < word.length; i++) { - if (!curr) return null - curr = curr[word[i]] - } - return curr -} - -// another - -class Trie { - constructor() { - this.links = new Map(); - this.isWord = false; - } - insert(word) { - let node = this; - for (const c of word) { - if (!node.links.has(c)) node.links.set(c, new Trie()); - node = node.links.get(c); - } - node.isWord = true; - } - search(word) { - const node = this.traverse(word); - return node ? node.isWord : false; - } - startsWith(prefix) { - const node = this.traverse(prefix); - return node !== null; - } - traverse(word) { - let node = this; - for (const c of word) { - if (node.links.has(c)) node = node.links.get(c); - else return null; - } - return node; - } -} - -// another -/** - * Initialize your data structure here. - */ -const Trie = function () { - this.root = new Node(null) -} - -/** - * Inserts a word into the trie. - * @param {string} word - * @return {void} - */ -Trie.prototype.insert = function (word) { - let cur = this.root - for (let i = 0, len = word.length; i < len; i++) { - if (!cur.children.has(word[i])) cur.children.set(word[i], new Node(null)) - cur = cur.children.get(word[i]) - if (i === len - 1) cur.word = true - } -} - -/** - * Returns if the word is in the trie. - * @param {string} word - * @return {boolean} - */ -Trie.prototype.search = function (word) { - let cur = this.root - for (let i = 0, len = word.length; i < len; i++) { - if (cur.children.has(word[i])) cur = cur.children.get(word[i]) - else return false - if (i === len - 1) return cur.word === true - } -} - -/** - * Returns if there is any word in the trie that starts with the given prefix. - * @param {string} prefix - * @return {boolean} - */ -Trie.prototype.startsWith = function (prefix) { - let cur = this.root - for (let i = 0, len = prefix.length; i < len; i++) { - if (cur.children.has(prefix[i])) cur = cur.children.get(prefix[i]) - else return false - if (i === len - 1) return true - } -} - -class Node { - constructor(v) { - this.val = v - this.word = false - this.children = new Map() - } -} - -/** - * Your Trie object will be instantiated and called as such: - * var obj = new Trie() - * obj.insert(word) - * var param_2 = obj.search(word) - * var param_3 = obj.startsWith(prefix) - */ diff --git a/208.implement-trie-prefix-tree.js b/208.implement-trie-prefix-tree.js new file mode 100644 index 00000000..c40a4718 --- /dev/null +++ b/208.implement-trie-prefix-tree.js @@ -0,0 +1,54 @@ +/** + * Initialize your data structure here. + */ +const Trie = function() { + this.root = {} +}; + +/** + * Inserts a word into the trie. + * @param {string} word + * @return {void} + */ +Trie.prototype.insert = function(word) { + let curr = this.root + word.split('').forEach(ch => (curr = curr[ch] = curr[ch] || {})) + curr.isWord = true +}; + +/** + * Returns if the word is in the trie. + * @param {string} word + * @return {boolean} + */ +Trie.prototype.search = function(word) { + let node = this.traverse(word) + return !!node && !!node.isWord +}; + +/** + * Returns if there is any word in the trie that starts with the given prefix. + * @param {string} prefix + * @return {boolean} + */ +Trie.prototype.startsWith = function(prefix) { + return !!this.traverse(prefix) +}; + +/** + * Your Trie object will be instantiated and called as such: + * var obj = new Trie() + * obj.insert(word) + * var param_2 = obj.search(word) + * var param_3 = obj.startsWith(prefix) + */ + +Trie.prototype.traverse = function(word) { + let curr = this.root + for (let i = 0; i < word.length; i++) { + if (!curr) return null + curr = curr[word[i]] + } + return curr +} + diff --git a/2080-range-frequency-queries.js b/2080.range-frequency-queries.js similarity index 100% rename from 2080-range-frequency-queries.js rename to 2080.range-frequency-queries.js diff --git a/2081-sum-of-k-mirror-numbers.js b/2081.sum-of-k-mirror-numbers.js similarity index 100% rename from 2081-sum-of-k-mirror-numbers.js rename to 2081.sum-of-k-mirror-numbers.js diff --git a/2083-substrings-that-begin-and-end-with-the-same-letter.js b/2083.substrings-that-begin-and-end-with-the-same-letter.js similarity index 100% rename from 2083-substrings-that-begin-and-end-with-the-same-letter.js rename to 2083.substrings-that-begin-and-end-with-the-same-letter.js diff --git a/2086-minimum-number-of-buckets-required-to-collect-rainwater-from-houses.js b/2086.minimum-number-of-buckets-required-to-collect-rainwater-from-houses.js similarity index 100% rename from 2086-minimum-number-of-buckets-required-to-collect-rainwater-from-houses.js rename to 2086.minimum-number-of-buckets-required-to-collect-rainwater-from-houses.js diff --git a/2088-count-fertile-pyramids-in-a-land.js b/2088.count-fertile-pyramids-in-a-land.js similarity index 100% rename from 2088-count-fertile-pyramids-in-a-land.js rename to 2088.count-fertile-pyramids-in-a-land.js diff --git a/2089-find-target-indices-after-sorting-array.js b/2089.find-target-indices-after-sorting-array.js similarity index 100% rename from 2089-find-target-indices-after-sorting-array.js rename to 2089.find-target-indices-after-sorting-array.js diff --git a/209-minimum-size-subarray-sum.js b/209.minimum-size-subarray-sum.js similarity index 100% rename from 209-minimum-size-subarray-sum.js rename to 209.minimum-size-subarray-sum.js diff --git a/2090-k-radius-subarray-averages.js b/2090.k-radius-subarray-averages.js similarity index 100% rename from 2090-k-radius-subarray-averages.js rename to 2090.k-radius-subarray-averages.js diff --git a/2091-removing-minimum-and-maximum-from-array.js b/2091.removing-minimum-and-maximum-from-array.js similarity index 100% rename from 2091-removing-minimum-and-maximum-from-array.js rename to 2091.removing-minimum-and-maximum-from-array.js diff --git a/2092-find-all-people-with-secret.js b/2092-find-all-people-with-secret.js deleted file mode 100644 index fc592271..00000000 --- a/2092-find-all-people-with-secret.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} meetings - * @param {number} firstPerson - * @return {number[]} - */ -const findAllPeople = function(n, meetings, firstPerson) { - meetings.sort((a, b) => a[2] - b[2]) - const uf = new UnionFind(n); - uf.connect(0, firstPerson); - let ppl = []; - for (let i = 0, len = meetings.length; i < len; ) { - ppl = []; - let time = meetings[i][2]; - while (i < len && meetings[i][2] === time) { - uf.connect(meetings[i][0], meetings[i][1]); - ppl.push(meetings[i][0]); - ppl.push(meetings[i][1]); - i++ - } - for (let n of ppl) { - if (!uf.connected(0, n)) uf.reset(n); - } - } - let ans = []; - for (let i = 0; i < n; ++i) { - if (uf.connected(0, i)) ans.push(i); - } - return ans; -}; - -class UnionFind { - constructor(n) { - this.arr = Array(n).fill(null) - this.arr.forEach((e, i, arr) => arr[i] = i) - } - connect(a, b) { - this.arr[this.find(a)] = this.find(this.arr[b]) - } - find(a) { - return this.arr[a] === a ? a : (this.arr[a] = this.find(this.arr[a])) - } - connected(a, b) { - return this.find(a) === this.find(b) - } - reset(a) { - this.arr[a] = a - } -} - -// another - -/** - * @param {number} n - * @param {number[][]} meetings - * @param {number} firstPerson - * @return {number[]} - */ -const findAllPeople = function(n, meetings, firstPerson) { - meetings.sort((a, b) => a[2] - b[2]) - const shared = new Set([0, firstPerson]) - - let start = new Set(), links = {} - for(let i = 0, len = meetings.length; i < len; i++) { - const [x,y,t] = meetings[i] - if(i > 0 && t !== meetings[i - 1][2]) { - bfs(start, links) - start = new Set() - links = {} - } - if(shared.has(x)) start.add(x) - if(shared.has(y)) start.add(y) - if(links[x] == null) links[x] = [] - if(links[y] == null) links[y] = [] - links[x].push(y) - links[y].push(x) - } - - bfs(start, links) - return Array.from(shared) - - function bfs(start, links) { - const visited = new Set() - while(start.size) { - const it = start[Symbol.iterator]() - const cur = it.next().value - start.delete(cur) - visited.add(cur) - shared.add(cur) - for(let e of (links[cur] || [])) { - if(!visited.has(e)) start.add(e) - } - } - } -}; diff --git a/2092.find-all-people-with-secret.js b/2092.find-all-people-with-secret.js new file mode 100644 index 00000000..c62d3ab0 --- /dev/null +++ b/2092.find-all-people-with-secret.js @@ -0,0 +1,50 @@ +/** + * @param {number} n + * @param {number[][]} meetings + * @param {number} firstPerson + * @return {number[]} + */ +const findAllPeople = function(n, meetings, firstPerson) { + meetings.sort((a, b) => a[2] - b[2]) + const uf = new UnionFind(n); + uf.connect(0, firstPerson); + let ppl = []; + for (let i = 0, len = meetings.length; i < len; ) { + ppl = []; + let time = meetings[i][2]; + while (i < len && meetings[i][2] === time) { + uf.connect(meetings[i][0], meetings[i][1]); + ppl.push(meetings[i][0]); + ppl.push(meetings[i][1]); + i++ + } + for (let n of ppl) { + if (!uf.connected(0, n)) uf.reset(n); + } + } + let ans = []; + for (let i = 0; i < n; ++i) { + if (uf.connected(0, i)) ans.push(i); + } + return ans; +}; + +class UnionFind { + constructor(n) { + this.arr = Array(n).fill(null) + this.arr.forEach((e, i, arr) => arr[i] = i) + } + connect(a, b) { + this.arr[this.find(a)] = this.find(this.arr[b]) + } + find(a) { + return this.arr[a] === a ? a : (this.arr[a] = this.find(this.arr[a])) + } + connected(a, b) { + return this.find(a) === this.find(b) + } + reset(a) { + this.arr[a] = a + } +} + diff --git a/2094-finding-3-digit-even-numbers.js b/2094.finding-3-digit-even-numbers.js similarity index 100% rename from 2094-finding-3-digit-even-numbers.js rename to 2094.finding-3-digit-even-numbers.js diff --git a/2095-delete-the-middle-node-of-a-linked-list.js b/2095.delete-the-middle-node-of-a-linked-list.js similarity index 100% rename from 2095-delete-the-middle-node-of-a-linked-list.js rename to 2095.delete-the-middle-node-of-a-linked-list.js diff --git a/2096-step-by-step-directions-from-a-binary-tree-node-to-another.js b/2096.step-by-step-directions-from-a-binary-tree-node-to-another.js similarity index 100% rename from 2096-step-by-step-directions-from-a-binary-tree-node-to-another.js rename to 2096.step-by-step-directions-from-a-binary-tree-node-to-another.js diff --git a/2097-valid-arrangement-of-pairs.js b/2097.valid-arrangement-of-pairs.js similarity index 100% rename from 2097-valid-arrangement-of-pairs.js rename to 2097.valid-arrangement-of-pairs.js diff --git a/2098-subsequence-of-size-k-with-the-largest-even-sum.js b/2098.subsequence-of-size-k-with-the-largest-even-sum.js similarity index 100% rename from 2098-subsequence-of-size-k-with-the-largest-even-sum.js rename to 2098.subsequence-of-size-k-with-the-largest-even-sum.js diff --git a/21-merge-two-sorted-lists.js b/21-merge-two-sorted-lists.js deleted file mode 100755 index 3d094664..00000000 --- a/21-merge-two-sorted-lists.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} l1 - * @param {ListNode} l2 - * @return {ListNode} - */ - -const mergeTwoLists = function(l1, l2) { - if (l1 === null) return l2; - if (l2 === null) return l1; - if (l1.val < l2.val) { - l1.next = mergeTwoLists(l1.next, l2); - return l1; - } else { - l2.next = mergeTwoLists(l1, l2.next); - return l2; - } -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} l1 - * @param {ListNode} l2 - * @return {ListNode} - */ -const mergeTwoLists = function(l1, l2) { - const dummy = new ListNode() - let cur = dummy - while(l1 && l2) { - if(l1.val < l2.val) { - cur.next = new ListNode(l1.val) - l1 = l1.next - } else { - cur.next = new ListNode(l2.val) - l2 = l2.next - } - - cur = cur.next - } - if(l1) cur.next = l1 - if(l2) cur.next = l2 - - return dummy.next -}; diff --git a/21.merge-two-sorted-lists.js b/21.merge-two-sorted-lists.js new file mode 100644 index 00000000..c75fabf1 --- /dev/null +++ b/21.merge-two-sorted-lists.js @@ -0,0 +1,25 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} l1 + * @param {ListNode} l2 + * @return {ListNode} + */ + +const mergeTwoLists = function(l1, l2) { + if (l1 === null) return l2; + if (l2 === null) return l1; + if (l1.val < l2.val) { + l1.next = mergeTwoLists(l1.next, l2); + return l1; + } else { + l2.next = mergeTwoLists(l1, l2.next); + return l2; + } +}; + diff --git a/210-course-schedule-ii.js b/210-course-schedule-ii.js deleted file mode 100644 index 350c4d33..00000000 --- a/210-course-schedule-ii.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @return {number[]} - */ -const findOrder = function(numCourses, prerequisites) { - const graph = {}, inDegree = Array(numCourses).fill(0) - for(const [s, e] of prerequisites) { - inDegree[s]++ - if(graph[e] == null) graph[e] = [] - graph[e].push(s) - } - - const res = [] - let q = [] - for(let i = 0; i < numCourses; i++) { - if(inDegree[i] === 0) q.push(i) - } - - while(q.length) { - const nxt = [] - for(let i = 0; i < q.length; i++) { - const cur = q[i] - res.push(cur) - for(const e of (graph[cur] || [])) { - inDegree[e]-- - if(inDegree[e] === 0) nxt.push(e) - } - } - q = nxt - } - - return res.length === numCourses ? res : [] -} - -// another - -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @return {number[]} - */ -const findOrder = function(numCourses, prerequisites) { - const indegree = new Array(numCourses).fill(0) - const graph = {} - for (let [course, prereq] of prerequisites) { - indegree[course]++ - graph[prereq] === undefined - ? (graph[prereq] = [course]) - : graph[prereq].push(course) - } - const queue = [], - ans = [] - for (let i = 0; i < indegree.length; i++) if (!indegree[i]) queue.push(i) - while (queue.length) { - let cur = queue.shift() - ans.push(cur) - for (let neigbhors of graph[cur] || []) { - if (!--indegree[neigbhors]) queue.push(neigbhors) - } - } - return ans.length === numCourses ? ans : [] -} - -// another - -/** - * @param {number} numCourses - * @param {number[][]} prerequisites - * @return {number[]} - */ -const findOrder = function(numCourses, prerequisites) { - const seen = new Set() - const seeing = new Set() - const res = [] - - const adj = [...Array(numCourses)].map(r => []) - for (let [u, v] of prerequisites) { - adj[v].push(u) - } - for (let c = 0; c < numCourses; c++) { - if (!dfs(c)) { - return [] - } - } - return res.reverse() - - function dfs(v) { - if (seen.has(v)) { - return true - } - if (seeing.has(v)) { - return false - } - seeing.add(v) - for (let nv of adj[v]) { - if (!dfs(nv)) { - return false - } - } - seeing.delete(v) - seen.add(v) - res.push(v) - return true - } -} diff --git a/210.course-schedule-ii.js b/210.course-schedule-ii.js new file mode 100644 index 00000000..d9f257c9 --- /dev/null +++ b/210.course-schedule-ii.js @@ -0,0 +1,35 @@ +/** + * @param {number} numCourses + * @param {number[][]} prerequisites + * @return {number[]} + */ +const findOrder = function(numCourses, prerequisites) { + const graph = {}, inDegree = Array(numCourses).fill(0) + for(const [s, e] of prerequisites) { + inDegree[s]++ + if(graph[e] == null) graph[e] = [] + graph[e].push(s) + } + + const res = [] + let q = [] + for(let i = 0; i < numCourses; i++) { + if(inDegree[i] === 0) q.push(i) + } + + while(q.length) { + const nxt = [] + for(let i = 0; i < q.length; i++) { + const cur = q[i] + res.push(cur) + for(const e of (graph[cur] || [])) { + inDegree[e]-- + if(inDegree[e] === 0) nxt.push(e) + } + } + q = nxt + } + + return res.length === numCourses ? res : [] +} + diff --git a/2100-find-good-days-to-rob-the-bank.js b/2100.find-good-days-to-rob-the-bank.js similarity index 100% rename from 2100-find-good-days-to-rob-the-bank.js rename to 2100.find-good-days-to-rob-the-bank.js diff --git a/2101-detonate-the-maximum-bombs.js b/2101-detonate-the-maximum-bombs.js deleted file mode 100644 index 7abf5737..00000000 --- a/2101-detonate-the-maximum-bombs.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @param {number[][]} bombs - * @return {number} - */ - const maximumDetonation = function(bombs) { - let n = bombs.length, res = 1, graph = {} - for(let i = 0; i < n; i++) { - for(let j = 0; j < n; j++) { - if (i === j) continue - if (bombAdj(bombs[i], bombs[j])) { - if (graph[i] == null) graph[i] = [] - graph[i].push(j) - } - } - } - function dfs(node, visited) { - for(const next of (graph[node] || [])) { - if(!visited.has(next)) { - visited.add(next) - dfs(next, visited) - } - } - } - for (let i = 0; i < n; i++) { - const set = new Set([i]) - dfs(i, set) - res = Math.max(res, set.size) - } - - return res -}; - -function bombAdj(source, target) { - const [x1, y1, r1] = source - const [x2, y2] = target - const { abs } = Math - return abs(x1 - x2) ** 2 + abs(y1 - y2) ** 2 <= r1 ** 2 -} - -// another - -/** - * @param {number[][]} bombs - * @return {number} - */ -const maximumDetonation = function(bombs) { - const n = bombs.length, graph = {} - for(let i = 0; i < n; i++) { - for(let j = 0; j < n; j++) { - if(i === j) continue - if(adjValid(bombs[i], bombs[j])) { - if(graph[i] == null) graph[i] = [] - graph[i].push(j) - } - } - } - - let res = 0 - for(let i = 0; i < n; i++) { - const set = new Set([i]) - dfs(i, set) - res = Math.max(res, set.size) - } - return res - - function dfs(node, visited){ - for (const e of (graph[node] || [])) { - if(!visited.has(e)) { - visited.add(e) - dfs(e, visited) - } - } - } - - function adjValid(start, target) { - const [sx, sy, r] = start - const [ex, ey] = target - return Math.abs(sx - ex) ** 2 + Math.abs(sy - ey) ** 2 <= r ** 2 - } -}; - - diff --git a/2101.detonate-the-maximum-bombs.js b/2101.detonate-the-maximum-bombs.js new file mode 100644 index 00000000..f70a41df --- /dev/null +++ b/2101.detonate-the-maximum-bombs.js @@ -0,0 +1,39 @@ +/** + * @param {number[][]} bombs + * @return {number} + */ + const maximumDetonation = function(bombs) { + let n = bombs.length, res = 1, graph = {} + for(let i = 0; i < n; i++) { + for(let j = 0; j < n; j++) { + if (i === j) continue + if (bombAdj(bombs[i], bombs[j])) { + if (graph[i] == null) graph[i] = [] + graph[i].push(j) + } + } + } + function dfs(node, visited) { + for(const next of (graph[node] || [])) { + if(!visited.has(next)) { + visited.add(next) + dfs(next, visited) + } + } + } + for (let i = 0; i < n; i++) { + const set = new Set([i]) + dfs(i, set) + res = Math.max(res, set.size) + } + + return res +}; + +function bombAdj(source, target) { + const [x1, y1, r1] = source + const [x2, y2] = target + const { abs } = Math + return abs(x1 - x2) ** 2 + abs(y1 - y2) ** 2 <= r1 ** 2 +} + diff --git a/2102-sequentially-ordinal-rank-tracker.js b/2102-sequentially-ordinal-rank-tracker.js deleted file mode 100644 index 3e2f8c83..00000000 --- a/2102-sequentially-ordinal-rank-tracker.js +++ /dev/null @@ -1,334 +0,0 @@ -const maxFn = (a, b) => a.score === b.score ? a.name < b.name : a.score > b.score -const minFn = (a, b) => a.score === b.score ? a.name > b.name : a.score < b.score -const SORTracker = function() { - this.maxPQ = new PQ(maxFn) - this.minPQ = new PQ(minFn) - this.idx = 0 -}; - -/** - * @param {string} name - * @param {number} score - * @return {void} - */ -SORTracker.prototype.add = function(name, score) { - this.maxPQ.push({name, score}) -}; - -/** - * @return {string} - */ -SORTracker.prototype.get = function() { - if(this.idx) { - this.minPQ.push(this.maxPQ.pop()) - while(maxFn(this.maxPQ.peek(), this.minPQ.peek())) { - const tmp = this.minPQ.pop() - this.minPQ.push(this.maxPQ.pop()) - this.maxPQ.push(tmp) - } - } - this.idx++ - return this.maxPQ.peek().name -}; - -/** - * Your SORTracker object will be instantiated and called as such: - * var obj = new SORTracker() - * obj.add(name,score) - * var param_2 = obj.get() - */ - -class PQ { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -const maxComp = (a, b) => { - return a[1] === b[1] ? b[0].localeCompare(a[0]) > 0 : a[1] > b[1] -} - -const minComp = (a, b) => { - return a[1] === b[1] ? a[0].localeCompare(b[0]) > 0: a[1] < b[1] -} - -const SORTracker = function() { - // max - this.pq = new PriorityQueue(maxComp) - // min - this.best = new PriorityQueue(minComp) -}; - -/** - * @param {string} name - * @param {number} score - * @return {void} - */ -SORTracker.prototype.add = function(name, score) { - this.pq.push([name, score]) - while(!this.best.isEmpty() && maxComp(this.pq.peek(), this.best.peek())) { - const a = this.best.pop(), b = this.pq.pop() - this.best.push(b) - this.pq.push(a) - } -}; - -/** - * @return {string} - */ -SORTracker.prototype.get = function() { - const tmp = this.pq.pop() - this.best.push(tmp) - return tmp[0] -}; - -/** - * Your SORTracker object will be instantiated and called as such: - * var obj = new SORTracker() - * obj.add(name,score) - * var param_2 = obj.get() - */ - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - - -// another - -const SORTracker = function() { - this.maxCmp = (a, b) => a[1] === b[1] ? a[0] < b[0] : a[1] > b[1] - this.minCmp = (a, b) => a[1] === b[1] ? a[0] > b[0] : a[1] < b[1] - this.maxQ = new PriorityQueue(this.maxCmp) - this.minQ = new PriorityQueue(this.minCmp) - this.cnt = 0 -}; - -/** - * @param {string} name - * @param {number} score - * @return {void} - */ -SORTracker.prototype.add = function(name, score) { - this.maxQ.push([name, score]) -}; - -/** - * @return {string} - */ -SORTracker.prototype.get = function() { - if(this.cnt) { - this.minQ.push(this.maxQ.pop()) - while(this.maxCmp(this.maxQ.peek(), this.minQ.peek())) { - const tmp = this.minQ.pop() - this.minQ.push(this.maxQ.pop()) - this.maxQ.push(tmp) - } - } - this.cnt++ - - return this.maxQ.peek()[0] -}; - -/** - * Your SORTracker object will be instantiated and called as such: - * var obj = new SORTracker() - * obj.add(name,score) - * var param_2 = obj.get() - */ - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/2102.sequentially-ordinal-rank-tracker.js b/2102.sequentially-ordinal-rank-tracker.js new file mode 100644 index 00000000..01e7cee3 --- /dev/null +++ b/2102.sequentially-ordinal-rank-tracker.js @@ -0,0 +1,108 @@ +const maxFn = (a, b) => a.score === b.score ? a.name < b.name : a.score > b.score +const minFn = (a, b) => a.score === b.score ? a.name > b.name : a.score < b.score +const SORTracker = function() { + this.maxPQ = new PQ(maxFn) + this.minPQ = new PQ(minFn) + this.idx = 0 +}; + +/** + * @param {string} name + * @param {number} score + * @return {void} + */ +SORTracker.prototype.add = function(name, score) { + this.maxPQ.push({name, score}) +}; + +/** + * @return {string} + */ +SORTracker.prototype.get = function() { + if(this.idx) { + this.minPQ.push(this.maxPQ.pop()) + while(maxFn(this.maxPQ.peek(), this.minPQ.peek())) { + const tmp = this.minPQ.pop() + this.minPQ.push(this.maxPQ.pop()) + this.maxPQ.push(tmp) + } + } + this.idx++ + return this.maxPQ.peek().name +}; + +/** + * Your SORTracker object will be instantiated and called as such: + * var obj = new SORTracker() + * obj.add(name,score) + * var param_2 = obj.get() + */ + +class PQ { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + diff --git a/2103-rings-and-rods.js b/2103.rings-and-rods.js similarity index 100% rename from 2103-rings-and-rods.js rename to 2103.rings-and-rods.js diff --git a/2104-sum-of-subarray-ranges.js b/2104-sum-of-subarray-ranges.js deleted file mode 100644 index 2feb3f2e..00000000 --- a/2104-sum-of-subarray-ranges.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const subArrayRanges = function(nums) { - const n = nums.length, { max, min } = Math - let res = 0 - - for(let i = 0; i < n; i++) { - let [most, least] = [-Infinity, Infinity] - for(let j = i; j < n; j++) { - most = max(most, nums[j]) - least = min(least, nums[j]) - res += most - least - } - } - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const subArrayRanges = function(nums) { - let res = 0, n = nums.length - for(let i = 0; i < n; i++) { - let max = nums[i], min = nums[i] - for(let j = i; j < n; j++) { - max = Math.max(max, nums[j]) - min = Math.min(min, nums[j]) - res += max - min - } - } - return res -}; diff --git a/2104.sum-of-subarray-ranges.js b/2104.sum-of-subarray-ranges.js new file mode 100644 index 00000000..bd22db1e --- /dev/null +++ b/2104.sum-of-subarray-ranges.js @@ -0,0 +1,19 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const subArrayRanges = function(nums) { + const n = nums.length, { max, min } = Math + let res = 0 + + for(let i = 0; i < n; i++) { + let [most, least] = [-Infinity, Infinity] + for(let j = i; j < n; j++) { + most = max(most, nums[j]) + least = min(least, nums[j]) + res += most - least + } + } + return res +}; + diff --git a/2105-watering-plants-ii.js b/2105.watering-plants-ii.js similarity index 100% rename from 2105-watering-plants-ii.js rename to 2105.watering-plants-ii.js diff --git a/2106-maximum-fruits-harvested-after-at-most-k-steps.js b/2106.maximum-fruits-harvested-after-at-most-k-steps.js similarity index 100% rename from 2106-maximum-fruits-harvested-after-at-most-k-steps.js rename to 2106.maximum-fruits-harvested-after-at-most-k-steps.js diff --git a/211-add-and-search-word-data-structure-design.js b/211.add-and-search-word-data-structure-design.js similarity index 100% rename from 211-add-and-search-word-data-structure-design.js rename to 211.add-and-search-word-data-structure-design.js diff --git a/2111-minimum-operations-to-make-the-array-k-increasing.js b/2111-minimum-operations-to-make-the-array-k-increasing.js deleted file mode 100644 index 821bceef..00000000 --- a/2111-minimum-operations-to-make-the-array-k-increasing.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @param {number[]} arr - * @param {number} k - * @return {number} - */ -const kIncreasing = function(arr, k) { - let res = 0, matrix = Array.from({ length: k }, () => []), n = arr.length - for(let i = 0; i < k; i++) { - for(let j = i; j < n; j += k) { - matrix[i].push(arr[j]) - } - } - - for (let i = 0; i < k; i++) { - res += matrix[i].length - nonDecreasing(matrix[i]) - } - - return res - - function bisect_right(ar, x, l = 0, r) { - if(r == null) r = ar.length - while(l < r) { - const mid = ~~((l + r) / 2) - if(ar[mid] <= x) l = mid + 1 - else r = mid - } - return l - } - - function nonDecreasing(ar) { - let stk = [] - for(let e of ar) { - const idx = bisect_right(stk, e) - if(idx === stk.length) stk.push(e) - else stk[idx] = e - } - - return stk.length - } -}; - -// another -/** - * @param {number[]} arr - * @param {number} k - * @return {number} - */ -const kIncreasing = function(arr, k) { - const n = arr.length - const a = Array.from({ length: k }, () => Array()) - - for(let i = 0; i < k; i++) { - for(let j = i; j < n; j += k) { - a[i].push(arr[j]) - } - } - - let res = 0 - for(let i = 0; i < a.length; i++) { - const r = a[i] - res += r.length - lis(r) - } - - return res - - function bisect_right(a, x, lo = 0, hi = null) { // > upper_bound - if (lo < 0) throw new Error('lo must be non-negative'); - if (hi == null) hi = a.length; - while (lo < hi) { - let mid = parseInt((lo + hi) / 2); - x < a[mid] ? hi = mid : lo = mid + 1; - } - return lo; - } - - function lis(ar) { - let q = [] - for (let x of ar) { - let i = bisect_right(q, x) - if (i == q.length) q.push(x) - else q[i] = x - } - - return q.length - } -}; - diff --git a/2111.minimum-operations-to-make-the-array-k-increasing.js b/2111.minimum-operations-to-make-the-array-k-increasing.js new file mode 100644 index 00000000..0c3a2c05 --- /dev/null +++ b/2111.minimum-operations-to-make-the-array-k-increasing.js @@ -0,0 +1,41 @@ +/** + * @param {number[]} arr + * @param {number} k + * @return {number} + */ +const kIncreasing = function(arr, k) { + let res = 0, matrix = Array.from({ length: k }, () => []), n = arr.length + for(let i = 0; i < k; i++) { + for(let j = i; j < n; j += k) { + matrix[i].push(arr[j]) + } + } + + for (let i = 0; i < k; i++) { + res += matrix[i].length - nonDecreasing(matrix[i]) + } + + return res + + function bisect_right(ar, x, l = 0, r) { + if(r == null) r = ar.length + while(l < r) { + const mid = ~~((l + r) / 2) + if(ar[mid] <= x) l = mid + 1 + else r = mid + } + return l + } + + function nonDecreasing(ar) { + let stk = [] + for(let e of ar) { + const idx = bisect_right(stk, e) + if(idx === stk.length) stk.push(e) + else stk[idx] = e + } + + return stk.length + } +}; + diff --git a/2115-find-all-possible-recipes-from-given-supplies.js b/2115-find-all-possible-recipes-from-given-supplies.js deleted file mode 100644 index 856512dd..00000000 --- a/2115-find-all-possible-recipes-from-given-supplies.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @param {string[]} recipes - * @param {string[][]} ingredients - * @param {string[]} supplies - * @return {string[]} - */ -const findAllRecipes = function(recipes, ingredients, supplies) { - const set = new Set(supplies), res = [], graph = {}, n = recipes.length - const inDegree = {} - for(let x of recipes) inDegree[x] = 0 - for(let i = 0; i < n; i++) { - for(let j = 0; j < ingredients[i].length; j++) { - const ing = ingredients[i][j] - if(!set.has(ing)) { - if (graph[ing] == null) graph[ing] = [] - graph[ing].push(recipes[i]) - inDegree[recipes[i]]++ - } - } - } - // Kahn's Algorithm - const q = [] - for(let x in inDegree) { - if (inDegree[x] === 0) q.push(x) - } - while(q.length) { - const len = q.length - for(let i = 0; i < len; i++) { - const cur = q.pop() - res.push(cur) - for(let next of (graph[cur] || [])) { - inDegree[next]-- - if(inDegree[next] === 0) { - q.push(next) - } - } - } - } - return res -}; - -// another - -/** - * @param {string[]} recipes - * @param {string[][]} ingredients - * @param {string[]} supplies - * @return {string[]} - */ -const findAllRecipes = function(recipes, ingredients, supplies) { - const graph = {} - const n = recipes.length - - const inDegree = {} - supplies = new Set(supplies) - for(const e of recipes) inDegree[e] = 0 - - let q = [] - for(let i = 0; i < n; i++) { - const rec = recipes[i] - for(let e of ingredients[i]) { - if(!supplies.has(e)) { - if(graph[e] == null) graph[e] = [] - graph[e].push(rec) - inDegree[rec]++ - } - } - } - // console.log(inDegree) - for(let i = 0; i < n; i++) { - if(inDegree[recipes[i]] === 0) { - q.push(recipes[i]) - } - } - - // console.log(q) - const res = [] - while(q.length) { - const size = q.length - const nxt = [] - - for(let i = 0; i < size; i++) { - const cur = q[i] - res.push(cur) - for(const e of (graph[cur] || [])) { - inDegree[e]-- - if(inDegree[e] === 0) nxt.push(e) - } - } - - q = nxt - } - - return res -}; diff --git a/2115.find-all-possible-recipes-from-given-supplies.js b/2115.find-all-possible-recipes-from-given-supplies.js new file mode 100644 index 00000000..c425ceb7 --- /dev/null +++ b/2115.find-all-possible-recipes-from-given-supplies.js @@ -0,0 +1,41 @@ +/** + * @param {string[]} recipes + * @param {string[][]} ingredients + * @param {string[]} supplies + * @return {string[]} + */ +const findAllRecipes = function(recipes, ingredients, supplies) { + const set = new Set(supplies), res = [], graph = {}, n = recipes.length + const inDegree = {} + for(let x of recipes) inDegree[x] = 0 + for(let i = 0; i < n; i++) { + for(let j = 0; j < ingredients[i].length; j++) { + const ing = ingredients[i][j] + if(!set.has(ing)) { + if (graph[ing] == null) graph[ing] = [] + graph[ing].push(recipes[i]) + inDegree[recipes[i]]++ + } + } + } + // Kahn's Algorithm + const q = [] + for(let x in inDegree) { + if (inDegree[x] === 0) q.push(x) + } + while(q.length) { + const len = q.length + for(let i = 0; i < len; i++) { + const cur = q.pop() + res.push(cur) + for(let next of (graph[cur] || [])) { + inDegree[next]-- + if(inDegree[next] === 0) { + q.push(next) + } + } + } + } + return res +}; + diff --git a/2116-check-if-a-parentheses-string-can-be-validcheck-if-a-parentheses-string-can-be-valid.js b/2116-check-if-a-parentheses-string-can-be-validcheck-if-a-parentheses-string-can-be-valid.js deleted file mode 100644 index 9c654fd1..00000000 --- a/2116-check-if-a-parentheses-string-can-be-validcheck-if-a-parentheses-string-can-be-valid.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @param {string} s - * @param {string} locked - * @return {boolean} - */ -const canBeValid = function(s, locked) { - const n = s.length - if(n % 2 === 1) return false - let x = 0 - for(let i = 0; i < n; i++) { - if(s[i] === '(' || locked[i] === '0') x++ - else if(x > 0) x-- - else return false - } - x = 0 - for(let i = n - 1; i >= 0; i--) { - if(s[i] === ')' || locked[i] === '0') x++ - else if(x > 0) x-- - else return false - } - return true -}; - -// another - -/** - * @param {string} s - * @param {string} locked - * @return {boolean} - */ -const canBeValid = function (s, locked) { - return s.length % 2 === 0 && chk(s, locked, '(') && chk(s, locked, ')') - - function chk(s, locked, op) { - let bal = 0, - wild = 0, - sz = s.length - let start = op === '(' ? 0 : sz - 1, - dir = op === '(' ? 1 : -1 - for (let i = start; i >= 0 && i < sz && wild + bal >= 0; i += dir) { - if (locked[i] === '1') bal += s[i] === op ? 1 : -1 - else wild++ - } - return Math.abs(bal) <= wild - } -} diff --git a/2116.check-if-a-parentheses-string-can-be-validcheck-if-a-parentheses-string-can-be-valid.js b/2116.check-if-a-parentheses-string-can-be-validcheck-if-a-parentheses-string-can-be-valid.js new file mode 100644 index 00000000..11c03073 --- /dev/null +++ b/2116.check-if-a-parentheses-string-can-be-validcheck-if-a-parentheses-string-can-be-valid.js @@ -0,0 +1,23 @@ +/** + * @param {string} s + * @param {string} locked + * @return {boolean} + */ +const canBeValid = function(s, locked) { + const n = s.length + if(n % 2 === 1) return false + let x = 0 + for(let i = 0; i < n; i++) { + if(s[i] === '(' || locked[i] === '0') x++ + else if(x > 0) x-- + else return false + } + x = 0 + for(let i = n - 1; i >= 0; i--) { + if(s[i] === ')' || locked[i] === '0') x++ + else if(x > 0) x-- + else return false + } + return true +}; + diff --git a/2119-a-number-after-a-double-reversal.js b/2119.a-number-after-a-double-reversal.js similarity index 100% rename from 2119-a-number-after-a-double-reversal.js rename to 2119.a-number-after-a-double-reversal.js diff --git a/212-word-search-ii.js b/212.word-search-ii.js similarity index 100% rename from 212-word-search-ii.js rename to 212.word-search-ii.js diff --git a/2121-intervals-between-identical-elements.js b/2121.intervals-between-identical-elements.js similarity index 100% rename from 2121-intervals-between-identical-elements.js rename to 2121.intervals-between-identical-elements.js diff --git a/2122-recover-the-original-array.js b/2122.recover-the-original-array.js similarity index 100% rename from 2122-recover-the-original-array.js rename to 2122.recover-the-original-array.js diff --git a/2124-check-if-all-as-appears-before-all-bs.js b/2124.check-if-all-as-appears-before-all-bs.js similarity index 100% rename from 2124-check-if-all-as-appears-before-all-bs.js rename to 2124.check-if-all-as-appears-before-all-bs.js diff --git a/2125-number-of-laser-beams-in-a-bank.js b/2125.number-of-laser-beams-in-a-bank.js similarity index 100% rename from 2125-number-of-laser-beams-in-a-bank.js rename to 2125.number-of-laser-beams-in-a-bank.js diff --git a/2126-destroying-asteroids.js b/2126.destroying-asteroids.js similarity index 100% rename from 2126-destroying-asteroids.js rename to 2126.destroying-asteroids.js diff --git a/2127-maximum-employees-to-be-invited-to-a-meeting.js b/2127-maximum-employees-to-be-invited-to-a-meeting.js deleted file mode 100644 index 8a8efe69..00000000 --- a/2127-maximum-employees-to-be-invited-to-a-meeting.js +++ /dev/null @@ -1,162 +0,0 @@ -/** - * @param {number[]} favorite - * @return {number} - */ -const maximumInvitations = function(favorite) { - const n = favorite.length - const inDegree = Array(n).fill(0) - const { max } = Math - for(let i = 0; i < n; i++) { - inDegree[favorite[i]]++ - } - - let q = [] - const visited = Array(n).fill(0) - const depth = Array(n).fill(1) - for(let i = 0; i < n; i++) { - if(inDegree[i] === 0) { - q.push(i) - visited[i] = 1 - depth[i] = 1 - } - } - - while(q.length) { - const cur = q.pop() - const nxt = favorite[cur] - inDegree[nxt]-- - if(inDegree[nxt] === 0) { - q.push(nxt) - visited[nxt] = 1 - } - depth[nxt] = max(depth[nxt], depth[cur] + 1) - } - - let maxLoopSize = 0 - let twoNodesSize = 0 - - for(let i = 0; i < n; i++) { - if(visited[i] === 1) continue - let j = i - let cnt = 0 - while(visited[j] === 0) { - cnt++ - visited[j] = 1 - j = favorite[j] - } - - if(cnt > 2) { - maxLoopSize = max(maxLoopSize, cnt) - } else if(cnt === 2) { - twoNodesSize += depth[i] + depth[favorite[i]] - } - } - - return max(maxLoopSize, twoNodesSize) -}; - -// another - -/** - * @param {number[]} favorite - * @return {number} - */ -const maximumInvitations = function (favorite) { - const n = favorite.length - const indegree = Array(n).fill(0) - for (let i = 0; i < n; i++) indegree[favorite[i]]++ - const { max } = Math - let q = [] - const visited = Array(n).fill(0) - const depth = Array(n).fill(1) - for (let i = 0; i < n; i++) { - if (indegree[i] === 0) { - depth[i] = 1 - visited[i] = 1 - q.push(i) - } - } - - while (q.length) { - const cur = q.shift() - const nxt = favorite[cur] - indegree[nxt]-- - if (indegree[nxt] == 0) { - q.push(nxt) - visited[nxt] = 1 - } - depth[nxt] = depth[cur] + 1 - } - - let max_circle_size = 0 - let max_link_size = 0 - for (let i = 0; i < n; i++) { - if (visited[i] === 1) continue - let j = i - let count = 0 - while (visited[j] == 0) { - count++ - visited[j] = 1 - j = favorite[j] - } - if (count > 2) max_circle_size = max(max_circle_size, count) - else if (count == 2) max_link_size += depth[i] + depth[favorite[i]] - } - - return max(max_circle_size, max_link_size) -} - -// another - -/** - * @param {number[]} favorite - * @return {number} - */ -var maximumInvitations = function(favorite) { - const n = favorite.length, m = Array(n).fill(-1), r = Array.from({ length: n }, () => []) - for(let i = 0; i < n; i++) r[favorite[i]].push(i) - - function dfs(u) { - if(m[u] !== -1) return m[u] - let res = 0 - for(let v of r[u]) res = Math.max(res, dfs(v)) - return m[u] = 1 + res - } - let res = 0, free = 0 - for(let i = 0; i < n; ++i) { - if (m[i] != -1) continue; // skip visited nodes - if (favorite[favorite[i]] == i) { - m[i] = m[favorite[i]] = 0; - let a = 0, b = 0; // find the length of the longest arms starting from `i` and `A[i]` - for (let v of r[i]) { - if (v == favorite[i]) continue; - a = Math.max(a, dfs(v)); - } - for (let v of r[favorite[i]]) { - if (v == i) continue; - b = Math.max(b, dfs(v)); - } - free += a + b + 2; // this free component is of length `a+b+2` - } - } - function dfs2(u) { - if (m[u] != -1) return[u, m[u], false]; // this is the merge point - m[u] = 0; - let [mergePoint, depth, mergePointMet] = dfs2(favorite[u]); - if (mergePointMet) { // If we've met the merge point again already, this node is outside of the cycle and should be ignored. - m[u] = 0; - return [mergePoint, depth, true]; - } - m[u] = 1 + depth; // If we haven't met the merge point, we increment the depth. - return [mergePoint, m[u], u == mergePoint]; - } - - for(let i = 0; i < n; i++) { - if(m[i] !== -1) continue - let [mergePoint, depth, mergePointMet] = dfs2(i) - if(mergePointMet) res = Math.max(res, depth) - } - - return Math.max(res, free) -}; - diff --git a/2127.maximum-employees-to-be-invited-to-a-meeting.js b/2127.maximum-employees-to-be-invited-to-a-meeting.js new file mode 100644 index 00000000..1a57fc66 --- /dev/null +++ b/2127.maximum-employees-to-be-invited-to-a-meeting.js @@ -0,0 +1,57 @@ +/** + * @param {number[]} favorite + * @return {number} + */ +const maximumInvitations = function(favorite) { + const n = favorite.length + const inDegree = Array(n).fill(0) + const { max } = Math + for(let i = 0; i < n; i++) { + inDegree[favorite[i]]++ + } + + let q = [] + const visited = Array(n).fill(0) + const depth = Array(n).fill(1) + for(let i = 0; i < n; i++) { + if(inDegree[i] === 0) { + q.push(i) + visited[i] = 1 + depth[i] = 1 + } + } + + while(q.length) { + const cur = q.pop() + const nxt = favorite[cur] + inDegree[nxt]-- + if(inDegree[nxt] === 0) { + q.push(nxt) + visited[nxt] = 1 + } + depth[nxt] = max(depth[nxt], depth[cur] + 1) + } + + let maxLoopSize = 0 + let twoNodesSize = 0 + + for(let i = 0; i < n; i++) { + if(visited[i] === 1) continue + let j = i + let cnt = 0 + while(visited[j] === 0) { + cnt++ + visited[j] = 1 + j = favorite[j] + } + + if(cnt > 2) { + maxLoopSize = max(maxLoopSize, cnt) + } else if(cnt === 2) { + twoNodesSize += depth[i] + depth[favorite[i]] + } + } + + return max(maxLoopSize, twoNodesSize) +}; + diff --git a/2128-remove-all-ones-with-row-and-column-flips.js b/2128.remove-all-ones-with-row-and-column-flips.js similarity index 100% rename from 2128-remove-all-ones-with-row-and-column-flips.js rename to 2128.remove-all-ones-with-row-and-column-flips.js diff --git a/213-house-robber-ii.js b/213-house-robber-ii.js deleted file mode 100644 index c4e1037f..00000000 --- a/213-house-robber-ii.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const rob = function(nums) { - if(nums.length === 0) return 0 - if(nums.length < 3) return Math.max(...nums) - - const startFromFirst = [0,nums[0]] - const startFromSecond = [0,0] - - for(let i = 2; i <= nums.length; i++) { - startFromFirst[i] = Math.max(startFromFirst[i - 1], startFromFirst[i - 2] + nums[i - 1]) - startFromSecond[i] = Math.max(startFromSecond[i - 1], startFromSecond[i - 2] + nums[i - 1]) - } - - return Math.max(startFromFirst[nums.length - 1], startFromSecond[nums.length]) - -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const rob = function(nums) { - if(nums.length === 1) return nums[0] - return Math.max(helper(0, nums.length - 2), helper(1, nums.length - 1)) - - function helper(l, r) { - let inc = 0, exc = 0 - for(let i = l; i <= r; i++) { - const pi = inc, pe = exc - inc = exc + nums[i] - exc = Math.max(pi, pe) - } - return Math.max(inc, exc) - } -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const rob = function(nums) { - const n = nums.length - nums = nums.concat(nums) - let res = 0 - for(let i = 0; i < n; i++) { - let tmp = nums[i] - let pp = 0 - let p = 0 - for(let j = i; j < n + i - 1; j++) { - tmp = Math.max(tmp, pp + nums[j], p); - [pp, p] = [p, tmp] - } - res = Math.max(res, tmp) - } - - return res -}; diff --git a/213.house-robber-ii.js b/213.house-robber-ii.js new file mode 100644 index 00000000..3d7da157 --- /dev/null +++ b/213.house-robber-ii.js @@ -0,0 +1,20 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const rob = function(nums) { + if(nums.length === 0) return 0 + if(nums.length < 3) return Math.max(...nums) + + const startFromFirst = [0,nums[0]] + const startFromSecond = [0,0] + + for(let i = 2; i <= nums.length; i++) { + startFromFirst[i] = Math.max(startFromFirst[i - 1], startFromFirst[i - 2] + nums[i - 1]) + startFromSecond[i] = Math.max(startFromSecond[i - 1], startFromSecond[i - 2] + nums[i - 1]) + } + + return Math.max(startFromFirst[nums.length - 1], startFromSecond[nums.length]) + +}; + diff --git a/2130-maximum-twin-sum-of-a-linked-list.js b/2130-maximum-twin-sum-of-a-linked-list.js deleted file mode 100644 index b1e45990..00000000 --- a/2130-maximum-twin-sum-of-a-linked-list.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @return {number} - */ -const pairSum = function(head) { - let slow = head, fast = head - while(fast && fast.next) { - slow = slow.next - fast = fast.next.next - } - // reverse - let next = null, pre = null - while(slow) { - next = slow.next - slow.next = pre - pre = slow - slow = next - } - - let res = 0 - while(pre) { - res = Math.max(res, pre.val + head.val) - pre = pre.next - head = head.next - } - - return res -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @return {number} - */ -const pairSum = function(head) { - const arr = [] - let cur = head - - while(cur) { - arr.push(cur.val) - cur = cur.next - } - - let res = 0 - for(let i = 0, n = arr.length; i < n / 2; i++) { - res = Math.max(res, arr[i] + arr[n - 1 - i]) - } - - return res -}; diff --git a/2130.maximum-twin-sum-of-a-linked-list.js b/2130.maximum-twin-sum-of-a-linked-list.js new file mode 100644 index 00000000..a1d8198c --- /dev/null +++ b/2130.maximum-twin-sum-of-a-linked-list.js @@ -0,0 +1,36 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} head + * @return {number} + */ +const pairSum = function(head) { + let slow = head, fast = head + while(fast && fast.next) { + slow = slow.next + fast = fast.next.next + } + // reverse + let next = null, pre = null + while(slow) { + next = slow.next + slow.next = pre + pre = slow + slow = next + } + + let res = 0 + while(pre) { + res = Math.max(res, pre.val + head.val) + pre = pre.next + head = head.next + } + + return res +}; + diff --git a/2132-stamping-the-grid.js b/2132.stamping-the-grid.js similarity index 100% rename from 2132-stamping-the-grid.js rename to 2132.stamping-the-grid.js diff --git a/2136-earliest-possible-day-of-full-bloom.js b/2136-earliest-possible-day-of-full-bloom.js deleted file mode 100644 index 6a736966..00000000 --- a/2136-earliest-possible-day-of-full-bloom.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @param {number[]} plantTime - * @param {number[]} growTime - * @return {number} - */ -const earliestFullBloom = function(plantTime, growTime) { - const n = plantTime.length, arr = Array(n) - for(let i = 0; i < n; i++) { - arr.push([growTime[i], plantTime[i]]) - } - arr.sort((a, b) => b[0] - a[0]) - - let res = 0, cur = 0 - for(let i = 0; i < n; i++) { - const e = arr[i] - res = Math.max(res, cur + e[0] + e[1]) - cur += e[1] - } - - return res -}; - -// another - - -/** - * @param {number[]} plantTime - * @param {number[]} growTime - * @return {number} - */ -const earliestFullBloom = function(plantTime, growTime) { - const sum = arr => arr.reduce((ac, e) => ac +e, 0) - let l = 0, r = sum(plantTime) + sum(growTime) - const n = plantTime.length - - const a = [] - for(let i = 0; i < n; i++) { - a.push([growTime[i], plantTime[i] ]) - } - - a.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]) - a.reverse() - function chk(d) { - let total = -1 - let max_num = 0 - for(let i = 0; i < n; i++) { - total += a[i][1] - max_num = Math.max(max_num, total + a[i][0] + 1) - } - return max_num <= d - } - - while (l < r) { - let m = ~~((l + r) / 2) - if (chk(m)) r = m - else l = m + 1 - } - - return l -}; - diff --git a/2136.earliest-possible-day-of-full-bloom.js b/2136.earliest-possible-day-of-full-bloom.js new file mode 100644 index 00000000..15d50243 --- /dev/null +++ b/2136.earliest-possible-day-of-full-bloom.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} plantTime + * @param {number[]} growTime + * @return {number} + */ +const earliestFullBloom = function(plantTime, growTime) { + const n = plantTime.length, arr = Array(n) + for(let i = 0; i < n; i++) { + arr.push([growTime[i], plantTime[i]]) + } + arr.sort((a, b) => b[0] - a[0]) + + let res = 0, cur = 0 + for(let i = 0; i < n; i++) { + const e = arr[i] + res = Math.max(res, cur + e[0] + e[1]) + cur += e[1] + } + + return res +}; + diff --git a/2138-divide-a-string-into-groups-of-size-k.js b/2138.divide-a-string-into-groups-of-size-k.js similarity index 100% rename from 2138-divide-a-string-into-groups-of-size-k.js rename to 2138.divide-a-string-into-groups-of-size-k.js diff --git a/2139-minimum-moves-to-reach-target-score.js b/2139.minimum-moves-to-reach-target-score.js similarity index 100% rename from 2139-minimum-moves-to-reach-target-score.js rename to 2139.minimum-moves-to-reach-target-score.js diff --git a/214-shortest-palindrome.js b/214-shortest-palindrome.js deleted file mode 100644 index a278095f..00000000 --- a/214-shortest-palindrome.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ -const shortestPalindrome = function(s) { - let j = 0; - for (let i = s.length - 1; i >= 0; i--) { - if (s.charAt(i) === s.charAt(j)) { j += 1; } - } - if (j === s.length) { return s; } - let suffix = s.substring(j); - return suffix.split('').reverse().join('') + shortestPalindrome(s.substring(0, j)) + suffix; -}; - -// another - -/** - * @param {string} s - * @return {string} - */ -const shortestPalindrome = function (s) { - const tmp = s + '#' + s.split('').reverse().join('') - const fail = getFail(tmp) - return ( - s - .split('') - .slice(fail[fail.length - 1]) - .reverse() - .join('') + s - ) -} - -function getFail(s) { - const n = s.length - const table = new Array(n).fill(0) - let index = 0 - for (let i = 1; i < n; ) { - if (s.charAt(index) === s.charAt(i)) { - table[i] = ++index - i++ - } else { - if (index > 0) { - index = table[index - 1] - } else { - index = 0 - i++ - } - } - } - return table -} - -// another - -/** - * @param {string} s - * @return {string} - */ -const shortestPalindrome = function(s) { - const tmp = `${s}#${reverse(s)}` - const table = kmp(tmp) - return `${reverse(s.slice(table[table.length - 1]))}${s}` -}; -function reverse(str) { - return [...str].reverse().join('') -} - -function kmp(s) { - const n = s.length, table = Array(n).fill(0) - let idx = 0 - for(let i = 1; i < n; ) { - if(s[i] === s[idx]) { - idx++ - table[i] = idx - i++ - } else { - if(idx > 0) { - idx = table[idx - 1] - } else { - idx = 0 - i++ - } - } - } - return table -} diff --git a/214.shortest-palindrome.js b/214.shortest-palindrome.js new file mode 100644 index 00000000..2309c51c --- /dev/null +++ b/214.shortest-palindrome.js @@ -0,0 +1,14 @@ +/** + * @param {string} s + * @return {string} + */ +const shortestPalindrome = function(s) { + let j = 0; + for (let i = s.length - 1; i >= 0; i--) { + if (s.charAt(i) === s.charAt(j)) { j += 1; } + } + if (j === s.length) { return s; } + let suffix = s.substring(j); + return suffix.split('').reverse().join('') + shortestPalindrome(s.substring(0, j)) + suffix; +}; + diff --git a/2140-solving-questions-with-brainpower.js b/2140-solving-questions-with-brainpower.js deleted file mode 100644 index 646ba1d2..00000000 --- a/2140-solving-questions-with-brainpower.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @param {number[][]} questions - * @return {number} - */ -const mostPoints = function(questions) { - const n = questions.length, dp = Array(n + 1).fill(0) - for (let i = n - 1; i >= 0; i--) { - const [gain, p] = questions[i] - dp[i] = Math.max(dp[i + 1], (dp[p + i + 1] || 0) + gain) - } - return dp[0] -}; - -// another - -/** - * @param {number[][]} questions - * @return {number} - */ -const mostPoints = function (questions) { - let n = questions.length - const temp = Array(n).fill(0) - - temp[n - 1] = questions[n - 1][0] - - for (let i = n - 2; i >= 0; i--) { - if (i + questions[i][1] + 1 <= n - 1) - temp[i] = Math.max( - temp[i + 1], - questions[i][0] + temp[i + questions[i][1] + 1] - ) - else temp[i] = Math.max(temp[i + 1], questions[i][0]) - } - return temp[0] -} diff --git a/2140.solving-questions-with-brainpower.js b/2140.solving-questions-with-brainpower.js new file mode 100644 index 00000000..61775ee7 --- /dev/null +++ b/2140.solving-questions-with-brainpower.js @@ -0,0 +1,13 @@ +/** + * @param {number[][]} questions + * @return {number} + */ +const mostPoints = function(questions) { + const n = questions.length, dp = Array(n + 1).fill(0) + for (let i = n - 1; i >= 0; i--) { + const [gain, p] = questions[i] + dp[i] = Math.max(dp[i + 1], (dp[p + i + 1] || 0) + gain) + } + return dp[0] +}; + diff --git a/2141-maximum-running-time-of-n-computers.js b/2141-maximum-running-time-of-n-computers.js deleted file mode 100644 index d71ebb67..00000000 --- a/2141-maximum-running-time-of-n-computers.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @param {number} n - * @param {number[]} batteries - * @return {number} - */ -const maxRunTime = function(n, batteries) { - n = BigInt(n) - batteries = batteries.map(e => BigInt(e)) - const sum = batteries.reduce((ac, e) => ac + e, 0n) - let l = 0n, r = sum / n - while(l < r) { - const mid = r - (r - l) / 2n - if(valid(mid)) l = mid - else r = mid - 1n - } - - return l - - function valid(mid) { - let curSum = 0n, target = mid * n - for(const e of batteries) { - curSum += e > mid ? mid : e - if(curSum >= target) return true - } - return false - } -}; - - -// another - - -/** - * @param {number} n - * @param {number[]} batteries - * @return {number} - */ -var maxRunTime = function (n, batteries) { - batteries.sort((a, b) => a - b) - const sum = batteries.reduce((ac, e) => ac + BigInt(e), 0n) - let hi = ~~(sum / BigInt(n)) + 1n, - lo = 0n - while (lo < hi) { - let mid = ~~((lo + hi) / 2n) - if (chk(mid)) { - lo = mid + 1n - } else { - hi = mid - } - } - - return lo - 1n - function chk(x) { - let current = 0n - let i = 0n - for (let b of batteries) { - if (i == BigInt(n)) break - if (b > x) b = x - if (b >= x - current) { - i += 1n - current = BigInt(b) - (x - current) - } else { - current += BigInt(b) - } - } - - return i == n - } -} diff --git a/2141.maximum-running-time-of-n-computers.js b/2141.maximum-running-time-of-n-computers.js new file mode 100644 index 00000000..054a9bb1 --- /dev/null +++ b/2141.maximum-running-time-of-n-computers.js @@ -0,0 +1,29 @@ +/** + * @param {number} n + * @param {number[]} batteries + * @return {number} + */ +const maxRunTime = function(n, batteries) { + n = BigInt(n) + batteries = batteries.map(e => BigInt(e)) + const sum = batteries.reduce((ac, e) => ac + e, 0n) + let l = 0n, r = sum / n + while(l < r) { + const mid = r - (r - l) / 2n + if(valid(mid)) l = mid + else r = mid - 1n + } + + return l + + function valid(mid) { + let curSum = 0n, target = mid * n + for(const e of batteries) { + curSum += e > mid ? mid : e + if(curSum >= target) return true + } + return false + } +}; + + diff --git a/2148-count-elements-with-strictly-smaller-and-greater-elements.js b/2148.count-elements-with-strictly-smaller-and-greater-elements.js similarity index 100% rename from 2148-count-elements-with-strictly-smaller-and-greater-elements.js rename to 2148.count-elements-with-strictly-smaller-and-greater-elements.js diff --git a/2149-rearrange-array-elements-by-sign.js b/2149.rearrange-array-elements-by-sign.js similarity index 100% rename from 2149-rearrange-array-elements-by-sign.js rename to 2149.rearrange-array-elements-by-sign.js diff --git a/215-kth-largest-element-in-an-array.js b/215-kth-largest-element-in-an-array.js deleted file mode 100755 index cbf5ce05..00000000 --- a/215-kth-largest-element-in-an-array.js +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const findKthLargest = function(nums, k) { - if (!nums || k > nums.length) return 0; - - const larger = []; - const smaller = []; - const pivot = nums[parseInt(nums.length / 2)]; - let pivotCount = 0; - - for (let i = 0; i < nums.length; i++) { - const ele = nums[i]; - - if (ele > pivot) larger.push(ele); - else if (ele === pivot) pivotCount++; - else smaller.push(ele); - } - - if (larger.length >= k) return findKthLargest(larger, k); - else if (k - larger.length - pivotCount <= 0) return pivot; - else return findKthLargest(smaller, k - larger.length - pivotCount); -}; - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const findKthLargest = function(nums, k) { - return quickselect(nums, 0, nums.length - 1, k) -}; -function quickselect(arr, lo, hi, k) { - let pivtIdx = Math.floor(Math.random() * (hi - lo + 1)) + lo - let pivtVal = arr[pivtIdx] - ;[arr[hi], arr[pivtIdx]] = [arr[pivtIdx], arr[hi]] - let i = lo - let j = hi - 1 - - while (i <= j) { - if (arr[i] <= pivtVal) { - i++ - } else { - ;[arr[j], arr[i]] = [arr[i], arr[j]] - j-- - } - } - - ;[arr[i], arr[hi]] = [arr[hi], arr[i]] - - pivtIdx = i - - if (pivtIdx === arr.length - k) return arr[pivtIdx] - if (pivtIdx < arr.length - k) return quickselect(arr, pivtIdx + 1, hi, k) - return quickselect(arr, lo, pivtIdx - 1, k) -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const findKthLargest = function(nums, k) { - const n = nums.length - let l = 0, r = n - 1, t = n - k - while(l < r) { - const mid = partition(nums, l, r) - if(mid < t) { - l = mid + 1 - } else { - if(mid === t) break - else r = mid - 1 - } - } - return nums[t] -}; - -function partition(arr, left, right) { - let pivot = arr[right] - let l = left, r = right - 1, j = left - for(let i = left; i < right; i++) { - if(arr[i] <= pivot) { - swap(arr, i, j) - j++ - } - } - swap(arr, j, right) - return j -} - -function swap(arr, i, j) { - const tmp = arr[i] - arr[i] = arr[j] - arr[j] = tmp -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const findKthLargest = function(nums, k) { - const n = nums.length - let l = 0, r = n - 1, t = n - k - while(l < r) { - const idx = partition(nums, l, r) - if (idx === t) return nums[t] - if (idx < t) l = idx + 1 - else r = idx - 1 - } - return nums[l] -}; - -function partition(arr, l, r) { - let tmp = l, pivot = arr[l] - while(l < r) { - while(l < r && arr[r] >= pivot) r-- - while(l < r && arr[l] <= pivot) l++ - swap(arr, l, r) - } - swap(arr, l, tmp) - return l -} - -function swap(arr, i, j) { - const tmp = arr[i] - arr[i] = arr[j] - arr[j] = tmp -} - - diff --git a/215.kth-largest-element-in-an-array.js b/215.kth-largest-element-in-an-array.js new file mode 100644 index 00000000..3e14e63f --- /dev/null +++ b/215.kth-largest-element-in-an-array.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const findKthLargest = function(nums, k) { + if (!nums || k > nums.length) return 0; + + const larger = []; + const smaller = []; + const pivot = nums[parseInt(nums.length / 2)]; + let pivotCount = 0; + + for (let i = 0; i < nums.length; i++) { + const ele = nums[i]; + + if (ele > pivot) larger.push(ele); + else if (ele === pivot) pivotCount++; + else smaller.push(ele); + } + + if (larger.length >= k) return findKthLargest(larger, k); + else if (k - larger.length - pivotCount <= 0) return pivot; + else return findKthLargest(smaller, k - larger.length - pivotCount); +}; + diff --git a/2150-find-all-lonely-numbers-in-the-array.js b/2150.find-all-lonely-numbers-in-the-array.js similarity index 100% rename from 2150-find-all-lonely-numbers-in-the-array.js rename to 2150.find-all-lonely-numbers-in-the-array.js diff --git a/2151-maximum-good-people-based-on-statements.js b/2151.maximum-good-people-based-on-statements.js similarity index 100% rename from 2151-maximum-good-people-based-on-statements.js rename to 2151.maximum-good-people-based-on-statements.js diff --git a/2152-minimum-number-of-lines-to-cover-points.js b/2152.minimum-number-of-lines-to-cover-points.js similarity index 100% rename from 2152-minimum-number-of-lines-to-cover-points.js rename to 2152.minimum-number-of-lines-to-cover-points.js diff --git a/2154-keep-multiplying-found-values-by-two.js b/2154.keep-multiplying-found-values-by-two.js similarity index 100% rename from 2154-keep-multiplying-found-values-by-two.js rename to 2154.keep-multiplying-found-values-by-two.js diff --git a/2155-all-divisions-with-the-highest-score-of-a-binary-array.js b/2155.all-divisions-with-the-highest-score-of-a-binary-array.js similarity index 100% rename from 2155-all-divisions-with-the-highest-score-of-a-binary-array.js rename to 2155.all-divisions-with-the-highest-score-of-a-binary-array.js diff --git a/2156-find-substring-with-given-hash-value.js b/2156.find-substring-with-given-hash-value.js similarity index 100% rename from 2156-find-substring-with-given-hash-value.js rename to 2156.find-substring-with-given-hash-value.js diff --git a/216-combination-sum-III.js b/216-combination-sum-III.js deleted file mode 100755 index c2caf4f5..00000000 --- a/216-combination-sum-III.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @param {number} k - * @param {number} n - * @return {number[][]} - */ -const combinationSum3 = function(k, n) { - const ans = []; - combination(ans, [], k, 1, n); - return ans; -}; - -function combination(ans, comb, k, start, n) { - if (comb.length > k) { - return; - } - if (comb.length === k && n === 0) { - ans.push(comb.slice(0)); - return; - } - for (let i = start; i <= n && i <= 9; i++) { - comb.push(i); - combination(ans, comb, k, i + 1, n - i); - comb.pop(); - } -} diff --git a/216.combination-sum-III.js b/216.combination-sum-III.js new file mode 100644 index 00000000..2fddcc1e --- /dev/null +++ b/216.combination-sum-III.js @@ -0,0 +1,25 @@ +/** + * @param {number} k + * @param {number} n + * @return {number[][]} + */ +const combinationSum3 = function(k, n) { + const ans = []; + combination(ans, [], k, 1, n); + return ans; +}; + +function combination(ans, comb, k, start, n) { + if (comb.length > k) { + return; + } + if (comb.length === k && n === 0) { + ans.push(comb.slice(0)); + return; + } + for (let i = start; i <= n && i <= 9; i++) { + comb.push(i); + combination(ans, comb, k, i + 1, n - i); + comb.pop(); + } +} diff --git a/2161-partition-array-according-to-given-pivot.js b/2161.partition-array-according-to-given-pivot.js similarity index 100% rename from 2161-partition-array-according-to-given-pivot.js rename to 2161.partition-array-according-to-given-pivot.js diff --git a/2163-minimum-difference-in-sums-after-removal-of-elements.js b/2163-minimum-difference-in-sums-after-removal-of-elements.js deleted file mode 100644 index 862bbe53..00000000 --- a/2163-minimum-difference-in-sums-after-removal-of-elements.js +++ /dev/null @@ -1,158 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const minimumDifference = function(nums) { - const n = nums.length, len = n / 3 - const maxCompare = (p, c) => { return p === c ? 0 : (p > c ? -1 : 1)} - const minCompare = (p, c) => { return p === c ? 0 : (p < c ? -1 : 1)} - const maxHeap = new PriorityQueue({compare: maxCompare}) - const minHeap = new PriorityQueue({compare: minCompare}) - const pre = Array(n).fill(Infinity), suffix = Array(n).fill(-Infinity) - for(let i = 0, sum = 0; i < 2 * len; i++) { - const cur = nums[i] - maxHeap.enqueue(cur) - sum += cur - if(maxHeap.size() > len) { - const tmp = maxHeap.dequeue() - sum -= tmp - } - if(maxHeap.size() === len) { - pre[i] = sum - } - } - - for(let i = n - 1, sum = 0; i >= len; i--) { - const cur = nums[i] - minHeap.enqueue(cur) - sum += cur - if(minHeap.size() > len) { - const tmp = minHeap.dequeue() - sum -= tmp - } - if(minHeap.size() === len) { - suffix[i] = sum - } - } - - // console.log(pre, suffix) - let res = Infinity - for(let i = len - 1; i < n - len; i++) { - res = Math.min(res, pre[i] - suffix[i + 1]) - } - return res -}; - -// another - - -/** - * @param {number[]} nums - * @return {number} - */ -const minimumDifference = function(nums) { - const n = nums.length, len = n / 3 - const maxHeap = new PriorityQueue((a, b) => a > b) - const minHeap = new PriorityQueue((a, b) => a < b) - const pre = Array(n).fill(Infinity), suffix = Array(n).fill(-Infinity) - for(let i = 0, sum = 0; i < 2 * len; i++) { - const cur = nums[i] - maxHeap.push(cur) - sum += cur - if(maxHeap.size() > len) { - const tmp = maxHeap.pop() - sum -= tmp - } - if(maxHeap.size() === len) { - pre[i] = sum - } - } - - for(let i = n - 1, sum = 0; i >= len; i--) { - const cur = nums[i] - minHeap.push(cur) - sum += cur - if(minHeap.size() > len) { - const tmp = minHeap.pop() - sum -= tmp - } - if(minHeap.size() === len) { - suffix[i] = sum - } - } - - // console.log(pre, suffix) - let res = Infinity - for(let i = len - 1; i < n - len; i++) { - res = Math.min(res, pre[i] - suffix[i + 1]) - } - return res -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/2163.minimum-difference-in-sums-after-removal-of-elements.js b/2163.minimum-difference-in-sums-after-removal-of-elements.js new file mode 100644 index 00000000..5179182b --- /dev/null +++ b/2163.minimum-difference-in-sums-after-removal-of-elements.js @@ -0,0 +1,45 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const minimumDifference = function(nums) { + const n = nums.length, len = n / 3 + const maxCompare = (p, c) => { return p === c ? 0 : (p > c ? -1 : 1)} + const minCompare = (p, c) => { return p === c ? 0 : (p < c ? -1 : 1)} + const maxHeap = new PriorityQueue({compare: maxCompare}) + const minHeap = new PriorityQueue({compare: minCompare}) + const pre = Array(n).fill(Infinity), suffix = Array(n).fill(-Infinity) + for(let i = 0, sum = 0; i < 2 * len; i++) { + const cur = nums[i] + maxHeap.enqueue(cur) + sum += cur + if(maxHeap.size() > len) { + const tmp = maxHeap.dequeue() + sum -= tmp + } + if(maxHeap.size() === len) { + pre[i] = sum + } + } + + for(let i = n - 1, sum = 0; i >= len; i--) { + const cur = nums[i] + minHeap.enqueue(cur) + sum += cur + if(minHeap.size() > len) { + const tmp = minHeap.dequeue() + sum -= tmp + } + if(minHeap.size() === len) { + suffix[i] = sum + } + } + + // console.log(pre, suffix) + let res = Infinity + for(let i = len - 1; i < n - len; i++) { + res = Math.min(res, pre[i] - suffix[i + 1]) + } + return res +}; + diff --git a/2164-sort-even-and-odd-indices-independently.js b/2164.sort-even-and-odd-indices-independently.js similarity index 100% rename from 2164-sort-even-and-odd-indices-independently.js rename to 2164.sort-even-and-odd-indices-independently.js diff --git a/2165-smallest-value-of-the-rearranged-number.js b/2165.smallest-value-of-the-rearranged-number.js similarity index 100% rename from 2165-smallest-value-of-the-rearranged-number.js rename to 2165.smallest-value-of-the-rearranged-number.js diff --git a/2166-design-bitset.js b/2166-design-bitset.js deleted file mode 100644 index 4c177ba6..00000000 --- a/2166-design-bitset.js +++ /dev/null @@ -1,171 +0,0 @@ -/** - * @param {number} size - */ -const Bitset = function (size) { - this.arr = Array.from({ length: 2 }, (el, idx) => - Array(size).fill(idx === 0 ? 0 : 1) - ) - this.cur = 0 - this.cnt = 0 -} - -/** - * @param {number} idx - * @return {void} - */ -Bitset.prototype.fix = function (idx) { - if(this.arr[this.cur][idx] === 1) return - this.arr[this.cur][idx] = 1 - this.arr[this.cur ^ 1][idx] = 0 - this.cnt++ -} - -/** - * @param {number} idx - * @return {void} - */ -Bitset.prototype.unfix = function (idx) { - if(this.arr[this.cur][idx] === 0) return - this.arr[this.cur][idx] = 0 - this.arr[this.cur ^ 1][idx] = 1 - this.cnt-- -} - -/** - * @return {void} - */ -Bitset.prototype.flip = function () { - this.cur ^= 1 - this.cnt = this.arr[this.cur].length - this.cnt -} - -/** - * @return {boolean} - */ -Bitset.prototype.all = function () { - return this.cnt === this.arr[this.cur].length -} - -/** - * @return {boolean} - */ -Bitset.prototype.one = function () { - return this.cnt > 0 -} - -/** - * @return {number} - */ -Bitset.prototype.count = function () { - return this.cnt -} - -/** - * @return {string} - */ -Bitset.prototype.toString = function () { - return this.arr[this.cur].join('') -} - -/** - * Your Bitset object will be instantiated and called as such: - * var obj = new Bitset(size) - * obj.fix(idx) - * obj.unfix(idx) - * obj.flip() - * var param_4 = obj.all() - * var param_5 = obj.one() - * var param_6 = obj.count() - * var param_7 = obj.toString() - */ - -// another - -/** - * @param {number} size - */ -var Bitset = function(size) { - this.s = Array.from({ length:2 }, () => Array()) - this.cnt = 0 - this.now = 0 - for (let i = 0; i < size; i++) { - this.s[this.now].push( '0'); - this.s[this.now ^ 1].push( '1'); - } -}; - -/** - * @param {number} idx - * @return {void} - */ -Bitset.prototype.fix = function(idx) { - if (this.s[this.now][idx] == '1') return; - // swap(this.s[this.now][idx], this.s[this.now ^ 1][idx]); - const tmp = this.s[this.now][idx] - this.s[this.now][idx] = this.s[this.now ^ 1][idx] - this.s[this.now ^ 1][idx] = tmp - this.cnt++; -}; - -/** - * @param {number} idx - * @return {void} - */ -Bitset.prototype.unfix = function(idx) { - if (this.s[this.now][idx] == '0') return; - // swap(this.s[this.now][idx], this.s[this.now ^ 1][idx]); - const tmp = this.s[this.now][idx] - this.s[this.now][idx] = this.s[this.now ^ 1][idx] - this.s[this.now ^ 1][idx] = tmp - this.cnt--; -}; - -/** - * @return {void} - */ -Bitset.prototype.flip = function() { - this.now = this.now ^ 1; - this.cnt = this.s[0].length - this.cnt; -}; - -/** - * @return {boolean} - */ -Bitset.prototype.all = function() { - return this.cnt == this.s[0].length; -}; - -/** - * @return {boolean} - */ -Bitset.prototype.one = function() { - return this.cnt !== 0 -}; - -/** - * @return {number} - */ -Bitset.prototype.count = function() { - return this.cnt; -}; - -/** - * @return {string} - */ -Bitset.prototype.toString = function() { - return this.s[this.now].join(''); -}; - - -/** - * Your Bitset object will be instantiated and called as such: - * var obj = new Bitset(size) - * obj.fix(idx) - * obj.unfix(idx) - * obj.flip() - * var param_4 = obj.all() - * var param_5 = obj.one() - * var param_6 = obj.count() - * var param_7 = obj.toString() - */ - diff --git a/2166.design-bitset.js b/2166.design-bitset.js new file mode 100644 index 00000000..86213e2c --- /dev/null +++ b/2166.design-bitset.js @@ -0,0 +1,81 @@ +/** + * @param {number} size + */ +const Bitset = function (size) { + this.arr = Array.from({ length: 2 }, (el, idx) => + Array(size).fill(idx === 0 ? 0 : 1) + ) + this.cur = 0 + this.cnt = 0 +} + +/** + * @param {number} idx + * @return {void} + */ +Bitset.prototype.fix = function (idx) { + if(this.arr[this.cur][idx] === 1) return + this.arr[this.cur][idx] = 1 + this.arr[this.cur ^ 1][idx] = 0 + this.cnt++ +} + +/** + * @param {number} idx + * @return {void} + */ +Bitset.prototype.unfix = function (idx) { + if(this.arr[this.cur][idx] === 0) return + this.arr[this.cur][idx] = 0 + this.arr[this.cur ^ 1][idx] = 1 + this.cnt-- +} + +/** + * @return {void} + */ +Bitset.prototype.flip = function () { + this.cur ^= 1 + this.cnt = this.arr[this.cur].length - this.cnt +} + +/** + * @return {boolean} + */ +Bitset.prototype.all = function () { + return this.cnt === this.arr[this.cur].length +} + +/** + * @return {boolean} + */ +Bitset.prototype.one = function () { + return this.cnt > 0 +} + +/** + * @return {number} + */ +Bitset.prototype.count = function () { + return this.cnt +} + +/** + * @return {string} + */ +Bitset.prototype.toString = function () { + return this.arr[this.cur].join('') +} + +/** + * Your Bitset object will be instantiated and called as such: + * var obj = new Bitset(size) + * obj.fix(idx) + * obj.unfix(idx) + * obj.flip() + * var param_4 = obj.all() + * var param_5 = obj.one() + * var param_6 = obj.count() + * var param_7 = obj.toString() + */ + diff --git a/2167-minimum-time-to-remove-all-cars-containing-illegal-goods.js b/2167-minimum-time-to-remove-all-cars-containing-illegal-goods.js deleted file mode 100644 index 6f4ca66e..00000000 --- a/2167-minimum-time-to-remove-all-cars-containing-illegal-goods.js +++ /dev/null @@ -1,128 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const minimumTime = function(s) { - const n = s.length - const arr = [] - for(let ch of s) { - arr.push(ch === '1' ? 1 : -1) - } - const score = minSum(arr) - return n + score - - function minSum(ar) { - const dp = Array(n).fill(Infinity) - dp[0] = ar[0] - let ans = dp[0] - for(let i = 1; i < n; i++) { - dp[i] = Math.min(ar[i], ar[i] + dp[i - 1]) - ans = Math.min(ans, dp[i]) - } - return ans > 0 ? 0 : ans - } -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const minimumTime = function(s) { - const n = s.length - const arr = [] - for(let ch of s) { - arr.push(ch === '1' ? 1 : -1) - } - const score = minSum(arr) - return n + score - - function minSum(ar) { - const dp = Array(n).fill(0) - dp[0] = ar[0] - for(let i = 1; i < n; i++) { - dp[i] = Math.min(ar[i], ar[i] + dp[i - 1]) - } - return Math.min(0, Math.min(...dp)) - } -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const minimumTime = function(s) { - if(s.length === 1) return s === '1' ? 1 : 0 - const n = s.length - const arr = [] - for(let ch of s) { - arr.push(ch === '1' ? 1 : -1) - } - const score = minSum(arr) - return n + score - - function minSum(ar) { - const dp = Array(n).fill(0) - dp[0] = ar[0] - let ans = dp[0] - for(let i = 1; i < n; i++) { - dp[i] = Math.min(ar[i], ar[i] + dp[i - 1]) - ans = Math.min(0, ans, dp[i]) - } - return ans - } -}; - -// another - - -/** - * @param {string} s - * @return {number} - */ -var minimumTime = function(s) { - - const { max, min } = Math - - let n = s.length; - const l = Array.from({ length: n + 1 }, () => Array(2).fill(0)) - const r = Array.from({ length: n + 1 }, () => Array(2).fill(0)) - for (let i = 0; i < n; i++) l[i][0] = l[i][1] = r[i][0] = r[i][1] = 0; - if (s[0] == '1') { - l[0][0] = 1; - l[0][1] = 2; - } - for (let i = 1; i < n; i++) { - if (s[i] == '0') { - l[i][0] = l[i - 1][0]; - l[i][1] = l[i - 1][1]; - } else { - l[i][0] = i + 1; - l[i][1] = min(l[i - 1][0], l[i - 1][1]) + 2; - } - } - if (s[n - 1] == '1') { - r[n - 1][0] = 1; - r[n - 1][1] = 2; - } - for (let i = n - 2; i >= 0; i--) { - if (s[i] == '0') { - r[i][0] = r[i + 1][0]; - r[i][1] = r[i + 1][1]; - } else { - r[i][0] = n - i; - r[i][1] = min(r[i + 1][0], r[i + 1][1]) + 2; - } - } - let ans = n; - for (let i = -1; i < n; i++) { - let cost = 0; - if (i != -1) cost += min(l[i][0], l[i][1]); - if (i != n - 1) cost += min(r[i + 1][0], r[i + 1][1]); - ans = min(ans, cost); - } - return ans; -}; diff --git a/2167.minimum-time-to-remove-all-cars-containing-illegal-goods.js b/2167.minimum-time-to-remove-all-cars-containing-illegal-goods.js new file mode 100644 index 00000000..3dcaf7da --- /dev/null +++ b/2167.minimum-time-to-remove-all-cars-containing-illegal-goods.js @@ -0,0 +1,25 @@ +/** + * @param {string} s + * @return {number} + */ +const minimumTime = function(s) { + const n = s.length + const arr = [] + for(let ch of s) { + arr.push(ch === '1' ? 1 : -1) + } + const score = minSum(arr) + return n + score + + function minSum(ar) { + const dp = Array(n).fill(Infinity) + dp[0] = ar[0] + let ans = dp[0] + for(let i = 1; i < n; i++) { + dp[i] = Math.min(ar[i], ar[i] + dp[i - 1]) + ans = Math.min(ans, dp[i]) + } + return ans > 0 ? 0 : ans + } +}; + diff --git a/2169-count-operations-to-obtain-zero.js b/2169.count-operations-to-obtain-zero.js similarity index 100% rename from 2169-count-operations-to-obtain-zero.js rename to 2169.count-operations-to-obtain-zero.js diff --git a/217-contains-duplicate.js b/217-contains-duplicate.js deleted file mode 100755 index 58c739b2..00000000 --- a/217-contains-duplicate.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @param {number[]} nums - * @return {boolean} - */ -const containsDuplicate = function(nums) { - const hash = {}; - for (let el of nums) { - if (hash.hasOwnProperty(el)) { - return true; - } else { - hash[el] = 1; - } - } - return false; -}; diff --git a/217.contains-duplicate.js b/217.contains-duplicate.js new file mode 100644 index 00000000..16096df7 --- /dev/null +++ b/217.contains-duplicate.js @@ -0,0 +1,15 @@ +/** + * @param {number[]} nums + * @return {boolean} + */ +const containsDuplicate = function(nums) { + const hash = {}; + for (let el of nums) { + if (hash.hasOwnProperty(el)) { + return true; + } else { + hash[el] = 1; + } + } + return false; +}; diff --git a/2172-maximum-and-sum-of-array.js b/2172.maximum-and-sum-of-array.js similarity index 100% rename from 2172-maximum-and-sum-of-array.js rename to 2172.maximum-and-sum-of-array.js diff --git a/2178-maximum-split-of-positive-even-integers.js b/2178.maximum-split-of-positive-even-integers.js similarity index 100% rename from 2178-maximum-split-of-positive-even-integers.js rename to 2178.maximum-split-of-positive-even-integers.js diff --git a/2179-count-good-triplets-in-an-array.js b/2179.count-good-triplets-in-an-array.js similarity index 100% rename from 2179-count-good-triplets-in-an-array.js rename to 2179.count-good-triplets-in-an-array.js diff --git a/218-the-skyline-problem.js b/218.the-skyline-problem.js similarity index 100% rename from 218-the-skyline-problem.js rename to 218.the-skyline-problem.js diff --git a/2180-count-integers-with-even-digit-sum.js b/2180.count-integers-with-even-digit-sum.js similarity index 100% rename from 2180-count-integers-with-even-digit-sum.js rename to 2180.count-integers-with-even-digit-sum.js diff --git a/2181-merge-nodes-in-between-zeros.js b/2181.merge-nodes-in-between-zeros.js similarity index 100% rename from 2181-merge-nodes-in-between-zeros.js rename to 2181.merge-nodes-in-between-zeros.js diff --git a/2182-construct-string-with-repeat-limit.js b/2182.construct-string-with-repeat-limit.js similarity index 100% rename from 2182-construct-string-with-repeat-limit.js rename to 2182.construct-string-with-repeat-limit.js diff --git a/2183-count-array-pairs-divisible-by-k.js b/2183-count-array-pairs-divisible-by-k.js deleted file mode 100644 index 268ad344..00000000 --- a/2183-count-array-pairs-divisible-by-k.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const countPairs = function (nums, k) { - const map = new Map() - - let res = 0 - for(const e of nums) { - const tmp = gcd(e, k) - - for(const [key, v] of map) { - if(tmp * key % k === 0) { - res += v - } - } - if(map.get(tmp) == null) map.set(tmp, 0) - map.set(tmp, map.get(tmp) + 1) - } - - return res - - function gcd(a, b) { - return b === 0 ? a : gcd(b, a % b) - } -} - -// another - - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const coutPairs = function(nums, k) { - let res = 0; - let cnt = Array(1e5 + 1).fill(0); - const n = nums.length - for (let i = 0; i < n; ++i) { - if (nums[i] % k == 0) { - res += i; - ++cnt[0]; - } - else { - let div = gcd(k, nums[i]); - for (let d = 0; d <= div; ++d) res += cnt[k / div * d]; - ++cnt[div]; - } - } - return res; -}; - -function gcd(a, b) { - if(b === 0) return a - return gcd(b, a % b) -} diff --git a/2183.count-array-pairs-divisible-by-k.js b/2183.count-array-pairs-divisible-by-k.js new file mode 100644 index 00000000..116038dc --- /dev/null +++ b/2183.count-array-pairs-divisible-by-k.js @@ -0,0 +1,28 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const countPairs = function (nums, k) { + const map = new Map() + + let res = 0 + for(const e of nums) { + const tmp = gcd(e, k) + + for(const [key, v] of map) { + if(tmp * key % k === 0) { + res += v + } + } + if(map.get(tmp) == null) map.set(tmp, 0) + map.set(tmp, map.get(tmp) + 1) + } + + return res + + function gcd(a, b) { + return b === 0 ? a : gcd(b, a % b) + } +} + diff --git a/2184-number-of-ways-to-build-sturdy-brick-wall.js b/2184-number-of-ways-to-build-sturdy-brick-wall.js deleted file mode 100644 index 99624b12..00000000 --- a/2184-number-of-ways-to-build-sturdy-brick-wall.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @param {number} height - * @param {number} width - * @param {number[]} bricks - * @return {number} - */ -const buildWall = function (height, width, bricks) { - const mod = 1e9 + 7 - const avail = [] - const bset = new Set(bricks) - const m = width - 1, limit = 1 << m - for(let mask = 0; mask < limit; mask++) { - const idxArr = [-1] - for(let j = 0; j < m; j++) { - if((mask >> j) & 1) idxArr.push(j) - } - idxArr.push(m) - let flag = true - for(let j = 1, len = idxArr.length; j < len; j++) { - if(!bset.has(idxArr[j] - idxArr[j - 1])) { - flag = false - break - } - } - if(flag) avail.push(mask) - } - - let res = 0 - if(height === 1) return avail.length - const dp = Array.from({ length: height }, () => Array(limit).fill(0)) - for(const mask of avail) { - dp[0][mask] = 1 - } - - for(let i = 1; i < height; i++) { - for(let j = 0, len = avail.length; j < len; j++) { - const cur = avail[j] - for(let k = 0; k < len; k++) { - const pre = avail[k] - if((cur & pre) === 0) { - dp[i][cur] = (dp[i][cur] + dp[i - 1][pre]) % mod - } - } - if(i === height - 1) { - res = (res + dp[i][cur]) % mod - } - } - } - - return res -} - -// another - -/** - * @param {number} height - * @param {number} width - * @param {number[]} bricks - * @return {number} - */ -const buildWall = function (height, width, bricks) { - const MOD = 1e9 + 7 - const rowPerms = new Set() // save all possible permutations of a row as a bitmask - const memo = [] - for (let i = 0; i <= height; ++i) { - memo[i] = new Array(2 ** 10).fill(0) - } - findAllPossRowPerms(rowPerms, 0, 0 | 0) - return countWaysToBuildSturdyWall(height, 0) - - function countWaysToBuildSturdyWall(currHeight, prevRowPerm) { - if (currHeight === 0) return 1 - if (memo[currHeight][prevRowPerm] != 0) { - return memo[currHeight][prevRowPerm] - } - let totCount = 0 - for (const rowPerm of rowPerms) { - if ((rowPerm & prevRowPerm) === 0) { - totCount = - (totCount + countWaysToBuildSturdyWall(currHeight - 1, rowPerm)) % MOD - } - } - memo[currHeight][prevRowPerm] = totCount - return totCount - } - - function findAllPossRowPerms(rowPerms, currWidth, mask) { - if (currWidth === width) { - rowPerms.add(mask) - return - } - // The reason why we don't want to mark the 0 index is that we are going from right to left - // when creating the wall and unlike other points of a row, the all rows will be flushed - // against the 0 index. - if (currWidth > 0) mask |= 1 << currWidth - for (const brick of bricks) { - if (currWidth + brick <= width) { - findAllPossRowPerms(rowPerms, currWidth + brick, mask) - } - } - return - } -} diff --git a/2184.number-of-ways-to-build-sturdy-brick-wall.js b/2184.number-of-ways-to-build-sturdy-brick-wall.js new file mode 100644 index 00000000..cb12e7f2 --- /dev/null +++ b/2184.number-of-ways-to-build-sturdy-brick-wall.js @@ -0,0 +1,52 @@ +/** + * @param {number} height + * @param {number} width + * @param {number[]} bricks + * @return {number} + */ +const buildWall = function (height, width, bricks) { + const mod = 1e9 + 7 + const avail = [] + const bset = new Set(bricks) + const m = width - 1, limit = 1 << m + for(let mask = 0; mask < limit; mask++) { + const idxArr = [-1] + for(let j = 0; j < m; j++) { + if((mask >> j) & 1) idxArr.push(j) + } + idxArr.push(m) + let flag = true + for(let j = 1, len = idxArr.length; j < len; j++) { + if(!bset.has(idxArr[j] - idxArr[j - 1])) { + flag = false + break + } + } + if(flag) avail.push(mask) + } + + let res = 0 + if(height === 1) return avail.length + const dp = Array.from({ length: height }, () => Array(limit).fill(0)) + for(const mask of avail) { + dp[0][mask] = 1 + } + + for(let i = 1; i < height; i++) { + for(let j = 0, len = avail.length; j < len; j++) { + const cur = avail[j] + for(let k = 0; k < len; k++) { + const pre = avail[k] + if((cur & pre) === 0) { + dp[i][cur] = (dp[i][cur] + dp[i - 1][pre]) % mod + } + } + if(i === height - 1) { + res = (res + dp[i][cur]) % mod + } + } + } + + return res +} + diff --git a/2188-minimum-time-to-finish-the-race.js b/2188-minimum-time-to-finish-the-race.js deleted file mode 100644 index 2e995cff..00000000 --- a/2188-minimum-time-to-finish-the-race.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @param {number[][]} tires - * @param {number} changeTime - * @param {number} numLaps - * @return {number} - */ - const minimumFinishTime = function (tires, changeTime, numLaps) { - tires = preprocess(tires) - let n = tires.length - const { max, min } = Math - // to handle the cases where numLaps is small - // pre[i][j]: the total time to run j laps consecutively with tire i - const pre = Array.from({ length: n }, () => - Array(20).fill(Infinity) - ) - for (let i = 0; i < n; i++) { - pre[i][1] = tires[i][0] - for (let j = 2; j < 20; j++) { - if (pre[i][j - 1] * tires[i][1] >= 2e9) break - pre[i][j] = pre[i][j - 1] * tires[i][1] - } - // since we define it as the total time, rather than just the time for the j-th lap - // we have to make it prefix sum - for (let j = 2; j < 20; j++) { - if (pre[i][j - 1] + pre[i][j] >= 2e9) break - pre[i][j] += pre[i][j - 1] - } - } - - // dp[x]: the minimum time to finish x laps - const dp = Array(numLaps + 1).fill(Infinity) - for (let i = 0; i < n; i++) { - dp[1] = min(dp[1], tires[i][0]) - } - for (let x = 1; x <= numLaps; x++) { - if (x < 20) { - // x is small enough, so an optimal solution might never changes tires! - for (let i = 0; i < n; i++) { - dp[x] = min(dp[x], pre[i][x]) - } - } - for (let j = x - 1; j > 0 && j >= x - 18; j--) { - dp[x] = min(dp[x], dp[j] + changeTime + dp[x - j]) - } - } - - return dp[numLaps] -} - -function preprocess(tires) { - tires.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])) - const res = [] - for (let t of tires) { - if (res.length === 0 || res[res.length - 1][1] > t[1]) { - res.push(t) - } - } - return res -} - -// another - -/** - * @param {number[][]} tires - * @param {number} changeTime - * @param {number} numLaps - * @return {number} - */ -var minimumFinishTime = function (tires, changeTime, numLaps) { - let N = tires.length, - len = 0 - const { max, min } = Math - const best = Array(numLaps).fill(Infinity), - dp = Array(numLaps + 1).fill(Infinity) - for (let i = 0; i < N; ++i) { - // We assume we also need `changeTime` time to use the first tire - // so that we don't need to treat the first tire as a special case - let f = tires[i][0], - r = tires[i][1], - sum = changeTime, - p = 1 - for (let j = 0; j < numLaps; ++j) { - sum += f * p - // If using the same tire takes no less time than changing the tire, - // stop further using the current tire - if (f * p >= f + changeTime) break - best[j] = min(best[j], sum) - len = max(len, j + 1) - p *= r - } - } - // dp[i + 1] is the minimum time to finish `numLaps` laps - dp[0] = 0 - for (let i = 0; i < numLaps; ++i) { - for (let j = 0; j < len && i - j >= 0; ++j) { - // try using the same tire in the last `j+1` laps - dp[i + 1] = min(dp[i + 1], dp[i - j] + best[j]) - } - } - // minus the `changeTime` we added to the first tire - return dp[numLaps] - changeTime -} - diff --git a/2188.minimum-time-to-finish-the-race.js b/2188.minimum-time-to-finish-the-race.js new file mode 100644 index 00000000..9a77fa16 --- /dev/null +++ b/2188.minimum-time-to-finish-the-race.js @@ -0,0 +1,60 @@ +/** + * @param {number[][]} tires + * @param {number} changeTime + * @param {number} numLaps + * @return {number} + */ + const minimumFinishTime = function (tires, changeTime, numLaps) { + tires = preprocess(tires) + let n = tires.length + const { max, min } = Math + // to handle the cases where numLaps is small + // pre[i][j]: the total time to run j laps consecutively with tire i + const pre = Array.from({ length: n }, () => + Array(20).fill(Infinity) + ) + for (let i = 0; i < n; i++) { + pre[i][1] = tires[i][0] + for (let j = 2; j < 20; j++) { + if (pre[i][j - 1] * tires[i][1] >= 2e9) break + pre[i][j] = pre[i][j - 1] * tires[i][1] + } + // since we define it as the total time, rather than just the time for the j-th lap + // we have to make it prefix sum + for (let j = 2; j < 20; j++) { + if (pre[i][j - 1] + pre[i][j] >= 2e9) break + pre[i][j] += pre[i][j - 1] + } + } + + // dp[x]: the minimum time to finish x laps + const dp = Array(numLaps + 1).fill(Infinity) + for (let i = 0; i < n; i++) { + dp[1] = min(dp[1], tires[i][0]) + } + for (let x = 1; x <= numLaps; x++) { + if (x < 20) { + // x is small enough, so an optimal solution might never changes tires! + for (let i = 0; i < n; i++) { + dp[x] = min(dp[x], pre[i][x]) + } + } + for (let j = x - 1; j > 0 && j >= x - 18; j--) { + dp[x] = min(dp[x], dp[j] + changeTime + dp[x - j]) + } + } + + return dp[numLaps] +} + +function preprocess(tires) { + tires.sort((a, b) => (a[0] === b[0] ? a[1] - b[1] : a[0] - b[0])) + const res = [] + for (let t of tires) { + if (res.length === 0 || res[res.length - 1][1] > t[1]) { + res.push(t) + } + } + return res +} + diff --git a/2189-number-of-ways-to-build-house-of-cards.js b/2189.number-of-ways-to-build-house-of-cards.js similarity index 100% rename from 2189-number-of-ways-to-build-house-of-cards.js rename to 2189.number-of-ways-to-build-house-of-cards.js diff --git a/219-contains-duplicate-ii.js b/219.contains-duplicate-ii.js similarity index 100% rename from 219-contains-duplicate-ii.js rename to 219.contains-duplicate-ii.js diff --git a/2192-all-ancestors-of-a-node-in-a-directed-acyclic-graph.js b/2192-all-ancestors-of-a-node-in-a-directed-acyclic-graph.js deleted file mode 100644 index 4ae95f82..00000000 --- a/2192-all-ancestors-of-a-node-in-a-directed-acyclic-graph.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} edges - * @return {number[][]} - */ -const getAncestors = function(n, edges) { - const res = Array.from({ length: n }, () => []) - const graph = {} - - for(const [u, v] of edges) { - if(graph[u] == null) graph[u] = [] - graph[u].push(v) - } - - for(let i = 0; i < n; i++) { - dfs(i, i) - } - - return res - - function dfs(p, cur) { - for(const nxt of (graph[cur] || [])) { - if(res[nxt].length === 0 || res[nxt][res[nxt].length - 1] !== p) { - res[nxt].push(p) - dfs(p, nxt) - } - } - } -}; - -// another - -/** - * @param {number} n - * @param {number[][]} edges - * @return {number[][]} - */ -const getAncestors = function(n, edges) { - const res = Array.from({ length: n }, () => new Set()) - const inDegree = Array(n).fill(0) - const graph = {} - - for(const [u, v] of edges) { - if(graph[v] == null) graph[v] = [] - graph[v].push(u) - inDegree[v]++ - } - - const visited = Array(n).fill(false) - for (let i = 0; i < n; i++) { - if (!visited[i]) dfs(i); - } - - return res.map(set => Array.from(set).sort((a, b) => a - b)) - - function dfs(i) { - visited[i] = true - for(const p of (graph[i] || [])) { - if(visited[p] === false) dfs(p) - res[i].add(p) - for(const e of res[p]) res[i].add(e) - } - } -}; diff --git a/2192.all-ancestors-of-a-node-in-a-directed-acyclic-graph.js b/2192.all-ancestors-of-a-node-in-a-directed-acyclic-graph.js new file mode 100644 index 00000000..b730c96b --- /dev/null +++ b/2192.all-ancestors-of-a-node-in-a-directed-acyclic-graph.js @@ -0,0 +1,30 @@ +/** + * @param {number} n + * @param {number[][]} edges + * @return {number[][]} + */ +const getAncestors = function(n, edges) { + const res = Array.from({ length: n }, () => []) + const graph = {} + + for(const [u, v] of edges) { + if(graph[u] == null) graph[u] = [] + graph[u].push(v) + } + + for(let i = 0; i < n; i++) { + dfs(i, i) + } + + return res + + function dfs(p, cur) { + for(const nxt of (graph[cur] || [])) { + if(res[nxt].length === 0 || res[nxt][res[nxt].length - 1] !== p) { + res[nxt].push(p) + dfs(p, nxt) + } + } + } +}; + diff --git a/2193-minimum-number-of-moves-to-make-palindrome.js b/2193.minimum-number-of-moves-to-make-palindrome.js similarity index 100% rename from 2193-minimum-number-of-moves-to-make-palindrome.js rename to 2193.minimum-number-of-moves-to-make-palindrome.js diff --git a/2197-replace-non-coprime-numbers-in-array.js b/2197.replace-non-coprime-numbers-in-array.js similarity index 100% rename from 2197-replace-non-coprime-numbers-in-array.js rename to 2197.replace-non-coprime-numbers-in-array.js diff --git a/22-generate-parentheses.js b/22-generate-parentheses.js deleted file mode 100755 index e6318566..00000000 --- a/22-generate-parentheses.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @param {number} n - * @return {string[]} - */ -const generateParenthesis = function(n) { - const res = []; - backtrack(res, "", 0, 0, n); - return res; -}; -function backtrack(arr, cur, open, close, max) { - if (cur.length === max * 2) { - arr.push(cur); - return; - } - if (open < max) backtrack(arr, cur + "(", open + 1, close, max); - if (close < open) backtrack(arr, cur + ")", open, close + 1, max); -} diff --git a/22.generate-parentheses.js b/22.generate-parentheses.js new file mode 100644 index 00000000..ef7a8f3e --- /dev/null +++ b/22.generate-parentheses.js @@ -0,0 +1,17 @@ +/** + * @param {number} n + * @return {string[]} + */ +const generateParenthesis = function(n) { + const res = []; + backtrack(res, "", 0, 0, n); + return res; +}; +function backtrack(arr, cur, open, close, max) { + if (cur.length === max * 2) { + arr.push(cur); + return; + } + if (open < max) backtrack(arr, cur + "(", open + 1, close, max); + if (close < open) backtrack(arr, cur + ")", open, close + 1, max); +} diff --git a/220-contains-duplicate-iii.js b/220-contains-duplicate-iii.js deleted file mode 100644 index e0247c1c..00000000 --- a/220-contains-duplicate-iii.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @param {number} t - * @return {boolean} - */ -const containsNearbyAlmostDuplicate = function(nums, k, t) { - if (k < 1 || t < 0) { - return false - } - const array = new Map() - const num = 10 ** 10 - for (let i = 0, iL = nums.length; i < iL; ++i) { - const noNegative = nums[i] + num - const factor = Math.floor(noNegative / (t + 1)) - if ( - array.has(factor) || - (array.has(factor - 1) && noNegative - array.get(factor - 1) <= t) || - (array.has(factor + 1) && array.get(factor + 1) - noNegative <= t) - ) { - return true - } - if (array.size >= k) { - array.delete(Math.floor((nums[i - k] + num) / (t + 1))) - } - array.set(factor, noNegative) - } - return false -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @param {number} t - * @return {boolean} - */ -const containsNearbyAlmostDuplicate = function(nums, k, t) { - const map = nums - .map((val, idx) => ({ val, idx })) - .sort((a, b) => a.val - b.val) - let l = 0 - let r = 1 - while (r < map.length) { - const diff = Math.abs(map[r].val - map[l].val) - const range = Math.abs(map[r].idx - map[l].idx) - if (diff <= t && range <= k) return true - else if (diff > t) l++ - else if (range > k) r++ - if (l === r) r++ - } - return false -} diff --git a/220.contains-duplicate-iii.js b/220.contains-duplicate-iii.js new file mode 100644 index 00000000..98e48c4a --- /dev/null +++ b/220.contains-duplicate-iii.js @@ -0,0 +1,30 @@ +/** + * @param {number[]} nums + * @param {number} k + * @param {number} t + * @return {boolean} + */ +const containsNearbyAlmostDuplicate = function(nums, k, t) { + if (k < 1 || t < 0) { + return false + } + const array = new Map() + const num = 10 ** 10 + for (let i = 0, iL = nums.length; i < iL; ++i) { + const noNegative = nums[i] + num + const factor = Math.floor(noNegative / (t + 1)) + if ( + array.has(factor) || + (array.has(factor - 1) && noNegative - array.get(factor - 1) <= t) || + (array.has(factor + 1) && array.get(factor + 1) - noNegative <= t) + ) { + return true + } + if (array.size >= k) { + array.delete(Math.floor((nums[i - k] + num) / (t + 1))) + } + array.set(factor, noNegative) + } + return false +} + diff --git a/2204-distance-to-a-cycle-in-undirected-graph.js b/2204.distance-to-a-cycle-in-undirected-graph.js similarity index 100% rename from 2204-distance-to-a-cycle-in-undirected-graph.js rename to 2204.distance-to-a-cycle-in-undirected-graph.js diff --git a/2209-minimum-white-tiles-after-covering-with-carpets.js b/2209.minimum-white-tiles-after-covering-with-carpets.js similarity index 100% rename from 2209-minimum-white-tiles-after-covering-with-carpets.js rename to 2209.minimum-white-tiles-after-covering-with-carpets.js diff --git a/221-maximal-square.js b/221-maximal-square.js deleted file mode 100644 index 1fadc79e..00000000 --- a/221-maximal-square.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @param {character[][]} matrix - * @return {number} - */ -const maximalSquare = function(matrix) { - const rows = matrix.length - const cols = rows > 0 ? matrix[0].length : 0 - const dp = Array.from(new Array(rows + 1), el => new Array(cols + 1).fill(0)) - let maxLen = 0 - for(let i = 1; i <= rows; i++) { - for(let j = 1; j <= cols; j++) { - if(matrix[i - 1][j - 1] === '1') { - dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1 - maxLen = Math.max(maxLen, dp[i][j]) - } - } - } - - return maxLen * maxLen -}; - -// another - -const maximalSquare = function(matrix) { - const rows = matrix.length - if(rows === 0) return 0 - const cols = matrix[0].length - const dp = new Array(cols + 1).fill(0) - let max = 0 - let prev = 0 - let tmp - for(let i = 1; i <= rows; i++) { - for(let j = 1; j <= cols; j++) { - tmp = dp[j] - if(matrix[i - 1][j - 1] === '1') { - dp[j] = Math.min(dp[j - 1], dp[j], prev) + 1 - if(dp[j] > max) max = dp[j] - } else { - dp[j] = 0 - } - prev = tmp - } - } - return max ** 2 -}; diff --git a/221.maximal-square.js b/221.maximal-square.js new file mode 100644 index 00000000..f516d9c1 --- /dev/null +++ b/221.maximal-square.js @@ -0,0 +1,21 @@ +/** + * @param {character[][]} matrix + * @return {number} + */ +const maximalSquare = function(matrix) { + const rows = matrix.length + const cols = rows > 0 ? matrix[0].length : 0 + const dp = Array.from(new Array(rows + 1), el => new Array(cols + 1).fill(0)) + let maxLen = 0 + for(let i = 1; i <= rows; i++) { + for(let j = 1; j <= cols; j++) { + if(matrix[i - 1][j - 1] === '1') { + dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]) + 1 + maxLen = Math.max(maxLen, dp[i][j]) + } + } + } + + return maxLen * maxLen +}; + diff --git a/2210-count-hills-and-valleys-in-an-array.js b/2210.count-hills-and-valleys-in-an-array.js similarity index 100% rename from 2210-count-hills-and-valleys-in-an-array.js rename to 2210.count-hills-and-valleys-in-an-array.js diff --git a/2211-count-collisions-on-a-road.js b/2211-count-collisions-on-a-road.js deleted file mode 100644 index 03ab8347..00000000 --- a/2211-count-collisions-on-a-road.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @param {string} directions - * @return {number} - */ -const countCollisions = function(directions) { - let res = 0, n = directions.length - - let flag = false - // left -> right - for(let i = 0; i < n; i++) { - if(directions[i] !== 'L') { - flag = true - } else { - res += flag ? 1 : 0 - } - } - flag = false - // right -> left - for(let i = n - 1; i >= 0; i--) { - if(directions[i] !== 'R') { - flag = true - } else { - res += flag ? 1 : 0 - } - } - - return res -}; - -// another - -/** - * @param {string} directions - * @return {number} - */ - const countCollisions = function(directions) { - let res = 0, n = directions.length - let left = 0, right = n - 1 - while(left < n && directions[left] === 'L') left++ - while(right >= 0 && directions[right] === 'R') right-- - for(let i = left; i <= right; i++) res += directions[i] === 'S' ? 0 : 1 - return res -}; diff --git a/2211.count-collisions-on-a-road.js b/2211.count-collisions-on-a-road.js new file mode 100644 index 00000000..8a560937 --- /dev/null +++ b/2211.count-collisions-on-a-road.js @@ -0,0 +1,29 @@ +/** + * @param {string} directions + * @return {number} + */ +const countCollisions = function(directions) { + let res = 0, n = directions.length + + let flag = false + // left -> right + for(let i = 0; i < n; i++) { + if(directions[i] !== 'L') { + flag = true + } else { + res += flag ? 1 : 0 + } + } + flag = false + // right -> left + for(let i = n - 1; i >= 0; i--) { + if(directions[i] !== 'R') { + flag = true + } else { + res += flag ? 1 : 0 + } + } + + return res +}; + diff --git a/2212-maximum-points-in-an-archery-competition.js b/2212.maximum-points-in-an-archery-competition.js similarity index 100% rename from 2212-maximum-points-in-an-archery-competition.js rename to 2212.maximum-points-in-an-archery-competition.js diff --git a/2213-longest-substring-of-one-repeating-character.js b/2213.longest-substring-of-one-repeating-character.js similarity index 100% rename from 2213-longest-substring-of-one-repeating-character.js rename to 2213.longest-substring-of-one-repeating-character.js diff --git a/2214-minimum-health-to-beat-game.js b/2214.minimum-health-to-beat-game.js similarity index 100% rename from 2214-minimum-health-to-beat-game.js rename to 2214.minimum-health-to-beat-game.js diff --git a/2215-find-the-difference-of-two-arrays.js b/2215.find-the-difference-of-two-arrays.js similarity index 100% rename from 2215-find-the-difference-of-two-arrays.js rename to 2215.find-the-difference-of-two-arrays.js diff --git a/2216-minimum-deletions-to-make-array-beautiful.js b/2216-minimum-deletions-to-make-array-beautiful.js deleted file mode 100644 index 4c7f09dd..00000000 --- a/2216-minimum-deletions-to-make-array-beautiful.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const minDeletion = function(nums) { - let res = 0, n = nums.length - - for(let i = 0; i < n; i += 2) { - while(i < n - 1 && nums[i] === nums[i + 1]) { - i++ - res++ - } - } - if((n - res) % 2 === 1) res++ - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const minDeletion = function(nums) { - let res = 0, i = 0 - for(i = 0, n = nums.length; i < n - 1;) { - if(nums[i] === nums[i + 1]) { - res++ - i++ - }else{ - i += 2 - } - } - if((nums.length - res) % 2 === 1) res++ - - return res -}; diff --git a/2216.minimum-deletions-to-make-array-beautiful.js b/2216.minimum-deletions-to-make-array-beautiful.js new file mode 100644 index 00000000..8a413e8d --- /dev/null +++ b/2216.minimum-deletions-to-make-array-beautiful.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const minDeletion = function(nums) { + let res = 0, n = nums.length + + for(let i = 0; i < n; i += 2) { + while(i < n - 1 && nums[i] === nums[i + 1]) { + i++ + res++ + } + } + if((n - res) % 2 === 1) res++ + return res +}; + diff --git a/2217-find-palindrome-with-fixed-length.js b/2217.find-palindrome-with-fixed-length.js similarity index 100% rename from 2217-find-palindrome-with-fixed-length.js rename to 2217.find-palindrome-with-fixed-length.js diff --git a/2218-maximum-value-of-k-coins-from-piles.js b/2218-maximum-value-of-k-coins-from-piles.js deleted file mode 100644 index 10f29d22..00000000 --- a/2218-maximum-value-of-k-coins-from-piles.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @param {number[][]} piles - * @param {number} k - * @return {number} - */ -var maxValueOfCoins = function(piles, k) { - let dp = Array(k + 1).fill(0); - for (let i = 0; i < piles.length; i++) { - const next = Array(k + 1).fill(0); - for (let l = 1; l <= k; l++) { - let sum = 0; - next[l] = dp[l]; - for (let j = 0; j < Math.min(piles[i].length, l); j++) { - sum += piles[i][j]; - next[l] = Math.max(next[l], dp[l - j - 1] + sum); - } - } - dp = next; - } - return dp[k]; -}; - -// another - -/** - * @param {number[][]} piles - * @param {number} k - * @return {number} - */ -const maxValueOfCoins = function(piles, k) { - const n = piles.length - const memo = Array.from({ length: n + 1 }, () => Array(k + 1).fill(null)) - return helper(0, k) - - // TC: O(k * m) - // k: k - // n: length of piles - // m: sum(piles[i]), total elements of all piles - function helper(i, k) { - if(k == 0 || i === n) return 0 - if(memo[i][k] != null) return memo[i][k] - let res = helper(i + 1, k) - let cur = 0 - - for(let j = 0; j < Math.min(piles[i].length, k); j++) { - cur += piles[i][j] - res = Math.max(res, cur + helper(i + 1, k - j - 1)) - } - return memo[i][k] = res - } -}; diff --git a/2218.maximum-value-of-k-coins-from-piles.js b/2218.maximum-value-of-k-coins-from-piles.js new file mode 100644 index 00000000..1c7a1abf --- /dev/null +++ b/2218.maximum-value-of-k-coins-from-piles.js @@ -0,0 +1,22 @@ +/** + * @param {number[][]} piles + * @param {number} k + * @return {number} + */ +var maxValueOfCoins = function(piles, k) { + let dp = Array(k + 1).fill(0); + for (let i = 0; i < piles.length; i++) { + const next = Array(k + 1).fill(0); + for (let l = 1; l <= k; l++) { + let sum = 0; + next[l] = dp[l]; + for (let j = 0; j < Math.min(piles[i].length, l); j++) { + sum += piles[i][j]; + next[l] = Math.max(next[l], dp[l - j - 1] + sum); + } + } + dp = next; + } + return dp[k]; +}; + diff --git a/222-count-complete-tree-nodes.js b/222-count-complete-tree-nodes.js deleted file mode 100644 index 73e20469..00000000 --- a/222-count-complete-tree-nodes.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const countNodes = function(root) { - if (root == null) return 0; - const payload = { depth: 0, numOfLast: 0, total: 0 }; - traverse([root], 0, payload); - return payload.total; -}; - -function traverse(row, depth, obj) { - const next = []; - for (let i = 0; i < row.length; i++) { - if (row[i].left) next.push(row[i].left); - if (row[i].right) next.push(row[i].right); - } - if (Math.pow(2, depth + 1) !== next.length) { - obj.total = Math.pow(2, depth + 1) - 1 + next.length; - return; - } - if (next.length) traverse(next, depth + 1, obj); -} - -// another - -/** - * @param {TreeNode} root - * @return {number} - */ -const countNodes = function(root) { - if (!root) { - return 0; - } - - return 1 + countNodes(root.left) + countNodes(root.right); -}; diff --git a/222.count-complete-tree-nodes.js b/222.count-complete-tree-nodes.js new file mode 100644 index 00000000..101b0a6a --- /dev/null +++ b/222.count-complete-tree-nodes.js @@ -0,0 +1,31 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +const countNodes = function(root) { + if (root == null) return 0; + const payload = { depth: 0, numOfLast: 0, total: 0 }; + traverse([root], 0, payload); + return payload.total; +}; + +function traverse(row, depth, obj) { + const next = []; + for (let i = 0; i < row.length; i++) { + if (row[i].left) next.push(row[i].left); + if (row[i].right) next.push(row[i].right); + } + if (Math.pow(2, depth + 1) !== next.length) { + obj.total = Math.pow(2, depth + 1) - 1 + next.length; + return; + } + if (next.length) traverse(next, depth + 1, obj); +} + diff --git a/2221-find-triangular-sum-of-an-array.js b/2221.find-triangular-sum-of-an-array.js similarity index 100% rename from 2221-find-triangular-sum-of-an-array.js rename to 2221.find-triangular-sum-of-an-array.js diff --git a/2222-number-of-ways-to-select-buildings.js b/2222.number-of-ways-to-select-buildings.js similarity index 100% rename from 2222-number-of-ways-to-select-buildings.js rename to 2222.number-of-ways-to-select-buildings.js diff --git a/2223-sum-of-scores-of-built-strings.js b/2223.sum-of-scores-of-built-strings.js similarity index 100% rename from 2223-sum-of-scores-of-built-strings.js rename to 2223.sum-of-scores-of-built-strings.js diff --git a/2224-minimum-number-of-operations-to-convert-time.js b/2224.minimum-number-of-operations-to-convert-time.js similarity index 100% rename from 2224-minimum-number-of-operations-to-convert-time.js rename to 2224.minimum-number-of-operations-to-convert-time.js diff --git a/2225-find-players-with-zero-or-one-losses.js b/2225.find-players-with-zero-or-one-losses.js similarity index 100% rename from 2225-find-players-with-zero-or-one-losses.js rename to 2225.find-players-with-zero-or-one-losses.js diff --git a/2226-maximum-candies-allocated-to-k-children.js b/2226-maximum-candies-allocated-to-k-children.js deleted file mode 100644 index 38ed2088..00000000 --- a/2226-maximum-candies-allocated-to-k-children.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {number[]} candies - * @param {number} k - * @return {number} - */ -const maximumCandies = function(candies, k) { - let max = candies.reduce((ac, e) => ac + e, 0); - let min = 0; - while (min < max) { - let mid = max - Math.floor((max - min) / 2); - let cnt = 0; - for (let cand of candies) { - cnt += ~~(cand / mid); - } - if (cnt < k) { - max = mid - 1; - } else { - min = mid; - } - } - return min; -}; - -// another - -/** - * @param {number[]} candies - * @param {number} k - * @return {number} - */ -const maximumCandies = function(candies, k) { - let max = candies.reduce((ac, e) => ac + e, 0) - let min = 0 - while(min < max) { - const mid = max - Math.floor((max - min) /2) - let num = 0 - for(let e of candies) num += ~~(e / mid) - if(num < k) max = mid - 1 - else min = mid - } - return min -}; diff --git a/2226.maximum-candies-allocated-to-k-children.js b/2226.maximum-candies-allocated-to-k-children.js new file mode 100644 index 00000000..b4edffdb --- /dev/null +++ b/2226.maximum-candies-allocated-to-k-children.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} candies + * @param {number} k + * @return {number} + */ +const maximumCandies = function(candies, k) { + let max = candies.reduce((ac, e) => ac + e, 0); + let min = 0; + while (min < max) { + let mid = max - Math.floor((max - min) / 2); + let cnt = 0; + for (let cand of candies) { + cnt += ~~(cand / mid); + } + if (cnt < k) { + max = mid - 1; + } else { + min = mid; + } + } + return min; +}; + diff --git a/2227-encrypt-and-decrypt-strings.js b/2227.encrypt-and-decrypt-strings.js similarity index 100% rename from 2227-encrypt-and-decrypt-strings.js rename to 2227.encrypt-and-decrypt-strings.js diff --git a/223-rectangle-area.js b/223-rectangle-area.js deleted file mode 100644 index 6c30c9d2..00000000 --- a/223-rectangle-area.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @param {number} A - * @param {number} B - * @param {number} C - * @param {number} D - * @param {number} E - * @param {number} F - * @param {number} G - * @param {number} H - * @return {number} - */ -const computeArea = function(A, B, C, D, E, F, G, H) { - const areaA = (C - A) * (D - B) - const areaB = (G - E) * (H - F) - const intersectionArea = - Math.max(0, Math.min(C, G) - Math.max(A, E)) * - Math.max(0, Math.min(D, H) - Math.max(B, F)) - return areaA + areaB - intersectionArea -} - - -// another - - -/** - * @param {number} A - * @param {number} B - * @param {number} C - * @param {number} D - * @param {number} E - * @param {number} F - * @param {number} G - * @param {number} H - * @return {number} - */ -const computeArea = function(A, B, C, D, E, F, G, H) { - const x1 = A, - x2 = C, - x3 = E, - x4 = G - const y1 = B, - y2 = D, - y3 = F, - y4 = H - return ( - area(x1, y1, x2, y2) + - area(x3, y3, x4, y4) - - delta(x1, x2, x3, x4) * delta(y1, y2, y3, y4) - ) -} - -function area(x1, y1, x2, y2) { - return Math.abs(x1 - x2) * Math.abs(y1 - y2) -} - -function delta(v1, v2, v3, v4) { - if (v1 > v2) { - let tmp = v1 - v1 = v2 - v2 = tmp - } - if (v3 > v4) { - let tmp = v3 - v3 = v4 - v4 = tmp - } - if (v3 >= v2 || v4 <= v1) return 0 - return Math.min(v2, v4) - Math.max(v1, v3) -} diff --git a/223.rectangle-area.js b/223.rectangle-area.js new file mode 100644 index 00000000..07503148 --- /dev/null +++ b/223.rectangle-area.js @@ -0,0 +1,21 @@ +/** + * @param {number} A + * @param {number} B + * @param {number} C + * @param {number} D + * @param {number} E + * @param {number} F + * @param {number} G + * @param {number} H + * @return {number} + */ +const computeArea = function(A, B, C, D, E, F, G, H) { + const areaA = (C - A) * (D - B) + const areaB = (G - E) * (H - F) + const intersectionArea = + Math.max(0, Math.min(C, G) - Math.max(A, E)) * + Math.max(0, Math.min(D, H) - Math.max(B, F)) + return areaA + areaB - intersectionArea +} + + diff --git a/2233-maximum-product-after-k-increments.js b/2233.maximum-product-after-k-increments.js similarity index 100% rename from 2233-maximum-product-after-k-increments.js rename to 2233.maximum-product-after-k-increments.js diff --git a/2234-maximum-total-beauty-of-the-gardens.js b/2234.maximum-total-beauty-of-the-gardens.js similarity index 100% rename from 2234-maximum-total-beauty-of-the-gardens.js rename to 2234.maximum-total-beauty-of-the-gardens.js diff --git a/2235-add-two-integers.js b/2235.add-two-integers.js similarity index 100% rename from 2235-add-two-integers.js rename to 2235.add-two-integers.js diff --git a/2237-count-positions-on-street-with-required-brightness.js b/2237.count-positions-on-street-with-required-brightness.js similarity index 100% rename from 2237-count-positions-on-street-with-required-brightness.js rename to 2237.count-positions-on-street-with-required-brightness.js diff --git a/224-basic-calculator.js b/224-basic-calculator.js deleted file mode 100644 index cf886088..00000000 --- a/224-basic-calculator.js +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const calculate = function(s) { - let stack = [] - let num = 0 - let sign = 1 - let res = 0 - for (let i = 0; i < s.length; i++) { - let char = s.charAt(i) - if (char >= '0' && char <= '9') { - num = num * 10 + parseInt(char, 10) - } else if (char === '+') { - res += sign * num - sign = 1 - num = 0 - } else if (char === '-') { - res += sign * num - sign = -1 - num = 0 - } else if (char === '(') { - stack.push(res) - stack.push(sign) - sign = 1 - res = 0 - num = 0 - } else if (char === ')') { - res += sign * num - res *= stack.pop() - res += stack.pop() - num = 0 - } - } - return res + sign * num -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const calculate = function(s) { - s = s.split(' ').join('') - const n = s.length, stack = [] - const isNum = ch => ch >= '0' && ch <= '9' - let num = 0, op = 1, res = 0 - for(let i = 0; i < n; i++) { - const ch = s[i] - if(isNum(ch)) { - num = num * 10 + (+ch) - } else { - if(ch === '(') { - stack.push(res) - stack.push(op) - num = 0 - op = 1 - res = 0 - } else if(ch === ')') { - res += num * op - res *= stack.pop() - res += stack.pop() - num = 0 - op = 1 - } else if(ch === '+') { - res += op * num - op = 1 - num = 0 - } else if(ch === '-') { - res += op * num - op = -1 - num = 0 - } - } - } - - return res + op * num -}; - -// another -/** - * @param {string} s - * @return {number} - */ -const calculate = function(s) { - s = s.trim() - - let res = 0, num = 0, op = 1 - const isDigit = ch => ch >= '0' && ch <= '9' - const stk = [] - for(let i = 0, n = s.length; i < n; i++) { - - const e = s[i] - if(e === ' ') continue - if(isDigit(e)) num = num * 10 + (+e) - else { - - if(e === '(') { - stk.push(res) - stk.push(op) - - res = 0 - num = 0 - op = 1 - } else if(e === ')') { - res += num * op - res *= stk.pop() - res += stk.pop() - op = 1 - num = 0 - } else if(e === '-') { - res += num * op - op = -1 - num = 0 - } else if(e === '+') { - res += num * op - op = 1 - num = 0 - } - } - } - - return res + num * op -}; diff --git a/224.basic-calculator.js b/224.basic-calculator.js new file mode 100644 index 00000000..082cd40c --- /dev/null +++ b/224.basic-calculator.js @@ -0,0 +1,37 @@ +/** + * @param {string} s + * @return {number} + */ +const calculate = function(s) { + let stack = [] + let num = 0 + let sign = 1 + let res = 0 + for (let i = 0; i < s.length; i++) { + let char = s.charAt(i) + if (char >= '0' && char <= '9') { + num = num * 10 + parseInt(char, 10) + } else if (char === '+') { + res += sign * num + sign = 1 + num = 0 + } else if (char === '-') { + res += sign * num + sign = -1 + num = 0 + } else if (char === '(') { + stack.push(res) + stack.push(sign) + sign = 1 + res = 0 + num = 0 + } else if (char === ')') { + res += sign * num + res *= stack.pop() + res += stack.pop() + num = 0 + } + } + return res + sign * num +} + diff --git a/2242-maximum-score-of-a-node-sequence.js b/2242.maximum-score-of-a-node-sequence.js similarity index 100% rename from 2242-maximum-score-of-a-node-sequence.js rename to 2242.maximum-score-of-a-node-sequence.js diff --git a/2243-calculate-digit-sum-of-a-string.js b/2243.calculate-digit-sum-of-a-string.js similarity index 100% rename from 2243-calculate-digit-sum-of-a-string.js rename to 2243.calculate-digit-sum-of-a-string.js diff --git a/2244-minimum-rounds-to-complete-all-tasks.js b/2244.minimum-rounds-to-complete-all-tasks.js similarity index 100% rename from 2244-minimum-rounds-to-complete-all-tasks.js rename to 2244.minimum-rounds-to-complete-all-tasks.js diff --git a/2245-maximum-trailing-zeros-in-a-cornered-path.js b/2245-maximum-trailing-zeros-in-a-cornered-path.js deleted file mode 100644 index b4914d6d..00000000 --- a/2245-maximum-trailing-zeros-in-a-cornered-path.js +++ /dev/null @@ -1,143 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const maxTrailingZeros = function maxTrailingZeros(grid) { - const m = grid.length - const n = grid[0].length - - const factors = (num, k) => { - let sum = 0 - while (!(num % k)) { - num /= k - sum += 1 - } - - return sum - } - - const getRowPrefixSum = (k) => { - const rowPrefixSum = [] - for (let i = 0; i < m; i++) { - rowPrefixSum.push([factors(grid[i][0], k)]) - for (let j = 1; j < n; j++) { - rowPrefixSum[i][j] = factors(grid[i][j], k) + rowPrefixSum[i][j - 1] - } - } - - return rowPrefixSum - } - - const getColPrefixSum = (k) => { - const colPrefixSum = [[factors(grid[0][0], k)]] - for (let i = 1; i < m; i++) { - colPrefixSum.push([factors(grid[i][0], k) + colPrefixSum[i - 1][0]]) - } - - for (let j = 1; j < n; j++) { - colPrefixSum[0][j] = factors(grid[0][j], k) - for (let i = 1; i < m; i++) { - colPrefixSum[i][j] = factors(grid[i][j], k) + colPrefixSum[i - 1][j] - } - } - - return colPrefixSum - } - - const twoRow = getRowPrefixSum(2) - const fiveRow = getRowPrefixSum(5) - const twoCol = getColPrefixSum(2) - const fiveCol = getColPrefixSum(5) - - let max = 0 - - // now check every cell in the whole grid - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - const twoLeft = twoRow[i][j] - const twoRight = twoRow[i][n - 1] - (j && twoRow[i][j - 1]) - const twoUp = i && twoCol[i - 1][j] - const twoDown = twoCol[m - 1][j] - twoCol[i][j] - - const fiveLeft = fiveRow[i][j] - const fiveRight = fiveRow[i][n - 1] - (j && fiveRow[i][j - 1]) - const fiveUp = i && fiveCol[i - 1][j] - const fiveDown = fiveCol[m - 1][j] - fiveCol[i][j] - - const corneredPaths = [ - Math.min(twoLeft + twoUp, fiveLeft + fiveUp), - Math.min(twoLeft + twoDown, fiveLeft + fiveDown), - Math.min(twoRight + twoUp, fiveRight + fiveUp), - Math.min(twoRight + twoDown, fiveRight + fiveDown), - ] - - const trailingZeros = Math.max(...corneredPaths) - - if (trailingZeros > max) { - max = trailingZeros - } - } - } - - return max -} - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -const maxTrailingZeros = function(grid) { - const g = grid - const m = g.length; - const n = g[0].length; - const ta = [...Array(m)].map(i => Array(n).fill(1)); - const tb = [...Array(m)].map(i => Array(n).fill(1)); - const tc = [...Array(m)].map(i => Array(n).fill(1)); - const td = [...Array(m)].map(i => Array(n).fill(1)); - - const c52 = (s) => { - let c5 = 0; - let c2 = 0; - while (s % 2 === 0) { - s = s / 2; - c2++; - } - while (s % 5 === 0) { - s = s / 5; - c5++; - } - return [c5, c2]; - } - - const c10 = ([c5, c2]) => { - return Math.min(c5, c2); - } - - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - ta[i][j] = (j === 0) ? c52(g[i][j]) : [c52(g[i][j])[0] + ta[i][j-1][0], c52(g[i][j])[1] + ta[i][j-1][1]]; - tb[i][j] = (i === 0) ? c52(g[i][j]) : [c52(g[i][j])[0] + tb[i-1][j][0], c52(g[i][j])[1] + tb[i-1][j][1]]; - } - } - - for (let i = m-1; i >= 0; i--) { - for (let j = n-1; j >= 0; j--) { - tc[i][j] = (j === n-1) ? c52(g[i][j]) : [c52(g[i][j])[0] + tc[i][j+1][0], c52(g[i][j])[1] + tc[i][j+1][1]]; // : ctz(hg(g[i][j]) * tc[i][j+1][0], tc[i][j+1][1]); // hg(g[i][j]) * tc[i][j+1]; - td[i][j] = (i === m-1) ? c52(g[i][j]) : [c52(g[i][j])[0] + td[i+1][j][0], c52(g[i][j])[1] + td[i+1][j][1]]; // : ctz(hg(g[i][j]) * td[i+1][j][0], td[i+1][j][1]); // hg(g[i][j]) * td[i+1][j]; - } - } - - let ret = 0; - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - let s1 = i === 0 ? c10(ta[i][j]) : c10([ta[i][j][0] + tb[i-1][j][0], ta[i][j][1] + tb[i-1][j][1]]); - let s2 = i === m - 1 ? c10(ta[i][j]) : c10([ta[i][j][0] + td[i+1][j][0], ta[i][j][1] + td[i+1][j][1]]); - let s3 = i === 0 ? c10(tc[i][j]) : c10([tc[i][j][0] + tb[i-1][j][0], tc[i][j][1] + tb[i-1][j][1]]); - let s4 = i === m - 1 ? c10(tc[i][j]) : c10([tc[i][j][0] + td[i+1][j][0], tc[i][j][1] + td[i+1][j][1]]); - ret = Math.max(ret, s1, s2, s3, s4); - } - } - return ret; -}; diff --git a/2245.maximum-trailing-zeros-in-a-cornered-path.js b/2245.maximum-trailing-zeros-in-a-cornered-path.js new file mode 100644 index 00000000..41fe7c37 --- /dev/null +++ b/2245.maximum-trailing-zeros-in-a-cornered-path.js @@ -0,0 +1,84 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const maxTrailingZeros = function maxTrailingZeros(grid) { + const m = grid.length + const n = grid[0].length + + const factors = (num, k) => { + let sum = 0 + while (!(num % k)) { + num /= k + sum += 1 + } + + return sum + } + + const getRowPrefixSum = (k) => { + const rowPrefixSum = [] + for (let i = 0; i < m; i++) { + rowPrefixSum.push([factors(grid[i][0], k)]) + for (let j = 1; j < n; j++) { + rowPrefixSum[i][j] = factors(grid[i][j], k) + rowPrefixSum[i][j - 1] + } + } + + return rowPrefixSum + } + + const getColPrefixSum = (k) => { + const colPrefixSum = [[factors(grid[0][0], k)]] + for (let i = 1; i < m; i++) { + colPrefixSum.push([factors(grid[i][0], k) + colPrefixSum[i - 1][0]]) + } + + for (let j = 1; j < n; j++) { + colPrefixSum[0][j] = factors(grid[0][j], k) + for (let i = 1; i < m; i++) { + colPrefixSum[i][j] = factors(grid[i][j], k) + colPrefixSum[i - 1][j] + } + } + + return colPrefixSum + } + + const twoRow = getRowPrefixSum(2) + const fiveRow = getRowPrefixSum(5) + const twoCol = getColPrefixSum(2) + const fiveCol = getColPrefixSum(5) + + let max = 0 + + // now check every cell in the whole grid + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + const twoLeft = twoRow[i][j] + const twoRight = twoRow[i][n - 1] - (j && twoRow[i][j - 1]) + const twoUp = i && twoCol[i - 1][j] + const twoDown = twoCol[m - 1][j] - twoCol[i][j] + + const fiveLeft = fiveRow[i][j] + const fiveRight = fiveRow[i][n - 1] - (j && fiveRow[i][j - 1]) + const fiveUp = i && fiveCol[i - 1][j] + const fiveDown = fiveCol[m - 1][j] - fiveCol[i][j] + + const corneredPaths = [ + Math.min(twoLeft + twoUp, fiveLeft + fiveUp), + Math.min(twoLeft + twoDown, fiveLeft + fiveDown), + Math.min(twoRight + twoUp, fiveRight + fiveUp), + Math.min(twoRight + twoDown, fiveRight + fiveDown), + ] + + const trailingZeros = Math.max(...corneredPaths) + + if (trailingZeros > max) { + max = trailingZeros + } + } + } + + return max +} + diff --git a/2246-longest-path-with-different-adjacent-characters.js b/2246-longest-path-with-different-adjacent-characters.js deleted file mode 100644 index 0b9e53e7..00000000 --- a/2246-longest-path-with-different-adjacent-characters.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @param {number[]} parent - * @param {string} s - * @return {number} - */ -var longestPath = function(parent, s) { - const n = parent.length - const hash = {} - for(let i = 1; i < n; i++) { - if(hash[parent[i]] == null) hash[parent[i]] = [] - hash[parent[i]].push(i) - } - - let res = 0 - dfs(0) - return res - - function dfs(i) { - let max1 = 0, max2 = 0 - for(const j of (hash[i] || [])) { - const len = dfs(j) - if(s[i] === s[j]) continue - if(len > max1) { - const tmp = max1 - max1 = len - max2 = tmp - } else if(len > max2) { - max2 = len - } - } - res = Math.max(res, max1 + max2 + 1) - return max1 + 1 - } -}; - - -// another - -/** - * @param {number[]} parent - * @param {string} s - * @return {number} - */ -var longestPath = function(parent, s) { - let n = s.length, res = 0; - const {max} = Math - let children = Array.from({ length: n}, () => Array()); - for (let i = 1; i < n; ++i) children[parent[i]].push(i); - dfs(children, s, 0); - return res; - - function dfs(children, s, i) { - let big1 = 0, big2 = 0; - for (let j of (children[i] || [])) { - let cur = dfs(children, s, j); - if (s[i] == s[j]) continue; - if (cur > big2) big2 = cur; - if (big2 > big1) { - let tmp = big1 - big1 = big2 - big2 = tmp - }; - } - res = max(res, big1 + big2 + 1); - return big1 + 1; - } -}; - - diff --git a/2246-determine-if-two-events-have-conflict.js b/2246.determine-if-two-events-have-conflict.js similarity index 100% rename from 2246-determine-if-two-events-have-conflict.js rename to 2246.determine-if-two-events-have-conflict.js diff --git a/2246.longest-path-with-different-adjacent-characters.js b/2246.longest-path-with-different-adjacent-characters.js new file mode 100644 index 00000000..b0d8baf5 --- /dev/null +++ b/2246.longest-path-with-different-adjacent-characters.js @@ -0,0 +1,36 @@ +/** + * @param {number[]} parent + * @param {string} s + * @return {number} + */ +var longestPath = function(parent, s) { + const n = parent.length + const hash = {} + for(let i = 1; i < n; i++) { + if(hash[parent[i]] == null) hash[parent[i]] = [] + hash[parent[i]].push(i) + } + + let res = 0 + dfs(0) + return res + + function dfs(i) { + let max1 = 0, max2 = 0 + for(const j of (hash[i] || [])) { + const len = dfs(j) + if(s[i] === s[j]) continue + if(len > max1) { + const tmp = max1 + max1 = len + max2 = tmp + } else if(len > max2) { + max2 = len + } + } + res = Math.max(res, max1 + max2 + 1) + return max1 + 1 + } +}; + + diff --git a/2248-intersection-of-multiple-arrays.js b/2248.intersection-of-multiple-arrays.js similarity index 100% rename from 2248-intersection-of-multiple-arrays.js rename to 2248.intersection-of-multiple-arrays.js diff --git a/2249-count-lattice-points-inside-a-circle.js b/2249.count-lattice-points-inside-a-circle.js similarity index 100% rename from 2249-count-lattice-points-inside-a-circle.js rename to 2249.count-lattice-points-inside-a-circle.js diff --git a/225-implement-stack-using-queues.js b/225.implement-stack-using-queues.js similarity index 100% rename from 225-implement-stack-using-queues.js rename to 225.implement-stack-using-queues.js diff --git a/2250-count-number-of-rectangles-containing-each-point.js b/2250-count-number-of-rectangles-containing-each-point.js deleted file mode 100644 index b76d92e0..00000000 --- a/2250-count-number-of-rectangles-containing-each-point.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @param {number[][]} rectangles - * @param {number[][]} points - * @return {number[]} - */ -const countRectangles = function(rectangles, points) { - const rect = rectangles - const matrix = Array.from({ length: 101 }, () => []) - for(const [x, y] of rect) { - matrix[y].push(x) - } - for(const row of matrix) row.sort((a, b) => a - b) - const res = [] - - for(const [x, y] of points) { - - let cnt = 0 - for(let i = y; i <= 100; i++) { - const arr = matrix[i], n = arr.length - let l = 0, r = n - while(l < r) { - const mid = l + Math.floor((r - l) / 2) - if(mid === n || arr[mid] >= x) r = mid - else l = mid + 1 - } - cnt += n - l - } - - res.push(cnt) - } - - return res -}; - -// another - -/** - * @param {number[][]} rectangles - * @param {number[][]} points - * @return {number[]} - */ -function countRectangles(rect, points) { - const hash = {} - for(let [y, x] of rect) { - if(hash[x] == null) hash[x] = [] - hash[x].push(y) - } - const keys = Object.keys(hash).map(e => +e) - for(const k of keys) { - hash[k].sort((a, b) => a - b) - } - keys.sort((a, b) => a - b) - const res = [] - const n = keys.length - // console.log(keys, hash) - for(const [y, x] of points) { - let v = 0 - const idx = helper(keys, x) - for(let i = idx; i < n; i++) { - const k = keys[i] - const p = helper(hash[k], y) - v += p === hash[k].length ? 0 : hash[k].length - p - } - res.push(v) - } - - return res - - function helper(arr, val) { - let l = 0, r = arr.length - while(l < r) { - const mid = l + Math.floor((r - l) / 2) - if(valid(mid)) r = mid - else l = mid + 1 - } - // console.log(arr, val, l) - return l - - function valid(mid) { - return arr[mid] >= val - } - } -} diff --git a/2250.count-number-of-rectangles-containing-each-point.js b/2250.count-number-of-rectangles-containing-each-point.js new file mode 100644 index 00000000..7d6e4d24 --- /dev/null +++ b/2250.count-number-of-rectangles-containing-each-point.js @@ -0,0 +1,34 @@ +/** + * @param {number[][]} rectangles + * @param {number[][]} points + * @return {number[]} + */ +const countRectangles = function(rectangles, points) { + const rect = rectangles + const matrix = Array.from({ length: 101 }, () => []) + for(const [x, y] of rect) { + matrix[y].push(x) + } + for(const row of matrix) row.sort((a, b) => a - b) + const res = [] + + for(const [x, y] of points) { + + let cnt = 0 + for(let i = y; i <= 100; i++) { + const arr = matrix[i], n = arr.length + let l = 0, r = n + while(l < r) { + const mid = l + Math.floor((r - l) / 2) + if(mid === n || arr[mid] >= x) r = mid + else l = mid + 1 + } + cnt += n - l + } + + res.push(cnt) + } + + return res +}; + diff --git a/2251-number-of-flowers-in-full-bloom.js b/2251.number-of-flowers-in-full-bloom.js similarity index 100% rename from 2251-number-of-flowers-in-full-bloom.js rename to 2251.number-of-flowers-in-full-bloom.js diff --git a/2258-escape-the-spreading-fire.js b/2258.escape-the-spreading-fire.js similarity index 100% rename from 2258-escape-the-spreading-fire.js rename to 2258.escape-the-spreading-fire.js diff --git a/2259-remove-digit-from-number-to-maximize-result.js b/2259.remove-digit-from-number-to-maximize-result.js similarity index 100% rename from 2259-remove-digit-from-number-to-maximize-result.js rename to 2259.remove-digit-from-number-to-maximize-result.js diff --git a/226-invert-binary-tree.js b/226-invert-binary-tree.js deleted file mode 100644 index 60a57563..00000000 --- a/226-invert-binary-tree.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode} - */ -const invertTree = function (root) { - if (root) { - ;[root.left, root.right] = [invertTree(root.right), invertTree(root.left)] - } - return root -} - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode} - */ -const invertTree = function (root) { - if (!root) return root - let queue = [root] - while (queue.length) { - let node = queue.shift() - if (node.left) { - queue.push(node.left) - } - if (node.right) { - queue.push(node.right) - } - let left = node.left - node.left = node.right - node.right = left - } - return root -} - -// anoother - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode} - */ -const invertTree = function(root) { - if(root == null) return root - let tmp = root.left - root.left = invertTree(root.right) - root.right = invertTree(tmp) - return root -}; diff --git a/226.invert-binary-tree.js b/226.invert-binary-tree.js new file mode 100644 index 00000000..8857027b --- /dev/null +++ b/226.invert-binary-tree.js @@ -0,0 +1,19 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {TreeNode} + */ +const invertTree = function (root) { + if (root) { + ;[root.left, root.right] = [invertTree(root.right), invertTree(root.left)] + } + return root +} + diff --git a/2260-minimum-consecutive-cards-to-pick-up.js b/2260.minimum-consecutive-cards-to-pick-up.js similarity index 100% rename from 2260-minimum-consecutive-cards-to-pick-up.js rename to 2260.minimum-consecutive-cards-to-pick-up.js diff --git a/2261-k-divisible-elements-subarrays.js b/2261.k-divisible-elements-subarrays.js similarity index 100% rename from 2261-k-divisible-elements-subarrays.js rename to 2261.k-divisible-elements-subarrays.js diff --git a/2262-total-appeal-of-a-string.js b/2262-total-appeal-of-a-string.js deleted file mode 100644 index 96fdec98..00000000 --- a/2262-total-appeal-of-a-string.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const appealSum = function (s) { - const n = s.length, pos = Array(26).fill(-1) - let res = 0 - const a = 'a'.charCodeAt(0) - for(let i = 0; i < n; i++) { - let tmp = n - i, idx = s.charCodeAt(i) - a - if(pos[idx] !== -1) { - tmp += (i - pos[idx] - 1) * (n - i) - } else tmp += i * (n - i) - res += tmp - pos[idx] = i - } - - return res -} - - -// another - -/** - * @param {string} s - * @return {number} - */ -var appealSum = function(s) { - const cnt = Array(26).fill(-1); - let ans = 0; - let n = s.length; - const a = 'a'.charCodeAt(0) - for (let i = 0; i < n; i++) { - let tmp = n - i; - if (cnt[s[i].charCodeAt(0) - a] !== -1) tmp += (i - cnt[s[i].charCodeAt(0) - a] - 1) * (n - i); - else tmp += i * (n - i); - ans += tmp; - cnt[s[i].charCodeAt(0) - a] = i; - } - return ans; -}; diff --git a/2262.total-appeal-of-a-string.js b/2262.total-appeal-of-a-string.js new file mode 100644 index 00000000..4a45c8e6 --- /dev/null +++ b/2262.total-appeal-of-a-string.js @@ -0,0 +1,21 @@ +/** + * @param {string} s + * @return {number} + */ +const appealSum = function (s) { + const n = s.length, pos = Array(26).fill(-1) + let res = 0 + const a = 'a'.charCodeAt(0) + for(let i = 0; i < n; i++) { + let tmp = n - i, idx = s.charCodeAt(i) - a + if(pos[idx] !== -1) { + tmp += (i - pos[idx] - 1) * (n - i) + } else tmp += i * (n - i) + res += tmp + pos[idx] = i + } + + return res +} + + diff --git a/2263-make-array-non-decreasing-or-non-increasing.js b/2263.make-array-non-decreasing-or-non-increasing.js similarity index 100% rename from 2263-make-array-non-decreasing-or-non-increasing.js rename to 2263.make-array-non-decreasing-or-non-increasing.js diff --git a/2264-largest-3-same-digit-number-in-string.js b/2264.largest-3-same-digit-number-in-string.js similarity index 100% rename from 2264-largest-3-same-digit-number-in-string.js rename to 2264.largest-3-same-digit-number-in-string.js diff --git a/2265-count-nodes-equal-to-average-of-subtree.js b/2265.count-nodes-equal-to-average-of-subtree.js similarity index 100% rename from 2265-count-nodes-equal-to-average-of-subtree.js rename to 2265.count-nodes-equal-to-average-of-subtree.js diff --git a/2266-count-number-of-texts.js b/2266.count-number-of-texts.js similarity index 100% rename from 2266-count-number-of-texts.js rename to 2266.count-number-of-texts.js diff --git a/2267-check-if-there-is-a-valid-parentheses-string-path.js b/2267-check-if-there-is-a-valid-parentheses-string-path.js deleted file mode 100644 index bafe3949..00000000 --- a/2267-check-if-there-is-a-valid-parentheses-string-path.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @param {character[][]} grid - * @return {boolean} - */ -const hasValidPath = function (grid) { - const m = grid.length - const n = grid[0].length - if (grid[0][0] != '(' || grid[m - 1][n - 1] != ')') return false - const dp = kdArr(-1, [m, n, ~~((m + n) / 2) + 1]) - - - function dfs(i, j, left) { - if (i >= m || j >= n) return false - if (grid[i][j] === '(') left++ - else left-- - if (left < 0 || left > Math.floor((m + n) / 2)) return false - if (dp[i][j][left] != -1) return dp[i][j][left] - if (i == m - 1 && j == n - 1 && left == 0) return (dp[i][j][left] = true) - return (dp[i][j][left] = dfs(i, j + 1, left) || dfs(i + 1, j, left)) - } - return dfs(0, 0, 0) - - function kdArr(defaultVal, arr) { - if(arr.length === 1) return Array(arr[0]).fill(defaultVal) - - const res = [] - for(let i = 0, len = arr[0]; i < len; i++) { - res.push(kdArr(defaultVal, arr.slice(1))) - } - - return res - } -} - - -// another - -/** - * @param {character[][]} grid - * @return {boolean} - */ -var hasValidPath = function(grid) { - if (grid[0][0] == ")") return false - let m = grid.length, n = grid[0].length - const dirs = [[0, 1], [1, 0]] - - if ((m + n - 1) % 2 == 1) return false - const a = Array.from({ length: m }, () => Array(n).fill(null)) - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - if(grid[i][j] === '(') a[i][j] = 1 - else a[i][j] = -1 - } - } - - - const visited = new Set([`0,0,1`]) - let q = [[0, 0, 1]] - - while (q.length){ - const tmp = [] - for (const [x, y, v] of q) { - if (`${x},${y},${v}` == `${m - 1},${n - 1},0`) return true - for (const [dx, dy] of dirs) { - let i= x + dx, j = y + dy - if (0 <= i && i < m && 0 <= j && j < n) { - let v2 = v + a[i][j] - if (v2 >= 0 && !visited.has(`${i},${j},${v2}`) ) { - tmp.push([i, j, v2]) - visited.add(`${i},${j},${v2}`) - } - - } - } - } - q = tmp - } - return false -}; - diff --git a/2267.check-if-there-is-a-valid-parentheses-string-path.js b/2267.check-if-there-is-a-valid-parentheses-string-path.js new file mode 100644 index 00000000..45e303e7 --- /dev/null +++ b/2267.check-if-there-is-a-valid-parentheses-string-path.js @@ -0,0 +1,35 @@ +/** + * @param {character[][]} grid + * @return {boolean} + */ +const hasValidPath = function (grid) { + const m = grid.length + const n = grid[0].length + if (grid[0][0] != '(' || grid[m - 1][n - 1] != ')') return false + const dp = kdArr(-1, [m, n, ~~((m + n) / 2) + 1]) + + + function dfs(i, j, left) { + if (i >= m || j >= n) return false + if (grid[i][j] === '(') left++ + else left-- + if (left < 0 || left > Math.floor((m + n) / 2)) return false + if (dp[i][j][left] != -1) return dp[i][j][left] + if (i == m - 1 && j == n - 1 && left == 0) return (dp[i][j][left] = true) + return (dp[i][j][left] = dfs(i, j + 1, left) || dfs(i + 1, j, left)) + } + return dfs(0, 0, 0) + + function kdArr(defaultVal, arr) { + if(arr.length === 1) return Array(arr[0]).fill(defaultVal) + + const res = [] + for(let i = 0, len = arr[0]; i < len; i++) { + res.push(kdArr(defaultVal, arr.slice(1))) + } + + return res + } +} + + diff --git a/2268-minimum-number-of-keypresses.js b/2268.minimum-number-of-keypresses.js similarity index 100% rename from 2268-minimum-number-of-keypresses.js rename to 2268.minimum-number-of-keypresses.js diff --git a/227-basic-calculator-ii.js b/227-basic-calculator-ii.js deleted file mode 100644 index e0f174ae..00000000 --- a/227-basic-calculator-ii.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const calculate = function(s) { - const stk = [] - let op = '+', num = 0 - s = s.trim() - const isDigit = ch => ch >= '0' && ch <= '9' - for(let i = 0, n = s.length; i < n; i++) { - const ch = s[i] - if(ch === ' ') continue - if(isDigit(ch)) { - num = (+num) * 10 + (+ch) - } - if(!isDigit(ch) || i === n - 1) { - if(op === '-') stk.push(-num) - else if(op === '+') stk.push(num) - else if(op === '*') stk.push(stk.pop() * num) - else if(op === '/') stk.push(~~(stk.pop() / num)) - - op = ch - num = 0 - } - } - let res = 0 - for(const e of stk) res += e - - return res -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const calculate = function(s) { - const stack = [], n = s.length - let op = '+', num = 0 - for(let i = 0; i < n; i++) { - const isNumber = s[i] >= '0' && s[i] <= '9' - if(isNumber) num = num * 10 + (+s[i]) - if((!isNumber && s[i] !== ' ') || i === n - 1) { - if(op === '+') stack.push(num) - else if(op === '-') stack.push(-num) - else if(op === '*') stack.push(stack.pop() * num) - else if(op === '/') stack.push(~~(stack.pop() / num)) - op = s[i] - num = 0 - } - } - - return stack.reduce((ac, e) => ac + e, 0) -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const calculate = function(s) { - if(s == null || s.length === 0) return 0 - let sum = 0, num = 0, op = '+', tmp = 0 - const stack = [] - for(let i = 0; i < s.length; i++) { - const ch = s[i] - const isInt = ch => ch >= '0' && ch <= '9' - if(isInt(ch)) { - num = num * 10 + (+ch) - } - if((!isInt(ch) && ch !== ' ') || i === s.length - 1) { - if(op === '+') { - sum += tmp - tmp = num - } - else if(op === '-') { - sum += tmp - tmp = - num - } - else if(op === '*') { - tmp *= num - } - else if(op === '/') { - tmp = ~~(tmp / num) - } - op = ch - num = 0 - } - - } - - return sum + tmp -} diff --git a/227.basic-calculator-ii.js b/227.basic-calculator-ii.js new file mode 100644 index 00000000..6787675f --- /dev/null +++ b/227.basic-calculator-ii.js @@ -0,0 +1,31 @@ +/** + * @param {string} s + * @return {number} + */ +const calculate = function(s) { + const stk = [] + let op = '+', num = 0 + s = s.trim() + const isDigit = ch => ch >= '0' && ch <= '9' + for(let i = 0, n = s.length; i < n; i++) { + const ch = s[i] + if(ch === ' ') continue + if(isDigit(ch)) { + num = (+num) * 10 + (+ch) + } + if(!isDigit(ch) || i === n - 1) { + if(op === '-') stk.push(-num) + else if(op === '+') stk.push(num) + else if(op === '*') stk.push(stk.pop() * num) + else if(op === '/') stk.push(~~(stk.pop() / num)) + + op = ch + num = 0 + } + } + let res = 0 + for(const e of stk) res += e + + return res +}; + diff --git a/2270-number-of-ways-to-split-array.js b/2270.number-of-ways-to-split-array.js similarity index 100% rename from 2270-number-of-ways-to-split-array.js rename to 2270.number-of-ways-to-split-array.js diff --git a/2271-maximum-white-tiles-covered-by-a-carpet.js b/2271-maximum-white-tiles-covered-by-a-carpet.js deleted file mode 100644 index f19e23d8..00000000 --- a/2271-maximum-white-tiles-covered-by-a-carpet.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @param {number[][]} tiles - * @param {number} carpetLen - * @return {number} - */ -const maximumWhiteTiles = function (tiles, carpetLen) { - const sorted = tiles.sort((a, b) => a[0] - b[0]) - let res = 0 - - let total = 0 - let right = 0 - - for (let tile of sorted) { - const start = tile[0] - const end = start + carpetLen - 1 - while (right < sorted.length && tiles[right][1] < end) { - total += tiles[right][1] - tiles[right][0] + 1 - right++ - } - if (right === sorted.length || sorted[right][0] > end) { - res = Math.max(res, total) - } else { - res = Math.max(res, total + (end - tiles[right][0] + 1)) - } - total -= tile[1] - tile[0] + 1 - } - - return res -} - -// another - -/** - * @param {number[][]} tiles - * @param {number} carpetLen - * @return {number} - */ -const maximumWhiteTiles = function (tiles, carpetLen) { - tiles.sort((a, b) => a[0] - b[0]) - let res = 0, total = 0, right = 0 - const n = tiles.length - for(let i = 0; i < n; i++) { - const [l, r] = tiles[i] - const end = l + carpetLen - 1 - while(right < n && tiles[right][1] <= end) { - total += tiles[right][1] - tiles[right][0] + 1 - right++ - } - - if(right === n || tiles[right][0] > end) { - res = Math.max(res, total) - } else { - res = Math.max(res, total + end - tiles[right][0] + 1) - } - - total -= r - l + 1 - } - - return res -} diff --git a/2271.maximum-white-tiles-covered-by-a-carpet.js b/2271.maximum-white-tiles-covered-by-a-carpet.js new file mode 100644 index 00000000..e3aebe36 --- /dev/null +++ b/2271.maximum-white-tiles-covered-by-a-carpet.js @@ -0,0 +1,30 @@ +/** + * @param {number[][]} tiles + * @param {number} carpetLen + * @return {number} + */ +const maximumWhiteTiles = function (tiles, carpetLen) { + const sorted = tiles.sort((a, b) => a[0] - b[0]) + let res = 0 + + let total = 0 + let right = 0 + + for (let tile of sorted) { + const start = tile[0] + const end = start + carpetLen - 1 + while (right < sorted.length && tiles[right][1] < end) { + total += tiles[right][1] - tiles[right][0] + 1 + right++ + } + if (right === sorted.length || sorted[right][0] > end) { + res = Math.max(res, total) + } else { + res = Math.max(res, total + (end - tiles[right][0] + 1)) + } + total -= tile[1] - tile[0] + 1 + } + + return res +} + diff --git a/2272-substring-with-largest-variance.js b/2272.substring-with-largest-variance.js similarity index 100% rename from 2272-substring-with-largest-variance.js rename to 2272.substring-with-largest-variance.js diff --git a/2273-find-resultant-array-after-removing-anagrams.js b/2273.find-resultant-array-after-removing-anagrams.js similarity index 100% rename from 2273-find-resultant-array-after-removing-anagrams.js rename to 2273.find-resultant-array-after-removing-anagrams.js diff --git a/2274-maximum-consecutive-floors-without-special-floors.js b/2274.maximum-consecutive-floors-without-special-floors.js similarity index 100% rename from 2274-maximum-consecutive-floors-without-special-floors.js rename to 2274.maximum-consecutive-floors-without-special-floors.js diff --git a/2275-largest-combination-with-bitwise-and-greater-than-zero.js b/2275-largest-combination-with-bitwise-and-greater-than-zero.js deleted file mode 100644 index e08649e4..00000000 --- a/2275-largest-combination-with-bitwise-and-greater-than-zero.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @param {number[]} candidates - * @return {number} - */ -const largestCombination = function(candidates) { - let res = 0 - for(let i = 0; i < 25; i++) { - let tmp = 0, bit = 1 << i - for(const e of candidates) { - if((e & bit) !== 0) tmp++ - } - res = Math.max(res, tmp) - } - return res -}; - -// another - -/** - * @param {number[]} candidates - * @return {number} - */ -const largestCombination = function(candidates) { - const arr = Array(24).fill(0), len = 24 - for(const e of candidates) { - const str = toBin(e) - for(let n = str.length, i = n - 1; i >= 0; i--) { - const cur = str[i] - if(cur === '1') { - arr[len - 1 - (n - 1 - i)]++ - } - } - } - - return Math.max(...arr) - - function toBin(num) { - return (num >>> 0).toString(2) - } -}; - diff --git a/2275.largest-combination-with-bitwise-and-greater-than-zero.js b/2275.largest-combination-with-bitwise-and-greater-than-zero.js new file mode 100644 index 00000000..aa96650e --- /dev/null +++ b/2275.largest-combination-with-bitwise-and-greater-than-zero.js @@ -0,0 +1,16 @@ +/** + * @param {number[]} candidates + * @return {number} + */ +const largestCombination = function(candidates) { + let res = 0 + for(let i = 0; i < 25; i++) { + let tmp = 0, bit = 1 << i + for(const e of candidates) { + if((e & bit) !== 0) tmp++ + } + res = Math.max(res, tmp) + } + return res +}; + diff --git a/2276-count-integers-in-intervals.js b/2276-count-integers-in-intervals.js deleted file mode 100644 index 2647fd6b..00000000 --- a/2276-count-integers-in-intervals.js +++ /dev/null @@ -1,200 +0,0 @@ -var CountIntervals = function() { - this.intervals = [] - this.ans = 0 -}; - -/** - * @param {number} left - * @param {number} right - * @return {void} - */ -CountIntervals.prototype.add = function(left, right) { - let l = 0, r = this.intervals.length - while (l < r) { - const m = Math.floor((l + r) / 2) - if (this.intervals[m][1] >= left) { - r = m - } else { - l = m + 1 - } - } - - let index = l - while (index < this.intervals.length && this.intervals[index][0] <= right) { - left = Math.min(left, this.intervals[index][0]) - right = Math.max(right, this.intervals[index][1]) - this.ans -= this.intervals[index][1] - this.intervals[index][0] + 1 - index += 1 - } - this.ans += right - left + 1 - this.intervals.splice(l, index - l, [left, right]) -}; - - -/** - * @return {number} - */ -CountIntervals.prototype.count = function() { - return this.ans -}; - -// another - -function binarySearch(l, r, fn) { - while (l <= r) { - const m = Math.floor((l + r) / 2) - if (fn(m)) { - l = m + 1 - } else { - r = m - 1 - } - } - return r -} - -var CountIntervals = function () { - this.intervals = [] - this.size = 0 -} - -/** - * @param {number} left - * @param {number} right - * @return {void} - */ -CountIntervals.prototype.add = function (left, right) { - const intervals = this.intervals - if (!intervals.length) { - intervals.push({ left, right }) - this.size += right - left + 1 - } else if (left > intervals[intervals.length - 1].right) { - intervals.push({ left, right }) - this.size += right - left + 1 - } else if (right < intervals[0].left) { - intervals.unshift({ left, right }) - this.size += right - left + 1 - } else { - const i = binarySearch(0, intervals.length - 1, (x) => { - return intervals[x].left < left - }) - let j, - start, - end, - sum = 0 - if (i < 0 || intervals[i].right < left) { - j = i + 1 - start = left - end = right - } else { - j = i - start = intervals[j].left - end = right - } - let first = -1 - while (j < intervals.length && right >= intervals[j].left) { - if (first < 0) first = j - end = Math.max(end, intervals[j].right) - sum += intervals[j].right - intervals[j].left + 1 - j++ - } - // delete [first, j) - // console.log('delete', j - first, '-', first, j) - this.size += end - start + 1 - sum - if (first < 0) { - this.intervals.splice(i + 1, 0, { left: start, right: end }) - } else { - this.intervals.splice(first, j - first, { left: start, right: end }) - } - } -} - -/** - * @return {number} - */ -CountIntervals.prototype.count = function () { - return this.size -} - - -// another - - - -var CountIntervals = function () { - this.root = new Node(1, 10 ** 9) -} - -/** - * @param {number} left - * @param {number} right - * @return {void} - */ -CountIntervals.prototype.add = function (left, right) { - this.root.addInterval(left, right) -} - -/** - * @return {number} - */ -CountIntervals.prototype.count = function () { - return this.root.total -} - -/** - * Your CountIntervals object will be instantiated and called as such: - * var obj = new CountIntervals() - * obj.add(left,right) - * var param_2 = obj.count() - */ - -class Node { - constructor(min, max) { - this.min = min - this.max = max - this.currentMin = -1 - this.currentMax = -1 - this.total = 0 - this.left = null - this.right = null - } - - addInterval(left, right) { - if (this.currentMin < 0) { - this.currentMin = left - this.currentMax = right - this.total = right - left + 1 - return this.total - } - - const mid = (this.min + this.max) >> 1 - - if (this.left) { - if (left <= mid) this.left.addInterval(left, Math.min(mid, right)) - if (right > mid) this.right.addInterval(Math.max(mid + 1, left), right) - - this.total = this.left.total + this.right.total - return - } - - if (left <= this.currentMax + 1 && right >= this.currentMin - 1) { - this.currentMin = Math.min(this.currentMin, left) - this.currentMax = Math.max(this.currentMax, right) - this.total = this.currentMax - this.currentMin + 1 - return - } - this.left = new Node(this.min, mid) - this.right = new Node(mid + 1, this.max) - - if (left <= mid) this.left.addInterval(left, Math.min(mid, right)) - if (right > mid) this.right.addInterval(Math.max(left, mid + 1), right) - if (this.currentMin <= mid) - this.left.addInterval(this.currentMin, Math.min(mid, this.currentMax)) - if (this.currentMax > mid) - this.right.addInterval( - Math.max(mid + 1, this.currentMin), - this.currentMax - ) - - this.total = this.left.total + this.right.total - } -} diff --git a/2276.count-integers-in-intervals.js b/2276.count-integers-in-intervals.js new file mode 100644 index 00000000..3c6d9ccb --- /dev/null +++ b/2276.count-integers-in-intervals.js @@ -0,0 +1,40 @@ +var CountIntervals = function() { + this.intervals = [] + this.ans = 0 +}; + +/** + * @param {number} left + * @param {number} right + * @return {void} + */ +CountIntervals.prototype.add = function(left, right) { + let l = 0, r = this.intervals.length + while (l < r) { + const m = Math.floor((l + r) / 2) + if (this.intervals[m][1] >= left) { + r = m + } else { + l = m + 1 + } + } + + let index = l + while (index < this.intervals.length && this.intervals[index][0] <= right) { + left = Math.min(left, this.intervals[index][0]) + right = Math.max(right, this.intervals[index][1]) + this.ans -= this.intervals[index][1] - this.intervals[index][0] + 1 + index += 1 + } + this.ans += right - left + 1 + this.intervals.splice(l, index - l, [left, right]) +}; + + +/** + * @return {number} + */ +CountIntervals.prototype.count = function() { + return this.ans +}; + diff --git a/2277-closest-node-to-path-in-tree.js b/2277.closest-node-to-path-in-tree.js similarity index 100% rename from 2277-closest-node-to-path-in-tree.js rename to 2277.closest-node-to-path-in-tree.js diff --git a/228-summary-ranges.js b/228-summary-ranges.js deleted file mode 100644 index eb708bde..00000000 --- a/228-summary-ranges.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @param {number[]} nums - * @return {string[]} - */ -const summaryRanges = function(nums) { - if (nums == null || nums.length === 0) return [] - const res = [] - if (nums.length === 1) return [`${nums[0]}`] - let start = nums[0] - let end = nums[0] - let endVal = end - for (let i = 1, len = nums.length; i < len; i++) { - let cur = nums[i] - if (cur - end > 1) { - endVal = end - insert(res, start, end) - start = cur - end = cur - } else { - end = cur - } - } - if (endVal !== end) { - insert(res, start, end) - } - return res -} - -function insert(arr, start, end) { - if (start === end) { - arr.push(`${start}`) - } else { - arr.push(`${start}->${end}`) - } -} - -// another - -const summaryRanges = nums => { - if (!nums || nums.length === 0) { - return []; - } - const returnArray = []; - let tempIdx = 0; - for (let i = 0; i < nums.length; i++) { - if (nums[i] + 1 !== nums[i + 1]) { - if (tempIdx === i) { - returnArray.push(nums[tempIdx].toString()); - } else { - returnArray.push(nums[tempIdx].toString() + "->" + nums[i].toString()); - } - tempIdx = i + 1; - } - } - - return returnArray; -}; diff --git a/228.summary-ranges.js b/228.summary-ranges.js new file mode 100644 index 00000000..52bda626 --- /dev/null +++ b/228.summary-ranges.js @@ -0,0 +1,36 @@ +/** + * @param {number[]} nums + * @return {string[]} + */ +const summaryRanges = function(nums) { + if (nums == null || nums.length === 0) return [] + const res = [] + if (nums.length === 1) return [`${nums[0]}`] + let start = nums[0] + let end = nums[0] + let endVal = end + for (let i = 1, len = nums.length; i < len; i++) { + let cur = nums[i] + if (cur - end > 1) { + endVal = end + insert(res, start, end) + start = cur + end = cur + } else { + end = cur + } + } + if (endVal !== end) { + insert(res, start, end) + } + return res +} + +function insert(arr, start, end) { + if (start === end) { + arr.push(`${start}`) + } else { + arr.push(`${start}->${end}`) + } +} + diff --git a/2280-minimum-lines-to-represent-a-line-chart.js b/2280-minimum-lines-to-represent-a-line-chart.js deleted file mode 100644 index a8d50bf9..00000000 --- a/2280-minimum-lines-to-represent-a-line-chart.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @param {number[][]} stockPrices - * @return {number} - */ -const minimumLines = function(stockPrices) { - let res = 1 - const n = stockPrices.length - if(n === 1) return 0 - stockPrices.sort((a, b) => a[0] - b[0]) - for(let i = 2; i < n; i++) { - const cur = stockPrices[i], p = stockPrices[i - 1], pp = stockPrices[i - 2] - if(chk(pp, p, cur)) continue - else res++ - } - - - return res -}; - -function chk(p1, p2, p3) { - const bi = BigInt - // (y3 - y1) / (x3 - x1) == (y2 - y1) / (x2 - x1) - const [x1, y1] = p1, [x2, y2] = p2, [x3, y3] = p3 - return (bi(y3) - bi(y1)) * (bi(x2) - bi(x1)) === (bi(y2) - bi(y1)) * (bi(x3) - bi(x1)) -} - - - -// another - -/** - * @param {number[][]} stockPrices - * @return {number} - */ -var minimumLines = function(stockPrices) { - let res = 1 - const ma = stockPrices - const n = ma.length - if(n === 0 || n === 1) return 0 - ma.sort((a, b) => a[0] - b[0]) - const eps = 1e-30 - let dx = ma[1][0] - ma[0][0], dy = ma[1][1] - ma[0][1] - for(let i = 2; i < n; i++) { - const cur = ma[i], pre = ma[i - 1] - const dxx = cur[0] - pre[0], dyy = cur[1] - pre[1] - if(BigInt(dxx) * BigInt(dy) !== BigInt(dx) * BigInt(dyy)) res++ - dx = dxx - dy = dyy - } - - return res -}; - -function product(p1, p2, p3) { - // 首先根据坐标计算p1p2和p1p3的向量,然后再计算叉乘 - // p1p2 向量表示为 (p2.x-p1.x,p2.y-p1.y) - // p1p3 向量表示为 (p3.x-p1.x,p3.y-p1.y) - return (p2.x-p1.x)*(p3.y-p1.y) - (p2.y-p1.y)*(p3.x-p1.x); -} diff --git a/2280.minimum-lines-to-represent-a-line-chart.js b/2280.minimum-lines-to-represent-a-line-chart.js new file mode 100644 index 00000000..94ace530 --- /dev/null +++ b/2280.minimum-lines-to-represent-a-line-chart.js @@ -0,0 +1,28 @@ +/** + * @param {number[][]} stockPrices + * @return {number} + */ +const minimumLines = function(stockPrices) { + let res = 1 + const n = stockPrices.length + if(n === 1) return 0 + stockPrices.sort((a, b) => a[0] - b[0]) + for(let i = 2; i < n; i++) { + const cur = stockPrices[i], p = stockPrices[i - 1], pp = stockPrices[i - 2] + if(chk(pp, p, cur)) continue + else res++ + } + + + return res +}; + +function chk(p1, p2, p3) { + const bi = BigInt + // (y3 - y1) / (x3 - x1) == (y2 - y1) / (x2 - x1) + const [x1, y1] = p1, [x2, y2] = p2, [x3, y3] = p3 + return (bi(y3) - bi(y1)) * (bi(x2) - bi(x1)) === (bi(y2) - bi(y1)) * (bi(x3) - bi(x1)) +} + + + diff --git a/2281-sum-of-total-strength-of-wizards.js b/2281.sum-of-total-strength-of-wizards.js similarity index 100% rename from 2281-sum-of-total-strength-of-wizards.js rename to 2281.sum-of-total-strength-of-wizards.js diff --git a/2282-number-of-people-that-can-be-seen-in-a-grid.js b/2282.number-of-people-that-can-be-seen-in-a-grid.js similarity index 100% rename from 2282-number-of-people-that-can-be-seen-in-a-grid.js rename to 2282.number-of-people-that-can-be-seen-in-a-grid.js diff --git a/2286-booking-concert-tickets-in-groups.js b/2286.booking-concert-tickets-in-groups.js similarity index 100% rename from 2286-booking-concert-tickets-in-groups.js rename to 2286.booking-concert-tickets-in-groups.js diff --git a/2287-rearrange-characters-to-make-target-string.js b/2287.rearrange-characters-to-make-target-string.js similarity index 100% rename from 2287-rearrange-characters-to-make-target-string.js rename to 2287.rearrange-characters-to-make-target-string.js diff --git a/2288-apply-discount-to-prices.js b/2288.apply-discount-to-prices.js similarity index 100% rename from 2288-apply-discount-to-prices.js rename to 2288.apply-discount-to-prices.js diff --git a/2289-steps-to-make-array-non-decreasing.js b/2289-steps-to-make-array-non-decreasing.js deleted file mode 100644 index 1fdfc322..00000000 --- a/2289-steps-to-make-array-non-decreasing.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -var totalSteps = function(nums) { - const n = nums.length - let res = 0, j = -1; - const dp = Array(n).fill(0), stack = Array(n).fill(0); - for (let i = n - 1; i >= 0; --i) { - while (j >= 0 && nums[i] > nums[stack[j]]) { - dp[i] = Math.max(++dp[i], dp[stack[j--]]) - res = Math.max(res, dp[i]) - } - stack[++j] = i - } - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const totalSteps = function(nums) { - let res = 0, stk = [] - stk.push([nums[0], 0]) - for(let i = 1, n = nums.length; i < n; i++) { - let steps = 0 - while(stk.length && stk[stk.length - 1][0] <= nums[i]) { - const peek = stk.pop() - steps = Math.max(steps, peek[1]) - } - if(stk.length === 0) steps = 0 - else steps++ - - res = Math.max(res, steps) - stk.push([nums[i], steps]) - } - - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const totalSteps = function(nums) { - let res = 0 - const stk = [] - for(const e of nums) { - let steps = 1 - while(stk.length && e >= stk[stk.length - 1][0]) { - const tmp = stk.pop() - steps = Math.max(tmp[1] + 1, steps) - } - if(stk.length === 0) steps = 0 - else { - res = Math.max(res, steps) - } - stk.push([e, steps]) - } - return res -}; - - diff --git a/2289.steps-to-make-array-non-decreasing.js b/2289.steps-to-make-array-non-decreasing.js new file mode 100644 index 00000000..77d7b132 --- /dev/null +++ b/2289.steps-to-make-array-non-decreasing.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums + * @return {number} + */ +var totalSteps = function(nums) { + const n = nums.length + let res = 0, j = -1; + const dp = Array(n).fill(0), stack = Array(n).fill(0); + for (let i = n - 1; i >= 0; --i) { + while (j >= 0 && nums[i] > nums[stack[j]]) { + dp[i] = Math.max(++dp[i], dp[stack[j--]]) + res = Math.max(res, dp[i]) + } + stack[++j] = i + } + return res +}; + diff --git a/229-majority-element-ii.js b/229.majority-element-ii.js similarity index 100% rename from 229-majority-element-ii.js rename to 229.majority-element-ii.js diff --git a/2290-minimum-obstacle-removal-to-reach-corner.js b/2290.minimum-obstacle-removal-to-reach-corner.js similarity index 100% rename from 2290-minimum-obstacle-removal-to-reach-corner.js rename to 2290.minimum-obstacle-removal-to-reach-corner.js diff --git a/2291-maximum-profit-from-trading-stocks.js b/2291.maximum-profit-from-trading-stocks.js similarity index 100% rename from 2291-maximum-profit-from-trading-stocks.js rename to 2291.maximum-profit-from-trading-stocks.js diff --git a/2293-min-max-game.js b/2293.min-max-game.js similarity index 100% rename from 2293-min-max-game.js rename to 2293.min-max-game.js diff --git a/2294-partition-array-such-that-maximum-difference-is-k.js b/2294.partition-array-such-that-maximum-difference-is-k.js similarity index 100% rename from 2294-partition-array-such-that-maximum-difference-is-k.js rename to 2294.partition-array-such-that-maximum-difference-is-k.js diff --git a/2295-replace-elements-in-an-array.js b/2295.replace-elements-in-an-array.js similarity index 100% rename from 2295-replace-elements-in-an-array.js rename to 2295.replace-elements-in-an-array.js diff --git a/2296-design-a-text-editor.js b/2296-design-a-text-editor.js deleted file mode 100644 index 1e953e41..00000000 --- a/2296-design-a-text-editor.js +++ /dev/null @@ -1,146 +0,0 @@ -const TextEditor = function () { - this.stk1 = [] - this.stk2 = [] -} - -/** - * @param {string} text - * @return {void} - */ -TextEditor.prototype.addText = function (text) { - for (const ch of text) this.stk1.push(ch) -} - -/** - * @param {number} k - * @return {number} - */ -TextEditor.prototype.deleteText = function (k) { - let res = 0 - while (this.stk1.length && k) { - k-- - res++ - this.stk1.pop() - } - return res -} - -/** - * @param {number} k - * @return {string} - */ -TextEditor.prototype.cursorLeft = function (k) { - let res = '' - while (this.stk1.length && k) { - const tmp = this.stk1.pop() - this.stk2.push(tmp) - k-- - } - - return this.slice() -} - -/** - * @param {number} k - * @return {string} - */ -TextEditor.prototype.cursorRight = function (k) { - let res = '' - - while (this.stk2.length && k) { - const tmp = this.stk2.pop() - this.stk1.push(tmp) - k-- - } - - return this.slice() -} - -TextEditor.prototype.slice = function() { - let res = '' - for ( - let len = this.stk1.length, size = Math.min(10, this.stk1.length), i = 0; - i < size; - i++ - ) { - res = this.stk1[len - i - 1] + res - } - return res -} - -// another - - -class Node { - constructor(val) { - this.val = val - this.prev = null - this.next = null - } -} - -var TextEditor = function() { - this.left = [] - this.right = [] - this.idx = 0 -}; - -/** - * @param {string} text - * @return {void} - */ -TextEditor.prototype.addText = function(text) { - for(const ch of text) this.left.push(ch) -}; - -/** - * @param {number} k - * @return {number} - */ -TextEditor.prototype.deleteText = function(k) { - let res = 0 - while(this.left.length && k) { - res++ - this.left.pop() - k-- - } - return res -}; - -/** - * @param {number} k - * @return {string} - */ -TextEditor.prototype.cursorLeft = function(k) { - while(k && this.left.length) { - const tmp = this.left.pop() - this.right.push(tmp) - k-- - } - - return this.left.slice(Math.max(0, this.left.length - 10), this.left.length).join('') -}; - -/** - * @param {number} k - * @return {string} - */ -TextEditor.prototype.cursorRight = function(k) { - while(k && this.right.length) { - const tmp = this.right.pop() - this.left.push(tmp) - k-- - } - - return this.left.slice(Math.max(0, this.left.length - 10), this.left.length).join('') -}; - - -/** - * Your TextEditor object will be instantiated and called as such: - * var obj = new TextEditor() - * obj.addText(text) - * var param_2 = obj.deleteText(k) - * var param_3 = obj.cursorLeft(k) - * var param_4 = obj.cursorRight(k) - */ diff --git a/2296.design-a-text-editor.js b/2296.design-a-text-editor.js new file mode 100644 index 00000000..3a2e598b --- /dev/null +++ b/2296.design-a-text-editor.js @@ -0,0 +1,70 @@ +const TextEditor = function () { + this.stk1 = [] + this.stk2 = [] +} + +/** + * @param {string} text + * @return {void} + */ +TextEditor.prototype.addText = function (text) { + for (const ch of text) this.stk1.push(ch) +} + +/** + * @param {number} k + * @return {number} + */ +TextEditor.prototype.deleteText = function (k) { + let res = 0 + while (this.stk1.length && k) { + k-- + res++ + this.stk1.pop() + } + return res +} + +/** + * @param {number} k + * @return {string} + */ +TextEditor.prototype.cursorLeft = function (k) { + let res = '' + while (this.stk1.length && k) { + const tmp = this.stk1.pop() + this.stk2.push(tmp) + k-- + } + + return this.slice() +} + +/** + * @param {number} k + * @return {string} + */ +TextEditor.prototype.cursorRight = function (k) { + let res = '' + + while (this.stk2.length && k) { + const tmp = this.stk2.pop() + this.stk1.push(tmp) + k-- + } + + return this.slice() +} + +TextEditor.prototype.slice = function() { + let res = '' + for ( + let len = this.stk1.length, size = Math.min(10, this.stk1.length), i = 0; + i < size; + i++ + ) { + res = this.stk1[len - i - 1] + res + } + return res +} + diff --git a/23-merge-k-sorted-lists.js b/23-merge-k-sorted-lists.js deleted file mode 100644 index 1804d044..00000000 --- a/23-merge-k-sorted-lists.js +++ /dev/null @@ -1,179 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode[]} lists - * @return {ListNode} - */ -const mergeKLists = function(lists) { - return merge(lists, 0, lists.length - 1) -} -function merge(lists, l, r) { - if (l > r) return null - if (l === r) return lists[l] - let m = Math.floor((r + l) / 2) - let left = merge(lists, l, m) - let right = merge(lists, m + 1, r) - let head = new ListNode(0) - let dummy = head - while (left && right) { - if (left.val <= right.val) { - head.next = left - left = left.next - } else { - head.next = right - right = right.next - } - head = head.next - } - head.next = left ? left : right - return dummy.next -} - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode[]} lists - * @return {ListNode} - */ -const mergeKLists = function(lists) { - if(lists == null || lists.length === 0) return null - if(lists.length === 1) return lists[0] - if(lists.length === 2) return mergeTwo(lists[0], lists[1]) - const left = mergeKLists(lists.slice(0, ~~(lists.length / 2))) - const right = mergeKLists(lists.slice(~~(lists.length / 2))) - - return mergeTwo(left, right) -}; - -function mergeTwo(l1, l2) { - const dummy = new ListNode() - let cur = dummy - while(l1 && l2) { - if(l1.val < l2.val) { - cur.next = l1 - l1 = l1.next - } else { - cur.next = l2 - l2 = l2.next - } - cur = cur.next - } - if(l1) cur.next = l1 - if(l2) cur.next = l2 - - - return dummy.next -} - - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode[]} lists - * @return {ListNode} - */ -const mergeKLists = function(lists) { - if(lists == null || lists.length === 0) return null - const dummy = new ListNode() - let head = dummy - const pq = new PriorityQueue((a, b) => a.val < b.val) - for(let list of lists) { - while(list) { - pq.push(list) - list = list.next - } - } - while(!pq.isEmpty()) { - const pop = pq.pop() - head.next = new ListNode(pop.val) - head = head.next - } - return dummy.next -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/23.merge-k-sorted-lists.js b/23.merge-k-sorted-lists.js new file mode 100644 index 00000000..092c8fc3 --- /dev/null +++ b/23.merge-k-sorted-lists.js @@ -0,0 +1,36 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode[]} lists + * @return {ListNode} + */ +const mergeKLists = function(lists) { + return merge(lists, 0, lists.length - 1) +} +function merge(lists, l, r) { + if (l > r) return null + if (l === r) return lists[l] + let m = Math.floor((r + l) / 2) + let left = merge(lists, l, m) + let right = merge(lists, m + 1, r) + let head = new ListNode(0) + let dummy = head + while (left && right) { + if (left.val <= right.val) { + head.next = left + left = left.next + } else { + head.next = right + right = right.next + } + head = head.next + } + head.next = left ? left : right + return dummy.next +} + diff --git a/230-kth-smallest-element-in-a-bst.js b/230.kth-smallest-element-in-a-bst.js similarity index 100% rename from 230-kth-smallest-element-in-a-bst.js rename to 230.kth-smallest-element-in-a-bst.js diff --git a/2302-count-subarrays-with-score-less-than-k.js b/2302.count-subarrays-with-score-less-than-k.js similarity index 100% rename from 2302-count-subarrays-with-score-less-than-k.js rename to 2302.count-subarrays-with-score-less-than-k.js diff --git a/2303-calculate-amount-paid-in-taxes.js b/2303.calculate-amount-paid-in-taxes.js similarity index 100% rename from 2303-calculate-amount-paid-in-taxes.js rename to 2303.calculate-amount-paid-in-taxes.js diff --git a/2304-minimum-path-cost-in-a-grid.js b/2304.minimum-path-cost-in-a-grid.js similarity index 100% rename from 2304-minimum-path-cost-in-a-grid.js rename to 2304.minimum-path-cost-in-a-grid.js diff --git a/2305-fair-distribution-of-cookies.js b/2305.fair-distribution-of-cookies.js similarity index 100% rename from 2305-fair-distribution-of-cookies.js rename to 2305.fair-distribution-of-cookies.js diff --git a/2306-naming-a-company.js b/2306.naming-a-company.js similarity index 100% rename from 2306-naming-a-company.js rename to 2306.naming-a-company.js diff --git a/231-power-of-two.js b/231-power-of-two.js deleted file mode 100644 index 397c73ba..00000000 --- a/231-power-of-two.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @param {number} n - * @return {boolean} - */ -const isPowerOfTwo = function(n) { - let tmp = 0 - let idx = 0 - while(tmp <= n) { - if((tmp = Math.pow(2, idx)) === n) { - return true - } else { - idx += 1 - } - } - return false -}; - -// another - -/** - * @param {number} n - * @return {boolean} - */ -const isPowerOfTwo = function(n) { - return Math.log2(n)%1 === 0 -}; - -// another - -/** - * @param {number} n - * @return {boolean} - */ -const isPowerOfTwo = n => n < 1 ? false : Number.MAX_VALUE % n === 0 - -// another - -/** - * @param {number} n - * @return {boolean} - */ -const isPowerOfTwo = x => x > 0 ? !(x & (x - 1)) : false; - diff --git a/231.power-of-two.js b/231.power-of-two.js new file mode 100644 index 00000000..cb434181 --- /dev/null +++ b/231.power-of-two.js @@ -0,0 +1,17 @@ +/** + * @param {number} n + * @return {boolean} + */ +const isPowerOfTwo = function(n) { + let tmp = 0 + let idx = 0 + while(tmp <= n) { + if((tmp = Math.pow(2, idx)) === n) { + return true + } else { + idx += 1 + } + } + return false +}; + diff --git a/2311-longest-binary-subsequence-less-than-or-equal-to-k.js b/2311.longest-binary-subsequence-less-than-or-equal-to-k.js similarity index 100% rename from 2311-longest-binary-subsequence-less-than-or-equal-to-k.js rename to 2311.longest-binary-subsequence-less-than-or-equal-to-k.js diff --git a/2312-selling-pieces-of-wood.js b/2312-selling-pieces-of-wood.js deleted file mode 100644 index 8cf6f8b5..00000000 --- a/2312-selling-pieces-of-wood.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @param {number} m - * @param {number} n - * @param {number[][]} prices - * @return {number} - */ -const sellingWood = function(m, n, prices) { - const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)) - for(const [h, w, p] of prices) { - dp[h][w] = p - } - - for (let i = 1; i <= m; ++i) { - for (let j = 1; j <= n; ++j) { - for (let k = 1; k <= i / 2; ++k) { - dp[i][j] = Math.max(dp[i][j], dp[k][j] + dp[i - k][j]); - } - for (let k = 1; k <= j / 2; ++k) { - dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[i][j - k]); - } - } - } - return dp[m][n]; -}; - -// another - -/** - * @param {number} m - * @param {number} n - * @param {number[][]} prices - * @return {number} - */ -const sellingWood = function(m, n, prices) { - const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)) - - for(const [h, w, p] of prices) dp[h][w] = p - for(let i = 1; i <= m; i++) { - for(let j = 1; j <= n; j++) { - for(let k = 1; k <= i / 2; k++) { - dp[i][j] = Math.max(dp[i][j], dp[k][j] + dp[i - k][j]) - } - - for(let k = 1; k <= j / 2; k++) { - dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[i][j - k]) - } - } - } - - return dp[m][n] -}; diff --git a/2312.selling-pieces-of-wood.js b/2312.selling-pieces-of-wood.js new file mode 100644 index 00000000..e4661b55 --- /dev/null +++ b/2312.selling-pieces-of-wood.js @@ -0,0 +1,25 @@ +/** + * @param {number} m + * @param {number} n + * @param {number[][]} prices + * @return {number} + */ +const sellingWood = function(m, n, prices) { + const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)) + for(const [h, w, p] of prices) { + dp[h][w] = p + } + + for (let i = 1; i <= m; ++i) { + for (let j = 1; j <= n; ++j) { + for (let k = 1; k <= i / 2; ++k) { + dp[i][j] = Math.max(dp[i][j], dp[k][j] + dp[i - k][j]); + } + for (let k = 1; k <= j / 2; ++k) { + dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[i][j - k]); + } + } + } + return dp[m][n]; +}; + diff --git a/2313-minimum-flips-in-binary-tree-to-get-result.js b/2313.minimum-flips-in-binary-tree-to-get-result.js similarity index 100% rename from 2313-minimum-flips-in-binary-tree-to-get-result.js rename to 2313.minimum-flips-in-binary-tree-to-get-result.js diff --git a/2317-maximum-xor-after-operations.js b/2317.maximum-xor-after-operations.js similarity index 100% rename from 2317-maximum-xor-after-operations.js rename to 2317.maximum-xor-after-operations.js diff --git a/2318-number-of-distinct-roll-sequences.js b/2318-number-of-distinct-roll-sequences.js deleted file mode 100644 index 14e19cee..00000000 --- a/2318-number-of-distinct-roll-sequences.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const distinctSequences = function(n) { - const hash = { - 1: [2,3,4,5,6], - 2: [1,3,5], - 3: [1,2,4,5], - 4: [1,3,5], - 5: [1,2,3,4,6], - 6: [1,5], - } - - const memo = kdArr(0, [7,7,n+1]) - const mod = 1e9 + 7 - let res = 0 - for(let i = 1; i <= 6; i++) { - res = (res + dfs(i, 0, n - 1)) % mod - } - - - return res - - function dfs(s,i,j) { - if(j === 0) return 1 - if(memo[s][i][j] !== 0) return memo[s][i][j] - let res = 0 - for(let e of hash[s]) { - if(e !== i) { - res = (res + dfs(e, s, j - 1)) % mod - } - } - memo[s][i][j] = res - return res - } - - function kdArr(defaultVal, arr) { - if(arr.length === 1) return Array(arr[0]).fill(defaultVal) - - const res = [] - for(let i = 0, len = arr[0]; i < len; i++) { - res.push(kdArr(defaultVal, arr.slice(1))) - } - - return res - } -}; - -// another - - -/** - * @param {number} n - * @return {number} - */ -const dp = MultidimensionalArray(0, 1e4 + 1, 7, 7) -const distinctSequences = function (n, p = 0, pp = 0) { - const mod = 1e9 + 7 - if (n === 0) return 1 - if (dp[n][p][pp] === 0) { - for (let d = 1; d < 7; d++) { - if (d !== p && d !== pp && (p === 0 || gcd(d, p) === 1)) { - dp[n][p][pp] = (dp[n][p][pp] + distinctSequences(n - 1, d, p)) % mod - } - } - } - - return dp[n][p][pp] -} - -function gcd(a, b) { - return b === 0 ? a : gcd(b, a % b) -} - -function MultidimensionalArray(defaultValue, ...args) { - if (args.length === 1) { - return Array(args[0]).fill(defaultValue) - } - const res = [] - - for (let i = 0, n = args[0]; i < n; i++) { - res.push(MultidimensionalArray(defaultValue, ...args.slice(1))) - } - - return res -} diff --git a/2318.number-of-distinct-roll-sequences.js b/2318.number-of-distinct-roll-sequences.js new file mode 100644 index 00000000..d08825ea --- /dev/null +++ b/2318.number-of-distinct-roll-sequences.js @@ -0,0 +1,49 @@ +/** + * @param {number} n + * @return {number} + */ +const distinctSequences = function(n) { + const hash = { + 1: [2,3,4,5,6], + 2: [1,3,5], + 3: [1,2,4,5], + 4: [1,3,5], + 5: [1,2,3,4,6], + 6: [1,5], + } + + const memo = kdArr(0, [7,7,n+1]) + const mod = 1e9 + 7 + let res = 0 + for(let i = 1; i <= 6; i++) { + res = (res + dfs(i, 0, n - 1)) % mod + } + + + return res + + function dfs(s,i,j) { + if(j === 0) return 1 + if(memo[s][i][j] !== 0) return memo[s][i][j] + let res = 0 + for(let e of hash[s]) { + if(e !== i) { + res = (res + dfs(e, s, j - 1)) % mod + } + } + memo[s][i][j] = res + return res + } + + function kdArr(defaultVal, arr) { + if(arr.length === 1) return Array(arr[0]).fill(defaultVal) + + const res = [] + for(let i = 0, len = arr[0]; i < len; i++) { + res.push(kdArr(defaultVal, arr.slice(1))) + } + + return res + } +}; + diff --git a/2319-check-if-matrix-is-x-matrix.js b/2319.check-if-matrix-is-x-matrix.js similarity index 100% rename from 2319-check-if-matrix-is-x-matrix.js rename to 2319.check-if-matrix-is-x-matrix.js diff --git a/232-implement-queue-using-stacks.js b/232.implement-queue-using-stacks.js similarity index 100% rename from 232-implement-queue-using-stacks.js rename to 232.implement-queue-using-stacks.js diff --git a/2320-count-number-of-ways-to-place-houses.js b/2320-count-number-of-ways-to-place-houses.js deleted file mode 100644 index b1d6f302..00000000 --- a/2320-count-number-of-ways-to-place-houses.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const countHousePlacements = function(n) { - const mod = BigInt(1e9 + 7) - let house = 1n, space = 1n, total = 2n - for(let i = 2; i <= n; i++) { - house = space - space = total - total = (house + space) % mod - } - - return total * total % mod -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -var countHousePlacements = function(n) { - const mod = 1e9 + 7 - let f0 = 1; - let f1 = 1; - for (let i = 1; i < n; i++) { - let nf0 = (f0 + f1) % mod; - let nf1 = f0; - f0 = nf0; - f1 = nf1; - } - let m = (f0 + f1) % mod; - return BigInt(m) * BigInt(m) % BigInt(mod) -}; diff --git a/2320.count-number-of-ways-to-place-houses.js b/2320.count-number-of-ways-to-place-houses.js new file mode 100644 index 00000000..1924abd5 --- /dev/null +++ b/2320.count-number-of-ways-to-place-houses.js @@ -0,0 +1,16 @@ +/** + * @param {number} n + * @return {number} + */ +const countHousePlacements = function(n) { + const mod = BigInt(1e9 + 7) + let house = 1n, space = 1n, total = 2n + for(let i = 2; i <= n; i++) { + house = space + space = total + total = (house + space) % mod + } + + return total * total % mod +}; + diff --git a/2321-maximum-score-of-spliced-array.js b/2321-maximum-score-of-spliced-array.js deleted file mode 100644 index 84fbf277..00000000 --- a/2321-maximum-score-of-spliced-array.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -var maximumsSplicedArray = function(nums1, nums2) { - let n = nums1.length; - let arr = new Array(n).fill(0); - let s1 = 0, s2 = 0; - for (let i = 0; i < n; i++) { - s1 += nums1[i]; - s2 += nums2[i]; - } - for (let i = 0; i < n; i++) { - arr[i] = nums1[i] - nums2[i]; - } - let sum = 0; - let min1 = 0; - let max1 = 0; - for (let i = 0; i < n; i++) { - sum += arr[i]; - max1 = Math.max(sum - min1, max1); - min1 = Math.min(min1, sum); - } - sum = 0; - let min2 = 0; - let max2 = 0; - for (let i = 0; i < n; i++) { - sum += arr[i]; - min2 = Math.min(sum - max2, min2); - max2 = Math.max(max2, sum); - } - return Math.max(s2 + max1, s1 - min2); -}; - -// another - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const maximumsSplicedArray = function (nums1, nums2) { - let sum1 = 0, - sum2 = 0, - max1 = 0, - max2 = 0, - ac1 = 0, - ac2 = 0 - sum1 = nums1.reduce((ac, e) => ac + e, 0) - sum2 = nums2.reduce((ac, e) => ac + e, 0) - const { max } = Math - let res = max(sum1, sum2) - for (let i = 0, n = nums1.length; i < n; i++) { - ac1 += nums1[i] - nums2[i] - ac2 += nums2[i] - nums1[i] - max1 = max(max1, ac1) - max2 = max(max2, ac2) - if(ac1 < 0) ac1 = 0 - if(ac2 < 0) ac2 = 0 - } - res = max(res, sum1 + max2, sum2 + max1) - - return res -} diff --git a/2321.maximum-score-of-spliced-array.js b/2321.maximum-score-of-spliced-array.js new file mode 100644 index 00000000..119eb540 --- /dev/null +++ b/2321.maximum-score-of-spliced-array.js @@ -0,0 +1,35 @@ +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var maximumsSplicedArray = function(nums1, nums2) { + let n = nums1.length; + let arr = new Array(n).fill(0); + let s1 = 0, s2 = 0; + for (let i = 0; i < n; i++) { + s1 += nums1[i]; + s2 += nums2[i]; + } + for (let i = 0; i < n; i++) { + arr[i] = nums1[i] - nums2[i]; + } + let sum = 0; + let min1 = 0; + let max1 = 0; + for (let i = 0; i < n; i++) { + sum += arr[i]; + max1 = Math.max(sum - min1, max1); + min1 = Math.min(min1, sum); + } + sum = 0; + let min2 = 0; + let max2 = 0; + for (let i = 0; i < n; i++) { + sum += arr[i]; + min2 = Math.min(sum - max2, min2); + max2 = Math.max(max2, sum); + } + return Math.max(s2 + max1, s1 - min2); +}; + diff --git a/2322-minimum-score-after-removals-on-a-tree.js b/2322-minimum-score-after-removals-on-a-tree.js deleted file mode 100644 index fe2fc586..00000000 --- a/2322-minimum-score-after-removals-on-a-tree.js +++ /dev/null @@ -1,141 +0,0 @@ -/** - * @param {number[]} nums - * @param {number[][]} edges - * @return {number} - */ -const minimumScore = function (nums, edges) { - const n = nums.length, m = edges.length - const graph = {} - const children = {} - const xor = nums.slice(0) - const degree = Array(n).fill(0) - - for(const [p, q] of edges) { - if(graph[p] == null) graph[p] = [] - if(graph[q] == null) graph[q] = [] - graph[p].push(q) - graph[q].push(p) - degree[p]++ - degree[q]++ - } - - let val = 0 - const seen = new Set() - const queue = [] - for(let i = 0; i < n; i++) { - val ^= nums[i] - if(degree[i] === 1) { - queue.push(i) - seen.add(i) - } - } - - while(queue.length) { - const cur = queue.shift() - for(const nxt of (graph[cur] || [])) { - if(!seen.has(nxt)) { - if(children[nxt] == null) children[nxt] = new Set() - children[nxt].add(cur) - for(const e of (children[cur] || [])) { - children[nxt].add(e) - } - xor[nxt] ^= xor[cur] - } - degree[nxt]-- - if(degree[nxt] === 1) { - seen.add(nxt) - queue.push(nxt) - } - } - } - - let res = Infinity - - for(let i = 0; i < m - 1; i++) { - for(let j = i + 1; j < m; j++) { - let [a, b] = edges[i] - // Let a, c be the lower break points - if(children[a]?.has(b)) { - ;[a, b] = [b, a] - } - let [c, d] = edges[j] - if(children[c]?.has(d)) { - ;[c, d] = [d, c] - } - let cur - if(children[a]?.has(c)) { - cur = [xor[c], xor[a] ^ xor[c], val ^ xor[a]] - } else if(children[c]?.has(a)) { - cur = [xor[a], xor[c] ^ xor[a], val ^ xor[c]] - } else { - cur = [xor[a], xor[c], val ^ xor[a] ^ xor[c]] - } - res = Math.min(res, Math.max(...cur) - Math.min(...cur)) - } - } - - return res -} - -// another - -/** - * @param {number[]} nums - * @param {number[][]} edges - * @return {number} - */ -var minimumScore = function (nums, edges) { - let n = nums.length, - ans = Infinity - let visited = Array(n).fill(0) - let pc = [] - let adj = Array.from({ length: n }, () => []) - let child_xor = Array(n).fill(0) - let childs = Array.from({ length: n }, () => Array(n).fill(false)) - const { min, max } = Math - let par = Array(n).fill(0) - - // Creating an adjacency matrix - for (const edge of edges) - adj[edge[0]].push(edge[1]), adj[edge[1]].push(edge[0]) - - dfs(0) - - // console.log(childs) - // console.log(pc) - for (let i = 0; i < pc.length; i++) - for (let j = i + 1; j < pc.length; j++) { - // removing an edge i and j - let a = pc[i][1], - b = pc[j][1] // node that will come below when you delete an edge i and j - let xa = child_xor[a], - xb = child_xor[b], - xc = child_xor[0] - // console.log(a,b) - if (childs[a][b]) (xc ^= xa), (xa ^= xb) - else (xc ^= xa), (xc ^= xb) - - ans = min(max(xa, max(xb, xc)) - min(xa, min(xb, xc)), ans) - } - - return ans - - function dfs(i) { - let ans = nums[i] - visited[i] = true - - for (let p of par) childs[p][i] = true // Defining this node as the child of all its parents - - par.push(i) - - for (let child of adj[i] || []) - if (!visited[child]) { - pc.push([i, child]) - ans ^= dfs(child) // Recurcively calculating xors - } - - par.pop() - - return (child_xor[i] = ans) - } -} diff --git a/2322.minimum-score-after-removals-on-a-tree.js b/2322.minimum-score-after-removals-on-a-tree.js new file mode 100644 index 00000000..6a1bd59f --- /dev/null +++ b/2322.minimum-score-after-removals-on-a-tree.js @@ -0,0 +1,79 @@ +/** + * @param {number[]} nums + * @param {number[][]} edges + * @return {number} + */ +const minimumScore = function (nums, edges) { + const n = nums.length, m = edges.length + const graph = {} + const children = {} + const xor = nums.slice(0) + const degree = Array(n).fill(0) + + for(const [p, q] of edges) { + if(graph[p] == null) graph[p] = [] + if(graph[q] == null) graph[q] = [] + graph[p].push(q) + graph[q].push(p) + degree[p]++ + degree[q]++ + } + + let val = 0 + const seen = new Set() + const queue = [] + for(let i = 0; i < n; i++) { + val ^= nums[i] + if(degree[i] === 1) { + queue.push(i) + seen.add(i) + } + } + + while(queue.length) { + const cur = queue.shift() + for(const nxt of (graph[cur] || [])) { + if(!seen.has(nxt)) { + if(children[nxt] == null) children[nxt] = new Set() + children[nxt].add(cur) + for(const e of (children[cur] || [])) { + children[nxt].add(e) + } + xor[nxt] ^= xor[cur] + } + degree[nxt]-- + if(degree[nxt] === 1) { + seen.add(nxt) + queue.push(nxt) + } + } + } + + let res = Infinity + + for(let i = 0; i < m - 1; i++) { + for(let j = i + 1; j < m; j++) { + let [a, b] = edges[i] + // Let a, c be the lower break points + if(children[a]?.has(b)) { + ;[a, b] = [b, a] + } + let [c, d] = edges[j] + if(children[c]?.has(d)) { + ;[c, d] = [d, c] + } + let cur + if(children[a]?.has(c)) { + cur = [xor[c], xor[a] ^ xor[c], val ^ xor[a]] + } else if(children[c]?.has(a)) { + cur = [xor[a], xor[c] ^ xor[a], val ^ xor[c]] + } else { + cur = [xor[a], xor[c], val ^ xor[a] ^ xor[c]] + } + res = Math.min(res, Math.max(...cur) - Math.min(...cur)) + } + } + + return res +} + diff --git a/2325-decode-the-message.js b/2325.decode-the-message.js similarity index 100% rename from 2325-decode-the-message.js rename to 2325.decode-the-message.js diff --git a/2326-spiral-matrix-iv.js b/2326.spiral-matrix-iv.js similarity index 100% rename from 2326-spiral-matrix-iv.js rename to 2326.spiral-matrix-iv.js diff --git a/2327-number-of-people-aware-of-a-secret.js b/2327-number-of-people-aware-of-a-secret.js deleted file mode 100644 index 8339fb12..00000000 --- a/2327-number-of-people-aware-of-a-secret.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @param {number} n - * @param {number} delay - * @param {number} forget - * @return {number} - */ -const peopleAwareOfSecret = function(n, delay, forget) { - const dp = Array(n + 1).fill(0) - const mod = 1e9 + 7 - - dp[1] = 1 - for(let i = 1; i <= n; i++) { - for(let j = i + delay; j < i + forget; j++) { - if(j > n) break - dp[j] += dp[i] - dp[j] %= mod - } - } - - let res = 0 - for(let i = n - forget + 1; i <= n; i++) { - res = (dp[i] + res) % mod - } - - return res -}; - -// another - -/** - * @param {number} n - * @param {number} delay - * @param {number} forget - * @return {number} - */ -const peopleAwareOfSecret = function(n, delay, forget) { - let cnt = new Array(n+1).fill(0); - cnt[1] = 1; - let i = 1; - let MOD = 1_000_000_007; - while (i+delay <= n) { - for (let j = i+delay; j <= Math.min(n, i+forget-1); j++) { - cnt[j] = (cnt[j]+cnt[i])%MOD; - } - i++; - } - let res = 0; - for (let j = n; j > n-forget; j--) { - res = (res + cnt[j])%MOD; - } - return res; -}; - -// another - -/** - * @param {number} n - * @param {number} delay - * @param {number} forget - * @return {number} - */ - const peopleAwareOfSecret = function(n, delay, forget) { - const mod = 1e9 + 7 - const dp = Array(n + 1).fill(0) - const { max } = Math - dp[1] = 1 - let share = 0 - for(let i = 2; i <= n; i++) { - share = (share + dp[max(0, i - delay)] - dp[max(i - forget, 0)] + mod) % mod - dp[i] = share - } - let res = 0 - for(let i = n - forget + 1; i <= n; i++) { - res = (res + dp[i]) % mod - } - return res -}; diff --git a/2327.number-of-people-aware-of-a-secret.js b/2327.number-of-people-aware-of-a-secret.js new file mode 100644 index 00000000..cfd47c35 --- /dev/null +++ b/2327.number-of-people-aware-of-a-secret.js @@ -0,0 +1,27 @@ +/** + * @param {number} n + * @param {number} delay + * @param {number} forget + * @return {number} + */ +const peopleAwareOfSecret = function(n, delay, forget) { + const dp = Array(n + 1).fill(0) + const mod = 1e9 + 7 + + dp[1] = 1 + for(let i = 1; i <= n; i++) { + for(let j = i + delay; j < i + forget; j++) { + if(j > n) break + dp[j] += dp[i] + dp[j] %= mod + } + } + + let res = 0 + for(let i = n - forget + 1; i <= n; i++) { + res = (dp[i] + res) % mod + } + + return res +}; + diff --git a/2328-number-of-increasing-paths-in-a-grid.js b/2328-number-of-increasing-paths-in-a-grid.js deleted file mode 100644 index e6b76dd6..00000000 --- a/2328-number-of-increasing-paths-in-a-grid.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const countPaths = function (grid) { - const mod = 1e9 + 7 - const m = grid.length, n = grid[0].length - let res = 0 - const dirs = [[1,0], [-1,0], [0, 1], [0, -1]] - const memo = Array.from({ length: m }, () => Array(n).fill(0)) - for(let i = 0; i = 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] > grid[i][j]) { - res = (res + dfs(nx, ny)) % mod - } - } - - memo[i][j] = res - - return res - } -} - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -var countPaths = function (grid) { - const MOD = 1e9 + 7 - let res = 0 - const M = grid.length, - N = grid[0].length - - const dp = Array.from({ length: M }, () => Array(N)) - - for (let r = 0; r < M; r++) { - for (let c = 0; c < N; c++) { - res = (res + dfs(r, c)) % MOD - } - } - return res - - function dfs(r, c) { - if (dp[r][c] != null) { - return dp[r][c] - } - let res = 1 - - for (const dir of [ - [-1, 0], - [0, -1], - [1, 0], - [0, 1], - ]) { - const nr = r + dir[0], - nc = c + dir[1] - if ( - nr < 0 || - nr >= M || - nc < 0 || - nc >= N || - grid[nr][nc] <= grid[r][c] - ) { - continue - } - res = (res + dfs(nr, nc)) % MOD - } - dp[r][c] = res - return res - } -} diff --git a/2328.number-of-increasing-paths-in-a-grid.js b/2328.number-of-increasing-paths-in-a-grid.js new file mode 100644 index 00000000..5cdd0262 --- /dev/null +++ b/2328.number-of-increasing-paths-in-a-grid.js @@ -0,0 +1,33 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const countPaths = function (grid) { + const mod = 1e9 + 7 + const m = grid.length, n = grid[0].length + let res = 0 + const dirs = [[1,0], [-1,0], [0, 1], [0, -1]] + const memo = Array.from({ length: m }, () => Array(n).fill(0)) + for(let i = 0; i = 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] > grid[i][j]) { + res = (res + dfs(nx, ny)) % mod + } + } + + memo[i][j] = res + + return res + } +} + diff --git a/233-number-of-digit-one.js b/233-number-of-digit-one.js deleted file mode 100644 index 82678200..00000000 --- a/233-number-of-digit-one.js +++ /dev/null @@ -1,121 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const countDigitOne = function(n) { - let res = 0 - const str = `${n}` - const len = str.length, { pow } = Math - - for(let i = 1; i <= len; i++) { - const pre = ~~(n / pow(10, i)) - const remain = n % (pow(10, i - 1)) - const post = pow(10, i - 1) - res += pre * post - const e = +(str[len - i]) - if(e > 1) { - res += pow(10, i - 1) - } else if(e === 1) { - res += remain + 1 - } - } - - return res -}; - - -// another - -/** - * @param {number} n - * @return {number} - */ -const countDigitOne = function(n) { - return countNum(1, n + 1) -}; - -// Counts the number of `digit` in the range [0, limit) -function countNum( digit, limit) { - let count = 0; - let factor = 1; - let tail = 0; - while (limit >= 10) { - let d = limit % 10; - limit = ~~(limit / 10); - count += limit * factor; - count += d > digit ? factor : d == digit ? tail : 0; - tail += d * factor; - factor *= 10; - } - return count + (limit > digit ? factor : limit == digit ? tail : 0); -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const countDigitOne = function(n) { - let count = 0 - for (let m = 1; m <= n; m *= 10) { - const a = Math.floor(n / m) - const b = n % m - if (a % 10 > 1) { - count += (Math.floor(a / 10) + 1) * m - } else if (a % 10 === 1) { - count += Math.floor(a / 10) * m + b + 1 - } else { - count += Math.floor(a / 10) * m - } - } - return count -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const countDigitOne = function (n) { - if (n <= 0) return 0 - let ones = 0 - for (let i = 1, q = n; i <= n; i *= 10, q = (q / 10) >> 0) { - const pre = (n / (i * 10)) >> 0, - cur = q % 10, - suf = n % i - ones += pre * i - ones += 1 < cur ? i : 1 == cur ? suf + 1 : 0 - } - return ones -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const countDigitOne = function(n) { - let res = 0, factor = 1, lower = 0, cur = 0, higher = 0 - while(~~(n / factor) !== 0) { - lower = n - (~~(n / factor)) * factor - cur = (~~(n / factor)) % 10 - higher = ~~(n / (factor * 10)) - switch(cur) { - case 0: - res += higher * factor - break - case 1: - res += higher * factor + lower + 1 - break - default: - res += (higher + 1) * factor - break - } - factor *= 10 - } - - return res -}; diff --git a/233.number-of-digit-one.js b/233.number-of-digit-one.js new file mode 100644 index 00000000..f8ff1f9f --- /dev/null +++ b/233.number-of-digit-one.js @@ -0,0 +1,26 @@ +/** + * @param {number} n + * @return {number} + */ +const countDigitOne = function(n) { + let res = 0 + const str = `${n}` + const len = str.length, { pow } = Math + + for(let i = 1; i <= len; i++) { + const pre = ~~(n / pow(10, i)) + const remain = n % (pow(10, i - 1)) + const post = pow(10, i - 1) + res += pre * post + const e = +(str[len - i]) + if(e > 1) { + res += pow(10, i - 1) + } else if(e === 1) { + res += remain + 1 + } + } + + return res +}; + + diff --git a/2332-the-latest-time-to-catch-a-bus.js b/2332.the-latest-time-to-catch-a-bus.js similarity index 100% rename from 2332-the-latest-time-to-catch-a-bus.js rename to 2332.the-latest-time-to-catch-a-bus.js diff --git a/2333-minimum-sum-of-squared-difference.js b/2333.minimum-sum-of-squared-difference.js similarity index 100% rename from 2333-minimum-sum-of-squared-difference.js rename to 2333.minimum-sum-of-squared-difference.js diff --git a/2334-subarray-with-elements-greater-than-varying-threshold.js b/2334.subarray-with-elements-greater-than-varying-threshold.js similarity index 100% rename from 2334-subarray-with-elements-greater-than-varying-threshold.js rename to 2334.subarray-with-elements-greater-than-varying-threshold.js diff --git a/2335-minimum-amount-of-time-to-fill-cups.js b/2335.minimum-amount-of-time-to-fill-cups.js similarity index 100% rename from 2335-minimum-amount-of-time-to-fill-cups.js rename to 2335.minimum-amount-of-time-to-fill-cups.js diff --git a/2336-smallest-number-in-infinite-set.js b/2336.smallest-number-in-infinite-set.js similarity index 100% rename from 2336-smallest-number-in-infinite-set.js rename to 2336.smallest-number-in-infinite-set.js diff --git a/2337-move-pieces-to-obtain-a-string.js b/2337.move-pieces-to-obtain-a-string.js similarity index 100% rename from 2337-move-pieces-to-obtain-a-string.js rename to 2337.move-pieces-to-obtain-a-string.js diff --git a/2338-count-the-number-of-ideal-arrays.js b/2338.count-the-number-of-ideal-arrays.js similarity index 100% rename from 2338-count-the-number-of-ideal-arrays.js rename to 2338.count-the-number-of-ideal-arrays.js diff --git a/234-palindrome-linked-list.js b/234.palindrome-linked-list.js similarity index 100% rename from 234-palindrome-linked-list.js rename to 234.palindrome-linked-list.js diff --git a/2340-minimum-adjacent-swaps-to-make-a-valid-array.js b/2340.minimum-adjacent-swaps-to-make-a-valid-array.js similarity index 100% rename from 2340-minimum-adjacent-swaps-to-make-a-valid-array.js rename to 2340.minimum-adjacent-swaps-to-make-a-valid-array.js diff --git a/2341-maximum-number-of-pairs-in-array.js b/2341.maximum-number-of-pairs-in-array.js similarity index 100% rename from 2341-maximum-number-of-pairs-in-array.js rename to 2341.maximum-number-of-pairs-in-array.js diff --git a/2342-max-sum-of-a-pair-with-equal-sum-of-digits.js b/2342.max-sum-of-a-pair-with-equal-sum-of-digits.js similarity index 100% rename from 2342-max-sum-of-a-pair-with-equal-sum-of-digits.js rename to 2342.max-sum-of-a-pair-with-equal-sum-of-digits.js diff --git a/2343-query-kth-smallest-trimmed-number.js b/2343.query-kth-smallest-trimmed-number.js similarity index 100% rename from 2343-query-kth-smallest-trimmed-number.js rename to 2343.query-kth-smallest-trimmed-number.js diff --git a/2344-minimum-deletions-to-make-array-divisible.js b/2344-minimum-deletions-to-make-array-divisible.js deleted file mode 100644 index cf3025b7..00000000 --- a/2344-minimum-deletions-to-make-array-divisible.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @param {number[]} nums - * @param {number[]} numsDivide - * @return {number} - */ -const minOperations = function (nums, numsDivide) { - nums.sort((a, b) => a - b) - let gcdVal = numsDivide[0] - - for(let i = 1, n = numsDivide.length; i < n; i++) { - gcdVal = gcd(gcdVal, numsDivide[i]) - } - - for(let i = 0, n = nums.length; i < n && nums[i] <= gcdVal; i++) { - if(gcdVal % nums[i] === 0) return i - } - - return -1 - - - function gcd(a,b) { - return b === 0 ? a : gcd(b, a % b) - } -} - -// another - -/** - * @param {number[]} nums - * @param {number[]} numsDivide - * @return {number} - */ -var minOperations = function(nums, numsDivide) { - let div = numsDivide[0], min = Infinity - for(let i = 1, n = numsDivide.length; i < n; i++) { - div = Math.min(div, gcd(numsDivide[i], div)) - min = Math.min(min, numsDivide[i]) - } - // console.log(div) - - nums.sort((a, b) => a - b) - if(div === 1 && nums[0] !== 1) return -1 - let res = 0 - for(const e of nums) { - if(e > min) break - if(div % e === 0) { - return res - } - if(e % div !== 0) res++ - else { - return res - } - } - - return -1 - - function gcd(a, b) { - return b === 0 ? a : gcd(b, a % b) - } -}; diff --git a/2344.minimum-deletions-to-make-array-divisible.js b/2344.minimum-deletions-to-make-array-divisible.js new file mode 100644 index 00000000..c336e2df --- /dev/null +++ b/2344.minimum-deletions-to-make-array-divisible.js @@ -0,0 +1,25 @@ +/** + * @param {number[]} nums + * @param {number[]} numsDivide + * @return {number} + */ +const minOperations = function (nums, numsDivide) { + nums.sort((a, b) => a - b) + let gcdVal = numsDivide[0] + + for(let i = 1, n = numsDivide.length; i < n; i++) { + gcdVal = gcd(gcdVal, numsDivide[i]) + } + + for(let i = 0, n = nums.length; i < n && nums[i] <= gcdVal; i++) { + if(gcdVal % nums[i] === 0) return i + } + + return -1 + + + function gcd(a,b) { + return b === 0 ? a : gcd(b, a % b) + } +} + diff --git a/2347-best-poker-hand.js b/2347.best-poker-hand.js similarity index 100% rename from 2347-best-poker-hand.js rename to 2347.best-poker-hand.js diff --git a/2348-number-of-zero-filled-subarrays.js b/2348.number-of-zero-filled-subarrays.js similarity index 100% rename from 2348-number-of-zero-filled-subarrays.js rename to 2348.number-of-zero-filled-subarrays.js diff --git a/235-lowest-common-ancestor-of-a-binary-search-tree.js b/235-lowest-common-ancestor-of-a-binary-search-tree.js deleted file mode 100644 index 205bcf3d..00000000 --- a/235-lowest-common-ancestor-of-a-binary-search-tree.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ - -/** - * @param {TreeNode} root - * @param {TreeNode} p - * @param {TreeNode} q - * @return {TreeNode} - */ -const lowestCommonAncestor = function(root, p, q) { - if(root == null || root == p || root == q) return root - const left = lowestCommonAncestor(root.left, p, q) - const right = lowestCommonAncestor(root.right, p, q) - if(left && right) return root - return left || right -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {TreeNode} p - * @param {TreeNode} q - * @return {TreeNode} - */ -const lowestCommonAncestor = function(root, p, q) { - while((root.val - p.val) * (root.val - q.val) > 0) { - root = root.val > p.val ? root.left : root.right - } - return root -}; diff --git a/235.lowest-common-ancestor-of-a-binary-search-tree.js b/235.lowest-common-ancestor-of-a-binary-search-tree.js new file mode 100644 index 00000000..5ab9bfad --- /dev/null +++ b/235.lowest-common-ancestor-of-a-binary-search-tree.js @@ -0,0 +1,22 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ + +/** + * @param {TreeNode} root + * @param {TreeNode} p + * @param {TreeNode} q + * @return {TreeNode} + */ +const lowestCommonAncestor = function(root, p, q) { + if(root == null || root == p || root == q) return root + const left = lowestCommonAncestor(root.left, p, q) + const right = lowestCommonAncestor(root.right, p, q) + if(left && right) return root + return left || right +}; + diff --git a/2350-shortest-impossible-sequence-of-rolls.js b/2350.shortest-impossible-sequence-of-rolls.js similarity index 100% rename from 2350-shortest-impossible-sequence-of-rolls.js rename to 2350.shortest-impossible-sequence-of-rolls.js diff --git a/2351-first-letter-to-appear-twice.js b/2351.first-letter-to-appear-twice.js similarity index 100% rename from 2351-first-letter-to-appear-twice.js rename to 2351.first-letter-to-appear-twice.js diff --git a/2352-equal-row-and-column-pairs.js b/2352.equal-row-and-column-pairs.js similarity index 100% rename from 2352-equal-row-and-column-pairs.js rename to 2352.equal-row-and-column-pairs.js diff --git a/2353-design-a-food-rating-system.js b/2353.design-a-food-rating-system.js similarity index 100% rename from 2353-design-a-food-rating-system.js rename to 2353.design-a-food-rating-system.js diff --git a/2354-number-of-excellent-pairs.js b/2354-number-of-excellent-pairs.js deleted file mode 100644 index b610661b..00000000 --- a/2354-number-of-excellent-pairs.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const countExcellentPairs = function(nums, k) { - const cnt = Array(31).fill(0), set = new Set(nums) - for(const e of set) { - cnt[setBits(e)]++ - } - let res = 0 - - for(let i = 1; i < 31; i++) { - for(let j = 1; j < 31; j++) { - if(i + j >= k) res += cnt[i] * cnt[j] - } - } - - return res - - function setBits(num) { - let res = 0 - while(num) { - res += num % 2 - num = num >> 1 - } - return res - } -}; - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const countExcellentPairs = function(nums, k) { - const arr = [], set = new Set(nums) - for(const e of set) { - arr.push(setBits(e)) - } - - arr.sort((a, b) => a - b) - let res = 0 - for(let i = 0, n = arr.length; i < n; i++) { - const idx = bs(arr, k - arr[i]) - res += n - idx - } - return res - - - function bs(arr, target) { - let l = 0, r = arr.length - - while(l < r) { - const mid = (l + r) >> 1 - if(arr[mid] < target) l = mid + 1 - else r = mid - } - - return l - } - function setBits(num) { - let res = 0 - while(num) { - res += num % 2 - num = num >> 1 - } - return res - } -}; diff --git a/2354.number-of-excellent-pairs.js b/2354.number-of-excellent-pairs.js new file mode 100644 index 00000000..e6841f24 --- /dev/null +++ b/2354.number-of-excellent-pairs.js @@ -0,0 +1,30 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const countExcellentPairs = function(nums, k) { + const cnt = Array(31).fill(0), set = new Set(nums) + for(const e of set) { + cnt[setBits(e)]++ + } + let res = 0 + + for(let i = 1; i < 31; i++) { + for(let j = 1; j < 31; j++) { + if(i + j >= k) res += cnt[i] * cnt[j] + } + } + + return res + + function setBits(num) { + let res = 0 + while(num) { + res += num % 2 + num = num >> 1 + } + return res + } +}; + diff --git a/2355-maximum-number-of-books-you-can-take.js b/2355.maximum-number-of-books-you-can-take.js similarity index 100% rename from 2355-maximum-number-of-books-you-can-take.js rename to 2355.maximum-number-of-books-you-can-take.js diff --git a/2357-make-array-zero-by-subtracting-equal-amounts.js b/2357.make-array-zero-by-subtracting-equal-amounts.js similarity index 100% rename from 2357-make-array-zero-by-subtracting-equal-amounts.js rename to 2357.make-array-zero-by-subtracting-equal-amounts.js diff --git a/2358-maximum-number-of-groups-entering-a-competition.js b/2358.maximum-number-of-groups-entering-a-competition.js similarity index 100% rename from 2358-maximum-number-of-groups-entering-a-competition.js rename to 2358.maximum-number-of-groups-entering-a-competition.js diff --git a/2359-find-closest-node-to-given-two-nodes.js b/2359.find-closest-node-to-given-two-nodes.js similarity index 100% rename from 2359-find-closest-node-to-given-two-nodes.js rename to 2359.find-closest-node-to-given-two-nodes.js diff --git a/236-lowest-common-ancestor-of-a-binary-tree.js b/236-lowest-common-ancestor-of-a-binary-tree.js deleted file mode 100644 index c0b40692..00000000 --- a/236-lowest-common-ancestor-of-a-binary-tree.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {TreeNode} p - * @param {TreeNode} q - * @return {TreeNode} - */ -const lowestCommonAncestor = function(root, p, q) { - const arr = [] - traverse(root, [], arr) - let pii - let qii - // in same path - for(let i = 0; i < arr.length; i++) { - let pi = arr[i].indexOf(p.val) - let qi = arr[i].indexOf(q.val) - if(pi !== -1) pii = [i, pi] - if(qi !== -1) qii = [i, qi] - if(pi !== -1 && qi !== -1) { - return new TreeNode( pi <= qi ? p.val : q.val ) - } - } - - const len = Math.min(arr[pii[0]].length, arr[qii[0]].length) - const pp = arr[pii[0]] - const qp = arr[qii[0]] - for(let i = 0; i < len; i++) { - if(pp[i] !== qp[i]) return new TreeNode(pp[i - 1]) - } -}; - -function traverse(node, path = [], arr) { - if(node == null) return - path.push(node.val) - if(node.left === null && node.right === null) { - arr.push(path.slice(0)) - return - } - traverse(node.left, path.slice(0), arr) - traverse(node.right, path.slice(0), arr) -} - -// another - -const lowestCommonAncestor = function(root, p, q) { - if(root === null || root === p || root === q) return root; - const left = lowestCommonAncestor(root.left, p, q); - const right = lowestCommonAncestor(root.right, p, q); - if(left && right) return root; - return left ? left : right; -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {TreeNode} p - * @param {TreeNode} q - * @return {TreeNode} - */ -const lowestCommonAncestor = function(root, p, q) { - if(root == null || root === p || root === q) return root - const left = lowestCommonAncestor(root.left, p, q) - const right = lowestCommonAncestor(root.right, p, q) - if(left && right) return root - return left || right -}; diff --git a/236.lowest-common-ancestor-of-a-binary-tree.js b/236.lowest-common-ancestor-of-a-binary-tree.js new file mode 100644 index 00000000..a8979914 --- /dev/null +++ b/236.lowest-common-ancestor-of-a-binary-tree.js @@ -0,0 +1,48 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {TreeNode} p + * @param {TreeNode} q + * @return {TreeNode} + */ +const lowestCommonAncestor = function(root, p, q) { + const arr = [] + traverse(root, [], arr) + let pii + let qii + // in same path + for(let i = 0; i < arr.length; i++) { + let pi = arr[i].indexOf(p.val) + let qi = arr[i].indexOf(q.val) + if(pi !== -1) pii = [i, pi] + if(qi !== -1) qii = [i, qi] + if(pi !== -1 && qi !== -1) { + return new TreeNode( pi <= qi ? p.val : q.val ) + } + } + + const len = Math.min(arr[pii[0]].length, arr[qii[0]].length) + const pp = arr[pii[0]] + const qp = arr[qii[0]] + for(let i = 0; i < len; i++) { + if(pp[i] !== qp[i]) return new TreeNode(pp[i - 1]) + } +}; + +function traverse(node, path = [], arr) { + if(node == null) return + path.push(node.val) + if(node.left === null && node.right === null) { + arr.push(path.slice(0)) + return + } + traverse(node.left, path.slice(0), arr) + traverse(node.right, path.slice(0), arr) +} + diff --git a/2360-longest-cycle-in-a-graph.js b/2360.longest-cycle-in-a-graph.js similarity index 100% rename from 2360-longest-cycle-in-a-graph.js rename to 2360.longest-cycle-in-a-graph.js diff --git a/2365-task-scheduler-ii.js b/2365.task-scheduler-ii.js similarity index 100% rename from 2365-task-scheduler-ii.js rename to 2365.task-scheduler-ii.js diff --git a/2366-minimum-replacements-to-sort-the-array.js b/2366.minimum-replacements-to-sort-the-array.js similarity index 100% rename from 2366-minimum-replacements-to-sort-the-array.js rename to 2366.minimum-replacements-to-sort-the-array.js diff --git a/2367-count-number-of-bad-pairs.js b/2367.count-number-of-bad-pairs.js similarity index 100% rename from 2367-count-number-of-bad-pairs.js rename to 2367.count-number-of-bad-pairs.js diff --git a/2367-number-of-arithmetic-triplets.js b/2367.number-of-arithmetic-triplets.js similarity index 100% rename from 2367-number-of-arithmetic-triplets.js rename to 2367.number-of-arithmetic-triplets.js diff --git a/2368-reachable-nodes-with-restrictions.js b/2368.reachable-nodes-with-restrictions.js similarity index 100% rename from 2368-reachable-nodes-with-restrictions.js rename to 2368.reachable-nodes-with-restrictions.js diff --git a/2369-check-if-there-is-a-valid-partition-for-the-array.js b/2369.check-if-there-is-a-valid-partition-for-the-array.js similarity index 100% rename from 2369-check-if-there-is-a-valid-partition-for-the-array.js rename to 2369.check-if-there-is-a-valid-partition-for-the-array.js diff --git a/237-delete-node-in-a-linked-list.js b/237-delete-node-in-a-linked-list.js deleted file mode 100755 index 84ee87b1..00000000 --- a/237-delete-node-in-a-linked-list.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} node - * @return {void} Do not return anything, modify node in-place instead. - */ -const deleteNode = function(node) { - if (node.next !== null) { - node.val = node.next.val; - node.next = node.next.next; - } -}; diff --git a/237.delete-node-in-a-linked-list.js b/237.delete-node-in-a-linked-list.js new file mode 100644 index 00000000..03cb8214 --- /dev/null +++ b/237.delete-node-in-a-linked-list.js @@ -0,0 +1,17 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} node + * @return {void} Do not return anything, modify node in-place instead. + */ +const deleteNode = function(node) { + if (node.next !== null) { + node.val = node.next.val; + node.next = node.next.next; + } +}; diff --git a/2370-longest-ideal-subsequence.js b/2370-longest-ideal-subsequence.js deleted file mode 100644 index b9f66ca6..00000000 --- a/2370-longest-ideal-subsequence.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @param {string} s - * @param {number} k - * @return {number} - */ -const longestIdealString = function(s, k) { - const n = s.length, a = 'a'.charCodeAt(0) - const dp = Array(26).fill(0) - let res = 0 - - for(let i = 0; i < n; i++) { - const cur = s[i], curCode = cur.charCodeAt(0) - const tmp = helper(curCode - a) + 1 - dp[curCode - a] = tmp - res = Math.max(res, tmp) - } - // console.log(dp) - return res - - function helper(end) { - let res = 0 - for(let i = Math.max(0, end - k), e = Math.min(25, end + k); i <= e; i++) { - if(dp[i] > res) res = dp[i] - } - - return res - } -}; - - -// another - -/** - * @param {string} s - * @param {number} k - * @return {number} - */ -const longestIdealString = function(s, k) { - const n = s.length - const arr = [], a = 'a'.charCodeAt(0) - for(const ch of s) { - arr.push(ch.charCodeAt(0) - a) - } - const dp = Array(26).fill(0) - for(const e of arr) { - dp[e] = 1 + Math.max(...dp.slice(Math.max(0, e - k), e + k + 1)) - } - return Math.max(...dp) -}; - diff --git a/2370.longest-ideal-subsequence.js b/2370.longest-ideal-subsequence.js new file mode 100644 index 00000000..4ecba50f --- /dev/null +++ b/2370.longest-ideal-subsequence.js @@ -0,0 +1,30 @@ +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +const longestIdealString = function(s, k) { + const n = s.length, a = 'a'.charCodeAt(0) + const dp = Array(26).fill(0) + let res = 0 + + for(let i = 0; i < n; i++) { + const cur = s[i], curCode = cur.charCodeAt(0) + const tmp = helper(curCode - a) + 1 + dp[curCode - a] = tmp + res = Math.max(res, tmp) + } + // console.log(dp) + return res + + function helper(end) { + let res = 0 + for(let i = Math.max(0, end - k), e = Math.min(25, end + k); i <= e; i++) { + if(dp[i] > res) res = dp[i] + } + + return res + } +}; + + diff --git a/2373-largest-local-values-in-a-matrix.js b/2373.largest-local-values-in-a-matrix.js similarity index 100% rename from 2373-largest-local-values-in-a-matrix.js rename to 2373.largest-local-values-in-a-matrix.js diff --git a/2374-node-with-highest-edge-score.js b/2374.node-with-highest-edge-score.js similarity index 100% rename from 2374-node-with-highest-edge-score.js rename to 2374.node-with-highest-edge-score.js diff --git a/2375-construct-smallest-number-from-di-string.js b/2375.construct-smallest-number-from-di-string.js similarity index 100% rename from 2375-construct-smallest-number-from-di-string.js rename to 2375.construct-smallest-number-from-di-string.js diff --git a/2376-count-special-integers.js b/2376-count-special-integers.js deleted file mode 100644 index c2f74b4f..00000000 --- a/2376-count-special-integers.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -var countSpecialNumbers = function(n) { - const L = []; - for (let x = n + 1; x > 0; x = Math.floor(x / 10)) L.unshift(x % 10); - - // Count the number with digits < N - let res = 0, - limit = L.length; - for (let i = 1; i < limit; ++i) res += 9 * A(9, i - 1); - - const seen = new Set(); - for (let i = 0; i < limit; ++i) { - for (let j = i > 0 ? 0 : 1; j < L[i]; ++j) - if (!seen.has(j)) res += A(9 - i, limit - i - 1); - if (seen.has(L[i])) break; - seen.add(L[i]); - } - return res; -}; - - -function A(m, n) { - return n === 0 ? 1 : A(m, n - 1) * (m - n + 1); -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const countSpecialNumbers = function (n) { - const s = '' + n - const dp = Array.from({ length: 11 }, () => - Array.from({ length: 2 }, () => Array(1024).fill(-1)) - ) - - return helper(0, 1, 0, s) - function helper(idx, tight = 1, mask = 0, digits) { - if (idx == digits.length) return mask !== 0 ? 1 : 0 - - if (dp[idx][tight][mask] != -1) return dp[idx][tight][mask] - - let k = tight ? +digits[idx] : 9 - let ans = 0 - - for (let i = 0; i <= k; i++) { - if (mask & (1 << i)) continue - let newMask = mask == 0 && i == 0 ? mask : mask | (1 << i) - - let nextTight = tight && i == digits[idx] ? 1 : 0 - ans += helper(idx + 1, nextTight, newMask, digits) - } - - return (dp[idx][tight][mask] = ans) - } -} diff --git a/2376.count-special-integers.js b/2376.count-special-integers.js new file mode 100644 index 00000000..8ef21dec --- /dev/null +++ b/2376.count-special-integers.js @@ -0,0 +1,28 @@ +/** + * @param {number} n + * @return {number} + */ +var countSpecialNumbers = function(n) { + const L = []; + for (let x = n + 1; x > 0; x = Math.floor(x / 10)) L.unshift(x % 10); + + // Count the number with digits < N + let res = 0, + limit = L.length; + for (let i = 1; i < limit; ++i) res += 9 * A(9, i - 1); + + const seen = new Set(); + for (let i = 0; i < limit; ++i) { + for (let j = i > 0 ? 0 : 1; j < L[i]; ++j) + if (!seen.has(j)) res += A(9 - i, limit - i - 1); + if (seen.has(L[i])) break; + seen.add(L[i]); + } + return res; +}; + + +function A(m, n) { + return n === 0 ? 1 : A(m, n - 1) * (m - n + 1); +} + diff --git a/238-product-of-array-except-self.js b/238-product-of-array-except-self.js deleted file mode 100755 index ccf2aa3e..00000000 --- a/238-product-of-array-except-self.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[]} - */ -const productExceptSelf = function(nums) { - const zeroIdx = new Set(); - const p = nums.reduce((ac, el, idx) => { - if (el === 0) { - zeroIdx.add(idx); - return ac; - } else { - return ac * el; - } - }, 1); - const res = []; - for (let i = 0; i < nums.length; i++) { - if (zeroIdx.size > 1) { - res.push(0); - } else if (zeroIdx.size === 1) { - res.push(i === [...zeroIdx.values()][0] ? p : 0); - } else { - res.push(p / nums[i]); - } - } - return res; -}; - diff --git a/238.product-of-array-except-self.js b/238.product-of-array-except-self.js new file mode 100644 index 00000000..619d6aeb --- /dev/null +++ b/238.product-of-array-except-self.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} nums + * @return {number[]} + */ +const productExceptSelf = function(nums) { + const zeroIdx = new Set(); + const p = nums.reduce((ac, el, idx) => { + if (el === 0) { + zeroIdx.add(idx); + return ac; + } else { + return ac * el; + } + }, 1); + const res = []; + for (let i = 0; i < nums.length; i++) { + if (zeroIdx.size > 1) { + res.push(0); + } else if (zeroIdx.size === 1) { + res.push(i === [...zeroIdx.values()][0] ? p : 0); + } else { + res.push(p / nums[i]); + } + } + return res; +}; + diff --git a/2380-time-needed-to-rearrange-a-binary-string.js b/2380-time-needed-to-rearrange-a-binary-string.js deleted file mode 100644 index 08f3cfc3..00000000 --- a/2380-time-needed-to-rearrange-a-binary-string.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const secondsToRemoveOccurrences = function(s) { - let zeros = 0 - const n = s.length, { max } = Math - let res = 0 - - for(let i = 0; i < n; i++) { - if(s[i] === '0') zeros++ - if(s[i] === '1' && zeros > 0) { - res = max(res + 1, zeros) - } - } - return res -}; - -// another - - -/** - * @param {string} s - * @return {number} - */ -var secondsToRemoveOccurrences = function(s) { - const n = s.length - let zeros = 0, seconds = 0; - for (let i = 0; i < n; ++i) { - zeros += s.charAt(i) == '0' ? 1 : 0; - if (s.charAt(i) == '1' && zeros > 0) - seconds = Math.max(seconds + 1, zeros); - } - return seconds; -}; diff --git a/2380.time-needed-to-rearrange-a-binary-string.js b/2380.time-needed-to-rearrange-a-binary-string.js new file mode 100644 index 00000000..124aaa0a --- /dev/null +++ b/2380.time-needed-to-rearrange-a-binary-string.js @@ -0,0 +1,18 @@ +/** + * @param {string} s + * @return {number} + */ +const secondsToRemoveOccurrences = function(s) { + let zeros = 0 + const n = s.length, { max } = Math + let res = 0 + + for(let i = 0; i < n; i++) { + if(s[i] === '0') zeros++ + if(s[i] === '1' && zeros > 0) { + res = max(res + 1, zeros) + } + } + return res +}; + diff --git a/2381-shifting-letters-ii.js b/2381.shifting-letters-ii.js similarity index 100% rename from 2381-shifting-letters-ii.js rename to 2381.shifting-letters-ii.js diff --git a/2382-maximum-segment-sum-after-removals.js b/2382.maximum-segment-sum-after-removals.js similarity index 100% rename from 2382-maximum-segment-sum-after-removals.js rename to 2382.maximum-segment-sum-after-removals.js diff --git a/2383-minimum-hours-of-training-to-win-a-competition.js b/2383.minimum-hours-of-training-to-win-a-competition.js similarity index 100% rename from 2383-minimum-hours-of-training-to-win-a-competition.js rename to 2383.minimum-hours-of-training-to-win-a-competition.js diff --git a/2384-largest-palindromic-number.js b/2384.largest-palindromic-number.js similarity index 100% rename from 2384-largest-palindromic-number.js rename to 2384.largest-palindromic-number.js diff --git a/2385-amount-of-time-for-binary-tree-to-be-infected.js b/2385.amount-of-time-for-binary-tree-to-be-infected.js similarity index 100% rename from 2385-amount-of-time-for-binary-tree-to-be-infected.js rename to 2385.amount-of-time-for-binary-tree-to-be-infected.js diff --git a/2386-find-the-k-sum-of-an-array.js b/2386-find-the-k-sum-of-an-array.js deleted file mode 100644 index 491ad86b..00000000 --- a/2386-find-the-k-sum-of-an-array.js +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -var kSum = function(nums, k) { - let sum = 0, n = nums.length, pq = new MaxPriorityQueue({ compare: (x, y) => y[0] - x[0] }); - for (let i = 0; i < n; i++) { - if (nums[i] < 0) { - nums[i] *= -1; - } else { - sum += nums[i]; - } - } - if (k == 1) return sum; - nums.sort((x, y) => x - y); - pq.enqueue([sum - nums[0], 0]); - for (let i = 2; i < k; i++) { - let [x, idx] = pq.dequeue(); - if (idx + 1 < n) { - pq.enqueue([x + nums[idx] - nums[idx + 1], idx + 1]); - pq.enqueue([x - nums[idx + 1], idx + 1]); - } - } - return pq.front()[0]; -}; - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const kSum = function (nums, k) { - let sum = 0, - n = nums.length, - pq = new PriorityQueue((x, y) => y[0] < x[0]) - for (let i = 0; i < n; i++) { - if (nums[i] < 0) { - nums[i] *= -1 - } else { - sum += nums[i] - } - } - if (k == 1) return sum - nums.sort((x, y) => x - y) - pq.push([sum - nums[0], 0]) - for (let i = 2; i < k; i++) { - let [x, idx] = pq.pop() - if (idx + 1 < n) { - pq.push([x + nums[idx] - nums[idx + 1], idx + 1]) - pq.push([x - nums[idx + 1], idx + 1]) - } - } - return pq.peek()[0] -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/2386.find-the-k-sum-of-an-array.js b/2386.find-the-k-sum-of-an-array.js new file mode 100644 index 00000000..64d64f4e --- /dev/null +++ b/2386.find-the-k-sum-of-an-array.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var kSum = function(nums, k) { + let sum = 0, n = nums.length, pq = new MaxPriorityQueue({ compare: (x, y) => y[0] - x[0] }); + for (let i = 0; i < n; i++) { + if (nums[i] < 0) { + nums[i] *= -1; + } else { + sum += nums[i]; + } + } + if (k == 1) return sum; + nums.sort((x, y) => x - y); + pq.enqueue([sum - nums[0], 0]); + for (let i = 2; i < k; i++) { + let [x, idx] = pq.dequeue(); + if (idx + 1 < n) { + pq.enqueue([x + nums[idx] - nums[idx + 1], idx + 1]); + pq.enqueue([x - nums[idx + 1], idx + 1]); + } + } + return pq.front()[0]; +}; + diff --git a/2389-longest-subsequence-with-limited-sum.js b/2389.longest-subsequence-with-limited-sum.js similarity index 100% rename from 2389-longest-subsequence-with-limited-sum.js rename to 2389.longest-subsequence-with-limited-sum.js diff --git a/239-sliding-window-maximum.js b/239-sliding-window-maximum.js deleted file mode 100644 index 3fdf50a4..00000000 --- a/239-sliding-window-maximum.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number[]} - */ -const maxSlidingWindow = function(nums, k) { - const n = nums.length - const stk = [] - const res = [] - - for(let i = 0; i < n; i++) { - while(stk.length && stk[0] < i - k + 1) { - stk.shift() - } - while(stk.length && nums[stk[stk.length - 1]] <= nums[i]) { - stk.pop() - } - stk.push(i) - if(i >= k - 1) { - res.push(nums[stk[0]]) - } - } - - return res -}; - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number[]} - */ -var maxSlidingWindow = function (nums, k) { - if (k === 0) return [] - const deque = new Deque() - for (let i = 0; i < k - 1; i++) { - while (!deque.isEmpty() && deque.last().val <= nums[i]) deque.pop() - deque.enqueue({ val: nums[i], idx: i }) - } - const result = [] - for (let i = k - 1; i < nums.length; i++) { - if (!deque.isEmpty() && deque.first().idx <= i - k) deque.dequeue() - while (!deque.isEmpty() && deque.last().val <= nums[i]) deque.pop() - deque.enqueue({ val: nums[i], idx: i }) - result.push(deque.first().val) - } - return result -} - -class Deque { - constructor() { - this.head = new Node() - this.tail = this.head - } - - isEmpty() { - return this.head.next === null - } - - first() { - return this.head.next.value - } - - last() { - return this.tail.value - } - - dequeue() { - this.head = this.head.next - this.head.prev = null - } - - enqueue(value) { - this.tail.next = new Node(value) - this.tail.next.prev = this.tail - this.tail = this.tail.next - } - - pop() { - this.tail = this.tail.prev - this.tail.next = null - } -} - -class Node { - constructor(value) { - this.value = value - this.next = null - this.prev = null - } -} diff --git a/239.sliding-window-maximum.js b/239.sliding-window-maximum.js new file mode 100644 index 00000000..d4c1da63 --- /dev/null +++ b/239.sliding-window-maximum.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number[]} + */ +const maxSlidingWindow = function(nums, k) { + const n = nums.length + const stk = [] + const res = [] + + for(let i = 0; i < n; i++) { + while(stk.length && stk[0] < i - k + 1) { + stk.shift() + } + while(stk.length && nums[stk[stk.length - 1]] <= nums[i]) { + stk.pop() + } + stk.push(i) + if(i >= k - 1) { + res.push(nums[stk[0]]) + } + } + + return res +}; + diff --git a/2390-removing-stars-from-a-string.js b/2390.removing-stars-from-a-string.js similarity index 100% rename from 2390-removing-stars-from-a-string.js rename to 2390.removing-stars-from-a-string.js diff --git a/2391-minimum-amount-of-time-to-collect-garbage.js b/2391.minimum-amount-of-time-to-collect-garbage.js similarity index 100% rename from 2391-minimum-amount-of-time-to-collect-garbage.js rename to 2391.minimum-amount-of-time-to-collect-garbage.js diff --git a/2392-build-a-matrix-with-conditions.js b/2392-build-a-matrix-with-conditions.js deleted file mode 100644 index 8bd4d8ac..00000000 --- a/2392-build-a-matrix-with-conditions.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @param {number} k - * @param {number[][]} rowConditions - * @param {number[][]} colConditions - * @return {number[][]} - */ -const buildMatrix = function (k, rowConditions, colConditions) { - const res = Array.from({ length: k }, () => Array(k).fill(0)) - - const row = khansAlgo(rowConditions, k) - if (row.length != k) return [] - - const col = khansAlgo(colConditions, k) - if (col.length != k) return [] - - const idx = Array(k + 1).fill(0) - for (let j = 0; j < col.length; j++) { - idx[col[j]] = j - } - for (let i = 0; i < k; i++) { - res[i][idx[row[i]]] = row[i] - } - return res - - function khansAlgo(r, k) { - const indegree = Array(k + 1).fill(0) - const adj = Array.from({ length: k + 1 }, () => Array()) - - for (let x of r) { - indegree[x[1]]++ - adj[x[0]].push(x[1]) - } - const row = [] - const q = [] - for (let i = 1; i <= k; i++) { - if (indegree[i] == 0) { - q.push(i) - } - } - while (q.length) { - let t = q.pop() - - row.push(t) - for (let x of adj[t] || []) { - indegree[x]-- - if (indegree[x] == 0) { - q.push(x) - } - } - } - return row - } -} - - - -// another - -/** - * @param {number} k - * @param {number[][]} rowConditions - * @param {number[][]} colConditions - * @return {number[][]} - */ -const initializeGraph = (n) => { - let g = [] - for (let i = 0; i < n; i++) { - g.push([]) - } - return g -} -const packDGInDegree = (g, edges, indegree) => { - for (const [u, v] of edges) { - g[u].unshift(v) - indegree[v]++ - } -} -const initialize2DArray = (n, m) => { - let d = [] - for (let i = 0; i < n; i++) { - let t = Array(m).fill(0) - d.push(t) - } - return d -} - -const buildMatrix = (k, rowConditions, colConditions) => { - let gr = make(k, rowConditions), - gc = make(k, colConditions), - d = initialize2DArray(k, 2), - res = initialize2DArray(k, k) - if (gr.length == 0 || gc.length == 0) return [] - for (let i = 0; i < k; i++) { - d[gr[i] - 1][0] = i - d[gc[i] - 1][1] = i - } - for (let i = 0; i < k; i++) { - let [x, y] = d[i] - res[x][y] = i + 1 - } - return res -} - -const make = (n, edges) => { - let g = initializeGraph(n + 1), - deg = Array(n + 1).fill(0) - packDGInDegree(g, edges, deg) - return topologicalSort_start_1(g, deg) -} - -const topologicalSort_start_1 = (g, indegree) => { - let res = [], - q = [], - n = g.length - 1 - for (let i = 1; i <= n; i++) { - if (indegree[i] == 0) q.push(i) - } - while (q.length) { - let cur = q.shift() - res.push(cur) - for (const child of g[cur]) { - indegree[child]-- - if (indegree[child] == 0) q.push(child) - } - } - for (let i = 1; i <= n; i++) { - if (indegree[i] > 0) return [] - } - return res -} diff --git a/2392.build-a-matrix-with-conditions.js b/2392.build-a-matrix-with-conditions.js new file mode 100644 index 00000000..1c19dfbd --- /dev/null +++ b/2392.build-a-matrix-with-conditions.js @@ -0,0 +1,56 @@ +/** + * @param {number} k + * @param {number[][]} rowConditions + * @param {number[][]} colConditions + * @return {number[][]} + */ +const buildMatrix = function (k, rowConditions, colConditions) { + const res = Array.from({ length: k }, () => Array(k).fill(0)) + + const row = khansAlgo(rowConditions, k) + if (row.length != k) return [] + + const col = khansAlgo(colConditions, k) + if (col.length != k) return [] + + const idx = Array(k + 1).fill(0) + for (let j = 0; j < col.length; j++) { + idx[col[j]] = j + } + for (let i = 0; i < k; i++) { + res[i][idx[row[i]]] = row[i] + } + return res + + function khansAlgo(r, k) { + const indegree = Array(k + 1).fill(0) + const adj = Array.from({ length: k + 1 }, () => Array()) + + for (let x of r) { + indegree[x[1]]++ + adj[x[0]].push(x[1]) + } + const row = [] + const q = [] + for (let i = 1; i <= k; i++) { + if (indegree[i] == 0) { + q.push(i) + } + } + while (q.length) { + let t = q.pop() + + row.push(t) + for (let x of adj[t] || []) { + indegree[x]-- + if (indegree[x] == 0) { + q.push(x) + } + } + } + return row + } +} + + + diff --git a/2397-maximum-rows-covered-by-columns.js b/2397.maximum-rows-covered-by-columns.js similarity index 100% rename from 2397-maximum-rows-covered-by-columns.js rename to 2397.maximum-rows-covered-by-columns.js diff --git a/2398-maximum-number-of-robots-within-budget.js b/2398.maximum-number-of-robots-within-budget.js similarity index 100% rename from 2398-maximum-number-of-robots-within-budget.js rename to 2398.maximum-number-of-robots-within-budget.js diff --git a/2399-check-distances-between-same-letters.js b/2399.check-distances-between-same-letters.js similarity index 100% rename from 2399-check-distances-between-same-letters.js rename to 2399.check-distances-between-same-letters.js diff --git a/24-swap-nodes-in-pairs.js b/24-swap-nodes-in-pairs.js deleted file mode 100755 index ca159f33..00000000 --- a/24-swap-nodes-in-pairs.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @return {ListNode} - */ -const swapPairs = function(node) { - const head = new ListNode(-1); - let cur = head; - - while (node !== null) { - if (node.next !== null) { - let one = node; - let two = node.next; - let three = node.next.next; - cur.next = two; - two.next = one; - one.next = three; - cur = cur.next.next; - node = three; - } else { - cur.next = node; - break; - } - } - - return head.next; -}; diff --git a/24.swap-nodes-in-pairs.js b/24.swap-nodes-in-pairs.js new file mode 100644 index 00000000..9e9766c3 --- /dev/null +++ b/24.swap-nodes-in-pairs.js @@ -0,0 +1,33 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ +const swapPairs = function(node) { + const head = new ListNode(-1); + let cur = head; + + while (node !== null) { + if (node.next !== null) { + let one = node; + let two = node.next; + let three = node.next.next; + cur.next = two; + two.next = one; + one.next = three; + cur = cur.next.next; + node = three; + } else { + cur.next = node; + break; + } + } + + return head.next; +}; diff --git a/240-search-a-2d-matrix-ii.js b/240.search-a-2d-matrix-ii.js similarity index 100% rename from 240-search-a-2d-matrix-ii.js rename to 240.search-a-2d-matrix-ii.js diff --git a/2400-number-of-ways-to-reach-a-position-after-exactly-k-steps.js b/2400-number-of-ways-to-reach-a-position-after-exactly-k-steps.js deleted file mode 100644 index e11d1929..00000000 --- a/2400-number-of-ways-to-reach-a-position-after-exactly-k-steps.js +++ /dev/null @@ -1,60 +0,0 @@ -const dp = Array.from({ length: 1000 + 1 }, () => Array(1000 + 1).fill(0)) -const mod = 1e9 + 7 -/** - * @param {number} startPos - * @param {number} endPos - * @param {number} k - * @return {number} - */ -const numberOfWays = function(startPos, endPos, k) { - const { abs } = Math - if (dp[1][1] == 0) { - for (let k = 1; k <= 1000; ++k) { - dp[k][k] = 1; - for (let i = 0; i < k; ++i) { - dp[k][i] = ((i === 0 ? dp[k - 1][1] : dp[k - 1][i - 1]) + dp[k - 1][i + 1]) % mod; - } - } - } - - return dp[k][abs(startPos - endPos)]; -}; - -// another - -/** - * @param {number} startPos - * @param {number} endPos - * @param {number} k - * @return {number} - */ -var numberOfWays = function(startPos, endPos, k) { - const ll = BigInt, mod = ll(1e9 + 7), N = 1005; - - let fact, ifact, inv; - const comb_init = () => { - fact = Array(N).fill(0); - ifact = Array(N).fill(0); - inv = Array(N).fill(0); - fact[0] = ifact[0] = inv[1] = 1n; - for (let i = 2; i < N; i++) inv[i] = (mod - mod / ll(i)) * inv[mod % ll(i)] % mod; - for (let i = 1; i < N; i++) { - fact[i] = fact[i - 1] * ll(i) % mod; - ifact[i] = ifact[i - 1] * inv[i] % mod; - } - }; - - const comb = (n, k) => { - if (n < k || k < 0) return 0; - return fact[n] * ifact[k] % mod * ifact[n - k] % mod; - }; - - comb_init(); - let res = 0n; - for (let i = 0; i <= k; i++) { - let moveRight = i, moveLeft = k - i; - if (startPos + moveRight - moveLeft == endPos) res += comb(k, i); - } - return res; - -}; diff --git a/2400.number-of-ways-to-reach-a-position-after-exactly-k-steps.js b/2400.number-of-ways-to-reach-a-position-after-exactly-k-steps.js new file mode 100644 index 00000000..c3993629 --- /dev/null +++ b/2400.number-of-ways-to-reach-a-position-after-exactly-k-steps.js @@ -0,0 +1,22 @@ +const dp = Array.from({ length: 1000 + 1 }, () => Array(1000 + 1).fill(0)) +const mod = 1e9 + 7 +/** + * @param {number} startPos + * @param {number} endPos + * @param {number} k + * @return {number} + */ +const numberOfWays = function(startPos, endPos, k) { + const { abs } = Math + if (dp[1][1] == 0) { + for (let k = 1; k <= 1000; ++k) { + dp[k][k] = 1; + for (let i = 0; i < k; ++i) { + dp[k][i] = ((i === 0 ? dp[k - 1][1] : dp[k - 1][i - 1]) + dp[k - 1][i + 1]) % mod; + } + } + } + + return dp[k][abs(startPos - endPos)]; +}; + diff --git a/2401-longest-nice-subarray.js b/2401-longest-nice-subarray.js deleted file mode 100644 index 9cd9ef95..00000000 --- a/2401-longest-nice-subarray.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const longestNiceSubarray = function (nums) { - let res = 1, i = 0, j = 0, mask = 0 - const n = nums.length - for(i = 0; i < n; i++) { - const cur = nums[i] - while((cur & mask) !== 0) { - mask ^= nums[j] - j++ - } - mask |= cur - // console.log(i, j, mask, i - j +1) - res = Math.max(res, i - j + 1) - } - - return res -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -var longestNiceSubarray = function(nums) { - let max = 1; - let stack = []; - for(let i =0;i a[1] === b[1] ? a[0] < b[0] : a[1] < b[1]) - const avail = new PQ((a, b) => a[0] < b[0]) - for(let i = 0; i < n; i++) { - avail.push([i, 0]) - } - meetings.sort((a, b) => a[0] - b[0]) - - for(let i = 0, len = meetings.length; i < len; i++) { - const [s, e] = meetings[i] - while(!busy.isEmpty() && busy.peek()[1] <= s) { - avail.push(busy.pop()) - } - if(!avail.isEmpty()) { - const r = avail.pop() - r[1] = e - rooms[r[0]]++ - busy.push(r) - } else { - const r = busy.pop() - r[1] += e - s - rooms[r[0]]++ - busy.push(r) - } - } - let res = 0 - // console.log(meetings.length, rooms) - const maxNum = Math.max(...rooms) - for(let i = 0; i < n; i++) { - if(rooms[i] === maxNum) { - res = i - break - } - } - return res -}; - -class PQ { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -/** - * @param {number} n - * @param {number[][]} meetings - * @return {number} - */ -var mostBooked = function(n, meetings) { - const count = new Array(n).fill(0); - const freeTime = new Array(n).fill(0); - meetings.sort((a, b) => a[0] - b[0]); - for(let i = 0 ; i < meetings.length ; i++){ - let minRoom = -1; - let minTime = Number.MAX_SAFE_INTEGER; - for(let j = 0 ; j < n ; j++){ - if(freeTime[j] <= meetings[i][0]){ - count[j]++; - freeTime[j] = meetings[i][1]; - minRoom = -1; - break; - } - if(freeTime[j] < minTime){ - minTime = freeTime[j]; - minRoom = j; - } - } - if(minRoom !== -1){ - count[minRoom]++; - freeTime[minRoom] += meetings[i][1] - meetings[i][0]; - } - } - - let ans = 0; - let maxCount = count[0]; - for(let i = 1 ; i < n ; i++){ - if(count[i] > maxCount){ - ans = i; - maxCount = count[i]; - } - } - return ans; -}; diff --git a/2402.meeting-rooms-iii.js b/2402.meeting-rooms-iii.js new file mode 100644 index 00000000..c287e124 --- /dev/null +++ b/2402.meeting-rooms-iii.js @@ -0,0 +1,111 @@ +/** + * @param {number} n + * @param {number[][]} meetings + * @return {number} + */ +const mostBooked = function(n, meetings) { + const rooms = Array(n).fill(0) + const busy = new PQ((a, b) => a[1] === b[1] ? a[0] < b[0] : a[1] < b[1]) + const avail = new PQ((a, b) => a[0] < b[0]) + for(let i = 0; i < n; i++) { + avail.push([i, 0]) + } + meetings.sort((a, b) => a[0] - b[0]) + + for(let i = 0, len = meetings.length; i < len; i++) { + const [s, e] = meetings[i] + while(!busy.isEmpty() && busy.peek()[1] <= s) { + avail.push(busy.pop()) + } + if(!avail.isEmpty()) { + const r = avail.pop() + r[1] = e + rooms[r[0]]++ + busy.push(r) + } else { + const r = busy.pop() + r[1] += e - s + rooms[r[0]]++ + busy.push(r) + } + } + let res = 0 + // console.log(meetings.length, rooms) + const maxNum = Math.max(...rooms) + for(let i = 0; i < n; i++) { + if(rooms[i] === maxNum) { + res = i + break + } + } + return res +}; + +class PQ { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + diff --git a/2403-minimum-time-to-kill-all-monsters.js b/2403.minimum-time-to-kill-all-monsters.js similarity index 100% rename from 2403-minimum-time-to-kill-all-monsters.js rename to 2403.minimum-time-to-kill-all-monsters.js diff --git a/2404-most-frequent-even-element.js b/2404.most-frequent-even-element.js similarity index 100% rename from 2404-most-frequent-even-element.js rename to 2404.most-frequent-even-element.js diff --git a/2405-optimal-partition-of-string.js b/2405.optimal-partition-of-string.js similarity index 100% rename from 2405-optimal-partition-of-string.js rename to 2405.optimal-partition-of-string.js diff --git a/2406.divide-intervals-into-minimum-number-of-groups.js b/2406.divide-intervals-into-minimum-number-of-groups.js deleted file mode 100644 index aaecb9aa..00000000 --- a/2406.divide-intervals-into-minimum-number-of-groups.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @param {number[][]} intervals - * @return {number} - */ -var minGroups = function(intervals) { - const hash = {} - for(let [s, e] of intervals) { - e = e + 1 - hash[s] = (hash[s] || 0) + 1 - hash[e] = (hash[e] || 0) - 1 - } - let res = 0, cur = 0 - const keys = Object.keys(hash).map(e => +e) - keys.sort((a, b) => a - b) - for(const k of keys) { - cur += hash[k] - res = Math.max(res, cur) - } - return res -}; - -// another - -/** - * @param {number[][]} intervals - * @return {number} - */ -const minGroups = function(intervals) { - const hash = {} - for(const [s, e] of intervals) { - if(hash[s] == null) hash[s] = 0 - if(hash[e + 1] == null) hash[e + 1] = 0 - hash[s]++ - hash[e + 1]-- - } - const keys = Object.keys(hash) - keys.sort((a, b) => a - b) - const n = keys.length - - const arr = Array(n).fill(0) - arr[0] = hash[keys[0]] - let res = arr[0] - for(let i = 1; i < n; i++) { - arr[i] = hash[keys[i]] + arr[i - 1] - res = Math.max(res, arr[i]) - } - return res -}; diff --git a/2406.divide.intervals-into-minimum-number-of-groups.js b/2406.divide.intervals-into-minimum-number-of-groups.js new file mode 100644 index 00000000..efcb2af4 --- /dev/null +++ b/2406.divide.intervals-into-minimum-number-of-groups.js @@ -0,0 +1,21 @@ +/** + * @param {number[][]} intervals + * @return {number} + */ +var minGroups = function(intervals) { + const hash = {} + for(let [s, e] of intervals) { + e = e + 1 + hash[s] = (hash[s] || 0) + 1 + hash[e] = (hash[e] || 0) - 1 + } + let res = 0, cur = 0 + const keys = Object.keys(hash).map(e => +e) + keys.sort((a, b) => a - b) + for(const k of keys) { + cur += hash[k] + res = Math.max(res, cur) + } + return res +}; + diff --git a/2407.longest-increasing-subsequence-ii.js b/2407.longest.increasing-subsequence-ii.js similarity index 100% rename from 2407.longest-increasing-subsequence-ii.js rename to 2407.longest.increasing-subsequence-ii.js diff --git a/241-different-ways-to-add-parentheses.js b/241-different-ways-to-add-parentheses.js deleted file mode 100755 index 54e72956..00000000 --- a/241-different-ways-to-add-parentheses.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @param {string} input - * @return {number[]} - */ -const diffWaysToCompute = function(input) { - const res = []; - let left; - let right; - for (let i = 0; i < input.length; i++) { - if (input[i] < "0") { - left = diffWaysToCompute(input.slice(0, i)); - right = diffWaysToCompute(input.slice(i + 1)); - for (let rl of left) { - for (let rr of right) { - switch (input[i]) { - case "+": - res.push(rl + rr); - break; - case "-": - res.push(rl - rr); - break; - case "*": - res.push(rl * rr); - break; - default: - break; - } - } - } - } - } - if (res.length === 0) { - res.push(+input); - } - return res; -}; diff --git a/241.different-ways-to-add-parentheses.js b/241.different-ways-to-add-parentheses.js new file mode 100644 index 00000000..4feb0b6f --- /dev/null +++ b/241.different-ways-to-add-parentheses.js @@ -0,0 +1,36 @@ +/** + * @param {string} input + * @return {number[]} + */ +const diffWaysToCompute = function(input) { + const res = []; + let left; + let right; + for (let i = 0; i < input.length; i++) { + if (input[i] < "0") { + left = diffWaysToCompute(input.slice(0, i)); + right = diffWaysToCompute(input.slice(i + 1)); + for (let rl of left) { + for (let rr of right) { + switch (input[i]) { + case "+": + res.push(rl + rr); + break; + case "-": + res.push(rl - rr); + break; + case "*": + res.push(rl * rr); + break; + default: + break; + } + } + } + } + } + if (res.length === 0) { + res.push(+input); + } + return res; +}; diff --git a/2411-smallest-subarrays-with-maximum-bitwise-or.js b/2411.smallest-subarrays-with-maximum-bitwise-or.js similarity index 100% rename from 2411-smallest-subarrays-with-maximum-bitwise-or.js rename to 2411.smallest-subarrays-with-maximum-bitwise-or.js diff --git a/2412-minimum-money-required-before-transactions.js b/2412.minimum-money-required-before-transactions.js similarity index 100% rename from 2412-minimum-money-required-before-transactions.js rename to 2412.minimum-money-required-before-transactions.js diff --git a/2413-smallest-even-multiple.js b/2413.smallest-even-multiple.js similarity index 100% rename from 2413-smallest-even-multiple.js rename to 2413.smallest-even-multiple.js diff --git a/2414-length-of-the-longest-alphabetical-continuous-substring.js b/2414.length-of-the-longest-alphabetical-continuous-substring.js similarity index 100% rename from 2414-length-of-the-longest-alphabetical-continuous-substring.js rename to 2414.length-of-the-longest-alphabetical-continuous-substring.js diff --git a/2415-reverse-odd-levels-of-binary-tree.js b/2415.reverse-odd-levels-of-binary-tree.js similarity index 100% rename from 2415-reverse-odd-levels-of-binary-tree.js rename to 2415.reverse-odd-levels-of-binary-tree.js diff --git a/2416-sum-of-prefix-scores-of-strings.js b/2416.sum-of-prefix-scores-of-strings.js similarity index 100% rename from 2416-sum-of-prefix-scores-of-strings.js rename to 2416.sum-of-prefix-scores-of-strings.js diff --git a/2418-sort-the-people.js b/2418.sort-the-people.js similarity index 100% rename from 2418-sort-the-people.js rename to 2418.sort-the-people.js diff --git a/2419-longest-subarray-with-maximum-bitwise-and.js b/2419.longest-subarray-with-maximum-bitwise-and.js similarity index 100% rename from 2419-longest-subarray-with-maximum-bitwise-and.js rename to 2419.longest-subarray-with-maximum-bitwise-and.js diff --git a/242-valid-anagram.js b/242-valid-anagram.js deleted file mode 100755 index c4b41da1..00000000 --- a/242-valid-anagram.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @param {string} s - * @param {string} t - * @return {boolean} - */ -const isAnagram = function(s, t) { - if (s.length !== t.length) return false; - const sh = strHash(s); - const th = strHash(t); - for (let key in sh) { - if (sh.hasOwnProperty(key) && sh[key] !== th[key]) { - return false; - } - } - return true; -}; - -function strHash(str) { - let res = {}; - for (let i = 0; i < str.length; i++) { - if (res.hasOwnProperty(str[i])) { - res[str[i]] += 1; - } else { - res[str[i]] = 1; - } - } - return res; -} diff --git a/242.valid-anagram.js b/242.valid-anagram.js new file mode 100644 index 00000000..9fc04773 --- /dev/null +++ b/242.valid-anagram.js @@ -0,0 +1,28 @@ +/** + * @param {string} s + * @param {string} t + * @return {boolean} + */ +const isAnagram = function(s, t) { + if (s.length !== t.length) return false; + const sh = strHash(s); + const th = strHash(t); + for (let key in sh) { + if (sh.hasOwnProperty(key) && sh[key] !== th[key]) { + return false; + } + } + return true; +}; + +function strHash(str) { + let res = {}; + for (let i = 0; i < str.length; i++) { + if (res.hasOwnProperty(str[i])) { + res[str[i]] += 1; + } else { + res[str[i]] = 1; + } + } + return res; +} diff --git a/2420-find-all-good-indices.js b/2420.find-all-good-indices.js similarity index 100% rename from 2420-find-all-good-indices.js rename to 2420.find-all-good-indices.js diff --git a/2421-number-of-good-paths.js b/2421.number-of-good-paths.js similarity index 100% rename from 2421-number-of-good-paths.js rename to 2421.number-of-good-paths.js diff --git a/2422-merge-operations-to-turn-array-into-a-palindrome.js b/2422.merge-operations-to-turn-array-into-a-palindrome.js similarity index 100% rename from 2422-merge-operations-to-turn-array-into-a-palindrome.js rename to 2422.merge-operations-to-turn-array-into-a-palindrome.js diff --git a/2423-remove-letter-to-equalize-frequency.js b/2423.remove-letter-to-equalize-frequency.js similarity index 100% rename from 2423-remove-letter-to-equalize-frequency.js rename to 2423.remove-letter-to-equalize-frequency.js diff --git a/2426-number-of-pairs-satisfying-inequality.js b/2426.number-of-pairs-satisfying-inequality.js similarity index 100% rename from 2426-number-of-pairs-satisfying-inequality.js rename to 2426.number-of-pairs-satisfying-inequality.js diff --git a/2427-number-of-common-factors.js b/2427.number-of-common-factors.js similarity index 100% rename from 2427-number-of-common-factors.js rename to 2427.number-of-common-factors.js diff --git a/2428-maximum-sum-of-an-hourglass.js b/2428.maximum-sum-of-an-hourglass.js similarity index 100% rename from 2428-maximum-sum-of-an-hourglass.js rename to 2428.maximum-sum-of-an-hourglass.js diff --git a/2429-minimize-xor.js b/2429.minimize-xor.js similarity index 100% rename from 2429-minimize-xor.js rename to 2429.minimize-xor.js diff --git a/243-shortest-word-distance.js b/243.shortest-word-distance.js similarity index 100% rename from 243-shortest-word-distance.js rename to 243.shortest-word-distance.js diff --git a/2430-maximum-deletions-on-a-string.js b/2430-maximum-deletions-on-a-string.js deleted file mode 100644 index 4f04ae64..00000000 --- a/2430-maximum-deletions-on-a-string.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const deleteString = function (s) { - const dp = Array(4000).fill(0) - const n = s.length - return helper(0) - - function helper(i) { - if(dp[i] === 0) { - dp[i] = 1 - for(let len = 1; dp[i] <= n - i - len; len++) { - if(s.slice(i, i + len) === s.slice(i + len, i + 2 * len)) { - dp[i] = Math.max(dp[i], 1 + helper(i + len)) - } - } - } - return dp[i] - } -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const deleteString = function (s) { - const dp = Array(4000).fill(0), lps = Array(4000).fill(0) - for (let k = s.length - 1; k >= 0; --k) { - dp[k] = 1; - for (let i = 1, j = 0; dp[k] <= s.length - i - k + 1; ++i) { - while (j && s[i + k] != s[j + k]) j = Math.max(0, lps[j] - 1); - j += s[i + k] == s[j + k]; - lps[i] = j; - if (i % 2) { - const len = ~~((i + 1) / 2); - if (lps[len * 2 - 1] == len) { - dp[k] = Math.max(dp[k], 1 + dp[k + len]); - } - } - } - } - return dp[0]; -} - - -// another - - -/** - * @param {string} s - * @return {number} - */ -const deleteString = function (t) { - let n = t.length - const set = new Set(t.split('')) - if (set.size == 1) return n - - let s = t.split('') - if (n === 1 || (n === 2 && s[0] !== s[1])) return 1 - if (n === 2 && s[0] === s[1]) return 2 - if (n === 3 && s[0] === s[1]) return s[1] === s[2] ? 3 : 2 - else if (n === 3) return 1 - const f = new Array(n).fill(null) - dfsSearchWithMemory(0) - return f[0] - - function dfsSearchWithMemory(i) { - if (i >= n) return 0 - if (f[i] !== null) return f[i] - if (i === n - 1) return (f[i] = 1) - let max = 0, - cur = 0, - j = i + 1 - for (j = i + 1; j <= ~~((n - i) / 2 + i); j++) { - if (t.slice(j).startsWith(t.slice(i, j))) { - cur = 1 + dfsSearchWithMemory(j) - if (cur > max) max = cur - } - } - if (j > (n - i) / 2 + i && max === 0) return (f[i] = 1) - return (f[i] = max) - } -} diff --git a/2430.maximum-deletions-on-a-string.js b/2430.maximum-deletions-on-a-string.js new file mode 100644 index 00000000..983edb83 --- /dev/null +++ b/2430.maximum-deletions-on-a-string.js @@ -0,0 +1,22 @@ +/** + * @param {string} s + * @return {number} + */ +const deleteString = function (s) { + const dp = Array(4000).fill(0) + const n = s.length + return helper(0) + + function helper(i) { + if(dp[i] === 0) { + dp[i] = 1 + for(let len = 1; dp[i] <= n - i - len; len++) { + if(s.slice(i, i + len) === s.slice(i + len, i + 2 * len)) { + dp[i] = Math.max(dp[i], 1 + helper(i + len)) + } + } + } + return dp[i] + } +} + diff --git a/2432-the-employee-that-worked-on-the-longest-task.js b/2432.the-employee-that-worked-on-the-longest-task.js similarity index 100% rename from 2432-the-employee-that-worked-on-the-longest-task.js rename to 2432.the-employee-that-worked-on-the-longest-task.js diff --git a/2433-find-the-original-array-of-prefix-xor.js b/2433.find-the-original-array-of-prefix-xor.js similarity index 100% rename from 2433-find-the-original-array-of-prefix-xor.js rename to 2433.find-the-original-array-of-prefix-xor.js diff --git a/2434-using-a-robot-to-print-the-lexicographically-smallest-string.js b/2434-using-a-robot-to-print-the-lexicographically-smallest-string.js deleted file mode 100644 index 9ffd6f29..00000000 --- a/2434-using-a-robot-to-print-the-lexicographically-smallest-string.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ -const robotWithString = function (s) { - const stk = [] - const freq = Array(26).fill(0) - const a = 'a'.charCodeAt(0) - for (const ch of s) { - freq[ch.charCodeAt(0) - a]++ - } - - let res = '' - - for (const ch of s) { - stk.push(ch) - freq[ch.charCodeAt(0) - a]-- - while (stk.length && stk[stk.length - 1] <= helper(freq)) { - const e = stk.pop() - res += e - } - } - - while (stk.length) { - res += stk.pop() - } - - return res - - function helper(arr) { - const a = 'a'.charCodeAt(0) - for (let i = 0; i < 26; i++) { - if (arr[i] !== 0) return String.fromCharCode(a + i) - } - - return '' - } -} - - -// another - -const ord = (c) => c.charCodeAt(); -const char = (ascii) => String.fromCharCode(ascii); -/** - * @param {string} s - * @return {string} - */ - -const robotWithString = (s) => { - let f = Array(26).fill(0), t = [], res = ''; - for (const c of s) f[ord(c) - 97]++; - for (const c of s) { - f[ord(c) - 97]--; - t.push(c); - while (t.length) { - let find = false; - for (let i = 0; i < 26; i++) { - let curC = char(i + 97); - if (curC < t[t.length - 1]) { // check if can find smaller char < t's last char, in the rest of S - if (f[i] > 0) { - find = true; - break; - } - } - } - if (find) { // find means there is lexical smaller one, by moving much more right - break; - } else { // not find, current is lexical smaller - res += t.pop(); - } - } - } - return res; -}; diff --git a/2434.using-a-robot-to-print-the-lexicographically-smallest-string.js b/2434.using-a-robot-to-print-the-lexicographically-smallest-string.js new file mode 100644 index 00000000..3987531f --- /dev/null +++ b/2434.using-a-robot-to-print-the-lexicographically-smallest-string.js @@ -0,0 +1,40 @@ +/** + * @param {string} s + * @return {string} + */ +const robotWithString = function (s) { + const stk = [] + const freq = Array(26).fill(0) + const a = 'a'.charCodeAt(0) + for (const ch of s) { + freq[ch.charCodeAt(0) - a]++ + } + + let res = '' + + for (const ch of s) { + stk.push(ch) + freq[ch.charCodeAt(0) - a]-- + while (stk.length && stk[stk.length - 1] <= helper(freq)) { + const e = stk.pop() + res += e + } + } + + while (stk.length) { + res += stk.pop() + } + + return res + + function helper(arr) { + const a = 'a'.charCodeAt(0) + for (let i = 0; i < 26; i++) { + if (arr[i] !== 0) return String.fromCharCode(a + i) + } + + return '' + } +} + + diff --git a/2435-paths-in-matrix-whose-sum-is-divisible-by-k.js b/2435.paths-in-matrix-whose-sum-is-divisible-by-k.js similarity index 100% rename from 2435-paths-in-matrix-whose-sum-is-divisible-by-k.js rename to 2435.paths-in-matrix-whose-sum-is-divisible-by-k.js diff --git a/2438-range-product-queries-of-powers.js b/2438.range-product-queries-of-powers.js similarity index 100% rename from 2438-range-product-queries-of-powers.js rename to 2438.range-product-queries-of-powers.js diff --git a/2439-minimize-maximum-of-array.js b/2439.minimize-maximum-of-array.js similarity index 100% rename from 2439-minimize-maximum-of-array.js rename to 2439.minimize-maximum-of-array.js diff --git a/244-shortest-word-distance-ii.js b/244.shortest-word-distance-ii.js similarity index 100% rename from 244-shortest-word-distance-ii.js rename to 244.shortest-word-distance-ii.js diff --git a/2441-largest-positive-integer-that-exists-with-its-negative.js b/2441.largest-positive-integer-that-exists-with-its-negative.js similarity index 100% rename from 2441-largest-positive-integer-that-exists-with-its-negative.js rename to 2441.largest-positive-integer-that-exists-with-its-negative.js diff --git a/2442-count-number-of-distinct-integers-after-reverse-operations.js b/2442.count-number-of-distinct-integers-after-reverse-operations.js similarity index 100% rename from 2442-count-number-of-distinct-integers-after-reverse-operations.js rename to 2442.count-number-of-distinct-integers-after-reverse-operations.js diff --git a/2443-sum-of-number-and-its-reverse.js b/2443.sum-of-number-and-its-reverse.js similarity index 100% rename from 2443-sum-of-number-and-its-reverse.js rename to 2443.sum-of-number-and-its-reverse.js diff --git a/2444-count-subarrays-with-fixed-bounds.js b/2444-count-subarrays-with-fixed-bounds.js deleted file mode 100644 index 9ad838c7..00000000 --- a/2444-count-subarrays-with-fixed-bounds.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} minK - * @param {number} maxK - * @return {number} - */ -const countSubarrays = function(nums, minK, maxK) { - let res = 0, n = nums.length - let minIdx = -1, maxIdx = -1 - - for(let i = 0, j = 0; i < n; i++) { - if(nums[i] < minK || nums[i] > maxK) { - minIdx = -1 - maxIdx = -1 - j = i + 1 - } - if(nums[i] === minK) minIdx = i - if(nums[i] === maxK) maxIdx = i - if(minIdx !== -1 && maxIdx !== -1) { - res += Math.min(minIdx, maxIdx) - j + 1 - } - } - - return res -}; - -// another - -/** - * @param {number[]} nums - * @param {number} minK - * @param {number} maxK - * @return {number} - */ -var countSubarrays = function(nums, minK, maxK) { - let res = 0, j = 0, jmin = -1, jmax = -1, n = nums.length; - for (let i = 0; i < n; ++i) { - if (nums[i] < minK || nums[i] > maxK) { - jmin = jmax = -1; - j = i + 1; - } - if (nums[i] == minK) jmin = i; - if (nums[i] == maxK) jmax = i; - res += Math.max(0, Math.min(jmin, jmax) - j + 1); - } - return res; -}; diff --git a/2444.count-subarrays-with-fixed-bounds.js b/2444.count-subarrays-with-fixed-bounds.js new file mode 100644 index 00000000..fcc3fbc0 --- /dev/null +++ b/2444.count-subarrays-with-fixed-bounds.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} nums + * @param {number} minK + * @param {number} maxK + * @return {number} + */ +const countSubarrays = function(nums, minK, maxK) { + let res = 0, n = nums.length + let minIdx = -1, maxIdx = -1 + + for(let i = 0, j = 0; i < n; i++) { + if(nums[i] < minK || nums[i] > maxK) { + minIdx = -1 + maxIdx = -1 + j = i + 1 + } + if(nums[i] === minK) minIdx = i + if(nums[i] === maxK) maxIdx = i + if(minIdx !== -1 && maxIdx !== -1) { + res += Math.min(minIdx, maxIdx) - j + 1 + } + } + + return res +}; + diff --git a/2447-number-of-subarrays-with-gcd-equal-to-k.js b/2447.number-of-subarrays-with-gcd-equal-to-k.js similarity index 100% rename from 2447-number-of-subarrays-with-gcd-equal-to-k.js rename to 2447.number-of-subarrays-with-gcd-equal-to-k.js diff --git a/2448-minimum-cost-to-make-array-equal.js b/2448.minimum-cost-to-make-array-equal.js similarity index 100% rename from 2448-minimum-cost-to-make-array-equal.js rename to 2448.minimum-cost-to-make-array-equal.js diff --git a/2449-minimum-number-of-operations-to-make-arrays-similar.js b/2449.minimum-number-of-operations-to-make-arrays-similar.js similarity index 100% rename from 2449-minimum-number-of-operations-to-make-arrays-similar.js rename to 2449.minimum-number-of-operations-to-make-arrays-similar.js diff --git a/245-shortest-word-distance-iii.js b/245.shortest-word-distance-iii.js similarity index 100% rename from 245-shortest-word-distance-iii.js rename to 245.shortest-word-distance-iii.js diff --git a/2453-destroy-sequential-targets.js b/2453.destroy-sequential-targets.js similarity index 100% rename from 2453-destroy-sequential-targets.js rename to 2453.destroy-sequential-targets.js diff --git a/2454-next-greater-element-iv.js b/2454.next-greater-element-iv.js similarity index 100% rename from 2454-next-greater-element-iv.js rename to 2454.next-greater-element-iv.js diff --git a/2457-minimum-addition-to-make-integer-beautiful.js b/2457.minimum-addition-to-make-integer-beautiful.js similarity index 100% rename from 2457-minimum-addition-to-make-integer-beautiful.js rename to 2457.minimum-addition-to-make-integer-beautiful.js diff --git a/246-strobogrammatic-number.js b/246-strobogrammatic-number.js deleted file mode 100644 index c02c9772..00000000 --- a/246-strobogrammatic-number.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @param {string} num - * @return {boolean} - */ -const isStrobogrammatic = function(num) { - const m = { - 0: 0, - 1: 1, - 2: null, - 3: null, - 4: null, - 5: null, - 6: 9, - 7: null, - 8: 8, - 9: 6 - } - const arr = num.split('') - for(let i = 0, len = arr.length; i < len; i++) { - if(m[arr[i]] === null) return false - else arr[i] = m[arr[i]] - } - return num === arr.reverse().join('') -}; - -// another - -const isStrobogrammatic = function(num) { - const map = { 0: '0', 1: '1', 8: '8', 6: '9', 9: '6' } - let left = 0 - let right = num.length - 1 - - while (left < right) { - const leftNum = num[left] - const rightNum = num[right] - if (map[leftNum] != rightNum) return false - left++ - right-- - } - if (right == left) { - if (!map[num[right]] || num[right] == '9' || num[right] == '6') return false - } - return true -} diff --git a/246.strobogrammatic-number.js b/246.strobogrammatic-number.js new file mode 100644 index 00000000..980811e6 --- /dev/null +++ b/246.strobogrammatic-number.js @@ -0,0 +1,25 @@ +/** + * @param {string} num + * @return {boolean} + */ +const isStrobogrammatic = function(num) { + const m = { + 0: 0, + 1: 1, + 2: null, + 3: null, + 4: null, + 5: null, + 6: 9, + 7: null, + 8: 8, + 9: 6 + } + const arr = num.split('') + for(let i = 0, len = arr.length; i < len; i++) { + if(m[arr[i]] === null) return false + else arr[i] = m[arr[i]] + } + return num === arr.reverse().join('') +}; + diff --git a/2460-apply-operations-to-an-array.js b/2460.apply-operations-to-an-array.js similarity index 100% rename from 2460-apply-operations-to-an-array.js rename to 2460.apply-operations-to-an-array.js diff --git a/2461-maximum-sum-of-distinct-subarrays-with-length-k.js b/2461-maximum-sum-of-distinct-subarrays-with-length-k.js deleted file mode 100644 index 932c8383..00000000 --- a/2461-maximum-sum-of-distinct-subarrays-with-length-k.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const maximumSubarraySum = function (nums, k) { - const map = new Map(), n = nums.length - let i = 0, res = 0, sum = 0 - - while(i < n && i < k) { - const cur = nums[i] - map.set(cur, (map.get(cur) || 0) + 1 ) - sum += cur - i++ - } - if(map.size === k) res = sum - - for(i = k; i < n; i++) { - const cur = nums[i] - map.set(cur, (map.get(cur) || 0) + 1) - const pre = nums[i - k] - map.set(pre, (map.get(pre) || 0) - 1) - if(map.get(pre) === 0) map.delete(pre) - - sum += cur - sum -= nums[i - k] - - if(map.size === k) res = Math.max(res, sum) - } - - return res -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const maximumSubarraySum = function(nums, k) { - let res = 0 - const n = nums.length - - const preSum = Array(n).fill(0) - preSum[0] = nums[0] - for(let i = 1; i < n; i++) { - preSum[i] = preSum[i - 1] + nums[i] - } - - const set = new Set() - - const lastHash = {} - - for(let i = 0; i < n; i++) { - const cur = nums[i] - lastHash[cur] = i - if(i < k - 1) set.add(cur) - else if(i === k - 1) { - set.add(cur) - if(set.size === k) { - res = preSum[i] - } - } else { - if(lastHash[nums[i - k]] == i - k) set.delete(nums[i - k]) - set.add(nums[i]) - if(set.size === k) { - res = Math.max(res, preSum[i] - preSum[i - k]) - } - } - } - - return res -}; diff --git a/2461.maximum-sum-of-distinct-subarrays-with-length-k.js b/2461.maximum-sum-of-distinct-subarrays-with-length-k.js new file mode 100644 index 00000000..c4773f8b --- /dev/null +++ b/2461.maximum-sum-of-distinct-subarrays-with-length-k.js @@ -0,0 +1,33 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const maximumSubarraySum = function (nums, k) { + const map = new Map(), n = nums.length + let i = 0, res = 0, sum = 0 + + while(i < n && i < k) { + const cur = nums[i] + map.set(cur, (map.get(cur) || 0) + 1 ) + sum += cur + i++ + } + if(map.size === k) res = sum + + for(i = k; i < n; i++) { + const cur = nums[i] + map.set(cur, (map.get(cur) || 0) + 1) + const pre = nums[i - k] + map.set(pre, (map.get(pre) || 0) - 1) + if(map.get(pre) === 0) map.delete(pre) + + sum += cur + sum -= nums[i - k] + + if(map.size === k) res = Math.max(res, sum) + } + + return res +} + diff --git a/2462-total-cost-to-hire-k-workers.js b/2462.total-cost-to-hire-k-workers.js similarity index 100% rename from 2462-total-cost-to-hire-k-workers.js rename to 2462.total-cost-to-hire-k-workers.js diff --git a/2463-minimum-total-distance-traveled.js b/2463.minimum-total-distance-traveled.js similarity index 100% rename from 2463-minimum-total-distance-traveled.js rename to 2463.minimum-total-distance-traveled.js diff --git a/2469-convert-the-temperature.js b/2469.convert-the-temperature.js similarity index 100% rename from 2469-convert-the-temperature.js rename to 2469.convert-the-temperature.js diff --git a/247-strobogrammatic-number-ii.js b/247-strobogrammatic-number-ii.js deleted file mode 100644 index 17d7e188..00000000 --- a/247-strobogrammatic-number-ii.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @param {number} n - * @return {string[]} - */ -const findStrobogrammatic = function(n) { - return recursionHelper(n, n) -} -const recursionHelper = function(n, m) { - if (n === 0) return [''] - if (n === 1) return ['0', '1', '8'] - let rtnArr = recursionHelper(n - 2, m) - let res = [] - for (let i = 0; i < rtnArr.length; i++) { - if (n !== m) res.push('0' + rtnArr[i] + '0') - res.push('1' + rtnArr[i] + '1') - res.push('6' + rtnArr[i] + '9') - res.push('8' + rtnArr[i] + '8') - res.push('9' + rtnArr[i] + '6') - } - return res -} - -// another - -/** - * @param {number} n - * @return {string[]} - */ -const findStrobogrammatic = function(n) { - let cur, ans - ans = (n & 1) == 0 ? [''] : ['0', '1', '8'] - if (n < 2) return ans - for (; n > 1; n -= 2) { - cur = ans - ans = [] - for (let i of cur) { - if (n > 3) ans.push('0' + i + '0') - ans.push('1' + i + '1') - ans.push('8' + i + '8') - ans.push('6' + i + '9') - ans.push('9' + i + '6') - } - } - return ans -} diff --git a/247.strobogrammatic-number-ii.js b/247.strobogrammatic-number-ii.js new file mode 100644 index 00000000..7c6630c4 --- /dev/null +++ b/247.strobogrammatic-number-ii.js @@ -0,0 +1,22 @@ +/** + * @param {number} n + * @return {string[]} + */ +const findStrobogrammatic = function(n) { + return recursionHelper(n, n) +} +const recursionHelper = function(n, m) { + if (n === 0) return [''] + if (n === 1) return ['0', '1', '8'] + let rtnArr = recursionHelper(n - 2, m) + let res = [] + for (let i = 0; i < rtnArr.length; i++) { + if (n !== m) res.push('0' + rtnArr[i] + '0') + res.push('1' + rtnArr[i] + '1') + res.push('6' + rtnArr[i] + '9') + res.push('8' + rtnArr[i] + '8') + res.push('9' + rtnArr[i] + '6') + } + return res +} + diff --git a/2470-number-of-subarrays-with-lcm-equal-to-k.js b/2470.number-of-subarrays-with-lcm-equal-to-k.js similarity index 100% rename from 2470-number-of-subarrays-with-lcm-equal-to-k.js rename to 2470.number-of-subarrays-with-lcm-equal-to-k.js diff --git a/2471-minimum-number-of-operations-to-sort-a-binary-tree-by-level.js b/2471.minimum-number-of-operations-to-sort-a-binary-tree-by-level.js similarity index 100% rename from 2471-minimum-number-of-operations-to-sort-a-binary-tree-by-level.js rename to 2471.minimum-number-of-operations-to-sort-a-binary-tree-by-level.js diff --git a/2472-maximum-number-of-non-overlapping-palindrome-substrings.js b/2472.maximum-number-of-non-overlapping-palindrome-substrings.js similarity index 100% rename from 2472-maximum-number-of-non-overlapping-palindrome-substrings.js rename to 2472.maximum-number-of-non-overlapping-palindrome-substrings.js diff --git a/2475-number-of-unequal-triplets-in-array.js b/2475.number-of-unequal-triplets-in-array.js similarity index 100% rename from 2475-number-of-unequal-triplets-in-array.js rename to 2475.number-of-unequal-triplets-in-array.js diff --git a/2476-closest-nodes-queries-in-a-binary-search-tree.js b/2476.closest-nodes-queries-in-a-binary-search-tree.js similarity index 100% rename from 2476-closest-nodes-queries-in-a-binary-search-tree.js rename to 2476.closest-nodes-queries-in-a-binary-search-tree.js diff --git a/2477-minimum-fuel-cost-to-report-to-the-capital.js b/2477.minimum-fuel-cost-to-report-to-the-capital.js similarity index 100% rename from 2477-minimum-fuel-cost-to-report-to-the-capital.js rename to 2477.minimum-fuel-cost-to-report-to-the-capital.js diff --git a/2478-number-of-beautiful-partitions.js b/2478.number-of-beautiful-partitions.js similarity index 100% rename from 2478-number-of-beautiful-partitions.js rename to 2478.number-of-beautiful-partitions.js diff --git a/248-strobogrammatic-number-iii.js b/248.strobogrammatic-number-iii.js similarity index 100% rename from 248-strobogrammatic-number-iii.js rename to 248.strobogrammatic-number-iii.js diff --git a/2484-count-palindromic-subsequences.js b/2484.count-palindromic-subsequences.js similarity index 100% rename from 2484-count-palindromic-subsequences.js rename to 2484.count-palindromic-subsequences.js diff --git a/2485-find-the-pivot-integer.js b/2485.find-the-pivot-integer.js similarity index 100% rename from 2485-find-the-pivot-integer.js rename to 2485.find-the-pivot-integer.js diff --git a/2486-append-characters-to-string-to-make-subsequence.js b/2486.append-characters-to-string-to-make-subsequence.js similarity index 100% rename from 2486-append-characters-to-string-to-make-subsequence.js rename to 2486.append-characters-to-string-to-make-subsequence.js diff --git a/2487-remove-nodes-from-linked-list.js b/2487.remove-nodes-from-linked-list.js similarity index 100% rename from 2487-remove-nodes-from-linked-list.js rename to 2487.remove-nodes-from-linked-list.js diff --git a/2488-count-subarrays-with-median-k.js b/2488.count-subarrays-with-median-k.js similarity index 100% rename from 2488-count-subarrays-with-median-k.js rename to 2488.count-subarrays-with-median-k.js diff --git a/249-group-shifted-strings.js b/249.group-shifted-strings.js similarity index 100% rename from 249-group-shifted-strings.js rename to 249.group-shifted-strings.js diff --git a/2490-circular-sentence.js b/2490.circular-sentence.js similarity index 100% rename from 2490-circular-sentence.js rename to 2490.circular-sentence.js diff --git a/2491-divide-players-into-teams-of-equal-skill.js b/2491.divide-players-into-teams-of-equal-skill.js similarity index 100% rename from 2491-divide-players-into-teams-of-equal-skill.js rename to 2491.divide-players-into-teams-of-equal-skill.js diff --git a/2492-minimum-score-of-a-path-between-two-cities.js b/2492-minimum-score-of-a-path-between-two-cities.js deleted file mode 100644 index 43c7f362..00000000 --- a/2492-minimum-score-of-a-path-between-two-cities.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} roads - * @return {number} - */ -const minScore = function(n, roads) { - const g = {}, visited = Array(n + 1).fill(0) - let res = Infinity - for(const [u, v, d] of roads) { - if(g[u] == null) g[u] = [] - if(g[v] == null) g[v] = [] - - g[u].push([v, d]) - g[v].push([u, d]) - } - - dfs(1) - - return res - - function dfs(node) { - visited[node] = 1 - for(const [nxt, dis] of (g[node] || [])) { - res = Math.min(res, dis) - if(visited[nxt] === 0) { - dfs(nxt) - } - } - } -}; - -// another - -class UnionFind { - constructor() { - this.sizes = new Map() - this.parents = new Map() - } - - find(x){ - if (x !== (this.parents.get(x) ?? x)) { - this.parents.set(x, this.find(this.parents.get(x) ?? x)); - } - return this.parents.get(x) ?? x; - } - size(x) { - return (this.sizes.get(this.find(x)) ?? 1); - } - connected(p, q) { - return this.find(p) == this.find(q); - } - union(a, b) { - const fa = this.find(a); - const fb = this.find(b); - if (fa == fb) { - return; - } - const sa = this.sizes.get(fa) ?? 1; - const sb = this.sizes.get(fb) ?? 1; - - if (sa < sb) { - this.parents.set(fa, fb); - this.sizes.set(fb, sb + sa); - } else { - this.parents.set(fb, fa); - this.sizes.set(fa, sb + sa); - } - } -} -/** - * @param {number} n - * @param {number[][]} roads - * @return {number} - */ -var minScore = function(n, roads) { - const uf = new UnionFind(); - - for (const [a, b] of roads) { - uf.union(a, b); - } - let ans = Infinity; - - for (const [i, j, d] of roads) { - if (uf.connected(1, i) && uf.connected(1, j)) { - ans = Math.min(ans, d); - } - } - return ans; -}; diff --git a/2492.minimum-score-of-a-path-between-two-cities.js b/2492.minimum-score-of-a-path-between-two-cities.js new file mode 100644 index 00000000..35195f71 --- /dev/null +++ b/2492.minimum-score-of-a-path-between-two-cities.js @@ -0,0 +1,31 @@ +/** + * @param {number} n + * @param {number[][]} roads + * @return {number} + */ +const minScore = function(n, roads) { + const g = {}, visited = Array(n + 1).fill(0) + let res = Infinity + for(const [u, v, d] of roads) { + if(g[u] == null) g[u] = [] + if(g[v] == null) g[v] = [] + + g[u].push([v, d]) + g[v].push([u, d]) + } + + dfs(1) + + return res + + function dfs(node) { + visited[node] = 1 + for(const [nxt, dis] of (g[node] || [])) { + res = Math.min(res, dis) + if(visited[nxt] === 0) { + dfs(nxt) + } + } + } +}; + diff --git a/2493-divide-nodes-into-the-maximum-number-of-groups.js b/2493-divide-nodes-into-the-maximum-number-of-groups.js deleted file mode 100644 index 371bf321..00000000 --- a/2493-divide-nodes-into-the-maximum-number-of-groups.js +++ /dev/null @@ -1,188 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} edges - * @return {number} - */ -const magnificentSets = function (n, edges) { - function getComponents(n) { - let visited = Array(n + 1).fill(false); - let ans = []; - for (let i = 1; i <= n; i++) { - if (!visited[i]) { - ans.push(visit(i, [], visited)); - } - } - return ans; - } - - function visit(cur, nodes, visited) { - visited[cur] = true; - nodes.push(cur); - for (let next of map.get(cur)) { - // skip if you have already visited this node - if (visited[next]) continue; - visit(next, nodes, visited); - } - return nodes; - } - - function find(node, n) { - let group = Array(n + 1).fill(-1); - - let queue = []; - queue.push(node); - let groups = 0; - while (queue.length > 0) { - let k = queue.length; - // store nodes in set to avoid duplicates - let set = new Set(); - while (k-- > 0) { - let cur = queue.shift(); - // this case occurs when 2 nodes in the same level are connected - // so, return -1 - if (group[cur] != -1) return -1; - group[cur] = groups; - for (let next of map.get(cur)) { - if (group[next] == -1) { - set.add(next); - } - } - } - for (let val of set) queue.push(val); - groups++; - } - return groups; - } - - let map = new Map(); // Integer -> List - for (let i = 1; i <= n; i++) { - map.set(i, []); - } - // adjacency list - for (let edge of edges) { - let u = edge[0], - v = edge[1]; - map.get(u).push(v); - map.get(v).push(u); - } - - // get all components as Graph can be disconnected - let components = getComponents(n); - - let ans = 0; - /* - - Take each component and get max groups can be formed from that component - - return -1 if you can't form groups from any one of the components - */ - for (let component of components) { - let groups = -1; - for (let node of component) { - groups = Math.max(groups, find(node, n)); - } - if (groups == -1) return -1; - ans += groups; - } - - return ans; -}; - -// another - -/////////////////////// Template //////////////////////////////////////// -const initializeGraph = (n) => { let g = []; for (let i = 0; i < n; i++) { g.push([]); } return g; }; -const packUG = (g, edges) => { for (const [u, v] of edges) { g[u].push(v); g[v].push(u); } }; -const initialize2DArray = (n, m) => { let d = []; for (let i = 0; i < n; i++) { let t = Array(m).fill(Number.MAX_SAFE_INTEGER); d.push(t); } return d; }; - -function DJSet(n) { - // parent[i] < 0, -parent[i] is the group size which root is i. example: (i -> parent[i] -> parent[parent[i]] -> parent[parent[parent[i]]] ...) - // parent[i] >= 0, i is not the root and parent[i] is i's parent. example: (... parent[parent[parent[i]]] -> parent[parent[i]] -> parent[i] -> i) - let parent = Array(n).fill(-1); - return { find, union, count, equiv, par } - function find(x) { - return parent[x] < 0 ? x : parent[x] = find(parent[x]); - } - function union(x, y) { - x = find(x); - y = find(y); - if (x != y) { - if (parent[x] < parent[y]) [x, y] = [y, x]; - parent[x] += parent[y]; - parent[y] = x; - } - return x == y; - } - function count() { // total groups - return parent.filter(v => v < 0).length; - } - function equiv(x, y) { // isConnected - return find(x) == find(y); - } - function par() { - return parent; - } -} - -const isBipartite = (g) => { - let n = g.length, start = 1, visit = Array(n).fill(false), q = [], color = Array(n).fill(0); // 0: no color, 1: red -1: blue - for (let i = start; i < n; i++) { - if (color[i] != 0) continue; - q.push(i); - color[i] = 1; - if (visit[i]) continue; - while (q.length) { - let cur = q.shift(); - if (visit[cur]) continue; - for (const child of g[cur]) { - if (color[child] == color[cur]) return false; - if (color[child]) continue; - color[child] = -color[cur]; - q.push(child); - } - } - } - return true; -}; -//////////////////////////////////////////////////////////////////// -/** - * @param {number} n - * @param {number[][]} edges - * @return {number} - */ -const magnificentSets = (n, edges) => { - let g = initializeGraph(n + 1), ds = new DJSet(n + 1); - packUG(g, edges); - if (!isBipartite(g)) return -1; - let d = initialize2DArray(n + 1, n + 1), res = Array(n + 1).fill(0); - for (let i = 1; i <= n; i++) d[i][i] = 0; - for (const [u, v] of edges) { - d[u][v] = 1; - d[v][u] = 1; - ds.union(u, v); - } - wf(d); - for (let i = 1; i <= n; i++) { - let max = 0; - for (let j = 1; j <= n; j++) { - if (d[i][j] >= Number.MAX_SAFE_INTEGER) continue; - max = Math.max(max, d[i][j]); - } - let par = ds.find(i); - res[par] = Math.max(res[par], max + 1); - } - let ans = 0; - for (let i = 1; i <= n; i++) ans += res[i]; - return ans; -}; - -const wf = (g) => { - let n = g.length; - for (let k = 0; k < n; k++) { - for (let i = 0; i < n; i++) { - for (let j = 0; j < n; j++) { - if (g[i][j] > g[i][k] + g[k][j]) { - g[i][j] = g[i][k] + g[k][j]; - } - } - } - } -}; diff --git a/2493.divide-nodes-into-the-maximum-number-of-groups.js b/2493.divide-nodes-into-the-maximum-number-of-groups.js new file mode 100644 index 00000000..c38de93b --- /dev/null +++ b/2493.divide-nodes-into-the-maximum-number-of-groups.js @@ -0,0 +1,88 @@ +/** + * @param {number} n + * @param {number[][]} edges + * @return {number} + */ +const magnificentSets = function (n, edges) { + function getComponents(n) { + let visited = Array(n + 1).fill(false); + let ans = []; + for (let i = 1; i <= n; i++) { + if (!visited[i]) { + ans.push(visit(i, [], visited)); + } + } + return ans; + } + + function visit(cur, nodes, visited) { + visited[cur] = true; + nodes.push(cur); + for (let next of map.get(cur)) { + // skip if you have already visited this node + if (visited[next]) continue; + visit(next, nodes, visited); + } + return nodes; + } + + function find(node, n) { + let group = Array(n + 1).fill(-1); + + let queue = []; + queue.push(node); + let groups = 0; + while (queue.length > 0) { + let k = queue.length; + // store nodes in set to avoid duplicates + let set = new Set(); + while (k-- > 0) { + let cur = queue.shift(); + // this case occurs when 2 nodes in the same level are connected + // so, return -1 + if (group[cur] != -1) return -1; + group[cur] = groups; + for (let next of map.get(cur)) { + if (group[next] == -1) { + set.add(next); + } + } + } + for (let val of set) queue.push(val); + groups++; + } + return groups; + } + + let map = new Map(); // Integer -> List + for (let i = 1; i <= n; i++) { + map.set(i, []); + } + // adjacency list + for (let edge of edges) { + let u = edge[0], + v = edge[1]; + map.get(u).push(v); + map.get(v).push(u); + } + + // get all components as Graph can be disconnected + let components = getComponents(n); + + let ans = 0; + /* + - Take each component and get max groups can be formed from that component + - return -1 if you can't form groups from any one of the components + */ + for (let component of components) { + let groups = -1; + for (let node of component) { + groups = Math.max(groups, find(node, n)); + } + if (groups == -1) return -1; + ans += groups; + } + + return ans; +}; + diff --git a/25-reverse-nodes-in-k-group.js b/25-reverse-nodes-in-k-group.js deleted file mode 100644 index bf6a75e2..00000000 --- a/25-reverse-nodes-in-k-group.js +++ /dev/null @@ -1,157 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @param {number} k - * @return {ListNode} - */ -const reverseKGroup = function(head, k) { - let n = 0 - for (let i = head; i != null; n++, i = i.next); - let dmy = new ListNode(0) - dmy.next = head - for (let prev = dmy, tail = head; n >= k; n -= k) { - for (let i = 1; i < k; i++) { - let next = tail.next.next - tail.next.next = prev.next - prev.next = tail.next - tail.next = next - } - - prev = tail - tail = tail.next - } - return dmy.next -} - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @param {number} k - * @return {ListNode} - */ -const reverseKGroup = function (head, k) { - if(head == null) return head - const dummy = new ListNode() - dummy.next = head - let n = 0, cur = head - while(cur) { - n++ - cur = cur.next - } - if(n < k) return head - let pre = dummy, tail = head - - for(let i = 0; i + k <= n; i += k) { - for(let j = 1; j < k; j++) { - const tmp = pre.next - pre.next = tail.next - tail.next = tail.next.next - pre.next.next = tmp - } - pre = tail - tail = tail.next - } - - return dummy.next -} - - - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @param {number} k - * @return {ListNode} - */ -const reverseKGroup = function (head, k) { - let ptr = head - let ktail = null - - // Head of the final, moified linked list - let new_head = null - - // Keep going until there are nodes in the list - while (ptr != null) { - let count = 0 - - // Start counting nodes from the head - ptr = head - - // Find the head of the next k nodes - while (count < k && ptr != null) { - ptr = ptr.next - count += 1 - } - - // If we counted k nodes, reverse them - if (count == k) { - // Reverse k nodes and get the new head - let revHead = reverseLinkedList(head, k) - - // new_head is the head of the final linked list - if (new_head == null) new_head = revHead - - // ktail is the tail of the previous block of - // reversed k nodes - if (ktail != null) ktail.next = revHead - - ktail = head - head = ptr - } - } - - // attach the final, possibly un-reversed portion - if (ktail != null) ktail.next = head - - return new_head == null ? head : new_head -} - -function reverseLinkedList(head, k) { - // Reverse k nodes of the given linked list. - // This function assumes that the list contains - // atleast k nodes. - let new_head = null - let ptr = head - - while (k > 0) { - // Keep track of the next node to process in the - // original list - let next_node = ptr.next - - // Insert the node pointed to by "ptr" - // at the beginning of the reversed list - ptr.next = new_head - new_head = ptr - - // Move on to the next node - ptr = next_node - - // Decrement the count of nodes to be reversed by 1 - k-- - } - - // Return the head of the reversed list - return new_head -} diff --git a/25.reverse-nodes-in-k-group.js b/25.reverse-nodes-in-k-group.js new file mode 100644 index 00000000..c913fd9c --- /dev/null +++ b/25.reverse-nodes-in-k-group.js @@ -0,0 +1,31 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @param {number} k + * @return {ListNode} + */ +const reverseKGroup = function(head, k) { + let n = 0 + for (let i = head; i != null; n++, i = i.next); + let dmy = new ListNode(0) + dmy.next = head + for (let prev = dmy, tail = head; n >= k; n -= k) { + for (let i = 1; i < k; i++) { + let next = tail.next.next + tail.next.next = prev.next + prev.next = tail.next + tail.next = next + } + + prev = tail + tail = tail.next + } + return dmy.next +} + diff --git a/250-count-univalue-subtrees.js b/250.count-univalue-subtrees.js similarity index 100% rename from 250-count-univalue-subtrees.js rename to 250.count-univalue-subtrees.js diff --git a/2503-maximum-number-of-points-from-grid-queries.js b/2503.maximum-number-of-points-from-grid-queries.js similarity index 100% rename from 2503-maximum-number-of-points-from-grid-queries.js rename to 2503.maximum-number-of-points-from-grid-queries.js diff --git a/2508-add-edges-to-make-degrees-of-all-nodes-even.js b/2508.add-edges-to-make-degrees-of-all-nodes-even.js similarity index 100% rename from 2508-add-edges-to-make-degrees-of-all-nodes-even.js rename to 2508.add-edges-to-make-degrees-of-all-nodes-even.js diff --git a/251-flatten-2d-vector.js b/251-flatten-2d-vector.js deleted file mode 100644 index 1a1e2f76..00000000 --- a/251-flatten-2d-vector.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @param {number[][]} v - */ -const Vector2D = function(v) { - this.a = [] - this.idx = 0 - v.forEach(el => this.a.push(...el)) -}; - -/** - * @return {number} - */ -Vector2D.prototype.next = function() { - return this.a[this.idx++] -}; - -/** - * @return {boolean} - */ -Vector2D.prototype.hasNext = function() { - return this.idx <= this.a.length - 1 -}; - -/** - * Your Vector2D object will be instantiated and called as such: - * var obj = new Vector2D(v) - * var param_1 = obj.next() - * var param_2 = obj.hasNext() - */ - -// another - -/** - * @param {number[][]} v - */ -const Vector2D = function(v) { - this.iterator = v[Symbol.iterator]() - this.row = this.iterator.next() - this.idx = 0 -} -/** - * @return {number} - */ -Vector2D.prototype.next = function() { - if (this.hasNext()) { - return this.row.value[this.idx++] - } -} -/** - * @return {boolean} - */ -Vector2D.prototype.hasNext = function() { - while (this.row.done == false && this.idx == this.row.value.length) { - this.row = this.iterator.next() - this.idx = 0 - } - return this.row.done == false -} -/** - * Your Vector2D object will be instantiated and called as such: - * var obj = new Vector2D(v) - * var param_1 = obj.next() - * var param_2 = obj.hasNext() - */ diff --git a/251.flatten-2d-vector.js b/251.flatten-2d-vector.js new file mode 100644 index 00000000..3c38d228 --- /dev/null +++ b/251.flatten-2d-vector.js @@ -0,0 +1,30 @@ +/** + * @param {number[][]} v + */ +const Vector2D = function(v) { + this.a = [] + this.idx = 0 + v.forEach(el => this.a.push(...el)) +}; + +/** + * @return {number} + */ +Vector2D.prototype.next = function() { + return this.a[this.idx++] +}; + +/** + * @return {boolean} + */ +Vector2D.prototype.hasNext = function() { + return this.idx <= this.a.length - 1 +}; + +/** + * Your Vector2D object will be instantiated and called as such: + * var obj = new Vector2D(v) + * var param_1 = obj.next() + * var param_2 = obj.hasNext() + */ + diff --git a/2514-count-anagrams.js b/2514.count-anagrams.js similarity index 100% rename from 2514-count-anagrams.js rename to 2514.count-anagrams.js diff --git a/2516-take-k-of-each-character-from-left-and-right.js b/2516.take-k-of-each-character-from-left-and-right.js similarity index 100% rename from 2516-take-k-of-each-character-from-left-and-right.js rename to 2516.take-k-of-each-character-from-left-and-right.js diff --git a/2518-number-of-great-partitions.js b/2518.number-of-great-partitions.js similarity index 100% rename from 2518-number-of-great-partitions.js rename to 2518.number-of-great-partitions.js diff --git a/252-meeting-rooms.js b/252.meeting-rooms.js similarity index 100% rename from 252-meeting-rooms.js rename to 252.meeting-rooms.js diff --git a/2521-distinct-prime-factors-of-product-of-array.js b/2521.distinct-prime-factors-of-product-of-array.js similarity index 100% rename from 2521-distinct-prime-factors-of-product-of-array.js rename to 2521.distinct-prime-factors-of-product-of-array.js diff --git a/2523-closest-prime-numbers-in-range.js b/2523.closest-prime-numbers-in-range.js similarity index 100% rename from 2523-closest-prime-numbers-in-range.js rename to 2523.closest-prime-numbers-in-range.js diff --git a/2527-find-xor-beauty-of-array.js b/2527.find-xor-beauty-of-array.js similarity index 100% rename from 2527-find-xor-beauty-of-array.js rename to 2527.find-xor-beauty-of-array.js diff --git a/2529-maximum-count-of-positive-integer-and-negative-integer.js b/2529.maximum-count-of-positive-integer-and-negative-integer.js similarity index 100% rename from 2529-maximum-count-of-positive-integer-and-negative-integer.js rename to 2529.maximum-count-of-positive-integer-and-negative-integer.js diff --git a/253-meeting-rooms-ii.js b/253-meeting-rooms-ii.js deleted file mode 100644 index fb5d5915..00000000 --- a/253-meeting-rooms-ii.js +++ /dev/null @@ -1,161 +0,0 @@ -/** - -Given an array of meeting time intervals consisting of -start and end times [[s1,e1],[s2,e2],...] (si < ei), -find the minimum number of conference rooms required. - -Example 1: - -Input: [[0, 30],[5, 10],[15, 20]] -Output: 2 -Example 2: - -Input: [[7,10],[2,4]] -Output: 1 - - */ - -/** - * @param {number[][]} intervals - * @return {number} - */ -const minMeetingRooms = function(intervals) { - const arr = Array(1e6 + 2).fill(0) - for(const [s, e] of intervals) { - arr[s]++ - arr[e]-- - } - let res = arr[0] - for(let i = 1; i < arr.length; i++) { - arr[i] += arr[i - 1] - res = Math.max(res, arr[i]) - } - - return res -}; - -// another - -/** - * @param {number[][]} intervals - * @return {number} - */ -const minMeetingRooms = function(intervals) { - const n = intervals.length - const start = Array(n), end = Array(n) - for(let i = 0; i < n; i++) { - start[i] = intervals[i][0] - end[i] = intervals[i][1] - } - start.sort((a, b) => a - b) - end.sort((a, b) => a - b) - - let res = 0, endIdx = 0 - for(let i = 0; i < n; i++) { - if(start[i] < end[endIdx]) res++ - else endIdx++ - } - - return res -} - - -// another - -/** - * @param {number[][]} intervals - * @return {number} - */ -const minMeetingRooms = function(intervals) { - let res = 0 - const sArr = [], eArr = [], n = intervals.length - for(const [s, e] of intervals) { - sArr.push(s) - eArr.push(e) - } - sArr.sort((a, b) => a - b) - eArr.sort((a, b) => a - b) - for(let i = 0, j = 0; i < n && j < n;) { - const s = sArr[i], e = eArr[j] - if(s < e) { - res++ - i++ - } else { - j++ - i++ - } - } - - return res -} - -// another - -/** - * @param {number[][]} intervals - * @return {number} - */ -const minMeetingRooms = function(intervals) { - intervals.sort((a, b) => a[0] - b[0] || a[1] - b[1]) - const n = intervals.length - const pq = new MinPriorityQueue() - let res = 0 - for(const [s, e] of intervals) { - while(!pq.isEmpty() && s >= pq.front().element) { - pq.dequeue() - } - pq.enqueue(e) - res = Math.max(res, pq.size()) - } - - return res -} - -// another - -/** - * @param {number[][]} intervals - * @return {number} - */ -const minMeetingRooms = function(intervals) { - const hash = {} - for(const [s, e] of intervals) { - hash[s] = (hash[s] || 0) + 1 - hash[e] = (hash[e] || 0) - 1 - } - let res = 0, cur = 0 - const keys = Object.keys(hash).map(e => +e) - keys.sort((a, b) => a - b) - for(const k of keys) { - cur += hash[k] - res = Math.max(res, cur) - } - return res -}; - -// another - -/** - * @param {number[][]} intervals - * @return {number} - */ -const minMeetingRooms = function(intervals) { - const n = intervals.length - const limit = 1e6 + 1 - const arr = Array(limit).fill(0) - let res = 0 - - for(const [start, end] of intervals) { - arr[start]++ - arr[end]-- - } - - for(let i = 1; i < limit; i++) { - arr[i] += arr[i - 1] - } - for(let i = 0; i < limit; i++) { - res = Math.max(res, arr[i]) - } - - return res -}; diff --git a/253.meeting-rooms-ii.js b/253.meeting-rooms-ii.js new file mode 100644 index 00000000..11d8aac7 --- /dev/null +++ b/253.meeting-rooms-ii.js @@ -0,0 +1,36 @@ +/** + +Given an array of meeting time intervals consisting of +start and end times [[s1,e1],[s2,e2],...] (si < ei), +find the minimum number of conference rooms required. + +Example 1: + +Input: [[0, 30],[5, 10],[15, 20]] +Output: 2 +Example 2: + +Input: [[7,10],[2,4]] +Output: 1 + + */ + +/** + * @param {number[][]} intervals + * @return {number} + */ +const minMeetingRooms = function(intervals) { + const arr = Array(1e6 + 2).fill(0) + for(const [s, e] of intervals) { + arr[s]++ + arr[e]-- + } + let res = arr[0] + for(let i = 1; i < arr.length; i++) { + arr[i] += arr[i - 1] + res = Math.max(res, arr[i]) + } + + return res +}; + diff --git a/2530-maximal-score-after-applying-k-operations.js b/2530.maximal-score-after-applying-k-operations.js similarity index 100% rename from 2530-maximal-score-after-applying-k-operations.js rename to 2530.maximal-score-after-applying-k-operations.js diff --git a/2531-make-number-of-distinct-characters-equal.js b/2531.make-number-of-distinct-characters-equal.js similarity index 100% rename from 2531-make-number-of-distinct-characters-equal.js rename to 2531.make-number-of-distinct-characters-equal.js diff --git a/2537-count-the-number-of-good-subarrays.js b/2537-count-the-number-of-good-subarrays.js deleted file mode 100644 index 58df8f51..00000000 --- a/2537-count-the-number-of-good-subarrays.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const countGood = function(nums, k) { - let res = 0, total = 0 - const cnt = {}, n = nums.length - - for(let i = 0, j = 0; i < n; i++) { - - while(j < n && total < k) { - total += diff(nums[j], 1) - cnt[nums[j]] = (cnt[nums[j]] || 0) + 1 - j++ - } - - if(total >= k) { - res += n - j + 1 - } - total += diff(nums[i], -1) - cnt[nums[i]]-- - } - - return res - - function diff(num, delta) { - const pre = cnt[num] || 0 - const old = pre * (pre - 1) / 2 - const post = pre + delta - const cur = post * (post - 1) / 2 - - return cur - old - } -}; - -// another - - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const countGood = function(nums, k) { - let res = 0; - const count = new Map() - for(let i = 0, j = 0; j < nums.length; ++j){ - k -= count.get(nums[j]) || 0; - count.set(nums[j], (count.get(nums[j]) || 0) + 1); - while(k <= 0) { - count.set(nums[i],count.get(nums[i]) - 1); - k += count.get(nums[i]); - i++ - } - res += i; - } - return res; -}; diff --git a/2537.count-the-number-of-good-subarrays.js b/2537.count-the-number-of-good-subarrays.js new file mode 100644 index 00000000..5e851cc0 --- /dev/null +++ b/2537.count-the-number-of-good-subarrays.js @@ -0,0 +1,36 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const countGood = function(nums, k) { + let res = 0, total = 0 + const cnt = {}, n = nums.length + + for(let i = 0, j = 0; i < n; i++) { + + while(j < n && total < k) { + total += diff(nums[j], 1) + cnt[nums[j]] = (cnt[nums[j]] || 0) + 1 + j++ + } + + if(total >= k) { + res += n - j + 1 + } + total += diff(nums[i], -1) + cnt[nums[i]]-- + } + + return res + + function diff(num, delta) { + const pre = cnt[num] || 0 + const old = pre * (pre - 1) / 2 + const post = pre + delta + const cur = post * (post - 1) / 2 + + return cur - old + } +}; + diff --git a/2538-difference-between-maximum-and-minimum-price-sum.js b/2538.difference-between-maximum-and-minimum-price-sum.js similarity index 100% rename from 2538-difference-between-maximum-and-minimum-price-sum.js rename to 2538.difference-between-maximum-and-minimum-price-sum.js diff --git a/254-factor-combinations.js b/254.factor-combinations.js similarity index 100% rename from 254-factor-combinations.js rename to 254.factor-combinations.js diff --git a/2542-maximum-subsequence-score.js b/2542.maximum-subsequence-score.js similarity index 100% rename from 2542-maximum-subsequence-score.js rename to 2542.maximum-subsequence-score.js diff --git a/2543-check-if-point-is-reachable.js b/2543.check-if-point-is-reachable.js similarity index 100% rename from 2543-check-if-point-is-reachable.js rename to 2543.check-if-point-is-reachable.js diff --git a/255-verify-preorder-sequence-in-binary-search-tree.js b/255.verify-preorder-sequence-in-binary-search-tree.js similarity index 100% rename from 255-verify-preorder-sequence-in-binary-search-tree.js rename to 255.verify-preorder-sequence-in-binary-search-tree.js diff --git a/2551-put-marbles-in-bags.js b/2551.put-marbles-in-bags.js similarity index 100% rename from 2551-put-marbles-in-bags.js rename to 2551.put-marbles-in-bags.js diff --git a/2555-maximize-win-from-two-segments.js b/2555.maximize-win-from-two-segments.js similarity index 100% rename from 2555-maximize-win-from-two-segments.js rename to 2555.maximize-win-from-two-segments.js diff --git a/2556-disconnect-path-in-a-binary-matrix-by-at-most-one-flip.js b/2556.disconnect-path-in-a-binary-matrix-by-at-most-one-flip.js similarity index 100% rename from 2556-disconnect-path-in-a-binary-matrix-by-at-most-one-flip.js rename to 2556.disconnect-path-in-a-binary-matrix-by-at-most-one-flip.js diff --git a/2557-maximum-number-of-integers-to-choose-from-a-range-ii.js b/2557.maximum-number-of-integers-to-choose-from-a-range-ii.js similarity index 100% rename from 2557-maximum-number-of-integers-to-choose-from-a-range-ii.js rename to 2557.maximum-number-of-integers-to-choose-from-a-range-ii.js diff --git a/2558-take-gifts-from-the-richest-pile.js b/2558.take-gifts-from-the-richest-pile.js similarity index 100% rename from 2558-take-gifts-from-the-richest-pile.js rename to 2558.take-gifts-from-the-richest-pile.js diff --git a/2559-count-vowel-strings-in-ranges.js b/2559.count-vowel-strings-in-ranges.js similarity index 100% rename from 2559-count-vowel-strings-in-ranges.js rename to 2559.count-vowel-strings-in-ranges.js diff --git a/256-paint-house.js b/256.paint-house.js similarity index 100% rename from 256-paint-house.js rename to 256.paint-house.js diff --git a/2560-house-robber-iv.js b/2560.house-robber-iv.js similarity index 100% rename from 2560-house-robber-iv.js rename to 2560.house-robber-iv.js diff --git a/2561-rearranging-fruits.js b/2561.rearranging-fruits.js similarity index 100% rename from 2561-rearranging-fruits.js rename to 2561.rearranging-fruits.js diff --git a/2563-count-the-number-of-fair-pairs.js b/2563.count-the-number-of-fair-pairs.js similarity index 100% rename from 2563-count-the-number-of-fair-pairs.js rename to 2563.count-the-number-of-fair-pairs.js diff --git a/2564-substring-xor-queries.js b/2564.substring-xor-queries.js similarity index 100% rename from 2564-substring-xor-queries.js rename to 2564.substring-xor-queries.js diff --git a/2565-subsequence-with-the-minimum-score.js b/2565.subsequence-with-the-minimum-score.js similarity index 100% rename from 2565-subsequence-with-the-minimum-score.js rename to 2565.subsequence-with-the-minimum-score.js diff --git a/2567-minimum-score-by-changing-two-elements.js b/2567-minimum-score-by-changing-two-elements.js deleted file mode 100644 index cf2a5321..00000000 --- a/2567-minimum-score-by-changing-two-elements.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const minimizeSum = function(nums) { - let s1 = Infinity, s2 = Infinity, s3 = Infinity - let l1 = -1, l2 = -1, l3 = -1 - const { max, min } = Math - // s1, s2, s3, ..., l3, l2, l1 - for(const e of nums) { - if(s1 > e) { - s3 = s2; - s2 = s1; - s1 = e; - } else if(s2 > e) { - s3 = s2 - s2 = e - } else if(s3 > e) { - s3 = e - } - - if(e > l1) { - l3 = l2 - l2 = l1 - l1 = e - } else if(e > l2) { - l3 = l2 - l2 = e - } else if(e > l3) { - l3 = e - } - } - - return min(l1 - s3, l2 - s2, l3 - s1) -}; - -// another - - -/** - * @param {number[]} nums - * @return {number} - */ -const minimizeSum = function(nums) { - nums.sort((a, b) => a - b) - const { max, min, abs } = Math - const res1 = nums.at(-1) - nums[2] - const res2 = nums.at(-2) - nums[1] - const res3 = nums.at(-3) - nums[0] - return min(res1, res2, res3) -}; diff --git a/2567.minimum-score-by-changing-two-elements.js b/2567.minimum-score-by-changing-two-elements.js new file mode 100644 index 00000000..b3973abe --- /dev/null +++ b/2567.minimum-score-by-changing-two-elements.js @@ -0,0 +1,36 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const minimizeSum = function(nums) { + let s1 = Infinity, s2 = Infinity, s3 = Infinity + let l1 = -1, l2 = -1, l3 = -1 + const { max, min } = Math + // s1, s2, s3, ..., l3, l2, l1 + for(const e of nums) { + if(s1 > e) { + s3 = s2; + s2 = s1; + s1 = e; + } else if(s2 > e) { + s3 = s2 + s2 = e + } else if(s3 > e) { + s3 = e + } + + if(e > l1) { + l3 = l2 + l2 = l1 + l1 = e + } else if(e > l2) { + l3 = l2 + l2 = e + } else if(e > l3) { + l3 = e + } + } + + return min(l1 - s3, l2 - s2, l3 - s1) +}; + diff --git a/2568-minimum-impossible-or.js b/2568.minimum-impossible-or.js similarity index 100% rename from 2568-minimum-impossible-or.js rename to 2568.minimum-impossible-or.js diff --git a/257-binary-tree-paths.js b/257-binary-tree-paths.js deleted file mode 100755 index ffc2a96a..00000000 --- a/257-binary-tree-paths.js +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {string[]} - */ -const binaryTreePaths = function(root) { - const res = []; - traverse(root, res, []); - return res; -}; - -function traverse(node, res, p) { - if (node === null) return; - p.push(node.val); - if (node.left === null && node.right === null) { - res.push(p.join("->")); - } - if (node.left) { - traverse(node.left, res, p.slice(0)); - } - if (node.right) { - traverse(node.right, res, p.slice(0)); - } -} diff --git a/257.binary-tree-paths.js b/257.binary-tree-paths.js new file mode 100644 index 00000000..86035e59 --- /dev/null +++ b/257.binary-tree-paths.js @@ -0,0 +1,30 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {string[]} + */ +const binaryTreePaths = function(root) { + const res = []; + traverse(root, res, []); + return res; +}; + +function traverse(node, res, p) { + if (node === null) return; + p.push(node.val); + if (node.left === null && node.right === null) { + res.push(p.join("->")); + } + if (node.left) { + traverse(node.left, res, p.slice(0)); + } + if (node.right) { + traverse(node.right, res, p.slice(0)); + } +} diff --git a/2570-merge-two-2d-arrays-by-summing-values.js b/2570.merge-two-2d-arrays-by-summing-values.js similarity index 100% rename from 2570-merge-two-2d-arrays-by-summing-values.js rename to 2570.merge-two-2d-arrays-by-summing-values.js diff --git a/2571-minimum-operations-to-reduce-an-integer-to-0.js b/2571-minimum-operations-to-reduce-an-integer-to-0.js deleted file mode 100644 index 70758216..00000000 --- a/2571-minimum-operations-to-reduce-an-integer-to-0.js +++ /dev/null @@ -1,54 +0,0 @@ -function dec2bin(dec) { - return (dec >>> 0).toString(2); -} -function bitCnt(s) { - let res = 0 - for(const e of s) { - if(e === '1') res++ - } - return res -} -function cnt(num) { - return bitCnt(dec2bin(num)) -} -/** - * @param {number} n - * @return {number} - */ -const minOperations = function(n) { - let res = 0 - for(let i = 0; i < 14; i++) { - if(cnt(n + (1 << i)) < cnt(n)) { - res++ - n += (1 << i) - } - } - - return res + cnt(n) -}; - -// another - - -function dec2bin(dec) { - return (dec >>> 0).toString(2); -} -function bitCnt(s) { - let res = 0 - for(const e of s) { - if(e === '1') res++ - } - return res -} -/** - * @param {number} n - * @return {number} - */ -var minOperations = function(n) { - if(n === 0) return 0 - if(bitCnt(dec2bin(n)) === 1) return 1 - const lowBit = n & -n - let low = minOperations(n + lowBit); - let high = minOperations(n - lowBit); - return Math.min(low, high) + 1; -}; diff --git a/2571.minimum-operations-to-reduce-an-integer-to-0.js b/2571.minimum-operations-to-reduce-an-integer-to-0.js new file mode 100644 index 00000000..d12b034a --- /dev/null +++ b/2571.minimum-operations-to-reduce-an-integer-to-0.js @@ -0,0 +1,29 @@ +function dec2bin(dec) { + return (dec >>> 0).toString(2); +} +function bitCnt(s) { + let res = 0 + for(const e of s) { + if(e === '1') res++ + } + return res +} +function cnt(num) { + return bitCnt(dec2bin(num)) +} +/** + * @param {number} n + * @return {number} + */ +const minOperations = function(n) { + let res = 0 + for(let i = 0; i < 14; i++) { + if(cnt(n + (1 << i)) < cnt(n)) { + res++ + n += (1 << i) + } + } + + return res + cnt(n) +}; + diff --git a/2572-count-the-number-of-square-free-subsets.js b/2572.count-the-number-of-square-free-subsets.js similarity index 100% rename from 2572-count-the-number-of-square-free-subsets.js rename to 2572.count-the-number-of-square-free-subsets.js diff --git a/2572-find-the-divisibility-array-of-a-string.js b/2572.find-the-divisibility-array-of-a-string.js similarity index 100% rename from 2572-find-the-divisibility-array-of-a-string.js rename to 2572.find-the-divisibility-array-of-a-string.js diff --git a/2573-find-the-string-with-lcp.js b/2573.find-the-string-with-lcp.js similarity index 100% rename from 2573-find-the-string-with-lcp.js rename to 2573.find-the-string-with-lcp.js diff --git a/2574-left-and-right-sum-differences.js b/2574.left-and-right-sum-differences.js similarity index 100% rename from 2574-left-and-right-sum-differences.js rename to 2574.left-and-right-sum-differences.js diff --git a/2576-find-the-maximum-number-of-marked-indices.js b/2576-find-the-maximum-number-of-marked-indices.js deleted file mode 100644 index de2fe1c7..00000000 --- a/2576-find-the-maximum-number-of-marked-indices.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const maxNumOfMarkedIndices = function(nums) { - let res = 0 - const n = nums.length - nums.sort((a, b) => a - b) - for(let i = 0, j = n - Math.floor(n / 2); j < n; j++) { - if(nums[i] * 2 <= nums[j]) { - res += 2 - i++ - } - } - - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxNumOfMarkedIndices = function(nums) { - let i = 0, n = nums.length; - nums.sort((a, b) => a - b) - for (let j = n - (~~(n / 2)); j < n; ++j) { - i += 2 * nums[i] <= nums[j] ? 1 : 0; - } - return i * 2; -}; diff --git a/2576.find-the-maximum-number-of-marked-indices.js b/2576.find-the-maximum-number-of-marked-indices.js new file mode 100644 index 00000000..94d97fdc --- /dev/null +++ b/2576.find-the-maximum-number-of-marked-indices.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const maxNumOfMarkedIndices = function(nums) { + let res = 0 + const n = nums.length + nums.sort((a, b) => a - b) + for(let i = 0, j = n - Math.floor(n / 2); j < n; j++) { + if(nums[i] * 2 <= nums[j]) { + res += 2 + i++ + } + } + + return res +}; + diff --git a/2577-minimum-time-to-visit-a-cell-in-a-grid.js b/2577.minimum-time-to-visit-a-cell-in-a-grid.js similarity index 100% rename from 2577-minimum-time-to-visit-a-cell-in-a-grid.js rename to 2577.minimum-time-to-visit-a-cell-in-a-grid.js diff --git a/258-add-digits.js b/258-add-digits.js deleted file mode 100755 index 510713b0..00000000 --- a/258-add-digits.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @param {number} num - * @return {number} - */ -const addDigits = function(num) { - let arr = ("" + num).split(""); - let res = num; - - while (arr.length > 1) { - res = arr.reduce((ac, el) => +ac + +el, 0); - arr = ("" + res).split(""); - } - return +res; -}; - -// another - -/** - * @param {number} num - * @return {number} - */ -const addDigits = function(num) { - return 1 + (num - 1) % 9; -}; - -console.log(addDigits(0)); -console.log(addDigits(38)); diff --git a/258.add-digits.js b/258.add-digits.js new file mode 100644 index 00000000..b6f25758 --- /dev/null +++ b/258.add-digits.js @@ -0,0 +1,15 @@ +/** + * @param {number} num + * @return {number} + */ +const addDigits = function(num) { + let arr = ("" + num).split(""); + let res = num; + + while (arr.length > 1) { + res = arr.reduce((ac, el) => +ac + +el, 0); + arr = ("" + res).split(""); + } + return +res; +}; + diff --git a/2582-pass-the-pillow.js b/2582.pass-the-pillow.js similarity index 100% rename from 2582-pass-the-pillow.js rename to 2582.pass-the-pillow.js diff --git a/2583-kth-largest-sum-in-a-binary-tree.js b/2583.kth-largest-sum-in-a-binary-tree.js similarity index 100% rename from 2583-kth-largest-sum-in-a-binary-tree.js rename to 2583.kth-largest-sum-in-a-binary-tree.js diff --git a/2584-split-the-array-to-make-coprime-products.js b/2584-split-the-array-to-make-coprime-products.js deleted file mode 100644 index 3d148bc2..00000000 --- a/2584-split-the-array-to-make-coprime-products.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const findValidSplit = function(nums) { - const n = nums.length, right = {}; - for (let i = 0; i < n; i++) { - const primeFactorsCount = getPrimeFactors(nums[i]); - for (let prime in primeFactorsCount) { - const count = primeFactorsCount[prime]; - right[prime] = (right[prime] || 0) + count; - } - } - const left = {}, common = new Set(); - for (let i = 0; i <= n - 2; i++) { - const primesFactorsCount = getPrimeFactors(nums[i]); - for (const prime in primesFactorsCount) { - const count = primesFactorsCount[prime]; - left[prime] = (left[prime] || 0) + count; - right[prime] -= count; - if (right[prime] > 0) common.add(prime); - else if (right[prime] === 0) common.delete(prime); - } - if (common.size === 0) return i; - } - return -1; -}; - -function getPrimeFactors(n) { - const counts = {}; - for (let x = 2; (x * x) <= n; x++) { - while (n % x === 0) { - counts[x] = (counts[x] || 0) + 1; - n /= x; - } - } - if (n > 1) counts[n] = (counts[n] || 0) + 1; - return counts; -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const findValidSplit = function (nums) { - const map = new Map() - const n = nums.length - const max = Math.max(...nums) - const primes = Eratosthenes(max) - - for (let i = 0; i < n; i++) { - let x = nums[i] - for (const p of primes) { - if (p * p > x && x > 1) { - if (!map.has(x)) { - map.set(x, [i, i]) - } - map.get(x)[1] = i - break - } - - if (x % p === 0) { - if (!map.has(p)) { - map.set(p, [i, i]) - } - const a = map.get(p) - a[1] = i - } - while (x % p === 0) x = x / p - } - } - - const diff = Array(n + 1).fill(0) - for (const [k, v] of map) { - const [s, e] = v - // if(s === e) continue - diff[s] += 1 - diff[e] -= 1 - } - // console.log(diff) - let sum = 0 - for (let i = 0; i < n - 1; i++) { - sum += diff[i] - if (sum === 0) return i - } - - return -1 -} - -function Eratosthenes(n) { - const q = Array(n + 1).fill(0) - const primes = [] - for (let i = 2; i <= Math.sqrt(n); i++) { - if (q[i] == 1) continue - let j = i * 2 - while (j <= n) { - q[j] = 1 - j += i - } - } - for (let i = 2; i <= n; i++) { - if (q[i] == 0) primes.push(i) - } - return primes -} - diff --git a/2584.split-the-array-to-make-coprime-products.js b/2584.split-the-array-to-make-coprime-products.js new file mode 100644 index 00000000..e1dcbb56 --- /dev/null +++ b/2584.split-the-array-to-make-coprime-products.js @@ -0,0 +1,40 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const findValidSplit = function(nums) { + const n = nums.length, right = {}; + for (let i = 0; i < n; i++) { + const primeFactorsCount = getPrimeFactors(nums[i]); + for (let prime in primeFactorsCount) { + const count = primeFactorsCount[prime]; + right[prime] = (right[prime] || 0) + count; + } + } + const left = {}, common = new Set(); + for (let i = 0; i <= n - 2; i++) { + const primesFactorsCount = getPrimeFactors(nums[i]); + for (const prime in primesFactorsCount) { + const count = primesFactorsCount[prime]; + left[prime] = (left[prime] || 0) + count; + right[prime] -= count; + if (right[prime] > 0) common.add(prime); + else if (right[prime] === 0) common.delete(prime); + } + if (common.size === 0) return i; + } + return -1; +}; + +function getPrimeFactors(n) { + const counts = {}; + for (let x = 2; (x * x) <= n; x++) { + while (n % x === 0) { + counts[x] = (counts[x] || 0) + 1; + n /= x; + } + } + if (n > 1) counts[n] = (counts[n] || 0) + 1; + return counts; +} + diff --git a/2585-number-of-ways-to-earn-points.js b/2585.number-of-ways-to-earn-points.js similarity index 100% rename from 2585-number-of-ways-to-earn-points.js rename to 2585.number-of-ways-to-earn-points.js diff --git a/259-3sum-smaller.js b/259.3sum-smaller.js similarity index 100% rename from 259-3sum-smaller.js rename to 259.3sum-smaller.js diff --git a/2599-make-the-prefix-sum-non-negative.js b/2599.make-the-prefix-sum-non-negative.js similarity index 100% rename from 2599-make-the-prefix-sum-non-negative.js rename to 2599.make-the-prefix-sum-non-negative.js diff --git a/26-remove-duplicates-from-sorted-array.js b/26-remove-duplicates-from-sorted-array.js deleted file mode 100755 index ed141188..00000000 --- a/26-remove-duplicates-from-sorted-array.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const removeDuplicates = function(nums) { - if (nums.length === 0) return 0; - if (nums.length === 1) return 1; - let pre = nums[0]; - for (let i = 1; i < nums.length; ) { - if (nums[i] !== pre) { - pre = nums[i]; - i += 1; - } else { - nums.splice(i, 1); - } - } - return nums.length; -}; diff --git a/26.remove-duplicates-from-sorted-array.js b/26.remove-duplicates-from-sorted-array.js new file mode 100644 index 00000000..cdf4f4cf --- /dev/null +++ b/26.remove-duplicates-from-sorted-array.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const removeDuplicates = function(nums) { + if (nums.length === 0) return 0; + if (nums.length === 1) return 1; + let pre = nums[0]; + for (let i = 1; i < nums.length; ) { + if (nums[i] !== pre) { + pre = nums[i]; + i += 1; + } else { + nums.splice(i, 1); + } + } + return nums.length; +}; diff --git a/260-single-number-III.js b/260-single-number-III.js deleted file mode 100755 index de88fee7..00000000 --- a/260-single-number-III.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[]} - */ -const singleNumber = function(nums) { - const hash = {}; - nums.forEach((el, idx) => { - if (hash.hasOwnProperty(el)) { - hash[el] += 1; - delete hash[el]; - } else { - hash[el] = 1; - } - }); - return Object.keys(hash).map(el => +el); -}; - -// another - -/** - * @param {number[]} nums - * @return {number[]} - */ -const singleNumber = function(nums) { - const s = new Set() - for(let el of nums) { - if(s.has(el)) s.delete(el) - else s.add(el) - } - return Array.from(s) -}; - -// another - -/** - * @param {number[]} nums - * @return {number[]} - */ -const singleNumber = function (nums) { - const res = Array(2).fill(0) - const x = nums.reduce((acc, v) => acc ^ v, 0) - const partition = x & ~(x - 1) - for (let i = 0; i < nums.length; i++) { - if (partition & nums[i]) { - res[1] ^= nums[i] - } else { - res[0] ^= nums[i] - } - } - return res -} diff --git a/260.single-number-III.js b/260.single-number-III.js new file mode 100644 index 00000000..4bf844c6 --- /dev/null +++ b/260.single-number-III.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} nums + * @return {number[]} + */ +const singleNumber = function(nums) { + const hash = {}; + nums.forEach((el, idx) => { + if (hash.hasOwnProperty(el)) { + hash[el] += 1; + delete hash[el]; + } else { + hash[el] = 1; + } + }); + return Object.keys(hash).map(el => +el); +}; + diff --git a/2604-minimum-time-to-eat-all-grains.js b/2604.minimum-time-to-eat-all-grains.js similarity index 100% rename from 2604-minimum-time-to-eat-all-grains.js rename to 2604.minimum-time-to-eat-all-grains.js diff --git a/2607-make-k-subarray-sums-equal.js b/2607.make-k-subarray-sums-equal.js similarity index 100% rename from 2607-make-k-subarray-sums-equal.js rename to 2607.make-k-subarray-sums-equal.js diff --git a/2608-shortest-cycle-in-a-graph.js b/2608.shortest-cycle-in-a-graph.js similarity index 100% rename from 2608-shortest-cycle-in-a-graph.js rename to 2608.shortest-cycle-in-a-graph.js diff --git a/2609-find-the-longest-balanced-substring-of-a-binary-string.js b/2609.find-the-longest-balanced-substring-of-a-binary-string.js similarity index 100% rename from 2609-find-the-longest-balanced-substring-of-a-binary-string.js rename to 2609.find-the-longest-balanced-substring-of-a-binary-string.js diff --git a/261-graph-valid-tree.js b/261-graph-valid-tree.js deleted file mode 100644 index 5347da57..00000000 --- a/261-graph-valid-tree.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} edges - * @return {boolean} - */ -const validTree = function(n, edges) { - const nums = Array(n).fill(-1) - for(let i = 0; i < edges.length; i++) { - const x = find(nums, edges[i][0]) - const y = find(nums, edges[i][1]) - if(x === y) return false - nums[x] = y - } - return edges.length === n - 1 - function find(arr, i) { - if(arr[i] === -1) return i - return find(arr, arr[i]) - } -}; - -// another - -/** - * @param {number} n - * @param {number[][]} edges - * @return {boolean} - */ -const validTree = function(n, edges) { - if (edges.length !== n - 1) { - return false - } - const graph = {} - edges.forEach(edge => { - if (!graph[edge[0]]) { - graph[edge[0]] = [] - } - if (!graph[edge[1]]) { - graph[edge[1]] = [] - } - graph[edge[0]].push(edge[1]) - graph[edge[1]].push(edge[0]) - }) - const queue = [0], - visited = new Set() - while (queue.length) { - const currentNode = queue.shift() - visited.add(currentNode) - if (graph[currentNode]) { - graph[currentNode].forEach(node => { - if (!visited.has(node)) { - queue.push(node) - } - }) - } - } - return visited.size === n -} diff --git a/261.graph-valid-tree.js b/261.graph-valid-tree.js new file mode 100644 index 00000000..5a549db6 --- /dev/null +++ b/261.graph-valid-tree.js @@ -0,0 +1,20 @@ +/** + * @param {number} n + * @param {number[][]} edges + * @return {boolean} + */ +const validTree = function(n, edges) { + const nums = Array(n).fill(-1) + for(let i = 0; i < edges.length; i++) { + const x = find(nums, edges[i][0]) + const y = find(nums, edges[i][1]) + if(x === y) return false + nums[x] = y + } + return edges.length === n - 1 + function find(arr, i) { + if(arr[i] === -1) return i + return find(arr, arr[i]) + } +}; + diff --git a/2610-convert-an-array-into-a-2d-array-with-conditions.js b/2610.convert-an-array-into-a-2d-array-with-conditions.js similarity index 100% rename from 2610-convert-an-array-into-a-2d-array-with-conditions.js rename to 2610.convert-an-array-into-a-2d-array-with-conditions.js diff --git a/2611-mice-and-cheese.js b/2611.mice-and-cheese.js similarity index 100% rename from 2611-mice-and-cheese.js rename to 2611.mice-and-cheese.js diff --git a/2614-prime-in-diagonal.js b/2614.prime-in-diagonal.js similarity index 100% rename from 2614-prime-in-diagonal.js rename to 2614.prime-in-diagonal.js diff --git a/2615-sum-of-distances.js b/2615.sum-of-distances.js similarity index 100% rename from 2615-sum-of-distances.js rename to 2615.sum-of-distances.js diff --git a/2616-minimize-the-maximum-difference-of-pairs.js b/2616.minimize-the-maximum-difference-of-pairs.js similarity index 100% rename from 2616-minimize-the-maximum-difference-of-pairs.js rename to 2616.minimize-the-maximum-difference-of-pairs.js diff --git a/2619-array-prototype-last.js b/2619.array-prototype-last.js similarity index 100% rename from 2619-array-prototype-last.js rename to 2619.array-prototype-last.js diff --git a/2626-array-reduce-transformation.js b/2626.array-reduce-transformation.js similarity index 100% rename from 2626-array-reduce-transformation.js rename to 2626.array-reduce-transformation.js diff --git a/2627-debounce.js b/2627.debounce.js similarity index 100% rename from 2627-debounce.js rename to 2627.debounce.js diff --git a/263-ugly-number.js b/263.ugly-number.js similarity index 100% rename from 263-ugly-number.js rename to 263.ugly-number.js diff --git a/2630-memoize-ii.js b/2630.memoize-ii.js similarity index 100% rename from 2630-memoize-ii.js rename to 2630.memoize-ii.js diff --git a/2632-curry.js b/2632.curry.js similarity index 100% rename from 2632-curry.js rename to 2632.curry.js diff --git a/2636-promise-pool.js b/2636.promise-pool.js similarity index 100% rename from 2636-promise-pool.js rename to 2636.promise-pool.js diff --git a/264-ugly-number-ii.js b/264.ugly-number-ii.js similarity index 100% rename from 264-ugly-number-ii.js rename to 264.ugly-number-ii.js diff --git a/2640-find-the-score-of-all-prefixes-of-an-array.js b/2640.find-the-score-of-all-prefixes-of-an-array.js similarity index 100% rename from 2640-find-the-score-of-all-prefixes-of-an-array.js rename to 2640.find-the-score-of-all-prefixes-of-an-array.js diff --git a/2642-design-graph-with-shortest-path-calculator.js b/2642.design-graph-with-shortest-path-calculator.js similarity index 100% rename from 2642-design-graph-with-shortest-path-calculator.js rename to 2642.design-graph-with-shortest-path-calculator.js diff --git a/2643-row-with-maximum-ones.js b/2643.row-with-maximum-ones.js similarity index 100% rename from 2643-row-with-maximum-ones.js rename to 2643.row-with-maximum-ones.js diff --git a/2644-find-the-maximum-divisibility-score.js b/2644.find-the-maximum-divisibility-score.js similarity index 100% rename from 2644-find-the-maximum-divisibility-score.js rename to 2644.find-the-maximum-divisibility-score.js diff --git a/2645-minimum-additions-to-make-valid-string.js b/2645.minimum-additions-to-make-valid-string.js similarity index 100% rename from 2645-minimum-additions-to-make-valid-string.js rename to 2645.minimum-additions-to-make-valid-string.js diff --git a/2646-minimize-the-total-price-of-the-trips.js b/2646.minimize-the-total-price-of-the-trips.js similarity index 100% rename from 2646-minimize-the-total-price-of-the-trips.js rename to 2646.minimize-the-total-price-of-the-trips.js diff --git a/265-paint-house-ii.js b/265.paint-house-ii.js similarity index 100% rename from 265-paint-house-ii.js rename to 265.paint-house-ii.js diff --git a/2651-calculate-delayed-arrival-time.js b/2651.calculate-delayed-arrival-time.js similarity index 100% rename from 2651-calculate-delayed-arrival-time.js rename to 2651.calculate-delayed-arrival-time.js diff --git a/2652-sum-multiples.js b/2652.sum-multiples.js similarity index 100% rename from 2652-sum-multiples.js rename to 2652.sum-multiples.js diff --git a/2653-sliding-subarray-beauty.js b/2653-sliding-subarray-beauty.js deleted file mode 100644 index 0450dda7..00000000 --- a/2653-sliding-subarray-beauty.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @param {number} x - * @return {number[]} - */ -const getSubarrayBeauty = function(nums, k, x) { - const arr = Array(101).fill(0) - const res = [], n = nums.length, delta = 50 - for(let i = 0; i < n; i++) { - const cur = nums[i] - const idx = cur + delta - arr[idx]++ - if(i < k - 1) continue - else if(i === k - 1) res.push(helper()) - else { - const prev = nums[i - k] - arr[prev + delta]-- - res.push(helper()) - } - } - - return res - - function helper() { - let res = 0, neg = 0 - // -50 ---> 0 - // -1 ---> 49 - for(let i = 0, len = arr.length; i < len; i++) { - if(i < delta && arr[i] > 0) neg += arr[i] - if(neg >= x) { - res = i - delta - break - } - } - - return res - } -}; - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @param {number} x - * @return {number[]} - */ -const getSubarrayBeauty = function(nums, k, x) { - let counter = Array(50).fill(0), ans = new Array(nums.length - k + 1).fill(0); - for (let i = 0; i < nums.length; i++) { - if (nums[i] < 0) counter[nums[i] + 50]++; - if (i - k >= 0 && nums[i - k] < 0) counter[nums[i - k] + 50]--; - if (i - k + 1 < 0) continue; - let count = 0; - for (let j = 0; j < 50; j++) { - count += counter[j]; - if (count >= x) { - ans[i - k + 1] = j - 50; - break; - } - } - } - return ans; -}; diff --git a/2653.sliding-subarray-beauty.js b/2653.sliding-subarray-beauty.js new file mode 100644 index 00000000..192ef80a --- /dev/null +++ b/2653.sliding-subarray-beauty.js @@ -0,0 +1,40 @@ +/** + * @param {number[]} nums + * @param {number} k + * @param {number} x + * @return {number[]} + */ +const getSubarrayBeauty = function(nums, k, x) { + const arr = Array(101).fill(0) + const res = [], n = nums.length, delta = 50 + for(let i = 0; i < n; i++) { + const cur = nums[i] + const idx = cur + delta + arr[idx]++ + if(i < k - 1) continue + else if(i === k - 1) res.push(helper()) + else { + const prev = nums[i - k] + arr[prev + delta]-- + res.push(helper()) + } + } + + return res + + function helper() { + let res = 0, neg = 0 + // -50 ---> 0 + // -1 ---> 49 + for(let i = 0, len = arr.length; i < len; i++) { + if(i < delta && arr[i] > 0) neg += arr[i] + if(neg >= x) { + res = i - delta + break + } + } + + return res + } +}; + diff --git a/2654-minimum-number-of-operations-to-make-all-array-elements-equal-to-1.js b/2654.minimum-number-of-operations-to-make-all-array-elements-equal-to-1.js similarity index 100% rename from 2654-minimum-number-of-operations-to-make-all-array-elements-equal-to-1.js rename to 2654.minimum-number-of-operations-to-make-all-array-elements-equal-to-1.js diff --git a/2658-maximum-number-of-fish-in-a-grid.js b/2658.maximum-number-of-fish-in-a-grid.js similarity index 100% rename from 2658-maximum-number-of-fish-in-a-grid.js rename to 2658.maximum-number-of-fish-in-a-grid.js diff --git a/266-palindrome-permutation.js b/266.palindrome-permutation.js similarity index 100% rename from 266-palindrome-permutation.js rename to 266.palindrome-permutation.js diff --git a/2660-determine-the-winner-of-a-bowling-game.js b/2660.determine-the-winner-of-a-bowling-game.js similarity index 100% rename from 2660-determine-the-winner-of-a-bowling-game.js rename to 2660.determine-the-winner-of-a-bowling-game.js diff --git a/2661-first-completely-painted-row-or-column.js b/2661.first-completely-painted-row-or-column.js similarity index 100% rename from 2661-first-completely-painted-row-or-column.js rename to 2661.first-completely-painted-row-or-column.js diff --git a/2662-minimum-cost-of-a-path-with-special-roads.js b/2662.minimum-cost-of-a-path-with-special-roads.js similarity index 100% rename from 2662-minimum-cost-of-a-path-with-special-roads.js rename to 2662.minimum-cost-of-a-path-with-special-roads.js diff --git a/2663-lexicographically-smallest-beautiful-string.js b/2663-lexicographically-smallest-beautiful-string.js deleted file mode 100644 index 9c6d0067..00000000 --- a/2663-lexicographically-smallest-beautiful-string.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @param {string} s - * @param {number} k - * @return {string} - */ -const smallestBeautifulString = function(s, k) { - const n = s.length - const original = s - const chars = s.split(''), a = 'a'.charCodeAt(0), z = 'z'.charCodeAt(0) - const codeToCh = code => String.fromCharCode(code) - let flag = false - for(let i = n - 1; i >= 0; i--) { - const code = chars[i].charCodeAt(0) - for(let j = code + 1; j < a + k && j <= z; j++) { - if(!valid(i, codeToCh(j))) continue - chars[i] = codeToCh(j) - for(let nxt = i + 1; nxt < n; nxt++) { - for(let c = a; c < a + k; c++) { - if(valid(nxt, codeToCh(c))) { - chars[nxt] = codeToCh(c) - break - } - } - } - flag = true - break - } - if(flag) break - } - - const res = chars.join('') - if(res === original) return '' - return res - - function valid(idx, ch) { - if(idx >= 1 && ch === chars[idx - 1]) return false - if(idx >= 2 && ch === chars[idx - 2]) return false - return true - } -}; - -// another - - -/** - * @param {string} s - * @param {number} k - * @return {string} - */ -const smallestBeautifulString = function (s, k) { - const chars = s.split('') - - for (let i = chars.length - 1; i >= 0; i--) { - chars[i] = String.fromCharCode(chars[i].charCodeAt(0) + 1) - while (containsPalindrome(chars, i)) { - chars[i] = String.fromCharCode(chars[i].charCodeAt(0) + 1) - } - if (chars[i] < String.fromCharCode('a'.charCodeAt(0) + k)) { - // If s[i] is among the first k letters, then change the letters after - // s[i] to the smallest ones that don't form any palindrome substring. - return changeSuffix(chars, i + 1) - } - } - - return '' - - // Returns true if chars[0..i] contains palindrome. - function containsPalindrome(chars, i) { - return ( - (i > 0 && chars[i] == chars[i - 1]) || (i > 1 && chars[i] == chars[i - 2]) - ) - } - - // Returns string where chars[i..] replaced with the smallest letters that - // don't form any palindrome substring. - function changeSuffix(chars, i) { - for (let j = i; j < chars.length; j++) { - chars[j] = 'a' - while (containsPalindrome(chars, j)) { - chars[j] = String.fromCharCode(chars[j].charCodeAt(0) + 1) - } - } - return chars.join('') - } -} diff --git a/2663.lexicographically-smallest-beautiful-string.js b/2663.lexicographically-smallest-beautiful-string.js new file mode 100644 index 00000000..bac990b3 --- /dev/null +++ b/2663.lexicographically-smallest-beautiful-string.js @@ -0,0 +1,41 @@ +/** + * @param {string} s + * @param {number} k + * @return {string} + */ +const smallestBeautifulString = function(s, k) { + const n = s.length + const original = s + const chars = s.split(''), a = 'a'.charCodeAt(0), z = 'z'.charCodeAt(0) + const codeToCh = code => String.fromCharCode(code) + let flag = false + for(let i = n - 1; i >= 0; i--) { + const code = chars[i].charCodeAt(0) + for(let j = code + 1; j < a + k && j <= z; j++) { + if(!valid(i, codeToCh(j))) continue + chars[i] = codeToCh(j) + for(let nxt = i + 1; nxt < n; nxt++) { + for(let c = a; c < a + k; c++) { + if(valid(nxt, codeToCh(c))) { + chars[nxt] = codeToCh(c) + break + } + } + } + flag = true + break + } + if(flag) break + } + + const res = chars.join('') + if(res === original) return '' + return res + + function valid(idx, ch) { + if(idx >= 1 && ch === chars[idx - 1]) return false + if(idx >= 2 && ch === chars[idx - 2]) return false + return true + } +}; + diff --git a/267-palindrome-permutation-ii.js b/267.palindrome-permutation-ii.js similarity index 100% rename from 267-palindrome-permutation-ii.js rename to 267.palindrome-permutation-ii.js diff --git a/2670-find-the-distinct-difference-array.js b/2670.find-the-distinct-difference-array.js similarity index 100% rename from 2670-find-the-distinct-difference-array.js rename to 2670.find-the-distinct-difference-array.js diff --git a/2671-frequency-tracker.js b/2671.frequency-tracker.js similarity index 100% rename from 2671-frequency-tracker.js rename to 2671.frequency-tracker.js diff --git a/2672-number-of-adjacent-elements-with-the-same-color.js b/2672.number-of-adjacent-elements-with-the-same-color.js similarity index 100% rename from 2672-number-of-adjacent-elements-with-the-same-color.js rename to 2672.number-of-adjacent-elements-with-the-same-color.js diff --git a/2673-make-costs-of-paths-equal-in-a-binary-tree.js b/2673.make-costs-of-paths-equal-in-a-binary-tree.js similarity index 100% rename from 2673-make-costs-of-paths-equal-in-a-binary-tree.js rename to 2673.make-costs-of-paths-equal-in-a-binary-tree.js diff --git a/268-missing-number.js b/268-missing-number.js deleted file mode 100755 index 69960ce7..00000000 --- a/268-missing-number.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const missingNumber = function(nums) { - const n = nums.length - let xor = 0 ^ nums[0] - for(let i = 1; i < n; i++) xor = xor ^ i ^ nums[i] - return xor ^ n -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const missingNumber = function(nums) { - const len = nums.length; - return (len * (len + 1)) / 2 - sum(nums); -}; - -function sum(arr) { - return arr.reduce((ac, el) => ac + el, 0); -} - -// another -/** - * @param {number[]} nums - * @return {number} - */ -var missingNumber = function(nums) { - const n = nums.length - const sum = nums.reduce((ac, e) => ac + e, 0) - const target = (n + 1) * n / 2 - return target - sum -}; diff --git a/268.missing-number.js b/268.missing-number.js new file mode 100644 index 00000000..1d47f100 --- /dev/null +++ b/268.missing-number.js @@ -0,0 +1,11 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const missingNumber = function(nums) { + const n = nums.length + let xor = 0 ^ nums[0] + for(let i = 1; i < n; i++) xor = xor ^ i ^ nums[i] + return xor ^ n +}; + diff --git a/2681-power-of-heroes.js b/2681.power-of-heroes.js similarity index 100% rename from 2681-power-of-heroes.js rename to 2681.power-of-heroes.js diff --git a/2682-find-the-losers-of-the-circular-game.js b/2682.find-the-losers-of-the-circular-game.js similarity index 100% rename from 2682-find-the-losers-of-the-circular-game.js rename to 2682.find-the-losers-of-the-circular-game.js diff --git a/2683-neighboring-bitwise-xor.js b/2683.neighboring-bitwise-xor.js similarity index 100% rename from 2683-neighboring-bitwise-xor.js rename to 2683.neighboring-bitwise-xor.js diff --git a/2684-maximum-number-of-moves-in-a-grid.js b/2684.maximum-number-of-moves-in-a-grid.js similarity index 100% rename from 2684-maximum-number-of-moves-in-a-grid.js rename to 2684.maximum-number-of-moves-in-a-grid.js diff --git a/2685-count-the-number-of-complete-components.js b/2685.count-the-number-of-complete-components.js similarity index 100% rename from 2685-count-the-number-of-complete-components.js rename to 2685.count-the-number-of-complete-components.js diff --git a/269-alien-dictionary.js b/269.alien-dictionary.js similarity index 100% rename from 269-alien-dictionary.js rename to 269.alien-dictionary.js diff --git a/27-remove-element.js b/27-remove-element.js deleted file mode 100755 index da7e0702..00000000 --- a/27-remove-element.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} val - * @return {number} - */ -const removeElement = function(nums, val) { - let j = 0; - for (let i = 0; i < nums.length; i++) { - if (nums[i] !== val) { - nums[j] = nums[i]; - j++; - } - } - return j; -}; diff --git a/27.remove-element.js b/27.remove-element.js new file mode 100644 index 00000000..b8f3f354 --- /dev/null +++ b/27.remove-element.js @@ -0,0 +1,15 @@ +/** + * @param {number[]} nums + * @param {number} val + * @return {number} + */ +const removeElement = function(nums, val) { + let j = 0; + for (let i = 0; i < nums.length; i++) { + if (nums[i] !== val) { + nums[j] = nums[i]; + j++; + } + } + return j; +}; diff --git a/270-closest-binary-search-tree-value.js b/270-closest-binary-search-tree-value.js deleted file mode 100644 index 5bde4e8b..00000000 --- a/270-closest-binary-search-tree-value.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - -Given a non-empty binary search tree and a target value, -find the value in the BST that is closest to the target. - -Note: - -Given target value is a floating point. -You are guaranteed to have only one unique value -in the BST that is closest to the target. - -Example: - -Input: root = [4,2,5,1,3], target = 3.714286 - - 4 - / \ - 2 5 - / \ -1 3 - -Output: 4 - -*/ - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {number} target - * @return {number} - */ -const closestValue = function(root, target) { - let res = root.val - while(root) { - if(Math.abs(root.val - target) < Math.abs(res - target)) { - res = root.val - } - root = root.val > target ? root.left : root.right - } - return res -}; - -// another - -const closestValue = function(root, target) { - const child = target < root.val ? root.left : root.right; - if (!child) return root.val; - const closest = closestValue(child, target); - return Math.abs(closest - target) < Math.abs(root.val - target) - ? closest - : root.val; -}; - -// another - -const closestValue = function(root, target) { - if(root == null) return -1 - let node = root - const stack = [] - const res = [] - const K = 1 - while(node || stack.length) { - if(node) { - stack.push(node) - node = node.left - } else { - node = stack.pop() - if(res.length === K) { - if(Math.abs(res[0] - target) < Math.abs(node.val - target)) { - return res[0] - } - res.shift() - } - res.push(node.val) - node = node.right - } - } - return res[0] -}; diff --git a/270.closest-binary-search-tree-value.js b/270.closest-binary-search-tree-value.js new file mode 100644 index 00000000..f397ce6c --- /dev/null +++ b/270.closest-binary-search-tree-value.js @@ -0,0 +1,48 @@ +/** + +Given a non-empty binary search tree and a target value, +find the value in the BST that is closest to the target. + +Note: + +Given target value is a floating point. +You are guaranteed to have only one unique value +in the BST that is closest to the target. + +Example: + +Input: root = [4,2,5,1,3], target = 3.714286 + + 4 + / \ + 2 5 + / \ +1 3 + +Output: 4 + +*/ + +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {number} target + * @return {number} + */ +const closestValue = function(root, target) { + let res = root.val + while(root) { + if(Math.abs(root.val - target) < Math.abs(res - target)) { + res = root.val + } + root = root.val > target ? root.left : root.right + } + return res +}; + diff --git a/2702-minimum-operations-to-make-numbers-non-positive.js b/2702.minimum-operations-to-make-numbers-non-positive.js similarity index 100% rename from 2702-minimum-operations-to-make-numbers-non-positive.js rename to 2702.minimum-operations-to-make-numbers-non-positive.js diff --git a/2709-greatest-common-divisor-traversal.js b/2709.greatest-common-divisor-traversal.js similarity index 100% rename from 2709-greatest-common-divisor-traversal.js rename to 2709.greatest-common-divisor-traversal.js diff --git a/271-encode-and-decode-strings.js b/271.encode-and-decode-strings.js similarity index 100% rename from 271-encode-and-decode-strings.js rename to 271.encode-and-decode-strings.js diff --git a/2710-remove-trailing-zeros-from-a-string.js b/2710.remove-trailing-zeros-from-a-string.js similarity index 100% rename from 2710-remove-trailing-zeros-from-a-string.js rename to 2710.remove-trailing-zeros-from-a-string.js diff --git a/2711-difference-of-number-of-distinct-values-on-diagonals.js b/2711.difference-of-number-of-distinct-values-on-diagonals.js similarity index 100% rename from 2711-difference-of-number-of-distinct-values-on-diagonals.js rename to 2711.difference-of-number-of-distinct-values-on-diagonals.js diff --git a/2712-minimum-cost-to-make-all-characters-equal.js b/2712.minimum-cost-to-make-all-characters-equal.js similarity index 100% rename from 2712-minimum-cost-to-make-all-characters-equal.js rename to 2712.minimum-cost-to-make-all-characters-equal.js diff --git a/2713-maximum-strictly-increasing-cells-in-a-matrix.js b/2713.maximum-strictly-increasing-cells-in-a-matrix.js similarity index 100% rename from 2713-maximum-strictly-increasing-cells-in-a-matrix.js rename to 2713.maximum-strictly-increasing-cells-in-a-matrix.js diff --git a/272-closest-binary-search-tree-value-ii.js b/272.closest-binary-search-tree-value-ii.js similarity index 100% rename from 272-closest-binary-search-tree-value-ii.js rename to 272.closest-binary-search-tree-value-ii.js diff --git a/273-integer-to-english-words.js b/273.integer-to-english-words.js similarity index 100% rename from 273-integer-to-english-words.js rename to 273.integer-to-english-words.js diff --git a/2730-find-the-longest-semi-repetitive-substring.js b/2730.find-the-longest-semi-repetitive-substring.js similarity index 100% rename from 2730-find-the-longest-semi-repetitive-substring.js rename to 2730.find-the-longest-semi-repetitive-substring.js diff --git a/274-h-index.js b/274-h-index.js deleted file mode 100644 index 80218b8a..00000000 --- a/274-h-index.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @param {number[]} citations - * @return {number} - */ -const hIndex = function(citations) { - const n = citations.length - const arr = Array(n + 1).fill(0) - for(let e of citations) { - if(e >= n) arr[n]++ - else arr[e]++ - } - for(let i = n, sum = 0; i >= 0; i--) { - sum += arr[i] - if(sum >= i) return i - } - return 0 -}; - -// another - -/** - * @param {number[]} citations - * @return {number} - */ -const hIndex = function(citations) { - citations = citations.sort((a, b) => b - a) - - for (let i = 0, len = citations.length; i < len; i++) { - if (i >= citations[i]) return i - } - - return citations.length -} - -// another - - -const hIndex = function(citations) { - const buckets = Array(citations.length + 1).fill(0) - citations.forEach(citation => { - buckets[citation >= citations.length ? citations.length : citation]++ - }) - for (let i = citations.length, count = 0; i >= 0; i--) { - count += buckets[i] - if (count >= i) return i - } - return 0 -} diff --git a/274.h-index.js b/274.h-index.js new file mode 100644 index 00000000..cebd8ea7 --- /dev/null +++ b/274.h-index.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} citations + * @return {number} + */ +const hIndex = function(citations) { + const n = citations.length + const arr = Array(n + 1).fill(0) + for(let e of citations) { + if(e >= n) arr[n]++ + else arr[e]++ + } + for(let i = n, sum = 0; i >= 0; i--) { + sum += arr[i] + if(sum >= i) return i + } + return 0 +}; + diff --git a/2747-count-zero-request-servers.js b/2747.count-zero-request-servers.js similarity index 100% rename from 2747-count-zero-request-servers.js rename to 2747.count-zero-request-servers.js diff --git a/275-h-index-ii.js b/275-h-index-ii.js deleted file mode 100644 index 254aa6db..00000000 --- a/275-h-index-ii.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @param {number[]} citations - * @return {number} - */ -const hIndex = function(citations) { - let left = 0, - len = citations.length, - right = len - 1, - mid - while (left <= right) { - mid = left + ((right - left) >> 1) - if (citations[mid] >= len - mid) right = mid - 1 - else left = mid + 1 - } - return len - left -} - -// another - -/** - * @param {number[]} citations - * @return {number} - */ -const hIndex = function(citations) { - const len = citations.length - let lo = 0, - hi = len - 1 - while (lo <= hi) { - let med = lo + ((hi - lo) >> 1) - if (citations[med] === len - med) { - return len - med - } else if (citations[med] < len - med) { - lo = med + 1 - } else { - hi = med - 1 - } - } - return len - lo -} diff --git a/275.h-index-ii.js b/275.h-index-ii.js new file mode 100644 index 00000000..dc96ce57 --- /dev/null +++ b/275.h-index-ii.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} citations + * @return {number} + */ +const hIndex = function(citations) { + let left = 0, + len = citations.length, + right = len - 1, + mid + while (left <= right) { + mid = left + ((right - left) >> 1) + if (citations[mid] >= len - mid) right = mid - 1 + else left = mid + 1 + } + return len - left +} + diff --git a/276-paint-fence.js b/276.paint-fence.js similarity index 100% rename from 276-paint-fence.js rename to 276.paint-fence.js diff --git a/2760-longest-even-odd-subarray-with-threshold.js b/2760.longest-even-odd-subarray-with-threshold.js similarity index 100% rename from 2760-longest-even-odd-subarray-with-threshold.js rename to 2760.longest-even-odd-subarray-with-threshold.js diff --git a/2761-prime-pairs-with-target-sum.js b/2761.prime-pairs-with-target-sum.js similarity index 100% rename from 2761-prime-pairs-with-target-sum.js rename to 2761.prime-pairs-with-target-sum.js diff --git a/2762-continuous-subarrays.js b/2762-continuous-subarrays.js deleted file mode 100644 index d812a6f4..00000000 --- a/2762-continuous-subarrays.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const continuousSubarrays = function(nums) { - let res = 0 - let l = 0 - let r = 0 - const mq1 = [], mq2 = [] - for(let r = 0; r < nums.length; r++) { - const e = nums[r] - while(mq1.length && nums[mq1.at(-1)] < e) mq1.pop() - mq1.push(r) - while(mq2.length && nums[mq2.at(-1)] > e) mq2.pop() - mq2.push(r) - - while(mq1.length && mq2.length && Math.abs(nums[mq1[0]] - nums[mq2[0]]) > 2) { - if(mq1.length && mq1[0] <= l) mq1.shift() - if(mq2.length && mq2[0] <= l) mq2.shift() - l++ - } - - res += r - l + 1 - } - return res -}; - - -// another - - -/** - * @param {number[]} nums - * @return {number} - */ -const continuousSubarrays = function(nums) { - let res = 0 - let l = 0 - let r = 0 - const mset = new MultiSet() - for(let r = 0; r < nums.length; r++) { - mset.add(nums[r]) - while (mset.max - mset.min > 2) { - mset.remove(nums[l]) - l++ - } - - res += r - l + 1 - } - return res -}; - -class MultiSet { - constructor() { - this.countMap = new Map() - this.valueList = [] - } - remove(value) { - if(!this.countMap.has(value)) return false - let index = binarySearch(this.valueList, value) - if (this.countMap.get(value) === 1) { - this.valueList.splice(index, 1) - this.countMap.delete(value) - } else { - this.countMap.set(value, (this.countMap.get(value) || 0) - 1) - } - return true - } - add(value) { - let index = binarySearch(this.valueList, value) - if (index < 0) { - this.valueList.splice(-index - 1, 0, value) - this.countMap.set(value, 1) - } else { - this.countMap.set(value, this.countMap.get(value) + 1) - } - } - get max() { - return this.valueList[this.valueList.length - 1] - } - get min() { - return this.valueList[0] - } -} - -function binarySearch(arr, val) { - let l = 0, r = arr.length - while( l < r ) { - const mid = Math.floor((l + r) / 2) - if(arr[mid] < val) { - l = mid + 1 - } else { - r = mid - } - } - if(arr[l] !== val) return -(l + 1) - - return l -} diff --git a/2762.continuous-subarrays.js b/2762.continuous-subarrays.js new file mode 100644 index 00000000..ad03d396 --- /dev/null +++ b/2762.continuous-subarrays.js @@ -0,0 +1,28 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const continuousSubarrays = function(nums) { + let res = 0 + let l = 0 + let r = 0 + const mq1 = [], mq2 = [] + for(let r = 0; r < nums.length; r++) { + const e = nums[r] + while(mq1.length && nums[mq1.at(-1)] < e) mq1.pop() + mq1.push(r) + while(mq2.length && nums[mq2.at(-1)] > e) mq2.pop() + mq2.push(r) + + while(mq1.length && mq2.length && Math.abs(nums[mq1[0]] - nums[mq2[0]]) > 2) { + if(mq1.length && mq1[0] <= l) mq1.shift() + if(mq2.length && mq2[0] <= l) mq2.shift() + l++ + } + + res += r - l + 1 + } + return res +}; + + diff --git a/2763-sum-of-imbalance-numbers-of-all-subarrays.js b/2763.sum-of-imbalance-numbers-of-all-subarrays.js similarity index 100% rename from 2763-sum-of-imbalance-numbers-of-all-subarrays.js rename to 2763.sum-of-imbalance-numbers-of-all-subarrays.js diff --git a/2769-find-the-maximum-achievable-number.js b/2769.find-the-maximum-achievable-number.js similarity index 100% rename from 2769-find-the-maximum-achievable-number.js rename to 2769.find-the-maximum-achievable-number.js diff --git a/277-find-the-celebrity.js b/277-find-the-celebrity.js deleted file mode 100644 index c37e8bdd..00000000 --- a/277-find-the-celebrity.js +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Definition for knows() - * - * @param {integer} person a - * @param {integer} person b - * @return {boolean} whether a knows b - * knows = function(a, b) { - * ... - * }; - */ - -/** - * @param {function} knows() - * @return {function} - */ -const solution = function(knows) { - /** - * @param {integer} n Total people - * @return {integer} The celebrity - */ - return function(n) { - if (n < 1) return -1 - let celebrity = 0 - for (let i = 1; i < n; i++) { - if (knows(celebrity, i)) { - celebrity = i - } - } - for (let i = 0; i < celebrity; i++) { - if (knows(celebrity, i)) { - return -1 - } - } - for (let i = 0; i < n; i++) { - if (i != celebrity && !knows(i, celebrity)) { - return -1 - } - } - return celebrity - } -} - -// another - -/** - * Definition for knows() - * - * @param {integer} person a - * @param {integer} person b - * @return {boolean} whether a knows b - * knows = function(a, b) { - * ... - * }; - */ - -/** - * @param {function} knows() - * @return {function} - */ -const solution = function(knows) { - /** - * @param {integer} n Total people - * @return {integer} The celebrity - */ - return function(n) { - if (n < 1) return -1 - let candidate = 0 - for (let i = 1; i < n; i++) { - if (knows(candidate, i)) candidate = i - } - for (let i = 0; i < n; i++) { - if (i < candidate && (knows(candidate, i) || !knows(i, candidate))) - return -1 - if (i > candidate && !knows(i, candidate)) return -1 - } - return candidate - } -} - diff --git a/277.find-the-celebrity.js b/277.find-the-celebrity.js new file mode 100644 index 00000000..f16393a6 --- /dev/null +++ b/277.find-the-celebrity.js @@ -0,0 +1,42 @@ +/** + * Definition for knows() + * + * @param {integer} person a + * @param {integer} person b + * @return {boolean} whether a knows b + * knows = function(a, b) { + * ... + * }; + */ + +/** + * @param {function} knows() + * @return {function} + */ +const solution = function(knows) { + /** + * @param {integer} n Total people + * @return {integer} The celebrity + */ + return function(n) { + if (n < 1) return -1 + let celebrity = 0 + for (let i = 1; i < n; i++) { + if (knows(celebrity, i)) { + celebrity = i + } + } + for (let i = 0; i < celebrity; i++) { + if (knows(celebrity, i)) { + return -1 + } + } + for (let i = 0; i < n; i++) { + if (i != celebrity && !knows(i, celebrity)) { + return -1 + } + } + return celebrity + } +} + diff --git a/2770-maximum-number-of-jumps-to-reach-the-last-index.js b/2770.maximum-number-of-jumps-to-reach-the-last-index.js similarity index 100% rename from 2770-maximum-number-of-jumps-to-reach-the-last-index.js rename to 2770.maximum-number-of-jumps-to-reach-the-last-index.js diff --git a/2771-longest-non-decreasing-subarray-from-two-arrays.js b/2771.longest-non-decreasing-subarray-from-two-arrays.js similarity index 100% rename from 2771-longest-non-decreasing-subarray-from-two-arrays.js rename to 2771.longest-non-decreasing-subarray-from-two-arrays.js diff --git a/2772-apply-operations-to-make-all-array-elements-equal-to-zero.js b/2772.apply-operations-to-make-all-array-elements-equal-to-zero.js similarity index 100% rename from 2772-apply-operations-to-make-all-array-elements-equal-to-zero.js rename to 2772.apply-operations-to-make-all-array-elements-equal-to-zero.js diff --git a/2778-sum-of-squares-of-special-elements.js b/2778.sum-of-squares-of-special-elements.js similarity index 100% rename from 2778-sum-of-squares-of-special-elements.js rename to 2778.sum-of-squares-of-special-elements.js diff --git a/2779-maximum-beauty-of-an-array-after-applying-operation.js b/2779.maximum-beauty-of-an-array-after-applying-operation.js similarity index 100% rename from 2779-maximum-beauty-of-an-array-after-applying-operation.js rename to 2779.maximum-beauty-of-an-array-after-applying-operation.js diff --git a/278-first-bad-version.js b/278.first-bad-version.js similarity index 100% rename from 278-first-bad-version.js rename to 278.first-bad-version.js diff --git a/2780-minimum-index-of-a-valid-split.js b/2780.minimum-index-of-a-valid-split.js similarity index 100% rename from 2780-minimum-index-of-a-valid-split.js rename to 2780.minimum-index-of-a-valid-split.js diff --git a/2781-length-of-the-longest-valid-substring.js b/2781.length-of-the-longest-valid-substring.js similarity index 100% rename from 2781-length-of-the-longest-valid-substring.js rename to 2781.length-of-the-longest-valid-substring.js diff --git a/279-perfect-squares.js b/279-perfect-squares.js deleted file mode 100644 index 6cdbbbdd..00000000 --- a/279-perfect-squares.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const numSquares = function(n) { - const dp = new Array(n+1).fill(Number.MAX_VALUE) - dp[0] = 0 - for(let i = 1; i <= n; i++) { - let min = Number.MAX_VALUE - let j = 1 - while(i - j*j >= 0) { - min = Math.min(min, dp[i-j*j] + 1) - ++j - } - dp[i] = min - } - return dp[n] -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const numSquares = function (n) { - if (n <= 0) return 0 - // cntPerfectSquares[i] = the least number of perfect square numbers - const cntPerfectSquares = [0] - // While cntPerfectSquares.length <= n, we need to incrementally - // calculate the next result until we get the result for n. - while (cntPerfectSquares.length <= n) { - const m = cntPerfectSquares.length - let cntSquares = Number.MAX_VALUE - for (let i = 1; i * i <= m; i++) { - cntSquares = Math.min(cntSquares, cntPerfectSquares[m - i * i] + 1) - } - cntPerfectSquares.push(cntSquares) - } - return cntPerfectSquares[n] -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const numSquares = function (n) { - // Based on Lagrange's Four Square theorem, there - // are only 4 possible results: 1, 2, 3, 4. - // If n is a perfect square, return 1. - if (is_square(n)) { - return 1 - } - // The result is 4 if and only if n can be written in the - // form of 4^k*(8*m + 7). Please refer to - // Legendre's three-square theorem. - while ((n & 3) === 0) { - // n%4 == 0 - n >>= 2 - } - if ((n & 7) === 7) { - // n%8 == 7 - return 4 - } - // Check whether 2 is the result. - let sqrt_n = Math.sqrt(n) >> 0 - for (let i = 1; i <= sqrt_n; i++) { - if (is_square(n - i * i)) { - return 2 - } - } - return 3 - function is_square(n) { - const sqrt_n = Math.sqrt(n) >> 0 - return sqrt_n * sqrt_n == n - } -} - diff --git a/279.perfect-squares.js b/279.perfect-squares.js new file mode 100644 index 00000000..bf86c8ed --- /dev/null +++ b/279.perfect-squares.js @@ -0,0 +1,19 @@ +/** + * @param {number} n + * @return {number} + */ +const numSquares = function(n) { + const dp = new Array(n+1).fill(Number.MAX_VALUE) + dp[0] = 0 + for(let i = 1; i <= n; i++) { + let min = Number.MAX_VALUE + let j = 1 + while(i - j*j >= 0) { + min = Math.min(min, dp[i-j*j] + 1) + ++j + } + dp[i] = min + } + return dp[n] +}; + diff --git a/28-implement-strStr().js b/28-implement-strStr().js deleted file mode 100755 index 98513914..00000000 --- a/28-implement-strStr().js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @param {string} haystack - * @param {string} needle - * @return {number} - */ -const strStr = function(a, b) { - if(b === '') return 0 - if(a.length < b.length) return -1 - if(a.length === b.length) return a === b ? 0 : -1 - const m = a.length, n = b.length - const fail = Array(n).fill(-1) - // DFA - for(let i = 1; i < n; i++) { - let j = fail[i - 1] - while(j !== -1 && b[j + 1] !== b[i]) { - j = fail[j] - } - if(b[j + 1] === b[i]) fail[i] = j + 1 - } - let pos = -1 - for(let i = 0; i < m; i++) { - while(pos !== -1 && a[i] !== b[pos + 1]) pos = fail[pos] - if(a[i] === b[pos + 1]) { - pos++ - if(pos === n - 1) return i - n + 1 - } - } - return -1 -}; - -// another - -/** - * @param {string} haystack - * @param {string} needle - * @return {number} - */ -const strStr = function(haystack, needle) { - if (needle === "") return 0; - for (let i = 0; ; i++) { - for (let j = 0; ; j++) { - if (j === needle.length) { - return i; - } - if (i + j === haystack.length) return -1; - if (haystack.charAt(i + j) !== needle.charAt(j)) { - break; - } - } - } -}; diff --git a/28.implement-strStr().js b/28.implement-strStr().js new file mode 100644 index 00000000..00435ab1 --- /dev/null +++ b/28.implement-strStr().js @@ -0,0 +1,30 @@ +/** + * @param {string} haystack + * @param {string} needle + * @return {number} + */ +const strStr = function(a, b) { + if(b === '') return 0 + if(a.length < b.length) return -1 + if(a.length === b.length) return a === b ? 0 : -1 + const m = a.length, n = b.length + const fail = Array(n).fill(-1) + // DFA + for(let i = 1; i < n; i++) { + let j = fail[i - 1] + while(j !== -1 && b[j + 1] !== b[i]) { + j = fail[j] + } + if(b[j + 1] === b[i]) fail[i] = j + 1 + } + let pos = -1 + for(let i = 0; i < m; i++) { + while(pos !== -1 && a[i] !== b[pos + 1]) pos = fail[pos] + if(a[i] === b[pos + 1]) { + pos++ + if(pos === n - 1) return i - n + 1 + } + } + return -1 +}; + diff --git a/280-wiggle-sort.js b/280.wiggle-sort.js similarity index 100% rename from 280-wiggle-sort.js rename to 280.wiggle-sort.js diff --git a/281-zigzag-iterator.js b/281-zigzag-iterator.js deleted file mode 100644 index 7d8ec1ce..00000000 --- a/281-zigzag-iterator.js +++ /dev/null @@ -1,142 +0,0 @@ -/** - * @constructor - * @param {Integer[]} v1 - * @param {Integer[]} v1 - */ -const ZigzagIterator = function ZigzagIterator(v1, v2) { - this.collection = [] - if (v1 !== null && v1.length !== 0) { - this.collection.push(v1) - } - if (v2 !== null && v2.length !== 0) { - this.collection.push(v2) - } -} - -/** - * @this ZigzagIterator - * @returns {boolean} - */ -ZigzagIterator.prototype.hasNext = function hasNext() { - return this.collection.length > 0 -} - -/** - * @this ZigzagIterator - * @returns {integer} - */ -ZigzagIterator.prototype.next = function next() { - if (this.collection[0].length === 1) { - return this.collection.shift()[0] - } else { - let v = this.collection.shift() - this.collection.push(v) - return v.shift() - } -} - -/** - * Your ZigzagIterator will be called like this: - * var i = new ZigzagIterator(v1, v2), a = []; - * while (i.hasNext()) a.push(i.next()); - */ - -// another - -/** - * @constructor - * @param {Integer[]} v1 - * @param {Integer[]} v1 - */ -const ZigzagIterator = function ZigzagIterator(v1, v2) { - const A = [v1, v2] - this.A = A - this.n = A.length - this.m = Math.max(v1.length, v2.length) - this.j = 0 - this.i = 0 -} - -/** - * @this ZigzagIterator - * @returns {boolean} - */ -ZigzagIterator.prototype.hasNext = function hasNext() { - return this.j < this.m -} - -/** - * @this ZigzagIterator - * @returns {integer} - */ -ZigzagIterator.prototype.incrementPointers = function incrementPointers() { - this.i += 1 - if (this.i === this.n) { - this.j += 1 - this.i = 0 - } -} - -ZigzagIterator.prototype.next = function next() { - let next = undefined - while (next === undefined) { - next = this.A[this.i][this.j] - this.incrementPointers() - } - while (this.hasNext()) { - if (this.A[this.i][this.j] !== undefined) break - this.incrementPointers() - } - return next -} - -/** - * Your ZigzagIterator will be called like this: - * var i = new ZigzagIterator(v1, v2), a = []; - * while (i.hasNext()) a.push(i.next()); - */ - -// another - -/** - * @constructor - * @param {Integer[]} v1 - * @param {Integer[]} v1 - */ -const ZigzagIterator = function ZigzagIterator(v1, v2) { - this.queue = [] - if (v1.length > 0) { - const it = v1[Symbol.iterator]() - const res = it.next() - this.queue.push({ it, res }) - } - if (v2.length > 0) { - const it = v2[Symbol.iterator]() - const res = it.next() - this.queue.push({ it, res }) - } -} -/** - * @this ZigzagIterator - * @returns {boolean} - */ -ZigzagIterator.prototype.hasNext = function hasNext() { - return this.queue.length > 0 -} -/** - * @this ZigzagIterator - * @returns {integer} - */ -ZigzagIterator.prototype.next = function next() { - const { it, res } = this.queue.shift() - const { value } = res - const res1 = it.next() - if (!res1.done) this.queue.push({ it, res: res1 }) - return value -} -/** - * Your ZigzagIterator will be called like this: - * var i = new ZigzagIterator(v1, v2), a = []; - * while (i.hasNext()) a.push(i.next()); - */ - diff --git a/281.zigzag-iterator.js b/281.zigzag-iterator.js new file mode 100644 index 00000000..adce83e0 --- /dev/null +++ b/281.zigzag-iterator.js @@ -0,0 +1,43 @@ +/** + * @constructor + * @param {Integer[]} v1 + * @param {Integer[]} v1 + */ +const ZigzagIterator = function ZigzagIterator(v1, v2) { + this.collection = [] + if (v1 !== null && v1.length !== 0) { + this.collection.push(v1) + } + if (v2 !== null && v2.length !== 0) { + this.collection.push(v2) + } +} + +/** + * @this ZigzagIterator + * @returns {boolean} + */ +ZigzagIterator.prototype.hasNext = function hasNext() { + return this.collection.length > 0 +} + +/** + * @this ZigzagIterator + * @returns {integer} + */ +ZigzagIterator.prototype.next = function next() { + if (this.collection[0].length === 1) { + return this.collection.shift()[0] + } else { + let v = this.collection.shift() + this.collection.push(v) + return v.shift() + } +} + +/** + * Your ZigzagIterator will be called like this: + * var i = new ZigzagIterator(v1, v2), a = []; + * while (i.hasNext()) a.push(i.next()); + */ + diff --git a/282-expression-add-operators.js b/282.expression-add-operators.js similarity index 100% rename from 282-expression-add-operators.js rename to 282.expression-add-operators.js diff --git a/283-move-zeroes.js b/283-move-zeroes.js deleted file mode 100755 index 3b836d3f..00000000 --- a/283-move-zeroes.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @param {number[]} nums - * @return {void} Do not return anything, modify nums in-place instead. - */ -const moveZeroes = function(nums) { - const len = nums.length; - let l = len; - for (let i = 0; i < l; ) { - if (nums[i] === 0) { - nums.splice(i, 1); - nums.push(0); - l -= 1; - } else { - i += 1; - } - } -}; diff --git a/283.move-zeroes.js b/283.move-zeroes.js new file mode 100644 index 00000000..6c991c3f --- /dev/null +++ b/283.move-zeroes.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ +const moveZeroes = function(nums) { + const len = nums.length; + let l = len; + for (let i = 0; i < l; ) { + if (nums[i] === 0) { + nums.splice(i, 1); + nums.push(0); + l -= 1; + } else { + i += 1; + } + } +}; diff --git a/285-inorder-successor-in-bst.js b/285-inorder-successor-in-bst.js deleted file mode 100644 index 71cf8ef9..00000000 --- a/285-inorder-successor-in-bst.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {TreeNode} p - * @return {TreeNode} - */ -const inorderSuccessor = function(root, p) { - const res = { node: null } - dfs(root, [], res, p) - return res.node -}; - -function dfs(node, arr, res, target) { - if(node === null) return - dfs(node.left, arr, res, target) - if(arr.length && arr[arr.length - 1] === target) res.node = node - arr.push(node) - dfs(node.right, arr, res, target) -} - -// another - -const inorderSuccessor = function(root, p) { - let last = null - const chk = node => { - if(!node) return - const l = chk(node.left) - if(l !== undefined) return l - if(last === p) return node - last = node - return chk(node.right) - } - return chk(root) -}; - -// another - -const inorderSuccessor = function(root, p) { - while (root != null && root.val <= p.val) root = root.right - const left = root == null ? null : inorderSuccessor(root.left, p) - return left != null && left.val > p.val ? left : root -} - -// another - -const inorderSuccessor = function(root, p) { - let succ = null - while(root) { - if (p.val < root.val) { - succ = root - root = root.left - } else { - root = root.right - } - } - return succ -} diff --git a/285.inorder-successor-in-bst.js b/285.inorder-successor-in-bst.js new file mode 100644 index 00000000..ff6158bc --- /dev/null +++ b/285.inorder-successor-in-bst.js @@ -0,0 +1,26 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {TreeNode} p + * @return {TreeNode} + */ +const inorderSuccessor = function(root, p) { + const res = { node: null } + dfs(root, [], res, p) + return res.node +}; + +function dfs(node, arr, res, target) { + if(node === null) return + dfs(node.left, arr, res, target) + if(arr.length && arr[arr.length - 1] === target) res.node = node + arr.push(node) + dfs(node.right, arr, res, target) +} + diff --git a/286-walls-and-gates.js b/286-walls-and-gates.js deleted file mode 100644 index f0a47019..00000000 --- a/286-walls-and-gates.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - -You are given a m x n 2D grid initialized with these three possible values. - --1 - A wall or an obstacle. -0 - A gate. -INF - Infinity means an empty room. We use the value 231 - 1 = 2147483647 -to represent INF as you may assume that the distance to a gate -is less than 2147483647. - -Fill each empty room with the distance to its nearest gate. -If it is impossible to reach a gate, it should be filled with INF. - -Example: - -Given the 2D grid: - -INF -1 0 INF -INF INF INF -1 -INF -1 INF -1 - 0 -1 INF INF -After running your function, the 2D grid should be: - - 3 -1 0 1 - 2 2 1 -1 - 1 -1 2 -1 - 0 -1 3 4 - -*/ - -/** - * @param {number[][]} rooms - * @return {void} Do not return anything, modify rooms in-place instead. - */ -const wallsAndGates = function(rooms) { - const dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]] - const rows = rooms.length - const cols = rows === 0 ? 0 : rooms[0].length - const q = [] - const INF = 2147483647 - for(let i = 0; i < rows; i++) { - for(let j = 0; j < cols; j++) { - if(rooms[i][j] === 0) q.push([i, j]) - } - } - while(q.length) { - const el = q.shift() - for(let d of dirs) { - const r = el[0] + d[0] - const c = el[1] + d[1] - if(r < 0 || c < 0 || r >= rows || c >= cols || rooms[r][c] !== INF) continue - rooms[r][c] = rooms[el[0]][el[1]] + 1 - q.push([r, c]) - } - } -}; - -// another - -/** - * @param {number[][]} rooms - * @return {void} Do not return anything, modify rooms in-place instead. - */ -const wallsAndGates = function(rooms) { - const dirs = [ - [1, 0], - [-1, 0], - [0, 1], - [0, -1] - ]; - const rows = rooms.length; - const cols = rows === 0 ? 0 : rooms[0].length; - const q = []; - const INF = 2147483647; - for (let i = 0; i < rows; i++) { - for (let j = 0; j < cols; j++) { - if (rooms[i][j] === 0) dfs(dirs, rooms, i, j, rows, cols, 0); - } - } -}; - -function dfs(dirs, rooms, i, j, rows, cols, dis) { - if ( - i < 0 || - j < 0 || - i >= rows || - j >= cols || - rooms[i][j] === -1 || - rooms[i][j] < dis - ) { - return; - } - rooms[i][j] = dis; - for (let dir of dirs) { - dfs(dirs, rooms, i + dir[0], j + dir[1], rows, cols, dis + 1); - } -} - diff --git a/286.walls-and-gates.js b/286.walls-and-gates.js new file mode 100644 index 00000000..0b7f37ac --- /dev/null +++ b/286.walls-and-gates.js @@ -0,0 +1,57 @@ +/** + +You are given a m x n 2D grid initialized with these three possible values. + +-1 - A wall or an obstacle. +0 - A gate. +INF - Infinity means an empty room. We use the value 231 - 1 = 2147483647 +to represent INF as you may assume that the distance to a gate +is less than 2147483647. + +Fill each empty room with the distance to its nearest gate. +If it is impossible to reach a gate, it should be filled with INF. + +Example: + +Given the 2D grid: + +INF -1 0 INF +INF INF INF -1 +INF -1 INF -1 + 0 -1 INF INF +After running your function, the 2D grid should be: + + 3 -1 0 1 + 2 2 1 -1 + 1 -1 2 -1 + 0 -1 3 4 + +*/ + +/** + * @param {number[][]} rooms + * @return {void} Do not return anything, modify rooms in-place instead. + */ +const wallsAndGates = function(rooms) { + const dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]] + const rows = rooms.length + const cols = rows === 0 ? 0 : rooms[0].length + const q = [] + const INF = 2147483647 + for(let i = 0; i < rows; i++) { + for(let j = 0; j < cols; j++) { + if(rooms[i][j] === 0) q.push([i, j]) + } + } + while(q.length) { + const el = q.shift() + for(let d of dirs) { + const r = el[0] + d[0] + const c = el[1] + d[1] + if(r < 0 || c < 0 || r >= rows || c >= cols || rooms[r][c] !== INF) continue + rooms[r][c] = rooms[el[0]][el[1]] + 1 + q.push([r, c]) + } + } +}; + diff --git a/287-find-the-duplicate-number.js b/287-find-the-duplicate-number.js deleted file mode 100755 index d0a9bb2d..00000000 --- a/287-find-the-duplicate-number.js +++ /dev/null @@ -1,283 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const findDuplicate = function(nums) { - const n = nums.length; - let ans = 0; - let bit_max = 31; - while (((n - 1) >> bit_max) == 0) { - bit_max -= 1; - } - for (let bit = 0; bit <= bit_max; ++bit) { - let x = 0, y = 0; - for (let i = 0; i < n; ++i) { - if ((nums[i] & (1 << bit)) != 0) { - x += 1; - } - if (i >= 1 && ((i & (1 << bit)) != 0)) { - y += 1; - } - } - if (x > y) { - ans |= 1 << bit; - } - } - return ans; -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const findDuplicate = function(nums) { - const len = nums.length - if(len > 0) { - let slow = nums[0] - let fast = nums[nums[0]] - while(slow !== fast) { - slow = nums[slow] - fast = nums[nums[fast]] - } - slow = 0 - while(slow !== fast) { - slow = nums[slow] - fast = nums[fast] - } - return slow - } - return -1; -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const findDuplicate = function(nums) { - let n = nums.length - 1, - res = 0 - for (let p = 0; p < 32; ++p) { - let bit = 1 << p, - a = 0, - b = 0 - for (let i = 0; i <= n; ++i) { - if (i > 0 && (i & bit) > 0) ++a - if ((nums[i] & bit) > 0) ++b - } - if (b > a) res += bit - } - return res -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const findDuplicate = function(nums) { - const hash = {}; - for (let i = 0; i < nums.length; i++) { - if (hash.hasOwnProperty(nums[i])) { - return nums[i]; - } else { - hash[nums[i]] = 1; - } - } -}; - - -/** - -# File: FindDuplicate.py -# Author: Keith Schwarz (htiek@cs.stanford.edu) -# -# An algorithm for solving the following (classic) hard interview problem: -# -# "You are given an array of integers of length n, where each element ranges -# from 0 to n - 2, inclusive. Prove that at least one duplicate element must -# exist, and give an O(n)-time, O(1)-space algorithm for finding some -# duplicated element. You must not modify the array elements during this -# process." -# -# This problem (reportedly) took CS legend Don Knuth twenty-four hours to solve -# and I have only met one person (Keith Amling) who could solve it in less time -# than this. -# -# The first part of this problem - proving that at least one duplicate element -# must exist - is a straightforward application of the pigeonhole principle. -# If the values range from 0 to n - 2, inclusive, then there are only n - 1 -# different values. If we have an array of n elements, one must necessarily be -# duplicated. -# -# The second part of this problem - finding the duplicated element subject to -# the given constraints - is much harder. To solve this, we're going to need a -# series of nonobvious insights that transform the problem into an instance of -# something entirely different. -# -# The main trick we need to use to solve this problem is to notice that because -# we have an array of n elements ranging from 0 to n - 2, we can think of the -# array as defining a function f from the set {0, 1, ..., n - 1} onto itself. -# This function is defined by f(i) = A[i]. Given this setup, a duplicated -# value corresponds to a pair of indices i != j such that f(i) = f(j). Our -# challenge, therefore, is to find this pair (i, j). Once we have it, we can -# easily find the duplicated value by just picking f(i) = A[i]. -# -# But how are we to find this repeated value? It turns out that this is a -# well-studied problem in computer science called cycle detection. The general -# form of the problem is as follows. We are given a function f. Define the -# sequence x_i as -# -# x_0 = k (for some k) -# x_1 = f(x_0) -# x_2 = f(f(x_0)) -# ... -# x_{n+1} = f(x_n) -# -# Assuming that f maps from a domain into itself, this function will have one -# of three forms. First, if the domain is infinite, then the sequence could be -# infinitely long and nonrepeating. For example, the function f(n) = n + 1 on -# the integers has this property - no number is ever duplicated. Second, the -# sequence could be a closed loop, which means that there is some i so that -# x_0 = x_i. In this case, the sequence cycles through some fixed set of -# values indefinitely. Finally, the sequence could be "rho-shaped." In this -# case, the sequence looks something like this: -# -# x_0 -> x_1 -> ... x_k -> x_{k+1} ... -> x_{k+j} -# ^ | -# | | -# +-----------------------+ -# -# That is, the sequence begins with a chain of elements that enters a cycle, -# then cycles around indefinitely. We'll denote the first element of the cycle -# that is reached in the sequence the "entry" of the cycle. -# -# For our particular problem of finding a duplicated element in the array, -# consider the sequence formed by starting at position n - 1 and then -# repeatedly applying f. That is, we start at the last position in the array, -# then go to the indicated index, repeating this process. My claim is that -# this sequence is rho-shaped. To see this, note that it must contains a cycle -# because the array is finite and after visiting n elements, we necessarily -# must visit some element twice. This is true no matter where we start off in -# the array. Moreover, note that since the array elements range from 0 to -# n - 2 inclusive, there is no array index that contains n - 1 as a value. -# Consequently, when we leave index n - 1 after applying the function f one -# time, we can never get back there. This means that n - 1 can't be part of a -# cycle, but if we follow indices starting there we must eventually hit some -# other node twice. The concatenation of the chain starting at n - 1 with the -# cycle it hits must be rho-shaped. -# -# Moreover, think about the node we encounter that starts at the entry of the -# cycle. Since this node is at the entry of the cycle, there must be two -# inputs to the function f that both result in that index being generated. For -# this to be possible, it must be that there are indices i != j with -# f(i) = f(j), meaning that A[i] = A[j]. Thus the index of the entry of the -# cycle must be one of the values that is duplicated in the array. -# -# There is a famous algorithm due to Robert Floyd that, given a rho-shaped -# sequence, finds the entry point of the cycle in linear time and using only -# constant space. This algorithm is often referred to as the "tortoise and -# hare" algorithm, for reasons that will become clearer shortly. -# -# The idea behind the algorithm is to define two quantities. First, let c be -# the length of the chain that enters the cycle, and let l be the length of the -# cycle. Next, let l' be the smallest multiple of l that's larger than c. -# I claim that for any rho-shaped sequence l' defined above, that -# -# x_{l'} = x_{2l'} -# -# The proof is actually straightforward and very illustrative - it's one of my -# favorite proofs in computer science. The idea is that since l' is at least -# c, it must be contained in the cycle. Moreover, since l' is a multiple of -# the length of the loop, we can write it as ml for some constant m. If we -# start at position x_{l'}, which is inside the loop, then take l' more steps -# forward to get to x_{2l'}, then we will just walk around the loop m times, -# ending up right back where we started. -# -# One key trick of Floyd's algorithm is that even if we don't explicitly know l -# or c, we can still find the value l' in O(l') time. The idea is as follows. -# We begin by keeping track of two values "slow" and "fast," both starting at -# x_0. We then iteratively compute -# -# slow = f(slow) -# fast = f(f(fast)) -# -# We repeat this process until we find that slow and fast are equal to one -# another. When this happens, we know that slow = x_j for some j, and -# fast = x_{2j} for that same j. Since x_j = x_{2j}, we know that j must be at -# least c, since it has to be contained in the cycle. Moreover, we know that j -# must be a multiple of l, since the fact that x_j = x_{2j} means that taking j -# steps while in the cycle ends up producing the same result. Finally, j must -# be the smallest multiple of l greater than c, since if there were a smaller -# multiple of l greater than c then we would have reached that multiple before -# we reached j. Consequently, we must have that j = l', meaning that we can -# find l' without knowing anything about the length or shape of the cycle! -# -# To complete the construction, we need to show how to use our information -# about l' to find the entry to the cycle (which is at position x_c). To do -# this, we start off one final variable, which we call "finder," at x_0. We -# then iteratively repeat the following: -# -# finder = f(finder) -# slow = f(slow) -# -# until finder = slow. We claim that (1) the two will eventually hit each -# other, and (2) they will hit each other at the entry to the cycle. To see -# this, we remark that since slow is at position x_{l'}, if we take c steps -# forward, then we have that slow will be at position x_{l' + c}. Since l' is -# a multiple of the loop length, this is equivalent to taking c steps forward, -# then walking around the loop some number of times back to where you started. -# In other words, x_{l' + c} = x_c. Moreover, consider the position of the -# finder variable after c steps. It starts at x_0, so after c steps it will be -# at position x_c. This proves both (1) and (2), since we've shown that the -# two must eventually hit each other, and when they do they hit at position x_c -# at the entry to the cycle. -# -# The beauty of this algorithm is that it uses only O(1) external memory to -# keep track of two different pointers - the slow pointer, and then the fast -# pointer (for the first half) and the finder pointer (for the second half). -# But on top of that, it runs in O(n) time. To see this, note that the time -# required for the slow pointer to hit the fast pointer is O(l'). Since l' is -# the smallest multiple of l greater than c, we have two cases to consider. -# First, if l > c, then this is l. Otherwise, if l < c, then we have that -# there must be some multiple of l between c and 2c. To see this, note that -# in the range c and 2c there are c different values, and since l < c at least -# one of them must be equal to 0 mod l. Finally, the time required to find the -# start of the cycle from this point is O(c). This gives a total runtime of at -# most O(c + max{l, 2c}). All of these values are at most n, so this algorithm -# runs in time O(n). - -def findArrayDuplicate(array): - assert len(array) > 0 - - # The "tortoise and hare" step. We start at the end of the array and try - # to find an intersection point in the cycle. - slow = len(array) - 1 - fast = len(array) - 1 - - # Keep advancing 'slow' by one step and 'fast' by two steps until they - # meet inside the loop. - while True: - slow = array[slow] - fast = array[array[fast]] - - if slow == fast: - break - - # Start up another pointer from the end of the array and march it forward - # until it hits the pointer inside the array. - finder = len(array) - 1 - while True: - slow = array[slow] - finder = array[finder] - - # If the two hit, the intersection index is the duplicate element. - if slow == finder: - return slow - - -*/ diff --git a/287.find-the-duplicate-number.js b/287.find-the-duplicate-number.js new file mode 100644 index 00000000..0a1e6bde --- /dev/null +++ b/287.find-the-duplicate-number.js @@ -0,0 +1,28 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const findDuplicate = function(nums) { + const n = nums.length; + let ans = 0; + let bit_max = 31; + while (((n - 1) >> bit_max) == 0) { + bit_max -= 1; + } + for (let bit = 0; bit <= bit_max; ++bit) { + let x = 0, y = 0; + for (let i = 0; i < n; ++i) { + if ((nums[i] & (1 << bit)) != 0) { + x += 1; + } + if (i >= 1 && ((i & (1 << bit)) != 0)) { + y += 1; + } + } + if (x > y) { + ans |= 1 << bit; + } + } + return ans; +}; + diff --git a/288-unique-word-abbreviation.js b/288.unique-word-abbreviation.js similarity index 100% rename from 288-unique-word-abbreviation.js rename to 288.unique-word-abbreviation.js diff --git a/289-game-of-life.js b/289.game-of-life.js similarity index 100% rename from 289-game-of-life.js rename to 289.game-of-life.js diff --git a/29-divide-two-integers.js b/29-divide-two-integers.js deleted file mode 100755 index 68e42803..00000000 --- a/29-divide-two-integers.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @param {number} dividend - * @param {number} divisor - * @return {number} - */ -const divide = function(dividend, divisor) { - if (!divisor || (dividend === Number.MIN_SAFE_INTEGER && divisor === -1)) { - return Number.MAX_SAFE_INTEGER; - } - const MAX_INT = Math.pow(2, 31) - 1; - if (dividend === -2147483648 && divisor === -1) return MAX_INT; - - const sign = (dividend < 0) ^ (divisor < 0) ? -1 : 1; - let dvd = Math.abs(dividend); - let dvs = Math.abs(divisor); - let res = 0; - - while (dvd >= dvs) { - let tmp = dvs; - let multiple = 1; - while (dvd >= tmp << 1 && tmp << 1 > 0) { - tmp <<= 1; - multiple <<= 1; - } - dvd -= tmp; - res += multiple; - } - return sign === 1 ? res : -res; -}; diff --git a/29.divide-two-integers.js b/29.divide-two-integers.js new file mode 100644 index 00000000..f06d3520 --- /dev/null +++ b/29.divide-two-integers.js @@ -0,0 +1,29 @@ +/** + * @param {number} dividend + * @param {number} divisor + * @return {number} + */ +const divide = function(dividend, divisor) { + if (!divisor || (dividend === Number.MIN_SAFE_INTEGER && divisor === -1)) { + return Number.MAX_SAFE_INTEGER; + } + const MAX_INT = Math.pow(2, 31) - 1; + if (dividend === -2147483648 && divisor === -1) return MAX_INT; + + const sign = (dividend < 0) ^ (divisor < 0) ? -1 : 1; + let dvd = Math.abs(dividend); + let dvs = Math.abs(divisor); + let res = 0; + + while (dvd >= dvs) { + let tmp = dvs; + let multiple = 1; + while (dvd >= tmp << 1 && tmp << 1 > 0) { + tmp <<= 1; + multiple <<= 1; + } + dvd -= tmp; + res += multiple; + } + return sign === 1 ? res : -res; +}; diff --git a/290-word-pattern.js b/290.word-pattern.js similarity index 100% rename from 290-word-pattern.js rename to 290.word-pattern.js diff --git a/291-word-pattern-ii.js b/291-word-pattern-ii.js deleted file mode 100644 index 91f77ac2..00000000 --- a/291-word-pattern-ii.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @param {string} pattern - * @param {string} str - * @return {boolean} - */ -const wordPatternMatch = function(pattern, str) { - const map = new Map() - const set = new Set() - return isMatch(str, 0, pattern, 0, map, set) -}; -function isMatch(str, i, pat, j, map, set) { - if(i === str.length && j === pat.length) return true - if(i === str.length || j === pat.length) return false - let c = pat.charAt(j) - if(map.has(c)) { - let s = map.get(c) - if(!str.startsWith(s, i)) return false - return isMatch(str, i + s.length, pat, j + 1, map, set) - } - for(let k = i; k < str.length; k++) { - let p = str.slice(i, k + 1) - if(set.has(p)) continue - map.set(c, p) - set.add(p) - if(isMatch(str, k + 1, pat, j + 1, map, set)) return true - map.delete(c) - set.delete(p) - } - return false -} - -// another - -/** - * @param {string} pattern - * @param {string} s - * @return {boolean} - */ -const wordPatternMatch = function(pattern, s) { - const obj = { res: false } - const hash = {} - helper(pattern, s, 0, 0, hash, obj) - return obj.res -}; - -function helper(p, s, i, j, hash, obj) { - if(obj.res) return - if(i === p.length && j === s.length) { - obj.res = true - return - } - if(i >= p.length || j >= s.length) return - for(let m = j; m < s.length && obj.res === false; m++) { - const tmp = s.slice(j, m + 1) - if(hash[p[i]]) { - if(tmp === hash[p[i]]) { - helper(p, s, i + 1, m + 1, hash, obj) - } - } else { - const set = new Set(Object.values(hash)) - if (!set.has(tmp)) { - hash[p[i]] = tmp - helper(p, s, i + 1, m + 1, hash, obj) - delete hash[p[i]] - } - } - } -} diff --git a/291.word-pattern-ii.js b/291.word-pattern-ii.js new file mode 100644 index 00000000..02439de9 --- /dev/null +++ b/291.word-pattern-ii.js @@ -0,0 +1,31 @@ +/** + * @param {string} pattern + * @param {string} str + * @return {boolean} + */ +const wordPatternMatch = function(pattern, str) { + const map = new Map() + const set = new Set() + return isMatch(str, 0, pattern, 0, map, set) +}; +function isMatch(str, i, pat, j, map, set) { + if(i === str.length && j === pat.length) return true + if(i === str.length || j === pat.length) return false + let c = pat.charAt(j) + if(map.has(c)) { + let s = map.get(c) + if(!str.startsWith(s, i)) return false + return isMatch(str, i + s.length, pat, j + 1, map, set) + } + for(let k = i; k < str.length; k++) { + let p = str.slice(i, k + 1) + if(set.has(p)) continue + map.set(c, p) + set.add(p) + if(isMatch(str, k + 1, pat, j + 1, map, set)) return true + map.delete(c) + set.delete(p) + } + return false +} + diff --git a/292-nim-game.js b/292.nim-game.js similarity index 100% rename from 292-nim-game.js rename to 292.nim-game.js diff --git a/293-flip-game.js b/293.flip-game.js similarity index 100% rename from 293-flip-game.js rename to 293.flip-game.js diff --git a/294-flip-game-ii.js b/294.flip-game-ii.js similarity index 100% rename from 294-flip-game-ii.js rename to 294.flip-game-ii.js diff --git a/295-find-median-from-data-stream.js b/295-find-median-from-data-stream.js deleted file mode 100644 index 99487161..00000000 --- a/295-find-median-from-data-stream.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - * initialize your data structure here. - */ -const MedianFinder = function() { - this.arr = []; -}; -/** - * @param {number} num - * @return {void} - */ -MedianFinder.prototype.addNum = function(num) { - const bs = n => { - let start = 0; - let end = this.arr.length; - while (start < end) { - let mid = ~~((start + end) / 2); - if (n > this.arr[mid]) start = mid + 1; - else end = mid; - } - this.arr.splice(start, 0, n); - }; - if (this.arr.length === 0) this.arr.push(num); - else bs(num); -}; - -/** - * @return {number} - */ -MedianFinder.prototype.findMedian = function() { - const mid = ~~(this.arr.length / 2); - return this.arr.length % 2 === 0 - ? (this.arr[mid - 1] + this.arr[mid]) / 2 - : this.arr[mid]; -}; -/** - * Your MedianFinder object will be instantiated and called as such: - * var obj = new MedianFinder() - * obj.addNum(num) - * var param_2 = obj.findMedian() - */ - -// another - -/** - * initialize your data structure here. - */ -const MedianFinder = function() { - this.minPQ = new PriorityQueue() - this.maxPQ = new PriorityQueue((a, b) => a < b) -}; - -/** - * @param {number} num - * @return {void} - */ -MedianFinder.prototype.addNum = function(num) { - this.minPQ.push(num) - this.maxPQ.push(this.minPQ.pop()) - if(this.minPQ.size() < this.maxPQ.size()) { - this.minPQ.push(this.maxPQ.pop()) - } -}; - -/** - * @return {number} - */ -MedianFinder.prototype.findMedian = function() { - if(this.minPQ.size() > this.maxPQ.size()) return this.minPQ.peek() - else return (this.minPQ.peek() + this.maxPQ.peek()) / 2 -}; - -/** - * Your MedianFinder object will be instantiated and called as such: - * var obj = new MedianFinder() - * obj.addNum(num) - * var param_2 = obj.findMedian() - */ -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/295.find-median-from-data-stream.js b/295.find-median-from-data-stream.js new file mode 100644 index 00000000..7d705fef --- /dev/null +++ b/295.find-median-from-data-stream.js @@ -0,0 +1,41 @@ +/** + * initialize your data structure here. + */ +const MedianFinder = function() { + this.arr = []; +}; +/** + * @param {number} num + * @return {void} + */ +MedianFinder.prototype.addNum = function(num) { + const bs = n => { + let start = 0; + let end = this.arr.length; + while (start < end) { + let mid = ~~((start + end) / 2); + if (n > this.arr[mid]) start = mid + 1; + else end = mid; + } + this.arr.splice(start, 0, n); + }; + if (this.arr.length === 0) this.arr.push(num); + else bs(num); +}; + +/** + * @return {number} + */ +MedianFinder.prototype.findMedian = function() { + const mid = ~~(this.arr.length / 2); + return this.arr.length % 2 === 0 + ? (this.arr[mid - 1] + this.arr[mid]) / 2 + : this.arr[mid]; +}; +/** + * Your MedianFinder object will be instantiated and called as such: + * var obj = new MedianFinder() + * obj.addNum(num) + * var param_2 = obj.findMedian() + */ + diff --git a/296-best-meeting-point.js b/296-best-meeting-point.js deleted file mode 100644 index deceaa09..00000000 --- a/296-best-meeting-point.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - -A group of two or more people wants to meet and minimize the total travel distance. -You are given a 2D grid of values 0 or 1, where each 1 marks the home of someone in the group. -The distance is calculated using Manhattan Distance, -where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|. - -Example: - -Input: - -1 - 0 - 0 - 0 - 1 -| | | | | -0 - 0 - 0 - 0 - 0 -| | | | | -0 - 0 - 1 - 0 - 0 - -Output: 6 - -Explanation: Given three people living at (0,0), (0,4), and (2,2): - The point (0,2) is an ideal meeting point, as the total travel distance - of 2+2+2=6 is minimal. So return 6. - -*/ - -/** - * @param {number[][]} grid - * @return {number} - */ -const minTotalDistance = function(grid) { - const m = grid.length - if(!m) return 0 - const n = grid[0].length - const I = [] - const J = [] - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - if(grid[i][j] === 1) I.push(i) - } - } - for(let j = 0; j < n; j++) { - for(let i = 0; i < m; i++) { - if(grid[i][j] === 1) J.push(j) - } - } - return min(I) + min(J) -}; - -function min(arr) { - let i = 0, j = arr.length - 1, sum = 0 - while(i < j) { - sum += arr[j--] - arr[i++] - } - return sum -} - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -const minTotalDistance = function (grid) { - const homeArr = [] - const horiArr = [], vertArr = [] - const m = grid.length, - n = grid[0].length - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - if (grid[i][j] === 1) { - homeArr.push([i, j]) - vertArr.push(i) - horiArr.push(j) - } - } - } - - vertArr.sort((a, b) => a - b) - horiArr.sort((a, b) => a - b) - - let y = vertArr[~~(vertArr.length/2)] - let x = horiArr[~~(horiArr.length/2)] - - const center = [y, x] - - let res = 0 - for(const point of homeArr) { - res += dis(center, point) - } - - return res - - function dis(a, b) { - return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]) - } - -} diff --git a/296.best-meeting-point.js b/296.best-meeting-point.js new file mode 100644 index 00000000..e0b6c6c3 --- /dev/null +++ b/296.best-meeting-point.js @@ -0,0 +1,56 @@ +/** + +A group of two or more people wants to meet and minimize the total travel distance. +You are given a 2D grid of values 0 or 1, where each 1 marks the home of someone in the group. +The distance is calculated using Manhattan Distance, +where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|. + +Example: + +Input: + +1 - 0 - 0 - 0 - 1 +| | | | | +0 - 0 - 0 - 0 - 0 +| | | | | +0 - 0 - 1 - 0 - 0 + +Output: 6 + +Explanation: Given three people living at (0,0), (0,4), and (2,2): + The point (0,2) is an ideal meeting point, as the total travel distance + of 2+2+2=6 is minimal. So return 6. + +*/ + +/** + * @param {number[][]} grid + * @return {number} + */ +const minTotalDistance = function(grid) { + const m = grid.length + if(!m) return 0 + const n = grid[0].length + const I = [] + const J = [] + for(let i = 0; i < m; i++) { + for(let j = 0; j < n; j++) { + if(grid[i][j] === 1) I.push(i) + } + } + for(let j = 0; j < n; j++) { + for(let i = 0; i < m; i++) { + if(grid[i][j] === 1) J.push(j) + } + } + return min(I) + min(J) +}; + +function min(arr) { + let i = 0, j = arr.length - 1, sum = 0 + while(i < j) { + sum += arr[j--] - arr[i++] + } + return sum +} + diff --git a/297-serialize-and-deserialize-binary-tree.js b/297.serialize-and-deserialize-binary-tree.js similarity index 100% rename from 297-serialize-and-deserialize-binary-tree.js rename to 297.serialize-and-deserialize-binary-tree.js diff --git a/298-binary-tree-longest-consecutive-sequence.js b/298.binary-tree-longest-consecutive-sequence.js similarity index 100% rename from 298-binary-tree-longest-consecutive-sequence.js rename to 298.binary-tree-longest-consecutive-sequence.js diff --git a/299-bulls-and-cows.js b/299-bulls-and-cows.js deleted file mode 100644 index dd67443e..00000000 --- a/299-bulls-and-cows.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @param {string} secret - * @param {string} guess - * @return {string} - */ -const getHint = function(secret, guess) { - let x = 0, y = 0 - const arr = Array(10).fill(0) - for(let i = 0; i < guess.length; i++) { - const ch = guess[i], e = secret[i] - if(secret[i] === ch) { - x++ - } else { - if(arr[+ch] < 0) y++ - if(arr[+e] > 0) y++ - arr[+ch]++ - arr[+e]-- - } - } - - return `${x}A${y}B` -}; - -// another - -/** - * @param {string} secret - * @param {string} guess - * @return {string} - */ -const getHint = function(secret, guess) { - let bulls = 0 - let cows = 0 - const h = {} - for(let i = 0, len = secret.length; i < len; i++) { - if(secret[i] === guess[i]) { - bulls++ - } else { - if(!h.hasOwnProperty(secret[i])) h[secret[i]] = 0 - h[secret[i]]++ - } - } - - for(let i = 0, len = secret.length; i < len; i++) { - if(secret[i] !== guess[i]) { - if(h.hasOwnProperty(guess[i]) && h[guess[i]] > 0) { - cows++ - h[guess[i]]-- - } - } - } - - return `${bulls}A${cows}B` -}; diff --git a/299.bulls-and-cows.js b/299.bulls-and-cows.js new file mode 100644 index 00000000..b16e11f4 --- /dev/null +++ b/299.bulls-and-cows.js @@ -0,0 +1,23 @@ +/** + * @param {string} secret + * @param {string} guess + * @return {string} + */ +const getHint = function(secret, guess) { + let x = 0, y = 0 + const arr = Array(10).fill(0) + for(let i = 0; i < guess.length; i++) { + const ch = guess[i], e = secret[i] + if(secret[i] === ch) { + x++ + } else { + if(arr[+ch] < 0) y++ + if(arr[+e] > 0) y++ + arr[+ch]++ + arr[+e]-- + } + } + + return `${x}A${y}B` +}; + diff --git a/3-longest-substring-without-repeating-characters.js b/3-longest-substring-without-repeating-characters.js deleted file mode 100755 index 78f0636b..00000000 --- a/3-longest-substring-without-repeating-characters.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const lengthOfLongestSubstring = function(s) { - if(s.length < 2) return s.length - const hash = {} - let max = 0 - for(let i = 0, j = -1, len = s.length; i < len; i++) { - const cur = s[i] - if(hash[cur] != null) j = Math.max(j, hash[cur]) - - hash[cur] = i - max = Math.max(max, i - j) - } - - return max -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const lengthOfLongestSubstring = function(s) { - // var p=0, q=0; //p: start of the sub, q: end of the queue - - //hashmap in js????? Array.indexOf - const sub = []; - let max = 0; - - for (let i = 0; i < s.length; i++) { - let index = sub.indexOf(s.charAt(i)); - if (index == -1) { - sub.push(s.charAt(i)); - // q++; - } else { - //find repeat, get index of repeat el, remve all el before that index - sub = sub.slice(index + 1, sub.length); - sub.push(s.charAt(i)); - } - max = Math.max(max, sub.length); - } - return max; -}; diff --git a/3.longest-substring-without-repeating-characters.js b/3.longest-substring-without-repeating-characters.js new file mode 100644 index 00000000..91fab5c9 --- /dev/null +++ b/3.longest-substring-without-repeating-characters.js @@ -0,0 +1,19 @@ +/** + * @param {string} s + * @return {number} + */ +const lengthOfLongestSubstring = function(s) { + if(s.length < 2) return s.length + const hash = {} + let max = 0 + for(let i = 0, j = -1, len = s.length; i < len; i++) { + const cur = s[i] + if(hash[cur] != null) j = Math.max(j, hash[cur]) + + hash[cur] = i + max = Math.max(max, i - j) + } + + return max +}; + diff --git a/30-substring-with-concatenation-of-all-words.js b/30-substring-with-concatenation-of-all-words.js deleted file mode 100644 index 09e30dcc..00000000 --- a/30-substring-with-concatenation-of-all-words.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * @param {string} s - * @param {string[]} words - * @return {number[]} - */ -const findSubstring = function(s, words) { - if (words == null || words.length === 0 || !s) return [] - const wh = {} - const slen = s.length - const wl = words[0].length - const len = words[0].length * words.length - words.forEach(el => { - if (wh[el]) wh[el]++ - else wh[el] = 1 - }) - const res = [] - for (let i = 0; i < slen - len + 1; i++) { - if (chk(wh, s.slice(i, i + len), wl, words.length)) res.push(i) - } - return res -} - -function chk(hash, str, wl, num) { - const oh = {} - for (let i = 0; i < num; i++) { - let tmp = str.slice(i * wl, i * wl + wl) - if (oh[tmp]) oh[tmp]++ - else oh[tmp] = 1 - } - const keys = Object.keys(hash) - for (let i = 0; i < keys.length; i++) { - if (oh[keys[i]] !== hash[keys[i]]) return false - } - return true -} - -// another - -/** - * @param {string} s - * @param {string[]} words - * @return {number[]} - */ -const findSubstring = function(s, words) { - if (s === "" || words.length === 0) return [] - const wordMap = new Map() - words.forEach(item => { - if (wordMap.has(item)) { - wordMap.set(item, wordMap.get(item) + 1) - } else { - wordMap.set(item, 1) - } - }) - const w = words[0].length - const wlen = words.length - const ans = [] - const n = s.length - for (let i = 0; i < w; i++) { - let left = i - let count = 0 - let sMap = new Map() - for (let j = i; j <= n - w; j += w) { - let sub = s.substring(j, j + w) - if (wordMap.has(sub)) { - if (sMap.has(sub)) { - sMap.set(sub, sMap.get(sub) + 1) - } else { - sMap.set(sub, 1) - } - if (sMap.get(sub) <= wordMap.get(sub)) { - count++ - } else { - while (sMap.get(sub) > wordMap.get(sub)) { - let next = s.substring(left, left + w) - sMap.set(next, sMap.get(next) - 1) - if (sMap.get(next) < wordMap.get(next)) { - count-- - } - left += w - } - } - if (count === wlen) { - ans.push(left) - let first = s.substring(left, left + w) - sMap.set(first, sMap.get(first) - 1) - left += w - count-- - } - } else { - sMap.clear() - count = 0 - left = j + w - } - } - } - return ans -} diff --git a/30.substring-with-concatenation-of-all-words.js b/30.substring-with-concatenation-of-all-words.js new file mode 100644 index 00000000..61f5bfd1 --- /dev/null +++ b/30.substring-with-concatenation-of-all-words.js @@ -0,0 +1,36 @@ +/** + * @param {string} s + * @param {string[]} words + * @return {number[]} + */ +const findSubstring = function(s, words) { + if (words == null || words.length === 0 || !s) return [] + const wh = {} + const slen = s.length + const wl = words[0].length + const len = words[0].length * words.length + words.forEach(el => { + if (wh[el]) wh[el]++ + else wh[el] = 1 + }) + const res = [] + for (let i = 0; i < slen - len + 1; i++) { + if (chk(wh, s.slice(i, i + len), wl, words.length)) res.push(i) + } + return res +} + +function chk(hash, str, wl, num) { + const oh = {} + for (let i = 0; i < num; i++) { + let tmp = str.slice(i * wl, i * wl + wl) + if (oh[tmp]) oh[tmp]++ + else oh[tmp] = 1 + } + const keys = Object.keys(hash) + for (let i = 0; i < keys.length; i++) { + if (oh[keys[i]] !== hash[keys[i]]) return false + } + return true +} + diff --git a/300-longest-increasing-subsequence.js b/300-longest-increasing-subsequence.js deleted file mode 100644 index 3d79c6ec..00000000 --- a/300-longest-increasing-subsequence.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const lengthOfLIS = function(nums) { - const stack = [] - for(let e of nums) { - if(stack.length === 0 || e > stack[stack.length - 1]) { - stack.push(e) - continue - } - let l = 0, r = stack.length - 1, mid - while(l < r) { - const mid = l + ((r - l) >> 1) - if(e > stack[mid]) l = mid + 1 - else r = mid - } - stack[l] = e - } - return stack.length -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const lengthOfLIS = function(nums) { - if (nums.length === 0) { - return 0 - } - const dp = new Array(nums.length).fill(0) - dp[0] = 1 - let maxans = 1 - for(let i = 1; i < dp.length; i++) { - let maxval = 0 - for(let j = 0; j < i; j++) { - if(nums[i] > nums[j]) { - maxval = Math.max(maxval, dp[j]) - } - } - dp[i] = maxval + 1 - maxans = Math.max(maxans, dp[i]) - } - return maxans -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const lengthOfLIS = function(nums) { - const n = nums.length - const tails = [] - let res = 0 - for(let e of nums) { - let i = 0, j = res - while(i !== j) { - const mid = i + ((j - i) >> 1) - if(tails[mid] < e) i = mid + 1 - else j = mid - } - tails[i] = e - if(i === res) res++ - } - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const lengthOfLIS = function(nums) { - const n = nums.length, stack = [] - let res = 0 - stack.push(nums[0]) - for(let i = 1; i < n; i++) { - const cur = nums[i] - if(cur > stack[stack.length - 1]) { - stack.push(cur) - } else { - let l = 0, r = stack.length - 1 - while(l < r) { - let mid = ~~((l + r) / 2) - if(stack[mid] < cur) { - l = mid + 1 - } else { - r = mid - } - } - stack[l] = cur - } - } - - return stack.length -}; diff --git a/300.longest-increasing-subsequence.js b/300.longest-increasing-subsequence.js new file mode 100644 index 00000000..7b13a04e --- /dev/null +++ b/300.longest-increasing-subsequence.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const lengthOfLIS = function(nums) { + const stack = [] + for(let e of nums) { + if(stack.length === 0 || e > stack[stack.length - 1]) { + stack.push(e) + continue + } + let l = 0, r = stack.length - 1, mid + while(l < r) { + const mid = l + ((r - l) >> 1) + if(e > stack[mid]) l = mid + 1 + else r = mid + } + stack[l] = e + } + return stack.length +}; + diff --git a/301-remove-invalid-parentheses.js b/301-remove-invalid-parentheses.js deleted file mode 100644 index 9cb8bdde..00000000 --- a/301-remove-invalid-parentheses.js +++ /dev/null @@ -1,69 +0,0 @@ -/** - * @param {string} s - * @return {string[]} - */ -const removeInvalidParentheses = function(s) { - const res = [] - helper(s, 0, 0, ['(', ')']) - return res - - function helper(str, lastI, lastJ, pair) { - let openNum = 0, closeNum = 0 - for(let i = lastI; i < str.length; i++) { - if(str[i] === pair[0]) openNum++ - if(str[i] === pair[1]) closeNum++ - if(closeNum > openNum) { - for(let j = lastJ; j <= i; j++) { - if(str[j] === pair[1] && (j === lastJ || str[j - 1] !== pair[1])) { - helper(str.slice(0, j) + str.slice(j + 1), i, j, pair) - } - } - return - } - } - let rev = str.split('').reverse().join('') - if(pair[0] === '(') { - helper(rev, 0, 0, [')', '(']) - } else { - res.push(rev) - } - } -}; - -// another - -/** - * @param {string} s - * @return {string[]} - */ -const removeInvalidParentheses = function(s) { - const ans = []; - remove(s, ans, 0, 0, ["(", ")"]); - return ans; -}; - -function remove(s, ans, last_i, last_j, par) { - for (let stack = 0, i = last_i; i < s.length; i++) { - if (s.charAt(i) === par[0]) stack++; - if (s.charAt(i) === par[1]) stack--; - if (stack >= 0) continue; - for (let j = last_j; j <= i; j++) { - if ( - s.charAt(j) === par[1] && - (j === last_j || s.charAt(j - 1) != par[1]) - ) { - remove(s.slice(0, j) + s.slice(j + 1), ans, i, j, par); - } - } - return; - } - const reversed = s - .split("") - .reverse() - .join(""); - if (par[0] === "(") { - remove(reversed, ans, 0, 0, [")", "("]); - } else { - ans.push(reversed); - } -} diff --git a/301.remove-invalid-parentheses.js b/301.remove-invalid-parentheses.js new file mode 100644 index 00000000..a68929bf --- /dev/null +++ b/301.remove-invalid-parentheses.js @@ -0,0 +1,32 @@ +/** + * @param {string} s + * @return {string[]} + */ +const removeInvalidParentheses = function(s) { + const res = [] + helper(s, 0, 0, ['(', ')']) + return res + + function helper(str, lastI, lastJ, pair) { + let openNum = 0, closeNum = 0 + for(let i = lastI; i < str.length; i++) { + if(str[i] === pair[0]) openNum++ + if(str[i] === pair[1]) closeNum++ + if(closeNum > openNum) { + for(let j = lastJ; j <= i; j++) { + if(str[j] === pair[1] && (j === lastJ || str[j - 1] !== pair[1])) { + helper(str.slice(0, j) + str.slice(j + 1), i, j, pair) + } + } + return + } + } + let rev = str.split('').reverse().join('') + if(pair[0] === '(') { + helper(rev, 0, 0, [')', '(']) + } else { + res.push(rev) + } + } +}; + diff --git a/302-smallest-rectangle-enclosing-black-pixels.js b/302-smallest-rectangle-enclosing-black-pixels.js deleted file mode 100644 index 7c085de5..00000000 --- a/302-smallest-rectangle-enclosing-black-pixels.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @param {character[][]} image - * @param {number} x - * @param {number} y - * @return {number} - */ -const minArea = function(image, x, y) { - const m = image.length, - n = image[0].length; - const left = searchColumns(0, y, 0, m, true); - const right = searchColumns(y + 1, n, 0, m, false); - const top = searchRows(0, x, left, right, true); - const bottom = searchRows(x + 1, m, left, right, false); - return (right - left) * (bottom - top); - function searchColumns(i, j, top, bottom, opt) { - while (i != j) { - let k = top, - mid = ((i + j) >> 1); - while (k < bottom && image[k][mid] === "0") ++k; - if (k < bottom === opt) j = mid; - else i = mid + 1; - } - return i; - } - function searchRows(i, j, left, right, opt) { - while (i != j) { - let k = left, - mid = ((i + j) >> 1); - while (k < right && image[mid][k] === "0") ++k; - if (k < right === opt) j = mid; - else i = mid + 1; - } - return i; - } -}; - -// another - -/** - * @param {character[][]} image - * @param {number} x - * @param {number} y - * @return {number} - */ -const minArea = function(image, x, y) { - let top = x, - bottom = x - let left = y, - right = y - function dfs(x, y) { - if ( - x < 0 || - y < 0 || - x >= image.length || - y >= image[0].length || - image[x][y] === '0' - ) - return - image[x][y] = '0' - top = Math.min(top, x) - bottom = Math.max(bottom, x) - left = Math.min(left, y) - right = Math.max(right, y) - dfs(x + 1, y) - dfs(x - 1, y) - dfs(x, y - 1) - dfs(x, y + 1) - } - - if (image.length === 0 || image[0].length === 0) return 0 - dfs(x, y) - return (right - left + 1) * (bottom - top + 1) -} - diff --git a/302.smallest-rectangle-enclosing-black-pixels.js b/302.smallest-rectangle-enclosing-black-pixels.js new file mode 100644 index 00000000..70c721a5 --- /dev/null +++ b/302.smallest-rectangle-enclosing-black-pixels.js @@ -0,0 +1,36 @@ +/** + * @param {character[][]} image + * @param {number} x + * @param {number} y + * @return {number} + */ +const minArea = function(image, x, y) { + const m = image.length, + n = image[0].length; + const left = searchColumns(0, y, 0, m, true); + const right = searchColumns(y + 1, n, 0, m, false); + const top = searchRows(0, x, left, right, true); + const bottom = searchRows(x + 1, m, left, right, false); + return (right - left) * (bottom - top); + function searchColumns(i, j, top, bottom, opt) { + while (i != j) { + let k = top, + mid = ((i + j) >> 1); + while (k < bottom && image[k][mid] === "0") ++k; + if (k < bottom === opt) j = mid; + else i = mid + 1; + } + return i; + } + function searchRows(i, j, left, right, opt) { + while (i != j) { + let k = left, + mid = ((i + j) >> 1); + while (k < right && image[mid][k] === "0") ++k; + if (k < right === opt) j = mid; + else i = mid + 1; + } + return i; + } +}; + diff --git a/304-range-sum-query-2d-immutable.js b/304-range-sum-query-2d-immutable.js deleted file mode 100644 index 8333a777..00000000 --- a/304-range-sum-query-2d-immutable.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @param {number[][]} matrix - */ -const NumMatrix = function(matrix) { - const dp = []; - if (matrix.length == 0 || matrix[0].length == 0) return; - for (let i = 0; i <= matrix.length; i++) { - let t = new Array(matrix[0].length + 1).fill(0); - dp.push(t); - } - - for (let i = 0; i < matrix.length; i++) { - for (let j = 0; j < matrix[0].length; j++) { - dp[i + 1][j + 1] = dp[i][j + 1] + dp[i + 1][j] + matrix[i][j] - dp[i][j]; - } - } - - this.cache = dp; -}; - -/** - * @param {number} row1 - * @param {number} col1 - * @param {number} row2 - * @param {number} col2 - * @return {number} - */ -NumMatrix.prototype.sumRegion = function(row1, col1, row2, col2) { - const dp = this.cache; - return ( - dp[row2 + 1][col2 + 1] - - dp[row1][col2 + 1] - - dp[row2 + 1][col1] + - dp[row1][col1] - ); -}; - -/** - * Your NumMatrix object will be instantiated and called as such: - * var obj = Object.create(NumMatrix).createNew(matrix) - * var param_1 = obj.sumRegion(row1,col1,row2,col2) - */ - -// another - -/** - * @param {number[][]} matrix - */ -const NumMatrix = function(matrix) { - const m = matrix.length, n = matrix[0].length - const dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)) - for(let i = 1; i <= m; i++) { - for(let j = 1; j <= n; j++) { - dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - dp[i - 1][j - 1] + matrix[i - 1][j - 1] - } - } - this.dp = dp -}; - -/** - * @param {number} row1 - * @param {number} col1 - * @param {number} row2 - * @param {number} col2 - * @return {number} - */ -NumMatrix.prototype.sumRegion = function(row1, col1, row2, col2) { - const dp = this.dp - return dp[row2 + 1][col2 + 1] - dp[row2 + 1][col1] - dp[row1][col2 + 1] + dp[row1][col1] -}; - -/** - * Your NumMatrix object will be instantiated and called as such: - * var obj = new NumMatrix(matrix) - * var param_1 = obj.sumRegion(row1,col1,row2,col2) - */ diff --git a/304.range-sum-query-2d-immutable.js b/304.range-sum-query-2d-immutable.js new file mode 100644 index 00000000..f4965686 --- /dev/null +++ b/304.range-sum-query-2d-immutable.js @@ -0,0 +1,43 @@ +/** + * @param {number[][]} matrix + */ +const NumMatrix = function(matrix) { + const dp = []; + if (matrix.length == 0 || matrix[0].length == 0) return; + for (let i = 0; i <= matrix.length; i++) { + let t = new Array(matrix[0].length + 1).fill(0); + dp.push(t); + } + + for (let i = 0; i < matrix.length; i++) { + for (let j = 0; j < matrix[0].length; j++) { + dp[i + 1][j + 1] = dp[i][j + 1] + dp[i + 1][j] + matrix[i][j] - dp[i][j]; + } + } + + this.cache = dp; +}; + +/** + * @param {number} row1 + * @param {number} col1 + * @param {number} row2 + * @param {number} col2 + * @return {number} + */ +NumMatrix.prototype.sumRegion = function(row1, col1, row2, col2) { + const dp = this.cache; + return ( + dp[row2 + 1][col2 + 1] - + dp[row1][col2 + 1] - + dp[row2 + 1][col1] + + dp[row1][col1] + ); +}; + +/** + * Your NumMatrix object will be instantiated and called as such: + * var obj = Object.create(NumMatrix).createNew(matrix) + * var param_1 = obj.sumRegion(row1,col1,row2,col2) + */ + diff --git a/305-number-of-islands-ii.js b/305.number-of-islands-ii.js similarity index 100% rename from 305-number-of-islands-ii.js rename to 305.number-of-islands-ii.js diff --git a/306-additive-number.js b/306.additive-number.js similarity index 100% rename from 306-additive-number.js rename to 306.additive-number.js diff --git a/307-range-sum-query-mutable.js b/307-range-sum-query-mutable.js deleted file mode 100644 index faff27c5..00000000 --- a/307-range-sum-query-mutable.js +++ /dev/null @@ -1,100 +0,0 @@ -const lowBit = (x) => x & -x -class FenwickTree { - constructor(n) { - if (n < 1) return - this.sum = Array(n + 1).fill(0) - } - update(i, delta) { - if (i < 1) return - while (i < this.sum.length) { - this.sum[i] += delta - i += lowBit(i) - } - } - query(i) { - if (i < 1) return 0 - let sum = 0 - while (i > 0) { - sum += this.sum[i] - i -= lowBit(i) - } - return sum - } -} - -/** - * @param {number[]} nums - */ -var NumArray = function(nums) { - this.nums = nums - const n = nums.length - this.bit = new FenwickTree(n) - for(let i = 1; i <= n; i++) { - this.bit.update(i, nums[i - 1]) - } -}; - -/** - * @param {number} index - * @param {number} val - * @return {void} - */ -NumArray.prototype.update = function(index, val) { - const delta = val - this.nums[index] - this.nums[index] = val - this.bit.update(index + 1, delta) -}; - -/** - * @param {number} left - * @param {number} right - * @return {number} - */ -NumArray.prototype.sumRange = function(left, right) { - return this.bit.query(right + 1) - this.bit.query(left) -}; - -/** - * Your NumArray object will be instantiated and called as such: - * var obj = new NumArray(nums) - * obj.update(index,val) - * var param_2 = obj.sumRange(left,right) - */ - -// another - -/** - * @param {number[]} nums - */ -const NumArray = function(nums) { - this.arr = nums -}; - -/** - * @param {number} i - * @param {number} val - * @return {void} - */ -NumArray.prototype.update = function(i, val) { - this.arr[i] = val -}; - -/** - * @param {number} i - * @param {number} j - * @return {number} - */ -NumArray.prototype.sumRange = function(i, j) { - let sum = 0; - for (let k = i; k <= j; k++) { - sum += this.arr[k]; - } - return sum; -}; - -/** - * Your NumArray object will be instantiated and called as such: - * var obj = Object.create(NumArray).createNew(nums) - * obj.update(i,val) - * var param_2 = obj.sumRange(i,j) - */ diff --git a/307.range-sum-query-mutable.js b/307.range-sum-query-mutable.js new file mode 100644 index 00000000..159c6869 --- /dev/null +++ b/307.range-sum-query-mutable.js @@ -0,0 +1,63 @@ +const lowBit = (x) => x & -x +class FenwickTree { + constructor(n) { + if (n < 1) return + this.sum = Array(n + 1).fill(0) + } + update(i, delta) { + if (i < 1) return + while (i < this.sum.length) { + this.sum[i] += delta + i += lowBit(i) + } + } + query(i) { + if (i < 1) return 0 + let sum = 0 + while (i > 0) { + sum += this.sum[i] + i -= lowBit(i) + } + return sum + } +} + +/** + * @param {number[]} nums + */ +var NumArray = function(nums) { + this.nums = nums + const n = nums.length + this.bit = new FenwickTree(n) + for(let i = 1; i <= n; i++) { + this.bit.update(i, nums[i - 1]) + } +}; + +/** + * @param {number} index + * @param {number} val + * @return {void} + */ +NumArray.prototype.update = function(index, val) { + const delta = val - this.nums[index] + this.nums[index] = val + this.bit.update(index + 1, delta) +}; + +/** + * @param {number} left + * @param {number} right + * @return {number} + */ +NumArray.prototype.sumRange = function(left, right) { + return this.bit.query(right + 1) - this.bit.query(left) +}; + +/** + * Your NumArray object will be instantiated and called as such: + * var obj = new NumArray(nums) + * obj.update(index,val) + * var param_2 = obj.sumRange(left,right) + */ + diff --git a/308-range-sum-query-2d-mutable.js b/308.range-sum-query-2d-mutable.js similarity index 100% rename from 308-range-sum-query-2d-mutable.js rename to 308.range-sum-query-2d-mutable.js diff --git a/309-best-time-to-buy-and-sell-stock-with-cooldown.js b/309-best-time-to-buy-and-sell-stock-with-cooldown.js deleted file mode 100755 index 0bc3138d..00000000 --- a/309-best-time-to-buy-and-sell-stock-with-cooldown.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {number[]} prices - * @return {number} - */ -const maxProfit = function(prices) { - if (prices === null || prices.length < 1) { - return 0; - } - - const length = prices.length; - // buy[i]: max profit if the first "i" days end with a "buy" day - const buy = Array(length + 1).fill(0); - // buy[i]: max profit if the first "i" days end with a "sell" day - const sell = Array(length + 1).fill(0); - - buy[1] = -prices[0]; - - for (let i = 2; i <= length; i++) { - const price = prices[i - 1]; - buy[i] = Math.max(buy[i - 1], sell[i - 2] - price); - sell[i] = Math.max(sell[i - 1], buy[i - 1] + price); - } - - // sell[length] >= buy[length] - return sell[length]; -}; diff --git a/309.best-time-to-buy-and-sell-stock-with-cooldown.js b/309.best-time-to-buy-and-sell-stock-with-cooldown.js new file mode 100644 index 00000000..e83471a1 --- /dev/null +++ b/309.best-time-to-buy-and-sell-stock-with-cooldown.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} prices + * @return {number} + */ +const maxProfit = function(prices) { + if (prices === null || prices.length < 1) { + return 0; + } + + const length = prices.length; + // buy[i]: max profit if the first "i" days end with a "buy" day + const buy = Array(length + 1).fill(0); + // buy[i]: max profit if the first "i" days end with a "sell" day + const sell = Array(length + 1).fill(0); + + buy[1] = -prices[0]; + + for (let i = 2; i <= length; i++) { + const price = prices[i - 1]; + buy[i] = Math.max(buy[i - 1], sell[i - 2] - price); + sell[i] = Math.max(sell[i - 1], buy[i - 1] + price); + } + + // sell[length] >= buy[length] + return sell[length]; +}; diff --git a/31-next-permutation.js b/31-next-permutation.js deleted file mode 100644 index 28de12d6..00000000 --- a/31-next-permutation.js +++ /dev/null @@ -1,116 +0,0 @@ -/** - * @param {number[]} nums - * @return {void} Do not return anything, modify nums in-place instead. - */ -const nextPermutation = function(nums) { - const n = nums.length - let k = null - for(let i = n - 2; i >= 0; i--) { - if(nums[i] < nums[i + 1]) { - k = i - break - } - } - if(k == null) { - reverse(nums, 0, n - 1) - } else { - let end - for(let i = n - 1; i >= 0; i--) { - if(nums[i] > nums[k]) { - end = i - break - } - } - swap(nums, k, end) - reverse(nums, k + 1, n - 1) - } - - function reverse(arr, start, end) { - while(start < end) { - swap(arr, start, end) - start++ - end-- - } - } - - function swap(arr, i, j) { - ;[arr[i], arr[j]] = [arr[j], arr[i]]; - } -}; - -// another - - -/** - * @param {number[]} nums - * @return {void} Do not return anything, modify nums in-place instead. - */ -const nextPermutation = function(nums) { - let i = nums.length - 2; - while (i >= 0 && nums[i + 1] <= nums[i]) { - i--; - } - if (i >= 0) { - let j = nums.length - 1; - while (j >= 0 && nums[j] <= nums[i]) { - j--; - } - swap(nums, i, j); - } - reverse(nums, i + 1); - -}; - -function reverse(nums, start) { - let i = start, j = nums.length - 1; - while (i < j) { - swap(nums, i, j); - i++; - j--; - } -} - -function swap(arr, i, j) { - arr[i] ^= arr[j]; - arr[j] ^= arr[i]; - arr[i] ^= arr[j]; -} - -// another - -/** - * @param {number[]} nums - * @return {void} Do not return anything, modify nums in-place instead. - */ -const nextPermutation = function(nums) { - const n = nums.length - let start, end - for(let i = n - 2; i >= 0; i--) { - if(nums[i] < nums[i + 1]) { - start = i - break - } - } - if(start == null) { - reverse(nums, 0, n - 1) - } else { - for(let i = n - 1; i >= 0; i--) { - if(nums[i] > nums[start]) { - end = i - break - } - } - swap(nums, start, end) - reverse(nums, start + 1, n - 1) - } -}; -function reverse(arr, start, end) { - while(start < end) { - swap(arr, start++, end--) - } -} -function swap(arr, i, j) { - const tmp = arr[i] - arr[i] = arr[j] - arr[j] = tmp -} diff --git a/31.next-permutation.js b/31.next-permutation.js new file mode 100644 index 00000000..0ff8148b --- /dev/null +++ b/31.next-permutation.js @@ -0,0 +1,40 @@ +/** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ +const nextPermutation = function(nums) { + const n = nums.length + let k = null + for(let i = n - 2; i >= 0; i--) { + if(nums[i] < nums[i + 1]) { + k = i + break + } + } + if(k == null) { + reverse(nums, 0, n - 1) + } else { + let end + for(let i = n - 1; i >= 0; i--) { + if(nums[i] > nums[k]) { + end = i + break + } + } + swap(nums, k, end) + reverse(nums, k + 1, n - 1) + } + + function reverse(arr, start, end) { + while(start < end) { + swap(arr, start, end) + start++ + end-- + } + } + + function swap(arr, i, j) { + ;[arr[i], arr[j]] = [arr[j], arr[i]]; + } +}; + diff --git a/310-minimum-height-trees.js b/310-minimum-height-trees.js deleted file mode 100644 index eeaa1111..00000000 --- a/310-minimum-height-trees.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} edges - * @return {number[]} - */ -const findMinHeightTrees = function (n, edges) { - const graph = {} - - for(const [u, v] of edges) { - if(graph[u] == null) graph[u] = new Set() - if(graph[v] == null) graph[v] = new Set() - graph[u].add(v) - graph[v].add(u) - } - - let q = [] - for(let i = 0; i < n; i++) { - if(graph[i].size === 1) q.push(i) - } - - while(n > 2) { - const size = q.length, nxt = [] - n -= size - for(let i = 0; i < size; i++) { - const cur = q[i] - for(const e of (graph[cur] || [])) { - graph[e].delete(cur) - if(graph[e].size === 1) nxt.push(e) - } - } - - q = nxt - } - - return q -} - -// another - -/** - * @param {number} n - * @param {number[][]} edges - * @return {number[]} - */ - const findMinHeightTrees = function(n, edges) { - if(n === 1) return [0] - const res = [], graph = {} - for(const [u, v] of edges) { - if(graph[u] == null) graph[u] = new Set() - if(graph[v] == null) graph[v] = new Set() - graph[u].add(v) - graph[v].add(u) - } - - let leaves = [] - Object.keys(graph).forEach(k => { - if(graph[k].size === 1) leaves.push(+k) - }) - while(n > 2) { - const newLeaves = [] - const size = leaves.length - for (let i = 0; i < size; i++) { - const cur = leaves.pop() - for (const next of graph[cur]) { - graph[next].delete(cur) - if(graph[next].size === 1) newLeaves.push(next) - } - } - n -= size - leaves = newLeaves - } - - return leaves -}; - -// another - -/** - * @param {number} n - * @param {number[][]} edges - * @return {number[]} - */ -const findMinHeightTrees = function(n, edges) { - if (n === 1) { - return [0]; - } - const adj = []; - for (let i = 0; i < n; i++) { - adj.push([]); - } - for (let edge of edges) { - adj[edge[0]].push(edge[1]); - adj[edge[1]].push(edge[0]); - } - let leaves = []; - for (let i = 0; i < n; i++) { - if (adj[i].length === 1) { - leaves.push(i); - } - } - - while (n > 2) { - n -= leaves.length; - let newLeaves = []; - for (let i of leaves) { - let j = adj[i].shift(); - let idx = adj[j].indexOf(i); - adj[j].splice(idx, 1); - if (adj[j].length === 1) newLeaves.push(j); - } - leaves = newLeaves; - } - - return leaves; -}; diff --git a/310.minimum-height-trees.js b/310.minimum-height-trees.js new file mode 100644 index 00000000..2a66528b --- /dev/null +++ b/310.minimum-height-trees.js @@ -0,0 +1,37 @@ +/** + * @param {number} n + * @param {number[][]} edges + * @return {number[]} + */ +const findMinHeightTrees = function (n, edges) { + const graph = {} + + for(const [u, v] of edges) { + if(graph[u] == null) graph[u] = new Set() + if(graph[v] == null) graph[v] = new Set() + graph[u].add(v) + graph[v].add(u) + } + + let q = [] + for(let i = 0; i < n; i++) { + if(graph[i].size === 1) q.push(i) + } + + while(n > 2) { + const size = q.length, nxt = [] + n -= size + for(let i = 0; i < size; i++) { + const cur = q[i] + for(const e of (graph[cur] || [])) { + graph[e].delete(cur) + if(graph[e].size === 1) nxt.push(e) + } + } + + q = nxt + } + + return q +} + diff --git a/311-sparse-matrix-multiplication.js b/311.sparse-matrix-multiplication.js similarity index 100% rename from 311-sparse-matrix-multiplication.js rename to 311.sparse-matrix-multiplication.js diff --git a/312-burst-balloons.js b/312-burst-balloons.js deleted file mode 100644 index a6cb9fa8..00000000 --- a/312-burst-balloons.js +++ /dev/null @@ -1,53 +0,0 @@ -function maxCoins(arr) { - const len = arr.length - const nums = Array(len + 2).fill(0); - let n = 1; - for (const x of arr) if (x > 0) nums[n++] = x; - nums[0] = nums[n++] = 1; - - const dp = Array.from({ length: n }, () => Array(n).fill(0)); - for (let k = 2; k < n; k++) { - for (let left = 0; left < n - k; left++) { - let right = left + k; - for (let i = left + 1; i < right; i++) { - dp[left][right] = Math.max( - dp[left][right], - nums[left] * nums[i] * nums[right] + dp[left][i] + dp[i][right], - ); - } - } - } - - return dp[0][n - 1]; -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxCoins = iNums => { - const nums = new Array(iNums.length + 2); - let n = 1; - for (let x of iNums) if (x > 0) nums[n++] = x; - nums[0] = nums[n++] = 1; - - const memo = Array.from({ length: n }, () => new Array(n)); - return burst(memo, nums, 0, n - 1); -}; - -function burst(memo, nums, left, right) { - if (left + 1 === right) return 0; - if (memo[left][right] > 0) return memo[left][right]; - let ans = 0; - for (let i = left + 1; i < right; ++i) - ans = Math.max( - ans, - nums[left] * nums[i] * nums[right] + - burst(memo, nums, left, i) + - burst(memo, nums, i, right) - ); - memo[left][right] = ans; - return ans; -} diff --git a/312.burst-balloons.js b/312.burst-balloons.js new file mode 100644 index 00000000..c75cc38d --- /dev/null +++ b/312.burst-balloons.js @@ -0,0 +1,23 @@ +function maxCoins(arr) { + const len = arr.length + const nums = Array(len + 2).fill(0); + let n = 1; + for (const x of arr) if (x > 0) nums[n++] = x; + nums[0] = nums[n++] = 1; + + const dp = Array.from({ length: n }, () => Array(n).fill(0)); + for (let k = 2; k < n; k++) { + for (let left = 0; left < n - k; left++) { + let right = left + k; + for (let i = left + 1; i < right; i++) { + dp[left][right] = Math.max( + dp[left][right], + nums[left] * nums[i] * nums[right] + dp[left][i] + dp[i][right], + ); + } + } + } + + return dp[0][n - 1]; +} + diff --git a/313-super-ugly-number.js b/313-super-ugly-number.js deleted file mode 100644 index 598944b8..00000000 --- a/313-super-ugly-number.js +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @param {number} n - * @param {number[]} primes - * @return {number} - */ -const nthSuperUglyNumber = function(n, primes) { - if (n === 1) return 1 - const indexes = new Array(primes.length).fill(0) - const arr = [1] - for (let i = 1; i <= n - 1; i++) { - arr[i] = +Infinity - for (let j = 0; j < primes.length; j++) { - arr[i] = Math.min(arr[i], arr[indexes[j]] * primes[j]) - } - for (let j = 0; j < primes.length; j++) { - if (arr[i] === arr[indexes[j]] * primes[j]) { - indexes[j]++ - } - } - } - return arr[n - 1] -} - -// another - -/** - * @param {number} n - * @param {number[]} primes - * @return {number} - */ -const nthSuperUglyNumber = function(n, primes) { - const ugly = Array(n).fill(0) - const pq = new PriorityQueue((a, b) => a[0] < b[0]) - - for(let i = 0; i < primes.length; i++) pq.push([primes[i], 1, primes[i]]) - ugly[0] = 1 - for(let i = 1; i < n; i++) { - ugly[i] = pq.peek()[0] - while(pq.peek()[0] === ugly[i]) { - const next = pq.pop() - pq.push([next[2] * ugly[next[1]], next[1] + 1, next[2]]) - } - } - - return ugly[n - 1] -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/313.super-ugly-number.js b/313.super-ugly-number.js new file mode 100644 index 00000000..d5746c03 --- /dev/null +++ b/313.super-ugly-number.js @@ -0,0 +1,23 @@ +/** + * @param {number} n + * @param {number[]} primes + * @return {number} + */ +const nthSuperUglyNumber = function(n, primes) { + if (n === 1) return 1 + const indexes = new Array(primes.length).fill(0) + const arr = [1] + for (let i = 1; i <= n - 1; i++) { + arr[i] = +Infinity + for (let j = 0; j < primes.length; j++) { + arr[i] = Math.min(arr[i], arr[indexes[j]] * primes[j]) + } + for (let j = 0; j < primes.length; j++) { + if (arr[i] === arr[indexes[j]] * primes[j]) { + indexes[j]++ + } + } + } + return arr[n - 1] +} + diff --git a/314-binary-tree-vertical-order-traversal.js b/314-binary-tree-vertical-order-traversal.js deleted file mode 100644 index 46123f5d..00000000 --- a/314-binary-tree-vertical-order-traversal.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - -Given a binary tree, return the vertical order traversal of its -nodes' values. (ie, from top to bottom, column by column). - -If two nodes are in the same row and column, the order -should be from left to right. - -Examples 1: - -Input: [3,9,20,null,null,15,7] - - 3 - /\ - / \ - 9 20 - /\ - / \ - 15 7 - -Output: - -[ - [9], - [3,15], - [20], - [7] -] - -Examples 2: - -Input: [3,9,8,4,0,1,7] - - 3 - /\ - / \ - 9 8 - /\ /\ - / \/ \ - 4 01 7 - -Output: - -[ - [4], - [9], - [3,0,1], - [8], - [7] -] - -Examples 3: - -Input: [3,9,8,4,0,1,7,null,null,null,2,5] (0's right child is 2 and 1's left child is 5) - - 3 - /\ - / \ - 9 8 - /\ /\ - / \/ \ - 4 01 7 - /\ - / \ - 5 2 - -Output: - -[ - [4], - [9,5], - [3,0,1], - [8,2], - [7] -] - -*/ - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number[][]} - */ -const verticalOrder = function(root) { - const res = [] - if(root == null) return res - const map = new Map() - const q = [] - const cols = [] - q.push(root) - cols.push(0) - let min = 0 - let max = 0 - while(q.length) { - const node = q.shift() - const col = cols.shift() - if(!map.has(col)) { - map.set(col, []) - } - map.get(col).push(node.val) - if(node.left !== null) { - q.push(node.left) - cols.push(col - 1) - min = Math.min(min, col - 1) - } - if(node.right !== null) { - q.push(node.right) - cols.push(col + 1) - max = Math.max(max, col + 1) - } - } - for(let i = min; i <= max; i++) { - res.push(map.get(i)) - } - return res -}; - -// another - -const verticalOrder = function(root) { - if (!root) return [] - let result = [] - function recurse(root, col, row) { - if (!root) return - recurse(root.left, col - 1, row + 1) - recurse(root.right, col + 1, row + 1) - result[col] = result[col] || [] - result[col][row] = result[col][row] || [] - result[col][row].push(root.val) - } - - recurse(root, 100, 0) - return result - .filter(x => x) - .map(row => row.reduce((acc, val) => acc.concat(val), [])) -} - - diff --git a/314.binary-tree-vertical-order-traversal.js b/314.binary-tree-vertical-order-traversal.js new file mode 100644 index 00000000..d8eceed1 --- /dev/null +++ b/314.binary-tree-vertical-order-traversal.js @@ -0,0 +1,123 @@ +/** + +Given a binary tree, return the vertical order traversal of its +nodes' values. (ie, from top to bottom, column by column). + +If two nodes are in the same row and column, the order +should be from left to right. + +Examples 1: + +Input: [3,9,20,null,null,15,7] + + 3 + /\ + / \ + 9 20 + /\ + / \ + 15 7 + +Output: + +[ + [9], + [3,15], + [20], + [7] +] + +Examples 2: + +Input: [3,9,8,4,0,1,7] + + 3 + /\ + / \ + 9 8 + /\ /\ + / \/ \ + 4 01 7 + +Output: + +[ + [4], + [9], + [3,0,1], + [8], + [7] +] + +Examples 3: + +Input: [3,9,8,4,0,1,7,null,null,null,2,5] (0's right child is 2 and 1's left child is 5) + + 3 + /\ + / \ + 9 8 + /\ /\ + / \/ \ + 4 01 7 + /\ + / \ + 5 2 + +Output: + +[ + [4], + [9,5], + [3,0,1], + [8,2], + [7] +] + +*/ + +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +const verticalOrder = function(root) { + const res = [] + if(root == null) return res + const map = new Map() + const q = [] + const cols = [] + q.push(root) + cols.push(0) + let min = 0 + let max = 0 + while(q.length) { + const node = q.shift() + const col = cols.shift() + if(!map.has(col)) { + map.set(col, []) + } + map.get(col).push(node.val) + if(node.left !== null) { + q.push(node.left) + cols.push(col - 1) + min = Math.min(min, col - 1) + } + if(node.right !== null) { + q.push(node.right) + cols.push(col + 1) + max = Math.max(max, col + 1) + } + } + for(let i = min; i <= max; i++) { + res.push(map.get(i)) + } + return res +}; + diff --git a/315-count-of-smaller-numbers-after-self.js b/315-count-of-smaller-numbers-after-self.js deleted file mode 100644 index 8bda9213..00000000 --- a/315-count-of-smaller-numbers-after-self.js +++ /dev/null @@ -1,137 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[]} - */ -const countSmaller = function(nums) { - const numsAndIndexes = nums.map((x, i) => [x, i]) - const output = [...new Array(nums.length)].map(_ => 0) - mergeSort(numsAndIndexes, output) - return output -} - -function mergeSort(arr, output) { - if (arr.length <= 1) return arr - const middle = Math.floor(arr.length / 2) - const left = mergeSort(arr.slice(0, middle), output), - right = mergeSort(arr.slice(middle), output) - const sorted = [] - let i = 0, - j = 0 - while (i < left.length || j < right.length) { - if (i >= left.length) { - sorted.push(right[j]) - j++ - } else if (j >= right.length) { - sorted.push(left[i]) - i++ - } else { - if (left[i][0] > right[j][0]) { - sorted.push(left[i]) - output[left[i][1]] += right.length - j - i++ - } else { - sorted.push(right[j]) - j++ - } - } - } - - return sorted -} - -// another - -class Node { - constructor(v, s) { - this.val = v - this.sum = s - this.left = null - this.right = null - this.dup = 1 - } -} -/** - * @param {number[]} nums - * @return {number[]} - */ -const countSmaller = function(nums) { - const ans = new Array(nums.length).fill(0) - let root = null - for (let i = nums.length - 1; i >= 0; i--) { - root = insert(nums[i], root, ans, i, 0) - } - return ans -} - -function insert(num, node, ans, i, preSum) { - if (node == null) { - node = new Node(num, 0) - ans[i] = preSum - } else if (node.val == num) { - node.dup++ - ans[i] = preSum + node.sum - } else if (node.val > num) { - node.sum++ - node.left = insert(num, node.left, ans, i, preSum) - } else { - node.right = insert(num, node.right, ans, i, preSum + node.dup + node.sum) - } - return node -} - -// another - -/** - * @param {number[]} nums - * @return {number[]} - */ -const countSmaller = function(nums) { - - const arr = [] - const n = nums.length - for(let i = 0; i < n; i++) { - arr.push([nums[i], i]) - } - - const res = Array(n).fill(0) - cntSmaller(arr, 0, n - 1, res) - - return res - - function cntSmaller(arr, l, r, res) { - if(l >= r) return - - const mid = ~~((l + r) / 2) - cntSmaller(arr, l, mid, res) - cntSmaller(arr, mid + 1, r, res) - let leftPos = l, rightPos = mid + 1, cnt = 0 - const merged = [] - while(leftPos < mid + 1 && rightPos <= r) { - if(arr[leftPos][0] > arr[rightPos][0]) { - cnt++ - merged.push(arr[rightPos]) - rightPos++ - } else { - res[arr[leftPos][1]] += cnt - merged.push(arr[leftPos]) - leftPos++ - } - } - - while(leftPos < mid + 1) { - res[arr[leftPos][1]] += cnt - merged.push(arr[leftPos]) - leftPos++ - } - - while(rightPos <= r) { - merged.push(arr[rightPos]) - rightPos++ - } - - for(let i = l; i <= r; i++) { - arr[i] = merged[i - l] - } - - } -}; diff --git a/315.count-of-smaller-numbers-after-self.js b/315.count-of-smaller-numbers-after-self.js new file mode 100644 index 00000000..aa17b72a --- /dev/null +++ b/315.count-of-smaller-numbers-after-self.js @@ -0,0 +1,41 @@ +/** + * @param {number[]} nums + * @return {number[]} + */ +const countSmaller = function(nums) { + const numsAndIndexes = nums.map((x, i) => [x, i]) + const output = [...new Array(nums.length)].map(_ => 0) + mergeSort(numsAndIndexes, output) + return output +} + +function mergeSort(arr, output) { + if (arr.length <= 1) return arr + const middle = Math.floor(arr.length / 2) + const left = mergeSort(arr.slice(0, middle), output), + right = mergeSort(arr.slice(middle), output) + const sorted = [] + let i = 0, + j = 0 + while (i < left.length || j < right.length) { + if (i >= left.length) { + sorted.push(right[j]) + j++ + } else if (j >= right.length) { + sorted.push(left[i]) + i++ + } else { + if (left[i][0] > right[j][0]) { + sorted.push(left[i]) + output[left[i][1]] += right.length - j + i++ + } else { + sorted.push(right[j]) + j++ + } + } + } + + return sorted +} + diff --git a/316-remove-duplicate-letters.js b/316-remove-duplicate-letters.js deleted file mode 100644 index a64a93b2..00000000 --- a/316-remove-duplicate-letters.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ -const removeDuplicateLetters = function(s) { - const last = {} - for (let i = 0; i < s.length; i++) last[s.charAt(i)] = i - const added = {} - const stack = [] - for (let i = 0; i < s.length; i++) { - const char = s.charAt(i) - if (added[char]) continue - while (stack.length && char < stack[0] && last[stack[0]] > i) { - added[stack[0]] = false - stack.shift() - } - stack.unshift(char) - added[char] = true - } - return stack.reverse().join('') -} - -// another - - -/** - * @param {string} s - * @return {string} - */ -const removeDuplicateLetters = function(s) { - const m = new Array(26) - const a = 'a'.charCodeAt(0) - for (let i = 0; i < s.length; i++) { - const k = s.charCodeAt(i) - a - m[k] = m[k] ? m[k] + 1 : 1 - } - const aChNo = [] - const visited = {} - for (let i = 0; i < s.length; i++) { - const k = s.charCodeAt(i) - a - m[k]-- - if (visited[k]) continue - while (aChNo.length > 0) { - const last = aChNo[aChNo.length - 1] - a - if (last > k && m[last] > 0) { - visited[last] = 0 - aChNo.pop() - } else break - } - visited[k] = 1 - aChNo.push(k + a) - } - return String.fromCharCode(...aChNo) -} - -// another - -/** - * @param {string} s - * @return {string} - */ -const removeDuplicateLetters = function(s) { - const last = {} - for (let i = 0; i < s.length; i++) last[s.charAt(i)] = i - const added = {} - const stack = [] - for (let i = 0; i < s.length; i++) { - const char = s.charAt(i) - if (added[char]) continue - while (stack.length && char < stack[stack.length - 1] && last[stack[stack.length - 1]] > i) { - added[stack[stack.length - 1]] = false - stack.pop() - } - stack.push(char) - added[char] = true - } - return stack.join('') -} diff --git a/316.remove-duplicate-letters.js b/316.remove-duplicate-letters.js new file mode 100644 index 00000000..76e6387a --- /dev/null +++ b/316.remove-duplicate-letters.js @@ -0,0 +1,22 @@ +/** + * @param {string} s + * @return {string} + */ +const removeDuplicateLetters = function(s) { + const last = {} + for (let i = 0; i < s.length; i++) last[s.charAt(i)] = i + const added = {} + const stack = [] + for (let i = 0; i < s.length; i++) { + const char = s.charAt(i) + if (added[char]) continue + while (stack.length && char < stack[0] && last[stack[0]] > i) { + added[stack[0]] = false + stack.shift() + } + stack.unshift(char) + added[char] = true + } + return stack.reverse().join('') +} + diff --git a/317-shortest-distance-from-all-buildings.js b/317.shortest-distance-from-all-buildings.js similarity index 100% rename from 317-shortest-distance-from-all-buildings.js rename to 317.shortest-distance-from-all-buildings.js diff --git a/318-maximum-product-of-word-lengths.js b/318-maximum-product-of-word-lengths.js deleted file mode 100755 index 7eb8b017..00000000 --- a/318-maximum-product-of-word-lengths.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {string[]} words - * @return {number} - */ -const maxProduct = function(words) { - if (words == null || words.length === 0) return 0; - let len = words.length; - let value = []; - for (let i = 0; i < len; i++) { - let tmp = words[i]; - value[i] = 0; - for (let j = 0; j < tmp.length; j++) { - value[i] |= 1 << (tmp.charAt(j).charCodeAt(0) - "a".charCodeAt(0)); - } - } - let maxProductNum = 0; - for (let i = 0; i < len; i++) - for (let j = i + 1; j < len; j++) { - if ( - (value[i] & value[j]) === 0 && - words[i].length * words[j].length > maxProductNum - ) - maxProductNum = words[i].length * words[j].length; - } - return maxProductNum; -}; diff --git a/318.maximum-product-of-word-lengths.js b/318.maximum-product-of-word-lengths.js new file mode 100644 index 00000000..f892c957 --- /dev/null +++ b/318.maximum-product-of-word-lengths.js @@ -0,0 +1,26 @@ +/** + * @param {string[]} words + * @return {number} + */ +const maxProduct = function(words) { + if (words == null || words.length === 0) return 0; + let len = words.length; + let value = []; + for (let i = 0; i < len; i++) { + let tmp = words[i]; + value[i] = 0; + for (let j = 0; j < tmp.length; j++) { + value[i] |= 1 << (tmp.charAt(j).charCodeAt(0) - "a".charCodeAt(0)); + } + } + let maxProductNum = 0; + for (let i = 0; i < len; i++) + for (let j = i + 1; j < len; j++) { + if ( + (value[i] & value[j]) === 0 && + words[i].length * words[j].length > maxProductNum + ) + maxProductNum = words[i].length * words[j].length; + } + return maxProductNum; +}; diff --git a/319-bulb-switcher.js b/319-bulb-switcher.js deleted file mode 100755 index ad48c1a5..00000000 --- a/319-bulb-switcher.js +++ /dev/null @@ -1,7 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const bulbSwitch = function(n) { - return Math.floor(Math.sqrt(n)); -}; diff --git a/319.bulb-switcher.js b/319.bulb-switcher.js new file mode 100644 index 00000000..d66cf4b2 --- /dev/null +++ b/319.bulb-switcher.js @@ -0,0 +1,7 @@ +/** + * @param {number} n + * @return {number} + */ +const bulbSwitch = function(n) { + return Math.floor(Math.sqrt(n)); +}; diff --git a/32-longest-valid-parentheses.js b/32-longest-valid-parentheses.js deleted file mode 100644 index cd69003d..00000000 --- a/32-longest-valid-parentheses.js +++ /dev/null @@ -1,77 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const longestValidParentheses = function(s) { - const arr = s.split("") - const dp = new Array(arr.length).fill(0) - let open = 0 - let max = 0 - for (let i = 0; i < arr.length; i++) { - if (arr[i] === "(") open++ - if (arr[i] === ")" && open > 0) { - dp[i] = 2 + dp[i - 1] - if (i - dp[i] > 0) dp[i] += dp[i - dp[i]] - open-- - } - if (dp[i] > max) max = dp[i] - } - return max -} - -// another - -const longestValidParentheses = function(s) { - let longest = 0 - let stack = [-1] - for (let i = 0; i < s.length; i++) { - if (s[i] === "(") { - stack.push(i) - } else { - stack.pop() - if (!stack.length) stack.push(i) - else longest = Math.max(longest, i - stack[stack.length - 1]) - } - } - - return longest -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const longestValidParentheses = function (s) { - let res = 0, - stk = [], - n = s.length, - idxStk = [] - for (let i = 0; i < n; i++) { - const ch = s[i] - if (stk.length && stk[stk.length - 1] === '(' && ch === ')') - stk.pop(), idxStk.pop() - else stk.push(ch), idxStk.push(i) - res = Math.max(res, i - (idxStk.length ? idxStk[idxStk.length - 1] : -1)) - } - return res -} -/** - * @param {string} s - * @return {number} - */ -const longestValidParentheses = function (s) { - let res = 0, - stk = [], - n = s.length, - idxStk = [] - for (let i = 0; i < n; i++) { - const ch = s[i] - if (stk.length && stk[stk.length - 1] === '(' && ch === ')') - stk.pop(), idxStk.pop() - else stk.push(ch), idxStk.push(i) - res = Math.max(res, i - (idxStk.length ? idxStk[idxStk.length - 1] : -1)) - } - return res -} diff --git a/32.longest-valid-parentheses.js b/32.longest-valid-parentheses.js new file mode 100644 index 00000000..21feb95f --- /dev/null +++ b/32.longest-valid-parentheses.js @@ -0,0 +1,21 @@ +/** + * @param {string} s + * @return {number} + */ +const longestValidParentheses = function(s) { + const arr = s.split("") + const dp = new Array(arr.length).fill(0) + let open = 0 + let max = 0 + for (let i = 0; i < arr.length; i++) { + if (arr[i] === "(") open++ + if (arr[i] === ")" && open > 0) { + dp[i] = 2 + dp[i - 1] + if (i - dp[i] > 0) dp[i] += dp[i - dp[i]] + open-- + } + if (dp[i] > max) max = dp[i] + } + return max +} + diff --git a/320-generalized-abbreviation.js b/320-generalized-abbreviation.js deleted file mode 100644 index b8fc1b48..00000000 --- a/320-generalized-abbreviation.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - -Write a function to generate the generalized abbreviations of a word. -Note: The order of the output does not matter. - -Example: - -Input: "word" -Output: -["word", "1ord", "w1rd", "wo1d", "wor1", "2rd", "w2d", "wo2", "1o1d", "1or1", "w1r1", "1o2", "2r1", "3d", "w3", "4"] - -*/ - -/** - * @param {string} word - * @return {string[]} - */ -const generateAbbreviations = function(word) { - const n = word.length - const limit = 1 << n - const res = [] - - for(let mask = 0; mask < limit; mask++) { - res.push(helper(word, mask)) - } - - return res - - function helper(word, mask) { - let res = '', zero = 0, idx = 0 - for(let i = 0; i < n; i++) { - if(mask & (1 << i)) { - if(zero) res += zero - res += word[i] - zero = 0 - } else { - zero++ - } - if(i === n - 1 && zero) res += zero - } - - return res - } -}; - -// another - -/** - * @param {string} word - * @return {string[]} - */ -const generateAbbreviations = function(word) { - const arr = [] - dfs(arr, word, 0, '', 0) - return arr -}; - -function dfs(res, word, pos, cur, cnt) { - if(pos === word.length) { - if(cnt > 0) cur += cnt - res.push(cur) - } else { - dfs(res, word, pos + 1, cur, cnt + 1) - dfs(res, word, pos + 1, cur + (cnt > 0 ? cnt : '') + word.charAt(pos), 0) - } -} diff --git a/320.generalized-abbreviation.js b/320.generalized-abbreviation.js new file mode 100644 index 00000000..441413b3 --- /dev/null +++ b/320.generalized-abbreviation.js @@ -0,0 +1,45 @@ +/** + +Write a function to generate the generalized abbreviations of a word. +Note: The order of the output does not matter. + +Example: + +Input: "word" +Output: +["word", "1ord", "w1rd", "wo1d", "wor1", "2rd", "w2d", "wo2", "1o1d", "1or1", "w1r1", "1o2", "2r1", "3d", "w3", "4"] + +*/ + +/** + * @param {string} word + * @return {string[]} + */ +const generateAbbreviations = function(word) { + const n = word.length + const limit = 1 << n + const res = [] + + for(let mask = 0; mask < limit; mask++) { + res.push(helper(word, mask)) + } + + return res + + function helper(word, mask) { + let res = '', zero = 0, idx = 0 + for(let i = 0; i < n; i++) { + if(mask & (1 << i)) { + if(zero) res += zero + res += word[i] + zero = 0 + } else { + zero++ + } + if(i === n - 1 && zero) res += zero + } + + return res + } +}; + diff --git a/321-create-maximum-number.js b/321.create-maximum-number.js similarity index 100% rename from 321-create-maximum-number.js rename to 321.create-maximum-number.js diff --git a/322-coin-change.js b/322-coin-change.js deleted file mode 100644 index 0c795775..00000000 --- a/322-coin-change.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @param {number[]} coins - * @param {number} amount - * @return {number} - */ -const coinChange = function(coins, amount) { - const dp = new Array(amount + 1).fill(amount + 1) - dp[0] = 0 - for (let i = 1; i <= amount; i++) { - for (let coin of coins) { - if (coin <= i) dp[i] = Math.min(dp[i], dp[i - coin] + 1) - } - } - return dp[amount] === amount + 1 ? -1 : dp[amount] -} - - -// another - -/** - * @param {number[]} coins - * @param {number} amount - * @return {number} - */ -const coinChange = function (coins, amount) { - const n = coins.length - const dp = Array.from({ length: n }, () => - Array(amount + 1).fill(Infinity) - ) - - for (let i = 0; i < n; i++) { - dp[i][0] = 0 - for (let j = 1; j <= amount; j++) { - if(i > 0) dp[i][j] = dp[i - 1][j] - if (j >= coins[i]) { - dp[i][j] = Math.min(dp[i][j], dp[i][j - coins[i]] + 1) - } - } - } - return dp[n - 1][amount] === Infinity ? -1 : dp[n - 1][amount] -} diff --git a/322.coin-change.js b/322.coin-change.js new file mode 100644 index 00000000..1a0b2a57 --- /dev/null +++ b/322.coin-change.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} coins + * @param {number} amount + * @return {number} + */ +const coinChange = function(coins, amount) { + const dp = new Array(amount + 1).fill(amount + 1) + dp[0] = 0 + for (let i = 1; i <= amount; i++) { + for (let coin of coins) { + if (coin <= i) dp[i] = Math.min(dp[i], dp[i - coin] + 1) + } + } + return dp[amount] === amount + 1 ? -1 : dp[amount] +} + + diff --git a/322-reconstruct-itinerary.js b/322.reconstruct-itinerary.js similarity index 100% rename from 322-reconstruct-itinerary.js rename to 322.reconstruct-itinerary.js diff --git a/323-number-of-connected-components-in-an-undirected-graph.js b/323.number-of-connected-components-in-an-undirected-graph.js similarity index 100% rename from 323-number-of-connected-components-in-an-undirected-graph.js rename to 323.number-of-connected-components-in-an-undirected-graph.js diff --git a/324-wiggle-sort-ii.js b/324.wiggle-sort-ii.js similarity index 100% rename from 324-wiggle-sort-ii.js rename to 324.wiggle-sort-ii.js diff --git a/325-maximum-size-subarray-sum-equals-k.js b/325.maximum-size-subarray-sum-equals-k.js similarity index 100% rename from 325-maximum-size-subarray-sum-equals-k.js rename to 325.maximum-size-subarray-sum-equals-k.js diff --git a/326-power-of-three.js b/326-power-of-three.js deleted file mode 100644 index 6657894b..00000000 --- a/326-power-of-three.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @param {number} n - * @return {boolean} - */ -const isPowerOfThree = function(n) { - const maxInt = Math.pow(3,30) - if(n < 0) { - return false - } - return maxInt % n === 0 -} - -// another - -const isPowerOfThree = function(n) { - if (n == 1) return true - if (n === 0) return false - if (n % 3 !== 0) return false - if (n == 3) return true - return isPowerOfThree(n / 3) -} - -// another - -const isPowerOfThree = function(n) { - if(n == null || n === 0) return false - let num = 1 - while(num < n) { - num *= 3 - } - return num > n ? false : true -} diff --git a/326.power-of-three.js b/326.power-of-three.js new file mode 100644 index 00000000..1ee6a9b3 --- /dev/null +++ b/326.power-of-three.js @@ -0,0 +1,12 @@ +/** + * @param {number} n + * @return {boolean} + */ +const isPowerOfThree = function(n) { + const maxInt = Math.pow(3,30) + if(n < 0) { + return false + } + return maxInt % n === 0 +} + diff --git a/327-count-of-range-sum.js b/327.count-of-range-sum.js similarity index 100% rename from 327-count-of-range-sum.js rename to 327.count-of-range-sum.js diff --git a/328-odd-even-linked-list.js b/328-odd-even-linked-list.js deleted file mode 100755 index 068e799b..00000000 --- a/328-odd-even-linked-list.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @return {ListNode} - */ -const oddEvenList = function(head) { - if (head === null) return null; - let odd = head, - even = head.next, - evenHead = even; - while (even !== null && even.next !== null) { - odd.next = even.next; - odd = odd.next; - even.next = odd.next; - even = even.next; - } - odd.next = evenHead; - return head; -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @return {ListNode} - */ -function oddEvenList(head) { - if(head == null) return head - const dummyOdd = new ListNode() - const dummyEven = new ListNode() - - dummyOdd.next = head - let odd = head, even = dummyEven - let idx = 2, cur = head.next - while(cur) { - if (idx % 2 === 1) { - odd.next = cur - odd = odd.next - } else { - even.next = cur - even = even.next - } - cur = cur.next - idx++ - } - odd.next = dummyEven.next - even.next = null - return dummyOdd.next -} diff --git a/328.odd-even-linked-list.js b/328.odd-even-linked-list.js new file mode 100644 index 00000000..454cd221 --- /dev/null +++ b/328.odd-even-linked-list.js @@ -0,0 +1,26 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ +const oddEvenList = function(head) { + if (head === null) return null; + let odd = head, + even = head.next, + evenHead = even; + while (even !== null && even.next !== null) { + odd.next = even.next; + odd = odd.next; + even.next = odd.next; + even = even.next; + } + odd.next = evenHead; + return head; +}; + diff --git a/329-longest-increasing-path-in-a-matrix.js b/329-longest-increasing-path-in-a-matrix.js deleted file mode 100644 index 6cce9611..00000000 --- a/329-longest-increasing-path-in-a-matrix.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @param {number[][]} matrix - * @return {number} - */ -const longestIncreasingPath = function(matrix) { - const m = matrix.length, n = matrix[0].length - let res = 1 - - const dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]] - const memo = Array.from({ length: m }, () => Array(n).fill(0)) - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - const len = dfs(i, j) - res = Math.max(res, len) - } - } - - return res - - function dfs(i, j) { - const v = matrix[i][j] - if(memo[i][j] !== 0) return memo[i][j] - let len = 1 - for(const [dx, dy] of dirs) { - const nx = i + dx, ny = j + dy - if(nx >= 0 && nx < m && ny >= 0 && ny < n && matrix[nx][ny] > v) { - const tmp = 1 + dfs(nx, ny) - len = Math.max(len, tmp) - } - } - - memo[i][j] = len - return len - } -}; - -// another - -/** - * @param {number[][]} matrix - * @return {number} - */ -const longestIncreasingPath = function (matrix) { - const dirs = [ - [-1, 0], - [1, 0], - [0, -1], - [0, 1], - ] - const m = matrix.length, - n = matrix[0].length - let res = 1 - const memo = Array.from({ length: m }, () => Array(n).fill(0)) - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - const tmp = dfs(matrix, i, j, m, n, memo, dirs) - res = Math.max(tmp, res) - } - } - return res -} - -function dfs(matrix, i, j, m, n, memo, dirs) { - if (memo[i][j] !== 0) return memo[i][j] - let res = 1 - for (let [dx, dy] of dirs) { - const nx = i + dx, - ny = j + dy - if ( - nx < 0 || - nx >= m || - ny < 0 || - ny >= n || - matrix[nx][ny] <= matrix[i][j] - ) - continue - const tmp = 1 + dfs(matrix, nx, ny, m, n, memo, dirs) - res = Math.max(res, tmp) - } - memo[i][j] = res - return res -} diff --git a/329.longest-increasing-path-in-a-matrix.js b/329.longest-increasing-path-in-a-matrix.js new file mode 100644 index 00000000..526e288c --- /dev/null +++ b/329.longest-increasing-path-in-a-matrix.js @@ -0,0 +1,36 @@ +/** + * @param {number[][]} matrix + * @return {number} + */ +const longestIncreasingPath = function(matrix) { + const m = matrix.length, n = matrix[0].length + let res = 1 + + const dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]] + const memo = Array.from({ length: m }, () => Array(n).fill(0)) + for(let i = 0; i < m; i++) { + for(let j = 0; j < n; j++) { + const len = dfs(i, j) + res = Math.max(res, len) + } + } + + return res + + function dfs(i, j) { + const v = matrix[i][j] + if(memo[i][j] !== 0) return memo[i][j] + let len = 1 + for(const [dx, dy] of dirs) { + const nx = i + dx, ny = j + dy + if(nx >= 0 && nx < m && ny >= 0 && ny < n && matrix[nx][ny] > v) { + const tmp = 1 + dfs(nx, ny) + len = Math.max(len, tmp) + } + } + + memo[i][j] = len + return len + } +}; + diff --git a/33-search-in-rotated-sorted-array.js b/33-search-in-rotated-sorted-array.js deleted file mode 100644 index 0d96552b..00000000 --- a/33-search-in-rotated-sorted-array.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} target - * @return {number} - */ -const search = function(nums, target) { - const len = nums.length - let r = false - let ridx = 0 - if(len === 0) return -1 - if(nums[0] === target) return 0 - for(let i = 1; i < len; i++) { - if(nums[i] === target) return i - if(nums[i] < nums[i - 1]) { - r = true - ridx = i - break - } - } - - if(r === true) { - for(let i = len - 1; i >= ridx; i--) { - if(nums[i] === target) return i - } - } - - return -1 -}; - -// another - -const search = function(nums, target) { - const len = nums.length - for(let i = 0; nums[i] <= target; i++){ - if(nums[i] === target){ - return i - } - } - for(let j = len - 1; nums[j] >= target; j--){ - if(nums[j] === target){ - return j - } - } - return -1 -}; - -// another -const search = function(nums, target) { - let low = 0 - let high = nums.length - 1 - while (low <= high) { - let mid = low + ((high - low) >> 1) - if (nums[mid] === target) return mid - - if (nums[low] <= nums[mid] ) { - if (target < nums[mid] && target >= nums[low]) { - high = mid - 1 - } else { - low = mid + 1 - } - } else { - if (target > nums[mid] && target <= nums[high]) { - low = mid + 1 - } else { - high = mid - 1 - } - } - - } - return -1 -}; diff --git a/33.search-in-rotated-sorted-array.js b/33.search-in-rotated-sorted-array.js new file mode 100644 index 00000000..9ba853dc --- /dev/null +++ b/33.search-in-rotated-sorted-array.js @@ -0,0 +1,29 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +const search = function(nums, target) { + const len = nums.length + let r = false + let ridx = 0 + if(len === 0) return -1 + if(nums[0] === target) return 0 + for(let i = 1; i < len; i++) { + if(nums[i] === target) return i + if(nums[i] < nums[i - 1]) { + r = true + ridx = i + break + } + } + + if(r === true) { + for(let i = len - 1; i >= ridx; i--) { + if(nums[i] === target) return i + } + } + + return -1 +}; + diff --git a/330-patching-array.js b/330.patching-array.js similarity index 100% rename from 330-patching-array.js rename to 330.patching-array.js diff --git a/331-verify-preorder-serialization-of-a-binary-tree.js b/331.verify-preorder-serialization-of-a-binary-tree.js similarity index 100% rename from 331-verify-preorder-serialization-of-a-binary-tree.js rename to 331.verify-preorder-serialization-of-a-binary-tree.js diff --git a/333-largest-bst-subtree.js b/333-largest-bst-subtree.js deleted file mode 100644 index f3655aae..00000000 --- a/333-largest-bst-subtree.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - -Given a binary tree, find the largest subtree -which is a Binary Search Tree (BST), -where largest means subtree with largest number of nodes in it. - -Note: -A subtree must include all of its descendants. - -Example: - -Input: [10,5,15,1,8,null,7] - - 10 - / \ - 5 15 - / \ \ -1 8 7 - -Output: 3 -Explanation: The Largest BST Subtree in this case is the highlighted one. - The return value is the subtree's size, which is 3. - -*/ - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const largestBSTSubtree = function(root) { - const res = helper(root) - return res[2] -} - -function helper(node) { - if (!node) return [Number.MAX_VALUE, -Number.MAX_VALUE, 0] - const left = helper(node.left) - const right = helper(node.right) - if (node.val > left[1] && node.val < right[0]) { - return [ - Math.min(node.val, left[0]), - Math.max(node.val, right[1]), - left[2] + right[2] + 1 - ] - } else { - return [-Number.MAX_VALUE, Number.MAX_VALUE, Math.max(left[2], right[2])] - } -} - -// another - -const largestBSTSubtree = function(root) { - function dfs(node) { - if (!node) return [0, 0, Number.MAX_VALUE, -Number.MAX_VALUE] - const [N1, n1, min1, max1] = dfs(node.left) - const [N2, n2, min2, max2] = dfs(node.right) - const n = - max1 < node.val && min2 > node.val ? n1 + 1 + n2 : -Number.MAX_VALUE - return [ - Math.max(N1, N2, n), - n, - Math.min(min1, node.val), - Math.max(max2, node.val) - ] - } - return dfs(root)[0] -} diff --git a/333.largest-bst-subtree.js b/333.largest-bst-subtree.js new file mode 100644 index 00000000..c7b1269a --- /dev/null +++ b/333.largest-bst-subtree.js @@ -0,0 +1,56 @@ +/** + +Given a binary tree, find the largest subtree +which is a Binary Search Tree (BST), +where largest means subtree with largest number of nodes in it. + +Note: +A subtree must include all of its descendants. + +Example: + +Input: [10,5,15,1,8,null,7] + + 10 + / \ + 5 15 + / \ \ +1 8 7 + +Output: 3 +Explanation: The Largest BST Subtree in this case is the highlighted one. + The return value is the subtree's size, which is 3. + +*/ + +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +const largestBSTSubtree = function(root) { + const res = helper(root) + return res[2] +} + +function helper(node) { + if (!node) return [Number.MAX_VALUE, -Number.MAX_VALUE, 0] + const left = helper(node.left) + const right = helper(node.right) + if (node.val > left[1] && node.val < right[0]) { + return [ + Math.min(node.val, left[0]), + Math.max(node.val, right[1]), + left[2] + right[2] + 1 + ] + } else { + return [-Number.MAX_VALUE, Number.MAX_VALUE, Math.max(left[2], right[2])] + } +} + diff --git a/334-increasing-triplet-subsequence.js b/334-increasing-triplet-subsequence.js deleted file mode 100644 index d8b22cc0..00000000 --- a/334-increasing-triplet-subsequence.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @param {number[]} nums - * @return {boolean} - */ -const increasingTriplet = function(nums) { - // start with two largest values, as soon as we find a number bigger than both, while both have been updated, return true. - let small = Number.MAX_VALUE, big = Number.MAX_VALUE; - for (let n of nums) { - if (n <= small) { small = n; } // update small if n is smaller than both - else if (n <= big) { big = n; } // update big only if greater than small but smaller than big - else return true; // return if you find a number bigger than both - } - return false; -}; - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -const increasingTriplet = function(nums) { - const n = nums.length, stk = [] - for(let e of nums) { - let l = 0, r = stk.length - while(l < r) { - const mid = l + Math.floor((r - l) / 2) - if (e > stk[mid]) l = mid + 1 - else r = mid - } - - stk[l] = e - if(stk.length > 2) return true - } - - return false -}; - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -const increasingTriplet = function(nums) { - let small = Number.MAX_VALUE, big = Number.MAX_VALUE - - for(const e of nums) { - if(e <= small) small = e - else if(e <= big) big = e - else return true - } - - return false -}; - diff --git a/334.increasing-triplet-subsequence.js b/334.increasing-triplet-subsequence.js new file mode 100644 index 00000000..f21bf4fc --- /dev/null +++ b/334.increasing-triplet-subsequence.js @@ -0,0 +1,15 @@ +/** + * @param {number[]} nums + * @return {boolean} + */ +const increasingTriplet = function(nums) { + // start with two largest values, as soon as we find a number bigger than both, while both have been updated, return true. + let small = Number.MAX_VALUE, big = Number.MAX_VALUE; + for (let n of nums) { + if (n <= small) { small = n; } // update small if n is smaller than both + else if (n <= big) { big = n; } // update big only if greater than small but smaller than big + else return true; // return if you find a number bigger than both + } + return false; +}; + diff --git a/335-self-crossing.js b/335.self-crossing.js similarity index 100% rename from 335-self-crossing.js rename to 335.self-crossing.js diff --git a/336-palindrome-pairs.js b/336-palindrome-pairs.js deleted file mode 100644 index e640f6d1..00000000 --- a/336-palindrome-pairs.js +++ /dev/null @@ -1,128 +0,0 @@ -/** - -Given a list of unique words, find all pairs of distinct indices (i, j) in the given list, -so that the concatenation of the two words, i.e. words[i] + words[j] is a palindrome. - -Example 1: - -Input: ["abcd","dcba","lls","s","sssll"] -Output: [[0,1],[1,0],[3,2],[2,4]] -Explanation: The palindromes are ["dcbaabcd","abcddcba","slls","llssssll"] -Example 2: - -Input: ["bat","tab","cat"] -Output: [[0,1],[1,0]] -Explanation: The palindromes are ["battab","tabbat"] - -*/ - -/** - * @param {string[]} words - * @return {number[][]} - */ -const palindromePairs = function(words) { - const root = new Trie(); - const pairs = []; - words.forEach((word, index) => addWord(word, index, root)); - words.forEach((word, index) => searchWord(word, index, root, pairs)); - return pairs; -}; - -const addWord = (word, wordIndex, root) => { - const length = word.length; - let curr = root; - for (let i = length - 1; i >= 0; i--) { - let char = word.charAt(i); - if (!curr.children[char]) curr.children[char] = new Trie(); - if (isPalindrome(0, i, word)) curr.words.push(wordIndex); - curr = curr.children[char]; - } - curr.wordIndex = wordIndex; - curr.words.push(wordIndex); -} - -const searchWord = (word, wordIndex, root, pairs) => { - const length = word.length; - let curr = root; - for (let i = 0; i < length; i++) { - let char = word.charAt(i); - if (curr.wordIndex >= 0 && curr.wordIndex !== wordIndex && isPalindrome(i, length - 1, word)) { - pairs.push([wordIndex, curr.wordIndex]); - } - curr = curr.children[char]; - if (!curr) return; - } - - curr.words.forEach((suffix) => { - if (suffix !== wordIndex) pairs.push([wordIndex, suffix]); - }) -} - -const isPalindrome = (left, right, word) => { - while (left < right) { - if (word.charAt(left++) !== word.charAt(right--)) return false; - } - return true; -} - -class Trie { - constructor() { - this.wordIndex = -1; - this.children = {}; - this.words = []; - } -} - -// another - -const reverseStr = s => { - let str = '' - for (let i = 0; i < s.length; i++) { - str = s[i] + str - } - return str -} -const isPalindrome = str => { - for (let i = 0; i < str.length / 2; i++) { - if (str[i] !== str[str.length - 1 - i]) return false - } - return true -} -/** - * @param {string[]} words - * @return {number[][]} - */ -const palindromePairs = function(words) { - const map = new Map() - words.forEach((word, idx) => map.set(word, idx)) - const result = [] - if (map.has('')) { - const idx = map.get('') - words.forEach((word, i) => { - if (i !== idx && isPalindrome(word)) { - result.push([idx, map.get(word)]) - result.push([map.get(word), idx]) - } - }) - } - map.delete('') - words.forEach((word, idx) => { - for (let i = 0; i < word.length; i++) { - const left = word.slice(0, i) - const right = word.slice(i) - if (isPalindrome(left)) { - const reversedRight = reverseStr(right) - if (map.has(reversedRight) && map.get(reversedRight) !== idx) { - result.push([map.get(reversedRight), idx]) - } - } - if (isPalindrome(right)) { - const reversedLeft = reverseStr(left) - if (map.has(reversedLeft) && map.get(reversedLeft) !== idx) { - result.push([idx, map.get(reversedLeft)]) - } - } - } - }) - return result -} diff --git a/336.palindrome-pairs.js b/336.palindrome-pairs.js new file mode 100644 index 00000000..4e4d1ebc --- /dev/null +++ b/336.palindrome-pairs.js @@ -0,0 +1,75 @@ +/** + +Given a list of unique words, find all pairs of distinct indices (i, j) in the given list, +so that the concatenation of the two words, i.e. words[i] + words[j] is a palindrome. + +Example 1: + +Input: ["abcd","dcba","lls","s","sssll"] +Output: [[0,1],[1,0],[3,2],[2,4]] +Explanation: The palindromes are ["dcbaabcd","abcddcba","slls","llssssll"] +Example 2: + +Input: ["bat","tab","cat"] +Output: [[0,1],[1,0]] +Explanation: The palindromes are ["battab","tabbat"] + +*/ + +/** + * @param {string[]} words + * @return {number[][]} + */ +const palindromePairs = function(words) { + const root = new Trie(); + const pairs = []; + words.forEach((word, index) => addWord(word, index, root)); + words.forEach((word, index) => searchWord(word, index, root, pairs)); + return pairs; +}; + +const addWord = (word, wordIndex, root) => { + const length = word.length; + let curr = root; + for (let i = length - 1; i >= 0; i--) { + let char = word.charAt(i); + if (!curr.children[char]) curr.children[char] = new Trie(); + if (isPalindrome(0, i, word)) curr.words.push(wordIndex); + curr = curr.children[char]; + } + curr.wordIndex = wordIndex; + curr.words.push(wordIndex); +} + +const searchWord = (word, wordIndex, root, pairs) => { + const length = word.length; + let curr = root; + for (let i = 0; i < length; i++) { + let char = word.charAt(i); + if (curr.wordIndex >= 0 && curr.wordIndex !== wordIndex && isPalindrome(i, length - 1, word)) { + pairs.push([wordIndex, curr.wordIndex]); + } + curr = curr.children[char]; + if (!curr) return; + } + + curr.words.forEach((suffix) => { + if (suffix !== wordIndex) pairs.push([wordIndex, suffix]); + }) +} + +const isPalindrome = (left, right, word) => { + while (left < right) { + if (word.charAt(left++) !== word.charAt(right--)) return false; + } + return true; +} + +class Trie { + constructor() { + this.wordIndex = -1; + this.children = {}; + this.words = []; + } +} + diff --git a/337-house-robber-iii.js b/337.house-robber-iii.js similarity index 100% rename from 337-house-robber-iii.js rename to 337.house-robber-iii.js diff --git a/338-counting-bits.js b/338.counting-bits.js similarity index 100% rename from 338-counting-bits.js rename to 338.counting-bits.js diff --git a/339-nested-list-weight-sum.js b/339-nested-list-weight-sum.js deleted file mode 100644 index d38d5c9f..00000000 --- a/339-nested-list-weight-sum.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * // This is the interface that allows for creating nested lists. - * // You should not implement it, or speculate about its implementation - * function NestedInteger() { - * - * Return true if this NestedInteger holds a single integer, rather than a nested list. - * @return {boolean} - * this.isInteger = function() { - * ... - * }; - * - * Return the single integer that this NestedInteger holds, if it holds a single integer - * Return null if this NestedInteger holds a nested list - * @return {integer} - * this.getInteger = function() { - * ... - * }; - * - * Set this NestedInteger to hold a single integer equal to value. - * @return {void} - * this.setInteger = function(value) { - * ... - * }; - * - * Set this NestedInteger to hold a nested list and adds a nested integer elem to it. - * @return {void} - * this.add = function(elem) { - * ... - * }; - * - * Return the nested list that this NestedInteger holds, if it holds a nested list - * Return null if this NestedInteger holds a single integer - * @return {NestedInteger[]} - * this.getList = function() { - * ... - * }; - * }; - */ -/** - * @param {NestedInteger[]} nestedList - * @return {number} - */ -const depthSum = function(nestedList) { - return h(nestedList, 1) -}; - -function h(arr, level) { - if(arr == null || arr.length === 0) return 0 - let sum = 0 - for(let i = 0, len = arr.length; i < len; i++) { - if(arr[i].isInteger()) sum += arr[i].getInteger() * level - else { - sum += h(arr[i].getList(), level + 1) - } - } - return sum -} - -// another - -const depthSum = function(nestedList) { - if(nestedList == null) return 0 - let sum = 0 - let level = 1 - const q = [...nestedList] - while(q.length) { - const len = q.length - for(let i = 0; i < len; i++) { - const el = q.shift() - if(el.isInteger()) sum += el.getInteger() * level - else q.push(...(el.getList())) - } - level++ - } - return sum -}; diff --git a/339.nested-list-weight-sum.js b/339.nested-list-weight-sum.js new file mode 100644 index 00000000..d8e6b30a --- /dev/null +++ b/339.nested-list-weight-sum.js @@ -0,0 +1,58 @@ +/** + * // This is the interface that allows for creating nested lists. + * // You should not implement it, or speculate about its implementation + * function NestedInteger() { + * + * Return true if this NestedInteger holds a single integer, rather than a nested list. + * @return {boolean} + * this.isInteger = function() { + * ... + * }; + * + * Return the single integer that this NestedInteger holds, if it holds a single integer + * Return null if this NestedInteger holds a nested list + * @return {integer} + * this.getInteger = function() { + * ... + * }; + * + * Set this NestedInteger to hold a single integer equal to value. + * @return {void} + * this.setInteger = function(value) { + * ... + * }; + * + * Set this NestedInteger to hold a nested list and adds a nested integer elem to it. + * @return {void} + * this.add = function(elem) { + * ... + * }; + * + * Return the nested list that this NestedInteger holds, if it holds a nested list + * Return null if this NestedInteger holds a single integer + * @return {NestedInteger[]} + * this.getList = function() { + * ... + * }; + * }; + */ +/** + * @param {NestedInteger[]} nestedList + * @return {number} + */ +const depthSum = function(nestedList) { + return h(nestedList, 1) +}; + +function h(arr, level) { + if(arr == null || arr.length === 0) return 0 + let sum = 0 + for(let i = 0, len = arr.length; i < len; i++) { + if(arr[i].isInteger()) sum += arr[i].getInteger() * level + else { + sum += h(arr[i].getList(), level + 1) + } + } + return sum +} + diff --git a/34-find-first-and-last-position-of-element-in-sorted-array.js b/34.find-first-and-last-position-of-element-in-sorted-array.js similarity index 100% rename from 34-find-first-and-last-position-of-element-in-sorted-array.js rename to 34.find-first-and-last-position-of-element-in-sorted-array.js diff --git a/340-longest-substring-with-at-most-k-distinct-characters.js b/340.longest-substring-with-at-most-k-distinct-characters.js similarity index 100% rename from 340-longest-substring-with-at-most-k-distinct-characters.js rename to 340.longest-substring-with-at-most-k-distinct-characters.js diff --git a/341-flatten-nested-list-iterator.js b/341.flatten-nested-list-iterator.js similarity index 100% rename from 341-flatten-nested-list-iterator.js rename to 341.flatten-nested-list-iterator.js diff --git a/342-power-of-four.js b/342.power-of-four.js similarity index 100% rename from 342-power-of-four.js rename to 342.power-of-four.js diff --git a/343-integer-break.js b/343-integer-break.js deleted file mode 100755 index 22446b08..00000000 --- a/343-integer-break.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const integerBreak = function(n) { - const dp = Array(n + 1).fill(0) - dp[2] = 1 - for(let i = 3; i <= n; i++) { - for(let j = 1; j < i; j++) { - dp[i] = Math.max(dp[i], j * Math.max(i - j, dp[i - j])) - } - } - return dp[n] -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const integerBreak = function(n) { - if (n <= 2) return 1; - - const maxArr = []; - for (let i = 0; i < n + 1; i++) { - maxArr[i] = 0; - } - - /** For a number i: write i as a sum of integers, then take the product of those integers. - maxArr[i] = maximum of all the possible products */ - - maxArr[1] = 0; - maxArr[2] = 1; // 2=1+1 so maxArr[2] = 1*1 - - for (let i = 3; i <= n; i++) { - for (let j = 1; j < i; j++) { - /** Try to write i as: i = j + S where S=i-j corresponds to either one number or a sum of two or more numbers - - Assuming that j+S corresponds to the optimal solution for maxArr[i], we have two cases: - (1) i is the sum of two numbers, i.e. S=i-j is one number, and so maxArr[i]=j*(i-j) - (2) i is the sum of at least three numbers, i.e. S=i-j is a sum of at least 2 numbers, - and so the product of the numbers in this sum for S is maxArr[i-j] - (=maximum product after breaking up i-j into a sum of at least two integers): - maxArr[i] = j*maxArr[i-j] - */ - maxArr[i] = Math.max(maxArr[i], j * (i - j), j * maxArr[i - j]); - } - } - return maxArr[n]; -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const integerBreak = function(n) { - if(n === 2) return 1 - if(n === 3) return 2 - let num = ~~(n / 3) - let rem = n % 3 - if(rem === 1) { - rem += 3 - num-- - } - return rem === 0 ? Math.pow(3, num) : Math.pow(3, num) * rem -}; - -/** - -If an optimal product contains a factor f >= 4, -then you can replace it with factors 2 and f-2 without losing optimality, -as 2*(f-2) = 2f-4 >= f. So you never need a factor greater than or equal to 4, -meaning you only need factors 1, 2 and 3 (and 1 is of course wasteful and you'd only use it for n=2 and n=3, where it's needed). - -For the rest I agree, 3*3 is simply better than 2*2*2, so you'd never use 2 more than twice. - -*/ diff --git a/343.integer-break.js b/343.integer-break.js new file mode 100644 index 00000000..a9f7ab3c --- /dev/null +++ b/343.integer-break.js @@ -0,0 +1,15 @@ +/** + * @param {number} n + * @return {number} + */ +const integerBreak = function(n) { + const dp = Array(n + 1).fill(0) + dp[2] = 1 + for(let i = 3; i <= n; i++) { + for(let j = 1; j < i; j++) { + dp[i] = Math.max(dp[i], j * Math.max(i - j, dp[i - j])) + } + } + return dp[n] +}; + diff --git a/344-reverse-string.js b/344-reverse-string.js deleted file mode 100644 index 155ddcac..00000000 --- a/344-reverse-string.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @param {character[]} s - * @return {void} Do not return anything, modify s in-place instead. - */ -const reverseString = function(s) { - s.reverse() -}; - -// another - -/** - * @param {character[]} s - * @return {void} Do not return anything, modify s in-place instead. - */ -const reverseString = function(s) { - for(let i = 0; i < s.length / 2; i++){ - [ s[i] , s[s.length - 1 - i] ] = [ s[s.length - 1 - i] , s[i] ]; - } -}; diff --git a/344.reverse-string.js b/344.reverse-string.js new file mode 100644 index 00000000..bbee0caf --- /dev/null +++ b/344.reverse-string.js @@ -0,0 +1,8 @@ +/** + * @param {character[]} s + * @return {void} Do not return anything, modify s in-place instead. + */ +const reverseString = function(s) { + s.reverse() +}; + diff --git a/345-reverse-vowels-of-a-string.js b/345-reverse-vowels-of-a-string.js deleted file mode 100644 index f0702f84..00000000 --- a/345-reverse-vowels-of-a-string.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ -const reverseVowels = function(s) { - if(s == null || s === '') return '' - const arr = s.split('') - let p = 0 - const len = s.length - let e = s.length - 1 - const v = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'] - while(p < e) { - while(v.indexOf(arr[p]) === -1 && p < e) p++ - while(v.indexOf(arr[e]) === -1 && p < e) e-- - const tmp = arr[p] - arr[p] = arr[e] - arr[e] = tmp - p++ - e-- - } - return arr.join('') -}; - - -// another - -const reverseVowels = function(s) { - let vowels = s.match(/[aeiou]/gi) - let k = 0 - if (vowels) { - vowels = vowels.reverse`` - } else { - return s - } - return s.replace(/[aeiou]/gi, () => vowels[k++]) -} diff --git a/345.reverse-vowels-of-a-string.js b/345.reverse-vowels-of-a-string.js new file mode 100644 index 00000000..9ffdc9ab --- /dev/null +++ b/345.reverse-vowels-of-a-string.js @@ -0,0 +1,24 @@ +/** + * @param {string} s + * @return {string} + */ +const reverseVowels = function(s) { + if(s == null || s === '') return '' + const arr = s.split('') + let p = 0 + const len = s.length + let e = s.length - 1 + const v = ['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'] + while(p < e) { + while(v.indexOf(arr[p]) === -1 && p < e) p++ + while(v.indexOf(arr[e]) === -1 && p < e) e-- + const tmp = arr[p] + arr[p] = arr[e] + arr[e] = tmp + p++ + e-- + } + return arr.join('') +}; + + diff --git a/346-moving-average-from-data-stream.js b/346.moving-average-from-data-stream.js similarity index 100% rename from 346-moving-average-from-data-stream.js rename to 346.moving-average-from-data-stream.js diff --git a/347-top-k-frequent-elements.js b/347-top-k-frequent-elements.js deleted file mode 100755 index 5a59bc3f..00000000 --- a/347-top-k-frequent-elements.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number[]} - */ -const topKFrequent = function(nums, k) { - const hash = {} - for(let i = 0; i < nums.length; i++) { - if(hash.hasOwnProperty(nums[i])) hash[nums[i]]++ - else hash[nums[i]] = 1 - } - const res = new Array() - const keys = Object.keys(hash) - - const bucket = new Array(nums.length) - - for(let k of keys) { - let freq = hash[k] - if(bucket[freq] == null) { - bucket[freq] = [] - } - bucket[freq].push(k) - } - - for(let i = bucket.length - 1; i >= 0 && res.length < k; i--) { - if(bucket[i] != null) { - res.push(...bucket[i]) - } - } - - return res -}; - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number[]} - */ -const topKFrequent = function(nums, k) { - const hash = {} - for(let n of nums) { - if(hash[n] == null) hash[n] = 0 - hash[n]++ - } - const entries = Object.entries(hash) - let min = Infinity, max = -Infinity - const reverse = {} - for(let [k, freq] of entries) { - if(freq < min) min = freq - if(freq > max) max = freq - if(reverse[freq] == null) reverse[freq] = [] - reverse[freq].push(k) - } - const n = max - min + 1 - const arr = Array(n) - let res = [] - let limit = max - while(limit) { - if(reverse[limit]) res.push(...reverse[limit]) - limit-- - if(res.length >= k) break - } - res.splice(k) - return res -}; - -// another - - -/** - * @param {number[]} nums - * @param {number} k - * @return {number[]} - */ - const topKFrequent = function(nums, k) { - const n = nums.length - const freq = Array(n + 1).fill(null) - const hash = {} - for(let e of nums) { - if(hash[e] == null) hash[e] = 0 - hash[e]++ - } - for(let k in hash) { - if(hash.hasOwnProperty(k)) { - const v = hash[k] - if(freq[v] == null) freq[v] = [] - freq[v].push(k) - } - } - const res = [] - for(let i = n; i >= 0; i--) { - if(freq[i] != null) res.push(...freq[i]) - if(res.length >= k) break - } - if(res.length > k) res.splice(k) - return res -}; diff --git a/347.top-k-frequent-elements.js b/347.top-k-frequent-elements.js new file mode 100644 index 00000000..23a83308 --- /dev/null +++ b/347.top-k-frequent-elements.js @@ -0,0 +1,33 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number[]} + */ +const topKFrequent = function(nums, k) { + const hash = {} + for(let i = 0; i < nums.length; i++) { + if(hash.hasOwnProperty(nums[i])) hash[nums[i]]++ + else hash[nums[i]] = 1 + } + const res = new Array() + const keys = Object.keys(hash) + + const bucket = new Array(nums.length) + + for(let k of keys) { + let freq = hash[k] + if(bucket[freq] == null) { + bucket[freq] = [] + } + bucket[freq].push(k) + } + + for(let i = bucket.length - 1; i >= 0 && res.length < k; i--) { + if(bucket[i] != null) { + res.push(...bucket[i]) + } + } + + return res +}; + diff --git a/348-design-tic-tac-toe.js b/348.design-tic-tac-toe.js similarity index 100% rename from 348-design-tic-tac-toe.js rename to 348.design-tic-tac-toe.js diff --git a/349-intersection-of-two-arrays.js b/349-intersection-of-two-arrays.js deleted file mode 100755 index 6838bdb7..00000000 --- a/349-intersection-of-two-arrays.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number[]} - */ - -const intersection = function(nums1, nums2) { - const obj = {}; - nums1.forEach(i => (obj[i] = true)); - - return nums2.filter(j => { - if (obj[j]) { - delete obj[j]; - return true; - } - return false; - }); -}; diff --git a/349.intersection-of-two-arrays.js b/349.intersection-of-two-arrays.js new file mode 100644 index 00000000..ca91e462 --- /dev/null +++ b/349.intersection-of-two-arrays.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number[]} + */ + +const intersection = function(nums1, nums2) { + const obj = {}; + nums1.forEach(i => (obj[i] = true)); + + return nums2.filter(j => { + if (obj[j]) { + delete obj[j]; + return true; + } + return false; + }); +}; diff --git a/35-search-insert-position.js b/35-search-insert-position.js deleted file mode 100755 index 7bd01758..00000000 --- a/35-search-insert-position.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} target - * @return {number} - */ -const searchInsert = function(nums, target) { - for (let i = 0; i < nums.length; i++) { - if (nums[i] >= target) { - return i; - } else { - if (i === nums.length - 1) { - return i + 1; - } - } - } -}; - -// another - -/** - * @param {number[]} nums - * @param {number} target - * @return {number} - */ -const searchInsert = function(nums, target) { - const n = nums.length - let l = 0, r = n - 1 - while(l <= r) { - const mid = l + ((r - l) >> 1) - if(nums[mid] === target) return mid - if(nums[mid] > target) r = mid - 1 - else l = mid + 1 - } - return l -}; diff --git a/35.search-insert-position.js b/35.search-insert-position.js new file mode 100644 index 00000000..d4c63df3 --- /dev/null +++ b/35.search-insert-position.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +const searchInsert = function(nums, target) { + for (let i = 0; i < nums.length; i++) { + if (nums[i] >= target) { + return i; + } else { + if (i === nums.length - 1) { + return i + 1; + } + } + } +}; + diff --git a/350-intersection-of-two-arrays-ii.js b/350.intersection-of-two-arrays-ii.js similarity index 100% rename from 350-intersection-of-two-arrays-ii.js rename to 350.intersection-of-two-arrays-ii.js diff --git a/351-android-unlock-patterns.js b/351-android-unlock-patterns.js deleted file mode 100644 index e8fc35eb..00000000 --- a/351-android-unlock-patterns.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @param {number} m - * @param {number} n - * @return {number} - */ -const numberOfPatterns = function(m, n) { - // Skip array represents number to skip between two pairs - const skip = Array.from({ length: 10 }, () => new Array(10).fill(0)) - skip[1][3] = skip[3][1] = 2 - skip[1][7] = skip[7][1] = 4 - skip[3][9] = skip[9][3] = 6 - skip[7][9] = skip[9][7] = 8 - skip[1][9] = skip[9][1] = skip[2][8] = skip[8][2] = skip[3][7] = skip[7][3] = skip[4][6] = skip[6][4] = 5 - const vis = new Array(10).fill(false) - let rst = 0 - // DFS search each length from m to n - for (let i = m; i <= n; ++i) { - rst += DFS(vis, skip, 1, i - 1) * 4 // 1, 3, 7, 9 are symmetric - rst += DFS(vis, skip, 2, i - 1) * 4 // 2, 4, 6, 8 are symmetric - rst += DFS(vis, skip, 5, i - 1) // 5 - } - return rst -} - -// cur: the current position -// remain: the steps remaining -function DFS(vis, skip, cur, remain) { - if (remain < 0) return 0 - if (remain === 0) return 1 - vis[cur] = true - let rst = 0 - for (let i = 1; i <= 9; ++i) { - // If vis[i] is not visited and (two numbers are adjacent or skip number is already visited) - if (!vis[i] && (skip[cur][i] === 0 || vis[skip[cur][i]])) { - rst += DFS(vis, skip, i, remain - 1) - } - } - vis[cur] = false - return rst -} - -// another - -/** - * @param {number} m - * @param {number} n - * @return {number} - */ -const numberOfPatterns = function (m, n) { - const skip = Array.from({ length: 10 }, () => Array(10).fill(0)) - let res = 0 - skip[1][3] = skip[3][1] = 2 - skip[1][7] = skip[7][1] = 4 - skip[9][7] = skip[7][9] = 8 - skip[9][3] = skip[3][9] = 6 - skip[1][9] = skip[9][1] = skip[2][8] = skip[8][2] = skip[3][7] = skip[7][3] = skip[4][6] = skip[6][4] = 5 - const visited = new Set() - for(let i = m ;i <= n; i++) { - res += dfs(1, i - 1) * 4 // 1, 3, 7, 9 - res += dfs(2, i - 1) * 4 // 2, 4, 6, 8 - res += dfs(5, i - 1) // 5 - } - - return res - - function dfs(cur, remain) { - if(remain === 0) return 1 - let res = 0 - visited.add(cur) - for(let i = 1; i <= 9; i++) { - if(!visited.has(i) && (skip[cur][i] === 0 || visited.has(skip[cur][i]))) { - res += dfs(i, remain - 1) - } - } - visited.delete(cur) - - return res - } -} - diff --git a/351.android-unlock-patterns.js b/351.android-unlock-patterns.js new file mode 100644 index 00000000..0c01e926 --- /dev/null +++ b/351.android-unlock-patterns.js @@ -0,0 +1,41 @@ +/** + * @param {number} m + * @param {number} n + * @return {number} + */ +const numberOfPatterns = function(m, n) { + // Skip array represents number to skip between two pairs + const skip = Array.from({ length: 10 }, () => new Array(10).fill(0)) + skip[1][3] = skip[3][1] = 2 + skip[1][7] = skip[7][1] = 4 + skip[3][9] = skip[9][3] = 6 + skip[7][9] = skip[9][7] = 8 + skip[1][9] = skip[9][1] = skip[2][8] = skip[8][2] = skip[3][7] = skip[7][3] = skip[4][6] = skip[6][4] = 5 + const vis = new Array(10).fill(false) + let rst = 0 + // DFS search each length from m to n + for (let i = m; i <= n; ++i) { + rst += DFS(vis, skip, 1, i - 1) * 4 // 1, 3, 7, 9 are symmetric + rst += DFS(vis, skip, 2, i - 1) * 4 // 2, 4, 6, 8 are symmetric + rst += DFS(vis, skip, 5, i - 1) // 5 + } + return rst +} + +// cur: the current position +// remain: the steps remaining +function DFS(vis, skip, cur, remain) { + if (remain < 0) return 0 + if (remain === 0) return 1 + vis[cur] = true + let rst = 0 + for (let i = 1; i <= 9; ++i) { + // If vis[i] is not visited and (two numbers are adjacent or skip number is already visited) + if (!vis[i] && (skip[cur][i] === 0 || vis[skip[cur][i]])) { + rst += DFS(vis, skip, i, remain - 1) + } + } + vis[cur] = false + return rst +} + diff --git a/352-data-stream-as-disjoint-intervals.js b/352.data-stream-as-disjoint-intervals.js similarity index 100% rename from 352-data-stream-as-disjoint-intervals.js rename to 352.data-stream-as-disjoint-intervals.js diff --git a/353-design-snake-game.js b/353.design-snake-game.js similarity index 100% rename from 353-design-snake-game.js rename to 353.design-snake-game.js diff --git a/354-russian-doll-envelopes.js b/354-russian-doll-envelopes.js deleted file mode 100644 index efdd4fa9..00000000 --- a/354-russian-doll-envelopes.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @param {number[][]} envelopes - * @return {number} - */ -const maxEnvelopes = function(envelopes) { - const env = envelopes - env.sort((a, b) => a[0] - b[0] || b[1] - a[1]) - const stk = [] - for(const e of env) { - if(stk.length === 0 || e[1] > stk[stk.length - 1][1]) { - stk.push(e) - continue - } - let l = 0, r = stk.length - 1 - while(l < r) { - const mid = l + Math.floor((r - l) / 2) - if(stk[mid][1] < e[1]) l = mid + 1 - else r = mid - } - - stk[l] = e - } - - return stk.length -}; - -// another - - -/** - * @param {number[][]} envelopes - * @return {number} - */ -const maxEnvelopes = function(envelopes) { - envelopes.sort((a, b) => { - if (a[0] == b[0]) { - return b[1] - a[1] - } else { - return a[0] - b[0] - } - }) - const n = envelopes.length - const dp = [] - for (let i = 0; i < n; i++) { - let l = 0, - r = dp.length, - t = envelopes[i][1] - while (l < r) { - let m = l + ~~((r - l) / 2) - if (dp[m] < t) l = m + 1 - else r = m - } - if (r >= dp.length) dp.push(t) - else dp[r] = t - } - return dp.length -} - -// another - -/** - * @param {number[][]} envelopes - * @return {number} - */ -const maxEnvelopes = function(envelopes) { - envelopes.sort((a, b) => a[0] === b[0] ? b[1] - a[1] : a[0] - b[0]) - const stack = [] - for(let e of envelopes) { - if(stack.length === 0 || e[1] > stack[stack.length - 1][1]) { - stack.push(e) - continue - } - let l = 0, r = stack.length - 1 - while(l < r) { - const mid = ~~((l+r)/2) - if(stack[mid][1] < e[1]) { - l = mid + 1 - } else r = mid - } - stack[l] = e - } - return stack.length -}; diff --git a/354.russian-doll-envelopes.js b/354.russian-doll-envelopes.js new file mode 100644 index 00000000..e119e9d3 --- /dev/null +++ b/354.russian-doll-envelopes.js @@ -0,0 +1,26 @@ +/** + * @param {number[][]} envelopes + * @return {number} + */ +const maxEnvelopes = function(envelopes) { + const env = envelopes + env.sort((a, b) => a[0] - b[0] || b[1] - a[1]) + const stk = [] + for(const e of env) { + if(stk.length === 0 || e[1] > stk[stk.length - 1][1]) { + stk.push(e) + continue + } + let l = 0, r = stk.length - 1 + while(l < r) { + const mid = l + Math.floor((r - l) / 2) + if(stk[mid][1] < e[1]) l = mid + 1 + else r = mid + } + + stk[l] = e + } + + return stk.length +}; + diff --git a/355-design-twitter.js b/355.design-twitter.js similarity index 100% rename from 355-design-twitter.js rename to 355.design-twitter.js diff --git a/356-line-reflection.js b/356.line-reflection.js similarity index 100% rename from 356-line-reflection.js rename to 356.line-reflection.js diff --git a/357-count-numbers-with-unique-digits.js b/357-count-numbers-with-unique-digits.js deleted file mode 100755 index 03018011..00000000 --- a/357-count-numbers-with-unique-digits.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const countNumbersWithUniqueDigits = function(n) { - if(n === 0) return 1 - let res = 10 - let uniqueDigits = 9, avail = 9 - while(n > 1 && avail) { - uniqueDigits = uniqueDigits * avail - res += uniqueDigits - avail-- - n-- - } - - return res -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const countNumbersWithUniqueDigits = function(n) { - if (n === 0) return 1; - let res = 10; - let tmp = 9; - let remainDigitNum = 9; - while (n - 1 > 0 && remainDigitNum > 0) { - tmp = tmp * remainDigitNum; - res += tmp; - n -= 1; - remainDigitNum -= 1; - } - - return res; -}; - - -// another - -/** - * @param {number} n - * @return {number} - */ -const countNumbersWithUniqueDigits = function(n) { - const limit = 10 ** n - let res = 1 - let m = 1 - if(n === 0) return 1 - while(10**m <= limit) { - res += 9 * helper(9, m - 1) - m++ - } - - return res - - function helper(m, n) { - return n === 0 ? 1 : helper(m, n - 1) * (m - n + 1) - } -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const countNumbersWithUniqueDigits = function(n) { - if(n === 0) return 1 - let res = 10 - let tmp = 9, digits = 9 - while(n > 1 && digits > 0) { - tmp *= digits - res += tmp - n-- - digits-- - } - - return res -}; diff --git a/357.count-numbers-with-unique-digits.js b/357.count-numbers-with-unique-digits.js new file mode 100644 index 00000000..4e2a9576 --- /dev/null +++ b/357.count-numbers-with-unique-digits.js @@ -0,0 +1,18 @@ +/** + * @param {number} n + * @return {number} + */ +const countNumbersWithUniqueDigits = function(n) { + if(n === 0) return 1 + let res = 10 + let uniqueDigits = 9, avail = 9 + while(n > 1 && avail) { + uniqueDigits = uniqueDigits * avail + res += uniqueDigits + avail-- + n-- + } + + return res +}; + diff --git a/358-rearrange-string-k-distance-apart.js b/358-rearrange-string-k-distance-apart.js deleted file mode 100644 index 825883f5..00000000 --- a/358-rearrange-string-k-distance-apart.js +++ /dev/null @@ -1,167 +0,0 @@ -/** - -Given a non-empty string s and an integer k, -rearrange the string such that the same characters are at least distance k from each other. - -All input strings are given in lowercase letters. -If it is not possible to rearrange the string, return an empty string "". - -Example 1: - -Input: s = "aabbcc", k = 3 -Output: "abcabc" -Explanation: The same letters are at least distance 3 from each other. -Example 2: - -Input: s = "aaabc", k = 3 -Output: "" -Explanation: It is not possible to rearrange the string. -Example 3: - -Input: s = "aaadbbcc", k = 2 -Output: "abacabcd" -Explanation: The same letters are at least distance 2 from each other. - -*/ - -/** - * @param {string} s - * @param {number} k - * @return {string} - */ -const rearrangeString = function(s, k) { - if(k > 26) return '' - const length = s.length - const count = new Array(26).fill(0) - const valid = new Array(26).fill(0) - const a = 'a'.charCodeAt(0) - for (let i = 0; i < length; i++) { - count[s.charCodeAt(i) - a]++ - } - let sb = '' - for (let index = 0; index < length; index++) { - let candidatePos = findValidMax(count, valid, index) - if (candidatePos == -1) return '' - count[candidatePos]-- - valid[candidatePos] = index + k - sb += String.fromCharCode(a + candidatePos) - } - return sb -} - -function findValidMax(count, valid, index) { - let max = Number.MIN_VALUE - let candidatePos = -1 - for (let i = 0; i < count.length; i++) { - if (count[i] > 0 && count[i] > max && index >= valid[i]) { - max = count[i] - candidatePos = i - } - } - return candidatePos -} - -// another - -/** - * @param {string} s - * @param {number} k - * @return {string} - */ -const rearrangeString = function(s, k) { - const freq = Array(26).fill(0) - const a = 'a'.charCodeAt(0) - for(const e of s) { - freq[e.charCodeAt(0) - a]++ - } - const pq = new PriorityQueue((a, b) => a[1] > b[1]) - for(let i = 0; i < 26; i++) { - if(freq[i]) pq.push([i, freq[i]]) - } - let res = '' - - // console.log(pq) - const q = [] - while(!pq.isEmpty()) { - const cur = pq.pop() - cur[1]-- - res += String.fromCharCode(a + cur[0]) - q.push(cur) - if(q.length >= k) { - const p = q.shift() - if(p[1] > 0) pq.push(p) - } - } - // console.log(res) - return res.length === s.length ? res : '' -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - - diff --git a/358.rearrange-string-k-distance-apart.js b/358.rearrange-string-k-distance-apart.js new file mode 100644 index 00000000..f0f22313 --- /dev/null +++ b/358.rearrange-string-k-distance-apart.js @@ -0,0 +1,63 @@ +/** + +Given a non-empty string s and an integer k, +rearrange the string such that the same characters are at least distance k from each other. + +All input strings are given in lowercase letters. +If it is not possible to rearrange the string, return an empty string "". + +Example 1: + +Input: s = "aabbcc", k = 3 +Output: "abcabc" +Explanation: The same letters are at least distance 3 from each other. +Example 2: + +Input: s = "aaabc", k = 3 +Output: "" +Explanation: It is not possible to rearrange the string. +Example 3: + +Input: s = "aaadbbcc", k = 2 +Output: "abacabcd" +Explanation: The same letters are at least distance 2 from each other. + +*/ + +/** + * @param {string} s + * @param {number} k + * @return {string} + */ +const rearrangeString = function(s, k) { + if(k > 26) return '' + const length = s.length + const count = new Array(26).fill(0) + const valid = new Array(26).fill(0) + const a = 'a'.charCodeAt(0) + for (let i = 0; i < length; i++) { + count[s.charCodeAt(i) - a]++ + } + let sb = '' + for (let index = 0; index < length; index++) { + let candidatePos = findValidMax(count, valid, index) + if (candidatePos == -1) return '' + count[candidatePos]-- + valid[candidatePos] = index + k + sb += String.fromCharCode(a + candidatePos) + } + return sb +} + +function findValidMax(count, valid, index) { + let max = Number.MIN_VALUE + let candidatePos = -1 + for (let i = 0; i < count.length; i++) { + if (count[i] > 0 && count[i] > max && index >= valid[i]) { + max = count[i] + candidatePos = i + } + } + return candidatePos +} + diff --git a/359-logger-rate-limiter.js b/359.logger-rate-limiter.js similarity index 100% rename from 359-logger-rate-limiter.js rename to 359.logger-rate-limiter.js diff --git a/36-valid-sudoku.js b/36-valid-sudoku.js deleted file mode 100644 index d99b0bfe..00000000 --- a/36-valid-sudoku.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @param {character[][]} board - * @return {boolean} - */ -const isValidSudoku = function(board) { - const n = 9 - const m = 3 - const row = [], - col = [], - block = [] - for (let i = 0; i < n; i++) { - row[i] = new Set() - col[i] = new Set() - block[i] = new Set() - } - for (let r = 0; r < n; r++) { - for (let c = 0; c < n; c++) { - const ch = board[r][c] - if (ch === '.') continue - const b = Math.floor(r / m) * m + Math.floor(c / m) - if (row[r].has(ch) || col[c].has(ch) || block[b].has(ch)) return false - row[r].add(ch) - col[c].add(ch) - block[b].add(ch) - } - } - return true -} - -// another - -/** - * @param {character[][]} board - * @return {boolean} - */ -const isValidSudoku = function(board) { - let seen = new Set() - for (let i = 0; i < 9; ++i) { - for (let j = 0; j < 9; ++j) { - let number = board[i][j] - if (number != '.') - if ( - !hset(seen, number + ' in row ' + i) || - !hset(seen, number + ' in column ' + j) || - !hset(seen, number + ' in block ' + ~~(i / 3) + '-' + ~~(j / 3)) - ) - return false - } - } - return true -} -function hset(s, val) { - if (s.has(val)) return false - else { - s.add(val) - return true - } -} diff --git a/36.valid-sudoku.js b/36.valid-sudoku.js new file mode 100644 index 00000000..cfddc13d --- /dev/null +++ b/36.valid-sudoku.js @@ -0,0 +1,29 @@ +/** + * @param {character[][]} board + * @return {boolean} + */ +const isValidSudoku = function(board) { + const n = 9 + const m = 3 + const row = [], + col = [], + block = [] + for (let i = 0; i < n; i++) { + row[i] = new Set() + col[i] = new Set() + block[i] = new Set() + } + for (let r = 0; r < n; r++) { + for (let c = 0; c < n; c++) { + const ch = board[r][c] + if (ch === '.') continue + const b = Math.floor(r / m) * m + Math.floor(c / m) + if (row[r].has(ch) || col[c].has(ch) || block[b].has(ch)) return false + row[r].add(ch) + col[c].add(ch) + block[b].add(ch) + } + } + return true +} + diff --git a/360-sort-transformed-array.js b/360-sort-transformed-array.js deleted file mode 100644 index 2caedcd0..00000000 --- a/360-sort-transformed-array.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - -Given a sorted array of integers nums and integer values a, b and c. -Apply a quadratic function of the form f(x) = ax2 + bx + c to each element x in the array. - -The returned array must be in sorted order. - -Expected time complexity: O(n) - -Example 1: - -Input: nums = [-4,-2,2,4], a = 1, b = 3, c = 5 -Output: [3,9,15,33] -Example 2: - -Input: nums = [-4,-2,2,4], a = -1, b = 3, c = 5 -Output: [-23,-5,1,7] - -*/ - -/** - * @param {number[]} nums - * @param {number} a - * @param {number} b - * @param {number} c - * @return {number[]} - */ -const sortTransformedArray = function(nums, a, b, c) { - const n = nums.length - const sorted = new Array(n) - let i = 0, - j = n - 1 - let index = a >= 0 ? n - 1 : 0 - while (i <= j) { - if (a >= 0) { - sorted[index--] = - quad(nums[i], a, b, c) >= quad(nums[j], a, b, c) - ? quad(nums[i++], a, b, c) - : quad(nums[j--], a, b, c) - } else { - sorted[index++] = - quad(nums[i], a, b, c) >= quad(nums[j], a, b, c) - ? quad(nums[j--], a, b, c) - : quad(nums[i++], a, b, c) - } - } - return sorted -} - -function quad(x, a, b, c) { - return a * x * x + b * x +c -} - -// another - -/** - * @param {number[]} nums - * @param {number} a - * @param {number} b - * @param {number} c - * @return {number[]} - */ -const sortTransformedArray = function(nums, a, b, c) { - const ret = [] - const sum = v => a * v * v + b * v + c - if (a > 0) { - const point = (b / a / 2) * -1 - let i = 0, - j = nums.length - while (i < j) { - let ax = nums[i] - if (Math.abs(nums[i] - point) - Math.abs(nums[j - 1] - point) > 0) { - ++i - } else { - ax = nums[--j] - } - ret.unshift(sum(ax)) - } - return ret - } else if (a < 0) { - const point = (b / a / 2) * -1 - let i = 0, - j = nums.length - while (i < j) { - let ax = nums[i] - if (Math.abs(ax - point) - Math.abs(nums[j - 1] - point) > 0) { - ++i - } else { - ax = nums[--j] - } - ret.push(sum(ax)) - } - return ret - } else { - if (b > 0) { - return nums.map(v => sum(v)) - } else { - nums.forEach(v => { - ret.unshift(sum(v)) - }) - return ret - } - } -} - diff --git a/360.sort-transformed-array.js b/360.sort-transformed-array.js new file mode 100644 index 00000000..88aef459 --- /dev/null +++ b/360.sort-transformed-array.js @@ -0,0 +1,53 @@ +/** + +Given a sorted array of integers nums and integer values a, b and c. +Apply a quadratic function of the form f(x) = ax2 + bx + c to each element x in the array. + +The returned array must be in sorted order. + +Expected time complexity: O(n) + +Example 1: + +Input: nums = [-4,-2,2,4], a = 1, b = 3, c = 5 +Output: [3,9,15,33] +Example 2: + +Input: nums = [-4,-2,2,4], a = -1, b = 3, c = 5 +Output: [-23,-5,1,7] + +*/ + +/** + * @param {number[]} nums + * @param {number} a + * @param {number} b + * @param {number} c + * @return {number[]} + */ +const sortTransformedArray = function(nums, a, b, c) { + const n = nums.length + const sorted = new Array(n) + let i = 0, + j = n - 1 + let index = a >= 0 ? n - 1 : 0 + while (i <= j) { + if (a >= 0) { + sorted[index--] = + quad(nums[i], a, b, c) >= quad(nums[j], a, b, c) + ? quad(nums[i++], a, b, c) + : quad(nums[j--], a, b, c) + } else { + sorted[index++] = + quad(nums[i], a, b, c) >= quad(nums[j], a, b, c) + ? quad(nums[j--], a, b, c) + : quad(nums[i++], a, b, c) + } + } + return sorted +} + +function quad(x, a, b, c) { + return a * x * x + b * x +c +} + diff --git a/361-bomb-enemy.js b/361-bomb-enemy.js deleted file mode 100644 index dd401e0a..00000000 --- a/361-bomb-enemy.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - -Given a 2D grid, each cell is either a wall 'W', -an enemy 'E' or empty '0' (the number zero), -return the maximum enemies you can kill using one bomb. -The bomb kills all the enemies in the same row and column -from the planted point until it hits the wall since the wall -is too strong to be destroyed. - -Note: You can only put the bomb at an empty cell. - -Example: - -Input: [["0","E","0","0"],["E","0","W","E"],["0","E","0","0"]] -Output: 3 -Explanation: For the given grid, - -0 E 0 0 -E 0 W E -0 E 0 0 - -Placing a bomb at (1,1) kills 3 enemies. - -*/ - -/** - * @param {character[][]} grid - * @return {number} - */ -const maxKilledEnemies = function(grid) { - const m = grid.length - const n = m !== 0 ? grid[0].length : 0 - let result = 0 - let rowhits = 0 - const colhits = new Array(n).fill(0) - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - if (j === 0 || grid[i][j - 1] === 'W') { - rowhits = 0 - for (let k = j; k < n && grid[i][k] !== 'W'; k++) - rowhits += grid[i][k] === 'E' ? 1 : 0 - } - if (i === 0 || grid[i - 1][j] === 'W') { - colhits[j] = 0 - for (let k = i; k < m && grid[k][j] !== 'W'; k++) - colhits[j] += grid[k][j] === 'E' ? 1 : 0 - } - if (grid[i][j] === '0') result = Math.max(result, rowhits + colhits[j]) - } - } - return result -} - -// another - -/** - * @param {character[][]} grid - * @return {number} - */ -const maxKilledEnemies = function(grid) { - if (grid == null || grid.length === 0 || grid[0].length === 0) return 0 - const rows = grid.length - const cols = grid[0].length - let max = 0 - const dp = Array.from({ length: rows }, () => new Array(cols).fill(0)) - //travel each column twice: from left and from right - for (let i = 0; i < rows; i++) { - let cnt = 0 - for (let k = 0; k < cols; k++) { - if (grid[i][k] === '0') { - dp[i][k] = cnt - } else if (grid[i][k] === 'E') { - cnt++ - } else { - cnt = 0 - } - } - cnt = 0 - for (let k = cols - 1; k >= 0; k--) { - if (grid[i][k] === '0') { - dp[i][k] += cnt - } else if (grid[i][k] === 'E') { - cnt++ - } else { - cnt = 0 - } - } - } - //travel each row twice: from top and from bottom - for (let i = 0; i < cols; i++) { - let cnt = 0 - for (let k = 0; k < rows; k++) { - if (grid[k][i] === '0') { - dp[k][i] += cnt - } else if (grid[k][i] === 'E') { - cnt++ - } else { - cnt = 0 - } - } - cnt = 0 - for (let k = rows - 1; k >= 0; k--) { - if (grid[k][i] === '0') { - dp[k][i] += cnt - max = Math.max(max, dp[k][i]) - } else if (grid[k][i] === 'E') { - cnt++ - } else { - cnt = 0 - } - } - } - return max -} - diff --git a/361.bomb-enemy.js b/361.bomb-enemy.js new file mode 100644 index 00000000..9aee4bc5 --- /dev/null +++ b/361.bomb-enemy.js @@ -0,0 +1,53 @@ +/** + +Given a 2D grid, each cell is either a wall 'W', +an enemy 'E' or empty '0' (the number zero), +return the maximum enemies you can kill using one bomb. +The bomb kills all the enemies in the same row and column +from the planted point until it hits the wall since the wall +is too strong to be destroyed. + +Note: You can only put the bomb at an empty cell. + +Example: + +Input: [["0","E","0","0"],["E","0","W","E"],["0","E","0","0"]] +Output: 3 +Explanation: For the given grid, + +0 E 0 0 +E 0 W E +0 E 0 0 + +Placing a bomb at (1,1) kills 3 enemies. + +*/ + +/** + * @param {character[][]} grid + * @return {number} + */ +const maxKilledEnemies = function(grid) { + const m = grid.length + const n = m !== 0 ? grid[0].length : 0 + let result = 0 + let rowhits = 0 + const colhits = new Array(n).fill(0) + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (j === 0 || grid[i][j - 1] === 'W') { + rowhits = 0 + for (let k = j; k < n && grid[i][k] !== 'W'; k++) + rowhits += grid[i][k] === 'E' ? 1 : 0 + } + if (i === 0 || grid[i - 1][j] === 'W') { + colhits[j] = 0 + for (let k = i; k < m && grid[k][j] !== 'W'; k++) + colhits[j] += grid[k][j] === 'E' ? 1 : 0 + } + if (grid[i][j] === '0') result = Math.max(result, rowhits + colhits[j]) + } + } + return result +} + diff --git a/362-design-hit-counter.js b/362.design-hit-counter.js similarity index 100% rename from 362-design-hit-counter.js rename to 362.design-hit-counter.js diff --git a/363-max-sum-of-rectangle-no-larger-than-k.js b/363.max-sum-of-rectangle-no-larger-than-k.js similarity index 100% rename from 363-max-sum-of-rectangle-no-larger-than-k.js rename to 363.max-sum-of-rectangle-no-larger-than-k.js diff --git a/364-nested-list-weight-sum-ii.js b/364-nested-list-weight-sum-ii.js deleted file mode 100644 index e3d1f4b1..00000000 --- a/364-nested-list-weight-sum-ii.js +++ /dev/null @@ -1,94 +0,0 @@ -/** - * // This is the interface that allows for creating nested lists. - * // You should not implement it, or speculate about its implementation - * function NestedInteger() { - * - * Return true if this NestedInteger holds a single integer, rather than a nested list. - * @return {boolean} - * this.isInteger = function() { - * ... - * }; - * - * Return the single integer that this NestedInteger holds, if it holds a single integer - * Return null if this NestedInteger holds a nested list - * @return {integer} - * this.getInteger = function() { - * ... - * }; - * - * Set this NestedInteger to hold a single integer equal to value. - * @return {void} - * this.setInteger = function(value) { - * ... - * }; - * - * Set this NestedInteger to hold a nested list and adds a nested integer elem to it. - * @return {void} - * this.add = function(elem) { - * ... - * }; - * - * Return the nested list that this NestedInteger holds, if it holds a nested list - * Return null if this NestedInteger holds a single integer - * @return {NestedInteger[]} - * this.getList = function() { - * ... - * }; - * }; - */ -/** - * @param {NestedInteger[]} nestedList - * @return {number} - */ -const depthSumInverse = function(nestedList) { - const maxDepth = nestedList.reduce( - (max, list) => Math.max(max, getMaxDepth(list)), - 1 - ) - return nestedList.reduce((total, list) => total + sum(list, maxDepth), 0) -} - -function getMaxDepth(nestedList) { - if (nestedList.isInteger()) return 1 - return nestedList - .getList() - .reduce((max, list) => Math.max(max, 1 + getMaxDepth(list)), 1) -} - -function sum(nestedList, n) { - if (nestedList.isInteger()) return n * nestedList.getInteger() - return nestedList - .getList() - .reduce((total, list) => total + sum(list, n - 1), 0) -} - -// another - -const depthSumInverse = function(nestedList) { - const Q = [] - let temp = [] - while (nestedList.length) { - temp = [] - for (let i = 0; i < nestedList.length; i++) { - if (nestedList[i].isInteger()) { - Q.push(nestedList[i].getInteger()) - } else { - let list = nestedList[i].getList() - temp.push(...list) - } - } - Q.push('level') - nestedList = temp - } - let sum = 0 - let level = 0 - while (Q.length) { - let item = Q.pop() - if (item === 'level') { - level++ - } else { - sum += item * level - } - } - return sum -} diff --git a/364.nested-list-weight-sum-ii.js b/364.nested-list-weight-sum-ii.js new file mode 100644 index 00000000..442f4caf --- /dev/null +++ b/364.nested-list-weight-sum-ii.js @@ -0,0 +1,64 @@ +/** + * // This is the interface that allows for creating nested lists. + * // You should not implement it, or speculate about its implementation + * function NestedInteger() { + * + * Return true if this NestedInteger holds a single integer, rather than a nested list. + * @return {boolean} + * this.isInteger = function() { + * ... + * }; + * + * Return the single integer that this NestedInteger holds, if it holds a single integer + * Return null if this NestedInteger holds a nested list + * @return {integer} + * this.getInteger = function() { + * ... + * }; + * + * Set this NestedInteger to hold a single integer equal to value. + * @return {void} + * this.setInteger = function(value) { + * ... + * }; + * + * Set this NestedInteger to hold a nested list and adds a nested integer elem to it. + * @return {void} + * this.add = function(elem) { + * ... + * }; + * + * Return the nested list that this NestedInteger holds, if it holds a nested list + * Return null if this NestedInteger holds a single integer + * @return {NestedInteger[]} + * this.getList = function() { + * ... + * }; + * }; + */ +/** + * @param {NestedInteger[]} nestedList + * @return {number} + */ +const depthSumInverse = function(nestedList) { + const maxDepth = nestedList.reduce( + (max, list) => Math.max(max, getMaxDepth(list)), + 1 + ) + return nestedList.reduce((total, list) => total + sum(list, maxDepth), 0) +} + +function getMaxDepth(nestedList) { + if (nestedList.isInteger()) return 1 + return nestedList + .getList() + .reduce((max, list) => Math.max(max, 1 + getMaxDepth(list)), 1) +} + +function sum(nestedList, n) { + if (nestedList.isInteger()) return n * nestedList.getInteger() + return nestedList + .getList() + .reduce((total, list) => total + sum(list, n - 1), 0) +} + diff --git a/365-water-and-jug-problem.js b/365.water-and-jug-problem.js similarity index 100% rename from 365-water-and-jug-problem.js rename to 365.water-and-jug-problem.js diff --git a/366-find-leaves-of-binary-tree.js b/366-find-leaves-of-binary-tree.js deleted file mode 100644 index a88ff385..00000000 --- a/366-find-leaves-of-binary-tree.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - -Given a binary tree, collect a tree's nodes as if you were doing this: -Collect and remove all leaves, repeat until the tree is empty. - -Example: - -Input: [1,2,3,4,5] - - 1 - / \ - 2 3 - / \ - 4 5 - -Output: [[4,5,3],[2],[1]] - -Explanation: - -1. Removing the leaves [4,5,3] would result in this tree: - - 1 - / - 2 - -2. Now removing the leaf [2] would result in this tree: - - 1 - -3. Now removing the leaf [1] would result in the empty tree: - - [] - -*/ - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number[][]} - */ -const findLeaves = function(root) { - const res = [] - if(root == null) return res - while(root.left || root.right) { - const tmp = [] - leaves(root, null, tmp) - res.push(tmp) - } - res.push([root.val]) - return res -}; - -function leaves(node, p, res) { - if(node == null) return - if(node.left === null && node.right === null) { - res.push(node.val) - if(p && p.left === node) p.left = null - if(p && p.right === node) p.right = null - return - } - leaves(node.left, node, res) - leaves(node.right, node, res) -} - -// another - -const findLeaves = function(root) { - const res = [] - dfs(root, res) - return res -}; - -function dfs(node, res) { - if(node == null) return -1 - const i = 1 + Math.max(dfs(node.left, res), dfs(node.right, res)) - if(!res[i]) res[i] = [] - res[i].push(node.val) - return i -} diff --git a/366.find-leaves-of-binary-tree.js b/366.find-leaves-of-binary-tree.js new file mode 100644 index 00000000..ef3cca54 --- /dev/null +++ b/366.find-leaves-of-binary-tree.js @@ -0,0 +1,70 @@ +/** + +Given a binary tree, collect a tree's nodes as if you were doing this: +Collect and remove all leaves, repeat until the tree is empty. + +Example: + +Input: [1,2,3,4,5] + + 1 + / \ + 2 3 + / \ + 4 5 + +Output: [[4,5,3],[2],[1]] + +Explanation: + +1. Removing the leaves [4,5,3] would result in this tree: + + 1 + / + 2 + +2. Now removing the leaf [2] would result in this tree: + + 1 + +3. Now removing the leaf [1] would result in the empty tree: + + [] + +*/ + +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[][]} + */ +const findLeaves = function(root) { + const res = [] + if(root == null) return res + while(root.left || root.right) { + const tmp = [] + leaves(root, null, tmp) + res.push(tmp) + } + res.push([root.val]) + return res +}; + +function leaves(node, p, res) { + if(node == null) return + if(node.left === null && node.right === null) { + res.push(node.val) + if(p && p.left === node) p.left = null + if(p && p.right === node) p.right = null + return + } + leaves(node.left, node, res) + leaves(node.right, node, res) +} + diff --git a/367-valid-perfect-square.js b/367.valid-perfect-square.js similarity index 100% rename from 367-valid-perfect-square.js rename to 367.valid-perfect-square.js diff --git a/368-largest-divisible-subset.js b/368-largest-divisible-subset.js deleted file mode 100644 index bd74d95a..00000000 --- a/368-largest-divisible-subset.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[]} - */ -const largestDivisibleSubset = function(nums) { - const n = nums.length; - if(n === 0 || n === 1) return nums - let maxSize = 0; - const dp = Array(n).fill(1) - nums.sort((a, b) => a - b) - for(let i = 1; i < n; i++) { - for(let j = i - 1; j >= 0; j--) { - if(nums[i] % nums[j] === 0) { - const tmp = dp[j] + 1 - if(tmp > dp[i]) dp[i] = tmp - } - } - if(dp[i] > maxSize) maxSize = dp[i] - } - const res = [] - let pivot = 0 - for(let i = n - 1; i >= 0; i--) { - if(dp[i] === maxSize && (pivot % nums[i] === 0)) { - pivot = nums[i] - maxSize-- - res.push(nums[i]) - } - } - - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number[]} - */ -const largestDivisibleSubset = function(nums) { - let len = nums.length; - let maxSize = 0; - let maxSizeLastIdx; - // T[n] should be the length of the largest divisible subset whose smallest number is a[n] - const T = new Array(len).fill(0); - const son = new Array(len).fill(0); - nums.sort((a, b) => a - b); - for (let i = 0; i < len; i++) { - for (let j = i; j >= 0; j--) { - if (nums[i] % nums[j] === 0 && T[j] + 1 > T[i]) { - T[i] = T[j] + 1; - son[i] = j; - } - } - if (T[i] > maxSize) { - maxSize = T[i]; - maxSizeLastIdx = i; - } - } - const re = []; - for (let i = 0; i < maxSize; i++) { - re.unshift(nums[maxSizeLastIdx]); - maxSizeLastIdx = son[maxSizeLastIdx]; - } - return re; -}; diff --git a/368.largest-divisible-subset.js b/368.largest-divisible-subset.js new file mode 100644 index 00000000..128a20ef --- /dev/null +++ b/368.largest-divisible-subset.js @@ -0,0 +1,32 @@ +/** + * @param {number[]} nums + * @return {number[]} + */ +const largestDivisibleSubset = function(nums) { + const n = nums.length; + if(n === 0 || n === 1) return nums + let maxSize = 0; + const dp = Array(n).fill(1) + nums.sort((a, b) => a - b) + for(let i = 1; i < n; i++) { + for(let j = i - 1; j >= 0; j--) { + if(nums[i] % nums[j] === 0) { + const tmp = dp[j] + 1 + if(tmp > dp[i]) dp[i] = tmp + } + } + if(dp[i] > maxSize) maxSize = dp[i] + } + const res = [] + let pivot = 0 + for(let i = n - 1; i >= 0; i--) { + if(dp[i] === maxSize && (pivot % nums[i] === 0)) { + pivot = nums[i] + maxSize-- + res.push(nums[i]) + } + } + + return res +}; + diff --git a/369-plus-one-linked-list.js b/369-plus-one-linked-list.js deleted file mode 100644 index 23f754b5..00000000 --- a/369-plus-one-linked-list.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - -Given a non-negative integer represented as non-empty a singly linked list of digits, plus one to the integer. -You may assume the integer do not contain any leading zero, except the number 0 itself. -The digits are stored such that the most significant digit is at the head of the list. - -Example : - -Input: [1,2,3] -Output: [1,2,4] - -*/ - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @return {ListNode} - */ -const plusOne = function(head) { - const dummy = new ListNode(1) - dummy.next = head - const carry = plusOneRecursion(head) - return carry ? dummy : dummy.next -} -const plusOneRecursion = node => { - if (!node) return 1 - node.val += plusOneRecursion(node.next) - if (node.val > 9) { - node.val %= 10 - return 1 - } - return 0 -} - -// another - -/** - * @param {ListNode} head - * @return {ListNode} - */ -const plusOne = function(head) { - const dummy = new ListNode(0) - dummy.next = head - let node = head - let lastNotNine = dummy - while(node) { - if(node.val !== 9) lastNotNine = node - node = node.next - } - lastNotNine.val++ - node = lastNotNine.next - while(node) { - node.val = 0 - node = node.next - } - return dummy.val === 1 ? dummy : dummy.next -} - - diff --git a/369.plus-one-linked-list.js b/369.plus-one-linked-list.js new file mode 100644 index 00000000..3e2a4c32 --- /dev/null +++ b/369.plus-one-linked-list.js @@ -0,0 +1,40 @@ +/** + +Given a non-negative integer represented as non-empty a singly linked list of digits, plus one to the integer. +You may assume the integer do not contain any leading zero, except the number 0 itself. +The digits are stored such that the most significant digit is at the head of the list. + +Example : + +Input: [1,2,3] +Output: [1,2,4] + +*/ + +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ +const plusOne = function(head) { + const dummy = new ListNode(1) + dummy.next = head + const carry = plusOneRecursion(head) + return carry ? dummy : dummy.next +} +const plusOneRecursion = node => { + if (!node) return 1 + node.val += plusOneRecursion(node.next) + if (node.val > 9) { + node.val %= 10 + return 1 + } + return 0 +} + diff --git a/37-sudoku-solver.js b/37-sudoku-solver.js deleted file mode 100644 index b057ce6e..00000000 --- a/37-sudoku-solver.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @param {character[][]} board - * @return {void} Do not return anything, modify board in-place instead. - */ -const solveSudoku = function(board) { - dfs(0, 0) - function dfs(row, col) { - if (row === 9) return true - if (col === 9) return dfs(row + 1, 0) - if (board[row][col] === ".") { - for (let num = 1; num <= 9; num++) { - if (isValid(row, col, `${num}`)) { - board[row][col] = `${num}` - if (dfs(row, col + 1)) return true - board[row][col] = "." - } - } - } else { - return dfs(row, col + 1) - } - return false - } - function isValid(row, col, num) { - for (let rowIdx = 0; rowIdx < 9; rowIdx++) if (board[rowIdx][col] === num) return false - for (let colIdx = 0; colIdx < 9; colIdx++) if (board[row][colIdx] === num) return false - - let squareRowStart = row - (row % 3) - let squareColStart = col - (col % 3) - for (let rIdx = 0; rIdx < 3; rIdx++) { - for (let cIdx = 0; cIdx < 3; cIdx++) { - if (board[squareRowStart + rIdx][squareColStart + cIdx] === num) return false - } - } - return true - } -} - - -// another - -/** - * @param {character[][]} board - * @return {void} Do not return anything, modify board in-place instead. - */ -const solveSudoku = function(board) { - helper(board, 0 , 0) -}; - -function helper(board, row, col) { - if(row >= 9) return true - if(col >= 9) return helper(board, row + 1, 0) - if(board[row][col] !== '.') return helper(board, row, col + 1) - for(let i = 1; i <= 9; i++) { - const ch = `${i}` - if(valid(board, row, col, ch)) { - board[row][col] = ch - if(helper(board, row, col + 1)) return true - board[row][col] = '.' - } - } - return false -} - -function valid(board, row, col, ch) { - const blkRow = ~~(row / 3), blkCol = ~~(col / 3) - for(let i = 0; i < 9; i++) { - if(board[row][i] === ch) return false - if(board[i][col] === ch) return false - if(board[blkRow * 3 + Math.floor(i / 3)][blkCol * 3 + (i % 3)] === ch) return false - } - return true -} diff --git a/37.sudoku-solver.js b/37.sudoku-solver.js new file mode 100644 index 00000000..59f9e07f --- /dev/null +++ b/37.sudoku-solver.js @@ -0,0 +1,38 @@ +/** + * @param {character[][]} board + * @return {void} Do not return anything, modify board in-place instead. + */ +const solveSudoku = function(board) { + dfs(0, 0) + function dfs(row, col) { + if (row === 9) return true + if (col === 9) return dfs(row + 1, 0) + if (board[row][col] === ".") { + for (let num = 1; num <= 9; num++) { + if (isValid(row, col, `${num}`)) { + board[row][col] = `${num}` + if (dfs(row, col + 1)) return true + board[row][col] = "." + } + } + } else { + return dfs(row, col + 1) + } + return false + } + function isValid(row, col, num) { + for (let rowIdx = 0; rowIdx < 9; rowIdx++) if (board[rowIdx][col] === num) return false + for (let colIdx = 0; colIdx < 9; colIdx++) if (board[row][colIdx] === num) return false + + let squareRowStart = row - (row % 3) + let squareColStart = col - (col % 3) + for (let rIdx = 0; rIdx < 3; rIdx++) { + for (let cIdx = 0; cIdx < 3; cIdx++) { + if (board[squareRowStart + rIdx][squareColStart + cIdx] === num) return false + } + } + return true + } +} + + diff --git a/370-range-addition.js b/370.range-addition.js similarity index 100% rename from 370-range-addition.js rename to 370.range-addition.js diff --git a/371-sum-of-two-integers.js b/371-sum-of-two-integers.js deleted file mode 100755 index cf7edf8e..00000000 --- a/371-sum-of-two-integers.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * @param {number} a - * @param {number} b - * @return {number} - */ -const getSum = function(a, b) { - return b === 0 ? a : getSum(a ^ b, (a & b) << 1); -}; diff --git a/371.sum-of-two-integers.js b/371.sum-of-two-integers.js new file mode 100644 index 00000000..f0a1ce08 --- /dev/null +++ b/371.sum-of-two-integers.js @@ -0,0 +1,8 @@ +/** + * @param {number} a + * @param {number} b + * @return {number} + */ +const getSum = function(a, b) { + return b === 0 ? a : getSum(a ^ b, (a & b) << 1); +}; diff --git a/372-super-pow.js b/372.super-pow.js similarity index 100% rename from 372-super-pow.js rename to 372.super-pow.js diff --git a/373-find-k-pairs-with-smallest-sums.js b/373-find-k-pairs-with-smallest-sums.js deleted file mode 100644 index 35fd1146..00000000 --- a/373-find-k-pairs-with-smallest-sums.js +++ /dev/null @@ -1,127 +0,0 @@ -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @param {number} k - * @return {number[][]} - */ -const kSmallestPairs = function (nums1, nums2, k) { - const pq = new PriorityQueue((a, b) => a[0] + a[1] < b[0] + b[1]) - for(let i = 0; i < nums1.length && i < k; i++) { - pq.push([nums1[i], nums2[0], 0]) - } - const res = [] - while(k > 0 && !pq.isEmpty()) { - const [e1, e2, e2i] = pq.pop() - res.push([e1, e2]) - if(e2i + 1 < nums2.length) pq.push([e1, nums2[e2i + 1], e2i + 1]) - k-- - } - - return res -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - - -// another - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @param {number} k - * @return {number[][]} - */ -const kSmallestPairs = function(nums1, nums2, k) { - let len1 = nums1.length, - len2 = nums2.length - let arr = Array(len1).fill(0), - resList = [] - while (k-- > 0) { - let min = Infinity, - index = -1, - lastj = Infinity - for (let i = 0; i < len1; i++) { - const j = arr[i] - if (j < lastj && j < len2) { - const sum = nums1[i] + nums2[j] - if (sum < min) { - min = sum - index = i - } - lastj = j - } - } - if (index == -1) { - break - } - resList.push([nums1[index], nums2[arr[index]]]) - arr[index]++ - } - return resList -} diff --git a/373.find-k-pairs-with-smallest-sums.js b/373.find-k-pairs-with-smallest-sums.js new file mode 100644 index 00000000..f18891c7 --- /dev/null +++ b/373.find-k-pairs-with-smallest-sums.js @@ -0,0 +1,91 @@ +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @param {number} k + * @return {number[][]} + */ +const kSmallestPairs = function (nums1, nums2, k) { + const pq = new PriorityQueue((a, b) => a[0] + a[1] < b[0] + b[1]) + for(let i = 0; i < nums1.length && i < k; i++) { + pq.push([nums1[i], nums2[0], 0]) + } + const res = [] + while(k > 0 && !pq.isEmpty()) { + const [e1, e2, e2i] = pq.pop() + res.push([e1, e2]) + if(e2i + 1 < nums2.length) pq.push([e1, nums2[e2i + 1], e2i + 1]) + k-- + } + + return res +} + +class PriorityQueue { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + + diff --git a/375-guess-number-higher-or-lower-ii.js b/375.guess-number-higher-or-lower-ii.js similarity index 100% rename from 375-guess-number-higher-or-lower-ii.js rename to 375.guess-number-higher-or-lower-ii.js diff --git a/376-wiggle-subsequence.js b/376-wiggle-subsequence.js deleted file mode 100644 index f20795a5..00000000 --- a/376-wiggle-subsequence.js +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const wiggleMaxLength = function(nums) { - if (nums.length < 2) return nums.length - let prevdiff = nums[1] - nums[0] - let count = prevdiff !== 0 ? 2 : 1 - for (let i = 2; i < nums.length; i++) { - let diff = nums[i] - nums[i - 1] - if ((diff > 0 && prevdiff <= 0) || (diff < 0 && prevdiff >= 0)) { - count++ - prevdiff = diff - } - } - return count -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const wiggleMaxLength = function(nums) { - const len = nums.length - if (len === 0) return 0 - let up = 1 - let down = 1 - for (let i = 1; i < len; i++) { - if (nums[i] > nums[i - 1]) { - up = down + 1 - } else if (nums[i] < nums[i - 1]) { - down = up + 1 - } - } - return Math.max(up, down) -} diff --git a/376.wiggle-subsequence.js b/376.wiggle-subsequence.js new file mode 100644 index 00000000..026b44f6 --- /dev/null +++ b/376.wiggle-subsequence.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const wiggleMaxLength = function(nums) { + if (nums.length < 2) return nums.length + let prevdiff = nums[1] - nums[0] + let count = prevdiff !== 0 ? 2 : 1 + for (let i = 2; i < nums.length; i++) { + let diff = nums[i] - nums[i - 1] + if ((diff > 0 && prevdiff <= 0) || (diff < 0 && prevdiff >= 0)) { + count++ + prevdiff = diff + } + } + return count +} + diff --git a/377-combination-sum-IV.js b/377-combination-sum-IV.js deleted file mode 100755 index 8a8e55be..00000000 --- a/377-combination-sum-IV.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} target - * @return {number} - */ -const combinationSum4 = function(nums, target) { - const comb = [1]; - for (let i = 1; i <= target; i++) { - comb[i] || (comb[i] = 0); - for (let j = 0; j < nums.length; j++) { - if (i >= nums[j]) { - comb[i] += comb[i - nums[j]]; - } - } - } - return comb[target]; -}; diff --git a/377.combination-sum-IV.js b/377.combination-sum-IV.js new file mode 100644 index 00000000..58b402b1 --- /dev/null +++ b/377.combination-sum-IV.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +const combinationSum4 = function(nums, target) { + const comb = [1]; + for (let i = 1; i <= target; i++) { + comb[i] || (comb[i] = 0); + for (let j = 0; j < nums.length; j++) { + if (i >= nums[j]) { + comb[i] += comb[i - nums[j]]; + } + } + } + return comb[target]; +}; diff --git a/378-kth-smallest-element-in-a-sorted-matrix.js b/378-kth-smallest-element-in-a-sorted-matrix.js deleted file mode 100755 index a955b4e8..00000000 --- a/378-kth-smallest-element-in-a-sorted-matrix.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {number[][]} matrix - * @param {number} k - * @return {number} - */ -const kthSmallest = function(matrix, k) { - let lo = matrix[0][0], - hi = matrix[matrix.length - 1][matrix[0].length - 1] + 1; //[lo, hi) - while (lo < hi) { - let mid = Math.floor(lo + (hi - lo) / 2); - let count = 0, - j = matrix[0].length - 1; - for (let i = 0; i < matrix.length; i++) { - while (j >= 0 && matrix[i][j] > mid) j--; - count += j + 1; - } - if (count < k) lo = mid + 1; - else hi = mid; - } - return lo; -}; - -console.log(kthSmallest([[-5]], 1)); -console.log(kthSmallest([[1, 2], [1, 3]], 4)); -console.log(kthSmallest([[1, 5, 9], [10, 11, 13], [12, 13, 15]], 8)); -console.log(kthSmallest([[1, 2], [1, 3]], 2)); diff --git a/378.kth-smallest-element-in-a-sorted-matrix.js b/378.kth-smallest-element-in-a-sorted-matrix.js new file mode 100644 index 00000000..406a9c6e --- /dev/null +++ b/378.kth-smallest-element-in-a-sorted-matrix.js @@ -0,0 +1,26 @@ +/** + * @param {number[][]} matrix + * @param {number} k + * @return {number} + */ +const kthSmallest = function(matrix, k) { + let lo = matrix[0][0], + hi = matrix[matrix.length - 1][matrix[0].length - 1] + 1; //[lo, hi) + while (lo < hi) { + let mid = Math.floor(lo + (hi - lo) / 2); + let count = 0, + j = matrix[0].length - 1; + for (let i = 0; i < matrix.length; i++) { + while (j >= 0 && matrix[i][j] > mid) j--; + count += j + 1; + } + if (count < k) lo = mid + 1; + else hi = mid; + } + return lo; +}; + +console.log(kthSmallest([[-5]], 1)); +console.log(kthSmallest([[1, 2], [1, 3]], 4)); +console.log(kthSmallest([[1, 5, 9], [10, 11, 13], [12, 13, 15]], 8)); +console.log(kthSmallest([[1, 2], [1, 3]], 2)); diff --git a/379-design-phone-directory.js b/379.design-phone-directory.js similarity index 100% rename from 379-design-phone-directory.js rename to 379.design-phone-directory.js diff --git a/38-count-and-say.js b/38.count-and-say.js similarity index 100% rename from 38-count-and-say.js rename to 38.count-and-say.js diff --git a/380-insert-delete-getrandom-o1.js b/380.insert-delete-getrandom-o1.js similarity index 100% rename from 380-insert-delete-getrandom-o1.js rename to 380.insert-delete-getrandom-o1.js diff --git a/381-insert-delete-getrandom-o1-duplicates-allowed.js b/381.insert-delete-getrandom-o1-duplicates-allowed.js similarity index 100% rename from 381-insert-delete-getrandom-o1-duplicates-allowed.js rename to 381.insert-delete-getrandom-o1-duplicates-allowed.js diff --git a/382-linked-list-random-node.js b/382-linked-list-random-node.js deleted file mode 100755 index 4c9a37a7..00000000 --- a/382-linked-list-random-node.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param head The linked list's head. - Note that the head is guaranteed to be not null, so it contains at least one node. - * @param {ListNode} head - */ -const Solution = function(head) { - this.list = head; - this.arr = []; - loop(head, this.arr); -}; - -/** - * Returns a random node's value. - * @return {number} - */ -Solution.prototype.getRandom = function() { - const len = this.arr.length; - return this.arr[Math.floor(Math.random() * len)].val; -}; - -/** - * Your Solution object will be instantiated and called as such: - * var obj = Object.create(Solution).createNew(head) - * var param_1 = obj.getRandom() - */ -function loop(node, arr) { - if (node == null) return; - arr.push(node); - loop(node.next, arr); -} diff --git a/382.linked-list-random-node.js b/382.linked-list-random-node.js new file mode 100644 index 00000000..026302cb --- /dev/null +++ b/382.linked-list-random-node.js @@ -0,0 +1,37 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param head The linked list's head. + Note that the head is guaranteed to be not null, so it contains at least one node. + * @param {ListNode} head + */ +const Solution = function(head) { + this.list = head; + this.arr = []; + loop(head, this.arr); +}; + +/** + * Returns a random node's value. + * @return {number} + */ +Solution.prototype.getRandom = function() { + const len = this.arr.length; + return this.arr[Math.floor(Math.random() * len)].val; +}; + +/** + * Your Solution object will be instantiated and called as such: + * var obj = Object.create(Solution).createNew(head) + * var param_1 = obj.getRandom() + */ +function loop(node, arr) { + if (node == null) return; + arr.push(node); + loop(node.next, arr); +} diff --git a/383-ransom-note.js b/383-ransom-note.js deleted file mode 100755 index 81ad0d58..00000000 --- a/383-ransom-note.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @param {string} ransomNote - * @param {string} magazine - * @return {boolean} - */ -const canConstruct = function(ransomNote, magazine) { - const m = new Map() - for(let c of magazine) { - m.set(c, (m.get(c) || 0) + 1 ) - } - for(let c of ransomNote) { - if(!m.has(c) || m.get(c) <= 0) return false - m.set(c, m.get(c) - 1) - } - return true -}; diff --git a/383.ransom-note.js b/383.ransom-note.js new file mode 100644 index 00000000..b8797404 --- /dev/null +++ b/383.ransom-note.js @@ -0,0 +1,16 @@ +/** + * @param {string} ransomNote + * @param {string} magazine + * @return {boolean} + */ +const canConstruct = function(ransomNote, magazine) { + const m = new Map() + for(let c of magazine) { + m.set(c, (m.get(c) || 0) + 1 ) + } + for(let c of ransomNote) { + if(!m.has(c) || m.get(c) <= 0) return false + m.set(c, m.get(c) - 1) + } + return true +}; diff --git a/384-shuffle-an-array.js b/384-shuffle-an-array.js deleted file mode 100755 index 7d86838b..00000000 --- a/384-shuffle-an-array.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @param {number[]} nums - */ -const Solution = function(nums) { - this.original = nums; -}; -/** - * Resets the array to its original configuration and return it. - * @return {number[]} - */ -Solution.prototype.reset = function() { - return this.original; -}; - -/** - * Returns a random shuffling of the array. - * @return {number[]} - */ -Solution.prototype.shuffle = function() { - const res = []; - const len = this.original.length; - let idx = 0; - let i = 0; - while (idx <= len - 1) { - i = Math.floor(Math.random() * len); - if (res[i] == null) { - res[i] = this.original[idx]; - idx += 1; - } - } - return res; -}; - -/** - * Your Solution object will be instantiated and called as such: - * var obj = Object.create(Solution).createNew(nums) - * var param_1 = obj.reset() - * var param_2 = obj.shuffle() - */ diff --git a/384.shuffle-an-array.js b/384.shuffle-an-array.js new file mode 100644 index 00000000..166c1283 --- /dev/null +++ b/384.shuffle-an-array.js @@ -0,0 +1,39 @@ +/** + * @param {number[]} nums + */ +const Solution = function(nums) { + this.original = nums; +}; +/** + * Resets the array to its original configuration and return it. + * @return {number[]} + */ +Solution.prototype.reset = function() { + return this.original; +}; + +/** + * Returns a random shuffling of the array. + * @return {number[]} + */ +Solution.prototype.shuffle = function() { + const res = []; + const len = this.original.length; + let idx = 0; + let i = 0; + while (idx <= len - 1) { + i = Math.floor(Math.random() * len); + if (res[i] == null) { + res[i] = this.original[idx]; + idx += 1; + } + } + return res; +}; + +/** + * Your Solution object will be instantiated and called as such: + * var obj = Object.create(Solution).createNew(nums) + * var param_1 = obj.reset() + * var param_2 = obj.shuffle() + */ diff --git a/385-mini-parser.js b/385.mini-parser.js similarity index 100% rename from 385-mini-parser.js rename to 385.mini-parser.js diff --git a/386-lexicographical-numbers.js b/386-lexicographical-numbers.js deleted file mode 100644 index d593eb57..00000000 --- a/386-lexicographical-numbers.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @param {number} n - * @return {number[]} - */ -const lexicalOrder = function(n) { - const res = [] - for(let i = 1; i < 10; i++) { - dfs(i) - } - - return res - - function dfs(num) { - if(num > n) return - res.push(num) - for(let i = 0; i < 10; i++) { - const tmp = num * 10 + i - if(tmp > n) return - dfs(tmp) - } - } -}; - -// another - -/** - * @param {number} n - * @return {number[]} - */ -const lexicalOrder = function(n) { - const result = [] - for (let i = 1; i < 10; i++) { - dfs(i) - } - function dfs(n) { - if (n <= num) result.push(n) - if (10 * n <= num) { - for (let j = 0; j < 10; j++) { - dfs(10 * n + j) - } - } - } - return result -} - -// another - -const lexicalOrder = function(n) { - function getNumberByOrder(start, end) { - for (let i = start; i <= end; i++) { - if (i > n) { - break - } - res.push(i) - getNumberByOrder(i * 10, i * 10 + 9) - } - } - const res = [] - getNumberByOrder(1, 9) - return res -} diff --git a/386.lexicographical-numbers.js b/386.lexicographical-numbers.js new file mode 100644 index 00000000..28b40459 --- /dev/null +++ b/386.lexicographical-numbers.js @@ -0,0 +1,23 @@ +/** + * @param {number} n + * @return {number[]} + */ +const lexicalOrder = function(n) { + const res = [] + for(let i = 1; i < 10; i++) { + dfs(i) + } + + return res + + function dfs(num) { + if(num > n) return + res.push(num) + for(let i = 0; i < 10; i++) { + const tmp = num * 10 + i + if(tmp > n) return + dfs(tmp) + } + } +}; + diff --git a/387-first-unique-character-in-a-string.js b/387-first-unique-character-in-a-string.js deleted file mode 100755 index b03d0169..00000000 --- a/387-first-unique-character-in-a-string.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const firstUniqChar = function(s) { - const arr = []; - const res = []; - const hash = {}; - let tmp; - let idx; - for (let i = 0; i < s.length; i++) { - tmp = s.charAt(i); - if (hash.hasOwnProperty(tmp)) { - idx = arr.indexOf(tmp); - if (idx >= 0) { - arr.splice(idx, 1); - res.splice(idx, 1); - } - - hash[tmp] += 1; - } else { - arr.push(tmp); - res.push(i); - hash[tmp] = 1; - } - } - return res[0] == null ? -1 : res[0]; -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const firstUniqChar = function(s) { - if(s === '') return -1 - const map = new Map() - for(let i = 0, len = s.length; i < len; i++) { - if(!map.has(s[i])) map.set(s[i], [i, 0]) - map.get(s[i])[1] += 1 - } - for(let [key, val] of map) { - if(val[1] === 1) return val[0] - } - return -1 - -}; diff --git a/387.first-unique-character-in-a-string.js b/387.first-unique-character-in-a-string.js new file mode 100644 index 00000000..6484632c --- /dev/null +++ b/387.first-unique-character-in-a-string.js @@ -0,0 +1,29 @@ +/** + * @param {string} s + * @return {number} + */ +const firstUniqChar = function(s) { + const arr = []; + const res = []; + const hash = {}; + let tmp; + let idx; + for (let i = 0; i < s.length; i++) { + tmp = s.charAt(i); + if (hash.hasOwnProperty(tmp)) { + idx = arr.indexOf(tmp); + if (idx >= 0) { + arr.splice(idx, 1); + res.splice(idx, 1); + } + + hash[tmp] += 1; + } else { + arr.push(tmp); + res.push(i); + hash[tmp] = 1; + } + } + return res[0] == null ? -1 : res[0]; +}; + diff --git a/388-longest-absolute-file-path.js b/388.longest-absolute-file-path.js similarity index 100% rename from 388-longest-absolute-file-path.js rename to 388.longest-absolute-file-path.js diff --git a/389-find-the-difference.js b/389-find-the-difference.js deleted file mode 100755 index 16dc0ba6..00000000 --- a/389-find-the-difference.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @param {string} s - * @param {string} t - * @return {character} - */ -const findTheDifference = function(s, t) { - let xor = 0 - for(let i = 0, len = s.length; i < len; i++) xor = xor ^ s.charCodeAt(i) ^ t.charCodeAt(i) - xor = xor ^ t.charCodeAt(t.length - 1) - return String.fromCharCode(xor) -}; - -// another - -/** - * @param {string} s - * @param {string} t - * @return {character} - */ -const findTheDifference = function(s, t) { - const arr = s.split(""); - let idx; - for (let i = 0; i < t.length; i++) { - idx = arr.indexOf(t[i]); - if (idx === -1) { - return t[i]; - } else { - arr.splice(idx, 1); - } - } -}; - -console.log(findTheDifference("abcd", "abcde")); diff --git a/389.find-the-difference.js b/389.find-the-difference.js new file mode 100644 index 00000000..8267a699 --- /dev/null +++ b/389.find-the-difference.js @@ -0,0 +1,12 @@ +/** + * @param {string} s + * @param {string} t + * @return {character} + */ +const findTheDifference = function(s, t) { + let xor = 0 + for(let i = 0, len = s.length; i < len; i++) xor = xor ^ s.charCodeAt(i) ^ t.charCodeAt(i) + xor = xor ^ t.charCodeAt(t.length - 1) + return String.fromCharCode(xor) +}; + diff --git a/39-combination-sum.js b/39-combination-sum.js deleted file mode 100755 index 56ecc406..00000000 --- a/39-combination-sum.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @param {number[]} candidates - * @param {number} target - * @return {number[][]} - */ -const combinationSum = function(candidates, target) { - candidates.sort((a, b) => a - b); - const res = []; - bt(candidates, target, res, [], 0); - return res; -}; - -function bt(candidates, target, res, combination, start) { - if (target === 0) { - res.push(combination.slice(0)); - return; - } - for (let i = start; i < candidates.length && target >= candidates[i]; i++) { - combination.push(candidates[i]); - bt(candidates, target - candidates[i], res, combination, i); - combination.pop(); - } -} diff --git a/39.combination-sum.js b/39.combination-sum.js new file mode 100644 index 00000000..34815ce0 --- /dev/null +++ b/39.combination-sum.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} candidates + * @param {number} target + * @return {number[][]} + */ +const combinationSum = function(candidates, target) { + candidates.sort((a, b) => a - b); + const res = []; + bt(candidates, target, res, [], 0); + return res; +}; + +function bt(candidates, target, res, combination, start) { + if (target === 0) { + res.push(combination.slice(0)); + return; + } + for (let i = start; i < candidates.length && target >= candidates[i]; i++) { + combination.push(candidates[i]); + bt(candidates, target - candidates[i], res, combination, i); + combination.pop(); + } +} diff --git a/390-elimination-game.js b/390.elimination-game.js similarity index 100% rename from 390-elimination-game.js rename to 390.elimination-game.js diff --git a/391-perfect-rectangle.js b/391.perfect-rectangle.js similarity index 100% rename from 391-perfect-rectangle.js rename to 391.perfect-rectangle.js diff --git a/392-is-subsequence.js b/392-is-subsequence.js deleted file mode 100644 index 46fe3361..00000000 --- a/392-is-subsequence.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @param {string} s - * @param {string} t - * @return {boolean} - */ -const isSubsequence = function(s, t) { - const sl = s.length - const tl = t.length - if(sl > tl) return false - if(sl === 0) return true - let si = 0 - for(let i = 0; i < tl && si < sl; i++) { - if(s[si] === t[i]) si++ - } - return si === sl -}; - -// another - -/** - * @param {string} s - * @param {string} t - * @return {boolean} - */ -const isSubsequence = function(s, t) { - let ti = 0 - let tmp = 0 - for (let i = 0; i < s.length; i++) { - if ((tmp = chk(t, ti, s.charAt(i))) === -1) { - return false - } else { - ti = tmp + 1 - } - } - - return true -} - -function chk(str, start, target) { - let idx = start - for (let i = start; i < str.length; i++) { - if (str.charAt(i) === target) { - return i - } - } - return -1 -} diff --git a/392.is-subsequence.js b/392.is-subsequence.js new file mode 100644 index 00000000..d7dc5259 --- /dev/null +++ b/392.is-subsequence.js @@ -0,0 +1,17 @@ +/** + * @param {string} s + * @param {string} t + * @return {boolean} + */ +const isSubsequence = function(s, t) { + const sl = s.length + const tl = t.length + if(sl > tl) return false + if(sl === 0) return true + let si = 0 + for(let i = 0; i < tl && si < sl; i++) { + if(s[si] === t[i]) si++ + } + return si === sl +}; + diff --git a/393-utf-8-validation.js b/393.utf-8-validation.js similarity index 100% rename from 393-utf-8-validation.js rename to 393.utf-8-validation.js diff --git a/394-decode-string.js b/394-decode-string.js deleted file mode 100755 index 36a19f99..00000000 --- a/394-decode-string.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ -const decodeString = function(s) { - const repeated = []; - const sbStack = []; - - let mul = 0; - let sb = ""; - for (let i = 0; i < s.length; i++) { - const c = s.charAt(i); - if (isDigit(c)) { - if (mul === 0) sbStack.push(sb); // here is the trick - mul = mul * 10 + +c; - } else if (c === "[") { - repeated.push(mul); - mul = 0; - sb = ""; - } else if (isLetter(c)) { - sb += c; - } else if (c === "]") { - let top = sbStack.pop(); - let r = repeated.pop(); - while (r-- > 0) top += sb; - sb = top; - } - } - - return sb; -}; - -function isDigit(c) { - return c.charCodeAt(0) >= 48 && c.charCodeAt(0) <= 57; -} - -function isLetter(c) { - return ( - (c.charCodeAt(0) >= 65 && c.charCodeAt(0) <= 90) || - (c.charCodeAt(0) >= 97 && c.charCodeAt(0) <= 122) - ); -} diff --git a/394.decode-string.js b/394.decode-string.js new file mode 100644 index 00000000..c3a4618e --- /dev/null +++ b/394.decode-string.js @@ -0,0 +1,42 @@ +/** + * @param {string} s + * @return {string} + */ +const decodeString = function(s) { + const repeated = []; + const sbStack = []; + + let mul = 0; + let sb = ""; + for (let i = 0; i < s.length; i++) { + const c = s.charAt(i); + if (isDigit(c)) { + if (mul === 0) sbStack.push(sb); // here is the trick + mul = mul * 10 + +c; + } else if (c === "[") { + repeated.push(mul); + mul = 0; + sb = ""; + } else if (isLetter(c)) { + sb += c; + } else if (c === "]") { + let top = sbStack.pop(); + let r = repeated.pop(); + while (r-- > 0) top += sb; + sb = top; + } + } + + return sb; +}; + +function isDigit(c) { + return c.charCodeAt(0) >= 48 && c.charCodeAt(0) <= 57; +} + +function isLetter(c) { + return ( + (c.charCodeAt(0) >= 65 && c.charCodeAt(0) <= 90) || + (c.charCodeAt(0) >= 97 && c.charCodeAt(0) <= 122) + ); +} diff --git a/395-longest-substring-with-at-least-k-repeating-characters.js b/395.longest-substring-with-at-least-k-repeating-characters.js similarity index 100% rename from 395-longest-substring-with-at-least-k-repeating-characters.js rename to 395.longest-substring-with-at-least-k-repeating-characters.js diff --git a/396-rotate-function.js b/396.rotate-function.js similarity index 100% rename from 396-rotate-function.js rename to 396.rotate-function.js diff --git a/397-integer-replacement.js b/397-integer-replacement.js deleted file mode 100644 index 36a4e692..00000000 --- a/397-integer-replacement.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const integerReplacement = function(n, memo = {}) { - if (n === 1) return 0; - if (memo[n]) return memo[n]; - memo[n] = n % 2 === 0 ? integerReplacement(n/2, memo) + 1 : Math.min(integerReplacement(n+1, memo), integerReplacement(n-1, memo)) + 1; - return memo[n]; -}; - -// another -const integerReplacement = function(n) { - let c = 0; - while (n !== 1) { - if ((n & 1) === 0) { - n >>>= 1; - } else if (n === 3 || ((n >>> 1) & 1) === 0) { - --n; - } else { - ++n; - } - ++c; - } - return c; -}; diff --git a/397.integer-replacement.js b/397.integer-replacement.js new file mode 100644 index 00000000..c09d94ab --- /dev/null +++ b/397.integer-replacement.js @@ -0,0 +1,11 @@ +/** + * @param {number} n + * @return {number} + */ +const integerReplacement = function(n, memo = {}) { + if (n === 1) return 0; + if (memo[n]) return memo[n]; + memo[n] = n % 2 === 0 ? integerReplacement(n/2, memo) + 1 : Math.min(integerReplacement(n+1, memo), integerReplacement(n-1, memo)) + 1; + return memo[n]; +}; + diff --git a/398-random-pick-index.js b/398-random-pick-index.js deleted file mode 100755 index 545b9883..00000000 --- a/398-random-pick-index.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {number[]} nums - */ -const Solution = function(nums) { - this.nums = nums; -}; - -/** - * @param {number} target - * @return {number} - */ -Solution.prototype.pick = function(target) { - const res = []; - for (let i = 0; i < this.nums.length; i++) { - if (this.nums[i] === target) { - res.push(i); - } - } - return res[Math.floor(Math.random() * res.length)]; -}; - -/** - * Your Solution object will be instantiated and called as such: - * var obj = Object.create(Solution).createNew(nums) - * var param_1 = obj.pick(target) - */ diff --git a/398.random-pick-index.js b/398.random-pick-index.js new file mode 100644 index 00000000..fad2b0b5 --- /dev/null +++ b/398.random-pick-index.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} nums + */ +const Solution = function(nums) { + this.nums = nums; +}; + +/** + * @param {number} target + * @return {number} + */ +Solution.prototype.pick = function(target) { + const res = []; + for (let i = 0; i < this.nums.length; i++) { + if (this.nums[i] === target) { + res.push(i); + } + } + return res[Math.floor(Math.random() * res.length)]; +}; + +/** + * Your Solution object will be instantiated and called as such: + * var obj = Object.create(Solution).createNew(nums) + * var param_1 = obj.pick(target) + */ diff --git a/399-evaluate-division.js b/399-evaluate-division.js deleted file mode 100755 index 391adc93..00000000 --- a/399-evaluate-division.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @param {string[][]} equations - * @param {number[]} values - * @param {string[][]} queries - * @return {number[]} - */ -const calcEquation = function(equations, values, queries) { - const m = {}; - for (let i = 0; i < values.length; i++) { - if (!m.hasOwnProperty(equations[i][0])) m[equations[i][0]] = {}; - if (!m.hasOwnProperty(equations[i][1])) m[equations[i][1]] = {}; - m[equations[i][0]][equations[i][1]] = values[i]; - m[equations[i][1]][equations[i][0]] = 1 / values[i]; - } - const r = []; - for (let i = 0; i < queries.length; i++) { - r[i] = dfs(queries[i][0], queries[i][1], 1, m, []); - } - return r; -}; - -function dfs(s, t, r, m, seen) { - if (!m.hasOwnProperty(s) || !hsetAdd(seen, s)) return -1; - if (s === t) return r; - let next = m[s]; - for (let c of Object.keys(next)) { - let result = dfs(c, t, r * next[c], m, seen); - if (result !== -1) return result; - } - return -1; -} - -function hsetAdd(arr, el) { - if (arr.indexOf(el) === -1) { - arr.push(el); - return true; - } else { - return false; - } -} diff --git a/399.evaluate-division.js b/399.evaluate-division.js new file mode 100644 index 00000000..66972b62 --- /dev/null +++ b/399.evaluate-division.js @@ -0,0 +1,40 @@ +/** + * @param {string[][]} equations + * @param {number[]} values + * @param {string[][]} queries + * @return {number[]} + */ +const calcEquation = function(equations, values, queries) { + const m = {}; + for (let i = 0; i < values.length; i++) { + if (!m.hasOwnProperty(equations[i][0])) m[equations[i][0]] = {}; + if (!m.hasOwnProperty(equations[i][1])) m[equations[i][1]] = {}; + m[equations[i][0]][equations[i][1]] = values[i]; + m[equations[i][1]][equations[i][0]] = 1 / values[i]; + } + const r = []; + for (let i = 0; i < queries.length; i++) { + r[i] = dfs(queries[i][0], queries[i][1], 1, m, []); + } + return r; +}; + +function dfs(s, t, r, m, seen) { + if (!m.hasOwnProperty(s) || !hsetAdd(seen, s)) return -1; + if (s === t) return r; + let next = m[s]; + for (let c of Object.keys(next)) { + let result = dfs(c, t, r * next[c], m, seen); + if (result !== -1) return result; + } + return -1; +} + +function hsetAdd(arr, el) { + if (arr.indexOf(el) === -1) { + arr.push(el); + return true; + } else { + return false; + } +} diff --git a/4-median-of-two-sorted-arrays.js b/4-median-of-two-sorted-arrays.js deleted file mode 100755 index 095350b7..00000000 --- a/4-median-of-two-sorted-arrays.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const findMedianSortedArrays = function(nums1, nums2) { - if(nums1.length > nums2.length) return findMedianSortedArrays(nums2, nums1) - const m = nums1.length, n = nums2.length - let low = 0, high = m - while(low <= high) { - - const px = Math.floor((low + high) / 2) - const py = Math.floor(( m + n + 1 ) / 2) - px - - const maxLeft1 = px === 0 ? -Infinity : nums1[px - 1] - const minRight1 = px === m ? Infinity : nums1[px] - - const maxLeft2 = py === 0 ? -Infinity : nums2[py - 1] - const minRight2 = py === n ? Infinity : nums2[py] - - if(maxLeft1 <= minRight2 && maxLeft2 <= minRight1) { - if((m + n) % 2 === 0) { - return (Math.max(maxLeft1, maxLeft2) + Math.min(minRight1, minRight2)) / 2 - } else { - return Math.max(maxLeft1, maxLeft2) - } - } else if(maxLeft1 > minRight2) { - high = px - 1 - } else { - low = px + 1 - } - - } -}; - -// another - -/** - * @param {number[]} A - * @param {number[]} B - * @return {number} - */ - -const findMedianSortedArrays = function(A, B) { - let m = A.length, - n = B.length; - - if (m > n) { - return findMedianSortedArrays(B, A); - } - - let imin = 0, - imax = m, - i, - j; - while (imin <= imax) { - i = (imin + imax) >> 1; - j = ((m + n + 1) >> 1) - i; - if (j > 0 && i < m && B[j - 1] > A[i]) { - imin = i + 1; - } else if (i > 0 && j < n && A[i - 1] > B[j]) { - imax = i - 1; - } else { - if (i === 0) { - num1 = B[j - 1]; - } else if (j === 0) { - num1 = A[i - 1]; - } else { - num1 = Math.max(A[i - 1], B[j - 1]); - } - - if ((m + n) & 1) { - return num1; - } - - if (i === m) { - num2 = B[j]; - } else if (j === n) { - num2 = A[i]; - } else { - num2 = Math.min(A[i], B[j]); - } - return (num1 + num2) / 2.0; - } - } -}; - -// another - -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number} - */ -const findMedianSortedArrays = function (nums1, nums2) { - if (nums1.length > nums2.length) { - return findMedianSortedArrays(nums2, nums1) - } - const x = nums1.length - const y = nums2.length - - let low = 0 - let high = x - - while (low <= high) { - const partX = Math.floor((low + high) / 2) - const partY = Math.floor((x + y + 1) / 2) - partX - - const maxX = partX === 0 ? Number.NEGATIVE_INFINITY : nums1[partX - 1] - const maxY = partY === 0 ? Number.NEGATIVE_INFINITY : nums2[partY - 1] - - const minX = - partX === nums1.length ? Number.POSITIVE_INFINITY : nums1[partX] - const minY = - partY === nums2.length ? Number.POSITIVE_INFINITY : nums2[partY] - - if (maxX <= minY && maxY <= minX) { - const lowMax = Math.max(maxX, maxY) - - if ((x + y) % 2 == 1) { - return Math.max(maxX, maxY) - } else { - return (Math.max(maxX, maxY) + Math.min(minX, minY)) / 2 - } - } else if (maxX < minY) { - low = partX + 1 - } else { - high = partX - 1 - } - } -} - - diff --git a/4.median-of-two-sorted-arrays.js b/4.median-of-two-sorted-arrays.js new file mode 100644 index 00000000..c025d3ff --- /dev/null +++ b/4.median-of-two-sorted-arrays.js @@ -0,0 +1,35 @@ +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +const findMedianSortedArrays = function(nums1, nums2) { + if(nums1.length > nums2.length) return findMedianSortedArrays(nums2, nums1) + const m = nums1.length, n = nums2.length + let low = 0, high = m + while(low <= high) { + + const px = Math.floor((low + high) / 2) + const py = Math.floor(( m + n + 1 ) / 2) - px + + const maxLeft1 = px === 0 ? -Infinity : nums1[px - 1] + const minRight1 = px === m ? Infinity : nums1[px] + + const maxLeft2 = py === 0 ? -Infinity : nums2[py - 1] + const minRight2 = py === n ? Infinity : nums2[py] + + if(maxLeft1 <= minRight2 && maxLeft2 <= minRight1) { + if((m + n) % 2 === 0) { + return (Math.max(maxLeft1, maxLeft2) + Math.min(minRight1, minRight2)) / 2 + } else { + return Math.max(maxLeft1, maxLeft2) + } + } else if(maxLeft1 > minRight2) { + high = px - 1 + } else { + low = px + 1 + } + + } +}; + diff --git a/40-combination-sum-II.js b/40-combination-sum-II.js deleted file mode 100755 index 4cea637b..00000000 --- a/40-combination-sum-II.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @param {number[]} candidates - * @param {number} target - * @return {number[][]} - */ -const combinationSum2 = function(candidates, target) { - candidates.sort((a, b) => a - b); - const res = []; - bt(candidates, target, res, [], 0); - return res; -}; - -function bt(candidates, target, res, combination, start) { - if (target === 0) { - res.push(combination.slice(0)); - return; - } - for (let i = start; i < candidates.length && target >= candidates[i]; i++) { - if (i > 0 && candidates[i] === candidates[i - 1] && i > start) continue; - combination.push(candidates[i]); - bt(candidates, target - candidates[i], res, combination, i + 1); - combination.pop(); - } -} diff --git a/40.combination-sum-II.js b/40.combination-sum-II.js new file mode 100644 index 00000000..53bfabf0 --- /dev/null +++ b/40.combination-sum-II.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} candidates + * @param {number} target + * @return {number[][]} + */ +const combinationSum2 = function(candidates, target) { + candidates.sort((a, b) => a - b); + const res = []; + bt(candidates, target, res, [], 0); + return res; +}; + +function bt(candidates, target, res, combination, start) { + if (target === 0) { + res.push(combination.slice(0)); + return; + } + for (let i = start; i < candidates.length && target >= candidates[i]; i++) { + if (i > 0 && candidates[i] === candidates[i - 1] && i > start) continue; + combination.push(candidates[i]); + bt(candidates, target - candidates[i], res, combination, i + 1); + combination.pop(); + } +} diff --git a/400-nth-digit.js b/400.nth-digit.js similarity index 100% rename from 400-nth-digit.js rename to 400.nth-digit.js diff --git a/401-binary-watch.js b/401.binary-watch.js similarity index 100% rename from 401-binary-watch.js rename to 401.binary-watch.js diff --git a/402-remove-k-digits.js b/402-remove-k-digits.js deleted file mode 100644 index 21ef2e47..00000000 --- a/402-remove-k-digits.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @param {string} num - * @param {number} k - * @return {string} - */ -const removeKdigits = function(num, k) { - const digits = num.length - k; - const stk = new Array(num.length); - let top = 0; - // k keeps track of how many characters we can remove - // if the previous character in stk is larger than the current one - // then removing it will get a smaller number - // but we can only do so when k is larger than 0 - for (let i = 0; i < num.length; i++) { - let c = num.charAt(i); - while (top > 0 && stk[top - 1] > c && k > 0) { - top -= 1; - k -= 1; - } - stk[top++] = c; - } - // find the index of first non-zero digit - let idx = 0; - while (idx < digits && stk[idx] === "0") idx++; - return idx === digits ? "0" : stk.slice(idx, digits + idx).join(""); -}; - - -// another - -/** - * @param {string} num - * @param {number} k - * @return {string} - */ -const removeKdigits = function(num, k) { - const n = num.length, stack = [] - if(n === k) return '0' - let i = 0 - while(i < n) { - while(k > 0 && stack.length && stack[stack.length - 1] > num[i]) { - k-- - stack.pop() - } - stack.push(num[i++]) - } - while(k-- > 0) stack.pop() - while(stack[0] === '0') stack.shift() - return stack.length ? stack.join('') : '0' -}; - -// another - -/** - * @param {string} num - * @param {number} k - * @return {string} - */ -const removeKdigits = function(num, k) { - const n = num.length, stack = [] - for(let i = 0; i < n; i++) { - const ch = num[i] - while(stack.length && k > 0 && ch < stack[stack.length - 1]) { - stack.pop() - k-- - } - stack.push(ch) - } - while(k > 0) { - stack.pop() - k-- - } - while(stack[0] === '0') stack.shift() - return stack.length ? stack.join('') : '0' -}; diff --git a/402.remove-k-digits.js b/402.remove-k-digits.js new file mode 100644 index 00000000..dbcc0828 --- /dev/null +++ b/402.remove-k-digits.js @@ -0,0 +1,28 @@ +/** + * @param {string} num + * @param {number} k + * @return {string} + */ +const removeKdigits = function(num, k) { + const digits = num.length - k; + const stk = new Array(num.length); + let top = 0; + // k keeps track of how many characters we can remove + // if the previous character in stk is larger than the current one + // then removing it will get a smaller number + // but we can only do so when k is larger than 0 + for (let i = 0; i < num.length; i++) { + let c = num.charAt(i); + while (top > 0 && stk[top - 1] > c && k > 0) { + top -= 1; + k -= 1; + } + stk[top++] = c; + } + // find the index of first non-zero digit + let idx = 0; + while (idx < digits && stk[idx] === "0") idx++; + return idx === digits ? "0" : stk.slice(idx, digits + idx).join(""); +}; + + diff --git a/403-frog-jump.js b/403.frog-jump.js similarity index 100% rename from 403-frog-jump.js rename to 403.frog-jump.js diff --git a/404-sum-of-left-leaves.js b/404.sum-of-left-leaves.js similarity index 100% rename from 404-sum-of-left-leaves.js rename to 404.sum-of-left-leaves.js diff --git a/405-convert-a-number-to-hexadecimal.js b/405.convert-a-number-to-hexadecimal.js similarity index 100% rename from 405-convert-a-number-to-hexadecimal.js rename to 405.convert-a-number-to-hexadecimal.js diff --git a/406-queue-reconstruction-by-height.js b/406-queue-reconstruction-by-height.js deleted file mode 100755 index 67f9eba1..00000000 --- a/406-queue-reconstruction-by-height.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @param {number[][]} people - * @return {number[][]} - */ -const reconstructQueue = function (people) { - const h = 0 - const k = 1 - people.sort((a, b) => (a[h] == b[h] ? a[k] - b[k] : b[h] - a[h])) - let queue = [] - for (let person of people) { - queue.splice(person[k], 0, person) - } - return queue -} - -// another - -/** - * @param {number[][]} people - * @return {number[][]} - */ -const reconstructQueue = function(people) { - if (!people) return []; - const peopledct = {}; - let height = []; - const res = []; - people.forEach((el, idx) => { - if (peopledct.hasOwnProperty(el[0])) { - peopledct[el[0]].push([el[1], idx]); - } else { - peopledct[el[0]] = [[el[1], idx]]; - height.push(el[0]); - } - }); - height = height.sort((a, b) => b - a); - - for (let i = 0; i < height.length; i++) { - peopledct[height[i]] = peopledct[height[i]].sort((a, b) => a[0] - b[0]); - for (el of peopledct[height[i]]) { - res.splice(el[0], 0, people[el[1]]); - } - } - return res; -}; - -console.log(reconstructQueue([[7, 0], [4, 4], [7, 1], [5, 0], [6, 1], [5, 2]])); diff --git a/406.queue-reconstruction-by-height.js b/406.queue-reconstruction-by-height.js new file mode 100644 index 00000000..8ef2a8d8 --- /dev/null +++ b/406.queue-reconstruction-by-height.js @@ -0,0 +1,15 @@ +/** + * @param {number[][]} people + * @return {number[][]} + */ +const reconstructQueue = function (people) { + const h = 0 + const k = 1 + people.sort((a, b) => (a[h] == b[h] ? a[k] - b[k] : b[h] - a[h])) + let queue = [] + for (let person of people) { + queue.splice(person[k], 0, person) + } + return queue +} + diff --git a/407-trapping-rain-water-ii.js b/407-trapping-rain-water-ii.js deleted file mode 100644 index 21892090..00000000 --- a/407-trapping-rain-water-ii.js +++ /dev/null @@ -1,325 +0,0 @@ -/** - * @param {number[][]} heightMap - * @return {number} - */ - -const trapRainWater = function (heightMap) { - const pq = new PriorityQueue((a, b) => a[2] < b[2]) - const m = heightMap.length, n = heightMap[0].length - - const visited = Array.from({ length: m }, () => Array(n).fill(false)) - - for(let i = 0; i < m; i++) { - visited[i][0] = visited[i][n - 1] = true - pq.push([i, 0, heightMap[i][0]]) - pq.push([i, n - 1, heightMap[i][n - 1]]) - } - for(let j = 1; j < n - 1; j++) { - visited[0][j] = visited[m - 1][j] = true - pq.push([0, j, heightMap[0][j]], [m - 1, j, heightMap[m - 1][j]]) - } - - let res = 0 - const dirs = [[-1, 0], [1, 0], [0, 1], [0, -1]] - while(!pq.isEmpty()) { - const cur = pq.pop() - const [r, c, h] = cur - for(let dir of dirs) { - const newR = r + dir[0], newC = c + dir[1] - if(newR < 0 || newR >= m || newC < 0 || newC >= n || visited[newR][newC]) continue - visited[newR][newC] = true - res += Math.max(0, h - heightMap[newR][newC]) - pq.push([newR, newC, Math.max(h, heightMap[newR][newC])]) - } - } - - return res - -} -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - - - -// another - -/** - * @param {number[][]} heightMap - * @return {number} - */ - -const trapRainWater = function (heightMap) { - const pq = new PriorityQueue((a, b) => a[2] < b[2]) - const visited = [] - for (let i = 0; i < heightMap.length; i++) { - visited[i] = [] - for (let j = 0; j < heightMap[0].length; j++) { - if ( - i > 0 && - i < heightMap.length - 1 && - j > 0 && - j < heightMap[0].length - 1 - ) - continue - pq.push([i, j, heightMap[i][j]]) - visited[i][j] = true - } - } - - let max = -Infinity, - count = 0 - while (!pq.isEmpty()) { - const cur = pq.pop() - if (cur[2] > max) max = cur[2] - check(cur[0], cur[1]) - } - function check(row, col) { - const step = [ - [-1, 0], - [1, 0], - [0, -1], - [0, 1], - ] - for (let i = 0; i < step.length; i++) { - let newR = row + step[i][0], - newC = col + step[i][1] - if ( - newR < 0 || - newR >= heightMap.length || - newC < 0 || - newC >= heightMap[0].length - ) - continue - if (visited[newR][newC]) continue - visited[newR][newC] = true - const newVal = heightMap[newR][newC] - if (newVal < max) { - count += max - newVal - check(newR, newC) - } else { - pq.push([newR, newC, newVal]) - } - } - } - - return count -} -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - - -// another - -/** - * @param {number[][]} heightMap - * @return {number} - */ -const trapRainWater = function(heightMap) { - - function PriorityQueueMin(){ - let heap=[null] - function swim(idx){ - if(idx<2)return - let k=Math.floor(idx/2) - if(heap[idx][2]-heap[k][2]<0){ - swap(heap,idx,k) - idx=k - swim(idx) - } - } - function sink(idx){ - let k=Math.floor(idx*2) - if(k>=heap.length)return - if(k0) k++ - if(heap[idx][2]-heap[k][2]>0){ - swap(heap,idx,k) - idx=k - sink(idx) - } - } - function swap(arr,i,j){ - let temp=arr[i] - arr[i]=arr[j] - arr[j]=temp - } - this.insert=function (v) { - heap.push(v) - swim(heap.length-1) - } - this.delMin=function () { - swap(heap,1,heap.length-1) - let min=heap.pop() - sink(1) - return min - } - this.isEmpty=function () { - return heap.length===1 - } - } - - let pq=new PriorityQueueMin() - let visited=[] - for(let i=0;i0 && i0 && jmax)max=cur[2] - check(cur[0],cur[1]) - } - function check(row,col){ - let step=[[-1,0],[1,0],[0,-1],[0,1]] - for(let i=0;i=heightMap.length) || (newC<0 || newC>=heightMap[0].length))continue - if(visited[newR][newC])continue - visited[newR][newC]=true - let newVal=heightMap[newR][newC] - if(newVal a[2] < b[2]) + const m = heightMap.length, n = heightMap[0].length + + const visited = Array.from({ length: m }, () => Array(n).fill(false)) + + for(let i = 0; i < m; i++) { + visited[i][0] = visited[i][n - 1] = true + pq.push([i, 0, heightMap[i][0]]) + pq.push([i, n - 1, heightMap[i][n - 1]]) + } + for(let j = 1; j < n - 1; j++) { + visited[0][j] = visited[m - 1][j] = true + pq.push([0, j, heightMap[0][j]], [m - 1, j, heightMap[m - 1][j]]) + } + + let res = 0 + const dirs = [[-1, 0], [1, 0], [0, 1], [0, -1]] + while(!pq.isEmpty()) { + const cur = pq.pop() + const [r, c, h] = cur + for(let dir of dirs) { + const newR = r + dir[0], newC = c + dir[1] + if(newR < 0 || newR >= m || newC < 0 || newC >= n || visited[newR][newC]) continue + visited[newR][newC] = true + res += Math.max(0, h - heightMap[newR][newC]) + pq.push([newR, newC, Math.max(h, heightMap[newR][newC])]) + } + } + + return res + +} +class PriorityQueue { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + + + diff --git a/408-valid-word-abbreviation.js b/408-valid-word-abbreviation.js deleted file mode 100644 index c9b27e3f..00000000 --- a/408-valid-word-abbreviation.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * @param {string} word - * @param {string} abbr - * @return {boolean} - */ -const validWordAbbreviation = (word, abbr) => { - if (word == null || abbr == null) return false - let i = 0 - let j = 0 - const len = word.length - const aLen = abbr.length - while (i < len && j < aLen) { - if (isNum(abbr[j])) { - if (abbr[j] === '0') return false - let n = 0 - while (j < aLen && isNum(abbr[j])) { - n = n * 10 + Number(abbr[j]) - j++ - } - i += n - } else { - if (word[i] !== abbr[j]) return false - i++ - j++ - } - } - return i === word.length && j === aLen -} -const isNum = c => !isNaN(c) - -// another - -/** - * @param {string} word - * @param {string} abbr - * @return {boolean} - */ -const validWordAbbreviation = (word, abbr) => { - let i = 0, - j = 0 - while (i < word.length && j < abbr.length) { - if (word.charAt(i) === abbr.charAt(j)) { - ++i - ++j - continue - } - if (abbr.charAt(j) <= '0' || abbr.charAt(j) > '9') { - return false - } - let start = j - while (j < abbr.length && abbr.charAt(j) >= '0' && abbr.charAt(j) <= '9') { - ++j - } - let num = +abbr.slice(start, j) - i += num - } - return i == word.length && j == abbr.length -} diff --git a/408.valid-word-abbreviation.js b/408.valid-word-abbreviation.js new file mode 100644 index 00000000..4e073ad0 --- /dev/null +++ b/408.valid-word-abbreviation.js @@ -0,0 +1,30 @@ +/** + * @param {string} word + * @param {string} abbr + * @return {boolean} + */ +const validWordAbbreviation = (word, abbr) => { + if (word == null || abbr == null) return false + let i = 0 + let j = 0 + const len = word.length + const aLen = abbr.length + while (i < len && j < aLen) { + if (isNum(abbr[j])) { + if (abbr[j] === '0') return false + let n = 0 + while (j < aLen && isNum(abbr[j])) { + n = n * 10 + Number(abbr[j]) + j++ + } + i += n + } else { + if (word[i] !== abbr[j]) return false + i++ + j++ + } + } + return i === word.length && j === aLen +} +const isNum = c => !isNaN(c) + diff --git a/409-longest-palindrome.js b/409-longest-palindrome.js deleted file mode 100755 index 0d67ad8a..00000000 --- a/409-longest-palindrome.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const longestPalindrome = function (s) { - const set = new Set() - let counter = 0 - for (let i = 0; i < s.length; i++) { - const currentChar = s[i] - if (set.has(currentChar)) { - counter++ - set.delete(currentChar) - } else { - set.add(currentChar) - } - } - counter *= 2 - if (set.size > 0) counter++ - return counter -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const longestPalindrome = function(s) { - const hash = {}; - let c; - for (let i = 0; i < s.length; i++) { - c = s.charAt(i); - if (hash.hasOwnProperty(c)) { - hash[c] += 1; - } else { - hash[c] = 1; - } - } - let res = 0; - let val; - for (let k in hash) { - if (hash.hasOwnProperty(k)) { - val = hash[k]; - res += Math.floor(val / 2) * 2; - if (res % 2 === 0 && val % 2 === 1) { - res += 1; - } - } - } - - return res; -}; diff --git a/409.longest-palindrome.js b/409.longest-palindrome.js new file mode 100644 index 00000000..9feb4709 --- /dev/null +++ b/409.longest-palindrome.js @@ -0,0 +1,21 @@ +/** + * @param {string} s + * @return {number} + */ +const longestPalindrome = function (s) { + const set = new Set() + let counter = 0 + for (let i = 0; i < s.length; i++) { + const currentChar = s[i] + if (set.has(currentChar)) { + counter++ + set.delete(currentChar) + } else { + set.add(currentChar) + } + } + counter *= 2 + if (set.size > 0) counter++ + return counter +} + diff --git a/41-first-missing-positive.js b/41-first-missing-positive.js deleted file mode 100644 index fa054946..00000000 --- a/41-first-missing-positive.js +++ /dev/null @@ -1,99 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const firstMissingPositive = function(nums) { - if(nums.length === 0) return 1 - const arr = [] - let max = Number.MIN_SAFE_INTEGER - for(let i = 0, len = nums.length; i < len; i++) { - if(nums[i] > 0) arr[nums[i]] = nums[i] - if(nums[i] > max) max = nums[i] - } - for(let i = 1; i < max; i++) { - if(arr[i] == null) return i - } - return max < 0 ? 1 : max + 1 -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -function firstMissingPositive(nums) { - const n = nums.length - for (let i = 0; i < n; i++) { - while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] !== nums[i]) - swap(nums, i, nums[i] - 1) - } - - for (let i = 0; i < n; i++) { - if (nums[i] !== i + 1) return i + 1 - } - return n + 1 -} - -function swap(arr, i, j) { - const tmp = arr[i] - arr[i] = arr[j] - arr[j] = tmp -} - - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const firstMissingPositive = function(nums) { - const n = nums.length - for(let i = 0; i < n; i++) { - while(nums[i] < n && nums[nums[i] - 1] !== nums[i]) { - swap(nums, i, nums[i] - 1) - } - } - - for(let i = 0; i < n; i++) { - if(nums[i] !== i + 1) return i + 1 - } - - return n + 1 -}; - -function swap(arr, i, j) { - const tmp = arr[i] - arr[i] = arr[j] - arr[j] = tmp -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const firstMissingPositive = function(nums) { - const n = nums.length - for(let i = 0; i < n; i++) { - while(nums[i] > 0 && nums[i] !== nums[nums[i] - 1] && nums[i] <= n) { - swap(i, nums[i] - 1) - } - } - - // console.log(nums) - for(let i = 0; i < n; i++) { - if(nums[i] !== i + 1) return i + 1 - } - - return n + 1 - - - function swap(i, j) { - const tmp = nums[j] - nums[j] = nums[i] - nums[i] = tmp - } -}; diff --git a/41.first-missing-positive.js b/41.first-missing-positive.js new file mode 100644 index 00000000..ed968b52 --- /dev/null +++ b/41.first-missing-positive.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const firstMissingPositive = function(nums) { + if(nums.length === 0) return 1 + const arr = [] + let max = Number.MIN_SAFE_INTEGER + for(let i = 0, len = nums.length; i < len; i++) { + if(nums[i] > 0) arr[nums[i]] = nums[i] + if(nums[i] > max) max = nums[i] + } + for(let i = 1; i < max; i++) { + if(arr[i] == null) return i + } + return max < 0 ? 1 : max + 1 +}; + diff --git a/410-split-array-largest-sum.js b/410-split-array-largest-sum.js deleted file mode 100644 index a48f3f1e..00000000 --- a/410-split-array-largest-sum.js +++ /dev/null @@ -1,141 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} m - * @return {number} - */ -function doable(nums, cuts, max) { - let acc = 0 - for(let num of nums) { - if(num > max) return false - else if(acc + num <= max) acc += num - else { - --cuts; - acc = num; - if(cuts < 0) return false - } - } - return true -} - - -function splitArray(nums, m) { - let left = 0 - let right = 0 - for(let num of nums) { - left = Math.max(left, num) - right += num - } - while(left < right) { - let mid = Math.floor(left + (right - left) / 2) - if(doable(nums, m - 1, mid)) right = mid - else left = mid + 1 - } - return left -} - - -/** - * @param {number[]} nums - * @param {number} m - * @return {number} - */ -const splitArray = function(nums, m) { - let l = 0, - r = 0 - for (let el of nums) { - if (el > l) l = el - r += el - } - while (l < r) { - let mid = Math.floor((l + r) / 2) - if (numOfSubArrLessOrEqualThanM(nums, mid, m)) r = mid - else l = mid + 1 - } - return l -} - -function numOfSubArrLessOrEqualThanM(nums, target, m) { - let sum = 0, - count = 1 - for (let el of nums) { - sum += el - if (sum > target) { - sum = el - count++ - } - if (count > m) return false - } - return true -} - -/** - -Introduction to this problem: -We can break this problem into two smaller problems: - -Given an array (A), number of cuts (CUTS), and the Largest sum of sub-arrays (MAX). Can you use at most CUTS cuts to segment array A into CUTS + 1 sub-arrays, such that the sum of each sub-array is smaller or equal to MAX? -Given a lower bound (left), an upper bound (right), an unknown bool array (B), and an API uses i as input and tells you whether B[i] is true. If we know there exists an index k, that B[i] is false when i < k, and B[i] is true when i >= k. What is the fastest way to find this k (the lower bound)? -Solution to the first sub-problem (Skip this part if you already knew how to solve 1st sub-problem): -For the first question, we can follow these steps: - -For each element in the array, if its value is larger than MAX, we know it's not possible to cut this array into groups that the sum of all groups are smaller than MAX. (Reason is straightforward, if A is [10, 2, 3, 5] and MAX is 6, even you have 3 cuts by which you can cut A as [[10], [2], [3], [5]], the group containing 10 will still be larger than 6). -Use greedy algorithm to cut A. Use an accumulator ACC to store the sum of the currently processed group, and process elements in A one by one. For each element num, if we add num with ACC and the new sum is still no larger than MAX, we update ACC to ACC + num, which means we can merge num into the current group. If not, we must use a cut before num to segment this array, then num will be the first element in the new group. -If we didn't go through A but already used up all cuts, then it's not possible only using CUTS cuts to segment this array into groups to make sure sum of each sub-array is smaller than MAX. Otherwise, if we can reach the end of A with cuts left (or use exactly CUTS cuts). It's possible to do so. -Then the first question is solved. - -Solution to the second sub-problem(Skip this part if you already knew how to solve 2nd sub-problem): -The array B will be something like [false, false, ..., false, true, true, ..., true]. We want to find the index of the first true. -Use binary search to find this k. Keep a value mid, mid = (left + right) / 2. If B[mid] = false, then move the search range to the upper half of the original search range, a.k.a left = mid + 1, otherwise move search range to the lower half, a.k.a right = mid. -Why this algorithm is correct... -No matter how we cut the array A, the Largest sum of sub-arrays will fall into a range [left, right]. Left is the value of the largest element in this array. right is the sum of this array. (e.g., Given array [1, 2, 3, 4, 5], if we have 4 cuts and cut it as [[1], [2], [3], [4], [5]], the Largest sum of sub-arrays is 5, it cannot be smaller. And if we have 0 cut, and the only sub-array is [[1, 2, 3, 4, 5]], the Largest sum of sub-arrays is 15, it cannot be larger). -However, we cannot decide the number of cuts (CUTS), this is an given constraint. But we know there must be a magic number k, which is the smallest value of the Largest sum of sub-arrays when given CUTS cuts. When the Largest sum of sub-arrays is larger than k, we can always find a way to cut A within CUTS cuts. When the Largest sum of sub-arrays is smaller than k, there is no way to do this. -Example -For example, given array A [1, 2, 3, 4, 5]. We can use 2 cuts. - -No matter how many cuts are allowed, the range of the possible value of the Largest sum of sub-arrays is [5, 15]. -When given 2 cuts, we can tell the magic number k here is 6, the result of segmentation is [[1, 2, 3], [4], [5]]. -When Largest sum of sub-arrays is in range [6, 15], we can always find a way to cut this array within two cuts. You can have a try. -However, when Largest sum of sub-arrays is in range [5, 5], there is no way to do this. -This mapped this problem into the second sub-problem. Bool array B here is [5:false, 6:true, 7:true, 8:true, ..., 15:true]. We want to find the index i of the first true in B, which is the answer of this entire question, and by solving the first sub-problem, we have an API that can tell us given an i (Largest sum of sub-arrays), whether B[i] is true (whether we can find a way to cut A to satisfy the constraint). - */ - - -// another - -/** - * @param {number[]} nums - * @param {number} m - * @return {number} - */ -const splitArray = (nums, m) => { - let max = -Infinity, sum = 0 - for(let num of nums) { - sum += num - max = Math.max(max, num) - } - if (m === 1) return sum - let l = max, r = sum - while(l < r) { - let mid = l + ((r - l) >> 1) - if(valid(mid, nums, m)) { - r = mid - } else { - l = mid + 1 - } - } - return l -} - -function valid(target, nums, m) { - let cnt = 1, sum = 0 - for(let num of nums) { - sum += num - if(sum > target) { - cnt++ - sum = num - if(cnt > m) return false - } - } - - return true -} diff --git a/410.split-array-largest-sum.js b/410.split-array-largest-sum.js new file mode 100644 index 00000000..98ed5f8b --- /dev/null +++ b/410.split-array-largest-sum.js @@ -0,0 +1,102 @@ +/** + * @param {number[]} nums + * @param {number} m + * @return {number} + */ +function doable(nums, cuts, max) { + let acc = 0 + for(let num of nums) { + if(num > max) return false + else if(acc + num <= max) acc += num + else { + --cuts; + acc = num; + if(cuts < 0) return false + } + } + return true +} + + +function splitArray(nums, m) { + let left = 0 + let right = 0 + for(let num of nums) { + left = Math.max(left, num) + right += num + } + while(left < right) { + let mid = Math.floor(left + (right - left) / 2) + if(doable(nums, m - 1, mid)) right = mid + else left = mid + 1 + } + return left +} + + +/** + * @param {number[]} nums + * @param {number} m + * @return {number} + */ +const splitArray = function(nums, m) { + let l = 0, + r = 0 + for (let el of nums) { + if (el > l) l = el + r += el + } + while (l < r) { + let mid = Math.floor((l + r) / 2) + if (numOfSubArrLessOrEqualThanM(nums, mid, m)) r = mid + else l = mid + 1 + } + return l +} + +function numOfSubArrLessOrEqualThanM(nums, target, m) { + let sum = 0, + count = 1 + for (let el of nums) { + sum += el + if (sum > target) { + sum = el + count++ + } + if (count > m) return false + } + return true +} + +/** + +Introduction to this problem: +We can break this problem into two smaller problems: + +Given an array (A), number of cuts (CUTS), and the Largest sum of sub-arrays (MAX). Can you use at most CUTS cuts to segment array A into CUTS + 1 sub-arrays, such that the sum of each sub-array is smaller or equal to MAX? +Given a lower bound (left), an upper bound (right), an unknown bool array (B), and an API uses i as input and tells you whether B[i] is true. If we know there exists an index k, that B[i] is false when i < k, and B[i] is true when i >= k. What is the fastest way to find this k (the lower bound)? +Solution to the first sub-problem (Skip this part if you already knew how to solve 1st sub-problem): +For the first question, we can follow these steps: + +For each element in the array, if its value is larger than MAX, we know it's not possible to cut this array into groups that the sum of all groups are smaller than MAX. (Reason is straightforward, if A is [10, 2, 3, 5] and MAX is 6, even you have 3 cuts by which you can cut A as [[10], [2], [3], [5]], the group containing 10 will still be larger than 6). +Use greedy algorithm to cut A. Use an accumulator ACC to store the sum of the currently processed group, and process elements in A one by one. For each element num, if we add num with ACC and the new sum is still no larger than MAX, we update ACC to ACC + num, which means we can merge num into the current group. If not, we must use a cut before num to segment this array, then num will be the first element in the new group. +If we didn't go through A but already used up all cuts, then it's not possible only using CUTS cuts to segment this array into groups to make sure sum of each sub-array is smaller than MAX. Otherwise, if we can reach the end of A with cuts left (or use exactly CUTS cuts). It's possible to do so. +Then the first question is solved. + +Solution to the second sub-problem(Skip this part if you already knew how to solve 2nd sub-problem): +The array B will be something like [false, false, ..., false, true, true, ..., true]. We want to find the index of the first true. +Use binary search to find this k. Keep a value mid, mid = (left + right) / 2. If B[mid] = false, then move the search range to the upper half of the original search range, a.k.a left = mid + 1, otherwise move search range to the lower half, a.k.a right = mid. +Why this algorithm is correct... +No matter how we cut the array A, the Largest sum of sub-arrays will fall into a range [left, right]. Left is the value of the largest element in this array. right is the sum of this array. (e.g., Given array [1, 2, 3, 4, 5], if we have 4 cuts and cut it as [[1], [2], [3], [4], [5]], the Largest sum of sub-arrays is 5, it cannot be smaller. And if we have 0 cut, and the only sub-array is [[1, 2, 3, 4, 5]], the Largest sum of sub-arrays is 15, it cannot be larger). +However, we cannot decide the number of cuts (CUTS), this is an given constraint. But we know there must be a magic number k, which is the smallest value of the Largest sum of sub-arrays when given CUTS cuts. When the Largest sum of sub-arrays is larger than k, we can always find a way to cut A within CUTS cuts. When the Largest sum of sub-arrays is smaller than k, there is no way to do this. +Example +For example, given array A [1, 2, 3, 4, 5]. We can use 2 cuts. + +No matter how many cuts are allowed, the range of the possible value of the Largest sum of sub-arrays is [5, 15]. +When given 2 cuts, we can tell the magic number k here is 6, the result of segmentation is [[1, 2, 3], [4], [5]]. +When Largest sum of sub-arrays is in range [6, 15], we can always find a way to cut this array within two cuts. You can have a try. +However, when Largest sum of sub-arrays is in range [5, 5], there is no way to do this. +This mapped this problem into the second sub-problem. Bool array B here is [5:false, 6:true, 7:true, 8:true, ..., 15:true]. We want to find the index i of the first true in B, which is the answer of this entire question, and by solving the first sub-problem, we have an API that can tell us given an i (Largest sum of sub-arrays), whether B[i] is true (whether we can find a way to cut A to satisfy the constraint). + */ + + diff --git a/411-minimum-unique-word-abbreviation.js b/411.minimum-unique-word-abbreviation.js similarity index 100% rename from 411-minimum-unique-word-abbreviation.js rename to 411.minimum-unique-word-abbreviation.js diff --git a/412-fizz-buzz.js b/412-fizz-buzz.js deleted file mode 100755 index 9eca78f2..00000000 --- a/412-fizz-buzz.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @param {number} n - * @return {string[]} - */ -const fizzBuzz = function(n) { - const res = []; - for (let i = 1; i <= n; i++) { - res.push(single(i)); - } - - return res; -}; - -function single(num) { - let str = ""; - if (num % 3 === 0) { - str += "Fizz"; - } - if (num % 5 === 0) { - str += "Buzz"; - } - if (str === "") { - str += num; - } - return str; -} - -console.log(fizzBuzz(15)); diff --git a/412.fizz-buzz.js b/412.fizz-buzz.js new file mode 100644 index 00000000..2891d92c --- /dev/null +++ b/412.fizz-buzz.js @@ -0,0 +1,28 @@ +/** + * @param {number} n + * @return {string[]} + */ +const fizzBuzz = function(n) { + const res = []; + for (let i = 1; i <= n; i++) { + res.push(single(i)); + } + + return res; +}; + +function single(num) { + let str = ""; + if (num % 3 === 0) { + str += "Fizz"; + } + if (num % 5 === 0) { + str += "Buzz"; + } + if (str === "") { + str += num; + } + return str; +} + +console.log(fizzBuzz(15)); diff --git a/413-arithmetic-slices.js b/413-arithmetic-slices.js deleted file mode 100755 index ff307a6c..00000000 --- a/413-arithmetic-slices.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @param {number[]} A - * @return {number} - */ -const numberOfArithmeticSlices = function(A) { - const arr = []; - let count = 0; - for (let i = 1; i < A.length - 1; i++) { - if (A[i] - A[i - 1] === A[i + 1] - A[i]) { - count += 1; - } else { - arr.push(count); - count = 0; - } - } - arr.push(count); - return arr.reduce((ac, el) => ac + calc(el), 0); -}; - -function calc(num) { - return (num * (num + 1)) / 2; -} - -console.log(numberOfArithmeticSlices([1, 2, 3, 4])); diff --git a/413.arithmetic-slices.js b/413.arithmetic-slices.js new file mode 100644 index 00000000..c5d85363 --- /dev/null +++ b/413.arithmetic-slices.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} A + * @return {number} + */ +const numberOfArithmeticSlices = function(A) { + const arr = []; + let count = 0; + for (let i = 1; i < A.length - 1; i++) { + if (A[i] - A[i - 1] === A[i + 1] - A[i]) { + count += 1; + } else { + arr.push(count); + count = 0; + } + } + arr.push(count); + return arr.reduce((ac, el) => ac + calc(el), 0); +}; + +function calc(num) { + return (num * (num + 1)) / 2; +} + +console.log(numberOfArithmeticSlices([1, 2, 3, 4])); diff --git a/414-third-maximum-number.js b/414.third-maximum-number.js similarity index 100% rename from 414-third-maximum-number.js rename to 414.third-maximum-number.js diff --git a/415-add-strings.js b/415-add-strings.js deleted file mode 100755 index cf2cad2a..00000000 --- a/415-add-strings.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @param {string} num1 - * @param {string} num2 - * @return {string} - */ -const addStrings = function(num1, num2) { - let sb = ""; - let carry = 0; - for ( - let i = num1.length - 1, j = num2.length - 1; - i >= 0 || j >= 0 || carry == 1; - i--, j-- - ) { - let x = i < 0 ? 0 : +num1.charAt(i); - let y = j < 0 ? 0 : +num2.charAt(j); - sb = (+(x + y + carry) % 10) + sb; - carry = x + y + carry >= 10 ? 1 : 0; - } - return sb; -}; diff --git a/415.add-strings.js b/415.add-strings.js new file mode 100644 index 00000000..eec7a034 --- /dev/null +++ b/415.add-strings.js @@ -0,0 +1,20 @@ +/** + * @param {string} num1 + * @param {string} num2 + * @return {string} + */ +const addStrings = function(num1, num2) { + let sb = ""; + let carry = 0; + for ( + let i = num1.length - 1, j = num2.length - 1; + i >= 0 || j >= 0 || carry == 1; + i--, j-- + ) { + let x = i < 0 ? 0 : +num1.charAt(i); + let y = j < 0 ? 0 : +num2.charAt(j); + sb = (+(x + y + carry) % 10) + sb; + carry = x + y + carry >= 10 ? 1 : 0; + } + return sb; +}; diff --git a/416-partition-equal-subset-sum.js b/416-partition-equal-subset-sum.js deleted file mode 100644 index c118c8e6..00000000 --- a/416-partition-equal-subset-sum.js +++ /dev/null @@ -1,114 +0,0 @@ -/** - * @param {number[]} nums - * @return {boolean} - */ -const canPartition = function(nums) { - let sum = 0 - for(let num of nums) { - sum += num - } - - if(sum & 1 === 1) { - return false - } - - sum /= 2 - let n = nums.length - const dp = Array.from(new Array(n+1), () => []) - for(let i = 0; i < dp.length; i++) { - dp[i] = new Array(sum+1).fill(false) - } - dp[0][0] = true - for(let i = 1; i < n + 1; i++) { - dp[i][0] = true - } - for(let j = 1; j < sum + 1; j++) { - dp[0][j] = false - } - for(let i = 1; i < n + 1; i++) { - for(let j = 1; j < sum + 1; j++) { - if(j >= nums[i - 1]) { - dp[i][j] = (dp[i -1][j] || dp[i - 1][j - nums[i - 1]]) - } - } - } - return dp[n][sum] -}; - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -const canPartition = function(nums) { - if (nums.length < 2) return false - - const total = nums.reduce((a, c) => a + c) - if (total % 2 !== 0) return false - - nums.sort((a, b) => b - a) - const target = total / 2 - - if (nums[0] > target) return false - return findCombination(nums, target, 0) -} - -function findCombination(nums, target, start) { - if (target === 0) { - return true - } else { - for (let i = start; i < nums.length; i++) { - if (nums[i] <= target) { - if (findCombination(nums, target - nums[i], i + 1)) { - return true - } - } - } - return false - } -} - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -function helper(nums, target, pos) { - for (let i = pos; i <= nums.length; i++) { - if (i != pos && nums[i] == nums[i - 1]) continue - if (nums[i] === target) return true - if (nums[i] > target) break - if (helper(nums, target - nums[i], i + 1)) return true - } - return false -} -const canPartition = function(nums) { - const sum = nums.reduce((sum, n) => (sum += n), 0) / 2 - if (sum % 1 != 0) { - return false - } - - return helper(nums, sum, 0) -} - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -const canPartition = function (nums) { - const sumA = nums.reduce((acc, curr) => acc + curr, 0) - if (sumA % 2) return false - let row = 1n << BigInt(sumA / 2) - for (const weight of nums) row = row | (row >> BigInt(weight)) - /* - check the the column corresponding to my target by bitwise ANDing - it with just 1,so if the first bit is 1, - it will return true, otherwise false - */ - return row & 1n -} - diff --git a/416.partition-equal-subset-sum.js b/416.partition-equal-subset-sum.js new file mode 100644 index 00000000..6aed0c9e --- /dev/null +++ b/416.partition-equal-subset-sum.js @@ -0,0 +1,37 @@ +/** + * @param {number[]} nums + * @return {boolean} + */ +const canPartition = function(nums) { + let sum = 0 + for(let num of nums) { + sum += num + } + + if(sum & 1 === 1) { + return false + } + + sum /= 2 + let n = nums.length + const dp = Array.from(new Array(n+1), () => []) + for(let i = 0; i < dp.length; i++) { + dp[i] = new Array(sum+1).fill(false) + } + dp[0][0] = true + for(let i = 1; i < n + 1; i++) { + dp[i][0] = true + } + for(let j = 1; j < sum + 1; j++) { + dp[0][j] = false + } + for(let i = 1; i < n + 1; i++) { + for(let j = 1; j < sum + 1; j++) { + if(j >= nums[i - 1]) { + dp[i][j] = (dp[i -1][j] || dp[i - 1][j - nums[i - 1]]) + } + } + } + return dp[n][sum] +}; + diff --git a/417-pacific-atlantic-water-flow.js b/417.pacific-atlantic-water-flow.js similarity index 100% rename from 417-pacific-atlantic-water-flow.js rename to 417.pacific-atlantic-water-flow.js diff --git a/418-sentence-screen-fitting.js b/418.sentence-screen-fitting.js similarity index 100% rename from 418-sentence-screen-fitting.js rename to 418.sentence-screen-fitting.js diff --git a/42-trapping-rain-water.js b/42-trapping-rain-water.js deleted file mode 100644 index 1b31b415..00000000 --- a/42-trapping-rain-water.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @param {number[]} height - * @return {number} - */ -const trap = function(height) { - - let s = height.length - if(s === 0) return 0 - let res = 0 - const left_max = [height[0]] - const right_max = [] - right_max[s - 1] = height[s - 1] - for(let i = 1; i < s; i++) { - left_max[i] = Math.max(height[i], left_max[i - 1]) - } - for(let i = s - 2; i >= 0; i--) { - right_max[i] = Math.max(height[i], right_max[i + 1]) - } - for(let i = 1; i < s - 1; i++) { - res += Math.min(left_max[i], right_max[i]) - height[i] - } - return res -}; - -// another - -/** - * @param {number[]} height - * @return {number} - */ -const trap = function(height) { - const len = height.length - if (len === 0) return 0 - const leftMax = [height[0]] - const rightMax = [] - rightMax[len - 1] = height[len - 1] - for (let i = len - 2; i >= 0; i--) { - rightMax[i] = Math.max(height[i], rightMax[i + 1]) - } - let res = 0 - for (let i = 1; i < len; i++) { - leftMax[i] = Math.max(height[i], leftMax[i - 1]) - res += Math.min(leftMax[i], rightMax[i]) - height[i] - } - return res -} - -// another - -/** - * @param {number[]} height - * @return {number} - */ -const trap = function(height) { - const n = height.length - let l = 0, r = n - 1, res = 0, leftMax = 0, rightMax = 0 - while(l <= r) { - if(height[l] <= height[r]) { - if(height[l] >= leftMax) leftMax = height[l] - else res += leftMax - height[l] - l++ - } else { - if(height[r] >= rightMax) rightMax = height[r] - else res += rightMax - height[r] - r-- - } - } - return res -}; - -// another - -/** - * @param {number[]} height - * @return {number} - */ -const trap = function(height) { - const n = height.length - if(n === 0) return 0 - let res = 0 - let l = 0, r = n - 1, leftMax = height[l], rightMax = height[r] - while(l < r) { - if(height[l] <= height[r]) { - l++ - leftMax = Math.max(leftMax, height[l]) - res += (leftMax - height[l]) - } else { - r-- - rightMax = Math.max(rightMax, height[r]) - res += rightMax - height[r] - } - } - - return res -}; - -// another - -/** - * @param {number[]} height - * @return {number} - */ -const trap = function(height) { - const n = height.length, { max } = Math - let res = 0, l = 0, r = n - 1, leftMax = height[0], rightMax = height[n - 1] - while(l <= r) { - if(leftMax < rightMax) { - leftMax = max(leftMax, height[l]) - res += leftMax - height[l] - l++ - } else { - rightMax = max(rightMax, height[r]) - res += rightMax - height[r] - r-- - } - } - - return res -}; diff --git a/42.trapping-rain-water.js b/42.trapping-rain-water.js new file mode 100644 index 00000000..73616a94 --- /dev/null +++ b/42.trapping-rain-water.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} height + * @return {number} + */ +const trap = function(height) { + + let s = height.length + if(s === 0) return 0 + let res = 0 + const left_max = [height[0]] + const right_max = [] + right_max[s - 1] = height[s - 1] + for(let i = 1; i < s; i++) { + left_max[i] = Math.max(height[i], left_max[i - 1]) + } + for(let i = s - 2; i >= 0; i--) { + right_max[i] = Math.max(height[i], right_max[i + 1]) + } + for(let i = 1; i < s - 1; i++) { + res += Math.min(left_max[i], right_max[i]) - height[i] + } + return res +}; + diff --git a/420-strong-password-checker.js b/420.strong-password-checker.js similarity index 100% rename from 420-strong-password-checker.js rename to 420.strong-password-checker.js diff --git a/421-maximum-xor-of-two-numbers-in-an-array.js b/421-maximum-xor-of-two-numbers-in-an-array.js deleted file mode 100644 index 1e71476c..00000000 --- a/421-maximum-xor-of-two-numbers-in-an-array.js +++ /dev/null @@ -1,135 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const findMaximumXOR = function(nums) { - let res = 0, mask = 0 - for(let i = 31; i >= 0; i--) { - mask = mask | (1 << i) - const set = new Set() - for(let e of nums) set.add(e & mask) - const tmp = res | (1 << i) - for(let e of set) { - if(set.has(e ^ tmp)) { - res = tmp - break - } - } - } - return res -}; - -// another - -/* - -This algorithm's idea is: -to iteratively determine what would be each bit of the final result from left to right. -And it narrows down the candidate group iteration by iteration. e.g. assume input are a,b,c,d,...z, 26 integers in total. -In first iteration, if you found that a, d, e, h, u differs on the MSB(most significant bit), -so you are sure your final result's MSB is set. Now in second iteration, -you try to see if among a, d, e, h, u there are at least two numbers make the 2nd MSB differs, -if yes, then definitely, the 2nd MSB will be set in the final result. -And maybe at this point the candidate group shinks from a,d,e,h,u to a, e, h. -Implicitly, every iteration, you are narrowing down the candidate group, -but you don't need to track how the group is shrinking, you only cares about the final result. - -*/ -/* - * @lc app=leetcode id=421 lang=javascript - * - * [421] Maximum XOR of Two Numbers in an Array - */ -/** - * @param {number[]} nums - * @return {number} - */ -const findMaximumXOR = function(nums) { - let maxResult = 0 - let mask = 0 - /*The maxResult is a record of the largest XOR we got so far. if it's 11100 at i = 2, it means - before we reach the last two bits, 11100 is the biggest XOR we have, and we're going to explore - whether we can get another two '1's and put them into maxResult - - This is a greedy part, since we're looking for the largest XOR, we start - from the very begining, aka, the 31st postition of bits. */ - for (let i = 31; i >= 0; i--) { - //The mask will grow like 100..000 , 110..000, 111..000, then 1111...111 - //for each iteration, we only care about the left parts - mask = mask | (1 << i) - - let set = new Set() - for (let num of nums) { - /* we only care about the left parts, for example, if i = 2, then we have - {1100, 1000, 0100, 0000} from {1110, 1011, 0111, 0010}*/ - let leftPartOfNum = num & mask - set.add(leftPartOfNum) - } - - // if i = 1 and before this iteration, the maxResult we have now is 1100, - // my wish is the maxResult will grow to 1110, so I will try to find a candidate - // which can give me the greedyTry; - let greedyTry = maxResult | (1 << i) - - for (let leftPartOfNum of set) { - //This is the most tricky part, coming from a fact that if a ^ b = c, then a ^ c = b; - // now we have the 'c', which is greedyTry, and we have the 'a', which is leftPartOfNum - // If we hope the formula a ^ b = c to be valid, then we need the b, - // and to get b, we need a ^ c, if a ^ c exisited in our set, then we're good to go - let anotherNum = leftPartOfNum ^ greedyTry - if (set.has(anotherNum)) { - maxResult = greedyTry - break - } - } - - // If unfortunately, we didn't get the greedyTry, we still have our max, - // So after this iteration, the max will stay at 1100. - } - return maxResult -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const findMaximumXOR = function (nums) { - if (nums == null || nums.length == 0) { - return 0 - } - const root = new Trie() - for (let num of nums) { - let curNode = root - for (let i = 31; i >= 0; i--) { - let curBit = (num >>> i) & 1 - if (curNode.children[curBit] == null) { - curNode.children[curBit] = new Trie() - } - curNode = curNode.children[curBit] - } - } - let max = Number.MIN_VALUE - for (let num of nums) { - let curNode = root - let curSum = 0 - for (let i = 31; i >= 0; i--) { - let curBit = (num >>> i) & 1 - if (curNode.children[curBit ^ 1] != null) { - curSum += 1 << i - curNode = curNode.children[curBit ^ 1] - } else { - curNode = curNode.children[curBit] - } - } - max = Math.max(curSum, max) - } - return max -} - -class Trie { - constructor() { - this.children = {} - } -} diff --git a/421.maximum-xor-of-two-numbers-in-an-array.js b/421.maximum-xor-of-two-numbers-in-an-array.js new file mode 100644 index 00000000..bbfd9b88 --- /dev/null +++ b/421.maximum-xor-of-two-numbers-in-an-array.js @@ -0,0 +1,21 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const findMaximumXOR = function(nums) { + let res = 0, mask = 0 + for(let i = 31; i >= 0; i--) { + mask = mask | (1 << i) + const set = new Set() + for(let e of nums) set.add(e & mask) + const tmp = res | (1 << i) + for(let e of set) { + if(set.has(e ^ tmp)) { + res = tmp + break + } + } + } + return res +}; + diff --git a/422-valid-word-square.js b/422.valid-word-square.js similarity index 100% rename from 422-valid-word-square.js rename to 422.valid-word-square.js diff --git a/423-reconstruct-original-digits-from-english.js b/423.reconstruct-original-digits-from-english.js similarity index 100% rename from 423-reconstruct-original-digits-from-english.js rename to 423.reconstruct-original-digits-from-english.js diff --git a/424-longest-repeating-character-replacement.js b/424-longest-repeating-character-replacement.js deleted file mode 100755 index 7a49780e..00000000 --- a/424-longest-repeating-character-replacement.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @param {string} s - * @param {number} k - * @return {number} - */ -const characterReplacement = function(s, k) { - const len = s.length; - const count = Array(26).fill(0); - let start = 0, - maxCount = 0, - maxLength = 0; - const ca = "A".charCodeAt(0); - for (let end = 0; end < len; end++) { - maxCount = Math.max(maxCount, ++count[s.charCodeAt(end) - ca]); - if (end - start + 1 - maxCount > k) { - count[s.charCodeAt(start) - ca]--; - start++; - } - maxLength = Math.max(maxLength, end - start + 1); - } - return maxLength; -}; - -console.log(characterReplacement("ABAB", 2)); -console.log(characterReplacement("AABABBA", 1)); - - -// another - -/** - * @param {string} s - * @param {number} k - * @return {number} - */ -const characterReplacement = function (s, k) { - const freq = Array(26).fill(0), - n = s.length, - { max } = Math, - A = 'A'.charCodeAt(0) - let res = 0, - l = 0, - r = 0, - maxFreq = 0 - while (r < n) { - maxFreq = max(maxFreq, ++freq[s.charCodeAt(r) - A]) - if (r - l + 1 - maxFreq > k) { - freq[s.charCodeAt(l) - A]-- - l++ - } - res = max(res, r - l + 1) - r++ - } - - return res -} - diff --git a/424.longest-repeating-character-replacement.js b/424.longest-repeating-character-replacement.js new file mode 100644 index 00000000..20366639 --- /dev/null +++ b/424.longest-repeating-character-replacement.js @@ -0,0 +1,27 @@ +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +const characterReplacement = function(s, k) { + const len = s.length; + const count = Array(26).fill(0); + let start = 0, + maxCount = 0, + maxLength = 0; + const ca = "A".charCodeAt(0); + for (let end = 0; end < len; end++) { + maxCount = Math.max(maxCount, ++count[s.charCodeAt(end) - ca]); + if (end - start + 1 - maxCount > k) { + count[s.charCodeAt(start) - ca]--; + start++; + } + maxLength = Math.max(maxLength, end - start + 1); + } + return maxLength; +}; + +console.log(characterReplacement("ABAB", 2)); +console.log(characterReplacement("AABABBA", 1)); + + diff --git a/425-word-squares.js b/425-word-squares.js deleted file mode 100644 index 66c6d9e8..00000000 --- a/425-word-squares.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @param {string[]} words - * @return {string[][]} - */ -const wordSquares = function(words) { - const length = words[0].length - const createPrefixMap = function(words) { - const result = new Map() - for (let word of words) { - for (let i = 0; i < word.length - 1; ++i) { - const prefix = word.slice(0, i + 1) - const array = result.get(prefix) - if (array) { - array.push(word) - } else { - result.set(prefix, [word]) - } - } - } - return result - } - const backtracking = function(step, result, martix, wordsList) { - if (step === length) { - result.push([...martix]) - return - } - for (let word of wordsList) { - martix.push(word) - let prefix = '' - for (let i = 0; i < step + 1; ++i) { - prefix += martix[i][step + 1] - } - let newLists = dictMap.get(prefix) - newLists = newLists ? newLists : [] - backtracking(step + 1, result, martix, newLists) - martix.pop() - } - } - const result = [] - const dictMap = createPrefixMap(words) - backtracking(0, result, [], words) - return result -} - -// another - -/** - * @param {string[]} words - * @return {string[][]} - */ -const wordSquares = function(words) { - let result = [] - let trie = new Trie() - for (let word of words) { - trie.add(word) - } - - findWordSquare(result, [], trie) - return result -}; - -function findWordSquare (result, temp, trie) { - if (temp.length > 0 && temp.length === temp[0].length) { - result.push(temp) - return - } - - let prefix = '' - let j = temp.length - for (let i = 0; i < temp.length; i++) { - prefix += temp[i][j] - } - - let startWith = trie.startWith(prefix) - for (let word of startWith) { - findWordSquare(result, temp.concat([word]), trie) - } -} - -function Trie () { - this.isWord = false - this.children = new Map() -} - -Trie.prototype.add = function (word) { - let cur = this - for (let i = 0; i < word.length; i++) { - if (!cur.children.has(word[i])) { - cur.children.set(word[i], new Trie()) - } - cur = cur.children.get(word[i]) - } - cur.isWord = true -} - -Trie.prototype.startWith = function (prefix) { - let cur = this - for (let i = 0; i < prefix.length; i++) { - if (cur.children.has(prefix[i])) { - cur = cur.children.get(prefix[i]) - } else { - return [] - } - } - - let res = [] - const findWords = function (res, cur, str) { - if (!cur.isWord) { - for (let [key, val] of cur.children) { - findWords(res, val, str + key) - } - } else { - res.push(str) - } - } - - findWords(res, cur, prefix) - return res -} diff --git a/425.word-squares.js b/425.word-squares.js new file mode 100644 index 00000000..42e9e8bc --- /dev/null +++ b/425.word-squares.js @@ -0,0 +1,44 @@ +/** + * @param {string[]} words + * @return {string[][]} + */ +const wordSquares = function(words) { + const length = words[0].length + const createPrefixMap = function(words) { + const result = new Map() + for (let word of words) { + for (let i = 0; i < word.length - 1; ++i) { + const prefix = word.slice(0, i + 1) + const array = result.get(prefix) + if (array) { + array.push(word) + } else { + result.set(prefix, [word]) + } + } + } + return result + } + const backtracking = function(step, result, martix, wordsList) { + if (step === length) { + result.push([...martix]) + return + } + for (let word of wordsList) { + martix.push(word) + let prefix = '' + for (let i = 0; i < step + 1; ++i) { + prefix += martix[i][step + 1] + } + let newLists = dictMap.get(prefix) + newLists = newLists ? newLists : [] + backtracking(step + 1, result, martix, newLists) + martix.pop() + } + } + const result = [] + const dictMap = createPrefixMap(words) + backtracking(0, result, [], words) + return result +} + diff --git a/426-convert-binary-search-tree-to-sorted-doubly-linked-list.js b/426-convert-binary-search-tree-to-sorted-doubly-linked-list.js deleted file mode 100644 index a75ad8a8..00000000 --- a/426-convert-binary-search-tree-to-sorted-doubly-linked-list.js +++ /dev/null @@ -1,93 +0,0 @@ -/** - * // Definition for a Node. - * function Node(val, left, right) { - * this.val = val; - * this.left = left; - * this.right = right; - * }; - */ -/** - * @param {Node} root - * @return {Node} - */ -const treeToDoublyList = function(root) { - let head = null, tail = null; - const helper = (node) => { - if(!node) return; - helper(node.left); - if(!head) head = node; - if(tail) tail.right = node; - node.left = tail; - tail = node; - helper(node.right); - }; - helper(root); - if(head) { - head.left = tail; - tail.right = head; - } - return head; -}; - -// another - -/** - * @param {Node} root - * @return {Node} - */ -const treeToDoublyList = function(root) { - if(root === null) return null - const left = treeToDoublyList(root.left) - const right = treeToDoublyList(root.right) - root.left = root - root.right = root - return connect(connect(left, root), right) -}; - -// n1 is the head of circular DLL as well as n2 -function connect(n1, n2) { - if(n1 === null) return n2 - if(n2 === null) return n1 - const t1 = n1.left - const t2 = n2.left - - t1.right = n2 - n2.left = t1 - t2.right = n1 - n1.left = t2 - - return n1 -} - -// another - -/** - * @param {Node} root - * @return {Node} - */ -const treeToDoublyList = function(root) { - if(root == null) return null - let cur = root - let start = root - while(start.left !== null) { - start = start.left - } - let prev = null - const stack = [] - while(stack.length !== 0 || cur !== null) { - while(cur !== null) { - stack.push(cur) - cur = cur.left - } - cur = stack.pop() - if(prev !== null) { - prev.right = cur - cur.left = prev - } - prev = cur - cur = cur.right - } - start.left = prev - prev.right = start - return start -}; diff --git a/426.convert-binary-search-tree-to-sorted-doubly-linked-list.js b/426.convert-binary-search-tree-to-sorted-doubly-linked-list.js new file mode 100644 index 00000000..da5f15d4 --- /dev/null +++ b/426.convert-binary-search-tree-to-sorted-doubly-linked-list.js @@ -0,0 +1,31 @@ +/** + * // Definition for a Node. + * function Node(val, left, right) { + * this.val = val; + * this.left = left; + * this.right = right; + * }; + */ +/** + * @param {Node} root + * @return {Node} + */ +const treeToDoublyList = function(root) { + let head = null, tail = null; + const helper = (node) => { + if(!node) return; + helper(node.left); + if(!head) head = node; + if(tail) tail.right = node; + node.left = tail; + tail = node; + helper(node.right); + }; + helper(root); + if(head) { + head.left = tail; + tail.right = head; + } + return head; +}; + diff --git a/427-construct-quad-tree.js b/427.construct-quad-tree.js similarity index 100% rename from 427-construct-quad-tree.js rename to 427.construct-quad-tree.js diff --git a/428-serialize-and-deserialize-n-ary-tree.js b/428-serialize-and-deserialize-n-ary-tree.js deleted file mode 100644 index edd89f55..00000000 --- a/428-serialize-and-deserialize-n-ary-tree.js +++ /dev/null @@ -1,124 +0,0 @@ -/** - * // Definition for a Node. - * function Node(val, children) { - * this.val = val; - * this.children = children; - * }; - */ - -class Codec { - constructor() {} - /** - * @param {Node} root - * @return {string} - */ - // Encodes a tree to a single string. - serialize = function(root) { - if (root === null) return '' - let str = '' - function dfs(node) { - str += node.val + ',' + node.children.length + ',' - for (let child of node.children) dfs(child) - } - dfs(root) - return str - } - /** - * @param {string} data - * @return {Node} - */ - // Decodes your encoded data to tree. - deserialize = function(data) { - if (data === '') return null - let idx = 0 - function input() { - let j = data.indexOf(',', idx) - let n = Number(data.slice(idx, j)) - idx = j + 1 - return n - } - function dfs() { - let val = input(), - len = input() - let node = new Node(val, []) - while (len-- > 0) node.children.push(dfs()) - return node - } - return dfs() - } -} -// Your Codec object will be instantiated and called as such: -// Codec codec = new Codec(); -// codec.deserialize(codec.serialize(root)); - -/** - * // Definition for a Node. - * function Node(val, children) { - * this.val = val; - * this.children = children; - * }; - */ - -// another - -/** - * // Definition for a Node. - * function Node(val, children) { - * this.val = val; - * this.children = children; - * }; - */ - -class Codec { - constructor() {} - /** - * @param {Node} root - * @return {string} - */ - // Encodes a tree to a single string. - serialize = function(root) { - const ans = [] - const stack = root ? [root] : [] - while (stack.length) { - const cur = stack.pop() - ans.push(cur.val, cur.children.length) - for (let i = cur.children.length - 1; i >= 0; i--) { - stack.push(cur.children[i]) - } - } - return ans.join(',') - } - /** - * @param {string} data - * @return {Node} - */ - // Decodes your encoded data to tree. - deserialize = function(data) { - if (!data) return null - const arr = data.split(',') - const helper = (index = 0, parent) => { - const node = new Node(arr[index++], []) - parent.children.push(node) - let childCount = arr[index++] - while (childCount--) { - index = helper(index, node) - } - return index - } - const fakeRoot = new Node(null, []) - helper(0, fakeRoot) - return fakeRoot.children[0] - } -} -// Your Codec object will be instantiated and called as such: -// Codec codec = new Codec(); -// codec.deserialize(codec.serialize(root)); - -/** - * // Definition for a Node. - * function Node(val, children) { - * this.val = val; - * this.children = children; - * }; - */ - diff --git a/428.serialize-and-deserialize-n-ary-tree.js b/428.serialize-and-deserialize-n-ary-tree.js new file mode 100644 index 00000000..097c15d5 --- /dev/null +++ b/428.serialize-and-deserialize-n-ary-tree.js @@ -0,0 +1,61 @@ +/** + * // Definition for a Node. + * function Node(val, children) { + * this.val = val; + * this.children = children; + * }; + */ + +class Codec { + constructor() {} + /** + * @param {Node} root + * @return {string} + */ + // Encodes a tree to a single string. + serialize = function(root) { + if (root === null) return '' + let str = '' + function dfs(node) { + str += node.val + ',' + node.children.length + ',' + for (let child of node.children) dfs(child) + } + dfs(root) + return str + } + /** + * @param {string} data + * @return {Node} + */ + // Decodes your encoded data to tree. + deserialize = function(data) { + if (data === '') return null + let idx = 0 + function input() { + let j = data.indexOf(',', idx) + let n = Number(data.slice(idx, j)) + idx = j + 1 + return n + } + function dfs() { + let val = input(), + len = input() + let node = new Node(val, []) + while (len-- > 0) node.children.push(dfs()) + return node + } + return dfs() + } +} +// Your Codec object will be instantiated and called as such: +// Codec codec = new Codec(); +// codec.deserialize(codec.serialize(root)); + +/** + * // Definition for a Node. + * function Node(val, children) { + * this.val = val; + * this.children = children; + * }; + */ + diff --git a/429-n-ary-tree-level-order-traversal.js b/429-n-ary-tree-level-order-traversal.js deleted file mode 100644 index 413cc641..00000000 --- a/429-n-ary-tree-level-order-traversal.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * // Definition for a Node. - * function Node(val,children) { - * this.val = val; - * this.children = children; - * }; - */ -/** - * @param {Node} root - * @return {number[][]} - */ -const levelOrder = function(root) { - const res = [] - if(root == null) return res - helper(root, 0, res) - return res -}; - -function helper(node, index, res) { - if(node == null) return - if(res[index] == null) res[index] = [] - res[index].push(node.val) - for(let i = 0, len = node.children.length; i < len; i++) { - helper(node.children[i], index + 1, res) - } -} - -// another - -/** - * // Definition for a Node. - * function Node(val,children) { - * this.val = val; - * this.children = children; - * }; - */ -/** - * @param {Node} root - * @return {number[][]} - */ -const levelOrder = function(root) { - const res = [] - if(root == null) return res - const q = [] - q.push(root) - while(q.length) { - const size = q.length - const cur = [] - for(let i = 0; i < size; i++) { - const node = q.shift() - cur.push(node.val) - q.push(...node.children) - } - res.push(cur) - } - return res -}; diff --git a/429.n-ary-tree-level-order-traversal.js b/429.n-ary-tree-level-order-traversal.js new file mode 100644 index 00000000..cdcc16d7 --- /dev/null +++ b/429.n-ary-tree-level-order-traversal.js @@ -0,0 +1,27 @@ +/** + * // Definition for a Node. + * function Node(val,children) { + * this.val = val; + * this.children = children; + * }; + */ +/** + * @param {Node} root + * @return {number[][]} + */ +const levelOrder = function(root) { + const res = [] + if(root == null) return res + helper(root, 0, res) + return res +}; + +function helper(node, index, res) { + if(node == null) return + if(res[index] == null) res[index] = [] + res[index].push(node.val) + for(let i = 0, len = node.children.length; i < len; i++) { + helper(node.children[i], index + 1, res) + } +} + diff --git a/43-multiply-strings.js b/43.multiply-strings.js similarity index 100% rename from 43-multiply-strings.js rename to 43.multiply-strings.js diff --git a/430-flatten-a-multilevel-doubly-linked-list.js b/430.flatten-a-multilevel-doubly-linked-list.js similarity index 100% rename from 430-flatten-a-multilevel-doubly-linked-list.js rename to 430.flatten-a-multilevel-doubly-linked-list.js diff --git a/431-encode-n-ary-tree-to-binary-tree.js b/431.encode-n-ary-tree-to-binary-tree.js similarity index 100% rename from 431-encode-n-ary-tree-to-binary-tree.js rename to 431.encode-n-ary-tree-to-binary-tree.js diff --git a/432-all-oone-data-structure.js b/432.all-oone-data-structure.js similarity index 100% rename from 432-all-oone-data-structure.js rename to 432.all-oone-data-structure.js diff --git a/433-minimum-genetic-mutation.js b/433-minimum-genetic-mutation.js deleted file mode 100644 index 8c5ab37c..00000000 --- a/433-minimum-genetic-mutation.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @param {string} start - * @param {string} end - * @param {string[]} bank - * @return {number} - */ -const minMutation = function(start, end, bank) { - const obj = { res: Number.MAX_VALUE } - dfs(start, end, bank, 0, obj, new Set()) - return obj.res === Number.MAX_VALUE ? -1 : obj.res -} - -function dfs(s, e, bank, num, obj, visited) { - if(s === e) { - obj.res = Math.min(obj.res, num) - return - } - for(let el of bank) { - let diff = 0 - for(let i = 0, len = s.length; i < len; i++) { - if(s[i] !== el[i]) { - diff++ - if(diff > 1) break - } - } - if(diff === 1 && !visited.has(el)) { - visited.add(el) - dfs(el, e, bank, num + 1, obj, visited) - visited.delete(el) - } - } -} - -// another - -/** - * @param {string} start - * @param {string} end - * @param {string[]} bank - * @return {number} - */ -const minMutation = function(start, end, bank) { - const bankSet = new Set(bank) - if (!bankSet.has(end)) return -1 - const queue = [[start, 0]] - const dna = ['A', 'C', 'G', 'T'] - while (queue.length) { - let [node, count] = queue.shift() - if (node === end) return count - for (let i = 0; i < node.length; i++) { - for (let j = 0; j < dna.length; j++) { - const d = node.slice(0, i) + dna[j] + node.slice(i + 1) - if (bankSet.has(d)) { - queue.push([d, count + 1]) - bankSet.delete(d) - } - } - } - } - return -1 -} diff --git a/433.minimum-genetic-mutation.js b/433.minimum-genetic-mutation.js new file mode 100644 index 00000000..715aaef0 --- /dev/null +++ b/433.minimum-genetic-mutation.js @@ -0,0 +1,33 @@ +/** + * @param {string} start + * @param {string} end + * @param {string[]} bank + * @return {number} + */ +const minMutation = function(start, end, bank) { + const obj = { res: Number.MAX_VALUE } + dfs(start, end, bank, 0, obj, new Set()) + return obj.res === Number.MAX_VALUE ? -1 : obj.res +} + +function dfs(s, e, bank, num, obj, visited) { + if(s === e) { + obj.res = Math.min(obj.res, num) + return + } + for(let el of bank) { + let diff = 0 + for(let i = 0, len = s.length; i < len; i++) { + if(s[i] !== el[i]) { + diff++ + if(diff > 1) break + } + } + if(diff === 1 && !visited.has(el)) { + visited.add(el) + dfs(el, e, bank, num + 1, obj, visited) + visited.delete(el) + } + } +} + diff --git a/434-number-of-segments-in-a-string.js b/434.number-of-segments-in-a-string.js similarity index 100% rename from 434-number-of-segments-in-a-string.js rename to 434.number-of-segments-in-a-string.js diff --git a/435-non-overlapping-intervals.js b/435-non-overlapping-intervals.js deleted file mode 100644 index 5b57a608..00000000 --- a/435-non-overlapping-intervals.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @param {number[][]} intervals - * @return {number} - */ -const eraseOverlapIntervals = function(intervals) { - if(intervals == null || intervals.length === 0) return 0 - intervals.sort((a, b) => a[1] - b[1]) - let res = 1, end = intervals[0][1] - const len = intervals.length - for(let i = 1; i < len; i++) { - if(intervals[i][0] >= end) { - end = intervals[i][1] - res++ - } - } - - return len - res -}; - -// another - -/** - * Definition for an interval. - * function Interval(start, end) { - * this.start = start; - * this.end = end; - * } - */ -/** - * @param {Interval[]} intervals - * @return {number} - */ -const eraseOverlapIntervals = function(intervals) { - intervals.sort((a, b) => a.end - b.end) - let count = 0 - let end = Number.MIN_SAFE_INTEGER - const len = intervals.length - for(let el of intervals) { - if(el.start >= end) { - end = el.end - count++ - } - } - return len - count -}; diff --git a/435.non-overlapping-intervals.js b/435.non-overlapping-intervals.js new file mode 100644 index 00000000..dd2f046e --- /dev/null +++ b/435.non-overlapping-intervals.js @@ -0,0 +1,19 @@ +/** + * @param {number[][]} intervals + * @return {number} + */ +const eraseOverlapIntervals = function(intervals) { + if(intervals == null || intervals.length === 0) return 0 + intervals.sort((a, b) => a[1] - b[1]) + let res = 1, end = intervals[0][1] + const len = intervals.length + for(let i = 1; i < len; i++) { + if(intervals[i][0] >= end) { + end = intervals[i][1] + res++ + } + } + + return len - res +}; + diff --git a/436-find-right-interval.js b/436.find-right-interval.js similarity index 100% rename from 436-find-right-interval.js rename to 436.find-right-interval.js diff --git a/437-path-sum-iii.js b/437.path-sum-iii.js similarity index 100% rename from 437-path-sum-iii.js rename to 437.path-sum-iii.js diff --git a/438-find-all-anagrams-in-a-string.js b/438.find-all-anagrams-in-a-string.js similarity index 100% rename from 438-find-all-anagrams-in-a-string.js rename to 438.find-all-anagrams-in-a-string.js diff --git a/439-ternary-expression-parser.js b/439.ternary-expression-parser.js similarity index 100% rename from 439-ternary-expression-parser.js rename to 439.ternary-expression-parser.js diff --git a/44-wildcard-matching.js b/44.wildcard-matching.js similarity index 100% rename from 44-wildcard-matching.js rename to 44.wildcard-matching.js diff --git a/440-k-th-smallest-in-lexicographical-order.js b/440-k-th-smallest-in-lexicographical-order.js deleted file mode 100644 index 00bb38fb..00000000 --- a/440-k-th-smallest-in-lexicographical-order.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {number} n - * @param {number} k - * @return {number} - */ -const findKthNumber = function (n, k) { - let cur = 1 - k = k - 1 - while(k > 0) { - const num = calc(cur) - if(num <= k) { - cur++ - k -= num - } else { - k-- - cur *= 10 - } - } - return cur - - function calc(cur) { - let total = 0 - let nxt = cur + 1 - while(cur <= n) { - total += Math.min(n - cur + 1, nxt - cur) - nxt *= 10 - cur *= 10 - } - - return total - } -} - -// another - -/** - * @param {number} n - * @param {number} k - * @return {number} - */ -const findKthNumber = function (n, k) { - let curr = 1 - k = k - 1 - while (k > 0) { - let steps = calSteps(n, curr, curr + 1) - if (steps <= k) { - curr += 1 - k -= steps - } else { - curr *= 10 - k -= 1 - } - } - return curr - - function calSteps(n, n1, n2) { - let steps = 0 - while (n1 <= n) { - steps += Math.min(n + 1, n2) - n1 - n1 *= 10 - n2 *= 10 - } - return steps - } -} diff --git a/440.k-th-smallest-in-lexicographical-order.js b/440.k-th-smallest-in-lexicographical-order.js new file mode 100644 index 00000000..ddb21dd5 --- /dev/null +++ b/440.k-th-smallest-in-lexicographical-order.js @@ -0,0 +1,33 @@ +/** + * @param {number} n + * @param {number} k + * @return {number} + */ +const findKthNumber = function (n, k) { + let cur = 1 + k = k - 1 + while(k > 0) { + const num = calc(cur) + if(num <= k) { + cur++ + k -= num + } else { + k-- + cur *= 10 + } + } + return cur + + function calc(cur) { + let total = 0 + let nxt = cur + 1 + while(cur <= n) { + total += Math.min(n - cur + 1, nxt - cur) + nxt *= 10 + cur *= 10 + } + + return total + } +} + diff --git a/441-arranging-coins.js b/441-arranging-coins.js deleted file mode 100644 index 605801fe..00000000 --- a/441-arranging-coins.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const arrangeCoins = function(n) { - if (n === 0) { - return 0 - } - let num = 1 - let sum = 1 - while(n >= sum + num + 1) { - num += 1 - sum += num - } - - return num -}; - -// another - -/** - * @param {number} n - * @return {number} - */ -const arrangeCoins = function(n) { - return (-1 + Math.sqrt(1+4*2*n)) >> 1 -}; diff --git a/441.arranging-coins.js b/441.arranging-coins.js new file mode 100644 index 00000000..b0c2bcb1 --- /dev/null +++ b/441.arranging-coins.js @@ -0,0 +1,18 @@ +/** + * @param {number} n + * @return {number} + */ +const arrangeCoins = function(n) { + if (n === 0) { + return 0 + } + let num = 1 + let sum = 1 + while(n >= sum + num + 1) { + num += 1 + sum += num + } + + return num +}; + diff --git a/442-find-all-duplicates-in-an-array.js b/442-find-all-duplicates-in-an-array.js deleted file mode 100755 index 4d28baa9..00000000 --- a/442-find-all-duplicates-in-an-array.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[]} - */ - -const findDuplicates = function(nums) { - if (nums === null || nums.length <= 1) { - return []; - } - - let dup = []; - for (let i = 0, n = nums.length; i < n; i++) { - let next = Math.abs(nums[i]); - nums[next - 1] < 0 ? dup.push(next) : (nums[next - 1] = -nums[next - 1]); - } - - return dup; -}; - -console.log(findDuplicates([4, 3, 2, 7, 8, 2, 3, 1])); -console.log(findDuplicates([10, 2, 5, 10, 9, 1, 1, 4, 3, 7])); - -// another - -/** - * @param {number[]} nums - * @return {number[]} - */ -const findDuplicates = function(nums) { - const res = [] - for(let i = 0, len = nums.length; i < len; i++) { - const idx = Math.abs(nums[i]) - 1 - if(nums[idx] < 0) res.push(idx + 1) - nums[idx] = -nums[idx] - } - return res; -}; diff --git a/442.find-all-duplicates-in-an-array.js b/442.find-all-duplicates-in-an-array.js new file mode 100644 index 00000000..f4902e13 --- /dev/null +++ b/442.find-all-duplicates-in-an-array.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} nums + * @return {number[]} + */ + +const findDuplicates = function(nums) { + if (nums === null || nums.length <= 1) { + return []; + } + + let dup = []; + for (let i = 0, n = nums.length; i < n; i++) { + let next = Math.abs(nums[i]); + nums[next - 1] < 0 ? dup.push(next) : (nums[next - 1] = -nums[next - 1]); + } + + return dup; +}; + +console.log(findDuplicates([4, 3, 2, 7, 8, 2, 3, 1])); +console.log(findDuplicates([10, 2, 5, 10, 9, 1, 1, 4, 3, 7])); + diff --git a/443-string-compression.js b/443.string-compression.js similarity index 100% rename from 443-string-compression.js rename to 443.string-compression.js diff --git a/444-sequence-reconstruction.js b/444-sequence-reconstruction.js deleted file mode 100644 index d8fde009..00000000 --- a/444-sequence-reconstruction.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {number[]} org - * @param {number[][]} seqs - * @return {boolean} - */ -const sequenceReconstruction = function(org, seqs) { - const pairs = {} - const idxs = {} - for (let i = 0; i < org.length; i++) idxs[org[i]] = i - for (let j = 0; j < seqs.length; j++) { - const s = seqs[j] - for (let i = 0; i < s.length; i++) { - if (idxs[s[i]] == null) return false - if (i > 0 && idxs[s[i - 1]] >= idxs[s[i]]) return false - pairs[`${s[i - 1]}_${s[i]}`] = 1 - } - } - - for (let i = 0; i < org.length; i++) - if (pairs[`${org[i - 1]}_${org[i]}`] == null) return false - - return true -} - -// another - -/** - * @param {number[]} org - * @param {number[][]} seqs - * @return {boolean} - */ -const sequenceReconstruction = function(org, seqs) { - const graph = new Map() - const indegree = new Map() - seqs.forEach(seq => { - for (let i = 0; i < seq.length; i++) { - if (!graph.has(seq[i])) graph.set(seq[i], []) - if (!indegree.has(seq[i])) indegree.set(seq[i], 0) - if (i > 0) { - graph.get(seq[i - 1]).push(seq[i]) - indegree.set(seq[i], indegree.get(seq[i]) + 1) - } - } - }) - if (org.length !== graph.size) return false - const array = [] - for (let [key, val] of indegree.entries()) { - if (val === 0) array.push(key) - } - let index = 0 - while (array.length > 0) { - if (array.length > 1) return false - const current = array.shift() - if (org[index] !== current) { - return false - } - index++ - graph.get(current).forEach(next => { - indegree.set(next, indegree.get(next) - 1) - if (indegree.get(next) === 0) array.push(next) - }) - } - return index === org.length -} - diff --git a/444.sequence-reconstruction.js b/444.sequence-reconstruction.js new file mode 100644 index 00000000..3ddce3f0 --- /dev/null +++ b/444.sequence-reconstruction.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} org + * @param {number[][]} seqs + * @return {boolean} + */ +const sequenceReconstruction = function(org, seqs) { + const pairs = {} + const idxs = {} + for (let i = 0; i < org.length; i++) idxs[org[i]] = i + for (let j = 0; j < seqs.length; j++) { + const s = seqs[j] + for (let i = 0; i < s.length; i++) { + if (idxs[s[i]] == null) return false + if (i > 0 && idxs[s[i - 1]] >= idxs[s[i]]) return false + pairs[`${s[i - 1]}_${s[i]}`] = 1 + } + } + + for (let i = 0; i < org.length; i++) + if (pairs[`${org[i - 1]}_${org[i]}`] == null) return false + + return true +} + diff --git a/445-add-two-numbers-II.js b/445-add-two-numbers-II.js deleted file mode 100755 index 4800985a..00000000 --- a/445-add-two-numbers-II.js +++ /dev/null @@ -1,154 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} l1 - * @param {ListNode} l2 - * @return {ListNode} - */ -const addTwoNumbers = function(head1, head2) { - const r1 = reverse(head1), r2 = reverse(head2) - let l1 = r1, l2 = r2, inc = 0 - let dummy = new ListNode() - let pre = dummy - while(l1 || l2) { - let val = inc - if(l1) { - val += l1.val - l1 = l1.next - } - if(l2) { - val += l2.val - l2 = l2.next - } - if(val > 9) inc = 1 - else inc = 0 - const cur = new ListNode(val % 10) - pre.next = cur - pre = cur - } - if (inc) { - pre.next = new ListNode(1) - } - return reverse(dummy.next) -}; - -function reverse(head) { - const dummy = new ListNode() - dummy.next = head - let len = 0, cur = head - while(cur) { - len++ - cur = cur.next - } - let p = dummy, tail = head, tmp = null - for(let i = 0; i < len - 1; i++) { - tmp = p.next - p.next = tail.next - tail.next = tail.next.next - p.next.next = tmp - } - return dummy.next -} - - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} l1 - * @param {ListNode} l2 - * @return {ListNode} - */ -const addTwoNumbers = function(l1, l2) { - const s1 = []; - const s2 = []; - while (l1 !== null) { - s1.push(l1.val); - l1 = l1.next; - } - while (l2 !== null) { - s2.push(l2.val); - l2 = l2.next; - } - - let list = new ListNode(0); - let sum = 0; - while (s1.length > 0 || s2.length > 0) { - if (s1.length > 0) { - sum += s1.pop(); - } - if (s2.length > 0) { - sum += s2.pop(); - } - list.val = sum % 10; - const head = new ListNode(Math.floor(sum / 10)); - head.next = list; - list = head; - sum = Math.floor(sum / 10); - } - - return list.val === 0 ? list.next : list; -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} l1 - * @param {ListNode} l2 - * @return {ListNode} - */ -const addTwoNumbers = function(l1, l2) { - const s1 = [], s2 = [] - let h1 = l1, h2 = l2 - while(h1) { - s1.push(h1.val) - h1 = h1.next - } - while(h2) { - s2.push(h2.val) - h2 = h2.next - } - let inc = false - let tail = null - while(s1.length || s2.length) { - let tmp = 0 - if(s1.length) tmp += s1.pop() - if(s2.length) tmp += s2.pop() - if(inc) tmp++ - if(tmp > 9) { - inc = true - } else { - inc = false - } - tmp = tmp % 10 - const cur = new ListNode(tmp) - if(tail) cur.next = tail - tail = cur - } - - if(inc) { - const head = new ListNode(1) - head.next = tail - return head - } - return tail - -}; diff --git a/445.add-two-numbers-II.js b/445.add-two-numbers-II.js new file mode 100644 index 00000000..be90acba --- /dev/null +++ b/445.add-two-numbers-II.js @@ -0,0 +1,58 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} l1 + * @param {ListNode} l2 + * @return {ListNode} + */ +const addTwoNumbers = function(head1, head2) { + const r1 = reverse(head1), r2 = reverse(head2) + let l1 = r1, l2 = r2, inc = 0 + let dummy = new ListNode() + let pre = dummy + while(l1 || l2) { + let val = inc + if(l1) { + val += l1.val + l1 = l1.next + } + if(l2) { + val += l2.val + l2 = l2.next + } + if(val > 9) inc = 1 + else inc = 0 + const cur = new ListNode(val % 10) + pre.next = cur + pre = cur + } + if (inc) { + pre.next = new ListNode(1) + } + return reverse(dummy.next) +}; + +function reverse(head) { + const dummy = new ListNode() + dummy.next = head + let len = 0, cur = head + while(cur) { + len++ + cur = cur.next + } + let p = dummy, tail = head, tmp = null + for(let i = 0; i < len - 1; i++) { + tmp = p.next + p.next = tail.next + tail.next = tail.next.next + p.next.next = tmp + } + return dummy.next +} + + diff --git a/446-arithmetic-slices-ii-subsequence.js b/446.arithmetic-slices-ii-subsequence.js similarity index 100% rename from 446-arithmetic-slices-ii-subsequence.js rename to 446.arithmetic-slices-ii-subsequence.js diff --git a/447-number-of-boomerangs.js b/447.number-of-boomerangs.js similarity index 100% rename from 447-number-of-boomerangs.js rename to 447.number-of-boomerangs.js diff --git a/448-find-all-numbers-disappeared-in-an-array.js b/448-find-all-numbers-disappeared-in-an-array.js deleted file mode 100755 index bf3dd2da..00000000 --- a/448-find-all-numbers-disappeared-in-an-array.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[]} - */ -const findDisappearedNumbers = function(nums) { - const res = []; - nums.forEach((el, idx) => { - res[el - 1] = 1; - }); - const arr = []; - for (let i = 0; i < nums.length; i++) { - if (res[i] == null) { - arr.push(i + 1); - } - } - return arr; -}; - -// another - -/** - * @param {number[]} nums - * @return {number[]} - */ -const findDisappearedNumbers = function(nums) { - for(let i = 0, len = nums.length; i < len; i++) { - const idx = Math.abs(nums[i]) - 1 - nums[idx] = - Math.abs(nums[idx]) - } - const res = [] - nums.forEach((e, i) => { - if(e > 0) res.push(i + 1) - }) - return res -}; diff --git a/448.find-all-numbers-disappeared-in-an-array.js b/448.find-all-numbers-disappeared-in-an-array.js new file mode 100644 index 00000000..cc874f7e --- /dev/null +++ b/448.find-all-numbers-disappeared-in-an-array.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums + * @return {number[]} + */ +const findDisappearedNumbers = function(nums) { + const res = []; + nums.forEach((el, idx) => { + res[el - 1] = 1; + }); + const arr = []; + for (let i = 0; i < nums.length; i++) { + if (res[i] == null) { + arr.push(i + 1); + } + } + return arr; +}; + diff --git a/449-serialize-and-deserialize-BST.js b/449-serialize-and-deserialize-BST.js deleted file mode 100755 index a3c35b02..00000000 --- a/449-serialize-and-deserialize-BST.js +++ /dev/null @@ -1,59 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ - -const splitter = ","; -/** - * Encodes a tree to a single string. - * - * @param {TreeNode} root - * @return {string} - */ -const serialize = function(root) { - const sb = []; - buildString(root, sb); - sb.pop(); - return sb.join(""); -}; -function buildString(node, sb) { - if (node == null) return; - sb.push(node.val); - sb.push(splitter); - buildString(node.left, sb); - buildString(node.right, sb); -} -/** - * Decodes your encoded data to tree. - * - * @param {string} data - * @return {TreeNode} - */ -const deserialize = function(data) { - if (data.length === 0) return null; - const pos = [0]; - return buildTree( - data.split(splitter), - pos, - Number.MIN_SAFE_INTEGER, - Number.MAX_SAFE_INTEGER - ); -}; -function buildTree(nodes, pos, min, max) { - if (pos[0] === nodes.length) return null; - let val = +nodes[pos[0]]; - if (val < min || val > max) return null; - const cur = new TreeNode(val); - pos[0] += 1; - cur.left = buildTree(nodes, pos, min, val); - cur.right = buildTree(nodes, pos, val, max); - return cur; -} - -/** - * Your functions will be called as such: - * deserialize(serialize(root)); - */ diff --git a/449.serialize-and-deserialize-BST.js b/449.serialize-and-deserialize-BST.js new file mode 100644 index 00000000..7b20ca75 --- /dev/null +++ b/449.serialize-and-deserialize-BST.js @@ -0,0 +1,59 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ + +const splitter = ","; +/** + * Encodes a tree to a single string. + * + * @param {TreeNode} root + * @return {string} + */ +const serialize = function(root) { + const sb = []; + buildString(root, sb); + sb.pop(); + return sb.join(""); +}; +function buildString(node, sb) { + if (node == null) return; + sb.push(node.val); + sb.push(splitter); + buildString(node.left, sb); + buildString(node.right, sb); +} +/** + * Decodes your encoded data to tree. + * + * @param {string} data + * @return {TreeNode} + */ +const deserialize = function(data) { + if (data.length === 0) return null; + const pos = [0]; + return buildTree( + data.split(splitter), + pos, + Number.MIN_SAFE_INTEGER, + Number.MAX_SAFE_INTEGER + ); +}; +function buildTree(nodes, pos, min, max) { + if (pos[0] === nodes.length) return null; + let val = +nodes[pos[0]]; + if (val < min || val > max) return null; + const cur = new TreeNode(val); + pos[0] += 1; + cur.left = buildTree(nodes, pos, min, val); + cur.right = buildTree(nodes, pos, val, max); + return cur; +} + +/** + * Your functions will be called as such: + * deserialize(serialize(root)); + */ diff --git a/45-jump-game-ii.js b/45.jump-game-ii.js similarity index 100% rename from 45-jump-game-ii.js rename to 45.jump-game-ii.js diff --git a/450-delete-node-in-a-bst.js b/450-delete-node-in-a-bst.js deleted file mode 100644 index 51eee135..00000000 --- a/450-delete-node-in-a-bst.js +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {number} key - * @return {TreeNode} - */ -const deleteNode = function(root, key) { - if(root == null) return null - if(key < root.val) { - root.left = deleteNode(root.left, key) - } else if(key > root.val) { - root.right = deleteNode(root.right, key) - } else { - if(root.left == null) { - return root.right - } else if(root.right == null) { - return root.left - } else { - let smallestRight = root.right - while(smallestRight.left !== null) smallestRight = smallestRight.left - smallestRight.left = root.left - return root.right - } - } - - return root -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @param {number} key - * @return {TreeNode} - */ -const deleteNode = function(root, key) { - if(root == null) return root - - if(root.val < key) root.right = deleteNode(root.right, key) - else if(root.val > key) root.left = deleteNode(root.left, key) - else { - if(root.left == null && root.right === null) root = null - else if(root.left == null) root = root.right - else if(root.right == null) root = root.left - else { - const min = findMin(root.right) - root.val = min.val - root.right = deleteNode(root.right, root.val) - } - } - - return root -}; - -function findMin(node) { - let cur = node - while(cur.left) { - cur = cur.left - } - return cur -} diff --git a/450.delete-node-in-a-bst.js b/450.delete-node-in-a-bst.js new file mode 100644 index 00000000..79d43b00 --- /dev/null +++ b/450.delete-node-in-a-bst.js @@ -0,0 +1,34 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {number} key + * @return {TreeNode} + */ +const deleteNode = function(root, key) { + if(root == null) return null + if(key < root.val) { + root.left = deleteNode(root.left, key) + } else if(key > root.val) { + root.right = deleteNode(root.right, key) + } else { + if(root.left == null) { + return root.right + } else if(root.right == null) { + return root.left + } else { + let smallestRight = root.right + while(smallestRight.left !== null) smallestRight = smallestRight.left + smallestRight.left = root.left + return root.right + } + } + + return root +}; + diff --git a/451-sort-characters-by-frequency.js b/451-sort-characters-by-frequency.js deleted file mode 100755 index 69fce9ff..00000000 --- a/451-sort-characters-by-frequency.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ -const frequencySort = function(s) { - const charMap = {}; - for (let i = 0; i < s.length; i++) { - const index = s.charAt(i); - charMap[index] = (charMap[index] || 0) + 1; - } - return Object.entries(charMap) - .sort((a, b) => { - return b[1] - a[1]; - }) - .map(x => { - return x[0].repeat(x[1]); - }) - .join(""); -}; diff --git a/451.sort-characters-by-frequency.js b/451.sort-characters-by-frequency.js new file mode 100644 index 00000000..c282fed3 --- /dev/null +++ b/451.sort-characters-by-frequency.js @@ -0,0 +1,19 @@ +/** + * @param {string} s + * @return {string} + */ +const frequencySort = function(s) { + const charMap = {}; + for (let i = 0; i < s.length; i++) { + const index = s.charAt(i); + charMap[index] = (charMap[index] || 0) + 1; + } + return Object.entries(charMap) + .sort((a, b) => { + return b[1] - a[1]; + }) + .map(x => { + return x[0].repeat(x[1]); + }) + .join(""); +}; diff --git a/452-minimum-number-of-arrows-to-burst-balloons.js b/452-minimum-number-of-arrows-to-burst-balloons.js deleted file mode 100644 index c47b87fa..00000000 --- a/452-minimum-number-of-arrows-to-burst-balloons.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {number[][]} points - * @return {number} - */ -const findMinArrowShots = function(points) { - const sorted = points.sort((a, b) => a[0] - b[0]) - let ans = 0 - let lastX = null - for (let i = 0; i < sorted.length; i += 1) { - if (lastX && sorted[i][0] <= lastX) { - lastX = Math.min(sorted[i][1], lastX) - } else { - ans += 1 - lastX = sorted[i][1] - } - } - return ans -} - -// another - -/** - * @param {number[][]} points - * @return {number} - */ -const findMinArrowShots = function(points) { - if(points == null || points.length === 0) return 0 - points.sort((a, b) => a[1] - b[1]) - let end = points[0][1], res = 1 - for(let i = 1, len = points.length; i < len; i++) { - if(points[i][0] > end) { - end = points[i][1] - res++ - } - } - return res -}; diff --git a/452.minimum-number-of-arrows-to-burst-balloons.js b/452.minimum-number-of-arrows-to-burst-balloons.js new file mode 100644 index 00000000..c7c3edf1 --- /dev/null +++ b/452.minimum-number-of-arrows-to-burst-balloons.js @@ -0,0 +1,19 @@ +/** + * @param {number[][]} points + * @return {number} + */ +const findMinArrowShots = function(points) { + const sorted = points.sort((a, b) => a[0] - b[0]) + let ans = 0 + let lastX = null + for (let i = 0; i < sorted.length; i += 1) { + if (lastX && sorted[i][0] <= lastX) { + lastX = Math.min(sorted[i][1], lastX) + } else { + ans += 1 + lastX = sorted[i][1] + } + } + return ans +} + diff --git a/453-minimum-moves-to-equal-array-elements.js b/453-minimum-moves-to-equal-array-elements.js deleted file mode 100755 index 19c0882e..00000000 --- a/453-minimum-moves-to-equal-array-elements.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const minMoves = function(nums) { - let min = Number.MAX_SAFE_INTEGER; - let sum = 0; - for (let i = 0; i < nums.length; i++) { - min = Math.min(min, nums[i]); - sum += nums[i]; - } - return sum - min * nums.length; -}; diff --git a/453.minimum-moves-to-equal-array-elements.js b/453.minimum-moves-to-equal-array-elements.js new file mode 100644 index 00000000..141066f3 --- /dev/null +++ b/453.minimum-moves-to-equal-array-elements.js @@ -0,0 +1,13 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const minMoves = function(nums) { + let min = Number.MAX_SAFE_INTEGER; + let sum = 0; + for (let i = 0; i < nums.length; i++) { + min = Math.min(min, nums[i]); + sum += nums[i]; + } + return sum - min * nums.length; +}; diff --git a/454-4sum-ii.js b/454.4sum-ii.js similarity index 100% rename from 454-4sum-ii.js rename to 454.4sum-ii.js diff --git a/455-assign-cookies.js b/455-assign-cookies.js deleted file mode 100755 index 0acfd960..00000000 --- a/455-assign-cookies.js +++ /dev/null @@ -1,15 +0,0 @@ -/** - * @param {number[]} g - * @param {number[]} s - * @return {number} - */ -const findContentChildren = function(g, s) { - s.sort((a, b) => a - b); - g.sort((a, b) => a - b); - - let i = 0; - for (let j = 0; i < g.length && j < s.length; j++) { - if (g[i] <= s[j]) i++; - } - return i; -}; diff --git a/455.assign-cookies.js b/455.assign-cookies.js new file mode 100644 index 00000000..14c5ad4e --- /dev/null +++ b/455.assign-cookies.js @@ -0,0 +1,15 @@ +/** + * @param {number[]} g + * @param {number[]} s + * @return {number} + */ +const findContentChildren = function(g, s) { + s.sort((a, b) => a - b); + g.sort((a, b) => a - b); + + let i = 0; + for (let j = 0; i < g.length && j < s.length; j++) { + if (g[i] <= s[j]) i++; + } + return i; +}; diff --git a/456-132-pattern.js b/456-132-pattern.js deleted file mode 100644 index e584d194..00000000 --- a/456-132-pattern.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {number[]} nums - * @return {boolean} - */ -const find132pattern = function(nums) { - let [stack, s3] = [[], -Infinity] - for (let i = nums.length - 1; i >= 0; i--) { - if (nums[i] < s3) { - return true - } - while (stack[stack.length - 1] < nums[i]) { - s3 = stack.pop() - } - stack.push(nums[i]) - } - return false -} - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -const find132pattern = function(nums) { - let idx = nums.length - let s3 = Number.NEGATIVE_INFINITY - for(let len = nums.length, i = len - 1; i >= 0; i--) { - if(nums[i] < s3) return true - while(idx < nums.length && nums[i] > nums[idx]) { - s3 = nums[idx++] - } - nums[--idx] = nums[i] - } - return false -} - diff --git a/456.132-pattern.js b/456.132-pattern.js new file mode 100644 index 00000000..29f591b4 --- /dev/null +++ b/456.132-pattern.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums + * @return {boolean} + */ +const find132pattern = function(nums) { + let [stack, s3] = [[], -Infinity] + for (let i = nums.length - 1; i >= 0; i--) { + if (nums[i] < s3) { + return true + } + while (stack[stack.length - 1] < nums[i]) { + s3 = stack.pop() + } + stack.push(nums[i]) + } + return false +} + diff --git a/457-circular-array-loop.js b/457.circular-array-loop.js similarity index 100% rename from 457-circular-array-loop.js rename to 457.circular-array-loop.js diff --git a/458-poor-pigs.js b/458-poor-pigs.js deleted file mode 100644 index da075dcc..00000000 --- a/458-poor-pigs.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {number} buckets - * @param {number} minutesToDie - * @param {number} minutesToTest - * @return {number} - */ -const poorPigs = function(buckets, minutesToDie, minutesToTest) { - const index = Math.ceil(minutesToTest / minutesToDie) + 1 - return Math.ceil(Math.log(buckets) / Math.log(index)) -} - -// another - -/** - * @param {number} buckets - * @param {number} minutesToDie - * @param {number} minutesToTest - * @return {number} - */ -const poorPigs = function(buckets, minutesToDie, minutesToTest) { - let pigs = 0 - while ((minutesToTest / minutesToDie + 1) ** pigs < buckets) { - pigs++ - } - return pigs -} diff --git a/458.poor-pigs.js b/458.poor-pigs.js new file mode 100644 index 00000000..0b1efffb --- /dev/null +++ b/458.poor-pigs.js @@ -0,0 +1,11 @@ +/** + * @param {number} buckets + * @param {number} minutesToDie + * @param {number} minutesToTest + * @return {number} + */ +const poorPigs = function(buckets, minutesToDie, minutesToTest) { + const index = Math.ceil(minutesToTest / minutesToDie) + 1 + return Math.ceil(Math.log(buckets) / Math.log(index)) +} + diff --git a/459-repeated-substring-pattern.js b/459-repeated-substring-pattern.js deleted file mode 100644 index 9debc498..00000000 --- a/459-repeated-substring-pattern.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - * @param {string} s - * @return {boolean} - */ -const repeatedSubstringPattern = function(s) { - - const len = s.length - const table = build(s) - return table[len] && (table[len] % (len - table[len]) === 0) - - function build(str) { - const n = str.length - const table = Array(n + 1).fill(0) - let i = 1, j = 0 - table[0] = -1 - while(i < n) { - if(str[i] === str[j]) { - i++ - j++ - table[i] = j - } else { - if(j > 0) j = table[j] - else i++ - } - } - - return table - } -}; - -// another - -/** - * @param {string} s - * @return {boolean} - */ -const repeatedSubstringPattern = function(s) { - const len = s.length - let tmp = '' - for(let i = 1; i <= len; i++) { - tmp = s.substr(0, i) - if (tmp.length === len) { - return false - } - if (s === genStr(tmp, len)) { - return true - } - } - return false -}; -function genStr(sub, limit) { - let str = sub - while(str.length < limit) { - str += sub - } - return str -} - -// another - -/** - * @param {string} s - * @return {boolean} - */ -const repeatedSubstringPattern = function (s) { - const l = s.length - const arr = DFA(s) - return arr[l] && arr[l] % (l - arr[l]) === 0 - function DFA(s) { - let i = 1 - let j = 0 - const len = s.length - const prefix = Array(len + 1).fill(0) - prefix[0] = -1 - prefix[1] = 0 - while (i < len) { - if (s[j] === s[i]) { - j++ - i++ - prefix[i] = j - } else { - if (j > 0) j = prefix[j] - else i++ - } - } - return prefix - } -} - -// another - -/** - * @param {string} s - * @return {boolean} - */ -const repeatedSubstringPattern = function(s) { - let i = 1, j = 0, n = s.length; - const dp = Array(n + 1).fill(0); - while( i < s.length ){ - if( s[i] === s[j] ) dp[++i] = ++j; - else if( j === 0 ) i++; - else j = dp[j]; - } - return dp[n] && (dp[n] % (n - dp[n]) === 0); -}; diff --git a/459.repeated-substring-pattern.js b/459.repeated-substring-pattern.js new file mode 100644 index 00000000..07b13580 --- /dev/null +++ b/459.repeated-substring-pattern.js @@ -0,0 +1,30 @@ +/** + * @param {string} s + * @return {boolean} + */ +const repeatedSubstringPattern = function(s) { + + const len = s.length + const table = build(s) + return table[len] && (table[len] % (len - table[len]) === 0) + + function build(str) { + const n = str.length + const table = Array(n + 1).fill(0) + let i = 1, j = 0 + table[0] = -1 + while(i < n) { + if(str[i] === str[j]) { + i++ + j++ + table[i] = j + } else { + if(j > 0) j = table[j] + else i++ + } + } + + return table + } +}; + diff --git a/46-permutations.js b/46-permutations.js deleted file mode 100755 index 82faf2f7..00000000 --- a/46-permutations.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[][]} - */ -function permute(nums) { - const list = []; - // Arrays.sort(nums); // not necessary - backtrack(list, [], nums); - return list; -} - -function backtrack(list, tempList, nums) { - if (tempList.length == nums.length) { - list.push(tempList.slice(0)); - } else { - for (let i = 0; i < nums.length; i++) { - if (tempList.includes(nums[i])) continue; // element already exists, skip - tempList.push(nums[i]); - backtrack(list, tempList, nums); - tempList.pop(); - } - } -} - -// another - -/** - * @param {number[]} nums - * @return {number[][]} - */ -const permute = function(nums) { - const res = [] - bt(nums, 0, [], res) - return res -}; - -function bt(nums, idx, cur, res) { - if(idx === nums.length) { - res.push(cur.slice()) - return - } - for(let i = 0; i < nums.length; i++) { - if(cur.indexOf(nums[i]) !== -1) continue - cur.push(nums[i]) - bt(nums, idx + 1, cur, res) - cur.pop() - } -} diff --git a/46.permutations.js b/46.permutations.js new file mode 100644 index 00000000..618ffddc --- /dev/null +++ b/46.permutations.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} nums + * @return {number[][]} + */ +function permute(nums) { + const list = []; + // Arrays.sort(nums); // not necessary + backtrack(list, [], nums); + return list; +} + +function backtrack(list, tempList, nums) { + if (tempList.length == nums.length) { + list.push(tempList.slice(0)); + } else { + for (let i = 0; i < nums.length; i++) { + if (tempList.includes(nums[i])) continue; // element already exists, skip + tempList.push(nums[i]); + backtrack(list, tempList, nums); + tempList.pop(); + } + } +} + diff --git a/460-lfu-cache.js b/460.lfu-cache.js similarity index 100% rename from 460-lfu-cache.js rename to 460.lfu-cache.js diff --git a/461-hamming-distance.js b/461-hamming-distance.js deleted file mode 100644 index 8174de3f..00000000 --- a/461-hamming-distance.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @param {number} x - * @param {number} y - * @return {number} - */ -const hammingDistance = function (x, y) { - let d = 0 - let h = x ^ y - while (h > 0) { - d++ - h &= h - 1 - } - return d -} - -// another - -/** - * @param {number} x - * @param {number} y - * @return {number} - */ -const hammingDistance = function (x, y) { - let n = x ^ y - n = n - ((n >> 1) & 0x55555555) - n = (n & 0x33333333) + ((n >> 2) & 0x33333333) - return (((n + (n >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24 -} - -// another - -/** - * @param {number} x - * @param {number} y - * @return {number} - */ -const hammingDistance = function (x, y) { - let n = x ^ y - let tmp = n - ((n >> 1) & 033333333333) - ((n >> 2) & 011111111111); - return ((tmp + (tmp >> 3)) & 030707070707) % 63; -} - -// https://tech.liuchao.me/2016/11/count-bits-of-integer/ diff --git a/461.hamming-distance.js b/461.hamming-distance.js new file mode 100644 index 00000000..5c386160 --- /dev/null +++ b/461.hamming-distance.js @@ -0,0 +1,15 @@ +/** + * @param {number} x + * @param {number} y + * @return {number} + */ +const hammingDistance = function (x, y) { + let d = 0 + let h = x ^ y + while (h > 0) { + d++ + h &= h - 1 + } + return d +} + diff --git a/462-minimum-moves-to-equal-array-elements-II.js b/462-minimum-moves-to-equal-array-elements-II.js deleted file mode 100755 index 4919debd..00000000 --- a/462-minimum-moves-to-equal-array-elements-II.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const minMoves2 = function(nums) { - nums.sort((a, b) => a - b); - let i = 0, - j = nums.length - 1; - let res = 0; - while (i < j) { - res += nums[j] - nums[i]; - i++; - j--; - } - return res; -}; diff --git a/462.minimum-moves-to-equal-array-elements-II.js b/462.minimum-moves-to-equal-array-elements-II.js new file mode 100644 index 00000000..27f14035 --- /dev/null +++ b/462.minimum-moves-to-equal-array-elements-II.js @@ -0,0 +1,16 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const minMoves2 = function(nums) { + nums.sort((a, b) => a - b); + let i = 0, + j = nums.length - 1; + let res = 0; + while (i < j) { + res += nums[j] - nums[i]; + i++; + j--; + } + return res; +}; diff --git a/463-island-perimeter.js b/463-island-perimeter.js deleted file mode 100755 index db888ecd..00000000 --- a/463-island-perimeter.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const islandPerimeter = function(grid) { - let len = 0; - for (let r = 0; r < grid.length; r++) { - for (let c = 0; c < grid[0].length; c++) { - if (grid[r][c] === 1) { - len += cell(grid, r, c); - } - } - } - return len; -}; - -function cell(grid, r, c) { - let len = 0; - // top - if (r === 0 || grid[r - 1][c] !== 1) { - len += 1; - } - // left - if (c === 0 || grid[r][c - 1] !== 1) { - len += 1; - } - // right - if (grid[r][c + 1] !== 1) { - len += 1; - } - // bottom - if (grid[r + 1] == null || grid[r + 1][c] !== 1) { - len += 1; - } - return len; -} - -console.log( - islandPerimeter([[0, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0], [1, 1, 0, 0]]) -); - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -const islandPerimeter = function(grid) { - const m = grid.length - const n = grid[0].length - const dirs = [[0, 1], [0, -1], [1, 0], [-1, 0]] - let r = 0 - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - if(grid[i][j] === 1) r += h(i, j) - } - } - - return r - - function h(i, j) { - let res = 0 - for(let d of dirs) { - const nr = i + d[0] - const nc = j + d[1] - if(nr < 0 || nc < 0 || nr >= m || nc >= n || grid[nr][nc] === 0) res++ - } - return res - } -}; diff --git a/463.island-perimeter.js b/463.island-perimeter.js new file mode 100644 index 00000000..9b168d2f --- /dev/null +++ b/463.island-perimeter.js @@ -0,0 +1,41 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const islandPerimeter = function(grid) { + let len = 0; + for (let r = 0; r < grid.length; r++) { + for (let c = 0; c < grid[0].length; c++) { + if (grid[r][c] === 1) { + len += cell(grid, r, c); + } + } + } + return len; +}; + +function cell(grid, r, c) { + let len = 0; + // top + if (r === 0 || grid[r - 1][c] !== 1) { + len += 1; + } + // left + if (c === 0 || grid[r][c - 1] !== 1) { + len += 1; + } + // right + if (grid[r][c + 1] !== 1) { + len += 1; + } + // bottom + if (grid[r + 1] == null || grid[r + 1][c] !== 1) { + len += 1; + } + return len; +} + +console.log( + islandPerimeter([[0, 1, 0, 0], [1, 1, 1, 0], [0, 1, 0, 0], [1, 1, 0, 0]]) +); + diff --git a/464-can-i-win.js b/464.can-i-win.js similarity index 100% rename from 464-can-i-win.js rename to 464.can-i-win.js diff --git a/465-optimal-account-balancing.js b/465.optimal-account-balancing.js similarity index 100% rename from 465-optimal-account-balancing.js rename to 465.optimal-account-balancing.js diff --git a/466-count-the-repetitions.js b/466.count-the-repetitions.js similarity index 100% rename from 466-count-the-repetitions.js rename to 466.count-the-repetitions.js diff --git a/467-unique-substrings-in-wraparound-string.js b/467.unique-substrings-in-wraparound-string.js similarity index 100% rename from 467-unique-substrings-in-wraparound-string.js rename to 467.unique-substrings-in-wraparound-string.js diff --git a/468-validate-ip-address.js b/468-validate-ip-address.js deleted file mode 100644 index d421c6c6..00000000 --- a/468-validate-ip-address.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @param {string} IP - * @return {string} - */ -const validIPAddress = function (IP) { - if (IP.indexOf('.') > 0) return validIPv4(IP) ? 'IPv4' : 'Neither' - else return validIPv6(IP) ? 'IPv6' : 'Neither' -} - -const validIPv4 = function (IP) { - const strs = IP.split('.') - if (strs.length !== 4) return false - for (let str of strs) { - if (str.length === 0) return false - if (str.match(/[^0-9]/)) return false - if (str.length > 1 && str.charAt(0) === '0') return false - if (+str > 255) return false - } - return true -} - -const validIPv6 = function (IP) { - const strs = IP.split(':') - if (strs.length !== 8) return false - for (let str of strs) { - if (str.length === 0) return false - if (str.length > 4) return false - if (str.match(/[^0-9a-fA-F]/g)) return false - } - return true -} - -// another - -/** - * @param {string} IP - * @return {string} - */ -const validIPAddress = function(IP) { - const ipv4 = /^((\d|[1-9]\d|1\d\d|2([0-4]\d|5[0-5]))\.){4}$/ - const ipv6 = /^([\da-f]{1,4}:){8}$/i - return ipv4.test(IP + '.') ? 'IPv4' : ipv6.test(IP + ':') ? 'IPv6' : 'Neither' -} - -// another - -/** - * @param {string} IP - * @return {string} - */ -const validIPAddress = function(IP) { - if (IP.indexOf('.') != -1) { - const arr = IP.split('.') - if (arr.length !== 4) return 'Neither' - for (let i = 0; i < arr.length; i++) { - const numVal = parseInt(arr[i]) - if ( - numVal < 0 || - numVal >= 256 || - arr[i].length !== ('' + numVal).length - ) { - return 'Neither' - } - } - return 'IPv4' - } else if (IP.indexOf(':') != -1) { - const arr = IP.split(':') - if (arr.length !== 8) return 'Neither' - for (let i = 0; i < arr.length; i++) { - if (arr[i].length > 4 || arr[i].length === 0) return 'Neither' - const re = /[^0-9A-F]/i - if (re.test(arr[i])) return 'Neither' - } - return 'IPv6' - } else { - return 'Neither' - } -} diff --git a/468.validate-ip-address.js b/468.validate-ip-address.js new file mode 100644 index 00000000..08be3f77 --- /dev/null +++ b/468.validate-ip-address.js @@ -0,0 +1,32 @@ +/** + * @param {string} IP + * @return {string} + */ +const validIPAddress = function (IP) { + if (IP.indexOf('.') > 0) return validIPv4(IP) ? 'IPv4' : 'Neither' + else return validIPv6(IP) ? 'IPv6' : 'Neither' +} + +const validIPv4 = function (IP) { + const strs = IP.split('.') + if (strs.length !== 4) return false + for (let str of strs) { + if (str.length === 0) return false + if (str.match(/[^0-9]/)) return false + if (str.length > 1 && str.charAt(0) === '0') return false + if (+str > 255) return false + } + return true +} + +const validIPv6 = function (IP) { + const strs = IP.split(':') + if (strs.length !== 8) return false + for (let str of strs) { + if (str.length === 0) return false + if (str.length > 4) return false + if (str.match(/[^0-9a-fA-F]/g)) return false + } + return true +} + diff --git a/469-convex-polygon.js b/469.convex-polygon.js similarity index 100% rename from 469-convex-polygon.js rename to 469.convex-polygon.js diff --git a/47-permutations-ii.js b/47-permutations-ii.js deleted file mode 100644 index 02337a11..00000000 --- a/47-permutations-ii.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[][]} - */ -const permuteUnique = function(nums) { - const result = []; - if (nums == null || nums.length === 0) { - return result; - } - const map = {}; - for (let n of nums) { - map[n] = map.hasOwnProperty(n) ? map[n] + 1 : 1; - } - permuteUniqueHelper(map, nums.length, [], 0, result); - return result; -}; - -function permuteUniqueHelper(m, l, p, i, r) { - if (l === i) { - r.push(p.slice(0, l)); - return; - } - for (let key of Object.keys(m)) { - if (m[key] > 0) { - m[key] = m[key] - 1; - p[i] = key; - permuteUniqueHelper(m, l, p, i + 1, r); - m[key] = m[key] + 1; - } - } -} - - -// another - -/** - * @param {number[]} nums - * @return {number[][]} - */ -const permuteUnique = function(nums) { - const set = new Set() - const used = new Set() - bt(nums, 0, [], used, set) - const res = [] - for(let item of set) { - res.push(item.split(',')) - } - return res -}; - -function bt(nums, i, cur, used, set) { - if(i === nums.length) { - set.add(cur.slice().join(',')) - return - } - for(let idx = 0; idx < nums.length; idx++) { - if(used.has(idx)) continue - cur.push(nums[idx]) - used.add(idx) - bt(nums, i + 1, cur, used, set) - used.delete(idx) - cur.pop() - } -} diff --git a/47.permutations-ii.js b/47.permutations-ii.js new file mode 100644 index 00000000..00b0a948 --- /dev/null +++ b/47.permutations-ii.js @@ -0,0 +1,33 @@ +/** + * @param {number[]} nums + * @return {number[][]} + */ +const permuteUnique = function(nums) { + const result = []; + if (nums == null || nums.length === 0) { + return result; + } + const map = {}; + for (let n of nums) { + map[n] = map.hasOwnProperty(n) ? map[n] + 1 : 1; + } + permuteUniqueHelper(map, nums.length, [], 0, result); + return result; +}; + +function permuteUniqueHelper(m, l, p, i, r) { + if (l === i) { + r.push(p.slice(0, l)); + return; + } + for (let key of Object.keys(m)) { + if (m[key] > 0) { + m[key] = m[key] - 1; + p[i] = key; + permuteUniqueHelper(m, l, p, i + 1, r); + m[key] = m[key] + 1; + } + } +} + + diff --git a/470-implement-rand10-using-rand7.js b/470-implement-rand10-using-rand7.js deleted file mode 100644 index eef7543c..00000000 --- a/470-implement-rand10-using-rand7.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * The rand7() API is already defined for you. - * var rand7 = function() {} - * @return {number} a random integer in the range 1 to 7 - */ -const rand10 = function() { - let result = 40 - while (result >= 40) { - result = 7 * (rand7() - 1) + (rand7() - 1) - } - return (result % 10) + 1 -} - -// another - -/** - * The rand7() API is already defined for you. - * var rand7 = function() {} - * @return {number} a random integer in the range 1 to 7 - */ -const rand10 = function() { - let tmp = 40 - while(tmp >= 40) tmp = 7 * (rand7() - 1) + (rand7() - 1) - - return tmp % 10 + 1 -}; diff --git a/470.implement-rand10-using-rand7.js b/470.implement-rand10-using-rand7.js new file mode 100644 index 00000000..7f192fd5 --- /dev/null +++ b/470.implement-rand10-using-rand7.js @@ -0,0 +1,13 @@ +/** + * The rand7() API is already defined for you. + * var rand7 = function() {} + * @return {number} a random integer in the range 1 to 7 + */ +const rand10 = function() { + let result = 40 + while (result >= 40) { + result = 7 * (rand7() - 1) + (rand7() - 1) + } + return (result % 10) + 1 +} + diff --git a/471-encode-string-with-shortest-length.js b/471.encode-string-with-shortest-length.js similarity index 100% rename from 471-encode-string-with-shortest-length.js rename to 471.encode-string-with-shortest-length.js diff --git a/472-concatenated-words.js b/472-concatenated-words.js deleted file mode 100644 index 096a4693..00000000 --- a/472-concatenated-words.js +++ /dev/null @@ -1,143 +0,0 @@ -/** - * @param {string[]} words - * @return {string[]} - */ - -const findAllConcatenatedWordsInADict = function (words) { - const pre = new Set() - words.sort((a, b) => a.length - b.length) - const res = [] - for(let i = 0; i < words.length; i++) { - if(valid(words[i], pre)) { - res.push(words[i]) - } - pre.add(words[i]) - } - - return res - - function valid(str, set) { - if(set.size === 0) return false - const dp = Array(str.length + 1).fill(false) - dp[0] = true - for(let i = 1; i <= str.length; i++) { - for(let j = 0; j < i; j++) { - if(!dp[j]) continue - if(set.has(str.slice(j, i))) { - dp[i] = true - break - } - } - } - - return dp[str.length] - } -} - - - - -// another - -/** - * @param {string[]} words - * @return {string[]} - */ - -const findAllConcatenatedWordsInADict = function (words) { - const set = new Set(words) - const res = [] - const map = new Map() - for (let w of words) { - if (w.length < 2) continue - if (dfs(w, set, map, 0)) res.push(w) - } - return res - - function dfs(word, set, map, pos) { - if (pos > 0 && map.get(word)) return map.get(word) - if (pos > 0 && set.has(word)) { - map.set(word, true) - return map.get(word) - } - for (let i = 1; i < word.length; i++) { - const left = word.slice(0, i) - const right = word.slice(i) - if (set.has(right) && dfs(left, set, map, pos + 1)) { - map.set(word, true) - return map.get(word) - } - } - - map.set(word, false) - return false - } -} - -// another - -/** - * @param {string[]} words - * @return {string[]} - */ - -const findAllConcatenatedWordsInADict = function (words) { - const set = new Set(words) - const res = [] - const map = new Map() - - for(let word of words) { - if(dfs(word, 0)) res.push(word) - } - return res - function dfs(word, idx) { - if(map.has(word)) return map.get(word) - if(idx > 0 && set.has(word)) return true - let tmp = false - for(let i = 1; i < word.length; i++) { - const prefix = word.slice(0, i), suffix = word.slice(i) - if(set.has(prefix) && set.has(suffix)) { - tmp = true - break - } - if(set.has(prefix) && dfs(suffix, idx + 1)) { - tmp = true - break - } - } - - map.set(word, tmp) - return tmp - } -} - - -// another - -/** - * @param {string[]} words - * @return {string[]} - */ -const findAllConcatenatedWordsInADict = function(words) { - let res = [] - if (words === null || words.length == 0) return res - let set = new Set(words) - for (let word of words) { - set.delete(word) - if (dfs(word, set, '')) res.push(word) - set.add(word) - } - return res -} - -function dfs(word, set, prev) { - if (prev != '') set.add(prev) - if (set.has(word)) return true - for (let i = 1; i <= word.length; i++) { - const prefix = word.substring(0, i) - if (set.has(prefix) && dfs(word.substring(i), set, prev + prefix)) { - return true - } - } - return false -} diff --git a/472.concatenated-words.js b/472.concatenated-words.js new file mode 100644 index 00000000..3f75055f --- /dev/null +++ b/472.concatenated-words.js @@ -0,0 +1,39 @@ +/** + * @param {string[]} words + * @return {string[]} + */ + +const findAllConcatenatedWordsInADict = function (words) { + const pre = new Set() + words.sort((a, b) => a.length - b.length) + const res = [] + for(let i = 0; i < words.length; i++) { + if(valid(words[i], pre)) { + res.push(words[i]) + } + pre.add(words[i]) + } + + return res + + function valid(str, set) { + if(set.size === 0) return false + const dp = Array(str.length + 1).fill(false) + dp[0] = true + for(let i = 1; i <= str.length; i++) { + for(let j = 0; j < i; j++) { + if(!dp[j]) continue + if(set.has(str.slice(j, i))) { + dp[i] = true + break + } + } + } + + return dp[str.length] + } +} + + + + diff --git a/473-matchsticks-to-square.js b/473-matchsticks-to-square.js deleted file mode 100644 index 101edd1d..00000000 --- a/473-matchsticks-to-square.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @param {number[]} nums - * @return {boolean} - */ -const makesquare = function(nums) { - if (nums == null || nums.length < 4) return false - const sum = nums.reduce((ac, el) => ac + el, 0) - if (sum % 4 !== 0) return false - nums.sort((a, b) => b - a) - return dfs(nums, new Array(4).fill(0), 0, sum / 4) -} - -function dfs(nums, arr, idx, target) { - if (idx === nums.length) { - return true - } - for (let i = 0; i < 4; i++) { - if (arr[i] + nums[idx] > target || (i > 0 && arr[i] === arr[i - 1])) - continue - arr[i] += nums[idx] - if (dfs(nums, arr, idx + 1, target)) return true - arr[i] -= nums[idx] - } - return false -} - - - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -const makesquare = function(nums) { - if (nums.length == 0) return false - const edge = nums.reduce((accum, val) => accum + val) / 4 - nums.sort((val1, val2) => val2 - val1) - if (edge !== Math.floor(edge)) return false - const findEdge = function(target) { - if (target <= 0) return target === 0 - let newNums = [] - while (nums.length) { - let item = nums.shift() - if (findEdge(target - item)) { - nums = newNums.concat(nums) - return true - } - newNums.push(item) - } - nums = newNums - return false - } - let count = 4 - while (count) { - if (!findEdge(edge)) return false - count-- - } - return true -} - diff --git a/473.matchsticks-to-square.js b/473.matchsticks-to-square.js new file mode 100644 index 00000000..78a14e64 --- /dev/null +++ b/473.matchsticks-to-square.js @@ -0,0 +1,28 @@ +/** + * @param {number[]} nums + * @return {boolean} + */ +const makesquare = function(nums) { + if (nums == null || nums.length < 4) return false + const sum = nums.reduce((ac, el) => ac + el, 0) + if (sum % 4 !== 0) return false + nums.sort((a, b) => b - a) + return dfs(nums, new Array(4).fill(0), 0, sum / 4) +} + +function dfs(nums, arr, idx, target) { + if (idx === nums.length) { + return true + } + for (let i = 0; i < 4; i++) { + if (arr[i] + nums[idx] > target || (i > 0 && arr[i] === arr[i - 1])) + continue + arr[i] += nums[idx] + if (dfs(nums, arr, idx + 1, target)) return true + arr[i] -= nums[idx] + } + return false +} + + + diff --git a/474-ones-and-zeroes.js b/474.ones-and-zeroes.js similarity index 100% rename from 474-ones-and-zeroes.js rename to 474.ones-and-zeroes.js diff --git a/475-heaters.js b/475-heaters.js deleted file mode 100644 index 316c0f51..00000000 --- a/475-heaters.js +++ /dev/null @@ -1,70 +0,0 @@ -/** - * @param {number[]} houses - * @param {number[]} heaters - * @return {number} - */ -const findRadius = function(houses, heaters) { - heaters.sort((a, b) => a - b) - return Math.max(...houses.map(h => findMinDistance(h, heaters))) -} - -const findMinDistance = (house, heaters) => { - let left = 0 - let right = heaters.length - 1 - while (left <= right) { - const mid = left + ((right - left) >> 1) - if (heaters[mid] <= house && house <= heaters[mid + 1]) { - return Math.min(house - heaters[mid], heaters[mid + 1] - house) - } else if (heaters[mid] <= house) { - left = mid + 1 - } else { - right = mid - 1 - } - } - if (left === 0) return heaters[0] - house - if (left === heaters.length) return house - heaters[heaters.length - 1] -} - -// another - -/** - * @param {number[]} houses - * @param {number[]} heaters - * @return {number} - */ -const findRadius = function(houses, heaters) { - let res = 0 - let k = 0 - houses = houses.sort((a, b) => a - b) - heaters = heaters.sort((a, b) => a - b) - for (let i = 0; i < houses.length; i++) { - const curr = houses[i] - while ( - k < heaters.length && - Math.abs(heaters[k + 1] - curr) <= Math.abs(heaters[k] - curr) - ) { - k++ - } - res = Math.max(res, Math.abs(heaters[k] - curr)) - } - return res -} - -// another - -/** - * @param {number[]} houses - * @param {number[]} heaters - * @return {number} - */ -const findRadius = function(houses, heaters) { - heaters.sort((a, b) => a - b) - houses.sort((a, b) => a - b) - let res = 0, i = 0 - for(let h of houses) { - while(i < heaters.length - 1 && heaters[i] + heaters[i + 1] <= h * 2) i++ - res = Math.max(res, Math.abs(heaters[i] - h)) - } - return res -} - diff --git a/475.heaters.js b/475.heaters.js new file mode 100644 index 00000000..54320dbc --- /dev/null +++ b/475.heaters.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} houses + * @param {number[]} heaters + * @return {number} + */ +const findRadius = function(houses, heaters) { + heaters.sort((a, b) => a - b) + return Math.max(...houses.map(h => findMinDistance(h, heaters))) +} + +const findMinDistance = (house, heaters) => { + let left = 0 + let right = heaters.length - 1 + while (left <= right) { + const mid = left + ((right - left) >> 1) + if (heaters[mid] <= house && house <= heaters[mid + 1]) { + return Math.min(house - heaters[mid], heaters[mid + 1] - house) + } else if (heaters[mid] <= house) { + left = mid + 1 + } else { + right = mid - 1 + } + } + if (left === 0) return heaters[0] - house + if (left === heaters.length) return house - heaters[heaters.length - 1] +} + diff --git a/476-number-complement.js b/476.number-complement.js similarity index 100% rename from 476-number-complement.js rename to 476.number-complement.js diff --git a/477-total-hamming-distance.js b/477-total-hamming-distance.js deleted file mode 100755 index cf1bf8fc..00000000 --- a/477-total-hamming-distance.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const totalHammingDistance = function(nums) { - let total = 0, - n = nums.length; - for (let j = 0; j < 32; j++) { - let bitCount = 0; - for (let i = 0; i < n; i++) bitCount += (nums[i] >> j) & 1; - total += bitCount * (n - bitCount); - } - return total; -}; diff --git a/477.total-hamming-distance.js b/477.total-hamming-distance.js new file mode 100644 index 00000000..fb86ef4a --- /dev/null +++ b/477.total-hamming-distance.js @@ -0,0 +1,14 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const totalHammingDistance = function(nums) { + let total = 0, + n = nums.length; + for (let j = 0; j < 32; j++) { + let bitCount = 0; + for (let i = 0; i < n; i++) bitCount += (nums[i] >> j) & 1; + total += bitCount * (n - bitCount); + } + return total; +}; diff --git a/478-generate-random-point-in-a-circle.js b/478.generate-random-point-in-a-circle.js similarity index 100% rename from 478-generate-random-point-in-a-circle.js rename to 478.generate-random-point-in-a-circle.js diff --git a/479-largest-palindrome-product.js b/479-largest-palindrome-product.js deleted file mode 100644 index 429c8aa4..00000000 --- a/479-largest-palindrome-product.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -function largestPalindrome(n) { - if(n === 1) return 9 - let max = BigInt(10 ** n - 1), min = max / 10n + 1n - for(let h = max; h >= min; h--) { - let left = h, right = 0n - for(let i = h; i !== 0n; ) { - right = right * 10n + i % 10n - i = i / 10n - left *= 10n - } - let pal = left + right - for(let i = max; i >= min; i--) { - let j = pal / i - if(j > i) break - if(pal % i === 0n) return pal % 1337n - } - } -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const largestPalindrome = function (n) { - if (n === 1) return 9 - for (let i = 2, limit = 9 * 10 ** (n - 1); i < limit; i++) { - let left = 10 ** n - i - let right = +('' + left).split('').reverse().join('') - if (i ** 2 - 4 * right < 0) continue - const tmp = (i ** 2 - 4 * right) ** 0.5 - if (tmp === Math.floor(tmp)) { - return ( - (BigInt(right) + 10n ** BigInt(n) * (10n ** BigInt(n) - BigInt(i))) % - 1337n - ) - } - } -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const largestPalindrome = function(n) { - if (n === 1) { - return 9 - } else if (n === 8) { - return 475 - } - let max = Math.pow(10, n) - let min = Math.pow(10, n - 1) - let ret = 0 - - for (let i = max - 1; i > 0; i--) { - ret = i * max + getReverse(i) - for (let factor = ~~Math.sqrt(ret); factor < max; factor++) { - if (ret % factor == 0 && ret / factor < max) { - return ret % 1337 - } - } - } - return -1 -} - -function getReverse(n) { - let result = 0 - let num = n - while (num > 0) { - result = result * 10 + (num % 10) - num = ~~(num / 10) - } - return result -} diff --git a/479.largest-palindrome-product.js b/479.largest-palindrome-product.js new file mode 100644 index 00000000..e264495f --- /dev/null +++ b/479.largest-palindrome-product.js @@ -0,0 +1,23 @@ +/** + * @param {number} n + * @return {number} + */ +function largestPalindrome(n) { + if(n === 1) return 9 + let max = BigInt(10 ** n - 1), min = max / 10n + 1n + for(let h = max; h >= min; h--) { + let left = h, right = 0n + for(let i = h; i !== 0n; ) { + right = right * 10n + i % 10n + i = i / 10n + left *= 10n + } + let pal = left + right + for(let i = max; i >= min; i--) { + let j = pal / i + if(j > i) break + if(pal % i === 0n) return pal % 1337n + } + } +} + diff --git a/48-rotate-image.js b/48-rotate-image.js deleted file mode 100644 index 83583d57..00000000 --- a/48-rotate-image.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @param {number[][]} matrix - * @return {void} Do not return anything, modify matrix in-place instead. - */ -const rotate = function(matrix) { - let s = 0, - e = matrix.length - 1 - while (s < e) { - let temp = matrix[s] - matrix[s] = matrix[e] - matrix[e] = temp - s++ - e-- - } - - for (let i = 0; i < matrix.length; i++) { - for (let j = i + 1; j < matrix[i].length; j++) { - let temp = matrix[i][j] - matrix[i][j] = matrix[j][i] - matrix[j][i] = temp - } - } -} - -// another - -/** - * @param {number[][]} matrix - * @return {void} Do not return anything, modify matrix in-place instead. - */ -const rotate = function (matrix) { - matrix.reverse() - for (let i = 0; i < matrix.length; ++i) { - for (let j = i + 1; j < matrix[i].length; ++j) swap(matrix, i, j) - } -} - -function swap(matrix, i, j) { - const tmp = matrix[j][i] - matrix[j][i] = matrix[i][j] - matrix[i][j] = tmp -} - -// another - -/** - * @param {number[][]} matrix - * @return {void} Do not return anything, modify matrix in-place instead. - */ -const rotate = function (matrix) { - matrix.reverse() - for (let i = 0; i < matrix.length; ++i) { - for (let j = matrix[i].length - 1; j > i; j--) swap(matrix, i, j) - } -} - -function swap(matrix, i, j) { - const tmp = matrix[j][i] - matrix[j][i] = matrix[i][j] - matrix[i][j] = tmp -} -/* -1 2 3 7 8 9 7 4 1 -4 5 6 ---> 4 5 6 --->8 5 2 -7 8 9 1 2 3 9 6 3 -*/ diff --git a/48.rotate-image.js b/48.rotate-image.js new file mode 100644 index 00000000..2028d5a0 --- /dev/null +++ b/48.rotate-image.js @@ -0,0 +1,24 @@ +/** + * @param {number[][]} matrix + * @return {void} Do not return anything, modify matrix in-place instead. + */ +const rotate = function(matrix) { + let s = 0, + e = matrix.length - 1 + while (s < e) { + let temp = matrix[s] + matrix[s] = matrix[e] + matrix[e] = temp + s++ + e-- + } + + for (let i = 0; i < matrix.length; i++) { + for (let j = i + 1; j < matrix[i].length; j++) { + let temp = matrix[i][j] + matrix[i][j] = matrix[j][i] + matrix[j][i] = temp + } + } +} + diff --git a/480-sliding-window-median.js b/480-sliding-window-median.js deleted file mode 100644 index a57beed9..00000000 --- a/480-sliding-window-median.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - * @lc app=leetcode id=480 lang=javascript - * - * [480] Sliding Window Median - */ -/** - * @param {number[]} nums - * @param {number} k - * @return {number[]} - */ -const medianSlidingWindow = function(nums, k) { - const window = nums.slice(0, k).sort((x, y) => x - y) - const resultLen = nums.length - k + 1 - nums.push(0) - - function insert(arr, val) { - let i = 0 - while (i < arr.length && arr[i] < val) { - i++ - } - arr.splice(i, 0, val) - } - - const medians = [] - const rightIdx = (k / 2) >>> 0 - const leftIdx = k + ~rightIdx - for (let i = 0; i < resultLen; i++) { - medians.push((window[leftIdx] + window[rightIdx]) / 2) - window.splice(window.indexOf(nums[i]), 1) - insert(window, nums[k + i]) - } - return medians -} - -// another - -const medianSlidingWindow = function(nums, k) { - let pq = [] - for (let i = 0; i < k; i++) { - insert(nums[i]) - } - let res = [] - res.push(findMid()) - for (let i = k; i < nums.length; i++) { - remove(nums[i - k]) - insert(nums[i]) - res.push(findMid()) - } - return res - function findMid() { - let mid = (pq.length - 1) / 2 - return (pq[Math.ceil(mid)] + pq[Math.floor(mid)]) / 2 - } - function insert(n) { - if (pq.length === 0 || pq[pq.length - 1] <= n) { - pq.push(n) - } else { - let idx = bsEnd(pq, n) - pq.splice(idx, 0, n) - } - } - function bsEnd(arr, n) { - let lo = 0, - hi = arr.length - 1 - while (lo < hi) { - let mid = Math.floor((lo + hi) / 2) - if (arr[mid] < n) lo = mid + 1 - else hi = mid - } - return hi - } - function remove(n) { - let idx = bsEnd(pq, n) - pq.splice(idx, 1) - } -} diff --git a/480.sliding-window-median.js b/480.sliding-window-median.js new file mode 100644 index 00000000..1b13eeb3 --- /dev/null +++ b/480.sliding-window-median.js @@ -0,0 +1,34 @@ +/* + * @lc app=leetcode id=480 lang=javascript + * + * [480] Sliding Window Median + */ +/** + * @param {number[]} nums + * @param {number} k + * @return {number[]} + */ +const medianSlidingWindow = function(nums, k) { + const window = nums.slice(0, k).sort((x, y) => x - y) + const resultLen = nums.length - k + 1 + nums.push(0) + + function insert(arr, val) { + let i = 0 + while (i < arr.length && arr[i] < val) { + i++ + } + arr.splice(i, 0, val) + } + + const medians = [] + const rightIdx = (k / 2) >>> 0 + const leftIdx = k + ~rightIdx + for (let i = 0; i < resultLen; i++) { + medians.push((window[leftIdx] + window[rightIdx]) / 2) + window.splice(window.indexOf(nums[i]), 1) + insert(window, nums[k + i]) + } + return medians +} + diff --git a/481-magical-string.js b/481.magical-string.js similarity index 100% rename from 481-magical-string.js rename to 481.magical-string.js diff --git a/482-license-key-formatting.js b/482.license-key-formatting.js similarity index 100% rename from 482-license-key-formatting.js rename to 482.license-key-formatting.js diff --git a/483-smallest-good-base.js b/483.smallest-good-base.js similarity index 100% rename from 483-smallest-good-base.js rename to 483.smallest-good-base.js diff --git a/484-find-permutation.js b/484-find-permutation.js deleted file mode 100644 index 18d3d441..00000000 --- a/484-find-permutation.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @param {string} s - * @return {number[]} - */ -const findPermutation = function(s) { - const n = s.length - const res = Array(n + 1) - res[n] = n + 1 - for (let i = 0, len = n; i < len;) { - let j = i; - while (j < len && s.charAt(j) === 'D') { - j++; - } - for (let k = j - i; k >= 0; k--, j--) { - res[i++] = j + 1; - } - } - return res; -}; - -// another - -/** - * @param {string} s - * @return {number[]} - */ -const findPermutation = function(s) { - const n = s.length - const res = Array(n) - res[n] = n + 1 - for(let i = 0; i < n;) { - let j = i - while(j < n && s[j] === 'D') j++ - // console.log(j) - for(let k = j - i + 1; k > 0; k--) { - res[i] = j + 1 - i++ - j-- - } - } - - return res -}; - - -// another - -/** - * @param {string} s - * @return {number[]} - */ -const findPermutation = function(s) { - const n = s.length - const arr = Array.from({ length: n + 1 }, (el, idx) => idx + 1) - for(let h = 0; h < n; h++) { - if(s.charAt(h) === 'D') { - const l = h - while(h < n && s.charAt(h) === 'D') h++ - reverse(arr, l, h) - } - } - return arr -}; - -function reverse(arr, l, h) { - while(l < h) { - arr[l] ^= arr[h] - arr[h] ^= arr[l] - arr[l] ^= arr[h] - l++, h-- - } -} diff --git a/484.find-permutation.js b/484.find-permutation.js new file mode 100644 index 00000000..9168041e --- /dev/null +++ b/484.find-permutation.js @@ -0,0 +1,20 @@ +/** + * @param {string} s + * @return {number[]} + */ +const findPermutation = function(s) { + const n = s.length + const res = Array(n + 1) + res[n] = n + 1 + for (let i = 0, len = n; i < len;) { + let j = i; + while (j < len && s.charAt(j) === 'D') { + j++; + } + for (let k = j - i; k >= 0; k--, j--) { + res[i++] = j + 1; + } + } + return res; +}; + diff --git a/485-max-consecutive-ones.js b/485.max-consecutive-ones.js old mode 100755 new mode 100644 similarity index 100% rename from 485-max-consecutive-ones.js rename to 485.max-consecutive-ones.js diff --git a/486-predict-the-winner.js b/486-predict-the-winner.js deleted file mode 100755 index f9c69836..00000000 --- a/486-predict-the-winner.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @param {number[]} nums - * @return {boolean} - */ -const PredictTheWinner = function(nums) { - // The dp[i][j] saves how much more scores that the first-in-action player will get from i to j than the second player. - const dp = []; - for (let i = 0; i <= nums.length; i++) { - dp.push(Array(nums.length).fill(0)); - } - for (let s = nums.length - 1; s >= 0; s--) { - dp[s][s] = nums[s]; - for (let e = s + 1; e < nums.length; e++) { - let a = nums[s] - dp[s + 1][e]; - let b = nums[e] - dp[s][e - 1]; - dp[s][e] = Math.max(a, b); - } - } - return dp[0][nums.length - 1] >= 0; -}; - -console.log(PredictTheWinner([1, 5, 233, 7])); -console.log(PredictTheWinner([3, 5, 3])); diff --git a/486.predict-the-winner.js b/486.predict-the-winner.js new file mode 100644 index 00000000..c0ef92f2 --- /dev/null +++ b/486.predict-the-winner.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} nums + * @return {boolean} + */ +const PredictTheWinner = function(nums) { + // The dp[i][j] saves how much more scores that the first-in-action player will get from i to j than the second player. + const dp = []; + for (let i = 0; i <= nums.length; i++) { + dp.push(Array(nums.length).fill(0)); + } + for (let s = nums.length - 1; s >= 0; s--) { + dp[s][s] = nums[s]; + for (let e = s + 1; e < nums.length; e++) { + let a = nums[s] - dp[s + 1][e]; + let b = nums[e] - dp[s][e - 1]; + dp[s][e] = Math.max(a, b); + } + } + return dp[0][nums.length - 1] >= 0; +}; + +console.log(PredictTheWinner([1, 5, 233, 7])); +console.log(PredictTheWinner([3, 5, 3])); diff --git a/487-max-consecutive-ones-ii.js b/487.max-consecutive-ones-ii.js similarity index 100% rename from 487-max-consecutive-ones-ii.js rename to 487.max-consecutive-ones-ii.js diff --git a/488-zuma-game.js b/488.zuma-game.js similarity index 100% rename from 488-zuma-game.js rename to 488.zuma-game.js diff --git a/489-robot-room-cleaner.js b/489-robot-room-cleaner.js deleted file mode 100644 index b1c55cef..00000000 --- a/489-robot-room-cleaner.js +++ /dev/null @@ -1,101 +0,0 @@ -/** - * // This is the robot's control interface. - * // You should not implement it, or speculate about its implementation - * function Robot() { - * - * // Returns true if the cell in front is open and robot moves into the cell. - * // Returns false if the cell in front is blocked and robot stays in the current cell. - * @return {boolean} - * this.move = function() { - * ... - * }; - * - * // Robot will stay in the same cell after calling turnLeft/turnRight. - * // Each turn will be 90 degrees. - * @return {void} - * this.turnLeft = function() { - * ... - * }; - * - * // Robot will stay in the same cell after calling turnLeft/turnRight. - * // Each turn will be 90 degrees. - * @return {void} - * this.turnRight = function() { - * ... - * }; - * - * // Clean the current cell. - * @return {void} - * this.clean = function() { - * ... - * }; - * }; - */ -/** - * @param {Robot} robot - * @return {void} - */ -const cleanRoom = function(robot) { - const visited = new Set() - const shift = [ - [-1, 0], - [0, 1], - [1, 0], - [0, -1] - ] - dfs(0, 0, 0) - function dfs(r, c, dir) { - visited.add(r + ',' + c) - robot.clean() - for (let i = 0; i < 4; i++) { - const newDir = (dir + i) % 4 - const x = shift[newDir][0] + r - const y = shift[newDir][1] + c - if (!visited.has(x + ',' + y) && robot.move()) { - dfs(x, y, newDir) - robot.turnRight() - robot.turnRight() - robot.move() - robot.turnRight() - robot.turnRight() - } - robot.turnRight() - } - } -} - -// another - -/** - * @param {Robot} robot - * @return {void} - */ -const cleanRoom = function(robot) { - const dirs = [ - [-1, 0], - [0, 1], - [1, 0], - [0, -1] - ] - const visited = new Set() - clean(0, 0, 0) - function clean( x, y, curDirection) { - robot.clean() - visited.add(`${x},${y}`) - for(let i = curDirection; i < curDirection + 4; i++) { - const nx = dirs[i % 4][0] + x - const ny = dirs[i % 4][1] + y - if(!visited.has(`${nx},${ny}`) && robot.move()) { - clean(nx, ny, i % 4) - } - robot.turnRight() - } - robot.turnRight() - robot.turnRight() - robot.move() - robot.turnRight() - robot.turnRight() - - } -}; - diff --git a/489.robot-room-cleaner.js b/489.robot-room-cleaner.js new file mode 100644 index 00000000..3b444d48 --- /dev/null +++ b/489.robot-room-cleaner.js @@ -0,0 +1,66 @@ +/** + * // This is the robot's control interface. + * // You should not implement it, or speculate about its implementation + * function Robot() { + * + * // Returns true if the cell in front is open and robot moves into the cell. + * // Returns false if the cell in front is blocked and robot stays in the current cell. + * @return {boolean} + * this.move = function() { + * ... + * }; + * + * // Robot will stay in the same cell after calling turnLeft/turnRight. + * // Each turn will be 90 degrees. + * @return {void} + * this.turnLeft = function() { + * ... + * }; + * + * // Robot will stay in the same cell after calling turnLeft/turnRight. + * // Each turn will be 90 degrees. + * @return {void} + * this.turnRight = function() { + * ... + * }; + * + * // Clean the current cell. + * @return {void} + * this.clean = function() { + * ... + * }; + * }; + */ +/** + * @param {Robot} robot + * @return {void} + */ +const cleanRoom = function(robot) { + const visited = new Set() + const shift = [ + [-1, 0], + [0, 1], + [1, 0], + [0, -1] + ] + dfs(0, 0, 0) + function dfs(r, c, dir) { + visited.add(r + ',' + c) + robot.clean() + for (let i = 0; i < 4; i++) { + const newDir = (dir + i) % 4 + const x = shift[newDir][0] + r + const y = shift[newDir][1] + c + if (!visited.has(x + ',' + y) && robot.move()) { + dfs(x, y, newDir) + robot.turnRight() + robot.turnRight() + robot.move() + robot.turnRight() + robot.turnRight() + } + robot.turnRight() + } + } +} + diff --git a/49-group-anagrams.js b/49-group-anagrams.js deleted file mode 100755 index dfffbb2f..00000000 --- a/49-group-anagrams.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @param {string[]} strs - * @return {string[][]} - */ -const groupAnagrams = (strs) => { - const resp = new Array(), - termsGrouped = new Map() - strs.forEach((term) => { - const hashed = hash(term) - if (!termsGrouped.has(hashed)) termsGrouped.set(hashed, new Array()) - termsGrouped.get(hashed).push(term) - }) - termsGrouped.forEach((terms) => { - resp.push(terms) - }) - return resp -} - -const hash = (term) => { - const arr = Array(26).fill(0) - const a = 'a'.charCodeAt(0) - for(let i = 0, len = term.length; i < len; i++) { - arr[term[i].charCodeAt(0) - a]++ - } - return arr.join('-') -} - -// another - -/** - * @param {string[]} strs - * @return {string[][]} - */ -const groupAnagrams = function(strs) { - if (strs.length === 0) { - return []; - } - const ans = []; - const hash = {}; - for (let el of strs) { - let sel = el - .split("") - .sort() - .join(""); - if (hash.hasOwnProperty(sel)) { - hash[sel].push(el); - } else { - hash[sel] = [el]; - } - } - return Object.values(hash); -}; diff --git a/49.group-anagrams.js b/49.group-anagrams.js new file mode 100644 index 00000000..6f55eff7 --- /dev/null +++ b/49.group-anagrams.js @@ -0,0 +1,27 @@ +/** + * @param {string[]} strs + * @return {string[][]} + */ +const groupAnagrams = (strs) => { + const resp = new Array(), + termsGrouped = new Map() + strs.forEach((term) => { + const hashed = hash(term) + if (!termsGrouped.has(hashed)) termsGrouped.set(hashed, new Array()) + termsGrouped.get(hashed).push(term) + }) + termsGrouped.forEach((terms) => { + resp.push(terms) + }) + return resp +} + +const hash = (term) => { + const arr = Array(26).fill(0) + const a = 'a'.charCodeAt(0) + for(let i = 0, len = term.length; i < len; i++) { + arr[term[i].charCodeAt(0) - a]++ + } + return arr.join('-') +} + diff --git a/490-the-maze.js b/490-the-maze.js deleted file mode 100644 index a19f6cb2..00000000 --- a/490-the-maze.js +++ /dev/null @@ -1,215 +0,0 @@ -/** - -There is a ball in a maze with empty spaces and walls. -The ball can go through empty spaces by rolling up, down, left or right, -but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction. -Given the ball's start position, the destination and the maze, determine whether the ball could stop at the destination. - -The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. -You may assume that the borders of the maze are all walls. -The start and destination coordinates are represented by row and column indexes. - -Example 1: - -Input 1: a maze represented by a 2D array - -0 0 1 0 0 -0 0 0 0 0 -0 0 0 1 0 -1 1 0 1 1 -0 0 0 0 0 - -Input 2: start coordinate (rowStart, colStart) = (0, 4) -Input 3: destination coordinate (rowDest, colDest) = (4, 4) - -Output: true - -Explanation: One possible way is : left -> down -> left -> down -> right -> down -> right. - -Example 2: - -Input 1: a maze represented by a 2D array - -0 0 1 0 0 -0 0 0 0 0 -0 0 0 1 0 -1 1 0 1 1 -0 0 0 0 0 - -Input 2: start coordinate (rowStart, colStart) = (0, 4) -Input 3: destination coordinate (rowDest, colDest) = (3, 2) - -Output: false - -Explanation: There is no way for the ball to stop at the destination. - -Note: - -There is only one ball and one destination in the maze. -Both the ball and the destination exist on an empty space, and they will not be at the same position initially. -The given maze does not contain border (like the red rectangle in the example pictures), -but you could assume the border of the maze are all walls. -The maze contains at least 2 empty spaces, and both the width and height of the maze won't exceed 100. - -*/ - -/** - * @param {number[][]} maze - * @param {number[]} start - * @param {number[]} destination - * @return {boolean} - */ -const hasPath = function(maze, start, destination) { - const m = maze.length - const n = maze[0].length - const queue = [] - const visited = Array.from({ length: m }, () => new Array(n).fill(false)) - queue.push(start) - const dirs = [ - [-1, 0], - [0, -1], - [0, 1], - [1, 0] - ] - while (queue.length) { - const cur = queue.shift() - if (cur[0] === destination[0] && cur[1] === destination[1]) return true - if (visited[cur[0]][cur[1]]) continue - visited[cur[0]][cur[1]] = true - for (let dir of dirs) { - let x = cur[0], - y = cur[1] - while (x >= 0 && x < m && y >= 0 && y < n && maze[x][y] === 0) { - x += dir[0] - y += dir[1] - } - x -= dir[0] - y -= dir[1] - queue.push([x, y]) - } - } - return false -} - -// another - -/** - * @param {number[][]} maze - * @param {number[]} start - * @param {number[]} destination - * @return {boolean} - */ -const hasPath = function(maze, start, destination) { - const visited = Array.from({ length: maze.length }, () => - new Array(maze[0].length).fill(false) - ) - const dirs = [ - [-1, 0], - [0, -1], - [0, 1], - [1, 0] - ] - return dfs(maze, start, destination, visited, dirs) -} - -function dfs(maze, start, destination, visited, dirs) { - if (visited[start[0]][start[1]]) return false - if (start[0] === destination[0] && start[1] === destination[1]) return true - visited[start[0]][start[1]] = true - for (let i = 0; i < dirs.length; i++) { - const d = dirs[i] - let row = start[0] - let col = start[1] - while (isValid(maze, row + d[0], col + d[1])) { - row += d[0] - col += d[1] - } - if (dfs(maze, [row, col], destination, visited, dirs)) return true - } - return false -} - -function isValid(maze, row, col) { - return ( - row >= 0 && - row < maze.length && - col >= 0 && - col < maze[0].length && - maze[row][col] !== 1 - ) -} - -// another - -/** - * @param {number[][]} maze - * @param {number[]} start - * @param {number[]} destination - * @return {boolean} - */ -const hasPath = function(maze, start, destination) { - const m = maze.length, n = maze[0].length - const dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]] - const visited = new Set() - let res = false - dfs(start[0], start[1]) - return res - - function dfs(i, j) { - if(i < 0 || i >= m || j < 0 || j >= n || maze[i][j] === 1 || visited.has(`${i},${j}`)) return - if(i === destination[0] && j === destination[1]) { - res = true - return - } - visited.add(`${i},${j}`) - const ib = i, jb = j - for(const [dx, dy] of dirs) { - let ii = i, jj = j - while( - ii + dx >= 0 && - ii + dx < m && - jj + dy >= 0 && - jj + dy < n && - maze[ii + dx][jj + dy] === 0 - ) { - ii += dx - jj += dy - } - dfs(ii, jj) - } - } -}; - -// another - -/** - * @param {number[][]} maze - * @param {number[]} start - * @param {number[]} destination - * @return {boolean} - */ -const hasPath = function(maze, start, destination) { - const m = maze.length, n = maze[0].length - const dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]] - const visited = new Set() - const q = [start] - while(q.length) { - const [i, j] = q.pop() - if(i === destination[0] && j === destination[1]) return true - visited.add(`${i},${j}`) - for(const [dx, dy] of dirs) { - let ni = i, nj = j - while(valid(ni + dx, nj + dy)) { - ni += dx - nj += dy - } - if(!visited.has(`${ni},${nj}`)) q.push([ni, nj]) - } - } - - return false - - function valid(i, j) { - return i >= 0 && i < m && j >= 0 && j < n && maze[i][j] === 0 - } -}; diff --git a/490.the-maze.js b/490.the-maze.js new file mode 100644 index 00000000..8fbbce6e --- /dev/null +++ b/490.the-maze.js @@ -0,0 +1,93 @@ +/** + +There is a ball in a maze with empty spaces and walls. +The ball can go through empty spaces by rolling up, down, left or right, +but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction. +Given the ball's start position, the destination and the maze, determine whether the ball could stop at the destination. + +The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. +You may assume that the borders of the maze are all walls. +The start and destination coordinates are represented by row and column indexes. + +Example 1: + +Input 1: a maze represented by a 2D array + +0 0 1 0 0 +0 0 0 0 0 +0 0 0 1 0 +1 1 0 1 1 +0 0 0 0 0 + +Input 2: start coordinate (rowStart, colStart) = (0, 4) +Input 3: destination coordinate (rowDest, colDest) = (4, 4) + +Output: true + +Explanation: One possible way is : left -> down -> left -> down -> right -> down -> right. + +Example 2: + +Input 1: a maze represented by a 2D array + +0 0 1 0 0 +0 0 0 0 0 +0 0 0 1 0 +1 1 0 1 1 +0 0 0 0 0 + +Input 2: start coordinate (rowStart, colStart) = (0, 4) +Input 3: destination coordinate (rowDest, colDest) = (3, 2) + +Output: false + +Explanation: There is no way for the ball to stop at the destination. + +Note: + +There is only one ball and one destination in the maze. +Both the ball and the destination exist on an empty space, and they will not be at the same position initially. +The given maze does not contain border (like the red rectangle in the example pictures), +but you could assume the border of the maze are all walls. +The maze contains at least 2 empty spaces, and both the width and height of the maze won't exceed 100. + +*/ + +/** + * @param {number[][]} maze + * @param {number[]} start + * @param {number[]} destination + * @return {boolean} + */ +const hasPath = function(maze, start, destination) { + const m = maze.length + const n = maze[0].length + const queue = [] + const visited = Array.from({ length: m }, () => new Array(n).fill(false)) + queue.push(start) + const dirs = [ + [-1, 0], + [0, -1], + [0, 1], + [1, 0] + ] + while (queue.length) { + const cur = queue.shift() + if (cur[0] === destination[0] && cur[1] === destination[1]) return true + if (visited[cur[0]][cur[1]]) continue + visited[cur[0]][cur[1]] = true + for (let dir of dirs) { + let x = cur[0], + y = cur[1] + while (x >= 0 && x < m && y >= 0 && y < n && maze[x][y] === 0) { + x += dir[0] + y += dir[1] + } + x -= dir[0] + y -= dir[1] + queue.push([x, y]) + } + } + return false +} + diff --git a/491-increasing-subsequences.js b/491.increasing-subsequences.js similarity index 100% rename from 491-increasing-subsequences.js rename to 491.increasing-subsequences.js diff --git a/492-construct-the-rectangle.js b/492.construct-the-rectangle.js similarity index 100% rename from 492-construct-the-rectangle.js rename to 492.construct-the-rectangle.js diff --git a/493-reverse-pairs.js b/493-reverse-pairs.js deleted file mode 100644 index 1ad26aa2..00000000 --- a/493-reverse-pairs.js +++ /dev/null @@ -1,115 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const reversePairs = function(nums) { - return mergeSort(nums, [], 0, nums.length-1); -}; - -function mergeSort(arr, temp, left, right){ - let mid = Math.floor((left+right)/2), count = 0; - if(left2*a[j])){ - j++; - } - count+= (j-(mid)); - } - i=left; - j=mid; - while(i<=(mid-1) && j<=right){ - if (a[i]>(a[j])) { - temp[k++] = a[j++]; - } else { - temp[k++] = a[i++]; - } - } - while(i<=(mid-1)){ - temp[k++] = a[i++]; - } - while(j<=right){ - temp[k++] = a[j++]; - } - for(let x=left; x<=right; x++){ - a[x] = temp[x]; - } - return count; -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const reversePairs = function(nums) { - return mergeSort(nums, 0, nums.length - 1); -}; - -function mergeSort(nums, s, e) { - if (s >= e) return 0; - let mid = s + Math.floor((e - s) / 2); - let cnt = mergeSort(nums, s, mid) + mergeSort(nums, mid + 1, e); - for (let i = s, j = mid + 1; i <= mid; i++) { - while (j <= e && nums[i] / 2.0 > nums[j]) j++; - cnt += j - (mid + 1); - } - sortSubArr(nums, s, e + 1); - return cnt; -} - -function sortSubArr(arr, s, e) { - const tmp = arr.slice(s, e); - tmp.sort((a, b) => a - b); - arr.splice(s, e - s, ...tmp); -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -function merge(A, start, mid, end) { - let n1 = mid - start + 1 - let n2 = end - mid - const L = new Array(n1).fill(0) - const R = new Array(n2).fill(0) - - for (let i = 0; i < n1; i++) L[i] = A[start + i] - for (let j = 0; j < n2; j++) R[j] = A[mid + 1 + j] - let i = 0, - j = 0 - for (let k = start; k <= end; k++) { - if (j >= n2 || (i < n1 && L[i] <= R[j])) A[k] = L[i++] - else A[k] = R[j++] - } -} - -function mergesort_and_count(A, start, end) { - if (start < end) { - let mid = start + ((end - start) >> 1) - let count = - mergesort_and_count(A, start, mid) + mergesort_and_count(A, mid + 1, end) - let j = mid + 1 - for (let i = start; i <= mid; i++) { - while (j <= end && A[i] > A[j] * 2) j++ - count += j - (mid + 1) - } - merge(A, start, mid, end) - return count - } else return 0 -} - -function reversePairs(nums) { - return mergesort_and_count(nums, 0, nums.length - 1) -} diff --git a/493.reverse-pairs.js b/493.reverse-pairs.js new file mode 100644 index 00000000..4d300fc3 --- /dev/null +++ b/493.reverse-pairs.js @@ -0,0 +1,47 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const reversePairs = function(nums) { + return mergeSort(nums, [], 0, nums.length-1); +}; + +function mergeSort(arr, temp, left, right){ + let mid = Math.floor((left+right)/2), count = 0; + if(left2*a[j])){ + j++; + } + count+= (j-(mid)); + } + i=left; + j=mid; + while(i<=(mid-1) && j<=right){ + if (a[i]>(a[j])) { + temp[k++] = a[j++]; + } else { + temp[k++] = a[i++]; + } + } + while(i<=(mid-1)){ + temp[k++] = a[i++]; + } + while(j<=right){ + temp[k++] = a[j++]; + } + for(let x=left; x<=right; x++){ + a[x] = temp[x]; + } + return count; +} + diff --git a/494-target-sum.js b/494-target-sum.js deleted file mode 100755 index 86e36c48..00000000 --- a/494-target-sum.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} target - * @return {number} - */ -const findTargetSumWays = function(nums, target) { - const sum = nums.reduce((a, b) => a+b); - if(Math.abs(target) > sum) { - return 0; - } - if((target + sum) % 2) { - return 0; - } - const newTarget = (target + sum) / 2; - let dp = new Array(newTarget+1).fill(0); - dp[0] = 1; - for(let i = 0; i < nums.length; i++) { - for(let j = newTarget; j >= nums[i]; j--) { - dp[j] += dp[j - nums[i]]; - } - } - return dp[newTarget]; -}; - - - -// another - -/** - * @param {number[]} nums - * @param {number} S - * @return {number} - */ -const findTargetSumWays = function(nums, s) { - const sum = nums.reduce((p, n) => p + n, 0); - return sum < s || (s + sum) % 2 > 0 ? 0 : subsetSum(nums, (s + sum) >>> 1); -}; - -function subsetSum(nums, s) { - const dp = Array(s + 1).fill(0); - dp[0] = 1; - for (let n of nums) { - for (let i = s; i >= n; i--) dp[i] += dp[i - n]; - } - return dp[s]; -} diff --git a/494.target-sum.js b/494.target-sum.js new file mode 100644 index 00000000..81a29cc1 --- /dev/null +++ b/494.target-sum.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +const findTargetSumWays = function(nums, target) { + const sum = nums.reduce((a, b) => a+b); + if(Math.abs(target) > sum) { + return 0; + } + if((target + sum) % 2) { + return 0; + } + const newTarget = (target + sum) / 2; + let dp = new Array(newTarget+1).fill(0); + dp[0] = 1; + for(let i = 0; i < nums.length; i++) { + for(let j = newTarget; j >= nums[i]; j--) { + dp[j] += dp[j - nums[i]]; + } + } + return dp[newTarget]; +}; + + + diff --git a/495-teemo-attacking.js b/495.teemo-attacking.js similarity index 100% rename from 495-teemo-attacking.js rename to 495.teemo-attacking.js diff --git a/496-next-greater-element-I.js b/496-next-greater-element-I.js deleted file mode 100755 index e3b281bb..00000000 --- a/496-next-greater-element-I.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @param {number[]} nums1 - * @param {number[]} nums2 - * @return {number[]} - */ -const nextGreaterElement = function(nums1, nums2) { - const map = new Map() - const stk = [] - - for(let i = 0, n = nums2.length; i < n; i++) { - const e = nums2[i] - while(stk.length && stk.at(-1) < e) { - const tmp = stk.pop() - map.set(tmp, e) - } - stk.push(e) - } - - const res = [] - for(const e of nums1) { - if(map.has(e)) { - res.push(map.get(e)) - } else { - res.push(-1) - } - } - - return res -}; - -// another - -/** - * @param {number[]} findNums - * @param {number[]} nums - * @return {number[]} - */ -const nextGreaterElement = function(findNums, nums) { - const map = {}; - const stack = []; - for (let num of nums) { - while (stack.length && stack[stack.length - 1] < num) { - let tmp = stack.pop(); - map[tmp] = num; - } - stack.push(num); - } - for (let i = 0; i < findNums.length; i++) { - findNums[i] = map[findNums[i]] == null ? -1 : map[findNums[i]]; - } - - return findNums; -}; - -console.log(nextGreaterElement([4, 1, 2], [1, 3, 4, 2])); -console.log(nextGreaterElement([2, 4], [1, 2, 3, 4])); -console.log(nextGreaterElement([1, 2, 3], [9, 8, 7, 3, 2, 1, 6])); diff --git a/496.next-greater-element-I.js b/496.next-greater-element-I.js new file mode 100644 index 00000000..c7bf4894 --- /dev/null +++ b/496.next-greater-element-I.js @@ -0,0 +1,30 @@ +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number[]} + */ +const nextGreaterElement = function(nums1, nums2) { + const map = new Map() + const stk = [] + + for(let i = 0, n = nums2.length; i < n; i++) { + const e = nums2[i] + while(stk.length && stk.at(-1) < e) { + const tmp = stk.pop() + map.set(tmp, e) + } + stk.push(e) + } + + const res = [] + for(const e of nums1) { + if(map.has(e)) { + res.push(map.get(e)) + } else { + res.push(-1) + } + } + + return res +}; + diff --git a/497-random-point-in-non-overlapping-rectangles.js b/497-random-point-in-non-overlapping-rectangles.js deleted file mode 100644 index 1dc372ac..00000000 --- a/497-random-point-in-non-overlapping-rectangles.js +++ /dev/null @@ -1,78 +0,0 @@ -/** - * @param {number[][]} rects - */ -const Solution = function(rects) { - this.rects = rects - this.areas = rects.map(([x1, y1, x2, y2]) => (x2 - x1 + 1) * (y2 - y1 + 1)) -} - -/** - * @return {number[]} - */ -Solution.prototype.pick = function() { - const { rects, areas } = this - let areaSum = 0 - let selected - for (let i = 0; i < rects.length; i++) { - const area = areas[i] - areaSum += area - const p = area / areaSum - if (Math.random() < p) { - selected = rects[i] - } - } - const [x1, y1, x2, y2] = selected - return [ - ((Math.random() * (x2 - x1 + 1)) | 0) + x1, - ((Math.random() * (y2 - y1 + 1)) | 0) + y1 - ] -} -/** - * Your Solution object will be instantiated and called as such: - * var obj = new Solution(rects) - * var param_1 = obj.pick() - */ - -// another - -/** - * @param {number[][]} rects - */ -const Solution = function(rects) { - const xywhs = [] - const acc_sums = [0] - let sum = 0 - for (const [x, y, x2, y2] of rects) { - const w = x2 - x + 1 - const h = y2 - y + 1 - xywhs.push({ x, y, w, h }) - sum += w * h - acc_sums.push(sum) - } - this.xywhs = xywhs - this.acc_sums = acc_sums -} - -/** - * @return {number[]} - */ -Solution.prototype.pick = function() { - const picked = Math.floor( - Math.random() * this.acc_sums[this.acc_sums.length - 1] - ) - let i = 0 - for (; i < this.acc_sums.length - 2; i++) { - if (picked >= this.acc_sums[i] && picked < this.acc_sums[i + 1]) { - break - } - } - const { x, y, w, h } = this.xywhs[i] - return [x + Math.floor(Math.random() * w), y + Math.floor(Math.random() * h)] -} - -/** - * Your Solution object will be instantiated and called as such: - * var obj = new Solution(rects) - * var param_1 = obj.pick() - */ - diff --git a/497.random-point-in-non-overlapping-rectangles.js b/497.random-point-in-non-overlapping-rectangles.js new file mode 100644 index 00000000..c38e1a0f --- /dev/null +++ b/497.random-point-in-non-overlapping-rectangles.js @@ -0,0 +1,35 @@ +/** + * @param {number[][]} rects + */ +const Solution = function(rects) { + this.rects = rects + this.areas = rects.map(([x1, y1, x2, y2]) => (x2 - x1 + 1) * (y2 - y1 + 1)) +} + +/** + * @return {number[]} + */ +Solution.prototype.pick = function() { + const { rects, areas } = this + let areaSum = 0 + let selected + for (let i = 0; i < rects.length; i++) { + const area = areas[i] + areaSum += area + const p = area / areaSum + if (Math.random() < p) { + selected = rects[i] + } + } + const [x1, y1, x2, y2] = selected + return [ + ((Math.random() * (x2 - x1 + 1)) | 0) + x1, + ((Math.random() * (y2 - y1 + 1)) | 0) + y1 + ] +} +/** + * Your Solution object will be instantiated and called as such: + * var obj = new Solution(rects) + * var param_1 = obj.pick() + */ + diff --git a/498-diagonal-traverse.js b/498-diagonal-traverse.js deleted file mode 100644 index 214b065b..00000000 --- a/498-diagonal-traverse.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @param {number[][]} matrix - * @return {number[]} - */ -const findDiagonalOrder = function(matrix) { - if (!matrix.length || !matrix[0].length) { - return [] - } - const m = matrix.length - const n = matrix[0].length - const output = [] - for (let sum = 0; sum <= m + n - 2; sum++) { - for ( - let i = Math.min(m - 1, sum); - sum % 2 === 0 && isValid(i, sum - i, m, n); - i-- - ) { - const j = sum - i - output.push(matrix[i][j]) - } - for ( - let j = Math.min(n - 1, sum); - sum % 2 === 1 && isValid(sum - j, j, m, n); - j-- - ) { - const i = sum - j - output.push(matrix[i][j]) - } - } - return output -} - -function isValid(i, j, m, n) { - if (i < 0 || i >= m || j < 0 || j >= n) { - return false - } - return true -} - -// another - -/** - * @param {number[][]} matrix - * @return {number[]} - */ -const findDiagonalOrder = function(matrix) { - if (matrix.length == 0) return [] - let r = 0, - c = 0, - m = matrix.length, - n = matrix[0].length, - arr = new Array(m * n) - for (let i = 0; i < arr.length; i++) { - arr[i] = matrix[r][c] - if ((r + c) % 2 === 0) { - // moving up - if (c === n - 1) { - r++ - } else if (r === 0) { - c++ - } else { - r-- - c++ - } - } else { - // moving down - if (r === m - 1) { - c++ - } else if (c === 0) { - r++ - } else { - r++ - c-- - } - } - } - return arr -} - - - diff --git a/498.diagonal-traverse.js b/498.diagonal-traverse.js new file mode 100644 index 00000000..8ed30159 --- /dev/null +++ b/498.diagonal-traverse.js @@ -0,0 +1,39 @@ +/** + * @param {number[][]} matrix + * @return {number[]} + */ +const findDiagonalOrder = function(matrix) { + if (!matrix.length || !matrix[0].length) { + return [] + } + const m = matrix.length + const n = matrix[0].length + const output = [] + for (let sum = 0; sum <= m + n - 2; sum++) { + for ( + let i = Math.min(m - 1, sum); + sum % 2 === 0 && isValid(i, sum - i, m, n); + i-- + ) { + const j = sum - i + output.push(matrix[i][j]) + } + for ( + let j = Math.min(n - 1, sum); + sum % 2 === 1 && isValid(sum - j, j, m, n); + j-- + ) { + const i = sum - j + output.push(matrix[i][j]) + } + } + return output +} + +function isValid(i, j, m, n) { + if (i < 0 || i >= m || j < 0 || j >= n) { + return false + } + return true +} + diff --git a/499-the-maze-iii.js b/499-the-maze-iii.js deleted file mode 100644 index f7543ea1..00000000 --- a/499-the-maze-iii.js +++ /dev/null @@ -1,230 +0,0 @@ -/** - -There is a ball in a maze with empty spaces and walls. -The ball can go through empty spaces by rolling up (u), down (d), left (l) or right (r), -but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction. -There is also a hole in this maze. The ball will drop into the hole if it rolls on to the hole. - -Given the ball position, the hole position and the maze, -find out how the ball could drop into the hole by moving the shortest distance. -The distance is defined by the number of empty spaces traveled by the ball from -the start position (excluded) to the hole (included). -Output the moving directions by using 'u', 'd', 'l' and 'r'. -Since there could be several different shortest ways, you should output the lexicographically smallest way. -If the ball cannot reach the hole, output "impossible". - -The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. -You may assume that the borders of the maze are all walls. -The ball and the hole coordinates are represented by row and column indexes. - -Example 1: - -Input 1: a maze represented by a 2D array - -0 0 0 0 0 -1 1 0 0 1 -0 0 0 0 0 -0 1 0 0 1 -0 1 0 0 0 - -Input 2: ball coordinate (rowBall, colBall) = (4, 3) -Input 3: hole coordinate (rowHole, colHole) = (0, 1) - -Output: "lul" - -Explanation: There are two shortest ways for the ball to drop into the hole. -The first way is left -> up -> left, represented by "lul". -The second way is up -> left, represented by 'ul'. -Both ways have shortest distance 6, but the first way is lexicographically smaller because 'l' < 'u'. So the output is "lul". - -Example 2: - -Input 1: a maze represented by a 2D array - -0 0 0 0 0 -1 1 0 0 1 -0 0 0 0 0 -0 1 0 0 1 -0 1 0 0 0 - -Input 2: ball coordinate (rowBall, colBall) = (4, 3) -Input 3: hole coordinate (rowHole, colHole) = (3, 0) - -Output: "impossible" - -Note: - -There is only one ball and one hole in the maze. -Both the ball and hole exist on an empty space, and they will not be at the same position initially. -The given maze does not contain border (like the red rectangle in the example pictures), -but you could assume the border of the maze are all walls. -The maze contains at least 2 empty spaces, and the width and the height of the maze won't exceed 30. - -*/ - -/** - * @param {number[][]} maze - * @param {number[]} ball - * @param {number[]} hole - * @return {string} - */ -function findShortestWay(maze, ball, hole) { - const H = maze.length - const W = maze[0].length - const costs = [...Array(H)].map(r => Array(W).fill(Number.MAX_VALUE)) - let minRoute = '' - dfs(ball[0], ball[1], 0, '') - return minRoute || 'impossible' - - function dfs(r, c, cost, route) { - if (cost >= costs[r][c]) return - costs[r][c] = cost - for (let [dr, dc, d] of [ - [1, 0, 'd'], - [0, -1, 'l'], - [0, 1, 'r'], - [-1, 0, 'u'] - ]) { - let rr = r - let cc = c - let steps = 0 - for ( - ; - rr + dr >= 0 && - rr + dr < H && - cc + dc >= 0 && - cc + dc < W && - maze[rr + dr][cc + dc] !== 1; - - ) { - rr += dr - cc += dc - steps++ - if (rr === hole[0] && cc === hole[1]) { - if (cost + steps < costs[hole[0]][hole[1]]) { - costs[hole[0]][hole[1]] = cost + steps - minRoute = route + d - } - return - } - } - dfs(rr, cc, cost + steps, route + d) - } - } -} - -// another - -const dirs = [ - [1, 0, 'd'], - [0, -1, 'l'], - [0, 1, 'r'], - [-1, 0, 'u'] -] - -/** - * @param {number[][]} maze - * @param {number[]} ball - * @param {number[]} hole - * @return {string} - */ -const findShortestWay = function(maze, ball, hole) { - const m = maze.length - const n = maze[0].length - const dist = [...new Array(m)].map(() => new Array(n).fill(Infinity)) - dist[ball[0]][ball[1]] = 0 - const pq = new PriorityQueue({ - comparator: (a, b) => { - if (dist[a[0][0]][a[0][1]] !== dist[b[0][0]][b[0][1]]) { - return dist[a[0][0]][a[0][1]] < dist[b[0][0]][b[0][1]] - } - return a[1] < b[1] - } - }) - pq.enqueue([ball, '']) - while (pq.length) { - const [[x, y], path] = pq.dequeue() - if (x === hole[0] && y === hole[1]) { - return path - } - for (const [di, dj, dir] of dirs) { - if (isValidPosition(x + di, y + dj, m, n) && maze[x + di][y + dj] === 0) { - const [i, j] = walk(maze, x + di, y + dj, di, dj, m, n, hole) - const deltaDist = Math.abs(x - i) + Math.abs(y - j) - if (dist[x][y] + deltaDist <= dist[i][j]) { - dist[i][j] = dist[x][y] + deltaDist - pq.enqueue([[i, j], path + dir]) - } - } - } - } - return 'impossible' -} - -function walk(maze, x, y, di, dj, m, n, [hi, hj]) { - let i = x - let j = y - while ( - isValidPosition(i + di, j + dj, m, n) && - maze[i + di][j + dj] === 0 && - !(hi === i && hj === j) - ) { - i += di - j += dj - } - return [i, j] -} - -function isValidPosition(i, j, m, n) { - if (i < 0 || i >= m || j < 0 || j >= n) { - return false - } - return true -} - -class PriorityQueue { - constructor({ comparator }) { - this.comparator = comparator - this.arr = [] - } - - enqueue(element) { - this.arr.push(element) - moveUp(this.arr, this.arr.length - 1, this.comparator) - } - - dequeue() { - const output = this.arr[0] - this.arr[0] = this.arr[this.arr.length - 1] - this.arr.pop() - moveDown(this.arr, 0, this.comparator) - return output - } - - get length() { - return this.arr.length - } -} - -function moveUp(arr, i, comparator) { - const p = Math.floor((i - 1) / 2) - const isValid = p < 0 || comparator(arr[p], arr[i]) - if (!isValid) { - ;[arr[i], arr[p]] = [arr[p], arr[i]] - moveUp(arr, p, comparator) - } -} - -function moveDown(arr, i, comparator) { - const left = 2 * i + 1 - const right = 2 * i + 2 - const isValid = - (left >= arr.length || comparator(arr[i], arr[left])) && - (right >= arr.length || comparator(arr[i], arr[right])) - if (!isValid) { - const next = - right >= arr.length || comparator(arr[left], arr[right]) ? left : right - ;[arr[i], arr[next]] = [arr[next], arr[i]] - moveDown(arr, next, comparator) - } -} diff --git a/499.the-maze-iii.js b/499.the-maze-iii.js new file mode 100644 index 00000000..d259751f --- /dev/null +++ b/499.the-maze-iii.js @@ -0,0 +1,115 @@ +/** + +There is a ball in a maze with empty spaces and walls. +The ball can go through empty spaces by rolling up (u), down (d), left (l) or right (r), +but it won't stop rolling until hitting a wall. When the ball stops, it could choose the next direction. +There is also a hole in this maze. The ball will drop into the hole if it rolls on to the hole. + +Given the ball position, the hole position and the maze, +find out how the ball could drop into the hole by moving the shortest distance. +The distance is defined by the number of empty spaces traveled by the ball from +the start position (excluded) to the hole (included). +Output the moving directions by using 'u', 'd', 'l' and 'r'. +Since there could be several different shortest ways, you should output the lexicographically smallest way. +If the ball cannot reach the hole, output "impossible". + +The maze is represented by a binary 2D array. 1 means the wall and 0 means the empty space. +You may assume that the borders of the maze are all walls. +The ball and the hole coordinates are represented by row and column indexes. + +Example 1: + +Input 1: a maze represented by a 2D array + +0 0 0 0 0 +1 1 0 0 1 +0 0 0 0 0 +0 1 0 0 1 +0 1 0 0 0 + +Input 2: ball coordinate (rowBall, colBall) = (4, 3) +Input 3: hole coordinate (rowHole, colHole) = (0, 1) + +Output: "lul" + +Explanation: There are two shortest ways for the ball to drop into the hole. +The first way is left -> up -> left, represented by "lul". +The second way is up -> left, represented by 'ul'. +Both ways have shortest distance 6, but the first way is lexicographically smaller because 'l' < 'u'. So the output is "lul". + +Example 2: + +Input 1: a maze represented by a 2D array + +0 0 0 0 0 +1 1 0 0 1 +0 0 0 0 0 +0 1 0 0 1 +0 1 0 0 0 + +Input 2: ball coordinate (rowBall, colBall) = (4, 3) +Input 3: hole coordinate (rowHole, colHole) = (3, 0) + +Output: "impossible" + +Note: + +There is only one ball and one hole in the maze. +Both the ball and hole exist on an empty space, and they will not be at the same position initially. +The given maze does not contain border (like the red rectangle in the example pictures), +but you could assume the border of the maze are all walls. +The maze contains at least 2 empty spaces, and the width and the height of the maze won't exceed 30. + +*/ + +/** + * @param {number[][]} maze + * @param {number[]} ball + * @param {number[]} hole + * @return {string} + */ +function findShortestWay(maze, ball, hole) { + const H = maze.length + const W = maze[0].length + const costs = [...Array(H)].map(r => Array(W).fill(Number.MAX_VALUE)) + let minRoute = '' + dfs(ball[0], ball[1], 0, '') + return minRoute || 'impossible' + + function dfs(r, c, cost, route) { + if (cost >= costs[r][c]) return + costs[r][c] = cost + for (let [dr, dc, d] of [ + [1, 0, 'd'], + [0, -1, 'l'], + [0, 1, 'r'], + [-1, 0, 'u'] + ]) { + let rr = r + let cc = c + let steps = 0 + for ( + ; + rr + dr >= 0 && + rr + dr < H && + cc + dc >= 0 && + cc + dc < W && + maze[rr + dr][cc + dc] !== 1; + + ) { + rr += dr + cc += dc + steps++ + if (rr === hole[0] && cc === hole[1]) { + if (cost + steps < costs[hole[0]][hole[1]]) { + costs[hole[0]][hole[1]] = cost + steps + minRoute = route + d + } + return + } + } + dfs(rr, cc, cost + steps, route + d) + } + } +} + diff --git a/5-longest-palindromic-substring.js b/5-longest-palindromic-substring.js deleted file mode 100755 index 76afe7f4..00000000 --- a/5-longest-palindromic-substring.js +++ /dev/null @@ -1,109 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ -const longestPalindrome = function(s) { - let res = '' - for(let i = 0, len = s.length; i < len; i++) { - let s1 = chk(s,i,i), s2 = chk(s,i,i+1) - if(s1.length > res.length) res = s1 - if(s2.length > res.length) res = s2 - } - return res -}; - -function chk(s, i, j) { - for(; i>= 0 && j < s.length; i--, j++) { - if(s[i] !== s[j]) break - } - return s.slice(i+1, j) -} - -// another - -/** - * @param {string} s - * @return {string} - */ -const longestPalindrome = function(s) { - let T = preProcess(s); - let n = T.length; - let P = []; - let C = 0, - R = 0; - let i_mirror; - for (let i = 1; i < n - 1; i++) { - i_mirror = 2 * C - i; // equals to i' = C - (i-C) - - P[i] = R > i ? Math.min(R - i, P[i_mirror]) : 0; - - // Attempt to expand palindrome centered at i - while (T[i + 1 + P[i]] == T[i - 1 - P[i]]) P[i]++; - - // If palindrome centered at i expand past R, - // adjust center based on expanded palindrome. - if (i + P[i] > R) { - C = i; - R = i + P[i]; - } - } - - // Find the maximum element in P. - let maxLen = 0; - let centerIndex = 0; - for (let j = 1; j < n - 1; j++) { - if (P[j] > maxLen) { - maxLen = P[j]; - centerIndex = j; - } - } - - return s.substr((centerIndex - 1 - maxLen) / 2, maxLen); -}; - -function preProcess(s) { - let n = s.length; - if (n === 0) return "^$"; - let ret = "^"; - for (let i = 0; i < n; i++) ret += "#" + s.substr(i, 1); - - ret += "#$"; - return ret; -} - -// another - -/** - * @param {string} s - * @return {string} - */ -const longestPalindrome = function(s) { - const n = s.length - let res = '' - for(let i = 0; i < n; i++) { - const first = chk(s, i, i, n) - if(first.length > res.length) res = first - const second = chk(s, i, i + 1, n) - if(second.length > res.length) res = second - } - return res -}; - -function chk(str, i, j, n) { - if(j >= n) return str[i] - let l = i, r = j - while(l >= 0 && r < n) { - if(str[l] === str[r]) { - l-- - r++ - } else { - return str.slice(l + 1, r) - } - } - if(l < 0) { - return str.slice(0, r) - } else { - return str.slice(l + 1, n) - } -} - diff --git a/5.longest-palindromic-substring.js b/5.longest-palindromic-substring.js new file mode 100644 index 00000000..0f9b4b3f --- /dev/null +++ b/5.longest-palindromic-substring.js @@ -0,0 +1,21 @@ +/** + * @param {string} s + * @return {string} + */ +const longestPalindrome = function(s) { + let res = '' + for(let i = 0, len = s.length; i < len; i++) { + let s1 = chk(s,i,i), s2 = chk(s,i,i+1) + if(s1.length > res.length) res = s1 + if(s2.length > res.length) res = s2 + } + return res +}; + +function chk(s, i, j) { + for(; i>= 0 && j < s.length; i--, j++) { + if(s[i] !== s[j]) break + } + return s.slice(i+1, j) +} + diff --git a/50-powx-n.js b/50-powx-n.js deleted file mode 100644 index 36c6619e..00000000 --- a/50-powx-n.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @param {number} x - * @param {number} n - * @return {number} - */ -const myPow = function(x, n) { - if (n === 0) return 1; - if (n === 1) return x; - if (x === 0) return 0; - - if (n > 0) { - return (n % 2 === 1 ? x : 1) * myPow(x * x, Math.floor(n / 2)); - } else { - return myPow(1 / x, -n); - } -}; - -// another - -/** - * @param {number} x - * @param {number} n - * @return {number} - */ -const myPow = function(x, n) { - if(n === 0) return 1 - if(n === 1) return x - if(n < 0) { - x = 1 / x - n = -n - } - return n % 2 === 1 ? myPow(x, ~~(n / 2)) ** 2 * x : myPow(x, ~~(n / 2)) ** 2 -}; - -// another - -/** - * @param {number} x - * @param {number} n - * @return {number} - */ -const myPow = function (x, n) { - if (n === 0) return 1 - if (n < 0) { - if (n === -(2 ** 31)) { - ++n - n = -n - x = 1 / x - return x * x * myPow(x * x, n / 2) - } - n = -n - x = 1 / x - } - return n % 2 == 0 ? myPow(x * x, n / 2) : x * myPow(x * x, (n / 2) >> 0) -} - -// another - -/** - * @param {number} x - * @param {number} n - * @return {number} - */ -const myPow = function (x, n) { - if (n === 0) return 1 - if (n < 0) { - n = -n - x = 1 / x - } - let res = 1 - while (n > 0) { - if (n & 1) { - res *= x - --n - } - x *= x - n /= 2 - } - return res -} - diff --git a/50.powx-n.js b/50.powx-n.js new file mode 100644 index 00000000..0911fe19 --- /dev/null +++ b/50.powx-n.js @@ -0,0 +1,17 @@ +/** + * @param {number} x + * @param {number} n + * @return {number} + */ +const myPow = function(x, n) { + if (n === 0) return 1; + if (n === 1) return x; + if (x === 0) return 0; + + if (n > 0) { + return (n % 2 === 1 ? x : 1) * myPow(x * x, Math.floor(n / 2)); + } else { + return myPow(1 / x, -n); + } +}; + diff --git a/500-keyboard-row.js b/500-keyboard-row.js deleted file mode 100755 index c64139fa..00000000 --- a/500-keyboard-row.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @param {string[]} words - * @return {string[]} - */ -const findWords = function(words) { - const regex = /^[qwertyuiop]*$|^[asdfghjkl]*$|^[zxcvbnm]*$/; - return words.filter( - s => (s.toLowerCase().match(regex) === null ? false : true) - ); -}; -console.log(findWords(["Hello", "Alaska", "Dad", "Peace"])); diff --git a/500.keyboard-row.js b/500.keyboard-row.js new file mode 100644 index 00000000..817fc04b --- /dev/null +++ b/500.keyboard-row.js @@ -0,0 +1,11 @@ +/** + * @param {string[]} words + * @return {string[]} + */ +const findWords = function(words) { + const regex = /^[qwertyuiop]*$|^[asdfghjkl]*$|^[zxcvbnm]*$/; + return words.filter( + s => (s.toLowerCase().match(regex) === null ? false : true) + ); +}; +console.log(findWords(["Hello", "Alaska", "Dad", "Peace"])); diff --git a/501-find-mode-in-binary-search-tree.js b/501-find-mode-in-binary-search-tree.js deleted file mode 100644 index 85c978ce..00000000 --- a/501-find-mode-in-binary-search-tree.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number[]} - */ -const findMode = function(root) { - if(root == null) return [] - const hash = {} - traverse(root, hash) - const res = Object.entries(hash).sort((a, b) => b[1] - a[1]) - const result = [res[0][0]] - for(let i = 1; i < res.length; i++) { - if(res[i][1] === res[0][1]) result.push(res[i][0]) - else break - } - return result -}; - -function traverse(node, hash) { - if(node === null) return - hash[node.val] = Object.prototype.hasOwnProperty.call(hash, node.val) ? hash[node.val] + 1 : 1 - traverse(node.left, hash) - traverse(node.right, hash) -} - - -// another -const findMode = function(root) { - let res = []; - let cnt = 1; - let mx = 0; - let pre = null; - let search = function(node) { - if (!node) return; - search(node.left); - if (pre) { - cnt = (node.val === pre.val) ? cnt + 1 : 1; - } - if (cnt >= mx) { - if (cnt > mx) res.length = 0; - res.push(node.val); - mx = cnt; - } - pre = node; - search(node.right); - } - search(root); - return res; -}; diff --git a/501.find-mode-in-binary-search-tree.js b/501.find-mode-in-binary-search-tree.js new file mode 100644 index 00000000..4b4a7f0a --- /dev/null +++ b/501.find-mode-in-binary-search-tree.js @@ -0,0 +1,32 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[]} + */ +const findMode = function(root) { + if(root == null) return [] + const hash = {} + traverse(root, hash) + const res = Object.entries(hash).sort((a, b) => b[1] - a[1]) + const result = [res[0][0]] + for(let i = 1; i < res.length; i++) { + if(res[i][1] === res[0][1]) result.push(res[i][0]) + else break + } + return result +}; + +function traverse(node, hash) { + if(node === null) return + hash[node.val] = Object.prototype.hasOwnProperty.call(hash, node.val) ? hash[node.val] + 1 : 1 + traverse(node.left, hash) + traverse(node.right, hash) +} + + diff --git a/502-ipo.js b/502-ipo.js deleted file mode 100644 index 9938088e..00000000 --- a/502-ipo.js +++ /dev/null @@ -1,215 +0,0 @@ -/** - * @param {number} k - * @param {number} W - * @param {number[]} Profits - * @param {number[]} Capital - * @return {number} - */ -const findMaximizedCapital = function(k, W, Profits, Capital) { - const capPQ = new PriorityQueue((a, b) => a.cap < b.cap) - const proPQ = new PriorityQueue((a, b) => a.pro > b.pro) - for(let i = 0, len = Profits.length; i < len; i++) { - capPQ.push({ cap: Capital[i], pro: Profits[i] }) - } - while(k) { - while(!capPQ.isEmpty() && capPQ.peek().cap <= W) { - proPQ.push(capPQ.pop()) - } - if(proPQ.isEmpty()) break - - W += proPQ.pop().pro - k-- - } - return W -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -/** - * @param {number} k - * @param {number} W - * @param {number[]} Profits - * @param {number[]} Capital - * @return {number} - */ -const findMaximizedCapital = function(k, W, Profits, Capital) { - const idxArr = Profits.map((_, i) => i).sort((ia, ib) => Profits[ib] - Profits[ia]); - while (k) { - const choose = idxArr.findIndex(i => Capital[i] <= W); - if (choose == -1) return W; - W += Profits[idxArr[choose]]; - idxArr.splice(choose, 1); - k--; - } - return W; -}; - -// another - -/** - * @param {number} k - * @param {number} w - * @param {number[]} profits - * @param {number[]} capital - * @return {number} - */ -const findMaximizedCapital = function(k, w, profits, capital) { - const capPQ = new PQ((a, b) => a.cap < b.cap) - const proPQ = new PQ((a, b) => a.pro > b.pro) - const n = profits.length - - for(let i = 0; i < n; i++) { - capPQ.push({ cap: capital[i], pro: profits[i] }) - } - - while(k) { - - while(!capPQ.isEmpty() && capPQ.peek().cap <= w) { - proPQ.push(capPQ.pop()) - } - - if(proPQ.isEmpty()) break - - w += proPQ.pop().pro - k-- - } - - - return w -}; - -class PQ { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/502.ipo.js b/502.ipo.js new file mode 100644 index 00000000..0a1ddf58 --- /dev/null +++ b/502.ipo.js @@ -0,0 +1,93 @@ +/** + * @param {number} k + * @param {number} W + * @param {number[]} Profits + * @param {number[]} Capital + * @return {number} + */ +const findMaximizedCapital = function(k, W, Profits, Capital) { + const capPQ = new PriorityQueue((a, b) => a.cap < b.cap) + const proPQ = new PriorityQueue((a, b) => a.pro > b.pro) + for(let i = 0, len = Profits.length; i < len; i++) { + capPQ.push({ cap: Capital[i], pro: Profits[i] }) + } + while(k) { + while(!capPQ.isEmpty() && capPQ.peek().cap <= W) { + proPQ.push(capPQ.pop()) + } + if(proPQ.isEmpty()) break + + W += proPQ.pop().pro + k-- + } + return W +}; + +class PriorityQueue { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + diff --git a/503-next-greater-element-II.js b/503-next-greater-element-II.js deleted file mode 100755 index 37a4898e..00000000 --- a/503-next-greater-element-II.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[]} - */ -const nextGreaterElements = function(nums) { - const arr = [] - const n = nums.length - const res = Array(n).fill(-1) - nums.push(...nums) - const stk = [] - for(let i = 0; i < 2 * n; i++) { - const e = nums[i] - while(stk.length && nums[stk.at(-1)] < e) { - const idx = stk.pop() - res[idx] = e - } - if(i < n) stk.push(i) - } - - return res -}; - -// another - - -/** - * @param {number[]} nums - * @return {number[]} - */ -const nextGreaterElements = function(nums) { - const res = []; - for (let i = 0; i < nums.length; i++) { - res.push(single(i, nums)); - } - return res; -}; - -function single(idx, arr) { - const base = arr[idx]; - const prev = idx === 0 ? [] : arr.slice(0, idx); - const next = arr.slice(idx); - const comb = next.concat(prev); - for (let i = 0; i < comb.length; i++) { - if (comb[i] > base) return comb[i]; - } - return -1; -} - -// another - -/** - * @param {number[]} nums - * @return {number[]} - */ - const nextGreaterElements = function(nums) { - const res = [], n = nums.length - const stack = [] - for(let i = 2 * n - 1; i >= 0; i--) { - while(stack.length && nums[stack[stack.length - 1]] <= nums[i % n]) { - stack.pop() - } - res[i % n] = stack.length ? nums[stack[stack.length - 1]] : -1 - stack.push(i % n) - } - - return res -}; diff --git a/503.next-greater-element-II.js b/503.next-greater-element-II.js new file mode 100644 index 00000000..799b52a8 --- /dev/null +++ b/503.next-greater-element-II.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} nums + * @return {number[]} + */ +const nextGreaterElements = function(nums) { + const arr = [] + const n = nums.length + const res = Array(n).fill(-1) + nums.push(...nums) + const stk = [] + for(let i = 0; i < 2 * n; i++) { + const e = nums[i] + while(stk.length && nums[stk.at(-1)] < e) { + const idx = stk.pop() + res[idx] = e + } + if(i < n) stk.push(i) + } + + return res +}; + diff --git a/504-base-7.js b/504-base-7.js deleted file mode 100644 index 56cc8352..00000000 --- a/504-base-7.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @param {number} num - * @return {string} - */ -const convertToBase7 = function(num) { - if(num == null) return '' - const sign = num >= 0 ? '+' : '-' - let res = '' - let remain = Math.abs(num) - if(num === 0) return '0' - while(remain > 0) { - res = remain % 7 + res - remain = Math.floor(remain / 7) - } - - return sign === '+' ? res : '-' + res -}; - -// another - -const convertToBase7 = function(num) { - return num.toString(7) -}; diff --git a/504.base-7.js b/504.base-7.js new file mode 100644 index 00000000..496487a3 --- /dev/null +++ b/504.base-7.js @@ -0,0 +1,18 @@ +/** + * @param {number} num + * @return {string} + */ +const convertToBase7 = function(num) { + if(num == null) return '' + const sign = num >= 0 ? '+' : '-' + let res = '' + let remain = Math.abs(num) + if(num === 0) return '0' + while(remain > 0) { + res = remain % 7 + res + remain = Math.floor(remain / 7) + } + + return sign === '+' ? res : '-' + res +}; + diff --git a/505-the-maze-ii.js b/505.the-maze-ii.js similarity index 100% rename from 505-the-maze-ii.js rename to 505.the-maze-ii.js diff --git a/506-relative-ranks.js b/506.relative-ranks.js similarity index 100% rename from 506-relative-ranks.js rename to 506.relative-ranks.js diff --git a/507-perfect-number.js b/507.perfect-number.js similarity index 100% rename from 507-perfect-number.js rename to 507.perfect-number.js diff --git a/508-most-frequent-subtree-sum.js b/508-most-frequent-subtree-sum.js deleted file mode 100755 index e63eabf1..00000000 --- a/508-most-frequent-subtree-sum.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number[]} - */ -const findFrequentTreeSum = function(root) { - if (root == null) return []; - const valArr = []; - calc(root, valArr); - const hash = {}; - valArr.forEach((el, idx) => { - if (hash.hasOwnProperty(el)) { - hash[el] += 1; - } else { - hash[el] = 1; - } - }); - const arr = Object.entries(hash).sort((a, b) => b[1] - a[1]); - const max = arr[0][1]; - const res = [+arr[0][0]]; - for (let i = 1; i < arr.length; i++) { - if (arr[i][1] === max) { - res.push(+arr[i][0]); - } else { - return res; - } - } - return res; -}; - -function calc(node, arr) { - let sum = 0; - if (node.left) { - sum += calc(node.left, arr); - } - if (node.right) { - sum += calc(node.right, arr); - } - sum += node.val; - arr.push(sum); - return sum; -} diff --git a/508.most-frequent-subtree-sum.js b/508.most-frequent-subtree-sum.js new file mode 100644 index 00000000..a3976e9a --- /dev/null +++ b/508.most-frequent-subtree-sum.js @@ -0,0 +1,48 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[]} + */ +const findFrequentTreeSum = function(root) { + if (root == null) return []; + const valArr = []; + calc(root, valArr); + const hash = {}; + valArr.forEach((el, idx) => { + if (hash.hasOwnProperty(el)) { + hash[el] += 1; + } else { + hash[el] = 1; + } + }); + const arr = Object.entries(hash).sort((a, b) => b[1] - a[1]); + const max = arr[0][1]; + const res = [+arr[0][0]]; + for (let i = 1; i < arr.length; i++) { + if (arr[i][1] === max) { + res.push(+arr[i][0]); + } else { + return res; + } + } + return res; +}; + +function calc(node, arr) { + let sum = 0; + if (node.left) { + sum += calc(node.left, arr); + } + if (node.right) { + sum += calc(node.right, arr); + } + sum += node.val; + arr.push(sum); + return sum; +} diff --git a/5083-occurrences-after-bigram.js b/5083.occurrences-after-bigram.js similarity index 100% rename from 5083-occurrences-after-bigram.js rename to 5083.occurrences-after-bigram.js diff --git a/5084-insufficient-nodes-in-root-to-leaf-paths.js b/5084.insufficient-nodes-in-root-to-leaf-paths.js similarity index 100% rename from 5084-insufficient-nodes-in-root-to-leaf-paths.js rename to 5084.insufficient-nodes-in-root-to-leaf-paths.js diff --git a/509-fibonacci-number.js b/509.fibonacci-number.js similarity index 100% rename from 509-fibonacci-number.js rename to 509.fibonacci-number.js diff --git a/51-n-queens.js b/51-n-queens.js deleted file mode 100644 index 0654b675..00000000 --- a/51-n-queens.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @param {number} n - * @return {string[][]} - */ -const solveNQueens = function(n) { - const res = [] - const chess = Array.from({length: n}, () => new Array(n).fill('.')) - bt(res, chess, 0) - return res -} - -function bt(res, chess, row) { - if(row === chess.length) { - res.push(build(chess)) - return - } - for(let i = 0, num = chess[0].length; i < num; i++) { - if(valid(chess, row, i)) { - chess[row][i] = 'Q' - bt(res, chess, row + 1) - chess[row][i] = '.' - } - } -} - -function valid(chess, row, col) { - for(let i = row - 1; i >= 0; i--) { - if(chess[i][col] === 'Q') return false - } - for(let i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { - if(chess[i][j] === 'Q') return false - } - for(let i = row - 1, j = col + 1; i >= 0 && j < chess[0].length; i--, j++) { - if(chess[i][j] === 'Q') return false - } - return true -} - -function build(chess) { - return chess.map(el => el.join('')) -} - -// another - -/** - * @param {number} n - * @return {string[][]} - */ -const solveNQueens = function(n) { - const res = [] - bt(res, n) - return res -} - -function bt(res, n, board = [], r = 0) { - if (r === n) { - res.push(board.map(c => '.'.repeat(c) + 'Q' + '.'.repeat(n - c - 1))) - return - } - for (let c = 0; c < n; c++) { - if ( - !board.some( - (bc, br) => bc === c || bc === c + r - br || bc === c - r + br - ) - ) { - board.push(c) - bt(res, n, board, r + 1) - board.pop() - } - } -} diff --git a/51.n-queens.js b/51.n-queens.js new file mode 100644 index 00000000..afe47e4c --- /dev/null +++ b/51.n-queens.js @@ -0,0 +1,42 @@ +/** + * @param {number} n + * @return {string[][]} + */ +const solveNQueens = function(n) { + const res = [] + const chess = Array.from({length: n}, () => new Array(n).fill('.')) + bt(res, chess, 0) + return res +} + +function bt(res, chess, row) { + if(row === chess.length) { + res.push(build(chess)) + return + } + for(let i = 0, num = chess[0].length; i < num; i++) { + if(valid(chess, row, i)) { + chess[row][i] = 'Q' + bt(res, chess, row + 1) + chess[row][i] = '.' + } + } +} + +function valid(chess, row, col) { + for(let i = row - 1; i >= 0; i--) { + if(chess[i][col] === 'Q') return false + } + for(let i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { + if(chess[i][j] === 'Q') return false + } + for(let i = row - 1, j = col + 1; i >= 0 && j < chess[0].length; i--, j++) { + if(chess[i][j] === 'Q') return false + } + return true +} + +function build(chess) { + return chess.map(el => el.join('')) +} + diff --git a/510-inorder-successor-in-bst-ii.js b/510.inorder-successor-in-bst-ii.js similarity index 100% rename from 510-inorder-successor-in-bst-ii.js rename to 510.inorder-successor-in-bst-ii.js diff --git a/513-find-bottom-left-tree-value.js b/513.find-bottom-left-tree-value.js old mode 100755 new mode 100644 similarity index 100% rename from 513-find-bottom-left-tree-value.js rename to 513.find-bottom-left-tree-value.js diff --git a/514-freedom-trail.js b/514.freedom-trail.js similarity index 100% rename from 514-freedom-trail.js rename to 514.freedom-trail.js diff --git a/515-find-largest-value-in-each-tree-row.js b/515.find-largest-value-in-each-tree-row.js old mode 100755 new mode 100644 similarity index 100% rename from 515-find-largest-value-in-each-tree-row.js rename to 515.find-largest-value-in-each-tree-row.js diff --git a/516-longest-palindromic-subsequence.js b/516-longest-palindromic-subsequence.js deleted file mode 100644 index 7eaeefe0..00000000 --- a/516-longest-palindromic-subsequence.js +++ /dev/null @@ -1,64 +0,0 @@ -// 区间DP - -/** - * @param {string} s - * @return {number} - */ -const longestPalindromeSubseq = function(s) { - const n = s.length - const dp = Array.from({ length: n }, () => Array(n).fill(0)) - for(let i = 0; i < n; i++) dp[i][i] = 1 - for(let len = 2; len <= n; len++) { - for(let i = 0; i + len - 1 < n; i++) { - const j = i + len - 1 - if(s[i] === s[j]) dp[i][j] = 2 + dp[i + 1][j - 1] - else dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]) - } - } - return dp[0][n - 1] -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const longestPalindromeSubseq = function(s) { - const n = s.length - const dp = Array.from({ length: n }, () => Array(n).fill(0)) - for(let i = 0; i < n; i++) { - dp[i][i] = 1 - for(let j = i - 1; j >= 0; j--) { - if(s[i] === s[j]) { - dp[i][j] = dp[i - 1][j + 1] + 2 - } else { - dp[i][j] = Math.max(dp[i - 1][j], dp[i][j + 1]) - } - } - } - - return dp[n - 1][0] -}; - -// another - -/** - * @param {string} s - * @return {number} - */ -const longestPalindromeSubseq = function(s) { - const len = s.length - const dp = Array.from({length: len + 1}, () => new Array(len + 1).fill(0)) - for(let i = len - 1; i >= 0; i--) { - dp[i][i] = 1 - for(let j = i + 1; j < len; j++) { - if(s[i] === s[j]) { - dp[i][j] = dp[i+1][j-1] + 2 - } else { - dp[i][j] = Math.max(dp[i][j - 1], dp[i+1][j]) - } - } - } - return dp[0][s.length - 1] -}; diff --git a/516.longest-palindromic-subsequence.js b/516.longest-palindromic-subsequence.js new file mode 100644 index 00000000..0377c66d --- /dev/null +++ b/516.longest-palindromic-subsequence.js @@ -0,0 +1,20 @@ +// 区间DP + +/** + * @param {string} s + * @return {number} + */ +const longestPalindromeSubseq = function(s) { + const n = s.length + const dp = Array.from({ length: n }, () => Array(n).fill(0)) + for(let i = 0; i < n; i++) dp[i][i] = 1 + for(let len = 2; len <= n; len++) { + for(let i = 0; i + len - 1 < n; i++) { + const j = i + len - 1 + if(s[i] === s[j]) dp[i][j] = 2 + dp[i + 1][j - 1] + else dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]) + } + } + return dp[0][n - 1] +}; + diff --git a/517-super-washing-machines.js b/517.super-washing-machines.js similarity index 100% rename from 517-super-washing-machines.js rename to 517.super-washing-machines.js diff --git a/518-coin-change-2.js b/518-coin-change-2.js deleted file mode 100644 index 54db7941..00000000 --- a/518-coin-change-2.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @param {number} amount - * @param {number[]} coins - * @return {number} - */ -function change(amount, coins) { - const dp = Array.from(new Array(coins.length + 1), () => - new Array(amount + 1).fill(0) - ) - dp[0][0] = 1 - for (let i = 1; i <= coins.length; i++) { - dp[i][0] = 1 - for (let j = 1; j <= amount; j++) { - dp[i][j] = - dp[i - 1][j] + (j >= coins[i - 1] ? dp[i][j - coins[i - 1]] : 0) - } - } - return dp[coins.length][amount] -} - - -// another - -/** - * @param {number} amount - * @param {number[]} coins - * @return {number} - */ -const change = function (amount, coins) { - const dp = Array(amount + 1).fill(0) - dp[0] = 1 - for (let coin of coins) { - for (let i = coin; i < amount + 1; i++) dp[i] += dp[i - coin] - } - return dp[amount] -} - -// another - -// another - -const change = function(amount,coins) { - const n = coins.length - const dp = Array.from({ length: n + 1 }, () => Array(amount + 1)) - dp[0][0] = 1 - for(let i = 0; i < n; i++) dp[i][0] = 1 - helper(0, amount) - return dp[0][amount] === undefined ? 0 : dp[0][amount] - - function helper(i, rem) { - if(dp[i][rem] != null) return dp[i][rem] - if(rem < 0) return 0 - if(rem === 0) return 1 - if(i >= coins.length) return 0 - let res = 0 - - res += helper(i, rem - coins[i]) - res += helper(i + 1, rem) - - dp[i][rem] = res - - return res - } -} diff --git a/518.coin-change-2.js b/518.coin-change-2.js new file mode 100644 index 00000000..1293b600 --- /dev/null +++ b/518.coin-change-2.js @@ -0,0 +1,21 @@ +/** + * @param {number} amount + * @param {number[]} coins + * @return {number} + */ +function change(amount, coins) { + const dp = Array.from(new Array(coins.length + 1), () => + new Array(amount + 1).fill(0) + ) + dp[0][0] = 1 + for (let i = 1; i <= coins.length; i++) { + dp[i][0] = 1 + for (let j = 1; j <= amount; j++) { + dp[i][j] = + dp[i - 1][j] + (j >= coins[i - 1] ? dp[i][j - coins[i - 1]] : 0) + } + } + return dp[coins.length][amount] +} + + diff --git a/519-random-flip-matrix.js b/519.random-flip-matrix.js similarity index 100% rename from 519-random-flip-matrix.js rename to 519.random-flip-matrix.js diff --git a/52-n-queens-II.js b/52-n-queens-II.js deleted file mode 100755 index 4bb41ffa..00000000 --- a/52-n-queens-II.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const totalNQueens = function(n) { - //Keeps track of the # of valid solutions - let count = 0; - - //Helps identify valid solutions - const done = Math.pow(2, n) - 1; - - //Checks all possible board configurations - const innerRecurse = function(ld, col, rd) { - //All columns are occupied, - //so the solution must be complete - if (col === done) { - count++; - return; - } - - //Gets a bit sequence with "1"s - //whereever there is an open "slot" - let poss = ~(ld | rd | col); - - //Loops as long as there is a valid - //place to put another queen. - while (poss & done) { - let bit = poss & -poss; - poss -= bit; - innerRecurse((ld | bit) >> 1, col | bit, (rd | bit) << 1); - } - }; - - innerRecurse(0, 0, 0); - - return count; -}; diff --git a/52.n-queens-II.js b/52.n-queens-II.js new file mode 100644 index 00000000..53e2c031 --- /dev/null +++ b/52.n-queens-II.js @@ -0,0 +1,37 @@ +/** + * @param {number} n + * @return {number} + */ +const totalNQueens = function(n) { + //Keeps track of the # of valid solutions + let count = 0; + + //Helps identify valid solutions + const done = Math.pow(2, n) - 1; + + //Checks all possible board configurations + const innerRecurse = function(ld, col, rd) { + //All columns are occupied, + //so the solution must be complete + if (col === done) { + count++; + return; + } + + //Gets a bit sequence with "1"s + //whereever there is an open "slot" + let poss = ~(ld | rd | col); + + //Loops as long as there is a valid + //place to put another queen. + while (poss & done) { + let bit = poss & -poss; + poss -= bit; + innerRecurse((ld | bit) >> 1, col | bit, (rd | bit) << 1); + } + }; + + innerRecurse(0, 0, 0); + + return count; +}; diff --git a/520-detect-capital.js b/520-detect-capital.js deleted file mode 100755 index 39235478..00000000 --- a/520-detect-capital.js +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @param {string} word - * @return {boolean} - */ -const ac = "A".charCodeAt(0); -const zc = "Z".charCodeAt(0); -const detectCapitalUse = function(word) { - if (allCap(word) || noCap(word) || capHead(word)) { - return true; - } - return false; -}; - -function allCap(str) { - let c; - for (let i = 0; i < str.length; i++) { - c = str.charCodeAt(i); - if (c < ac || c > zc) { - return false; - } - } - return true; -} - -function noCap(str) { - let c; - for (let i = 0; i < str.length; i++) { - c = str.charCodeAt(i); - if (c >= ac && c <= zc) { - return false; - } - } - return true; -} - -function capHead(str) { - let c; - let first; - for (let i = 0; i < str.length; i++) { - c = str.charCodeAt(i); - if (i === 0) { - first = c; - } else if (c >= ac && c <= zc) { - return false; - } - } - if (first >= ac && first <= zc) { - return true; - } else { - return false; - } -} - -console.log(detectCapitalUse("ffffffffffffffffffffF")); -console.log(detectCapitalUse("Leetcode")); diff --git a/520.detect-capital.js b/520.detect-capital.js new file mode 100644 index 00000000..a317f951 --- /dev/null +++ b/520.detect-capital.js @@ -0,0 +1,55 @@ +/** + * @param {string} word + * @return {boolean} + */ +const ac = "A".charCodeAt(0); +const zc = "Z".charCodeAt(0); +const detectCapitalUse = function(word) { + if (allCap(word) || noCap(word) || capHead(word)) { + return true; + } + return false; +}; + +function allCap(str) { + let c; + for (let i = 0; i < str.length; i++) { + c = str.charCodeAt(i); + if (c < ac || c > zc) { + return false; + } + } + return true; +} + +function noCap(str) { + let c; + for (let i = 0; i < str.length; i++) { + c = str.charCodeAt(i); + if (c >= ac && c <= zc) { + return false; + } + } + return true; +} + +function capHead(str) { + let c; + let first; + for (let i = 0; i < str.length; i++) { + c = str.charCodeAt(i); + if (i === 0) { + first = c; + } else if (c >= ac && c <= zc) { + return false; + } + } + if (first >= ac && first <= zc) { + return true; + } else { + return false; + } +} + +console.log(detectCapitalUse("ffffffffffffffffffffF")); +console.log(detectCapitalUse("Leetcode")); diff --git a/521-longest-uncommon-subsequence-i.js b/521.longest-uncommon-subsequence-i.js similarity index 100% rename from 521-longest-uncommon-subsequence-i.js rename to 521.longest-uncommon-subsequence-i.js diff --git a/522-longest-uncommon-subsequence-ii.js b/522.longest-uncommon-subsequence-ii.js similarity index 100% rename from 522-longest-uncommon-subsequence-ii.js rename to 522.longest-uncommon-subsequence-ii.js diff --git a/523-continuous-subarray-sum.js b/523.continuous-subarray-sum.js similarity index 100% rename from 523-continuous-subarray-sum.js rename to 523.continuous-subarray-sum.js diff --git a/524-longest-word-in-dictionary-through-deleting.js b/524-longest-word-in-dictionary-through-deleting.js deleted file mode 100644 index bfe2742f..00000000 --- a/524-longest-word-in-dictionary-through-deleting.js +++ /dev/null @@ -1,138 +0,0 @@ -/** - * @param {string} s - * @param {string[]} dictionary - * @return {string} - */ - const findLongestWord = function(s, dictionary) { - let res = '' - for (const word of dictionary) { - let j = 0 - for (let i = 0, len = s.length; i < len; i++) { - if(word[j] === s[i]) j++ - if(j === word.length) { - if(word.length > res.length) res = word - else if(word.length === res.length && word < res) res = word - break - } - } - } - return res -}; - -// another - -/** - * @param {string} s - * @param {string[]} dictionary - * @return {string} - */ -const findLongestWord = function (s, dictionary) { - const n = dictionary.length - const idxArr = Array(n).fill(0) - let res = '' - for (const ch of s) { - for (let i = 0; i < n; i++) { - const idx = idxArr[i] - if (idx >= dictionary[i].length) continue - if (ch === dictionary[i][idx]) { - idxArr[i]++ - } - - if ( - idxArr[i] === dictionary[i].length && - (dictionary[i].length > res.length || - (dictionary[i].length === res.length && dictionary[i] < res)) - ) { - res = dictionary[i] - } - } - } - return res -} - - -// another - -/** - * @param {string} s - * @param {string[]} dictionary - * @return {string} - */ -const findLongestWord = function(s, dictionary) { - let res = '' - for(let d of dictionary) { - let j = 0 - for(let i = 0, n = s.length; i < n; i++) { - if(d[j] === s[i]) j++ - if(j === d.length && j >= res.length) { - if(j > res.length || d < res) { - res = d - } - break - } - } - } - return res -}; - -// another - -/** - * @param {string} s - * @param {string[]} dictionary - * @return {string} - */ -const findLongestWord = function(s, dictionary) { - dictionary.sort((a, b) => a.length === b.length ? cmp(a, b) : b.length - a.length) - let res = '' - for(let d of dictionary) { - let j = 0 - for(let i = 0, n = s.length; i < n; i++) { - if(d[j] === s[i]) j++ - if(j === d.length) return d - } - } - return '' - function cmp(s1, s2) { - for(let i = 0, n = s1.length; i < n; i++) { - if(s1[i] < s2[i]) return -1 - else if(s1[i] > s2[i]) return 1 - } - return 0 - } -}; - -// another - - -/** - * @param {string} s - * @param {string[]} d - * @return {string} - */ -const findLongestWord = function(s, d) { - let results = []; - let maxLen = 0; - for (const word of d) { - let j = 0; - for (let i = 0; i < s.length; i++) { - if (s[i] === word[j]) { - j++; - if (j === word.length) break; - } - } - if (j === word.length && word.length >= maxLen) { - if (word.length > maxLen) { - maxLen = word.length; - results = []; - } - results.push(word); - } - } - - let result = results[0]; - for (let i = 1; i < results.length; i++) { - if (results[i] < result) result = results[i]; - } - return result || ''; -} diff --git a/524.longest-word-in-dictionary-through-deleting.js b/524.longest-word-in-dictionary-through-deleting.js new file mode 100644 index 00000000..525d0ed9 --- /dev/null +++ b/524.longest-word-in-dictionary-through-deleting.js @@ -0,0 +1,21 @@ +/** + * @param {string} s + * @param {string[]} dictionary + * @return {string} + */ + const findLongestWord = function(s, dictionary) { + let res = '' + for (const word of dictionary) { + let j = 0 + for (let i = 0, len = s.length; i < len; i++) { + if(word[j] === s[i]) j++ + if(j === word.length) { + if(word.length > res.length) res = word + else if(word.length === res.length && word < res) res = word + break + } + } + } + return res +}; + diff --git a/525-contiguous-array.js b/525-contiguous-array.js deleted file mode 100644 index 9b0da1ea..00000000 --- a/525-contiguous-array.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const findMaxLength = function(nums) { - let res = 0, sum = 0 - const hash = {0: -1}, n = nums.length - - for(let i = 0; i < n; i++) { - const cur = nums[i] - sum += cur === 0 ? -1 : 1 - if(hash[sum] != null) { - res = Math.max(res, i - hash[sum]) - } else { - hash[sum] = i - } - - } - - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const findMaxLength = function (nums) { - const map = new Map() - map.set(0, -1) - let count = 0 - let max = 0 - for (let i = 0; i < nums.length; i++) { - let num = nums[i] - if (num === 0) { - count -= 1 - } - if (num === 1) { - count += 1 - } - if (map.has(count)) { - max = Math.max(max, i - map.get(count)) - } else { - map.set(count, i) - } - } - return max -} diff --git a/525.contiguous-array.js b/525.contiguous-array.js new file mode 100644 index 00000000..8f6cdb41 --- /dev/null +++ b/525.contiguous-array.js @@ -0,0 +1,22 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const findMaxLength = function(nums) { + let res = 0, sum = 0 + const hash = {0: -1}, n = nums.length + + for(let i = 0; i < n; i++) { + const cur = nums[i] + sum += cur === 0 ? -1 : 1 + if(hash[sum] != null) { + res = Math.max(res, i - hash[sum]) + } else { + hash[sum] = i + } + + } + + return res +}; + diff --git a/526-beautiful-arrangement.js b/526.beautiful-arrangement.js similarity index 100% rename from 526-beautiful-arrangement.js rename to 526.beautiful-arrangement.js diff --git a/527-word-abbreviation.js b/527.word-abbreviation.js similarity index 100% rename from 527-word-abbreviation.js rename to 527.word-abbreviation.js diff --git a/528-random-pick-with-weight.js b/528-random-pick-with-weight.js deleted file mode 100644 index e33a3904..00000000 --- a/528-random-pick-with-weight.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * @param {number[]} w - */ -const Solution = function(w) { - this.a = [] - let sum = 0 - for (let i = 0, len = w.length; i < len; i++) { - sum += w[i] - this.a[i] = sum - } -} - -/** - * @return {number} - */ -Solution.prototype.pickIndex = function() { - const len = this.a.length - const sum = this.a[len - 1] - const rand = ((Math.random() * sum) >> 0) + 1 - let l = 0, - h = len - 1 - while (l < h) { - const mid = (l + h) >> 1 - if (this.a[mid] === rand) return mid - else if (this.a[mid] < rand) l = mid + 1 - else h = mid - } - return l -} - -/** - * Your Solution object will be instantiated and called as such: - * var obj = new Solution(w) - * var param_1 = obj.pickIndex() - */ - -// another - -/** - * @param {number[]} w - */ -const Solution = function(w) { - this.a = [] - let sum = 0 - for(let i = 0, len = w.length; i < len; i++) { - sum += w[i] - this.a[i] = sum - } -}; - -/** - * @return {number} - */ -Solution.prototype.pickIndex = function() { - const len = this.a.length - const sum = this.a[len - 1] - const rand = ((Math.random() * sum) >> 0) + 1 - let l = 0, h = len - 1 - while(l <= h) { - const mid = (l + h) >> 1 - if(this.a[mid] === rand) return mid - else if(this.a[mid] < rand) l = mid + 1 - else h = mid - 1 - } - return l -}; - -/** - * Your Solution object will be instantiated and called as such: - * var obj = new Solution(w) - * var param_1 = obj.pickIndex() - */ - -// another - -/** - * @param {number[]} w - */ -const Solution = function(w) { - this.a = [] - let sum = 0 - for(let i = 0, len = w.length; i < len; i++) { - sum += w[i] - this.a[i] = sum - } -}; - -/** - * @return {number} - */ -Solution.prototype.pickIndex = function() { - const len = this.a.length - const sum = this.a[len - 1] - const rand = ((Math.random() * sum) >> 0) + 1 - let l = 0, h = len - 1 - while(l < h) { - const mid = (l + h) >> 1 - if(this.a[mid] < rand) l = mid + 1 - else h = mid - } - return l -}; - -/** - * Your Solution object will be instantiated and called as such: - * var obj = new Solution(w) - * var param_1 = obj.pickIndex() - */ diff --git a/528.random-pick-with-weight.js b/528.random-pick-with-weight.js new file mode 100644 index 00000000..ac553180 --- /dev/null +++ b/528.random-pick-with-weight.js @@ -0,0 +1,36 @@ +/** + * @param {number[]} w + */ +const Solution = function(w) { + this.a = [] + let sum = 0 + for (let i = 0, len = w.length; i < len; i++) { + sum += w[i] + this.a[i] = sum + } +} + +/** + * @return {number} + */ +Solution.prototype.pickIndex = function() { + const len = this.a.length + const sum = this.a[len - 1] + const rand = ((Math.random() * sum) >> 0) + 1 + let l = 0, + h = len - 1 + while (l < h) { + const mid = (l + h) >> 1 + if (this.a[mid] === rand) return mid + else if (this.a[mid] < rand) l = mid + 1 + else h = mid + } + return l +} + +/** + * Your Solution object will be instantiated and called as such: + * var obj = new Solution(w) + * var param_1 = obj.pickIndex() + */ + diff --git a/529-minesweeper.js b/529.minesweeper.js similarity index 100% rename from 529-minesweeper.js rename to 529.minesweeper.js diff --git a/53-maximum-subarray.js b/53-maximum-subarray.js deleted file mode 100755 index dde9daa9..00000000 --- a/53-maximum-subarray.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const maxSubArray = function (nums) { - let res = -1e9, sum = 0 - for(const e of nums) { - sum += e - res = Math.max(res, sum) - if(sum < 0) sum = 0 - } - return res -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxSubArray = function(nums) { - let preSum = nums[0]; - let maxSum = preSum; - for (let i = 1; i < nums.length; i++) { - preSum = preSum > 0 ? preSum + nums[i] : nums[i]; - maxSum = Math.max(preSum, maxSum); - } - return maxSum; -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxSubArray = function(nums) { - const n = nums.length, dp = Array(n).fill(0) - dp[0] = nums[0] - let res = dp[0] - for(let i = 1; i < n; i++) { - dp[i] = Math.max(dp[i - 1], 0) + nums[i] - res = Math.max(res, dp[i]) - } - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maxSubArray = function(nums) { - return helper(nums, 0, nums.length - 1) -}; - -function helper(arr, l, r) { - if(l > r) return -Infinity - const mid = l + ((r - l) >> 1) - let cur = 0, leftMax = 0, rightMax = 0 - for(let i = mid - 1; i >= l; i--) { - cur += arr[i] - leftMax = Math.max(leftMax, cur) - } - cur = 0 - for(let i = mid + 1; i <= r; i++) { - cur += arr[i] - rightMax = Math.max(rightMax, cur) - } - const res = arr[mid] + leftMax + rightMax - const leftRes = helper(arr, l, mid - 1) - const rightRes = helper(arr, mid + 1, r) - - return Math.max(res, leftRes, rightRes) -} diff --git a/53.maximum-subarray.js b/53.maximum-subarray.js new file mode 100644 index 00000000..312ff42c --- /dev/null +++ b/53.maximum-subarray.js @@ -0,0 +1,14 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const maxSubArray = function (nums) { + let res = -1e9, sum = 0 + for(const e of nums) { + sum += e + res = Math.max(res, sum) + if(sum < 0) sum = 0 + } + return res +} + diff --git a/530-minimum-absolute-difference-in-BST.js b/530-minimum-absolute-difference-in-BST.js deleted file mode 100755 index 173f1715..00000000 --- a/530-minimum-absolute-difference-in-BST.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const getMinimumDifference = function(root) { - const arr = []; - traversal(root, arr); - let min = Number.MAX_SAFE_INTEGER; - for (let i = 1; i < arr.length; i++) { - min = Math.min(min, arr[i] - arr[i - 1]); - } - return min; -}; - -function traversal(node, arr) { - if (node === null) return; - if (node.left) { - traversal(node.left, arr); - } - arr.push(node.val); - if (node.right) { - traversal(node.right, arr); - } -} diff --git a/530.minimum-absolute-difference-in-BST.js b/530.minimum-absolute-difference-in-BST.js new file mode 100644 index 00000000..369d64d7 --- /dev/null +++ b/530.minimum-absolute-difference-in-BST.js @@ -0,0 +1,31 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +const getMinimumDifference = function(root) { + const arr = []; + traversal(root, arr); + let min = Number.MAX_SAFE_INTEGER; + for (let i = 1; i < arr.length; i++) { + min = Math.min(min, arr[i] - arr[i - 1]); + } + return min; +}; + +function traversal(node, arr) { + if (node === null) return; + if (node.left) { + traversal(node.left, arr); + } + arr.push(node.val); + if (node.right) { + traversal(node.right, arr); + } +} diff --git a/531-lonely-pixel-i.js b/531-lonely-pixel-i.js deleted file mode 100644 index c56dd1ea..00000000 --- a/531-lonely-pixel-i.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @param {character[][]} picture - * @return {number} - */ -const findLonelyPixel = function(picture) { - if(picture == null || picture[0].length === 0) return 0 - const rows = picture.length - const cols = picture[0].length - const r = new Array(rows).fill(0) - const c = new Array(cols).fill(0) - for(let i = 0; i < rows; i++) { - for(let j = 0; j < cols; j++) { - if(picture[i][j] === 'B') { - r[i]++ - c[j]++ - } - } - } - let res = 0 - for(let i = 0; i < rows; i++) { - if(r[i] === 1) { - for(let j = 0; j < cols; j++) { - if(picture[i][j] === 'B') { - if(c[j] === 1)res++ - break - } - } - } - } - return res -}; - -// another - -/** - * @param {character[][]} picture - * @return {number} - */ -const findLonelyPixel = function(picture) { - if(picture == null || picture[0].length === 0) return 0 - const rows = picture.length - const cols = picture[0].length - const c = new Array(cols).fill(0) - for(let i = 0; i < rows; i++) { - for(let j = 0; j < cols; j++) { - if(picture[i][j] === 'B') c[j]++ - } - } - let res = 0 - for(let i = 0; i < rows; i++) { - let cnt = 0, pos = -1 - for(let j = 0; j < cols; j++) { - if(picture[i][j] !== 'B') continue - if(++cnt === 1) pos = j - else break - } - if(cnt === 1 && c[pos] === 1) res++ - } - return res -}; diff --git a/531.lonely-pixel-i.js b/531.lonely-pixel-i.js new file mode 100644 index 00000000..f2979338 --- /dev/null +++ b/531.lonely-pixel-i.js @@ -0,0 +1,32 @@ +/** + * @param {character[][]} picture + * @return {number} + */ +const findLonelyPixel = function(picture) { + if(picture == null || picture[0].length === 0) return 0 + const rows = picture.length + const cols = picture[0].length + const r = new Array(rows).fill(0) + const c = new Array(cols).fill(0) + for(let i = 0; i < rows; i++) { + for(let j = 0; j < cols; j++) { + if(picture[i][j] === 'B') { + r[i]++ + c[j]++ + } + } + } + let res = 0 + for(let i = 0; i < rows; i++) { + if(r[i] === 1) { + for(let j = 0; j < cols; j++) { + if(picture[i][j] === 'B') { + if(c[j] === 1)res++ + break + } + } + } + } + return res +}; + diff --git a/532-k-diff-pairs-in-an-array.js b/532.k-diff-pairs-in-an-array.js similarity index 100% rename from 532-k-diff-pairs-in-an-array.js rename to 532.k-diff-pairs-in-an-array.js diff --git a/533-lonely-pixel-ii.js b/533-lonely-pixel-ii.js deleted file mode 100644 index f4de89c9..00000000 --- a/533-lonely-pixel-ii.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @param {character[][]} picture - * @param {number} N - * @return {number} - */ -const findBlackPixel = function(picture, N) { - let m = [] - for (let i = 0; i < picture.length; i++) { - let cnt = 0 - let str = '' - for (let j = 0; j < picture[0].length; j++) { - if (picture[i][j] === 'W') continue - cnt++ - if (cnt > N) break - str += j + ',' - } - if (cnt === N) m[i] = str - } - let ans = 0 - for (let j = 0; j < picture[0].length; j++) { - let cnt = 0 - let rowStr = '' - for (let i = 0; i < picture.length; i++) { - if (picture[i][j] === 'W') continue - cnt++ - if (cnt === 1) rowStr = m[i] - else if (cnt > N || m[i] !== rowStr) { - rowStr = '' - break - } - } - if (cnt === N && rowStr) ans += N - } - return ans -} - -// another - -/** - * @param {character[][]} picture - * @param {number} N - * @return {number} - */ -const findBlackPixel = function(picture, N) { - const rows = picture.length - if(rows === 0) return 0 - const cols = picture[0].length - if(cols === 0) return 0 - const m = new Map() - const colCnt = new Array(cols).fill(0) - for(let i = 0; i < rows; i++) { - const k = scanRow(picture, i, cols, N, colCnt) - if(k) { - m.set(k, (m.get(k) || 0) + 1) - } - } - let res = 0 - for(let [k, v] of m) { - if(v === N) { - for(let i = 0; i < cols; i++) { - if(k[i] === 'B' && colCnt[i] === N) res += N - } - } - } - return res -} - -function scanRow(p, r, cols, N, arr) { - let str = '' - let cnt = 0 - for(let i = 0; i < cols; i++) { - if(p[r][i] === 'B') { - cnt++ - arr[i] += 1 - } - str += p[r][i] - } - if(cnt === N) return str - return '' -} - diff --git a/533.lonely-pixel-ii.js b/533.lonely-pixel-ii.js new file mode 100644 index 00000000..f67eaffd --- /dev/null +++ b/533.lonely-pixel-ii.js @@ -0,0 +1,36 @@ +/** + * @param {character[][]} picture + * @param {number} N + * @return {number} + */ +const findBlackPixel = function(picture, N) { + let m = [] + for (let i = 0; i < picture.length; i++) { + let cnt = 0 + let str = '' + for (let j = 0; j < picture[0].length; j++) { + if (picture[i][j] === 'W') continue + cnt++ + if (cnt > N) break + str += j + ',' + } + if (cnt === N) m[i] = str + } + let ans = 0 + for (let j = 0; j < picture[0].length; j++) { + let cnt = 0 + let rowStr = '' + for (let i = 0; i < picture.length; i++) { + if (picture[i][j] === 'W') continue + cnt++ + if (cnt === 1) rowStr = m[i] + else if (cnt > N || m[i] !== rowStr) { + rowStr = '' + break + } + } + if (cnt === N && rowStr) ans += N + } + return ans +} + diff --git a/536-construct-binary-tree-from-string.js b/536.construct-binary-tree-from-string.js similarity index 100% rename from 536-construct-binary-tree-from-string.js rename to 536.construct-binary-tree-from-string.js diff --git a/538-convert-BST-to-greater-tree.js b/538-convert-BST-to-greater-tree.js deleted file mode 100755 index 6d28ba26..00000000 --- a/538-convert-BST-to-greater-tree.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode} - */ -const convertBST = function(root) { - if (root == null) return null; - convertBST(root.right); - root.val += sum; - sum = root.val; - convertBST(root.left); - return root; -}; diff --git a/538-convert-bst-to-greater-tree.js b/538-convert-bst-to-greater-tree.js deleted file mode 100644 index 9ee89693..00000000 --- a/538-convert-bst-to-greater-tree.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode} - */ -const convertBST = function(root) { - const arr = [] - traverse(root, arr) - for(let i = arr.length - 2; i >= 0; i--) { - arr[i].val += arr[i + 1].val - } - return root -}; - -function traverse(node, arr) { - if(node == null) return - traverse(node.right, arr) - arr.unshift(node) - traverse(node.left, arr) -} - - -// another - -/** - * @param {TreeNode} root - * @return {TreeNode} - */ -const convertBST = function(root) { - const obj = {sum: 0} - traverse(root, obj) - return root -}; - -function traverse(node, obj) { - if(node == null) return - traverse(node.right, obj) - node.val += obj.sum - obj.sum = node.val - traverse(node.left, obj) -} diff --git a/538.convert-BST-to-greater-tree.js b/538.convert-BST-to-greater-tree.js new file mode 100644 index 00000000..7302830b --- /dev/null +++ b/538.convert-BST-to-greater-tree.js @@ -0,0 +1,19 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {TreeNode} + */ +const convertBST = function(root) { + if (root == null) return null; + convertBST(root.right); + root.val += sum; + sum = root.val; + convertBST(root.left); + return root; +}; diff --git a/539-minimum-time-difference.js b/539-minimum-time-difference.js deleted file mode 100755 index 2941bbd4..00000000 --- a/539-minimum-time-difference.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @param {string[]} timePoints - * @return {number} - */ -const findMinDifference = function(timePoints) { - const sortedArr = timePoints - .map(el => { - const arr = el.trim().split(":"); - return arr[0] === "00" && arr[1] === "00" - ? 24 * 60 - : +arr[0] * 60 + +arr[1]; - }) - .sort((a, b) => a - b); - let prev = sortedArr[0]; - let res = Number.MAX_SAFE_INTEGER; - const mid = 12 * 60; - for (let i = 1; i < sortedArr.length; i++) { - res = Math.min(res, Math.abs(sortedArr[i] - prev)); - prev = sortedArr[i]; - } - if (sortedArr[0] < mid && sortedArr[sortedArr.length - 1] > mid) { - res = Math.min( - res, - sortedArr[0] + 2 * mid - sortedArr[sortedArr.length - 1] - ); - } - return res; -}; - -console.log(findMinDifference(["23:59", "00:00"])); -console.log(findMinDifference(["12:12", "00:13"])); -console.log(findMinDifference(["05:31", "22:08", "00:35"])); diff --git a/539.minimum-time-difference.js b/539.minimum-time-difference.js new file mode 100644 index 00000000..01232915 --- /dev/null +++ b/539.minimum-time-difference.js @@ -0,0 +1,32 @@ +/** + * @param {string[]} timePoints + * @return {number} + */ +const findMinDifference = function(timePoints) { + const sortedArr = timePoints + .map(el => { + const arr = el.trim().split(":"); + return arr[0] === "00" && arr[1] === "00" + ? 24 * 60 + : +arr[0] * 60 + +arr[1]; + }) + .sort((a, b) => a - b); + let prev = sortedArr[0]; + let res = Number.MAX_SAFE_INTEGER; + const mid = 12 * 60; + for (let i = 1; i < sortedArr.length; i++) { + res = Math.min(res, Math.abs(sortedArr[i] - prev)); + prev = sortedArr[i]; + } + if (sortedArr[0] < mid && sortedArr[sortedArr.length - 1] > mid) { + res = Math.min( + res, + sortedArr[0] + 2 * mid - sortedArr[sortedArr.length - 1] + ); + } + return res; +}; + +console.log(findMinDifference(["23:59", "00:00"])); +console.log(findMinDifference(["12:12", "00:13"])); +console.log(findMinDifference(["05:31", "22:08", "00:35"])); diff --git a/54-spiral-matrix.js b/54-spiral-matrix.js deleted file mode 100644 index fbbb5aff..00000000 --- a/54-spiral-matrix.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @param {number[][]} matrix - * @return {number[]} - */ -const spiralOrder = function(matrix) { - const res = [] - let dir = 'top' - while(matrix.length) { - switch (dir) { - case 'top': - res.push(...matrix.shift()) - dir = 'right' - break; - case 'right': - for(let i = 0; i < matrix.length - 1; ) { - res.push(matrix[i].pop()) - if (matrix[i].length === 0) { - matrix.splice(i, 1) - } else { - i++ - } - } - dir = 'bottom' - break; - case 'bottom': - res.push(...matrix.pop().reverse()) - dir = 'left' - break; - case 'left': - for(let i = matrix.length - 1; i >= 0; i--) { - res.push(matrix[i].shift()) - if (matrix[i].length === 0) { - matrix.splice(i, 1) - } - } - dir = 'top' - break; - } - } - return res -}; - -// another - -/** - * @param {number[][]} matrix - * @return {number[]} - */ -const spiralOrder = function(matrix) { - const res = [], m = matrix.length, n = matrix[0].length - const dirs = [[0, 1], [1, 0], [0, -1], [-1, 0]] - let di = 0, i = 0, j = 0, nx = 0, ny = 1 - while(true) { - res.push(matrix[i][j]) - matrix[i][j] = Infinity - if(chk(i, j)) { - if(di === 0 && (j + 1 >= n || matrix[i][j + 1] === Infinity)) { - i++ - di = 1 - } else if(di === 1 && (i + 1 >= m || matrix[i + 1][j] === Infinity)) { - j-- - di = 2 - } else if(di === 2 && (j - 1 < 0 || matrix[i][j - 1] === Infinity)) { - i-- - di = 3 - } else if(di === 3 && (i - 1 < 0 || matrix[i - 1][j] === Infinity)) { - j++ - di = 0 - } else { - i += dirs[di][0] - j += dirs[di][1] - } - } else break - } - return res - - function chk(i, j) { - for(let dir of dirs) { - const nx = i + dir[0], ny = j + dir[1] - if(nx >= 0 && nx < matrix.length && ny >= 0 && ny < matrix[0].length && matrix[nx][ny] !== Infinity) return true - } - return false - } -}; - - diff --git a/54.spiral-matrix.js b/54.spiral-matrix.js new file mode 100644 index 00000000..933a6cb8 --- /dev/null +++ b/54.spiral-matrix.js @@ -0,0 +1,42 @@ +/** + * @param {number[][]} matrix + * @return {number[]} + */ +const spiralOrder = function(matrix) { + const res = [] + let dir = 'top' + while(matrix.length) { + switch (dir) { + case 'top': + res.push(...matrix.shift()) + dir = 'right' + break; + case 'right': + for(let i = 0; i < matrix.length - 1; ) { + res.push(matrix[i].pop()) + if (matrix[i].length === 0) { + matrix.splice(i, 1) + } else { + i++ + } + } + dir = 'bottom' + break; + case 'bottom': + res.push(...matrix.pop().reverse()) + dir = 'left' + break; + case 'left': + for(let i = matrix.length - 1; i >= 0; i--) { + res.push(matrix[i].shift()) + if (matrix[i].length === 0) { + matrix.splice(i, 1) + } + } + dir = 'top' + break; + } + } + return res +}; + diff --git a/540-single-element-in-a-sorted-array.js b/540-single-element-in-a-sorted-array.js deleted file mode 100755 index a840caa3..00000000 --- a/540-single-element-in-a-sorted-array.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const singleNonDuplicate = function(nums) { - let i = 0; - while (true) { - if (nums[i] == nums[i + 1]) { - i += 2; - } else { - return nums[i]; - } - } -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const singleNonDuplicate = function(nums) { - const n = nums.length - let left = 0, right = n - 1 - while(left < right) { - const mid = left + ((right - left) >> 1) - if(nums[mid] === nums[mid ^ 1]) left = mid + 1 - else right = mid - } - - return nums[left] -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const singleNonDuplicate = function(nums) { - const n = nums.length - let left = 0, right = n - 1 - while(left < right) { - const mid = ~~((left + right) / 2) - if((mid % 2 === 0 && nums[mid] === nums[mid + 1]) || (mid % 2 === 1 && nums[mid] === nums[mid - 1])) left = mid + 1 - else right = mid - } - - return nums[left] -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const singleNonDuplicate = function(nums) { - if(nums.length === 0) return 0 - let res = nums[0] - for(let i = 1, len = nums.length; i < len; i++) { - res ^= nums[i] - } - return res -}; diff --git a/540.single-element-in-a-sorted-array.js b/540.single-element-in-a-sorted-array.js new file mode 100644 index 00000000..359a2057 --- /dev/null +++ b/540.single-element-in-a-sorted-array.js @@ -0,0 +1,15 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const singleNonDuplicate = function(nums) { + let i = 0; + while (true) { + if (nums[i] == nums[i + 1]) { + i += 2; + } else { + return nums[i]; + } + } +}; + diff --git a/541-reverse-string-ii.js b/541.reverse-string-ii.js similarity index 100% rename from 541-reverse-string-ii.js rename to 541.reverse-string-ii.js diff --git a/542-01-matrix.js b/542.01-matrix.js similarity index 100% rename from 542-01-matrix.js rename to 542.01-matrix.js diff --git a/543-diameter-of-binary-tree.js b/543-diameter-of-binary-tree.js deleted file mode 100755 index acf2deac..00000000 --- a/543-diameter-of-binary-tree.js +++ /dev/null @@ -1,79 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const diameterOfBinaryTree = function (root) { - if (root === null) return 0 - let longest = 0 - function dfs(node) { - if (node === null) return 0 - let leftmax = dfs(node.left) - let rightmax = dfs(node.right) - longest = Math.max(longest, leftmax + 1 + rightmax) - return Math.max(leftmax, rightmax) + 1 - } - dfs(root) - return longest - 1 -} - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const diameterOfBinaryTree = function(root) { - let res = 0 - dfs(root) - return res - - function dfs(node) { - if(node == null) return 0 - const left = dfs(node.left), right = dfs(node.right) - res = Math.max(res, left + right) - return Math.max(left, right) + 1 - } -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const diameterOfBinaryTree = function(root) { - let res = -Infinity - dfs(root) - return res - function dfs(node) { - if(node == null) return -1 - const left = dfs(node.left) - const right = dfs(node.right) - res = Math.max(res, left + right + 2) - return Math.max(left, right) + 1 - } -}; - diff --git a/543.diameter-of-binary-tree.js b/543.diameter-of-binary-tree.js new file mode 100644 index 00000000..088a6463 --- /dev/null +++ b/543.diameter-of-binary-tree.js @@ -0,0 +1,25 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +const diameterOfBinaryTree = function (root) { + if (root === null) return 0 + let longest = 0 + function dfs(node) { + if (node === null) return 0 + let leftmax = dfs(node.left) + let rightmax = dfs(node.right) + longest = Math.max(longest, leftmax + 1 + rightmax) + return Math.max(leftmax, rightmax) + 1 + } + dfs(root) + return longest - 1 +} + diff --git a/544-output-contest-matches.js b/544-output-contest-matches.js deleted file mode 100644 index e81f6d0f..00000000 --- a/544-output-contest-matches.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - -During the NBA playoffs, we always arrange the rather strong team to play with the rather weak team, -like make the rank 1 team play with the rank nth team, which is a good strategy to make the contest more interesting. -Now, you're given n teams, you need to output their final contest matches in the form of a string. - -The n teams are given in the form of positive integers from 1 to n, which represents their initial rank. -(Rank 1 is the strongest team and Rank n is the weakest team.) -We'll use parentheses('(', ')') and commas(',') to represent the contest team pairing - parentheses('(' , ')') for -pairing and commas(',') for partition. During the pairing process in each round, -you always need to follow the strategy of making the rather strong one pair with the rather weak one. - -Example 1: -Input: 2 -Output: (1,2) -Explanation: -Initially, we have the team 1 and the team 2, placed like: 1,2. -Then we pair the team (1,2) together with '(', ')' and ',', which is the final answer. -Example 2: -Input: 4 -Output: ((1,4),(2,3)) -Explanation: -In the first round, we pair the team 1 and 4, the team 2 and 3 together, as we need to make the strong team and weak team together. -And we got (1,4),(2,3). -In the second round, the winners of (1,4) and (2,3) need to play again to generate the final winner, -so you need to add the paratheses outside them. -And we got the final answer ((1,4),(2,3)). -Example 3: -Input: 8 -Output: (((1,8),(4,5)),((2,7),(3,6))) -Explanation: -First round: (1,8),(2,7),(3,6),(4,5) -Second round: ((1,8),(4,5)),((2,7),(3,6)) -Third round: (((1,8),(4,5)),((2,7),(3,6))) -Since the third round will generate the final winner, you need to output the answer (((1,8),(4,5)),((2,7),(3,6))). -Note: -The n is in range [2, 212]. -We ensure that the input n can be converted into the form 2k, where k is a positive integer. - -*/ - -/** - * @param {number} n - * @return {string} - */ -const findContestMatch = function(n) { - const arr = [] - for(let i = 0; i < n; i++) { - arr[i] = i + 1 - } - while(n > 1) { - for(let i = 0; i < (n >> 1); i++) { - arr[i] = `(${arr[i]},${arr[n - 1 - i]})` - } - n = n >> 1 - } - return arr[0] -}; - -// another - -/** - * @param {number} n - * @return {string} - */ -const findContestMatch = function(n) { - const arr = [] - for(let i = 0; i < n; i++) { - arr[i] = i + 1 - } - let l = 0 - let r = n - 1 - while(l < r) { - while(l < r) { - arr[l] = `(${arr[l]},${arr[r]})` - l++ - r-- - } - l = 0 - } - return arr[0] -}; diff --git a/544.output-contest-matches.js b/544.output-contest-matches.js new file mode 100644 index 00000000..b464a248 --- /dev/null +++ b/544.output-contest-matches.js @@ -0,0 +1,59 @@ +/** + +During the NBA playoffs, we always arrange the rather strong team to play with the rather weak team, +like make the rank 1 team play with the rank nth team, which is a good strategy to make the contest more interesting. +Now, you're given n teams, you need to output their final contest matches in the form of a string. + +The n teams are given in the form of positive integers from 1 to n, which represents their initial rank. +(Rank 1 is the strongest team and Rank n is the weakest team.) +We'll use parentheses('(', ')') and commas(',') to represent the contest team pairing - parentheses('(' , ')') for +pairing and commas(',') for partition. During the pairing process in each round, +you always need to follow the strategy of making the rather strong one pair with the rather weak one. + +Example 1: +Input: 2 +Output: (1,2) +Explanation: +Initially, we have the team 1 and the team 2, placed like: 1,2. +Then we pair the team (1,2) together with '(', ')' and ',', which is the final answer. +Example 2: +Input: 4 +Output: ((1,4),(2,3)) +Explanation: +In the first round, we pair the team 1 and 4, the team 2 and 3 together, as we need to make the strong team and weak team together. +And we got (1,4),(2,3). +In the second round, the winners of (1,4) and (2,3) need to play again to generate the final winner, +so you need to add the paratheses outside them. +And we got the final answer ((1,4),(2,3)). +Example 3: +Input: 8 +Output: (((1,8),(4,5)),((2,7),(3,6))) +Explanation: +First round: (1,8),(2,7),(3,6),(4,5) +Second round: ((1,8),(4,5)),((2,7),(3,6)) +Third round: (((1,8),(4,5)),((2,7),(3,6))) +Since the third round will generate the final winner, you need to output the answer (((1,8),(4,5)),((2,7),(3,6))). +Note: +The n is in range [2, 212]. +We ensure that the input n can be converted into the form 2k, where k is a positive integer. + +*/ + +/** + * @param {number} n + * @return {string} + */ +const findContestMatch = function(n) { + const arr = [] + for(let i = 0; i < n; i++) { + arr[i] = i + 1 + } + while(n > 1) { + for(let i = 0; i < (n >> 1); i++) { + arr[i] = `(${arr[i]},${arr[n - 1 - i]})` + } + n = n >> 1 + } + return arr[0] +}; + diff --git a/545-boundary-of-binary-tree.js b/545.boundary-of-binary-tree.js similarity index 100% rename from 545-boundary-of-binary-tree.js rename to 545.boundary-of-binary-tree.js diff --git a/546-remove-boxes.js b/546.remove-boxes.js similarity index 100% rename from 546-remove-boxes.js rename to 546.remove-boxes.js diff --git a/547-friend-circles.js b/547.friend-circles.js similarity index 100% rename from 547-friend-circles.js rename to 547.friend-circles.js diff --git a/548-split-array-with-equal-sum.js b/548.split-array-with-equal-sum.js similarity index 100% rename from 548-split-array-with-equal-sum.js rename to 548.split-array-with-equal-sum.js diff --git a/549-binary-tree-longest-consecutive-sequence-ii.js b/549.binary-tree-longest-consecutive-sequence-ii.js similarity index 100% rename from 549-binary-tree-longest-consecutive-sequence-ii.js rename to 549.binary-tree-longest-consecutive-sequence-ii.js diff --git a/55-jump-game.js b/55-jump-game.js deleted file mode 100644 index 4bf6ebf6..00000000 --- a/55-jump-game.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @param {number[]} nums - * @return {boolean} - */ -const canJump = function(nums) { - let max = 0 - for(let i = 0, len = nums.length; i < len; i++) { - if(i <= max && nums[i] > 0) { - max = Math.max(max, i + nums[i]) - } - } - return max >= nums.length - 1 -}; - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -const canJump = function(nums) { - let max = 0 - const n = nums.length - for(let i = 0; i < n; i++) { - if(max < i) return false - max = Math.max(max, i + nums[i]) - if(max >= n - 1) return true - } -}; diff --git a/55.jump-game.js b/55.jump-game.js new file mode 100644 index 00000000..68b71b94 --- /dev/null +++ b/55.jump-game.js @@ -0,0 +1,14 @@ +/** + * @param {number[]} nums + * @return {boolean} + */ +const canJump = function(nums) { + let max = 0 + for(let i = 0, len = nums.length; i < len; i++) { + if(i <= max && nums[i] > 0) { + max = Math.max(max, i + nums[i]) + } + } + return max >= nums.length - 1 +}; + diff --git a/551-student-attendance-record-i.js b/551.student-attendance-record-i.js similarity index 100% rename from 551-student-attendance-record-i.js rename to 551.student-attendance-record-i.js diff --git a/552-student-attendance-record-ii.js b/552.student-attendance-record-ii.js similarity index 100% rename from 552-student-attendance-record-ii.js rename to 552.student-attendance-record-ii.js diff --git a/553-optimal-division.js b/553.optimal-division.js similarity index 100% rename from 553-optimal-division.js rename to 553.optimal-division.js diff --git a/554-brick-wall.js b/554-brick-wall.js deleted file mode 100755 index b412e0e2..00000000 --- a/554-brick-wall.js +++ /dev/null @@ -1,25 +0,0 @@ -/** - * @param {number[][]} wall - * @return {number} - */ -const leastBricks = function(wall) { - const hash = {}; - let row; - let rowSum = 0; - for (let i = 0; i < wall.length; i++) { - rowSum = 0; - row = wall[i]; - for (let j = 0; j < row.length - 1; j++) { - rowSum += row[j]; - hash[rowSum] = hash.hasOwnProperty(rowSum) ? hash[rowSum] + 1 : 1; - } - } - return ( - wall.length - - (Object.keys(hash).length > 0 - ? Math.max(...Object.keys(hash).map(key => hash[key])) - : 0) - ); -}; - -console.log(leastBricks([[1], [1], [1]])); diff --git a/554.brick-wall.js b/554.brick-wall.js new file mode 100644 index 00000000..ddb17c08 --- /dev/null +++ b/554.brick-wall.js @@ -0,0 +1,25 @@ +/** + * @param {number[][]} wall + * @return {number} + */ +const leastBricks = function(wall) { + const hash = {}; + let row; + let rowSum = 0; + for (let i = 0; i < wall.length; i++) { + rowSum = 0; + row = wall[i]; + for (let j = 0; j < row.length - 1; j++) { + rowSum += row[j]; + hash[rowSum] = hash.hasOwnProperty(rowSum) ? hash[rowSum] + 1 : 1; + } + } + return ( + wall.length - + (Object.keys(hash).length > 0 + ? Math.max(...Object.keys(hash).map(key => hash[key])) + : 0) + ); +}; + +console.log(leastBricks([[1], [1], [1]])); diff --git a/555-split-concatenated-strings.js b/555.split-concatenated-strings.js similarity index 100% rename from 555-split-concatenated-strings.js rename to 555.split-concatenated-strings.js diff --git a/556-next-greater-element-iii.js b/556.next-greater-element-iii.js similarity index 100% rename from 556-next-greater-element-iii.js rename to 556.next-greater-element-iii.js diff --git a/558-logical-or-of-two-binary-grids-represented-as-quad-trees.js b/558.logical-or-of-two-binary-grids-represented-as-quad-trees.js similarity index 100% rename from 558-logical-or-of-two-binary-grids-represented-as-quad-trees.js rename to 558.logical-or-of-two-binary-grids-represented-as-quad-trees.js diff --git a/559-maximum-depth-of-n-ary-tree.js b/559.maximum-depth-of-n-ary-tree.js similarity index 100% rename from 559-maximum-depth-of-n-ary-tree.js rename to 559.maximum-depth-of-n-ary-tree.js diff --git a/56-merge-intervals.js b/56-merge-intervals.js deleted file mode 100644 index a772b911..00000000 --- a/56-merge-intervals.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @param {number[][]} intervals - * @return {number[][]} - */ -const merge = function(intervals) { - intervals.sort((a, b) => a[0] - b[0] || a[1] - b[1]) - const res = [intervals[0]] - for(let i = 1, n = intervals.length; i < n; i++) { - const [s, e] = intervals[i] - const pre = res[res.length - 1] - if(s <= pre[1]) { - pre[1] = Math.max(pre[1], e) - } else { - res.push(intervals[i]) - } - } - return res -}; - -// another - - -/** - * @param {number[][]} intervals - * @return {number[][]} - */ -const merge = function(intervals) { - if(intervals == null || intervals.length === 0) return [] - intervals.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]) - const res = [intervals[0]] - for(let i = 1, n = intervals.length; i < n; i++) { - const last = res[res.length - 1] - const lastEnd = last[1] - const [s, e] = intervals[i] - if(s > lastEnd) { - res.push(intervals[i]) - } else { - last[1] = Math.max(last[1], e) - } - } - return res -}; - -// another - -/** - * Definition for an interval. - * function Interval(start, end) { - * this.start = start; - * this.end = end; - * } - */ -/** - * @param {Interval[]} intervals - * @return {Interval[]} - */ -const merge = function(intervals) { - const hash = {} - intervals.forEach(el => { - if (hash.hasOwnProperty(el.start)) { - hash[el.start][1] = Math.max(hash[el.start][1], el.end) - } else { - hash[el.start] = [el.start, el.end] - } - }) - - const startArr = Object.keys(hash).sort((a, b) => +a - +b) - const res = [] - - while(startArr.length) { - let start = startArr.shift() - let end = hash[start][1] - - for(let i = 0; i < startArr.length; ) { - if (+startArr[i] <= end) { - end = Math.max(end, hash[startArr[i]][1]) - startArr.shift() - } else { - break - } - } - let ins = new Interval(+start, end) - res.push(ins) - - } - return res -}; diff --git a/56.merge-intervals.js b/56.merge-intervals.js new file mode 100644 index 00000000..8fb1661e --- /dev/null +++ b/56.merge-intervals.js @@ -0,0 +1,19 @@ +/** + * @param {number[][]} intervals + * @return {number[][]} + */ +const merge = function(intervals) { + intervals.sort((a, b) => a[0] - b[0] || a[1] - b[1]) + const res = [intervals[0]] + for(let i = 1, n = intervals.length; i < n; i++) { + const [s, e] = intervals[i] + const pre = res[res.length - 1] + if(s <= pre[1]) { + pre[1] = Math.max(pre[1], e) + } else { + res.push(intervals[i]) + } + } + return res +}; + diff --git a/560-subarray-sum-equals-k.js b/560-subarray-sum-equals-k.js deleted file mode 100644 index c81bff23..00000000 --- a/560-subarray-sum-equals-k.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const subarraySum = function(nums, k) { - let totalNum = 0 - const map = new Map() - let cumulativeSum = 0 - map.set(0, 1) - for (let i = 0, len = nums.length; i < len; i++) { - cumulativeSum += nums[i] - if (map.get(cumulativeSum - k)) { - totalNum += map.get(cumulativeSum - k) - } - if (map.get(cumulativeSum)) { - map.set(cumulativeSum, map.get(cumulativeSum) + 1) - } else { - map.set(cumulativeSum, 1) - } - } - return totalNum -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const subarraySum = function (nums, k) { - const n = nums.length, hash = { 0: 1 } - let pre = 0 - let res = 0 - for (let i = 0; i < n; i++) { - const cur = pre + nums[i] - if (hash[cur - k] != null) res += hash[cur - k] - hash[cur] = (hash[cur] || 0) + 1 - pre = cur - } - return res -} diff --git a/560.subarray-sum-equals-k.js b/560.subarray-sum-equals-k.js new file mode 100644 index 00000000..eba420c4 --- /dev/null +++ b/560.subarray-sum-equals-k.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const subarraySum = function(nums, k) { + let totalNum = 0 + const map = new Map() + let cumulativeSum = 0 + map.set(0, 1) + for (let i = 0, len = nums.length; i < len; i++) { + cumulativeSum += nums[i] + if (map.get(cumulativeSum - k)) { + totalNum += map.get(cumulativeSum - k) + } + if (map.get(cumulativeSum)) { + map.set(cumulativeSum, map.get(cumulativeSum) + 1) + } else { + map.set(cumulativeSum, 1) + } + } + return totalNum +} + diff --git a/562-longest-line-of-consecutive-one-in-matrix.js b/562.longest-line-of-consecutive-one-in-matrix.js similarity index 100% rename from 562-longest-line-of-consecutive-one-in-matrix.js rename to 562.longest-line-of-consecutive-one-in-matrix.js diff --git a/563-binary-tree-tilt.js b/563.binary-tree-tilt.js similarity index 100% rename from 563-binary-tree-tilt.js rename to 563.binary-tree-tilt.js diff --git a/564-find-the-closest-palindrome.js b/564.find-the-closest-palindrome.js similarity index 100% rename from 564-find-the-closest-palindrome.js rename to 564.find-the-closest-palindrome.js diff --git a/565-array-nesting.js b/565-array-nesting.js deleted file mode 100755 index 621fa822..00000000 --- a/565-array-nesting.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const arrayNesting = function(nums) { - let res = 0; - for (let i = 0; i < nums.length; i++) { - if (nums[i] !== Number.MAX_SAFE_INTEGER) { - let start = nums[i], - count = 0; - while (nums[start] !== Number.MAX_SAFE_INTEGER) { - let temp = start; - start = nums[start]; - count++; - nums[temp] = Number.MAX_SAFE_INTEGER; - } - res = Math.max(res, count); - } - } - return res; -}; diff --git a/565.array-nesting.js b/565.array-nesting.js new file mode 100644 index 00000000..188f342e --- /dev/null +++ b/565.array-nesting.js @@ -0,0 +1,21 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const arrayNesting = function(nums) { + let res = 0; + for (let i = 0; i < nums.length; i++) { + if (nums[i] !== Number.MAX_SAFE_INTEGER) { + let start = nums[i], + count = 0; + while (nums[start] !== Number.MAX_SAFE_INTEGER) { + let temp = start; + start = nums[start]; + count++; + nums[temp] = Number.MAX_SAFE_INTEGER; + } + res = Math.max(res, count); + } + } + return res; +}; diff --git a/566-reshape-the-matrix.js b/566-reshape-the-matrix.js deleted file mode 100755 index 5d780ee5..00000000 --- a/566-reshape-the-matrix.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @param {number[][]} nums - * @param {number} r - * @param {number} c - * @return {number[][]} - */ -const matrixReshape = function(nums, r, c) { - if (isValid(nums, r, c) === false) { - return nums; - } - const arr = []; - nums.forEach(el => arr.push(...el)); - const res = []; - for (let start = 0; start < arr.length; start = start + c) { - res.push(arr.slice(start, start + c)); - } - return res; -}; - -function isValid(matrix, r, c) { - if (matrix.length * matrix[0].length !== r * c) { - return false; - } else { - return true; - } -} - -console.log(matrixReshape([[1, 2], [3, 4]], 1, 4)); -console.log(matrixReshape([[1, 2], [3, 4]], 2, 4)); diff --git a/566.reshape-the-matrix.js b/566.reshape-the-matrix.js new file mode 100644 index 00000000..6cbf3a10 --- /dev/null +++ b/566.reshape-the-matrix.js @@ -0,0 +1,29 @@ +/** + * @param {number[][]} nums + * @param {number} r + * @param {number} c + * @return {number[][]} + */ +const matrixReshape = function(nums, r, c) { + if (isValid(nums, r, c) === false) { + return nums; + } + const arr = []; + nums.forEach(el => arr.push(...el)); + const res = []; + for (let start = 0; start < arr.length; start = start + c) { + res.push(arr.slice(start, start + c)); + } + return res; +}; + +function isValid(matrix, r, c) { + if (matrix.length * matrix[0].length !== r * c) { + return false; + } else { + return true; + } +} + +console.log(matrixReshape([[1, 2], [3, 4]], 1, 4)); +console.log(matrixReshape([[1, 2], [3, 4]], 2, 4)); diff --git a/567-permutation-in-string.js b/567-permutation-in-string.js deleted file mode 100644 index 9a36f675..00000000 --- a/567-permutation-in-string.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @param {string} s1 - * @param {string} s2 - * @return {boolean} - */ -const checkInclusion = function(s1, s2) { - if(s1.length > s2.length) return false - const s1map = new Array(26).fill(0) - const s2map = new Array(26).fill(0) - const aCode = ('a').charCodeAt(0) - const zCode = ('z').charCodeAt(0) - - for(let i = 0; i < s1.length; i++) { - s1map[s1.charCodeAt(i) - aCode]++ - s2map[s2.charCodeAt(i) - aCode]++ - } - - for(let i = 0; i < s2.length - s1.length; i++) { - if(matches(s1map, s2map)) return true - s2map[s2.charCodeAt(i + s1.length) - aCode]++ - s2map[s2.charCodeAt(i) - aCode]-- - } - - return matches(s1map, s2map) - -}; - -function matches(s1map, s2map) { - for(let i = 0; i < 26; i++) { - if(s1map[i] !== s2map[i]) return false - } - return true -} - - -// another - -/** - * @param {string} s1 - * @param {string} s2 - * @return {boolean} - */ -const checkInclusion = function(s1, s2) { - const arr = Array(26).fill(0) - const a = 'a'.charCodeAt(0) - const s1l = s1.length - for(let c of s1) arr[c.charCodeAt(0) - a] += 1 - for(let i = 0, len = s2.length; i < len; i++) { - const tmp = s2[i] - arr[tmp.charCodeAt(0) - a]-- - if(i >= s1l - 1) { - if(allZeros(arr)) return true - arr[s2.charCodeAt(i - s1l + 1) - a]++ - } - - } - - return false -}; - -function allZeros(arr) { - for(let e of arr) { - if(e !== 0) return false - } - return true -} diff --git a/567.permutation-in-string.js b/567.permutation-in-string.js new file mode 100644 index 00000000..a86c9baa --- /dev/null +++ b/567.permutation-in-string.js @@ -0,0 +1,35 @@ +/** + * @param {string} s1 + * @param {string} s2 + * @return {boolean} + */ +const checkInclusion = function(s1, s2) { + if(s1.length > s2.length) return false + const s1map = new Array(26).fill(0) + const s2map = new Array(26).fill(0) + const aCode = ('a').charCodeAt(0) + const zCode = ('z').charCodeAt(0) + + for(let i = 0; i < s1.length; i++) { + s1map[s1.charCodeAt(i) - aCode]++ + s2map[s2.charCodeAt(i) - aCode]++ + } + + for(let i = 0; i < s2.length - s1.length; i++) { + if(matches(s1map, s2map)) return true + s2map[s2.charCodeAt(i + s1.length) - aCode]++ + s2map[s2.charCodeAt(i) - aCode]-- + } + + return matches(s1map, s2map) + +}; + +function matches(s1map, s2map) { + for(let i = 0; i < 26; i++) { + if(s1map[i] !== s2map[i]) return false + } + return true +} + + diff --git a/568-maximum-vacation-days.js b/568.maximum-vacation-days.js similarity index 100% rename from 568-maximum-vacation-days.js rename to 568.maximum-vacation-days.js diff --git a/57-insert-interval.js b/57.insert-interval.js similarity index 100% rename from 57-insert-interval.js rename to 57.insert-interval.js diff --git a/572-subtree-of-another-tree.js b/572.subtree-of-another-tree.js similarity index 100% rename from 572-subtree-of-another-tree.js rename to 572.subtree-of-another-tree.js diff --git a/573-squirrel-simulation.js b/573-squirrel-simulation.js deleted file mode 100644 index 6d9f5cd5..00000000 --- a/573-squirrel-simulation.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @param {number} height - * @param {number} width - * @param {number[]} tree - * @param {number[]} squirrel - * @param {number[][]} nuts - * @return {number} - */ -const minDistance = function(height, width, tree, squirrel, nuts) { - const arr = nuts.map(el => 2 * distance(el, tree)) - const sum = arr.reduce((ac, el) => ac + el, 0) - let res = Number.MAX_VALUE - for(let i = 0, len = arr.length; i < len; i++) { - let tmp = sum - arr[i] + distance(squirrel, nuts[i]) + distance(nuts[i], tree) - res = Math.min(res, tmp) - } - return res -}; - -function distance(p1, p2) { - return Math.abs(p1[0] - p2[0]) + Math.abs(p1[1] - p2[1]) -} - -// another - -/** - * @param {number} height - * @param {number} width - * @param {number[]} tree - * @param {number[]} squirrel - * @param {number[][]} nuts - * @return {number} - */ -const minDistance = function (height, width, tree, squirrel, nuts) { - let sum = 0, - maxDiff = -Number.MAX_VALUE - for (let nut of nuts) { - const dist = Math.abs(tree[0] - nut[0]) + Math.abs(tree[1] - nut[1]) - sum += 2 * dist - maxDiff = Math.max( - maxDiff, - dist - Math.abs(squirrel[0] - nut[0]) - Math.abs(squirrel[1] - nut[1]) - ) - } - return sum - maxDiff -} diff --git a/573.squirrel-simulation.js b/573.squirrel-simulation.js new file mode 100644 index 00000000..ddee10a3 --- /dev/null +++ b/573.squirrel-simulation.js @@ -0,0 +1,23 @@ +/** + * @param {number} height + * @param {number} width + * @param {number[]} tree + * @param {number[]} squirrel + * @param {number[][]} nuts + * @return {number} + */ +const minDistance = function(height, width, tree, squirrel, nuts) { + const arr = nuts.map(el => 2 * distance(el, tree)) + const sum = arr.reduce((ac, el) => ac + el, 0) + let res = Number.MAX_VALUE + for(let i = 0, len = arr.length; i < len; i++) { + let tmp = sum - arr[i] + distance(squirrel, nuts[i]) + distance(nuts[i], tree) + res = Math.min(res, tmp) + } + return res +}; + +function distance(p1, p2) { + return Math.abs(p1[0] - p2[0]) + Math.abs(p1[1] - p2[1]) +} + diff --git a/5745-last-day-where-you-can-still-cross.js b/5745.last-day-where-you-can-still-cross.js similarity index 100% rename from 5745-last-day-where-you-can-still-cross.js rename to 5745.last-day-where-you-can-still-cross.js diff --git a/575-distribute-candies.js b/575-distribute-candies.js deleted file mode 100755 index 2077d614..00000000 --- a/575-distribute-candies.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @param {number[]} candies - * @return {number} - */ -const distributeCandies = function(candies) { - const uniqNum = candies.filter((el, idx, arr) => arr.indexOf(el) === idx) - .length; - const halfNum = candies.length / 2; - return halfNum > uniqNum ? uniqNum : halfNum; -}; - -console.log(distributeCandies([1, 1, 2, 2, 3, 3])); -console.log(distributeCandies([1, 1, 2, 3])); diff --git a/575.distribute-candies.js b/575.distribute-candies.js new file mode 100644 index 00000000..4d72865b --- /dev/null +++ b/575.distribute-candies.js @@ -0,0 +1,13 @@ +/** + * @param {number[]} candies + * @return {number} + */ +const distributeCandies = function(candies) { + const uniqNum = candies.filter((el, idx, arr) => arr.indexOf(el) === idx) + .length; + const halfNum = candies.length / 2; + return halfNum > uniqNum ? uniqNum : halfNum; +}; + +console.log(distributeCandies([1, 1, 2, 2, 3, 3])); +console.log(distributeCandies([1, 1, 2, 3])); diff --git a/576-out-of-boundary-paths.js b/576-out-of-boundary-paths.js deleted file mode 100644 index 78472acd..00000000 --- a/576-out-of-boundary-paths.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @param {number} m - * @param {number} n - * @param {number} N - * @param {number} i - * @param {number} j - * @return {number} - */ -const findPaths = function (m, n, N, i, j) { - const dp = [...Array(2)].map((_) => - [...Array(50)].map((_) => Array(50).fill(0)) - ) - while (N-- > 0) { - for (let i = 0; i < m; i++) { - for (let j = 0, nc = (N + 1) % 2, np = N % 2; j < n; j++) { - dp[nc][i][j] = - ((i === 0 ? 1 : dp[np][i - 1][j]) + - (i === m - 1 ? 1 : dp[np][i + 1][j]) + - (j === 0 ? 1 : dp[np][i][j - 1]) + - (j === n - 1 ? 1 : dp[np][i][j + 1])) % - 1000000007 - } - } - } - return dp[1][i][j] -} - -// another - -/** - * @param {number} m - * @param {number} n - * @param {number} N - * @param {number} i - * @param {number} j - * @return {number} - */ -const findPaths = function (m, n, N, i, j) { - if (N <= 0) return 0; - const MOD = 1000000007; - let count = Array.from({ length: m }, () => new Array(n).fill(0)); - count[i][j] = 1; - let result = 0; - const dirs = [ - [-1, 0], - [1, 0], - [0, -1], - [0, 1], - ]; - for (let step = 0; step < N; step++) { - const temp = Array.from({ length: m }, () => new Array(n).fill(0)); - for (let r = 0; r < m; r++) { - for (let c = 0; c < n; c++) { - for (let d of dirs) { - const nr = r + d[0]; - const nc = c + d[1]; - if (nr < 0 || nr >= m || nc < 0 || nc >= n) { - result = (result + count[r][c]) % MOD; - } else { - temp[nr][nc] = (temp[nr][nc] + count[r][c]) % MOD; - } - } - } - } - count = temp; - } - return result; -}; - -// another - -/** - * @param {number} m - * @param {number} n - * @param {number} N - * @param {number} i - * @param {number} j - * @return {number} - */ -const findPaths = function (m, n, N, i, j, memo = new Map()) { - const key = N + ',' + i + ',' + j; - if (memo.has(key)) return memo.get(key); - const isOutside = i === -1 || i === m || j === -1 || j === n; - if (N === 0 || isOutside) return +isOutside; - memo.set(key, ( - findPaths(m, n, N - 1, i - 1, j, memo) - + findPaths(m, n, N - 1, i + 1, j, memo) - + findPaths(m, n, N - 1, i, j + 1, memo) - + findPaths(m, n, N - 1, i, j - 1, memo) - ) % 1000000007); - return memo.get(key); -} - - - diff --git a/576.out-of-boundary-paths.js b/576.out-of-boundary-paths.js new file mode 100644 index 00000000..dd972834 --- /dev/null +++ b/576.out-of-boundary-paths.js @@ -0,0 +1,27 @@ +/** + * @param {number} m + * @param {number} n + * @param {number} N + * @param {number} i + * @param {number} j + * @return {number} + */ +const findPaths = function (m, n, N, i, j) { + const dp = [...Array(2)].map((_) => + [...Array(50)].map((_) => Array(50).fill(0)) + ) + while (N-- > 0) { + for (let i = 0; i < m; i++) { + for (let j = 0, nc = (N + 1) % 2, np = N % 2; j < n; j++) { + dp[nc][i][j] = + ((i === 0 ? 1 : dp[np][i - 1][j]) + + (i === m - 1 ? 1 : dp[np][i + 1][j]) + + (j === 0 ? 1 : dp[np][i][j - 1]) + + (j === n - 1 ? 1 : dp[np][i][j + 1])) % + 1000000007 + } + } + } + return dp[1][i][j] +} + diff --git a/58-length-of-last-word.js b/58-length-of-last-word.js deleted file mode 100755 index 7ded6d23..00000000 --- a/58-length-of-last-word.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const lengthOfLastWord = function(s) { - const arr = s.split(" "); - for (let i = arr.length - 1; i >= 0; i--) { - if (arr[i].length > 0) return arr[i].length; - } - return 0; -}; diff --git a/58.length-of-last-word.js b/58.length-of-last-word.js new file mode 100644 index 00000000..b6d9c573 --- /dev/null +++ b/58.length-of-last-word.js @@ -0,0 +1,11 @@ +/** + * @param {string} s + * @return {number} + */ +const lengthOfLastWord = function(s) { + const arr = s.split(" "); + for (let i = arr.length - 1; i >= 0; i--) { + if (arr[i].length > 0) return arr[i].length; + } + return 0; +}; diff --git a/581-shortest-unsorted-continuous-subarray.js b/581.shortest-unsorted-continuous-subarray.js similarity index 100% rename from 581-shortest-unsorted-continuous-subarray.js rename to 581.shortest-unsorted-continuous-subarray.js diff --git a/582-kill-process.js b/582-kill-process.js deleted file mode 100644 index d5c5c502..00000000 --- a/582-kill-process.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @param {number[]} pid - * @param {number[]} ppid - * @param {number} kill - * @return {number[]} - */ -const killProcess = function(pid, ppid, kill) { - const pm = new Map() - for(let i = 0, len = pid.length; i < len; i++) { - const c = pid[i] - const p = ppid[i] - let tmp = pm.get(p) - if(!tmp) tmp = new Set() - tmp.add(c) - pm.set(p, tmp) - } - const res = [] - const q = [kill] - while(q.length) { - const size = q.length - for(let i = 0; i < size; i++) { - const el = q.shift() - res.push(el) - if(pm.get(el)) { - q.push(...Array.from(pm.get(el))) - } - } - } - return res -}; - -// another - -/** - * @param {number[]} pid - * @param {number[]} ppid - * @param {number} kill - * @return {number[]} - */ -const killProcess = function(pid, ppid, kill) { - const pm = new Map() - for(let i = 0, len = pid.length; i < len; i++) { - const p = ppid[i] - let tmp = pm.get(p) - if(!tmp) tmp = new Set() - tmp.add(pid[i]) - pm.set(p, tmp) - } - const res = [] - function dfs(k) { - res.push(k) - if(pm.get(k)) { - for(let e of pm.get(k)) { - dfs(e) - } - } - } - dfs(kill) - return res -}; diff --git a/582.kill-process.js b/582.kill-process.js new file mode 100644 index 00000000..014b472d --- /dev/null +++ b/582.kill-process.js @@ -0,0 +1,31 @@ +/** + * @param {number[]} pid + * @param {number[]} ppid + * @param {number} kill + * @return {number[]} + */ +const killProcess = function(pid, ppid, kill) { + const pm = new Map() + for(let i = 0, len = pid.length; i < len; i++) { + const c = pid[i] + const p = ppid[i] + let tmp = pm.get(p) + if(!tmp) tmp = new Set() + tmp.add(c) + pm.set(p, tmp) + } + const res = [] + const q = [kill] + while(q.length) { + const size = q.length + for(let i = 0; i < size; i++) { + const el = q.shift() + res.push(el) + if(pm.get(el)) { + q.push(...Array.from(pm.get(el))) + } + } + } + return res +}; + diff --git a/583-delete-operation-for-two-strings.js b/583-delete-operation-for-two-strings.js deleted file mode 100644 index 66821d18..00000000 --- a/583-delete-operation-for-two-strings.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @param {string} word1 - * @param {string} word2 - * @return {number} - */ -const minDistance = function (word1, word2, memo = new Map()) { - if (word1 === word2) return 0 - if (word1 === '' || word2 === '') return Math.max(word1.length, word2.length) - const len1 = word1.length - const len2 = word2.length - if (memo.has(`${word1}-${word2}`)) return memo.get(`${word1}-${word2}`) - let res - if (word1[len1 - 1] === word2[len2 - 1]) { - res = minDistance(word1.slice(0, len1 - 1), word2.slice(0, len2 - 1), memo) - } else { - res = - 1 + - Math.min( - minDistance(word1.slice(0, len1 - 1), word2, memo), - minDistance(word1, word2.slice(0, len2 - 1), memo) - ) - } - memo.set(`${word1}-${word2}`, res) - return res -} - -// another - -/** - * @param {string} word1 - * @param {string} word2 - * @return {number} - */ -const minDistance = function (word1, word2) { - const len1 = word1.length - const len2 = word2.length - const dp = Array.from({ length: len1 + 1 }, () => new Array(len2 + 1).fill(0)) - for(let i = 1; i <= len1; i++) { - for(let j = 1; j<= len2; j++) { - if(word1[i - 1] === word2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1 - else dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]) - } - } - return len1 + len2 - dp[len1][len2] * 2 -} - -// another - -/** - * @param {string} word1 - * @param {string} word2 - * @return {number} - */ -const minDistance = function (word1, word2) { - const len1 = word1.length - const len2 = word2.length - const dp = Array.from({ length: len1 + 1 }, () => new Array(len2 + 1).fill(0)) - for(let i = 1; i <= len2; i++) { - dp[0][i] = i - } - for(let j = 1; j <= len1; j++) { - dp[j][0] = j - } - for(let i = 1; i <= len1; i++) { - for(let j = 1; j<= len2; j++) { - if(word1[i - 1] === word2[j - 1]) dp[i][j] = dp[i - 1][j - 1] - else dp[i][j] = Math.min(dp[i - 1][j], dp[i][j - 1]) + 1 - } - } - return dp[len1][len2] -} diff --git a/583.delete-operation-for-two-strings.js b/583.delete-operation-for-two-strings.js new file mode 100644 index 00000000..20e81b49 --- /dev/null +++ b/583.delete-operation-for-two-strings.js @@ -0,0 +1,26 @@ +/** + * @param {string} word1 + * @param {string} word2 + * @return {number} + */ +const minDistance = function (word1, word2, memo = new Map()) { + if (word1 === word2) return 0 + if (word1 === '' || word2 === '') return Math.max(word1.length, word2.length) + const len1 = word1.length + const len2 = word2.length + if (memo.has(`${word1}-${word2}`)) return memo.get(`${word1}-${word2}`) + let res + if (word1[len1 - 1] === word2[len2 - 1]) { + res = minDistance(word1.slice(0, len1 - 1), word2.slice(0, len2 - 1), memo) + } else { + res = + 1 + + Math.min( + minDistance(word1.slice(0, len1 - 1), word2, memo), + minDistance(word1, word2.slice(0, len2 - 1), memo) + ) + } + memo.set(`${word1}-${word2}`, res) + return res +} + diff --git a/5832-array-with-elements-not-equal-to-average-of-neighbors.js b/5832.array-with-elements-not-equal-to-average-of-neighbors.js similarity index 100% rename from 5832-array-with-elements-not-equal-to-average-of-neighbors.js rename to 5832.array-with-elements-not-equal-to-average-of-neighbors.js diff --git a/5843-number-of-strings-that-appear-as-substrings-in-word.js b/5843.number-of-strings-that-appear-as-substrings-in-word.js similarity index 100% rename from 5843-number-of-strings-that-appear-as-substrings-in-word.js rename to 5843.number-of-strings-that-appear-as-substrings-in-word.js diff --git a/5844-minimum-non-zero-product-of-the-array-elements.js b/5844.minimum-non-zero-product-of-the-array-elements.js similarity index 100% rename from 5844-minimum-non-zero-product-of-the-array-elements.js rename to 5844.minimum-non-zero-product-of-the-array-elements.js diff --git a/587-erect-the-fence.js b/587.erect-the-fence.js similarity index 100% rename from 587-erect-the-fence.js rename to 587.erect-the-fence.js diff --git a/588-design-in-memory-file-system.js b/588-design-in-memory-file-system.js deleted file mode 100644 index e23ea7dd..00000000 --- a/588-design-in-memory-file-system.js +++ /dev/null @@ -1,149 +0,0 @@ -const FileSystem = function () { - this.items = new Map() -} - -/** - * @param {string} path - * @return {string[]} - */ -FileSystem.prototype.ls = function (path) { - const paths = path.split('/').filter((p) => !!p.length) - let curr = this.items - let last = '' - - for (const p of paths) { - curr = curr.get(p) - last = p - } - const list = Array.from(curr.keys()).filter((e) => e !== 'content') - if (curr.has('content')) list.push(last) - return list.sort() -} - -/** - * @param {string} path - * @return {void} - */ -FileSystem.prototype.mkdir = function (path) { - const paths = path.split('/').filter((p) => !!p.length) - let curr = this.items - for (const p of paths) { - if (!curr.has(p)) { - curr.set(p, new Map()) - } - curr = curr.get(p) - } -} - -/** - * @param {string} filePath - * @param {string} content - * @return {void} - */ -FileSystem.prototype.addContentToFile = function (filePath, content) { - const paths = filePath.split('/').filter((p) => !!p.length) - let curr = this.items - for (const p of paths) { - if (!curr.has(p)) { - curr.set(p, new Map()) - } - curr = curr.get(p) - } - curr.set('content', (curr.get('content') || '') + content) -} - -/** - * @param {string} filePath - * @return {string} - */ -FileSystem.prototype.readContentFromFile = function (filePath) { - const paths = filePath.split('/').filter((p) => !!p.length) - let curr = this.items - for (const p of paths) { - curr = curr.get(p) - } - return curr.get('content') -} - -/** - * Your FileSystem object will be instantiated and called as such: - * var obj = new FileSystem() - * var param_1 = obj.ls(path) - * obj.mkdir(path) - * obj.addContentToFile(filePath,content) - * var param_4 = obj.readContentFromFile(filePath) - */ - -// another - -const FileSystem = function () { - this.root = new Node() -} - -/** - * @param {string} path - * @return {string[]} - */ -FileSystem.prototype.ls = function (path) { - const cur = this.find(path) - if(cur.content) { - const arr = path.split('/') - return [arr[arr.length - 1]] - } - return Object.keys(cur.children).sort() -} - -/** - * @param {string} path - * @return {void} - */ -FileSystem.prototype.mkdir = function (path) { - this.find(path) -} - -/** - * @param {string} filePath - * @param {string} content - * @return {void} - */ -FileSystem.prototype.addContentToFile = function (filePath, content) { - const cur = this.find(filePath) - cur.content += content -} - -/** - * @param {string} filePath - * @return {string} - */ -FileSystem.prototype.readContentFromFile = function (filePath) { - const cur = this.find(filePath) - return cur.content -} - -FileSystem.prototype.find = function (filePath) { - if(filePath.length === 1) return this.root - const arr = filePath.split('/').slice(1) - let cur = this.root - for(let e of arr) { - if (cur.children[e] == null) cur.children[e] = new Node() - cur = cur.children[e] - } - return cur -} - -/** - * Your FileSystem object will be instantiated and called as such: - * var obj = new FileSystem() - * var param_1 = obj.ls(path) - * obj.mkdir(path) - * obj.addContentToFile(filePath,content) - * var param_4 = obj.readContentFromFile(filePath) - */ - -class Node { - constructor() { - this.children = {} - this.content = '' - } -} - diff --git a/588.design-in-memory-file-system.js b/588.design-in-memory-file-system.js new file mode 100644 index 00000000..38e83bb1 --- /dev/null +++ b/588.design-in-memory-file-system.js @@ -0,0 +1,76 @@ +const FileSystem = function () { + this.items = new Map() +} + +/** + * @param {string} path + * @return {string[]} + */ +FileSystem.prototype.ls = function (path) { + const paths = path.split('/').filter((p) => !!p.length) + let curr = this.items + let last = '' + + for (const p of paths) { + curr = curr.get(p) + last = p + } + const list = Array.from(curr.keys()).filter((e) => e !== 'content') + if (curr.has('content')) list.push(last) + return list.sort() +} + +/** + * @param {string} path + * @return {void} + */ +FileSystem.prototype.mkdir = function (path) { + const paths = path.split('/').filter((p) => !!p.length) + let curr = this.items + for (const p of paths) { + if (!curr.has(p)) { + curr.set(p, new Map()) + } + curr = curr.get(p) + } +} + +/** + * @param {string} filePath + * @param {string} content + * @return {void} + */ +FileSystem.prototype.addContentToFile = function (filePath, content) { + const paths = filePath.split('/').filter((p) => !!p.length) + let curr = this.items + for (const p of paths) { + if (!curr.has(p)) { + curr.set(p, new Map()) + } + curr = curr.get(p) + } + curr.set('content', (curr.get('content') || '') + content) +} + +/** + * @param {string} filePath + * @return {string} + */ +FileSystem.prototype.readContentFromFile = function (filePath) { + const paths = filePath.split('/').filter((p) => !!p.length) + let curr = this.items + for (const p of paths) { + curr = curr.get(p) + } + return curr.get('content') +} + +/** + * Your FileSystem object will be instantiated and called as such: + * var obj = new FileSystem() + * var param_1 = obj.ls(path) + * obj.mkdir(path) + * obj.addContentToFile(filePath,content) + * var param_4 = obj.readContentFromFile(filePath) + */ + diff --git a/589-n-ary-tree-preorder-traversal.js b/589.n-ary-tree-preorder-traversal.js similarity index 100% rename from 589-n-ary-tree-preorder-traversal.js rename to 589.n-ary-tree-preorder-traversal.js diff --git a/59-spiral-matrix-II.js b/59-spiral-matrix-II.js deleted file mode 100755 index a05de8d9..00000000 --- a/59-spiral-matrix-II.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @param {number} n - * @return {number[][]} - */ -const generateMatrix = function(n) { - const res = []; - for (let i = 0; i < n; i++) { - res[i] = []; - } - let i = 0, - j = 0, - cur = 1; - while (n > 0) { - res[i][j] = cur++; - n--; - let step = n; - while (step > 0) { - res[i][++j] = cur++; - step--; - } - step = n; - while (step > 0) { - res[++i][j] = cur++; - step--; - } - step = n--; - while (step > 0) { - res[i][--j] = cur++; - step--; - } - step = n; - while (step > 0) { - res[--i][j] = cur++; - step--; - } - j++; - } - return res; -}; diff --git a/59.spiral-matrix-II.js b/59.spiral-matrix-II.js new file mode 100644 index 00000000..b09ce63d --- /dev/null +++ b/59.spiral-matrix-II.js @@ -0,0 +1,39 @@ +/** + * @param {number} n + * @return {number[][]} + */ +const generateMatrix = function(n) { + const res = []; + for (let i = 0; i < n; i++) { + res[i] = []; + } + let i = 0, + j = 0, + cur = 1; + while (n > 0) { + res[i][j] = cur++; + n--; + let step = n; + while (step > 0) { + res[i][++j] = cur++; + step--; + } + step = n; + while (step > 0) { + res[++i][j] = cur++; + step--; + } + step = n--; + while (step > 0) { + res[i][--j] = cur++; + step--; + } + step = n; + while (step > 0) { + res[--i][j] = cur++; + step--; + } + j++; + } + return res; +}; diff --git a/590-n-ary-tree-postorder-traversal.js b/590.n-ary-tree-postorder-traversal.js similarity index 100% rename from 590-n-ary-tree-postorder-traversal.js rename to 590.n-ary-tree-postorder-traversal.js diff --git a/591-tag-validator.js b/591-tag-validator.js deleted file mode 100644 index ead25315..00000000 --- a/591-tag-validator.js +++ /dev/null @@ -1,205 +0,0 @@ -/** - * @param {string} code - * @return {boolean} - */ -const isValid = function (code) { - const stack = [] - const [A, Z] = ['A', 'Z'].map((e) => e.charCodeAt(0)) - for (let i = 0; i < code.length; ) { - if (i > 0 && stack.length === 0) return false - if (code.startsWith('', j) - if (i < 0) return false - i += 3 - } else if (code.startsWith('', j) - if (i < 0 || i === j || i - j > 9) return false - for (let k = j; k < i; k++) { - if ( - code.charAt(k) !== code[k].toUpperCase() || - !(code.charCodeAt(k) >= A && code.charCodeAt(k) <= Z) - ) - return false - } - let s = code.slice(j, i++) - if (stack.length === 0 || stack.pop() !== s) return false - } else if (code.startsWith('<', i)) { - let j = i + 1 - i = code.indexOf('>', j) - if (i < 0 || i === j || i - j > 9) return false - for (let k = j; k < i; k++) { - if ( - code.charAt(k) !== code[k].toUpperCase() || - !(code.charCodeAt(k) >= A && code.charCodeAt(k) <= Z) - ) - return false - } - let s = code.slice(j, i++) - stack.push(s) - } else { - i++ - } - } - return stack.length === 0 -} - -// another - -/** - * @param {string} code - * @return {boolean} - */ -const isValid = function (code) { - code = code.replace(/|t/g, '-') - let prev - while (code !== prev) { - prev = code - code = code.replace(/<([A-Z]{1,9})>[^<]*<\/\1>/g, 't') - } - return code === 't' -} - - -// another - -/** - * @param {string} code - * @return {boolean} - */ -const isValid = function (code) { - const STATES = { - lt: 1, // < - tagOrData: 2, // uppercase=tag, '!'=data - tagName: 3, // uppercase, '>'=end - dataContent: 4, // any, ']'=wait-for-end - dataEnd: 5, // any, ']'=end - tagContent: 6, // any, '<'=tag-or-data - } - class Validator { - constructor(str) { - this.state = STATES.lt - this.str = str - this.stack = [] - this.i = 0 - // this ensure it doesnt start with cdata - this.isValid = this.isUpperCase(this.str[1]) - // check through code - while (this.isValid && this.i < this.str.length) { - this.isValid = this.validate() - } - // check if there is unclosed tags - this.isValid = this.isValid && !this.stack.length - } - - /** - * check and move on - */ - validate() { - let char = this.str[this.i] - switch (this.state) { - // expect '<', only used at start - case STATES.lt: - this.i++ - if (char == '<') { - this.state = STATES.tagOrData - return true - } - return false - // expect (end-)tag-name or cdata - case STATES.tagOrData: - // data - if (char == '!') { - this.i = this.findStrEnd(this.i + 1, '[CDATA[') - if (this.i == -1) { - return false - } - this.state = STATES.dataContent - return true - } - // end tag - if (char == '/') { - let name = this.stack.pop() - if (!name) { - return false - } - this.i = this.findStrEnd(this.i + 1, name + '>') - if (this.i == -1) { - return false - } - if (!this.stack.length & (this.i < this.str.length)) { - // more than one top level tags - return false - } - this.state = STATES.tagContent - return true - } - // tag name - { - let name = this.findTagName(this.i) - if (!name) { - return false - } - if (name.length > 9) { - return false - } - this.i += name.length + 1 - this.stack.push(name) - this.state = STATES.tagContent - return true - } - case STATES.dataContent: // you can try replace these code with indexOf - { - let end = this.findStrEnd(this.i, ']]>') - if (end != -1) { - // found end - this.i = end - this.state = STATES.tagContent - return true - } - // not yet - this.i++ - return true - } - case STATES.tagContent: - if (char == '<') { - this.state = STATES.tagOrData - this.i++ - return true - } - this.i++ - return true - } - } - - isUpperCase(char) { - return /[A-Z]/.test(char) - } - - findStrEnd(from, toFind = '') { - let end = from + toFind.length - for (let i = 0; i < toFind.length; i++) { - if (toFind[i] != this.str[i + from]) return -1 - } - return end - } - - findTagName(from) { - let tagName = '' - for (let i = from; i < this.str.length; i++) { - if (this.isUpperCase(this.str[i])) { - tagName += this.str[i] - continue - } - if (this.str[i] == '>') { - return tagName - } - return '' - } - return '' - } - } - let v = new Validator(code) - return v.isValid -} diff --git a/591.tag-validator.js b/591.tag-validator.js new file mode 100644 index 00000000..3d6d514a --- /dev/null +++ b/591.tag-validator.js @@ -0,0 +1,47 @@ +/** + * @param {string} code + * @return {boolean} + */ +const isValid = function (code) { + const stack = [] + const [A, Z] = ['A', 'Z'].map((e) => e.charCodeAt(0)) + for (let i = 0; i < code.length; ) { + if (i > 0 && stack.length === 0) return false + if (code.startsWith('', j) + if (i < 0) return false + i += 3 + } else if (code.startsWith('', j) + if (i < 0 || i === j || i - j > 9) return false + for (let k = j; k < i; k++) { + if ( + code.charAt(k) !== code[k].toUpperCase() || + !(code.charCodeAt(k) >= A && code.charCodeAt(k) <= Z) + ) + return false + } + let s = code.slice(j, i++) + if (stack.length === 0 || stack.pop() !== s) return false + } else if (code.startsWith('<', i)) { + let j = i + 1 + i = code.indexOf('>', j) + if (i < 0 || i === j || i - j > 9) return false + for (let k = j; k < i; k++) { + if ( + code.charAt(k) !== code[k].toUpperCase() || + !(code.charCodeAt(k) >= A && code.charCodeAt(k) <= Z) + ) + return false + } + let s = code.slice(j, i++) + stack.push(s) + } else { + i++ + } + } + return stack.length === 0 +} + diff --git a/592-fraction-addition-and-subtraction.js b/592.fraction-addition-and-subtraction.js similarity index 100% rename from 592-fraction-addition-and-subtraction.js rename to 592.fraction-addition-and-subtraction.js diff --git a/593-valid-square.js b/593.valid-square.js similarity index 100% rename from 593-valid-square.js rename to 593.valid-square.js diff --git a/594-longest-harmonious-subsequence.js b/594.longest-harmonious-subsequence.js similarity index 100% rename from 594-longest-harmonious-subsequence.js rename to 594.longest-harmonious-subsequence.js diff --git a/5956-find-first-palindromic-string-in-the-array.js b/5956.find-first-palindromic-string-in-the-array.js similarity index 100% rename from 5956-find-first-palindromic-string-in-the-array.js rename to 5956.find-first-palindromic-string-in-the-array.js diff --git a/5957-adding-spaces-to-a-string.js b/5957.adding-spaces-to-a-string.js similarity index 100% rename from 5957-adding-spaces-to-a-string.js rename to 5957.adding-spaces-to-a-string.js diff --git a/5958-number-of-smooth-descent-periods-of-a-stock.js b/5958.number-of-smooth-descent-periods-of-a-stock.js similarity index 100% rename from 5958-number-of-smooth-descent-periods-of-a-stock.js rename to 5958.number-of-smooth-descent-periods-of-a-stock.js diff --git a/5976-check-if-every-row-and-column-contains-all-numbers.js b/5976.check-if-every-row-and-column-contains-all-numbers.js similarity index 100% rename from 5976-check-if-every-row-and-column-contains-all-numbers.js rename to 5976.check-if-every-row-and-column-contains-all-numbers.js diff --git a/5977-minimum-swaps-to-group-all-1s-together-ii.js b/5977.minimum-swaps-to-group-all-1s-together-ii.js similarity index 100% rename from 5977-minimum-swaps-to-group-all-1s-together-ii.js rename to 5977.minimum-swaps-to-group-all-1s-together-ii.js diff --git a/5978-count-words-obtained-after-adding-a-letter.js b/5978.count-words-obtained-after-adding-a-letter.js similarity index 100% rename from 5978-count-words-obtained-after-adding-a-letter.js rename to 5978.count-words-obtained-after-adding-a-letter.js diff --git a/598-range-addition-ii.js b/598.range-addition-ii.js similarity index 100% rename from 598-range-addition-ii.js rename to 598.range-addition-ii.js diff --git a/599-minimum-index-sum-of-two-lists.js b/599-minimum-index-sum-of-two-lists.js deleted file mode 100755 index 6102fba8..00000000 --- a/599-minimum-index-sum-of-two-lists.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @param {string[]} list1 - * @param {string[]} list2 - * @return {string[]} - */ -const findRestaurant = function(list1, list2) { - const hash = {}; - for (let i = 0; i < list1.length; i++) { - if (!hash.hasOwnProperty(list1[i])) { - hash[list1[i]] = i; - } - } - const resArr = []; - for (let j = 0; j < list2.length; j++) { - if (hash.hasOwnProperty(list2[j])) { - resArr.push([list2[j], hash[list2[j]] + j]); - } - } - const resHash = {}; - resArr.forEach(el => { - if (resHash.hasOwnProperty(el[1])) { - resHash[el[1]].push(el[0]); - } else { - resHash[el[1]] = [el[0]]; - } - }); - resArr.sort((a, b) => a[1] - b[1]); - return resHash[resArr[0][1]]; -}; - -console.log( - findRestaurant( - ["Shogun", "Tapioca Express", "Burger King", "KFC"], - ["KFC", "Burger King", "Tapioca Express", "Shogun"] - ) -); diff --git a/599.minimum-index-sum-of-two-lists.js b/599.minimum-index-sum-of-two-lists.js new file mode 100644 index 00000000..b4fbb647 --- /dev/null +++ b/599.minimum-index-sum-of-two-lists.js @@ -0,0 +1,36 @@ +/** + * @param {string[]} list1 + * @param {string[]} list2 + * @return {string[]} + */ +const findRestaurant = function(list1, list2) { + const hash = {}; + for (let i = 0; i < list1.length; i++) { + if (!hash.hasOwnProperty(list1[i])) { + hash[list1[i]] = i; + } + } + const resArr = []; + for (let j = 0; j < list2.length; j++) { + if (hash.hasOwnProperty(list2[j])) { + resArr.push([list2[j], hash[list2[j]] + j]); + } + } + const resHash = {}; + resArr.forEach(el => { + if (resHash.hasOwnProperty(el[1])) { + resHash[el[1]].push(el[0]); + } else { + resHash[el[1]] = [el[0]]; + } + }); + resArr.sort((a, b) => a[1] - b[1]); + return resHash[resArr[0][1]]; +}; + +console.log( + findRestaurant( + ["Shogun", "Tapioca Express", "Burger King", "KFC"], + ["KFC", "Burger King", "Tapioca Express", "Shogun"] + ) +); diff --git a/6-zigzag-conversion.js b/6-zigzag-conversion.js deleted file mode 100755 index 5b6a3881..00000000 --- a/6-zigzag-conversion.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @param {string} s - * @param {number} numRows - * @return {string} - */ -const convert = function(s, numRows) { - if (numRows === 1) { - return s; - } - let output = ""; - for (let i = 1; i <= numRows; i++) { - let j = i - 1; - let maxIncrement = 2 * numRows - 2; - let increment = 2 * numRows - 2 - 2 * j; - if (increment === 0) { - increment = maxIncrement; - } else { - increment = maxIncrement - increment; - } - for (j; j < s.length; j += increment) { - output += s[j]; - if (maxIncrement !== increment) { - increment = maxIncrement - increment; - } - } - } - return output; -}; diff --git a/6.zigzag-conversion.js b/6.zigzag-conversion.js new file mode 100644 index 00000000..6c17c397 --- /dev/null +++ b/6.zigzag-conversion.js @@ -0,0 +1,28 @@ +/** + * @param {string} s + * @param {number} numRows + * @return {string} + */ +const convert = function(s, numRows) { + if (numRows === 1) { + return s; + } + let output = ""; + for (let i = 1; i <= numRows; i++) { + let j = i - 1; + let maxIncrement = 2 * numRows - 2; + let increment = 2 * numRows - 2 - 2 * j; + if (increment === 0) { + increment = maxIncrement; + } else { + increment = maxIncrement - increment; + } + for (j; j < s.length; j += increment) { + output += s[j]; + if (maxIncrement !== increment) { + increment = maxIncrement - increment; + } + } + } + return output; +}; diff --git a/60-permutation-sequence.js b/60-permutation-sequence.js deleted file mode 100644 index ea812807..00000000 --- a/60-permutation-sequence.js +++ /dev/null @@ -1,145 +0,0 @@ -/** - * @param {number} n - * @param {number} k - * @return {string} - */ -const getPermutation = function(n, k) { - const factorial = Array(n + 1).fill(0) - factorial[0] = 1 - for(let i = 1; i <= n; i++) { - factorial[i] = factorial[i - 1] * i - } - let res = '' - const visited = Array(n + 1).fill(0) - dfs(0) - return res - - function dfs(idx) { - if(idx === n) return - - const cnt = factorial[n - idx - 1] - for(let i = 1; i <= n; i++) { - if(visited[i]) continue - if(cnt < k) { - k -= cnt - continue - } - res += i - visited[i] = 1 - dfs(idx + 1) - return - } - } -}; - -// another - -/** - * @param {number} n - * @param {number} k - * @return {string} - */ -const getPermutation = function(n, k) { - const factorial = Array(n + 1).fill(0) - factorial[0] = 1 - for(let i = 1, pre = 1; i <= n; i++) { - factorial[i] = pre * i - pre = factorial[i] - } - const nums = Array.from({length: n}, (_, i) => i + 1) - - let res = '' - k-- - for(let i = 1; i <= n; i++) { - const idx = ~~(k / factorial[n - i]) - res += nums[idx] - nums.splice(idx, 1) - k -= idx * factorial[n - i] - } - - return res -}; - -// another - -/** - * @param {number} n - * @param {number} k - * @return {string} - */ -const getPermutation = function(n, k) { - const fact = [] - const nums = [] - for(let i = 1; i <= n; i++) { - nums.push(i) - } - fact[0] = 1 - for(let i = 1, tmp = 1; i <= n; i++) { - tmp *= i - fact[i] = tmp - } - let res = '' - k-- - for(let i = 1; i <= n; i++) { - const idx = ~~(k / fact[n - i]) - res += nums[idx] - nums.splice(idx, 1) - k -= idx * fact[n - i] - } - - return res -}; - -// another - -/** - * @param {number} n - * @param {number} k - * @return {string} - */ -const getPermutation = function (n, k) { - let sb = '' - const num = [] - let fact = 1 - for (let i = 1; i <= n; i++) { - fact *= i - num.push(i) - } - for (let i = 0, l = k - 1; i < n; i++) { - fact = Math.floor(fact / (n - i)) - const index = Math.floor(l / fact) - sb += num.splice(index, 1)[0] - l -= index * fact - } - return sb -} - -// another - -/** - * @param {number} n - * @param {number} k - * @return {string} - */ -const getPermutation = function(n, k) { - const factorial = [] - const nums = [] - let res = '' - factorial[0] = 1 - for(let i = 1, sum = 1; i <= n; i++) { - sum *= i - factorial[i] = sum - } - for(let i = 1; i <= n; i++) { - nums.push(i) - } - k-- - for(let i = 0; i <= n; i++) { - const idx = ~~(k / factorial[n - i]) - res += nums[idx] - nums.splice(idx, 1) - k -= idx * factorial[n - i] - } - - return res -}; diff --git a/60.permutation-sequence.js b/60.permutation-sequence.js new file mode 100644 index 00000000..c38c6fe9 --- /dev/null +++ b/60.permutation-sequence.js @@ -0,0 +1,34 @@ +/** + * @param {number} n + * @param {number} k + * @return {string} + */ +const getPermutation = function(n, k) { + const factorial = Array(n + 1).fill(0) + factorial[0] = 1 + for(let i = 1; i <= n; i++) { + factorial[i] = factorial[i - 1] * i + } + let res = '' + const visited = Array(n + 1).fill(0) + dfs(0) + return res + + function dfs(idx) { + if(idx === n) return + + const cnt = factorial[n - idx - 1] + for(let i = 1; i <= n; i++) { + if(visited[i]) continue + if(cnt < k) { + k -= cnt + continue + } + res += i + visited[i] = 1 + dfs(idx + 1) + return + } + } +}; + diff --git a/600-non-negative-integers-without-consecutive-ones.js b/600.non-negative-integers-without-consecutive-ones.js similarity index 100% rename from 600-non-negative-integers-without-consecutive-ones.js rename to 600.non-negative-integers-without-consecutive-ones.js diff --git a/604-design-compressed-string-iterator.js b/604.design-compressed-string-iterator.js similarity index 100% rename from 604-design-compressed-string-iterator.js rename to 604.design-compressed-string-iterator.js diff --git a/605-can-place-flowers.js b/605.can-place-flowers.js similarity index 100% rename from 605-can-place-flowers.js rename to 605.can-place-flowers.js diff --git a/606-construct-string-from-binary-tree.js b/606.construct-string-from-binary-tree.js similarity index 100% rename from 606-construct-string-from-binary-tree.js rename to 606.construct-string-from-binary-tree.js diff --git a/609-find-duplicate-file-in-system.js b/609.find-duplicate-file-in-system.js similarity index 100% rename from 609-find-duplicate-file-in-system.js rename to 609.find-duplicate-file-in-system.js diff --git a/61-rotate-list.js b/61-rotate-list.js deleted file mode 100644 index 5f97560e..00000000 --- a/61-rotate-list.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @param {number} k - * @return {ListNode} - */ -const rotateRight = function(head, k) { - if (head === null || head.next === null) return head; - const dummy = new ListNode(0); - dummy.next = head; - let fast = dummy,slow = dummy; - - let i; - for (i = 0; fast.next != null; i++)//Get the total length - fast = fast.next; - - for (let j = i - k % i; j > 0; j--) //Get the i-n%i th node - slow = slow.next; - - fast.next = dummy.next; //Do the rotation - dummy.next = slow.next; - slow.next = null; - - return dummy.next; -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @param {number} k - * @return {ListNode} - */ -const rotateRight = function(head, k) { - if(head == null) return null - let len = 1 - let tmp = head - while(tmp.next) { - len++ - tmp = tmp.next - } - k = k % len - if(k === 0) return head - let tail = head - for(let i = 1; i < len - k; i++) { - tail = tail.next - } - const newHead = tail.next - tmp.next = head - tail.next = null - return newHead -}; diff --git a/61.rotate-list.js b/61.rotate-list.js new file mode 100644 index 00000000..65fdc136 --- /dev/null +++ b/61.rotate-list.js @@ -0,0 +1,32 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @param {number} k + * @return {ListNode} + */ +const rotateRight = function(head, k) { + if (head === null || head.next === null) return head; + const dummy = new ListNode(0); + dummy.next = head; + let fast = dummy,slow = dummy; + + let i; + for (i = 0; fast.next != null; i++)//Get the total length + fast = fast.next; + + for (let j = i - k % i; j > 0; j--) //Get the i-n%i th node + slow = slow.next; + + fast.next = dummy.next; //Do the rotation + dummy.next = slow.next; + slow.next = null; + + return dummy.next; +}; + diff --git a/611-valid-triangle-number.js b/611-valid-triangle-number.js deleted file mode 100755 index fa449f85..00000000 --- a/611-valid-triangle-number.js +++ /dev/null @@ -1,24 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const triangleNumber = function(nums) { - nums.sort((a, b) => a - b); - let count = 0; - let n = nums.length; - for (let i = n - 1; i >= 2; i--) { - let lo = 0; - let mid = i - 1; - while (lo < mid) { - if (nums[lo] + nums[mid] > nums[i]) { - count += mid - lo; - mid -= 1; - } else { - lo += 1; - } - } - } - return count; -}; - -console.log(triangleNumber([2, 2, 3, 4])); diff --git a/611.valid-triangle-number.js b/611.valid-triangle-number.js new file mode 100644 index 00000000..52b08d2a --- /dev/null +++ b/611.valid-triangle-number.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const triangleNumber = function(nums) { + nums.sort((a, b) => a - b); + let count = 0; + let n = nums.length; + for (let i = n - 1; i >= 2; i--) { + let lo = 0; + let mid = i - 1; + while (lo < mid) { + if (nums[lo] + nums[mid] > nums[i]) { + count += mid - lo; + mid -= 1; + } else { + lo += 1; + } + } + } + return count; +}; + +console.log(triangleNumber([2, 2, 3, 4])); diff --git a/616-add-bold-tag-in-string.js b/616.add-bold-tag-in-string.js similarity index 100% rename from 616-add-bold-tag-in-string.js rename to 616.add-bold-tag-in-string.js diff --git a/62-unique-paths.js b/62-unique-paths.js deleted file mode 100644 index 6abde1b3..00000000 --- a/62-unique-paths.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @param {number} m - * @param {number} n - * @return {number} - */ -const uniquePaths = function(m, n) { - if(m === 0 || n === 0) return 0 - const dp = Array.from({length: m+1}, () => new Array(n+1).fill(1)) - dp[0][1] = dp[1][0] = 1 - for(let i = 1; i <= m; i++) { - for(let j = 1; j <= n; j++) { - dp[i][j] = dp[i - 1][j] + dp[i][j - 1] - } - } - return dp[m - 1][n - 1] -}; - -// another - -/** - * @param {number} m - * @param {number} n - * @return {number} - */ -const uniquePaths = function(m, n) { - const dp = Array(m).fill(0) - for(let i = 0; i < n; i++) { - dp[0] = 1 - for(let j = 1; j < m; j++) { - dp[j] += dp[j - 1] - } - } - return dp[m - 1] -}; - -// another - -/** - * @param {number} m - * @param {number} n - * @return {number} - */ -const uniquePaths = function(m, n) { - return factorial(m+n-2)/(factorial(m - 1) * factorial(n - 1)) -}; - -function factorial(n) { - let res = 1 - while(n > 0) { - res *= n - n-- - } - return res -} diff --git a/62.unique-paths.js b/62.unique-paths.js new file mode 100644 index 00000000..59e77cdc --- /dev/null +++ b/62.unique-paths.js @@ -0,0 +1,17 @@ +/** + * @param {number} m + * @param {number} n + * @return {number} + */ +const uniquePaths = function(m, n) { + if(m === 0 || n === 0) return 0 + const dp = Array.from({length: m+1}, () => new Array(n+1).fill(1)) + dp[0][1] = dp[1][0] = 1 + for(let i = 1; i <= m; i++) { + for(let j = 1; j <= n; j++) { + dp[i][j] = dp[i - 1][j] + dp[i][j - 1] + } + } + return dp[m - 1][n - 1] +}; + diff --git a/621-task-scheduler.js b/621-task-scheduler.js deleted file mode 100755 index 1c07d12c..00000000 --- a/621-task-scheduler.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * @param {character[]} tasks - * @param {number} n - * @return {number} - */ -const leastInterval = function (tasks, n) { - const len = tasks.length - const cnt = Array(26).fill(0) - - const A = 'A'.charCodeAt(0) - let maxFreq = 0, - maxFreqCnt = 0 - for (const ch of tasks) { - const idx = ch.charCodeAt(0) - A - cnt[idx]++ - if (maxFreq === cnt[idx]) { - maxFreqCnt++ - } else if (maxFreq < cnt[idx]) { - maxFreqCnt = 1 - maxFreq = cnt[idx] - } - } - - const slot = maxFreq - 1 - const numOfPerSlot = n - (maxFreqCnt - 1) - const available = len - maxFreq * maxFreqCnt - const idles = Math.max(0, slot * numOfPerSlot - available) - return len + idles -} - - -// another - -/** - * @param {character[]} tasks - * @param {number} n - * @return {number} - */ -const leastInterval = function(tasks, n) { - const map = Array(26).fill(0); - const ca = "A".charCodeAt(0); - for (let c of tasks) map[c.charCodeAt(0) - ca]++; - map.sort((a, b) => a - b); - let max_val = map[25] - 1, - idle_slots = max_val * n; - for (let i = 24; i >= 0 && map[i] > 0; i--) { - idle_slots -= Math.min(map[i], max_val); - } - return idle_slots > 0 ? idle_slots + tasks.length : tasks.length; -}; - -// another - -/** - * @param {character[]} tasks - * @param {number} n - * @return {number} - */ -const leastInterval = function(tasks, n) { - const hash = {}; - for(let task of tasks) { - hash[task] = hash[task] + 1 || 1 - } - let max = 0, count = 0; - for(let el in hash) { - if(hash[el] > max) { - max = hash[el]; - count = 1 - } else if(hash[el] === max) { - count++; - } - } - return Math.max((max - 1) * (n + 1) + count, tasks.length) -}; - -// another - -/** - * @param {character[]} tasks - * @param {number} n - * @return {number} - */ -const leastInterval = function(tasks, n) { - let max = 0, maxCnt = 0 - const len = tasks.length, cnt = Array(26).fill(0), A = 'A'.charCodeAt(0) - - for(let ch of tasks) { - const idx = ch.charCodeAt(0) - A - cnt[idx]++ - if(max === cnt[idx]) maxCnt++ - else if(max < cnt[idx]) { - max = cnt[idx] - maxCnt = 1 - } - } - - const maxSlots = max * maxCnt - const avaiSlots = (max - 1) * (n - (maxCnt - 1)) - const rem = len - maxSlots - const emptySlots = Math.max(0, avaiSlots - rem) - - return len + emptySlots -}; diff --git a/621.task-scheduler.js b/621.task-scheduler.js new file mode 100644 index 00000000..eac1fb6b --- /dev/null +++ b/621.task-scheduler.js @@ -0,0 +1,31 @@ +/** + * @param {character[]} tasks + * @param {number} n + * @return {number} + */ +const leastInterval = function (tasks, n) { + const len = tasks.length + const cnt = Array(26).fill(0) + + const A = 'A'.charCodeAt(0) + let maxFreq = 0, + maxFreqCnt = 0 + for (const ch of tasks) { + const idx = ch.charCodeAt(0) - A + cnt[idx]++ + if (maxFreq === cnt[idx]) { + maxFreqCnt++ + } else if (maxFreq < cnt[idx]) { + maxFreqCnt = 1 + maxFreq = cnt[idx] + } + } + + const slot = maxFreq - 1 + const numOfPerSlot = n - (maxFreqCnt - 1) + const available = len - maxFreq * maxFreqCnt + const idles = Math.max(0, slot * numOfPerSlot - available) + return len + idles +} + + diff --git a/622-design-circular-queue.js b/622.design-circular-queue.js similarity index 100% rename from 622-design-circular-queue.js rename to 622.design-circular-queue.js diff --git a/623-add-one-row-to-tree.js b/623-add-one-row-to-tree.js deleted file mode 100644 index 1ce663de..00000000 --- a/623-add-one-row-to-tree.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {number} v - * @param {number} d - * @return {TreeNode} - */ -const addOneRow = function (root, v, d, level = 1) { - if (d === 1) { - const node = new TreeNode(v) - node.left = root - return node - } - const queue = [] - queue.push(root) - let depth = 1 - while (queue.length) { - const size = queue.length - for (let i = 0; i < size; i++) { - const cur = queue.shift() - if (depth === d - 1) { - let left = new TreeNode(v) - let right = new TreeNode(v) - left.left = cur.left - right.right = cur.right - cur.left = left - cur.right = right - } else { - if (cur.left !== null) { - queue.push(cur.left) - } - if (cur.right !== null) { - queue.push(cur.right) - } - } - } - depth++ - } - return root -} - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {number} v - * @param {number} d - * @return {TreeNode} - */ -const addOneRow = function (root, v, d, level = 1) { - if (!root) return - if (d === 1) { - const newRoot = new TreeNode(v) - newRoot.left = root - return newRoot - } else if (d === level + 1) { - const oldLeft = root.left - const oldRight = root.right - root.left = new TreeNode(v) - root.right = new TreeNode(v) - root.left.left = oldLeft - root.right.right = oldRight - } else { - addOneRow(root.left, v, d, level + 1) - addOneRow(root.right, v, d, level + 1) - } - return root -} diff --git a/623.add-one-row-to-tree.js b/623.add-one-row-to-tree.js new file mode 100644 index 00000000..645d231e --- /dev/null +++ b/623.add-one-row-to-tree.js @@ -0,0 +1,47 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {number} v + * @param {number} d + * @return {TreeNode} + */ +const addOneRow = function (root, v, d, level = 1) { + if (d === 1) { + const node = new TreeNode(v) + node.left = root + return node + } + const queue = [] + queue.push(root) + let depth = 1 + while (queue.length) { + const size = queue.length + for (let i = 0; i < size; i++) { + const cur = queue.shift() + if (depth === d - 1) { + let left = new TreeNode(v) + let right = new TreeNode(v) + left.left = cur.left + right.right = cur.right + cur.left = left + cur.right = right + } else { + if (cur.left !== null) { + queue.push(cur.left) + } + if (cur.right !== null) { + queue.push(cur.right) + } + } + } + depth++ + } + return root +} + diff --git a/624-maximum-distance-in-arrays.js b/624.maximum-distance-in-arrays.js similarity index 100% rename from 624-maximum-distance-in-arrays.js rename to 624.maximum-distance-in-arrays.js diff --git a/625-minimum-factorization.js b/625.minimum-factorization.js similarity index 100% rename from 625-minimum-factorization.js rename to 625.minimum-factorization.js diff --git a/628-maximum-product-of-three-numbers.js b/628-maximum-product-of-three-numbers.js deleted file mode 100644 index d801ee9f..00000000 --- a/628-maximum-product-of-three-numbers.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const maximumProduct = function (nums) { - nums.sort((a, b) => a - b) - return Math.max( - nums[0] * nums[1] * nums[nums.length - 1], - nums[nums.length - 1] * nums[nums.length - 2] * nums[nums.length - 3] - ) -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const maximumProduct = function (nums) { - let max1 = -Infinity - let max2 = -Infinity - let max3 = -Infinity - let min1 = Infinity - let min2 = Infinity - for (let num of nums) { - if (num > max1) { - max3 = max2 - max2 = max1 - max1 = num - } else if (num > max2) { - max3 = max2 - max2 = num - } else if (num > max3) { - max3 = num - } - - if (num < min1) { - min2 = min1 - min1 = num - } else if (num < min2) { - min2 = num - } - } - return Math.max(max1 * max2 * max3, max1 * min1 * min2) -} diff --git a/628.maximum-product-of-three-numbers.js b/628.maximum-product-of-three-numbers.js new file mode 100644 index 00000000..1a188af8 --- /dev/null +++ b/628.maximum-product-of-three-numbers.js @@ -0,0 +1,12 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const maximumProduct = function (nums) { + nums.sort((a, b) => a - b) + return Math.max( + nums[0] * nums[1] * nums[nums.length - 1], + nums[nums.length - 1] * nums[nums.length - 2] * nums[nums.length - 3] + ) +} + diff --git a/629-k-inverse-pairs-array.js b/629.k-inverse-pairs-array.js similarity index 100% rename from 629-k-inverse-pairs-array.js rename to 629.k-inverse-pairs-array.js diff --git a/63-unique-paths-ii.js b/63.unique-paths-ii.js similarity index 100% rename from 63-unique-paths-ii.js rename to 63.unique-paths-ii.js diff --git a/630-course-schedule-iii.js b/630-course-schedule-iii.js deleted file mode 100644 index b2f0f289..00000000 --- a/630-course-schedule-iii.js +++ /dev/null @@ -1,252 +0,0 @@ -/** - * @param {number[][]} courses - * @return {number} - */ -const scheduleCourse = function (courses) { - const compare = (a, b) => a[0] === b[0] ? 0 : (a[0] > b[0] ? -1 : 1) - const queue = new PriorityQueue({ compare }) - courses.sort((a, b) => a[1] - b[1]) - let time = 0 - for(let e of courses) { - time += e[0] - queue.enqueue(e) - if(time > e[1]) { - const tmp = queue.dequeue() - time -= tmp[0] - } - } - return queue.size() -} - -// another - -/** - * @param {number[][]} courses - * @return {number} - */ -const scheduleCourse = function(courses) { - const pq = new PQ((a, b) => a[0] === b[0] ? a[1] < b[1] : a[0] > b[0]) - const n = courses.length - courses.sort((a, b) => a[1] === b[1] ? a[0] - b[0] : a[1] - b[1]) - - let time = 0 - for(const e of courses) { - const [dur, end] = e - time += dur - pq.push(e) - if(time > end) { - const tmp = pq.pop() - time -= tmp[0] - } - } - - return pq.size() -}; - -class PQ { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - - -/** - * @param {number[][]} courses - * @return {number} - */ -const scheduleCourse = function (courses) { - const queue = new MaxPriorityQueue({ - priority: e => e[0] - }) - courses.sort((a, b) => a[1] - b[1]) - let time = 0 - for(let e of courses) { - time += e[0] - queue.enqueue(e) - if(time > e[1]) { - const tmp = queue.dequeue().element - time -= tmp[0] - } - } - return queue.size() -} - -// another - -/** - * @param {number[][]} courses - * @return {number} - */ -const scheduleCourse = function (courses) { - courses.sort((c1, c2) => c1[1] - c2[1]) - let count = 0 - let time = 0 - const queue = [] - const inQueue = (val) => { - let i = 0 - while (i < queue.length && queue[i] > val) i += 1 - queue.splice(i, 0, val) - } - for (let i = 0; i < courses.length; i += 1) { - const [dur, end] = courses[i] - if (time <= end - dur) { - count += 1 - time += dur - inQueue(dur) - } else if (queue.length && queue[0] > dur) { - time = time - queue.shift() + dur - inQueue(dur) - } - } - return count -} - -// another - -/** - * @param {number[][]} courses - * @return {number} - */ -const scheduleCourse = function (courses) { - courses.sort((a, b) => +a[1] - +b[1]) - let queue = new Heap() - let time = 0 - for (let c of courses) { - if (c[0] + time <= c[1]) { - time += c[0] - queue.push(c[0]) - } else if (queue.size() > 0) { - let top = queue.peek() - if (top > c[0]) { - queue.pop() - queue.push(c[0]) - time += c[0] - top - } - } - } - return queue.size() -} - -const parent = (i) => Math.floor((i - 1) / 2) -const left = (i) => 2 * i + 1 -const right = (i) => 2 * i + 2 -class Heap { - constructor() { - this.compare = (a, b) => +b - +a - this._heap = [] - } - size() { - return this._heap.length - } - _upper(i, j) { - return this.compare(this._heap[i], this._heap[j]) < 0 - } - _swap(i, j) { - let tmp = this._heap[i] - this._heap[i] = this._heap[j] - this._heap[j] = tmp - } - push(item) { - this._heap.push(item) - this._siftUp() - return this.size() - } - _siftUp() { - let node = this._heap.length - 1 - while (node > 0 && this._upper(node, parent(node))) { - this._swap(node, parent(node)) - node = parent(node) - } - } - peek() { - return this._heap[0] - } - pop() { - let ret = this._heap[0] - if (this.size() > 1) { - this._swap(0, this._heap.length - 1) - } - this._heap.pop() - this._siftDown() - return ret - } - _siftDown() { - let node = 0 - while ( - (right(node) < this.size() && this._upper(right(node), node)) || - (left(node) < this.size() && this._upper(left(node), node)) - ) { - let upperChild = - right(node) < this.size() && this._upper(right(node), left(node)) - ? right(node) - : left(node) - this._swap(upperChild, node) - node = upperChild - } - } -} - diff --git a/630.course-schedule-iii.js b/630.course-schedule-iii.js new file mode 100644 index 00000000..f567b543 --- /dev/null +++ b/630.course-schedule-iii.js @@ -0,0 +1,20 @@ +/** + * @param {number[][]} courses + * @return {number} + */ +const scheduleCourse = function (courses) { + const compare = (a, b) => a[0] === b[0] ? 0 : (a[0] > b[0] ? -1 : 1) + const queue = new PriorityQueue({ compare }) + courses.sort((a, b) => a[1] - b[1]) + let time = 0 + for(let e of courses) { + time += e[0] + queue.enqueue(e) + if(time > e[1]) { + const tmp = queue.dequeue() + time -= tmp[0] + } + } + return queue.size() +} + diff --git a/631-design-excel-sum-formula.js b/631-design-excel-sum-formula.js deleted file mode 100644 index ad7db1f9..00000000 --- a/631-design-excel-sum-formula.js +++ /dev/null @@ -1,169 +0,0 @@ -/** - * @param {number} H - * @param {character} W - */ -const Excel = function (H, W) { - this.W = W.charCodeAt(0) - 'A'.charCodeAt(0) + 1 - this.H = H - this.map = {} - this.mat = [] - for (let i = 0; i < this.H; i++) { - this.mat[i] = new Array(this.W).fill(0) - } - return -} - -/** - * @param {number} r - * @param {character} c - * @param {number} v - * @return {void} - */ -Excel.prototype.set = function (r, c, v) { - let row = r - 1 - let col = c.charCodeAt(0) - 'A'.charCodeAt(0) - if (this.map[r + ':' + c]) delete this.map[r + ':' + c] - this.mat[row][col] = v -} -/** - * @param {number} r - * @param {character} c - * @return {number} - */ -Excel.prototype.get = function (r, c) { - let row = r - 1 - let col = c.charCodeAt(0) - 'A'.charCodeAt(0) - if (this.map[r + ':' + c] !== undefined) - return this.sum(r, c, this.map[r + ':' + c]) - return this.mat[row][col] -} - -/** - * @param {number} r - * @param {character} c - * @param {string[]} strs - * @return {number} - */ -Excel.prototype.sum = function (r, c, strs) { - let sum = 0 - for (let str of strs) { - if (str.indexOf(':') < 0) { - sum += this.get(+str.substring(1), str[0]) - } else { - let [r1, c1, r2, c2] = this.getRange(str.split(':')) - for (let i = r1; i <= r2; i++) { - for (let j = c1; j <= c2; j++) { - sum += this.get(i + 1, String.fromCharCode(j + 'A'.charCodeAt(0))) - } - } - } - } - this.map[r + ':' + c] = strs - return sum -} - -Excel.prototype.getRange = function (arr) { - let p1 = arr[0], - p2 = arr[1] - let c1 = p1[0].charCodeAt(0) - 'A'.charCodeAt(0) - let r1 = +p1.substring(1) - 1 - let c2 = p2[0].charCodeAt(0) - 'A'.charCodeAt(0) - let r2 = +p2.substring(1) - 1 - return [r1, c1, r2, c2] -} - -/** - * Your Excel object will be instantiated and called as such: - * var obj = Object.create(Excel).createNew(H, W) - * obj.set(r,c,v) - * var param_2 = obj.get(r,c) - * var param_3 = obj.sum(r,c,strs) - */ - - -// another - -/** - * @param {number} H - * @param {character} W - */ -const Excel = function (H, W) { - this.data = [] - for (let i = 1; i <= H; i++) { - this.data[i] = [] - for (let j = 1; j <= this.col(W); j++) { - this.data[i][j] = 0 - } - } -} - -Excel.prototype.col = function (c) { - return c.charCodeAt() - 'A'.charCodeAt() + 1 -} - -Excel.prototype.parse = function (str) { - let idx = str.indexOf(':') - if (idx === -1) return { r: Number(str.slice(1)), c: str[0] } - let topLeft = str.slice(0, idx), - bottomRight = str.slice(idx + 1) - return [ - { r: Number(topLeft.slice(1)), c: topLeft[0] }, - { r: Number(bottomRight.slice(1)), c: bottomRight[0] }, - ] -} - -/** - * @param {number} r - * @param {character} c - * @param {number} v - * @return {void} - */ -Excel.prototype.set = function (r, c, v) { - this.data[r][this.col(c)] = v -} - -/** - * @param {number} r - * @param {character} c - * @return {number} - */ -Excel.prototype.get = function (r, c) { - if (Array.isArray(this.data[r][this.col(c)])) { - let sum = 0 - for (let str of this.data[r][this.col(c)]) { - let parsed = this.parse(str) - if (Array.isArray(parsed)) { - for (let i = parsed[0].r; i <= parsed[1].r; i++) { - for ( - let jc = parsed[0].c; - jc <= parsed[1].c; - jc = String.fromCharCode(jc.charCodeAt() + 1) - ) { - sum += this.get(i, jc) - } - } - } else sum += this.get(parsed.r, parsed.c) - } - return sum - } - return this.data[r][this.col(c)] -} - -/** - * @param {number} r - * @param {character} c - * @param {string[]} strs - * @return {number} - */ -Excel.prototype.sum = function (r, c, strs) { - this.set(r, c, strs) - return this.get(r, c) -} - -/** - * Your Excel object will be instantiated and called as such: - * var obj = new Excel(H, W) - * obj.set(r,c,v) - * var param_2 = obj.get(r,c) - * var param_3 = obj.sum(r,c,strs) - */ diff --git a/631.design-excel-sum-formula.js b/631.design-excel-sum-formula.js new file mode 100644 index 00000000..c7908e46 --- /dev/null +++ b/631.design-excel-sum-formula.js @@ -0,0 +1,83 @@ +/** + * @param {number} H + * @param {character} W + */ +const Excel = function (H, W) { + this.W = W.charCodeAt(0) - 'A'.charCodeAt(0) + 1 + this.H = H + this.map = {} + this.mat = [] + for (let i = 0; i < this.H; i++) { + this.mat[i] = new Array(this.W).fill(0) + } + return +} + +/** + * @param {number} r + * @param {character} c + * @param {number} v + * @return {void} + */ +Excel.prototype.set = function (r, c, v) { + let row = r - 1 + let col = c.charCodeAt(0) - 'A'.charCodeAt(0) + if (this.map[r + ':' + c]) delete this.map[r + ':' + c] + this.mat[row][col] = v +} +/** + * @param {number} r + * @param {character} c + * @return {number} + */ +Excel.prototype.get = function (r, c) { + let row = r - 1 + let col = c.charCodeAt(0) - 'A'.charCodeAt(0) + if (this.map[r + ':' + c] !== undefined) + return this.sum(r, c, this.map[r + ':' + c]) + return this.mat[row][col] +} + +/** + * @param {number} r + * @param {character} c + * @param {string[]} strs + * @return {number} + */ +Excel.prototype.sum = function (r, c, strs) { + let sum = 0 + for (let str of strs) { + if (str.indexOf(':') < 0) { + sum += this.get(+str.substring(1), str[0]) + } else { + let [r1, c1, r2, c2] = this.getRange(str.split(':')) + for (let i = r1; i <= r2; i++) { + for (let j = c1; j <= c2; j++) { + sum += this.get(i + 1, String.fromCharCode(j + 'A'.charCodeAt(0))) + } + } + } + } + this.map[r + ':' + c] = strs + return sum +} + +Excel.prototype.getRange = function (arr) { + let p1 = arr[0], + p2 = arr[1] + let c1 = p1[0].charCodeAt(0) - 'A'.charCodeAt(0) + let r1 = +p1.substring(1) - 1 + let c2 = p2[0].charCodeAt(0) - 'A'.charCodeAt(0) + let r2 = +p2.substring(1) - 1 + return [r1, c1, r2, c2] +} + +/** + * Your Excel object will be instantiated and called as such: + * var obj = Object.create(Excel).createNew(H, W) + * obj.set(r,c,v) + * var param_2 = obj.get(r,c) + * var param_3 = obj.sum(r,c,strs) + */ + + diff --git a/632-smallest-range.js b/632-smallest-range.js deleted file mode 100644 index 16153b17..00000000 --- a/632-smallest-range.js +++ /dev/null @@ -1,282 +0,0 @@ -/** - * @param {number[][]} nums - * @return {number[]} - */ -const smallestRange = function(nums) { - if (nums.length === 1) return [nums[0], nums[0]] - const pq = new PQ((a, b) => a.v < b.v) - let min = Number.MAX_SAFE_INTEGER - let max = Number.MIN_SAFE_INTEGER - for (let i = 0; i < nums.length; i++) { - if (nums[i].length > 0) { - const top = nums[i].shift() - pq.push({ v: top, i }) - min = Math.min(min, top) - max = Math.max(max, top) - } - } - let bestRange = [min, max] - while (pq.size() > 0) { - const { v, i } = pq.pop() - if (nums[i].length === 0) return bestRange - const newVal = nums[i].shift() - pq.push({ v: newVal, i }) - min = pq.peek().v - max = Math.max(max, newVal) - if (max - min < bestRange[1] - bestRange[0]) { - bestRange = [min, max] - } - } - return bestRange -} - -function PQ(f) { - this.q = [] - this.f = f -} - -PQ.prototype.size = function() { - return this.q.length -} - -PQ.prototype.peek = function() { - return this.q[0] -} - -PQ.prototype.push = function(v) { - const q = this.q - let i = q.length - q.push(v) - let parent = Math.floor((i - 1) / 2) - while (parent >= 0 && this.f(q[i], q[parent])) { - this.swap(i, parent) - i = parent - parent = Math.floor((i - 1) / 2) - } -} - -PQ.prototype.pop = function() { - const q = this.q - if (q.length === 0) return null - this.swap(0, q.length - 1) - let i = 0 - let lc = 1 - let rc = 2 - while (lc < q.length - 1) { - let r = i - if (this.f(q[lc], q[r])) { - r = lc - } - if (rc < q.length - 1 && this.f(q[rc], q[r])) { - r = rc - } - if (r === i) break - this.swap(i, r) - i = r - lc = i * 2 + 1 - rc = i * 2 + 2 - } - return q.pop() -} - -PQ.prototype.swap = function(i, j) { - const q = this.q - const t = q[i] - q[i] = q[j] - q[j] = t -} - -// another - -function Queue() { - this.data = [] -} - -Queue.prototype.pop = function() { - return this.data.shift() -} - -Queue.prototype.getMax = function() { - let n = this.data.length - 1 - let max = this.data[n] - if (max === undefined) { - return 100000000 - } - return max.val -} - -Queue.prototype.getMin = function() { - let min = this.data[0] - if (min === undefined) { - return -100000000 - } - return min.val -} - -Queue.prototype.add = function(node) { - if (!this.data.length) { - this.data.push(node) - return - } - - let index = findIndex(this.data, node) - this.data.splice(index, 0, node) - return true - - function findIndex(arr, node) { - let left = 0 - let right = arr.length - 1 - while (left <= right) { - let mid = Math.floor((left + right) / 2) - if (arr[mid].val === node.val) { - return mid - } - - if (arr[mid].val > node.val) { - right = mid - 1 - } else { - left = mid + 1 - } - } - return left - } -} - -function Node(list, val, index) { - this.list = list - this.val = val - this.index = index -} -/** - * @param {number[][]} nums - * @return {number[]} - */ -var smallestRange = function(nums) { - let queue = new Queue() - for (let i = 0; i < nums.length; i++) { - let node = new Node(i, nums[i][0], 0) - queue.add(node) - } - - let a = Math.min(queue.getMin(), queue.getMax()) - let b = Math.max(queue.getMin(), queue.getMax()) - let ans = [a, b] - let min = ans[1] - ans[0] - for (;;) { - let a = Math.min(queue.getMin(), queue.getMax()) - let b = Math.max(queue.getMin(), queue.getMax()) - if (b - a < min) { - min = b - a - ans = [a, b] - } - - let m = queue.pop() - let list = nums[m.list] - let index = m.index - if (index + 1 < list.length) { - m.index++ - m.val = list[m.index] - queue.add(m) - } else { - break - } - } - - return ans -} - - -// another - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} -/** - * @param {number[][]} nums - * @return {number[]} - */ -const smallestRange = function (nums) { - const pq = new PriorityQueue((a, b) => a[0] < b[0]) - const limit = 10 ** 5, - n = nums.length, - { max } = Math - let right = -1e5, - res = [-limit, limit] - for (let i = 0; i < n; i++) { - pq.push([nums[i][0], i, 0]) - right = max(right, nums[i][0]) - } - while (pq.size()) { - const cur = pq.pop() - const [left, list, indice] = cur - if (right - left < res[1] - res[0]) res = [left, right] - if (indice + 1 === nums[list].length) return res - right = max(right, nums[list][indice + 1]) - pq.push([nums[list][indice + 1], list, indice + 1]) - } - return [] -} diff --git a/632.smallest-range.js b/632.smallest-range.js new file mode 100644 index 00000000..c198610e --- /dev/null +++ b/632.smallest-range.js @@ -0,0 +1,88 @@ +/** + * @param {number[][]} nums + * @return {number[]} + */ +const smallestRange = function(nums) { + if (nums.length === 1) return [nums[0], nums[0]] + const pq = new PQ((a, b) => a.v < b.v) + let min = Number.MAX_SAFE_INTEGER + let max = Number.MIN_SAFE_INTEGER + for (let i = 0; i < nums.length; i++) { + if (nums[i].length > 0) { + const top = nums[i].shift() + pq.push({ v: top, i }) + min = Math.min(min, top) + max = Math.max(max, top) + } + } + let bestRange = [min, max] + while (pq.size() > 0) { + const { v, i } = pq.pop() + if (nums[i].length === 0) return bestRange + const newVal = nums[i].shift() + pq.push({ v: newVal, i }) + min = pq.peek().v + max = Math.max(max, newVal) + if (max - min < bestRange[1] - bestRange[0]) { + bestRange = [min, max] + } + } + return bestRange +} + +function PQ(f) { + this.q = [] + this.f = f +} + +PQ.prototype.size = function() { + return this.q.length +} + +PQ.prototype.peek = function() { + return this.q[0] +} + +PQ.prototype.push = function(v) { + const q = this.q + let i = q.length + q.push(v) + let parent = Math.floor((i - 1) / 2) + while (parent >= 0 && this.f(q[i], q[parent])) { + this.swap(i, parent) + i = parent + parent = Math.floor((i - 1) / 2) + } +} + +PQ.prototype.pop = function() { + const q = this.q + if (q.length === 0) return null + this.swap(0, q.length - 1) + let i = 0 + let lc = 1 + let rc = 2 + while (lc < q.length - 1) { + let r = i + if (this.f(q[lc], q[r])) { + r = lc + } + if (rc < q.length - 1 && this.f(q[rc], q[r])) { + r = rc + } + if (r === i) break + this.swap(i, r) + i = r + lc = i * 2 + 1 + rc = i * 2 + 2 + } + return q.pop() +} + +PQ.prototype.swap = function(i, j) { + const q = this.q + const t = q[i] + q[i] = q[j] + q[j] = t +} + diff --git a/633-sum-of-square-numbers.js b/633.sum-of-square-numbers.js similarity index 100% rename from 633-sum-of-square-numbers.js rename to 633.sum-of-square-numbers.js diff --git a/634-find-the-derangement-of-an-array.js b/634-find-the-derangement-of-an-array.js deleted file mode 100644 index ae7c4945..00000000 --- a/634-find-the-derangement-of-an-array.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const findDerangement = function (n) { - if ([0, 1].includes(n)) return 0 - if (n === 2) return 1 - let prev = 1 - const MOD = 10 ** 9 + 7 - let result = 0 - for (let i = 3; i <= n; i++) { - result = (prev * i + (i % 2 === 1 ? -1 : 1)) % MOD - prev = result - } - return result -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const findDerangement = function (n) { - if (n === 0) return 0 - const MOD = 10 ** 9 + 7 - const dp = [1, 0] - for (let i = 2; i <= n; i++) { - dp[i] = ((i - 1) * (dp[i - 2] + dp[i - 1])) % MOD - } - return dp[n] -} - diff --git a/634.find-the-derangement-of-an-array.js b/634.find-the-derangement-of-an-array.js new file mode 100644 index 00000000..14feee16 --- /dev/null +++ b/634.find-the-derangement-of-an-array.js @@ -0,0 +1,17 @@ +/** + * @param {number} n + * @return {number} + */ +const findDerangement = function (n) { + if ([0, 1].includes(n)) return 0 + if (n === 2) return 1 + let prev = 1 + const MOD = 10 ** 9 + 7 + let result = 0 + for (let i = 3; i <= n; i++) { + result = (prev * i + (i % 2 === 1 ? -1 : 1)) % MOD + prev = result + } + return result +} + diff --git a/635-design-log-storage-system.js b/635.design-log-storage-system.js similarity index 100% rename from 635-design-log-storage-system.js rename to 635.design-log-storage-system.js diff --git a/636-exclusive-time-of-functions.js b/636.exclusive-time-of-functions.js similarity index 100% rename from 636-exclusive-time-of-functions.js rename to 636.exclusive-time-of-functions.js diff --git a/637-average-of-levels-in-binary-tree.js b/637.average-of-levels-in-binary-tree.js old mode 100755 new mode 100644 similarity index 100% rename from 637-average-of-levels-in-binary-tree.js rename to 637.average-of-levels-in-binary-tree.js diff --git a/638-shopping-offers.js b/638.shopping-offers.js similarity index 100% rename from 638-shopping-offers.js rename to 638.shopping-offers.js diff --git a/639-decode-ways-ii.js b/639.decode-ways-ii.js similarity index 100% rename from 639-decode-ways-ii.js rename to 639.decode-ways-ii.js diff --git a/64-minimum-path-sum.js b/64-minimum-path-sum.js deleted file mode 100755 index d14f7e8b..00000000 --- a/64-minimum-path-sum.js +++ /dev/null @@ -1,20 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const minPathSum = function(grid) { - const m = grid.length; - const n = grid[0].length; - for (let i = 1; i < n; i++) { - grid[0][i] += grid[0][i - 1]; - } - for (let i = 1; i < m; i++) { - grid[i][0] += grid[i - 1][0]; - } - for (let i = 1; i < m; i++) { - for (let j = 1; j < n; j++) { - grid[i][j] += Math.min(grid[i - 1][j], grid[i][j - 1]); - } - } - return grid[m - 1][n - 1]; -}; diff --git a/64.minimum-path-sum.js b/64.minimum-path-sum.js new file mode 100644 index 00000000..6bbddab6 --- /dev/null +++ b/64.minimum-path-sum.js @@ -0,0 +1,20 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const minPathSum = function(grid) { + const m = grid.length; + const n = grid[0].length; + for (let i = 1; i < n; i++) { + grid[0][i] += grid[0][i - 1]; + } + for (let i = 1; i < m; i++) { + grid[i][0] += grid[i - 1][0]; + } + for (let i = 1; i < m; i++) { + for (let j = 1; j < n; j++) { + grid[i][j] += Math.min(grid[i - 1][j], grid[i][j - 1]); + } + } + return grid[m - 1][n - 1]; +}; diff --git a/640-solve-the-equation.js b/640.solve-the-equation.js similarity index 100% rename from 640-solve-the-equation.js rename to 640.solve-the-equation.js diff --git a/641-design-circular-deque.js b/641.design-circular-deque.js similarity index 100% rename from 641-design-circular-deque.js rename to 641.design-circular-deque.js diff --git a/642-design-search-autocomplete-system.js b/642-design-search-autocomplete-system.js deleted file mode 100644 index 1f4a5657..00000000 --- a/642-design-search-autocomplete-system.js +++ /dev/null @@ -1,258 +0,0 @@ -/** - * @param {string[]} sentences - * @param {number[]} times - */ -const AutocompleteSystem = function (sentences, times) { - this.trie = new Trie() - this.inputString = '' - this.MAX_RESULTS = 3 - for (let i = 0, len = times.length; i < len; i++) { - this.trie.insert(sentences[i], times[i]) - } -} - -/** - * @param {character} c - * @return {string[]} - */ -AutocompleteSystem.prototype.input = function (c) { - if (c === '#') { - this.trie.insert(this.inputString) - this.inputString = '' - return [] - } - this.inputString += c - const strings = this.trie.stringsStartingWith(this.inputString) - const results = Object.keys(strings) - results.sort((a, b) => { - const aFreq = strings[a] - const bFreq = strings[b] - return aFreq !== bFreq ? bFreq - aFreq : a > b ? 1 : -1 - }) - return results.slice(0, this.MAX_RESULTS) -} - -/** - * Your AutocompleteSystem object will be instantiated and called as such: - * var obj = new AutocompleteSystem(sentences, times) - * var param_1 = obj.input(c) - */ - -// Using a Trie (Prefix tree). -/** - * Initialize your data structure here. - */ -const Trie = function () { - this._trie = {} -} - -/** - * Inserts a string into the trie a number of times. - * @param {string} word - * @param {number} [count=1] - * @return {void} - */ -Trie.prototype.insert = function (word, count = 1) { - if (!word.length || count < 1) { - return - } - let curr = this._trie - for (let i = 0; i < word.length; i++) { - const char = word[i] - if (!curr.hasOwnProperty(char)) { - curr[char] = {} - } - curr = curr[char] - } - if (!curr.hasOwnProperty('#')) { - curr['#'] = 0 - } - curr['#'] += count -} - -/** - * Returns if there is any string in the trie that starts with the given prefix. - * @param {string} prefix - * @return {Object} - */ -// Time: O(n), where n is the number of different strings in the Trie. -// Space: O(1) -Trie.prototype.stringsStartingWith = function (prefix) { - if (!prefix.length) { - return false - } - let curr = this._trie - for (let i = 0; i < prefix.length; i++) { - const char = prefix[i] - if (!curr.hasOwnProperty(char)) { - return false - } - curr = curr[char] - } - const results = {} - function traverse(node, chars) { - if (!node) { - return - } - Object.keys(node).forEach((char) => { - if (char === '#') { - results[chars] = node[char] - return - } - traverse(node[char], chars + char) - }) - } - traverse(curr, prefix) - return results -} - -// another - -class TrieNode { - constructor() { - this.children = new Map() - this.counts = new Map() - this.isWord = false - } -} - -class Pair { - constructor(s, c) { - this.str = s - this.cnt = c - } -} - -/** - * @param {string[]} sentences - * @param {number[]} times - */ -const AutocompleteSystem = function (sentences, times) { - this.root = new TrieNode() - this.prefix = '' - for (let i = 0, n = sentences.length; i < n; i++) { - this.add(sentences[i], times[i]) - } -} - -AutocompleteSystem.prototype.add = function (str, cnt) { - let cur = this.root - for (const ch of str) { - let next = cur.children.get(ch) - if (next == null) { - next = new TrieNode() - cur.children.set(ch, next) - } - cur = next - cur.counts.set(str, (cur.counts.get(str) || 0) + cnt) - } - cur.isWord = true -} - -/** - * @param {character} c - * @return {string[]} - */ -AutocompleteSystem.prototype.input = function (c) { - if (c === '#') { - this.add(this.prefix, 1) - this.prefix = '' - return [] - } - this.prefix += c - let cur = this.root - for (const ch of this.prefix) { - const next = cur.children.get(ch) - if (next == null) { - return [] - } - cur = next - } - const pq = new PriorityQueue((a, b) => - a.cnt === b.cnt ? a.str.localeCompare(b.str) < 0 : a.cnt > b.cnt - ) - - for(const s of cur.counts.keys()) { - pq.push(new Pair(s, cur.counts.get(s))) - } - const res = [] - for(let i = 0; i < 3 && pq.size(); i++) { - res.push(pq.pop().str) - } - - return res -} - -/** - * Your AutocompleteSystem object will be instantiated and called as such: - * var obj = new AutocompleteSystem(sentences, times) - * var param_1 = obj.input(c) - */ - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/642.design-search-autocomplete-system.js b/642.design-search-autocomplete-system.js new file mode 100644 index 00000000..bac080da --- /dev/null +++ b/642.design-search-autocomplete-system.js @@ -0,0 +1,108 @@ +/** + * @param {string[]} sentences + * @param {number[]} times + */ +const AutocompleteSystem = function (sentences, times) { + this.trie = new Trie() + this.inputString = '' + this.MAX_RESULTS = 3 + for (let i = 0, len = times.length; i < len; i++) { + this.trie.insert(sentences[i], times[i]) + } +} + +/** + * @param {character} c + * @return {string[]} + */ +AutocompleteSystem.prototype.input = function (c) { + if (c === '#') { + this.trie.insert(this.inputString) + this.inputString = '' + return [] + } + this.inputString += c + const strings = this.trie.stringsStartingWith(this.inputString) + const results = Object.keys(strings) + results.sort((a, b) => { + const aFreq = strings[a] + const bFreq = strings[b] + return aFreq !== bFreq ? bFreq - aFreq : a > b ? 1 : -1 + }) + return results.slice(0, this.MAX_RESULTS) +} + +/** + * Your AutocompleteSystem object will be instantiated and called as such: + * var obj = new AutocompleteSystem(sentences, times) + * var param_1 = obj.input(c) + */ + +// Using a Trie (Prefix tree). +/** + * Initialize your data structure here. + */ +const Trie = function () { + this._trie = {} +} + +/** + * Inserts a string into the trie a number of times. + * @param {string} word + * @param {number} [count=1] + * @return {void} + */ +Trie.prototype.insert = function (word, count = 1) { + if (!word.length || count < 1) { + return + } + let curr = this._trie + for (let i = 0; i < word.length; i++) { + const char = word[i] + if (!curr.hasOwnProperty(char)) { + curr[char] = {} + } + curr = curr[char] + } + if (!curr.hasOwnProperty('#')) { + curr['#'] = 0 + } + curr['#'] += count +} + +/** + * Returns if there is any string in the trie that starts with the given prefix. + * @param {string} prefix + * @return {Object} + */ +// Time: O(n), where n is the number of different strings in the Trie. +// Space: O(1) +Trie.prototype.stringsStartingWith = function (prefix) { + if (!prefix.length) { + return false + } + let curr = this._trie + for (let i = 0; i < prefix.length; i++) { + const char = prefix[i] + if (!curr.hasOwnProperty(char)) { + return false + } + curr = curr[char] + } + const results = {} + function traverse(node, chars) { + if (!node) { + return + } + Object.keys(node).forEach((char) => { + if (char === '#') { + results[chars] = node[char] + return + } + traverse(node[char], chars + char) + }) + } + traverse(curr, prefix) + return results +} + diff --git a/643-maximum-average-subarray-i.js b/643.maximum-average-subarray-i.js similarity index 100% rename from 643-maximum-average-subarray-i.js rename to 643.maximum-average-subarray-i.js diff --git a/644-maximum-average-subarray-ii.js b/644.maximum-average-subarray-ii.js similarity index 100% rename from 644-maximum-average-subarray-ii.js rename to 644.maximum-average-subarray-ii.js diff --git a/645-set-mismatch.js b/645-set-mismatch.js deleted file mode 100644 index 98106af4..00000000 --- a/645-set-mismatch.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[]} - */ -const findErrorNums = function(nums) { - if(nums == null || nums.length === 0) return null - const res = [] - const hash = {} - for(let el of nums) { - if(hash.hasOwnProperty(el)){ - res[0] = el - } else hash[el] = 0 - hash[el]++ - } - for(let i = 1, len = nums.length; i <= len; i++) { - if(!hash.hasOwnProperty(i)) { - res[1] = i - break - } - } - return res -}; - -// another - -/** - * @param {number[]} nums - * @return {number[]} - */ -const findErrorNums = function(nums) { - const res = []; - for (const i of nums) { - if (nums[Math.abs(i) - 1] < 0) res[0] = Math.abs(i); - else nums[Math.abs(i) - 1] *= -1; - } - for (let i = 0; i < nums.length; i++) { - if (nums[i] > 0) res[1] = i + 1; - } - return res; -}; - diff --git a/645.set-mismatch.js b/645.set-mismatch.js new file mode 100644 index 00000000..803cedd7 --- /dev/null +++ b/645.set-mismatch.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} nums + * @return {number[]} + */ +const findErrorNums = function(nums) { + if(nums == null || nums.length === 0) return null + const res = [] + const hash = {} + for(let el of nums) { + if(hash.hasOwnProperty(el)){ + res[0] = el + } else hash[el] = 0 + hash[el]++ + } + for(let i = 1, len = nums.length; i <= len; i++) { + if(!hash.hasOwnProperty(i)) { + res[1] = i + break + } + } + return res +}; + diff --git a/646-maximum-length-of-pair-chain.js b/646-maximum-length-of-pair-chain.js deleted file mode 100755 index ec50ac9d..00000000 --- a/646-maximum-length-of-pair-chain.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @param {number[][]} pairs - * @return {number} - */ -const findLongestChain = function(pairs) { - pairs.sort((a, b) => a[1] - b[1]) - let end = pairs[0][1], res = 1 - for(let i = 1, len = pairs.length; i < len; i++) { - if(pairs[i][0] > end) { - res++ - end = pairs[i][1] - } - } - return res -}; - -// another - -/** - * @param {number[][]} pairs - * @return {number} - */ -const findLongestChain = function(pairs) { - pairs.sort((a, b) => a[1] - b[1]); - let cur = Number.MIN_SAFE_INTEGER; - let res = 0; - for (let i = 0; i < pairs.length; i++) { - if (cur < pairs[i][0]) { - cur = pairs[i][1]; - res += 1; - } - } - return res; -}; - -// another - -/** - * @param {number[][]} pairs - * @return {number} - */ -const findLongestChain = function (pairs) { - pairs.sort((a, b) => a[0] - b[0]) - let out = 0 - let prevEnd = Number.MIN_SAFE_INTEGER - for (let i = 0; i < pairs.length; i++) { - const cur = pairs[i] - if (prevEnd < cur[0]) { - prevEnd = cur[1] - out += 1 - } else { - prevEnd = Math.min(cur[1], prevEnd) - } - } - return out -} diff --git a/646.maximum-length-of-pair-chain.js b/646.maximum-length-of-pair-chain.js new file mode 100644 index 00000000..5dc110cb --- /dev/null +++ b/646.maximum-length-of-pair-chain.js @@ -0,0 +1,16 @@ +/** + * @param {number[][]} pairs + * @return {number} + */ +const findLongestChain = function(pairs) { + pairs.sort((a, b) => a[1] - b[1]) + let end = pairs[0][1], res = 1 + for(let i = 1, len = pairs.length; i < len; i++) { + if(pairs[i][0] > end) { + res++ + end = pairs[i][1] + } + } + return res +}; + diff --git a/647-palindromic-substrings.js b/647-palindromic-substrings.js deleted file mode 100755 index ebf640e7..00000000 --- a/647-palindromic-substrings.js +++ /dev/null @@ -1,64 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const countSubstrings = function(s) { - let count = 0; - - if (s == null || s.length === 0) { - return 0; - } - - for (let i = 0; i < s.length; i++) { - extendPalindrome(s, i, i); - extendPalindrome(s, i, i + 1); - } - - function extendPalindrome(str, left, right) { - while ( - left >= 0 && - right < s.length && - s.charAt(left) === s.charAt(right) - ) { - count++; - left--; - right++; - } - } - return count; -}; - -console.log(countSubstrings("abc")); -console.log(countSubstrings("aaa")); - -// another - -/** - * @param {string} s - * @return {number} - */ -const countSubstrings = function(s) { - const arr = manachers(s) - return arr.map(e => ~~((e + 1) / 2)).reduce((ac, e) => ac + e, 0) -}; - -function manachers(s) { - const str = `@#${s.split('').join('#')}#$` - const arr = Array(str.length).fill(0) - - let center = right = 0 - for(let i = 1, n = str.length; i < n - 1; i++) { - if(i < right) { - arr[i] = Math.min(right - i, arr[2 * center - i]) - } - while(str[i + arr[i] + 1] === str[i - arr[i] - 1]) { - arr[i] += 1 - } - if(i + arr[i] > right) { - center = i - right = i + arr[i] - } - } - - return arr -} diff --git a/647.palindromic-substrings.js b/647.palindromic-substrings.js new file mode 100644 index 00000000..aa868b6e --- /dev/null +++ b/647.palindromic-substrings.js @@ -0,0 +1,33 @@ +/** + * @param {string} s + * @return {number} + */ +const countSubstrings = function(s) { + let count = 0; + + if (s == null || s.length === 0) { + return 0; + } + + for (let i = 0; i < s.length; i++) { + extendPalindrome(s, i, i); + extendPalindrome(s, i, i + 1); + } + + function extendPalindrome(str, left, right) { + while ( + left >= 0 && + right < s.length && + s.charAt(left) === s.charAt(right) + ) { + count++; + left--; + right++; + } + } + return count; +}; + +console.log(countSubstrings("abc")); +console.log(countSubstrings("aaa")); + diff --git a/648-replace-words.js b/648-replace-words.js deleted file mode 100755 index 7ed1742c..00000000 --- a/648-replace-words.js +++ /dev/null @@ -1,39 +0,0 @@ -/** - * @param {string[]} dict - * @param {string} sentence - * @return {string} - */ -const replaceWords = function(dict, sentence) { - dict.sort(); - const unsortedParts = sentence.split(" "); - const parts = unsortedParts.slice(); - parts.sort(); - - let i = (j = 0); - const rootMap = {}; - while (i < dict.length && j < parts.length) { - let part = parts[j]; - let root = dict[i]; - // dict is ahead, increase part - if (root > part) { - j++; - } else { - if (part.startsWith(root)) { - rootMap[part] = root; - j++; - } else { - i++; - } - } - } - for (i = 0; i < unsortedParts.length; i++) { - if (rootMap[unsortedParts[i]]) { - unsortedParts[i] = rootMap[unsortedParts[i]]; - } - } - return unsortedParts.join(" "); -}; - -console.log( - replaceWords(["cat", "bat", "rat"], "the cattle was rattled by the battery") -); diff --git a/648.replace-words.js b/648.replace-words.js new file mode 100644 index 00000000..6e358f5f --- /dev/null +++ b/648.replace-words.js @@ -0,0 +1,39 @@ +/** + * @param {string[]} dict + * @param {string} sentence + * @return {string} + */ +const replaceWords = function(dict, sentence) { + dict.sort(); + const unsortedParts = sentence.split(" "); + const parts = unsortedParts.slice(); + parts.sort(); + + let i = (j = 0); + const rootMap = {}; + while (i < dict.length && j < parts.length) { + let part = parts[j]; + let root = dict[i]; + // dict is ahead, increase part + if (root > part) { + j++; + } else { + if (part.startsWith(root)) { + rootMap[part] = root; + j++; + } else { + i++; + } + } + } + for (i = 0; i < unsortedParts.length; i++) { + if (rootMap[unsortedParts[i]]) { + unsortedParts[i] = rootMap[unsortedParts[i]]; + } + } + return unsortedParts.join(" "); +}; + +console.log( + replaceWords(["cat", "bat", "rat"], "the cattle was rattled by the battery") +); diff --git a/649-dota2-senate.js b/649.dota2-senate.js similarity index 100% rename from 649-dota2-senate.js rename to 649.dota2-senate.js diff --git a/65-valid-number.js b/65-valid-number.js deleted file mode 100755 index 1660b715..00000000 --- a/65-valid-number.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @param {string} str - * @returns {boolean} - */ -const isNumber = function(str) { - let i = 0; - let s = str; - // 跳过前导空格 - for (; i < s.length && " " == s[i]; ++i); - // 处理正负号 - if ("+" == s[i] || "-" == s[i]) ++i; - // 处理后面数字部分 - let digit = false, - dot = false, - exp = false; - for (; i < s.length; ++i) { - if ("." == s[i] && !dot) - // '.'不能出现2次,'.'前面可以没有数字 - dot = true; - else if ("e" == s[i] && !exp && digit) { - // 'e'不能出现2次,'e'前面必须有数字 - // 'e'后面不能出现'.','e'后面必须是整数(可以是正的或负的) - dot = exp = true; - if (i + 1 < s.length && ("+" == s[i + 1] || "-" == s[i + 1])) ++i; - if (i + 1 >= s.length || !(s[i + 1] >= "0" && s[i + 1] <= "9")) - return false; - } else if (s[i] >= "0" && s[i] <= "9") digit = true; - else break; - } - - // 跳过后面空格 - for (; i < s.length && " " == s[i]; ++i); - - return digit && i == s.length; -}; diff --git a/65.valid-number.js b/65.valid-number.js new file mode 100644 index 00000000..1708248a --- /dev/null +++ b/65.valid-number.js @@ -0,0 +1,35 @@ +/** + * @param {string} str + * @returns {boolean} + */ +const isNumber = function(str) { + let i = 0; + let s = str; + // 跳过前导空格 + for (; i < s.length && " " == s[i]; ++i); + // 处理正负号 + if ("+" == s[i] || "-" == s[i]) ++i; + // 处理后面数字部分 + let digit = false, + dot = false, + exp = false; + for (; i < s.length; ++i) { + if ("." == s[i] && !dot) + // '.'不能出现2次,'.'前面可以没有数字 + dot = true; + else if ("e" == s[i] && !exp && digit) { + // 'e'不能出现2次,'e'前面必须有数字 + // 'e'后面不能出现'.','e'后面必须是整数(可以是正的或负的) + dot = exp = true; + if (i + 1 < s.length && ("+" == s[i + 1] || "-" == s[i + 1])) ++i; + if (i + 1 >= s.length || !(s[i + 1] >= "0" && s[i + 1] <= "9")) + return false; + } else if (s[i] >= "0" && s[i] <= "9") digit = true; + else break; + } + + // 跳过后面空格 + for (; i < s.length && " " == s[i]; ++i); + + return digit && i == s.length; +}; diff --git a/650-2-keys-keyboard.js b/650-2-keys-keyboard.js deleted file mode 100755 index ff4f513e..00000000 --- a/650-2-keys-keyboard.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const minSteps = function(n) { - let res = 0 - for (let i = 2; i <= n; i++) { - while (n % i === 0) { - res += i - n /= i - } - } - return res -} diff --git a/650.2-keys-keyboard.js b/650.2-keys-keyboard.js new file mode 100644 index 00000000..a77d8c51 --- /dev/null +++ b/650.2-keys-keyboard.js @@ -0,0 +1,14 @@ +/** + * @param {number} n + * @return {number} + */ +const minSteps = function(n) { + let res = 0 + for (let i = 2; i <= n; i++) { + while (n % i === 0) { + res += i + n /= i + } + } + return res +} diff --git a/651-4-keys-keyboard.js b/651-4-keys-keyboard.js deleted file mode 100644 index b20bcd6f..00000000 --- a/651-4-keys-keyboard.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @param {number} N - * @return {number} - */ -const maxA = function (N) { - const dp = [0, 1, 2, 3, 4, 5, 6] - const recurse = function (n) { - if (dp[n]) return dp[n] - const max = Math.max( - recurse(n - 3) * 2, - recurse(n - 4) * 3, - recurse(n - 5) * 4 - ) - return (dp[n] = max) - } - return recurse(N) -} - -// another - -/** - * @param {number} N - * @return {number} - */ -const maxA = function (N) { - const dp = [...new Array(N + 1)].map((_, i) => i) - for (let i = 4; i <= N; i++) { - for (let j = 1; j <= i - 3; j++) { - dp[i] = Math.max(dp[i], dp[j] * (i - j - 1)) - } - } - return dp[N] -} - -// another - -/** - * @param {number} N - * @return {number} - */ -const maxA = function (N) { - const dp = new Array(7).fill(0) - for (let i = 1; i <= N; i++) { - dp[0] = i - for (let k = 6; k > 2; k--) { - dp[0] = Math.max(dp[0], dp[k] * (k - 1)) - } - for (let k = 6; k > 0; k--) { - dp[k] = dp[k - 1] - } - } - return dp[0] -} - diff --git a/651.4-keys-keyboard.js b/651.4-keys-keyboard.js new file mode 100644 index 00000000..99d67aa9 --- /dev/null +++ b/651.4-keys-keyboard.js @@ -0,0 +1,18 @@ +/** + * @param {number} N + * @return {number} + */ +const maxA = function (N) { + const dp = [0, 1, 2, 3, 4, 5, 6] + const recurse = function (n) { + if (dp[n]) return dp[n] + const max = Math.max( + recurse(n - 3) * 2, + recurse(n - 4) * 3, + recurse(n - 5) * 4 + ) + return (dp[n] = max) + } + return recurse(N) +} + diff --git a/652-find-duplicate-subtrees.js b/652-find-duplicate-subtrees.js deleted file mode 100644 index 8a1a84da..00000000 --- a/652-find-duplicate-subtrees.js +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode[]} - */ -const findDuplicateSubtrees = function(root) { - const hash = {}, res = [] - pre(root, hash, res) - return res -}; - -function pre(node, hash, res) { - if(node == null) return '#' - const str = `${node.val},${pre(node.left, hash, res)},${pre(node.right, hash, res)}` - if(hash[str] == null) hash[str] = 0 - hash[str]++ - if(hash[str] === 2) res.push(node) - return str -} - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode[]} - */ -const findDuplicateSubtrees = function(root) { - const serId = {}, cntId = {}, res = [] - let id = 1 - post(root) - return res - - function post(node) { - if(node == null) return 0 - const curId = `${post(node.left)},${node.val},${post(node.right)}` - serId[curId] = serId[curId] || id - if(serId[curId] === id) id++ - cntId[curId] = (cntId[curId] || 0) + 1 - if(cntId[curId] === 2) res.push(node) - return serId[curId] - } -}; - diff --git a/652.find-duplicate-subtrees.js b/652.find-duplicate-subtrees.js new file mode 100644 index 00000000..a15cf417 --- /dev/null +++ b/652.find-duplicate-subtrees.js @@ -0,0 +1,27 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {TreeNode[]} + */ +const findDuplicateSubtrees = function(root) { + const hash = {}, res = [] + pre(root, hash, res) + return res +}; + +function pre(node, hash, res) { + if(node == null) return '#' + const str = `${node.val},${pre(node.left, hash, res)},${pre(node.right, hash, res)}` + if(hash[str] == null) hash[str] = 0 + hash[str]++ + if(hash[str] === 2) res.push(node) + return str +} + diff --git a/653-two-sum-iv-input-is-a-bst.js b/653.two-sum-iv-input-is-a-bst.js similarity index 100% rename from 653-two-sum-iv-input-is-a-bst.js rename to 653.two-sum-iv-input-is-a-bst.js diff --git a/655-print-binary-tree.js b/655.print-binary-tree.js similarity index 100% rename from 655-print-binary-tree.js rename to 655.print-binary-tree.js diff --git a/656-coin-path.js b/656.coin-path.js similarity index 100% rename from 656-coin-path.js rename to 656.coin-path.js diff --git a/658-find-k-closest-elements.js b/658-find-k-closest-elements.js deleted file mode 100644 index 38d61158..00000000 --- a/658-find-k-closest-elements.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {number[]} arr - * @param {number} k - * @param {number} x - * @return {number[]} - */ -const findClosestElements = function(arr, k, x) { - let lo = 0, hi = arr.length - k - 1; - while (lo <= hi) { - let mid = Math.floor(lo + (hi - lo) / 2); - if (Math.abs(x - arr[mid]) > Math.abs(x - arr[mid+k])) { - lo = mid + 1; - } else { - hi = mid - 1; - } - } - return arr.slice(lo, lo+k); -}; - -// another - -/** - * @param {number[]} arr - * @param {number} k - * @param {number} x - * @return {number[]} - */ -const findClosestElements = function(arr, k, x) { - let lo=0,hi=arr.length-1 - while(hi-lo>=k){ - let left=Math.abs(x-arr[lo]) - let right=Math.abs(x-arr[hi]) - if(leftright){ - lo++ - }else{ - hi-- - } - } - return arr.slice(lo,hi+1) -}; diff --git a/658.find-k-closest-elements.js b/658.find-k-closest-elements.js new file mode 100644 index 00000000..474f9081 --- /dev/null +++ b/658.find-k-closest-elements.js @@ -0,0 +1,19 @@ +/** + * @param {number[]} arr + * @param {number} k + * @param {number} x + * @return {number[]} + */ +const findClosestElements = function(arr, k, x) { + let lo = 0, hi = arr.length - k - 1; + while (lo <= hi) { + let mid = Math.floor(lo + (hi - lo) / 2); + if (Math.abs(x - arr[mid]) > Math.abs(x - arr[mid+k])) { + lo = mid + 1; + } else { + hi = mid - 1; + } + } + return arr.slice(lo, lo+k); +}; + diff --git a/659-split-array-into-consecutive-subsequences.js b/659-split-array-into-consecutive-subsequences.js deleted file mode 100644 index af5bb0fc..00000000 --- a/659-split-array-into-consecutive-subsequences.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @param {number[]} nums - * @return {boolean} - */ -const isPossible = function(nums) { - const freq = new Map() - const build = new Map() - for (let el of nums) { - freq.has(el) ? freq.set(el, freq.get(el) + 1) : freq.set(el, 1) - } - for (let item of nums) { - if (freq.get(item) === 0) continue - else if (getOrDefault(build, item) > 0) { - build.set(item, build.get(item) - 1) - build.set(item + 1, getOrDefault(build, item + 1) + 1) - } else if (getOrDefault(freq, item + 1) > 0 && getOrDefault(freq, item + 2) > 0) { - freq.set(item + 1, freq.get(item + 1) - 1) - freq.set(item + 2, freq.get(item + 2) - 1) - build.set(item + 3, getOrDefault(build, item + 3) + 1) - } else return false - freq.set(item, freq.get(item) - 1) - } - return true -} - -function getOrDefault(map, key) { - return map.get(key) || 0 -} - - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -const isPossible = function(nums) { - let prev = -Infinity, p1 = 0, p2 = 0, p3 = 0 - let i = 0 - const n = nums.length - while (i < n) { - let curr = nums[i], c1 = 0, c2 = 0, c3 = 0 - let cnt = 0 - while (i < n && nums[i] === curr) { cnt++; i++ } - if (curr !== prev+1) { - if (p1 > 0 || p2 > 0) { return false } - c1 = cnt; c2 = 0; c3 = 0 - } else { - if (cnt < p1 + p2) { return false } - c2 = p1 - c3 = p2 + Math.min(p3, cnt - p1 - p2) - c1 = Math.max(0, cnt - p1 - p2 - p3) - } - prev = curr; p1 = c1; p2 = c2; p3 = c3; - } - return p1 === 0 && p2 === 0 -}; diff --git a/659.split-array-into-consecutive-subsequences.js b/659.split-array-into-consecutive-subsequences.js new file mode 100644 index 00000000..27473aa8 --- /dev/null +++ b/659.split-array-into-consecutive-subsequences.js @@ -0,0 +1,30 @@ +/** + * @param {number[]} nums + * @return {boolean} + */ +const isPossible = function(nums) { + const freq = new Map() + const build = new Map() + for (let el of nums) { + freq.has(el) ? freq.set(el, freq.get(el) + 1) : freq.set(el, 1) + } + for (let item of nums) { + if (freq.get(item) === 0) continue + else if (getOrDefault(build, item) > 0) { + build.set(item, build.get(item) - 1) + build.set(item + 1, getOrDefault(build, item + 1) + 1) + } else if (getOrDefault(freq, item + 1) > 0 && getOrDefault(freq, item + 2) > 0) { + freq.set(item + 1, freq.get(item + 1) - 1) + freq.set(item + 2, freq.get(item + 2) - 1) + build.set(item + 3, getOrDefault(build, item + 3) + 1) + } else return false + freq.set(item, freq.get(item) - 1) + } + return true +} + +function getOrDefault(map, key) { + return map.get(key) || 0 +} + + diff --git a/66-plus-one.js b/66.plus-one.js similarity index 100% rename from 66-plus-one.js rename to 66.plus-one.js diff --git a/660-remove-9.js b/660-remove-9.js deleted file mode 100644 index c9fc656b..00000000 --- a/660-remove-9.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const newInteger = function (n) { - let res = '' - while (n > 0) { - res = (n % 9) + res - n = Math.floor(n / 9) - } - return parseInt(res, 10) -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const newInteger = function (n) { - return +(n).toString(9) -} diff --git a/660.remove-9.js b/660.remove-9.js new file mode 100644 index 00000000..17ac462e --- /dev/null +++ b/660.remove-9.js @@ -0,0 +1,13 @@ +/** + * @param {number} n + * @return {number} + */ +const newInteger = function (n) { + let res = '' + while (n > 0) { + res = (n % 9) + res + n = Math.floor(n / 9) + } + return parseInt(res, 10) +} + diff --git a/661-image-smoother.js b/661.image-smoother.js similarity index 100% rename from 661-image-smoother.js rename to 661.image-smoother.js diff --git a/662-maximum-width-of-binary-tree.js b/662.maximum-width-of-binary-tree.js similarity index 100% rename from 662-maximum-width-of-binary-tree.js rename to 662.maximum-width-of-binary-tree.js diff --git a/663-equal-tree-partition.js b/663.equal-tree-partition.js similarity index 100% rename from 663-equal-tree-partition.js rename to 663.equal-tree-partition.js diff --git a/664-strange-printer.js b/664-strange-printer.js deleted file mode 100644 index deb5a1fe..00000000 --- a/664-strange-printer.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const strangePrinter = function(s) { - // optimize - const arr = s.split('') - for(let i = 1; i < arr.length; i++) { - if(arr[i] === arr[i - 1]) arr[i - 1] = '' - } - s = arr.join('') - let n = s.length - let dp = new Array(n).fill(0).map(() => new Array(n).fill(0)) - - const help = (s, i, j) => { - if (i > j) return 0 - if (dp[i][j] > 0) { - return dp[i][j] - } - let res = help(s, i, j - 1) + 1 - for (let k = i; k < j; k++) { - if (s[k] === s[j]) { - res = Math.min(help(s, i, k) + help(s, k + 1, j - 1), res) - } - } - dp[i][j] = res - return res - } - - return help(s, 0, n - 1) -} - -// another - -/** - * @param {string} s - * @return {number} - */ -const strangePrinter = function(s) { - const n = s.length - const dp = Array.from({ length: n }, () => Array(n).fill(n)) - for(let i = 0; i < n; i++) dp[i][i] = 1 - for(let len = 2; len <= n; len++) { - for(let i = 0; i < n - len + 1; i++) { - let j = i + len - 1 - dp[i][j] = 1 + dp[i + 1][j] - for(let k = i + 1; k < j; k++) { - if(s[i] === s[k]) dp[i][j] = Math.min(dp[i][j], dp[i][k - 1] + dp[k + 1][j]) - } - if(s[i] === s[j]) dp[i][j] = Math.min(dp[i][j - 1], dp[i][j]) - } - } - return dp[0][n - 1] -}; diff --git a/664.strange-printer.js b/664.strange-printer.js new file mode 100644 index 00000000..19b2f122 --- /dev/null +++ b/664.strange-printer.js @@ -0,0 +1,32 @@ +/** + * @param {string} s + * @return {number} + */ +const strangePrinter = function(s) { + // optimize + const arr = s.split('') + for(let i = 1; i < arr.length; i++) { + if(arr[i] === arr[i - 1]) arr[i - 1] = '' + } + s = arr.join('') + let n = s.length + let dp = new Array(n).fill(0).map(() => new Array(n).fill(0)) + + const help = (s, i, j) => { + if (i > j) return 0 + if (dp[i][j] > 0) { + return dp[i][j] + } + let res = help(s, i, j - 1) + 1 + for (let k = i; k < j; k++) { + if (s[k] === s[j]) { + res = Math.min(help(s, i, k) + help(s, k + 1, j - 1), res) + } + } + dp[i][j] = res + return res + } + + return help(s, 0, n - 1) +} + diff --git a/665-non-decreasing-array.js b/665.non-decreasing-array.js similarity index 100% rename from 665-non-decreasing-array.js rename to 665.non-decreasing-array.js diff --git a/666-path-sum-iv.js b/666-path-sum-iv.js deleted file mode 100644 index a223b42f..00000000 --- a/666-path-sum-iv.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const pathSum = function (nums) { - if (nums == null || nums.length === 0) return 0 - const tree = Array(2 ** 5).fill(null) - for (let num of nums) { - const r = ((num / 100) >> 0) - 1 - const pos = (((num % 100) / 10) >> 0) - 1 - const v = num % 10 - tree[Math.pow(2, r) + pos] = v - } - let res = 0 - const q = [1] - while (q.length) { - const cur = q.shift() - const left = cur * 2 - const right = cur * 2 + 1 - if (left >= tree.length || (tree[left] == null && tree[right] == null)) - res += tree[cur] - else { - if (tree[left] != null) { - q.push(left) - tree[left] += tree[cur] - } - if (tree[right] != null) { - q.push(right) - tree[right] += tree[cur] - } - } - } - return res -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const pathSum = function (nums) { - if (nums == null || nums.length === 0) return 0 - const tree = new Map() - for (let num of nums) { - tree.set((num / 10) >> 0, num % 10) - } - return traverse((nums[0] / 10) >> 0, 0) - - function traverse(node, prev) { - if (!tree.has(node)) return 0 - const level = (node / 10) >> 0 - const pos = node % 10 - const val = tree.get(node) - const left = (level + 1) * 10 + pos * 2 - 1 - const right = (level + 1) * 10 + pos * 2 - const cur = prev + val - if (!tree.has(left) && !tree.has(right)) return cur - return traverse(left, cur) + traverse(right, cur) - } -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const pathSum = function (nums) { - const arr = Array(1 << 5).fill(-1) - for (let num of nums) { - let [lvl, pos, val] = [ - parseInt(num / 100), - parseInt((num % 100) / 10), - num % 10, - ] - arr[(1 << (lvl - 1)) - 1 + pos - 1] = val - } - let sum = 0 - for (let i = 0; i < 1 << 4; i++) { - if (arr[i] !== -1) { - arr[i] += i > 0 ? arr[parseInt((i - 1) >> 1)] : 0 - if (arr[i * 2 + 1] === -1 && arr[i * 2 + 2] === -1) { - sum += arr[i] - } - } - } - return sum -} diff --git a/666.path-sum-iv.js b/666.path-sum-iv.js new file mode 100644 index 00000000..249e5119 --- /dev/null +++ b/666.path-sum-iv.js @@ -0,0 +1,35 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const pathSum = function (nums) { + if (nums == null || nums.length === 0) return 0 + const tree = Array(2 ** 5).fill(null) + for (let num of nums) { + const r = ((num / 100) >> 0) - 1 + const pos = (((num % 100) / 10) >> 0) - 1 + const v = num % 10 + tree[Math.pow(2, r) + pos] = v + } + let res = 0 + const q = [1] + while (q.length) { + const cur = q.shift() + const left = cur * 2 + const right = cur * 2 + 1 + if (left >= tree.length || (tree[left] == null && tree[right] == null)) + res += tree[cur] + else { + if (tree[left] != null) { + q.push(left) + tree[left] += tree[cur] + } + if (tree[right] != null) { + q.push(right) + tree[right] += tree[cur] + } + } + } + return res +} + diff --git a/667-beautiful-arrangement-ii.js b/667.beautiful-arrangement-ii.js similarity index 100% rename from 667-beautiful-arrangement-ii.js rename to 667.beautiful-arrangement-ii.js diff --git a/668-kth-smallest-number-in-multiplication-table.js b/668-kth-smallest-number-in-multiplication-table.js deleted file mode 100644 index 6e15d6e4..00000000 --- a/668-kth-smallest-number-in-multiplication-table.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @param {number} m - * @param {number} n - * @param {number} k - * @return {number} - */ -const findKthNumber = function(m, n, k) { - let left = 1; - let right = m * n; - while (left < right) { - const mid = Math.floor((left + right) / 2); - const nSmaller = count(m, n, mid); - if (nSmaller >= k) { - right = mid; - } else { - left = mid + 1; - } - } - return left; -}; - -function count(m, n, target) { - let nSmaller = 0; - let j = n; - for (let i = 1; i <= m; i++) { - while (i * j > target) { - j -= 1; - } - nSmaller += j; - } - return nSmaller; -} - -// another - -/** - * @param {number} m - * @param {number} n - * @param {number} k - * @return {number} - */ -const findKthNumber = function(m, n, k) { - let left = 1; - let right = m * n; - while (left < right) { - const mid = Math.floor((left + right) / 2); - const num = count(m, n, mid); - if (num < k) left = mid + 1; - else right = mid; - } - return left; -}; - -function count(m, n, target) { - let res = 0; - let j = n; - for (let i = 1; i <= m; i++) { - while (i * j > target) j-- - res += j; - } - return res; -} diff --git a/668.kth-smallest-number-in-multiplication-table.js b/668.kth-smallest-number-in-multiplication-table.js new file mode 100644 index 00000000..2774f24c --- /dev/null +++ b/668.kth-smallest-number-in-multiplication-table.js @@ -0,0 +1,33 @@ +/** + * @param {number} m + * @param {number} n + * @param {number} k + * @return {number} + */ +const findKthNumber = function(m, n, k) { + let left = 1; + let right = m * n; + while (left < right) { + const mid = Math.floor((left + right) / 2); + const nSmaller = count(m, n, mid); + if (nSmaller >= k) { + right = mid; + } else { + left = mid + 1; + } + } + return left; +}; + +function count(m, n, target) { + let nSmaller = 0; + let j = n; + for (let i = 1; i <= m; i++) { + while (i * j > target) { + j -= 1; + } + nSmaller += j; + } + return nSmaller; +} + diff --git a/669-trim-a-binary-search-tree.js b/669-trim-a-binary-search-tree.js deleted file mode 100755 index 506a7578..00000000 --- a/669-trim-a-binary-search-tree.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {number} L - * @param {number} R - * @return {TreeNode} - */ -const trimBST = function(root, L, R) { - return single(root, L, R); -}; - -function single(node, L, R) { - if (node === null) { - return null; - } - if (node.val > R) { - return single(node.left, L, R); - } - if (node.val < L) { - return single(node.right, L, R); - } - if (node.left !== null) { - node.left = single(node.left, L, R); - } - if (node.right !== null) { - node.right = single(node.right, L, R); - } - return node; -} diff --git a/669.trim-a-binary-search-tree.js b/669.trim-a-binary-search-tree.js new file mode 100644 index 00000000..323fc01e --- /dev/null +++ b/669.trim-a-binary-search-tree.js @@ -0,0 +1,35 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {number} L + * @param {number} R + * @return {TreeNode} + */ +const trimBST = function(root, L, R) { + return single(root, L, R); +}; + +function single(node, L, R) { + if (node === null) { + return null; + } + if (node.val > R) { + return single(node.left, L, R); + } + if (node.val < L) { + return single(node.right, L, R); + } + if (node.left !== null) { + node.left = single(node.left, L, R); + } + if (node.right !== null) { + node.right = single(node.right, L, R); + } + return node; +} diff --git a/67-add-binary.js b/67-add-binary.js deleted file mode 100644 index 1e6c437f..00000000 --- a/67-add-binary.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @param {string} a - * @param {string} b - * @return {string} - */ -const addBinary = function(a, b) { - let s = '' - let c = 0 - let i = a.length - 1 - let j = b.length - 1 - while(i >= 0 || j >= 0 || c === 1) { - c += i >= 0 ? +a[i--] : 0 - c += j >= 0 ? +b[j--] : 0 - s = (c % 2 === 1 ? '1' : '0') + s - c = Math.floor(c / 2) - } - return s -}; - -// another - -/** - * @param {string} a - * @param {string} b - * @return {string} - */ -const addBinary = function(a, b) { - let next = false - let res = [] - let ai = a.length - 1 - let bi = b.length - 1 - while((ai >= 0 && bi >=0) || next) { - const tmp = (ai >= 0 ? +a[ai--] : 0) + (bi >= 0 ? +b[bi--] : 0) + (next ? 1 : 0) - if(tmp > 1) next = true - else next = false - res.unshift('' + (tmp % 2)) - } - - while(ai >= 0) res.unshift(a[ai--]) - while(bi >= 0) res.unshift(b[bi--]) - - return res.join('') -}; diff --git a/67.add-binary.js b/67.add-binary.js new file mode 100644 index 00000000..ef605517 --- /dev/null +++ b/67.add-binary.js @@ -0,0 +1,19 @@ +/** + * @param {string} a + * @param {string} b + * @return {string} + */ +const addBinary = function(a, b) { + let s = '' + let c = 0 + let i = a.length - 1 + let j = b.length - 1 + while(i >= 0 || j >= 0 || c === 1) { + c += i >= 0 ? +a[i--] : 0 + c += j >= 0 ? +b[j--] : 0 + s = (c % 2 === 1 ? '1' : '0') + s + c = Math.floor(c / 2) + } + return s +}; + diff --git a/670-maximum-swap.js b/670.maximum-swap.js similarity index 100% rename from 670-maximum-swap.js rename to 670.maximum-swap.js diff --git a/671-second-minimum-node-in-a-binary-tree.js b/671-second-minimum-node-in-a-binary-tree.js deleted file mode 100644 index 12bd486a..00000000 --- a/671-second-minimum-node-in-a-binary-tree.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const findSecondMinimumValue = function(root) { - if(root == null) return -1 - const q = [root] - let min = Number.MAX_VALUE - let min2nd = Number.MAX_VALUE - while(q.length) { - const len = q.length - for(let i = 0; i < len; i++) { - const cur = q.shift() - if(cur.val <= min) { - min = cur.val - } else if(cur.val > min && cur.val < min2nd) { - min2nd = cur.val - } - if(cur.left) q.push(cur.left) - if(cur.right) q.push(cur.right) - } - } - return min2nd === Number.MAX_VALUE ? -1 : min2nd -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const findSecondMinimumValue = function (root) { - if (root === null) return -1; - if (root.left === null && root.right === null) return -1; - let left = root.left.val; - let right = root.right.val; - if (left === root.val) { - left = findSecondMinimumValue(root.left); - } - if (right === root.val) { - right = findSecondMinimumValue(root.right); - } - if (right !== -1 && left !== -1) { - return Math.min(left, right); - } - if (right === -1) { - return left; - } - if (left === -1) { - return right; - } -}; diff --git a/671.second-minimum-node-in-a-binary-tree.js b/671.second-minimum-node-in-a-binary-tree.js new file mode 100644 index 00000000..63bc7f66 --- /dev/null +++ b/671.second-minimum-node-in-a-binary-tree.js @@ -0,0 +1,32 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +const findSecondMinimumValue = function(root) { + if(root == null) return -1 + const q = [root] + let min = Number.MAX_VALUE + let min2nd = Number.MAX_VALUE + while(q.length) { + const len = q.length + for(let i = 0; i < len; i++) { + const cur = q.shift() + if(cur.val <= min) { + min = cur.val + } else if(cur.val > min && cur.val < min2nd) { + min2nd = cur.val + } + if(cur.left) q.push(cur.left) + if(cur.right) q.push(cur.right) + } + } + return min2nd === Number.MAX_VALUE ? -1 : min2nd +}; + diff --git a/672-bulb-switcher-ii.js b/672.bulb-switcher-ii.js similarity index 100% rename from 672-bulb-switcher-ii.js rename to 672.bulb-switcher-ii.js diff --git a/673-number-of-longest-increasing-subsequence.js b/673.number-of-longest-increasing-subsequence.js similarity index 100% rename from 673-number-of-longest-increasing-subsequence.js rename to 673.number-of-longest-increasing-subsequence.js diff --git a/674-longest-continuous-increasing-subsequence.js b/674-longest-continuous-increasing-subsequence.js deleted file mode 100755 index 730d31e0..00000000 --- a/674-longest-continuous-increasing-subsequence.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const findLengthOfLCIS = function(nums) { - if (nums.length == 1) { - return 1; - } - let ans = 0, - anchor = 0; - for (let i = 1; i < nums.length; i++) { - if (nums[i - 1] >= nums[i]) { - anchor = i; - } - ans = Math.max(ans, i - anchor + 1); - } - return ans; -}; diff --git a/674.longest-continuous-increasing-subsequence.js b/674.longest-continuous-increasing-subsequence.js new file mode 100644 index 00000000..9f37c6ca --- /dev/null +++ b/674.longest-continuous-increasing-subsequence.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const findLengthOfLCIS = function(nums) { + if (nums.length == 1) { + return 1; + } + let ans = 0, + anchor = 0; + for (let i = 1; i < nums.length; i++) { + if (nums[i - 1] >= nums[i]) { + anchor = i; + } + ans = Math.max(ans, i - anchor + 1); + } + return ans; +}; diff --git a/675-cut-off-trees-for-golf-event.js b/675.cut-off-trees-for-golf-event.js similarity index 100% rename from 675-cut-off-trees-for-golf-event.js rename to 675.cut-off-trees-for-golf-event.js diff --git a/676-implement-magic-dictionary.js b/676-implement-magic-dictionary.js deleted file mode 100755 index 18e27e69..00000000 --- a/676-implement-magic-dictionary.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Initialize your data structure here. - */ -const MagicDictionary = function(dict) { - this.dict = []; -}; - -/** - * Build a dictionary through a list of words - * @param {string[]} dict - * @return {void} - */ -MagicDictionary.prototype.buildDict = function(dict) { - this.dict = dict; -}; - -/** - * Returns if there is any word in the trie that equals to the given word after modifying exactly one character - * @param {string} word - * @return {boolean} - */ -MagicDictionary.prototype.search = function(word) { - return check(word, this.dict); -}; - -/** - * Your MagicDictionary object will be instantiated and called as such: - * var obj = Object.create(MagicDictionary).createNew() - * obj.buildDict(dict) - * var param_2 = obj.search(word) - */ - -function check(str, arr) { - let el; - for (let i = 0; i < arr.length; i++) { - el = arr[i]; - if (el.length === str.length && oneCharDiff(el, str)) { - return true; - } - } - - return false; -} - -function oneCharDiff(str1, str2) { - let diff = 0; - for (let i = 0; i < str1.length; i++) { - if (str1[i] !== str2[i]) { - diff += 1; - } - } - return diff === 1 ? true : false; -} diff --git a/676.implement-magic-dictionary.js b/676.implement-magic-dictionary.js new file mode 100644 index 00000000..e24c6265 --- /dev/null +++ b/676.implement-magic-dictionary.js @@ -0,0 +1,53 @@ +/** + * Initialize your data structure here. + */ +const MagicDictionary = function(dict) { + this.dict = []; +}; + +/** + * Build a dictionary through a list of words + * @param {string[]} dict + * @return {void} + */ +MagicDictionary.prototype.buildDict = function(dict) { + this.dict = dict; +}; + +/** + * Returns if there is any word in the trie that equals to the given word after modifying exactly one character + * @param {string} word + * @return {boolean} + */ +MagicDictionary.prototype.search = function(word) { + return check(word, this.dict); +}; + +/** + * Your MagicDictionary object will be instantiated and called as such: + * var obj = Object.create(MagicDictionary).createNew() + * obj.buildDict(dict) + * var param_2 = obj.search(word) + */ + +function check(str, arr) { + let el; + for (let i = 0; i < arr.length; i++) { + el = arr[i]; + if (el.length === str.length && oneCharDiff(el, str)) { + return true; + } + } + + return false; +} + +function oneCharDiff(str1, str2) { + let diff = 0; + for (let i = 0; i < str1.length; i++) { + if (str1[i] !== str2[i]) { + diff += 1; + } + } + return diff === 1 ? true : false; +} diff --git a/677-map-sum-pairs.js b/677-map-sum-pairs.js deleted file mode 100755 index 07e17464..00000000 --- a/677-map-sum-pairs.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Initialize your data structure here. - */ -const MapSum = function() { - this.hash = {}; -}; - -/** - * @param {string} key - * @param {number} val - * @return {void} - */ -MapSum.prototype.insert = function(key, val) { - this.hash[key] = val; -}; - -/** - * @param {string} prefix - * @return {number} - */ -MapSum.prototype.sum = function(prefix) { - let res = 0; - Object.keys(this.hash).forEach(el => { - if (el.indexOf(prefix) === 0) { - res += this.hash[el]; - } - }); - return res; -}; - -/** - * Your MapSum object will be instantiated and called as such: - * var obj = Object.create(MapSum).createNew() - * obj.insert(key,val) - * var param_2 = obj.sum(prefix) - */ diff --git a/677.map-sum-pairs.js b/677.map-sum-pairs.js new file mode 100644 index 00000000..4059a485 --- /dev/null +++ b/677.map-sum-pairs.js @@ -0,0 +1,36 @@ +/** + * Initialize your data structure here. + */ +const MapSum = function() { + this.hash = {}; +}; + +/** + * @param {string} key + * @param {number} val + * @return {void} + */ +MapSum.prototype.insert = function(key, val) { + this.hash[key] = val; +}; + +/** + * @param {string} prefix + * @return {number} + */ +MapSum.prototype.sum = function(prefix) { + let res = 0; + Object.keys(this.hash).forEach(el => { + if (el.indexOf(prefix) === 0) { + res += this.hash[el]; + } + }); + return res; +}; + +/** + * Your MapSum object will be instantiated and called as such: + * var obj = Object.create(MapSum).createNew() + * obj.insert(key,val) + * var param_2 = obj.sum(prefix) + */ diff --git a/678-valid-parenthesis-string.js b/678-valid-parenthesis-string.js deleted file mode 100644 index 443a9a4d..00000000 --- a/678-valid-parenthesis-string.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {string} s - * @return {boolean} - */ -const checkValidString = function(s) { - let lo = 0, hi = 0; - for (let i = 0; i < s.length; i++) { - lo += s[i] == '(' ? 1 : -1; - hi += s[i] != ')' ? 1 : -1; - if (hi < 0) break; - lo = Math.max(lo, 0); - } - return lo === 0; -}; - -// another - -/** - * @param {string} s - * @return {boolean} - */ - const checkValidString = function (s) { - let lo = 0, hi = 0 // 可能多余的‘(’ - for(let ch of s) { - if(ch === '(') lo++, hi++ - if(ch === ')') { - if(lo > 0) lo-- - hi-- - } - if(ch === '*') { - if(lo > 0) lo-- - hi++ - } - if(hi < 0) return false - } - return lo === 0 -} diff --git a/678.valid-parenthesis-string.js b/678.valid-parenthesis-string.js new file mode 100644 index 00000000..384c4dbe --- /dev/null +++ b/678.valid-parenthesis-string.js @@ -0,0 +1,15 @@ +/** + * @param {string} s + * @return {boolean} + */ +const checkValidString = function(s) { + let lo = 0, hi = 0; + for (let i = 0; i < s.length; i++) { + lo += s[i] == '(' ? 1 : -1; + hi += s[i] != ')' ? 1 : -1; + if (hi < 0) break; + lo = Math.max(lo, 0); + } + return lo === 0; +}; + diff --git a/679-24-game.js b/679-24-game.js deleted file mode 100644 index 20fd0351..00000000 --- a/679-24-game.js +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @param {number[]} nums - * @return {boolean} - */ -const judgePoint24 = function(nums) { - return dfs(nums) -} - -function dfs(list) { - let eps = 0.0001 - if (list.length === 1) { - if (Math.abs(list[0] - 24) < eps) { - return true - } - return false - } - let n = list.length - for (let i = 0; i < n; i++) { - for (let j = i + 1; j < n; j++) { - const next = new Array(n - 1) - for (let k = 0, index = 0; k < n; k++) { - if (k !== i && k !== j) next[index++] = list[k] - } - let d1 = list[i], - d2 = list[j] - const dirs = [d1 + d2, d1 - d2, d2 - d1, d2 * d1] - if (d1 > eps) dirs.push(d2 / d1) - if (d2 > eps) dirs.push(d1 / d2) - for (let dir of dirs) { - next[n - 2] = dir - if (dfs(next)) return true - } - } - } - return false -} - - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -const judgePoint24 = function(nums) { - return dfs(nums); -}; - -function dfs(list) { - if (list.length === 1) { - if (Math.abs(list[0] - 24) < 0.001) { - return true; - } - return false; - } - for (let i = 0; i < list.length; i++) { - for (let j = i + 1; j < list.length; j++) { - for (let c of compute(list[i], list[j])) { - let nextRound = []; - nextRound.push(c); - for (let k = 0; k < list.length; k++) { - if (k === j || k === i) continue; - nextRound.push(list[k]); - } - if (dfs(nextRound)) return true; - } - } - } - return false; -} - -function compute(a, b) { - return [a + b, a - b, b - a, a * b, a / b, b / a]; -} diff --git a/679.24-game.js b/679.24-game.js new file mode 100644 index 00000000..95c97cc2 --- /dev/null +++ b/679.24-game.js @@ -0,0 +1,38 @@ +/** + * @param {number[]} nums + * @return {boolean} + */ +const judgePoint24 = function(nums) { + return dfs(nums) +} + +function dfs(list) { + let eps = 0.0001 + if (list.length === 1) { + if (Math.abs(list[0] - 24) < eps) { + return true + } + return false + } + let n = list.length + for (let i = 0; i < n; i++) { + for (let j = i + 1; j < n; j++) { + const next = new Array(n - 1) + for (let k = 0, index = 0; k < n; k++) { + if (k !== i && k !== j) next[index++] = list[k] + } + let d1 = list[i], + d2 = list[j] + const dirs = [d1 + d2, d1 - d2, d2 - d1, d2 * d1] + if (d1 > eps) dirs.push(d2 / d1) + if (d2 > eps) dirs.push(d1 / d2) + for (let dir of dirs) { + next[n - 2] = dir + if (dfs(next)) return true + } + } + } + return false +} + + diff --git a/68-text-justification.js b/68-text-justification.js deleted file mode 100755 index 3f26e4a1..00000000 --- a/68-text-justification.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @param {string[]} words - * @param {number} maxWidth - * @return {string[]} - */ -const fullJustify = function(words, maxWidth) { - const res = [] - let curRow = [] - let numOfChars = 0 - - for (let w of words) { - if (numOfChars + w.length + curRow.length > maxWidth) { - for(let i = 0; i < maxWidth - numOfChars; i++) { - if(curRow.length === 1) { - curRow[0] += ' ' - } else { - curRow[i % (curRow.length - 1)] += ' ' - } - } - res.push(curRow.join('')) - curRow = [] - numOfChars = 0 - } - curRow.push(w) - numOfChars += w.length - } - - const numOfSpace = maxWidth - numOfChars - (curRow.length - 1) - let tail = '' - for(let i = 0; i < numOfSpace; i++) tail += ' ' - res.push(curRow.join(' ') + tail) - - return res -}; - -// another - -/** - * @param {string[]} words - * @param {number} L - * @returns {string[]} - */ -const fullJustify = function(words, L) { - const res = [""]; - if (words.length === 0 || L === 0) { - return res; - } else { - res.shift(); - for (let i = 0, k, l; i < words.length; i += k) { - for ( - k = l = 0; - i + k < words.length && l + words[i + k].length <= L - k; - k++ - ) { - l += words[i + k].length; - } - let tmp = words[i]; - for (j = 0; j < k - 1; j++) { - if (i + k >= words.length) { - tmp += " "; - } else { - // for (i = 0; i < ((L - l) / (k - 1) + (j < (L - l) % (k - 1))) - 1; i++) { - // tmp += ' '; - // } - tmp += Array( - parseInt((L - l) / (k - 1) + (j < (L - l) % (k - 1))) + 1 - ).join(" "); - } - // tmp += (L - l) / (k - 1) + (j < (L - l) % (k - 1)) + ' '; - tmp += words[i + j + 1]; - } - // for (i = 0; i < (L - tmp.length); i++) { - // tmp += ' ' - // } - tmp += Array(parseInt(L - tmp.length) + 1).join(" "); - // tmp += L - tmp.length + ' '; - res.push(tmp); - } - return res; - } -}; diff --git a/68.text-justification.js b/68.text-justification.js new file mode 100644 index 00000000..e38a4d85 --- /dev/null +++ b/68.text-justification.js @@ -0,0 +1,35 @@ +/** + * @param {string[]} words + * @param {number} maxWidth + * @return {string[]} + */ +const fullJustify = function(words, maxWidth) { + const res = [] + let curRow = [] + let numOfChars = 0 + + for (let w of words) { + if (numOfChars + w.length + curRow.length > maxWidth) { + for(let i = 0; i < maxWidth - numOfChars; i++) { + if(curRow.length === 1) { + curRow[0] += ' ' + } else { + curRow[i % (curRow.length - 1)] += ' ' + } + } + res.push(curRow.join('')) + curRow = [] + numOfChars = 0 + } + curRow.push(w) + numOfChars += w.length + } + + const numOfSpace = maxWidth - numOfChars - (curRow.length - 1) + let tail = '' + for(let i = 0; i < numOfSpace; i++) tail += ' ' + res.push(curRow.join(' ') + tail) + + return res +}; + diff --git a/680-valid-palindrome-ii.js b/680.valid-palindrome-ii.js similarity index 100% rename from 680-valid-palindrome-ii.js rename to 680.valid-palindrome-ii.js diff --git a/681-next-closest-time.js b/681.next-closest-time.js similarity index 100% rename from 681-next-closest-time.js rename to 681.next-closest-time.js diff --git a/682-baseball-game.js b/682-baseball-game.js deleted file mode 100755 index 5357131d..00000000 --- a/682-baseball-game.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @param {string[]} ops - * @return {number} - */ -const calPoints = function(ops) { - const opArr = ["C", "D", "+"]; - const arr = []; - ops.forEach((el, idx) => { - const item = { - value: 0, - valid: true - }; - switch (el) { - case "C": - findValid(arr, idx, 1).forEach(el => { - el.value = 0; - el.valid = false; - }); - item.valid = false; - break; - case "D": - item.value = findValid(arr, idx, 1)[0].value * 2; - break; - case "+": - item.value = findValid(arr, idx, 2).reduce( - (ac, ele) => ac + ele.value, - 0 - ); - break; - default: - item.value = +el; - break; - } - arr.push(item); - }); - return arr.reduce((ac, el) => ac + el.value, 0); -}; - -function findValid(arr, idx, backStep) { - const res = []; - while (backStep > 0 && idx - 1 >= 0) { - if (arr[idx - 1].valid === true) { - backStep -= 1; - res.push(arr[idx - 1]); - } - idx -= 1; - } - return res; -} - -console.log(calPoints(["5", "2", "C", "D", "+"])); -console.log(calPoints(["5", "-2", "4", "C", "D", "9", "+", "+"])); diff --git a/682.baseball-game.js b/682.baseball-game.js new file mode 100644 index 00000000..90a1d3e8 --- /dev/null +++ b/682.baseball-game.js @@ -0,0 +1,52 @@ +/** + * @param {string[]} ops + * @return {number} + */ +const calPoints = function(ops) { + const opArr = ["C", "D", "+"]; + const arr = []; + ops.forEach((el, idx) => { + const item = { + value: 0, + valid: true + }; + switch (el) { + case "C": + findValid(arr, idx, 1).forEach(el => { + el.value = 0; + el.valid = false; + }); + item.valid = false; + break; + case "D": + item.value = findValid(arr, idx, 1)[0].value * 2; + break; + case "+": + item.value = findValid(arr, idx, 2).reduce( + (ac, ele) => ac + ele.value, + 0 + ); + break; + default: + item.value = +el; + break; + } + arr.push(item); + }); + return arr.reduce((ac, el) => ac + el.value, 0); +}; + +function findValid(arr, idx, backStep) { + const res = []; + while (backStep > 0 && idx - 1 >= 0) { + if (arr[idx - 1].valid === true) { + backStep -= 1; + res.push(arr[idx - 1]); + } + idx -= 1; + } + return res; +} + +console.log(calPoints(["5", "2", "C", "D", "+"])); +console.log(calPoints(["5", "-2", "4", "C", "D", "9", "+", "+"])); diff --git a/683-k-empty-slots.js b/683.k-empty-slots.js similarity index 100% rename from 683-k-empty-slots.js rename to 683.k-empty-slots.js diff --git a/684-redundant-connection.js b/684.redundant-connection.js similarity index 100% rename from 684-redundant-connection.js rename to 684.redundant-connection.js diff --git a/685-redundant-connection-ii.js b/685.redundant-connection-ii.js similarity index 100% rename from 685-redundant-connection-ii.js rename to 685.redundant-connection-ii.js diff --git a/686-repeated-string-match.js b/686.repeated-string-match.js similarity index 100% rename from 686-repeated-string-match.js rename to 686.repeated-string-match.js diff --git a/687-longest-univalue-path.js b/687-longest-univalue-path.js deleted file mode 100644 index 123bfd54..00000000 --- a/687-longest-univalue-path.js +++ /dev/null @@ -1,70 +0,0 @@ - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const longestUnivaluePath = function(root) { - let res = 0 - dfs(root) - return res - - function dfs(node) { - if(node == null) return 0 - let left = dfs(node.left), right = dfs(node.right) - if(node.left && node.left.val === node.val) left++ - else left = 0 - - if(node.right && node.right.val === node.val) right++ - else right = 0 - - res = Math.max(res, left + right) - return Math.max(left, right) - } -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const getCount = function(root, longest) { - if (!root) { - return 0; - } - let leftCount = getCount(root.left, longest); - let rightCount = getCount(root.right, longest); - if (root.left && root.left.val === root.val) { - leftCount++; - } else { - leftCount = 0; - } - if (root.right && root.right.val === root.val) { - rightCount++; - } else { - rightCount = 0; - } - longest.max = Math.max(longest.max, leftCount + rightCount); - return Math.max(leftCount, rightCount); -}; - -const longestUnivaluePath = function(root) { - let longest = { max: 0 }; - getCount(root, longest); - return longest.max; -}; diff --git a/687.longest-univalue-path.js b/687.longest-univalue-path.js new file mode 100644 index 00000000..8d2c48a2 --- /dev/null +++ b/687.longest-univalue-path.js @@ -0,0 +1,32 @@ + +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +const longestUnivaluePath = function(root) { + let res = 0 + dfs(root) + return res + + function dfs(node) { + if(node == null) return 0 + let left = dfs(node.left), right = dfs(node.right) + if(node.left && node.left.val === node.val) left++ + else left = 0 + + if(node.right && node.right.val === node.val) right++ + else right = 0 + + res = Math.max(res, left + right) + return Math.max(left, right) + } +}; + diff --git a/688-knight-probability-in-chessboard.js b/688.knight-probability-in-chessboard.js similarity index 100% rename from 688-knight-probability-in-chessboard.js rename to 688.knight-probability-in-chessboard.js diff --git a/689-maximum-sum-of-3-non-overlapping-subarrays.js b/689.maximum-sum-of-3-non-overlapping-subarrays.js similarity index 100% rename from 689-maximum-sum-of-3-non-overlapping-subarrays.js rename to 689.maximum-sum-of-3-non-overlapping-subarrays.js diff --git a/69-sqrt(x).js b/69-sqrt(x).js deleted file mode 100755 index 3e3da29d..00000000 --- a/69-sqrt(x).js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @param {number} x - * @return {number} - */ -const mySqrt = function(x) { - let left = 0, right = x; - while (left < right) { - let mid = right - ((right - left) >> 1); - if (mid * mid > x) { - right = mid - 1; - } else { - left = mid; - } - } - return left; -}; - -// another - -/** - * @param {number} x - * @return {number} - */ -const mySqrt = function(x) { - r = x; - while (r * r > x) r = ((r + x / r) / 2) | 0; - return r; -}; - -// another - -/** - * @param {number} x - * @return {number} - */ -const mySqrt = function(x) { - let l = 1, r = x - if(x === 0) return 0 - while(true) { - let mid = l + ((r - l) >> 1) - if(mid * mid > x) r = mid - 1 - else { - if((mid + 1) * (mid + 1) > x) return mid - l = mid + 1 - } - } -}; diff --git a/69.sqrt(x).js b/69.sqrt(x).js new file mode 100644 index 00000000..b1e8913e --- /dev/null +++ b/69.sqrt(x).js @@ -0,0 +1,17 @@ +/** + * @param {number} x + * @return {number} + */ +const mySqrt = function(x) { + let left = 0, right = x; + while (left < right) { + let mid = right - ((right - left) >> 1); + if (mid * mid > x) { + right = mid - 1; + } else { + left = mid; + } + } + return left; +}; + diff --git a/690-employee-importance.js b/690.employee-importance.js similarity index 100% rename from 690-employee-importance.js rename to 690.employee-importance.js diff --git a/691-stickers-to-spell-word.js b/691-stickers-to-spell-word.js deleted file mode 100644 index 8c0574c5..00000000 --- a/691-stickers-to-spell-word.js +++ /dev/null @@ -1,94 +0,0 @@ -/** - * @param {string[]} stickers - * @param {string} target - * @return {number} - */ -const minStickers = function (stickers, target) { - const n = stickers.length - const m = target.length - const limit = 1 << m - const dp = Array(limit).fill(Infinity) - dp[0] = 0 - for (let i = 0; i < limit; i++) { - if (dp[i] === Infinity) continue - for (const sticker of stickers) { - let stat = i - for (const ch of sticker) { - for (let j = 0; j < m; j++) { - if (target[j] === ch && ((stat >> j) & 1) === 0) { - stat |= (1 << j) - break - } - } - } - dp[stat] = Math.min(dp[stat], dp[i] + 1) - } - } - - return dp[limit - 1] === Infinity ? -1 : dp[limit - 1] -} - - -// another - - -/** - * @param {string[]} stickers - * @param {string} target - * @return {number} - */ -const minStickers = function(stickers, target) { - const isEqual = (arr1, arr2) => { - for (let i = 0; i < arr1.length; ++i) if (arr1[i] !== arr2[i]) return false - return true - } - - const minus = (arr1, arr2) => { - let res = [] - for (let i = 0; i < arr1.length; ++i) - res[i] = arr1[i] <= 0 ? arr1[i] : arr1[i] - arr2[i] - return res - } - - const isAllNonpositive = arr => { - return arr.every(item => item <= 0) - } - - const getString = arr => { - return arr.reduce((acc, cur, idx) => { - if (cur > 0) return acc + String.fromCharCode(idx + 97).repeat(cur) - else return acc - }, '') - } - - let ss = stickers.map(word => { - let tmp = new Array(26).fill(0) - for (let i = 0; i < word.length; ++i) tmp[word.charCodeAt(i) - 97]++ - return tmp - }) - let root = new Array(26).fill(0) - for (let i = 0; i < target.length; ++i) root[target.charCodeAt(i) - 97]++ - let cache = new Set() - let queue = [root] - let size = 0, - level = 0, - front = null - while (queue.length !== 0) { - size = queue.length - while (size--) { - front = queue.shift() - for (let w of ss) { - let t = minus(front, w) - let str = getString(t) - if (isEqual(t, front) || cache.has(str)) continue - if (isAllNonpositive(t)) return level + 1 - else { - queue.push(t) - cache.add(str) - } - } - } - level++ - } - return -1 -} diff --git a/691.stickers-to-spell-word.js b/691.stickers-to-spell-word.js new file mode 100644 index 00000000..35a9d800 --- /dev/null +++ b/691.stickers-to-spell-word.js @@ -0,0 +1,31 @@ +/** + * @param {string[]} stickers + * @param {string} target + * @return {number} + */ +const minStickers = function (stickers, target) { + const n = stickers.length + const m = target.length + const limit = 1 << m + const dp = Array(limit).fill(Infinity) + dp[0] = 0 + for (let i = 0; i < limit; i++) { + if (dp[i] === Infinity) continue + for (const sticker of stickers) { + let stat = i + for (const ch of sticker) { + for (let j = 0; j < m; j++) { + if (target[j] === ch && ((stat >> j) & 1) === 0) { + stat |= (1 << j) + break + } + } + } + dp[stat] = Math.min(dp[stat], dp[i] + 1) + } + } + + return dp[limit - 1] === Infinity ? -1 : dp[limit - 1] +} + + diff --git a/692-top-k-frequent-words.js b/692.top-k-frequent-words.js similarity index 100% rename from 692-top-k-frequent-words.js rename to 692.top-k-frequent-words.js diff --git a/693-binary-number-with-alternating-bits.js b/693.binary-number-with-alternating-bits.js old mode 100755 new mode 100644 similarity index 100% rename from 693-binary-number-with-alternating-bits.js rename to 693.binary-number-with-alternating-bits.js diff --git a/694-number-of-distinct-islands.js b/694-number-of-distinct-islands.js deleted file mode 100644 index 1472a640..00000000 --- a/694-number-of-distinct-islands.js +++ /dev/null @@ -1,105 +0,0 @@ -/** - -Given a non-empty 2D array grid of 0's and 1's, -an island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) -You may assume all four edges of the grid are surrounded by water. - -Count the number of distinct islands. An island is considered to -be the same as another if and only if one island can -be translated (and not rotated or reflected) to equal the other. - -Example 1: -11000 -11000 -00011 -00011 - -Given the above grid map, return 1. - -Example 2: -11011 -10000 -00001 -11011 - -Given the above grid map, return 3. - -Notice that: -11 -1 -and - 1 -11 -are considered different island shapes, because we do not consider reflection / rotation. -Note: The length of each dimension in the given grid does not exceed 50. - -*/ - -/** - * @param {number[][]} grid - * @return {number} - */ -const numDistinctIslands = function(grid) { - const set = new Set() - for (let i = 0; i < grid.length; i++) { - for (let j = 0; j < grid[0].length; j++) { - if (grid[i][j] === 1) { - const tempArr = [] - helper(i, j, grid, tempArr) - const x = tempArr[0][0] - 0 - const y = tempArr[0][1] - 0 - let str = '' - for (let k = 0; k < tempArr.length; k++) { - str += '#' + (tempArr[k][0] - x) + '#' + (tempArr[k][1] - y) - } - set.add(str) - } - } - } - return set.size -} - -function helper(i, j, arr, tempArr) { - tempArr.push([i, j]) - arr[i][j] = 0 - - if (arr[i][j - 1] === 1) helper(i, j - 1, arr, tempArr) - if (arr[i][j + 1] === 1) helper(i, j + 1, arr, tempArr) - if (arr[i - 1]) { - if (arr[i - 1][j] === 1) helper(i - 1, j, arr, tempArr) - } - if (arr[i + 1]) { - if (arr[i + 1][j] === 1) helper(i + 1, j, arr, tempArr) - } -} - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -const numDistinctIslands = function(grid) { - if (!grid.length) return 0; - const pattern = new Set(); - grid.forEach((rows, row) => { - rows.forEach((val, col) => { - if (val === 1) pattern.add(depthFirst(grid, row, col, "o")); - }); - }); - return pattern.size; -}; - -function depthFirst(graph, row, col, di) { - if (graph[row] && graph[row][col]) { - graph[row][col] = 0; - let p = - di + - depthFirst(graph, row + 1, col, "d") + - depthFirst(graph, row - 1, col, "u") + - depthFirst(graph, row, col + 1, "r") + - depthFirst(graph, row, col - 1, "l") + - "b"; - return p; - } else return ""; -} diff --git a/694.number-of-distinct-islands.js b/694.number-of-distinct-islands.js new file mode 100644 index 00000000..d350780f --- /dev/null +++ b/694.number-of-distinct-islands.js @@ -0,0 +1,75 @@ +/** + +Given a non-empty 2D array grid of 0's and 1's, +an island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) +You may assume all four edges of the grid are surrounded by water. + +Count the number of distinct islands. An island is considered to +be the same as another if and only if one island can +be translated (and not rotated or reflected) to equal the other. + +Example 1: +11000 +11000 +00011 +00011 + +Given the above grid map, return 1. + +Example 2: +11011 +10000 +00001 +11011 + +Given the above grid map, return 3. + +Notice that: +11 +1 +and + 1 +11 +are considered different island shapes, because we do not consider reflection / rotation. +Note: The length of each dimension in the given grid does not exceed 50. + +*/ + +/** + * @param {number[][]} grid + * @return {number} + */ +const numDistinctIslands = function(grid) { + const set = new Set() + for (let i = 0; i < grid.length; i++) { + for (let j = 0; j < grid[0].length; j++) { + if (grid[i][j] === 1) { + const tempArr = [] + helper(i, j, grid, tempArr) + const x = tempArr[0][0] - 0 + const y = tempArr[0][1] - 0 + let str = '' + for (let k = 0; k < tempArr.length; k++) { + str += '#' + (tempArr[k][0] - x) + '#' + (tempArr[k][1] - y) + } + set.add(str) + } + } + } + return set.size +} + +function helper(i, j, arr, tempArr) { + tempArr.push([i, j]) + arr[i][j] = 0 + + if (arr[i][j - 1] === 1) helper(i, j - 1, arr, tempArr) + if (arr[i][j + 1] === 1) helper(i, j + 1, arr, tempArr) + if (arr[i - 1]) { + if (arr[i - 1][j] === 1) helper(i - 1, j, arr, tempArr) + } + if (arr[i + 1]) { + if (arr[i + 1][j] === 1) helper(i + 1, j, arr, tempArr) + } +} + diff --git a/695-max-area-of-island.js b/695.max-area-of-island.js similarity index 100% rename from 695-max-area-of-island.js rename to 695.max-area-of-island.js diff --git a/697-degree-of-an-array.js b/697-degree-of-an-array.js deleted file mode 100755 index 9831e67f..00000000 --- a/697-degree-of-an-array.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const findShortestSubArray = function(nums) { - const left = {}; - const right = {}; - const count = {}; - - for (let i = 0; i < nums.length; i++) { - if (!left.hasOwnProperty(nums[i])) { - left[nums[i]] = i; - } - right[nums[i]] = i; - count[nums[i]] = count[nums[i]] ? count[nums[i]] + 1 : 1; - } - const degree = Math.max(...Object.keys(count).map(el => count[el])); - let res = nums.length; - for (let el in count) { - if (count.hasOwnProperty(el) && count[el] === degree) { - res = Math.min(res, right[el] - left[el] + 1); - } - } - - return res; -}; diff --git a/697.degree-of-an-array.js b/697.degree-of-an-array.js new file mode 100644 index 00000000..b498559a --- /dev/null +++ b/697.degree-of-an-array.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const findShortestSubArray = function(nums) { + const left = {}; + const right = {}; + const count = {}; + + for (let i = 0; i < nums.length; i++) { + if (!left.hasOwnProperty(nums[i])) { + left[nums[i]] = i; + } + right[nums[i]] = i; + count[nums[i]] = count[nums[i]] ? count[nums[i]] + 1 : 1; + } + const degree = Math.max(...Object.keys(count).map(el => count[el])); + let res = nums.length; + for (let el in count) { + if (count.hasOwnProperty(el) && count[el] === degree) { + res = Math.min(res, right[el] - left[el] + 1); + } + } + + return res; +}; diff --git a/698-partition-to-k-equal-sum-subsets.js b/698.partition-to-k-equal-sum-subsets.js similarity index 100% rename from 698-partition-to-k-equal-sum-subsets.js rename to 698.partition-to-k-equal-sum-subsets.js diff --git a/699-falling-squares.js b/699-falling-squares.js deleted file mode 100644 index aeebee63..00000000 --- a/699-falling-squares.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * @param {number[][]} positions - * @return {number[]} - */ -class Interval { - constructor(start, end, height) { - this.start = start - this.end = end - this.height = height - } -} -function fallingSquares(positions) { - const intervals = [] - const res = [] - let h = 0 - for (let pos of positions) { - let cur = new Interval(pos[0], pos[0] + pos[1], pos[1]) - h = Math.max(h, getHeight(intervals, cur)) - res.push(h) - } - console.log(intervals) - return res -} -function getHeight(intervals, cur) { - let preMaxHeight = 0 - for (let i of intervals) { - if (i.end <= cur.start) continue - if (i.start >= cur.end) continue - preMaxHeight = Math.max(preMaxHeight, i.height) - } - cur.height += preMaxHeight - intervals.push(cur) - return cur.height -} - -// another - -/** - * @param {number[][]} positions - * @return {number[]} - */ -var fallingSquares = function (positions) { - let ranges = [{ left: 0, height: 0, right: 1e8 + 1e6 }], rtn = [], max = 0 - - outer: - for (let [left, length] of positions) { - let curHeight = 0, startI = -1, right = left + length, newRanges = [] - for (let i = 0; i < ranges.length; i++) { - let range = ranges[i] - if (left < range.right && startI == -1) { - startI = i - // left part - if (left != range.left) { - newRanges.push({ - left: range.left, - height: range.height, - right: left - }) - } - } - if (startI != -1) { - curHeight = Math.max(curHeight, range.height) - } - if (right <= range.right) { - // added part - let newHeight = length + curHeight - newRanges.push({ - left, - height: newHeight, - right, - }) - // right part - if (right != range.right) { - newRanges.push({ - left: right, - height: range.height, - right: range.right, - }) - } - max = Math.max(newHeight, max) - rtn.push(max) - // replace - ranges.splice(startI, i - startI + 1, ...newRanges) - continue outer - } - } - } - return rtn -}; diff --git a/699.falling-squares.js b/699.falling-squares.js new file mode 100644 index 00000000..2fd806a0 --- /dev/null +++ b/699.falling-squares.js @@ -0,0 +1,35 @@ +/** + * @param {number[][]} positions + * @return {number[]} + */ +class Interval { + constructor(start, end, height) { + this.start = start + this.end = end + this.height = height + } +} +function fallingSquares(positions) { + const intervals = [] + const res = [] + let h = 0 + for (let pos of positions) { + let cur = new Interval(pos[0], pos[0] + pos[1], pos[1]) + h = Math.max(h, getHeight(intervals, cur)) + res.push(h) + } + console.log(intervals) + return res +} +function getHeight(intervals, cur) { + let preMaxHeight = 0 + for (let i of intervals) { + if (i.end <= cur.start) continue + if (i.start >= cur.end) continue + preMaxHeight = Math.max(preMaxHeight, i.height) + } + cur.height += preMaxHeight + intervals.push(cur) + return cur.height +} + diff --git a/7-reverse-integer.js b/7-reverse-integer.js deleted file mode 100755 index 4a2fef60..00000000 --- a/7-reverse-integer.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {number} x - * @return {number} - */ -const reverse = function (x) { - let res = 0, tail, newResult - const low = -Math.pow(2, 31), high = Math.pow(2, 31) - while(x !== 0) { - tail = x % 10 - newResult = res * 10 + tail - // if((newResult - tail) / 10 !== res) return 0 - if(newResult < low || newResult >= high) return 0 - res = newResult - x = ~~(x / 10) - } - - return res -}; - -// another - - -/** - * @param {number} x - * @return {number} - */ -const reverse = function(num) { - let negative = false; - let result = 0; - if (num < 0) { - negative = true; - num = Math.abs(num); - } - while (num > 0) { - mod = num % 10; // mod = 3 // mod = 2 // mod - num = Math.floor(num / 10); // num = 12 // num = 1 - result = result * 10 + mod; // 0 = 0 * 10 + 3 = 0 + 3 = 3 // 3 = 3 * 10 + 2 = 30 + 2 = 32 - } - if (result > 2147483647) return 0; - if (negative) return result * -1; - return result; -}; diff --git a/7.reverse-integer.js b/7.reverse-integer.js new file mode 100644 index 00000000..e694c15c --- /dev/null +++ b/7.reverse-integer.js @@ -0,0 +1,19 @@ +/** + * @param {number} x + * @return {number} + */ +const reverse = function (x) { + let res = 0, tail, newResult + const low = -Math.pow(2, 31), high = Math.pow(2, 31) + while(x !== 0) { + tail = x % 10 + newResult = res * 10 + tail + // if((newResult - tail) / 10 !== res) return 0 + if(newResult < low || newResult >= high) return 0 + res = newResult + x = ~~(x / 10) + } + + return res +}; + diff --git a/70-climbing-stairs.js b/70-climbing-stairs.js deleted file mode 100755 index a52c4c63..00000000 --- a/70-climbing-stairs.js +++ /dev/null @@ -1,47 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const climbStairs = function(n) { - const hash = {}; - return single(n, hash); -}; - -function single(i, hash) { - if (hash.hasOwnProperty(i)) { - return hash[i]; - } - if (i === 1) { - hash[1] = 1; - return 1; - } - if (i === 2) { - hash[2] = 2; - return 2; - } - hash[i] = single(i - 1, hash) + single(i - 2, hash); - return hash[i]; -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const climbStairs = function (n) { - const dp = new Array(n + 1).fill(0) - if (n === 1) { - return 1 - } - if (n === 2) { - return 2 - } - dp[0] = 0 - dp[1] = 1 - dp[2] = 2 - for (let i = 3; i <= n; i++) { - dp[i] = dp[i - 1] + dp[i - 2] - } - return dp[n] -} diff --git a/70.climbing-stairs.js b/70.climbing-stairs.js new file mode 100644 index 00000000..01e7205e --- /dev/null +++ b/70.climbing-stairs.js @@ -0,0 +1,25 @@ +/** + * @param {number} n + * @return {number} + */ +const climbStairs = function(n) { + const hash = {}; + return single(n, hash); +}; + +function single(i, hash) { + if (hash.hasOwnProperty(i)) { + return hash[i]; + } + if (i === 1) { + hash[1] = 1; + return 1; + } + if (i === 2) { + hash[2] = 2; + return 2; + } + hash[i] = single(i - 1, hash) + single(i - 2, hash); + return hash[i]; +} + diff --git a/700-search-in-a-binary-search-tree.js b/700-search-in-a-binary-search-tree.js deleted file mode 100755 index 7b4b24df..00000000 --- a/700-search-in-a-binary-search-tree.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @param {number} val - * @return {TreeNode} - */ -const searchBST = function (root, val) { - if (!root || root.val === val) { - return root - } - return root.val < val ? searchBST(root.right, val) : searchBST(root.left, val) -} diff --git a/700.search-in-a-binary-search-tree.js b/700.search-in-a-binary-search-tree.js new file mode 100644 index 00000000..6e53066d --- /dev/null +++ b/700.search-in-a-binary-search-tree.js @@ -0,0 +1,19 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} val + * @return {TreeNode} + */ +const searchBST = function (root, val) { + if (!root || root.val === val) { + return root + } + return root.val < val ? searchBST(root.right, val) : searchBST(root.left, val) +} diff --git a/701-insert-into-a-binary-search-tree.js b/701-insert-into-a-binary-search-tree.js deleted file mode 100644 index f6b8a655..00000000 --- a/701-insert-into-a-binary-search-tree.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {number} val - * @return {TreeNode} - */ -const insertIntoBST = function(root, val) { - if(root == null) return new TreeNode(val); - let cur = root; - while(true) { - if(cur.val <= val) { - if(cur.right != null) cur = cur.right; - else { - cur.right = new TreeNode(val); - break; - } - } else { - if(cur.left != null) cur = cur.left; - else { - cur.left = new TreeNode(val); - break; - } - } - } - return root; -}; - -// another - -const insertIntoBST = function(root, val) { - if (root == null) { - return new TreeNode(val); - } - if (root.val > val) { - root.left = insertIntoBST(root.left, val); - } else { - root.right = insertIntoBST(root.right, val); - } - return root; -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @param {number} val - * @return {TreeNode} - */ -const insertIntoBST = function(root, val) { - if(root == null) return new TreeNode(val) - if(val < root.val) root.left = insertIntoBST(root.left, val) - else if(val > root.val) root.right = insertIntoBST(root.right, val) - return root -}; diff --git a/701.insert-into-a-binary-search-tree.js b/701.insert-into-a-binary-search-tree.js new file mode 100644 index 00000000..89da9bda --- /dev/null +++ b/701.insert-into-a-binary-search-tree.js @@ -0,0 +1,33 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {number} val + * @return {TreeNode} + */ +const insertIntoBST = function(root, val) { + if(root == null) return new TreeNode(val); + let cur = root; + while(true) { + if(cur.val <= val) { + if(cur.right != null) cur = cur.right; + else { + cur.right = new TreeNode(val); + break; + } + } else { + if(cur.left != null) cur = cur.left; + else { + cur.left = new TreeNode(val); + break; + } + } + } + return root; +}; + diff --git a/702-search-in-a-sorted-array-of-unknown-size.js b/702.search-in-a-sorted-array-of-unknown-size.js similarity index 100% rename from 702-search-in-a-sorted-array-of-unknown-size.js rename to 702.search-in-a-sorted-array-of-unknown-size.js diff --git a/703-kth-largest-element-in-a-stream.js b/703.kth-largest-element-in-a-stream.js similarity index 100% rename from 703-kth-largest-element-in-a-stream.js rename to 703.kth-largest-element-in-a-stream.js diff --git a/704-binary-search.js b/704.binary-search.js similarity index 100% rename from 704-binary-search.js rename to 704.binary-search.js diff --git a/705-design-hashset.js b/705.design-hashset.js similarity index 100% rename from 705-design-hashset.js rename to 705.design-hashset.js diff --git a/706-design-hashmap.js b/706.design-hashmap.js similarity index 100% rename from 706-design-hashmap.js rename to 706.design-hashmap.js diff --git a/707-design-linked-list.js b/707-design-linked-list.js deleted file mode 100644 index 081e9b95..00000000 --- a/707-design-linked-list.js +++ /dev/null @@ -1,200 +0,0 @@ -/** - * Initialize your data structure here. - */ -var MyLinkedList = function() { - this.arr = [] -} - -/** - * Get the value of the index-th node in the linked list. If the index is invalid, return -1. - * @param {number} index - * @return {number} - */ -MyLinkedList.prototype.get = function(index) { - if (this.arr[index] !== undefined) { - return this.arr[index] - } else { - return -1 - } -} - -/** - * Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. - * @param {number} val - * @return {void} - */ -MyLinkedList.prototype.addAtHead = function(val) { - this.arr.unshift(val) -} - -/** - * Append a node of value val to the last element of the linked list. - * @param {number} val - * @return {void} - */ -MyLinkedList.prototype.addAtTail = function(val) { - this.arr.push(val) -} - -/** - * Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. - * @param {number} index - * @param {number} val - * @return {void} - */ -MyLinkedList.prototype.addAtIndex = function(index, val) { - if (this.arr.length >= index) { - this.arr.splice(index, 0, val) - } - if (index < 0) { - this.arr.unshift(val) - } -} - -/** - * Delete the index-th node in the linked list, if the index is valid. - * @param {number} index - * @return {void} - */ -MyLinkedList.prototype.deleteAtIndex = function(index) { - if (index >= 0 && index < this.arr.length) { - this.arr.splice(index, 1) - } -} - -/** - * Your MyLinkedList object will be instantiated and called as such: - * var obj = new MyLinkedList() - * var param_1 = obj.get(index) - * obj.addAtHead(val) - * obj.addAtTail(val) - * obj.addAtIndex(index,val) - * obj.deleteAtIndex(index) - */ - -// another - -/** - * Initialize your data structure here. - */ -var MyLinkedList = function(val) { - this.head = null - this.tail = null - this.size = 0 -} - -// Create Node class to store node data as an 'object' -var Node = function(val) { - this.val = val - this.next = null -} - -/** - * Get the value of the index-th node in the linked list. If the index is invalid, return -1. - * @param {number} index - * @return {number} - */ -MyLinkedList.prototype.get = function(index) { - if (index < 0 || this.size === 0 || index > this.size - 1) return -1 - let curr = this.head - let i = 0 - while (i < index) { - curr = curr.next - i += 1 - } - return curr.val -} - -/** - * Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. - * @param {number} val - * @return {void} - */ -MyLinkedList.prototype.addAtHead = function(val) { - let newNode = new Node(val) - if (this.head === null) { - this.head = newNode - this.tail = newNode - } else { - newNode.next = this.head - this.head = newNode - } - this.size++ - return this -} - -/** - * Append a node of value val to the last element of the linked list. - * @param {number} val - * @return {void} - */ -MyLinkedList.prototype.addAtTail = function(val) { - const newNode = new Node(val) - if (this.head === null) { - this.head = newNode - this.tail = newNode - } else { - this.tail.next = newNode - this.tail = newNode - } - this.size++ - return this -} - -/** - * Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. - * @param {number} index - * @param {number} val - * @return {void} - */ -MyLinkedList.prototype.addAtIndex = function(index, val) { - if (index > this.size) return - if (index <= 0) return this.addAtHead(val) - if (index === this.size) return this.addAtTail(val) - let newNode = new Node(val) - let i = 0 - let curr = this.head - while (i < index - 1) { - curr = curr.next - i++ - } - newNode.next = curr.next ? curr.next : null - curr.next = newNode - this.size++ - return this -} - -/** - * Delete the index-th node in the linked list, if the index is valid. - * @param {number} index - * @return {void} - */ -MyLinkedList.prototype.deleteAtIndex = function(index) { - if (index >= this.size || index < 0) return - if (index === 0) { - this.head = this.head.next - this.size-- - return this - } - let curr = this.head - let i = 0 - while (i < index - 1) { - i++ - curr = curr.next - } - curr.next = curr.next.next ? curr.next.next : null - if (!curr.next) this.tail = curr - this.size-- - return this -} - -/** - * Your MyLinkedList object will be instantiated and called as such: - * var obj = new MyLinkedList() - * var param_1 = obj.get(index) - * obj.addAtHead(val) - * obj.addAtTail(val) - * obj.addAtIndex(index,val) - * obj.deleteAtIndex(index) - */ - diff --git a/707.design-linked-list.js b/707.design-linked-list.js new file mode 100644 index 00000000..639485e3 --- /dev/null +++ b/707.design-linked-list.js @@ -0,0 +1,74 @@ +/** + * Initialize your data structure here. + */ +var MyLinkedList = function() { + this.arr = [] +} + +/** + * Get the value of the index-th node in the linked list. If the index is invalid, return -1. + * @param {number} index + * @return {number} + */ +MyLinkedList.prototype.get = function(index) { + if (this.arr[index] !== undefined) { + return this.arr[index] + } else { + return -1 + } +} + +/** + * Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. + * @param {number} val + * @return {void} + */ +MyLinkedList.prototype.addAtHead = function(val) { + this.arr.unshift(val) +} + +/** + * Append a node of value val to the last element of the linked list. + * @param {number} val + * @return {void} + */ +MyLinkedList.prototype.addAtTail = function(val) { + this.arr.push(val) +} + +/** + * Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. + * @param {number} index + * @param {number} val + * @return {void} + */ +MyLinkedList.prototype.addAtIndex = function(index, val) { + if (this.arr.length >= index) { + this.arr.splice(index, 0, val) + } + if (index < 0) { + this.arr.unshift(val) + } +} + +/** + * Delete the index-th node in the linked list, if the index is valid. + * @param {number} index + * @return {void} + */ +MyLinkedList.prototype.deleteAtIndex = function(index) { + if (index >= 0 && index < this.arr.length) { + this.arr.splice(index, 1) + } +} + +/** + * Your MyLinkedList object will be instantiated and called as such: + * var obj = new MyLinkedList() + * var param_1 = obj.get(index) + * obj.addAtHead(val) + * obj.addAtTail(val) + * obj.addAtIndex(index,val) + * obj.deleteAtIndex(index) + */ + diff --git a/708-insert-into-a-sorted-circular-linked-list.js b/708.insert-into-a-sorted-circular-linked-list.js similarity index 100% rename from 708-insert-into-a-sorted-circular-linked-list.js rename to 708.insert-into-a-sorted-circular-linked-list.js diff --git a/71-simplify-path.js b/71.simplify-path.js similarity index 100% rename from 71-simplify-path.js rename to 71.simplify-path.js diff --git a/710-random-pick-with-blacklist.js b/710.random-pick-with-blacklist.js similarity index 100% rename from 710-random-pick-with-blacklist.js rename to 710.random-pick-with-blacklist.js diff --git a/711-number-of-distinct-islands-ii.js b/711.number-of-distinct-islands-ii.js similarity index 100% rename from 711-number-of-distinct-islands-ii.js rename to 711.number-of-distinct-islands-ii.js diff --git a/712-minimum-ASCII-delete-sum-for-two-strings.js b/712-minimum-ASCII-delete-sum-for-two-strings.js deleted file mode 100755 index 033de353..00000000 --- a/712-minimum-ASCII-delete-sum-for-two-strings.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @param {string} s1 - * @param {string} s2 - * @return {number} - */ -const minimumDeleteSum = function(s1, s2) { - const l1 = s1.length; - const l2 = s2.length; - const dp = []; - for (let i = 0; i <= l1; i++) { - dp[i] = []; - } - let sum = 0; - for (let i = 0; i <= l1; i++) { - for (let j = 0; j <= l2; j++) { - if (i === 0 || j === 0) { - sum = 0; - for (let k = 0; k < Math.max(i, j); k++) { - sum += i > j ? s1.charCodeAt(k) : s2.charCodeAt(k); - } - dp[i][j] = sum; - } else { - if (s1[i - 1] === s2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1]; - } else { - dp[i][j] = Math.min( - s1.charCodeAt(i - 1) + dp[i - 1][j], - s2.charCodeAt(j - 1) + dp[i][j - 1], - s1.charCodeAt(i - 1) + s2.charCodeAt(j - 1) + dp[i - 1][j - 1] - ); - } - } - } - } - return dp[l1][l2]; -}; diff --git a/712.minimum-ASCII-delete-sum-for-two-strings.js b/712.minimum-ASCII-delete-sum-for-two-strings.js new file mode 100644 index 00000000..bc250cb4 --- /dev/null +++ b/712.minimum-ASCII-delete-sum-for-two-strings.js @@ -0,0 +1,36 @@ +/** + * @param {string} s1 + * @param {string} s2 + * @return {number} + */ +const minimumDeleteSum = function(s1, s2) { + const l1 = s1.length; + const l2 = s2.length; + const dp = []; + for (let i = 0; i <= l1; i++) { + dp[i] = []; + } + let sum = 0; + for (let i = 0; i <= l1; i++) { + for (let j = 0; j <= l2; j++) { + if (i === 0 || j === 0) { + sum = 0; + for (let k = 0; k < Math.max(i, j); k++) { + sum += i > j ? s1.charCodeAt(k) : s2.charCodeAt(k); + } + dp[i][j] = sum; + } else { + if (s1[i - 1] === s2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1]; + } else { + dp[i][j] = Math.min( + s1.charCodeAt(i - 1) + dp[i - 1][j], + s2.charCodeAt(j - 1) + dp[i][j - 1], + s1.charCodeAt(i - 1) + s2.charCodeAt(j - 1) + dp[i - 1][j - 1] + ); + } + } + } + } + return dp[l1][l2]; +}; diff --git a/713-subarray-product-less-than-k.js b/713.subarray-product-less-than-k.js similarity index 100% rename from 713-subarray-product-less-than-k.js rename to 713.subarray-product-less-than-k.js diff --git a/714-best-time-to-buy-and-sell-stock-with-transaction-fee.js b/714-best-time-to-buy-and-sell-stock-with-transaction-fee.js deleted file mode 100755 index 4ab03237..00000000 --- a/714-best-time-to-buy-and-sell-stock-with-transaction-fee.js +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @param {number[]} prices - * @param {number} fee - * @return {number} - */ -const maxProfit = function(prices, fee) { - let cash = 0, - hold = -prices[0]; - for (let i = 1; i < prices.length; i++) { - cash = Math.max(cash, hold + prices[i] - fee); - hold = Math.max(hold, cash - prices[i]); - } - return cash; -}; - -console.log(maxProfit([1, 3, 2, 8, 4, 9], 2)); diff --git a/714.best-time-to-buy-and-sell-stock-with-transaction-fee.js b/714.best-time-to-buy-and-sell-stock-with-transaction-fee.js new file mode 100644 index 00000000..38f4a617 --- /dev/null +++ b/714.best-time-to-buy-and-sell-stock-with-transaction-fee.js @@ -0,0 +1,16 @@ +/** + * @param {number[]} prices + * @param {number} fee + * @return {number} + */ +const maxProfit = function(prices, fee) { + let cash = 0, + hold = -prices[0]; + for (let i = 1; i < prices.length; i++) { + cash = Math.max(cash, hold + prices[i] - fee); + hold = Math.max(hold, cash - prices[i]); + } + return cash; +}; + +console.log(maxProfit([1, 3, 2, 8, 4, 9], 2)); diff --git a/715-range-module.js b/715-range-module.js deleted file mode 100644 index 4c193227..00000000 --- a/715-range-module.js +++ /dev/null @@ -1,380 +0,0 @@ - -const RangeModule = function() { - this.st = new SegmentTree(); -}; - -/** - * @param {number} left - * @param {number} right - * @return {void} - */ -RangeModule.prototype.addRange = function(left, right) { - this.st.add(left, right); -}; - -/** - * @param {number} left - * @param {number} right - * @return {boolean} - */ -RangeModule.prototype.queryRange = function(left, right) { - return this.st.query(left, right); -}; - -/** - * @param {number} left - * @param {number} right - * @return {void} - */ -RangeModule.prototype.removeRange = function(left, right) { - this.st.remove(left, right); -}; - -/** - * Your RangeModule object will be instantiated and called as such: - * var obj = new RangeModule() - * obj.addRange(left,right) - * var param_2 = obj.queryRange(left,right) - * obj.removeRange(left,right) - */ -class SegNode { - constructor(l, r, state) { - this.l = l; - this.r = r; - this.state = state; - this.left = null; - this.right = null; - } -} - -function SegmentTree() { - let root = new SegNode(0, 1e9, false); - return { update, query, add, remove } - function update(node, l, r, state) { - if (l <= node.l && r >= node.r) { - node.state = state; - node.left = null; - node.right = null; - return node.state; - } - if (l >= node.r || r <= node.l) return node.state; - let mid = node.l + parseInt((node.r - node.l) / 2); - if (node.left == null) { - node.left = new SegNode(node.l, mid, node.state); - node.right = new SegNode(mid, node.r, node.state); - } - let left = update(node.left, l, r, state); - let right = update(node.right, l, r, state); - node.state = left && right; - return node.state; - } - function query(l, r) { - return dfs(root, l, r); - } - function dfs(node, l, r) { - if (l >= node.r || r <= node.l) return true; - if ((l <= node.l && r >= node.r) || (node.left == null)) return node.state; - let mid = node.l + parseInt((node.r - node.l) / 2); - if (r <= mid) { - return dfs(node.left, l, r); - } else if (l >= mid) { - return dfs(node.right, l, r); - } else { - return dfs(node.left, l, r) && dfs(node.right, l, r); - } - } - function add(l, r) { - update(root, l, r, true); - } - function remove(l, r) { - update(root, l, r, false); - } -} - - -// another - -const RangeModule = function() { - this.range = [] -} - -/** - * @param {number} left - * @param {number} right - * @return {void} - */ -RangeModule.prototype.addRange = function(left, right) { - let index1 = this.range.length - let low = 0 - let high = this.range.length - 1 - while (low <= high) { - const mid = (low + high) >> 1 - if (this.range[mid][1] >= left) { - index1 = Math.min(index1, mid) - high = mid - 1 - } else { - low = mid + 1 - } - } - - let index2 = -1 - low = 0 - high = this.range.length - 1 - while (low <= high) { - const mid = (low + high) >> 1 - if (this.range[mid][0] <= right) { - index2 = Math.max(index2, mid) - low = mid + 1 - } else { - high = mid - 1 - } - } - - if (index1 === this.range.length) { - this.range.push([left, right]) - return - } else if (index2 === -1) { - this.range.unshift([left, right]) - return - } - left = Math.min(left, this.range[index1][0]) - right = Math.max(right, this.range[index2][1]) - this.range.splice(index1, index2 - index1 + 1, [left, right]) -} - -/** - * @param {number} left - * @param {number} right - * @return {boolean} - */ -RangeModule.prototype.queryRange = function(left, right) { - let index = -1 - let low = 0 - let high = this.range.length - 1 - while (low <= high) { - const mid = (low + high) >> 1 - if (this.range[mid][0] <= left) { - index = Math.max(index, mid) - low = mid + 1 - } else { - high = mid - 1 - } - } - if (index === -1 || this.range[index][1] < right) { - return false - } - return true -} - -/** - * @param {number} left - * @param {number} right - * @return {void} - */ -RangeModule.prototype.removeRange = function(left, right) { - let index1 = this.range.length - let low = 0 - let high = this.range.length - 1 - while (low <= high) { - const mid = (low + high) >> 1 - if (this.range[mid][1] >= left) { - index1 = Math.min(index1, mid) - high = mid - 1 - } else { - low = mid + 1 - } - } - - let index2 = -1 - low = 0 - high = this.range.length - 1 - while (low <= high) { - const mid = (low + high) >> 1 - if (this.range[mid][0] <= right) { - index2 = Math.max(index2, mid) - low = mid + 1 - } else { - high = mid - 1 - } - } - - if (index1 === this.range.length || index2 === -1) { - return - } - - const newRange = [] - if (left > this.range[index1][0]) { - newRange.push([this.range[index1][0], left]) - } - if (right < this.range[index2][1]) { - newRange.push([right, this.range[index2][1]]) - } - this.range.splice(index1, index2 - index1 + 1, ...newRange) -} - -/** - * Your RangeModule object will be instantiated and called as such: - * var obj = new RangeModule() - * obj.addRange(left,right) - * var param_2 = obj.queryRange(left,right) - * obj.removeRange(left,right) - */ - - -// another - -const RangeModule = function () { - this.intervals = [] -} - -/** - * @param {number} left - * @param {number} right - * @return {void} - */ -RangeModule.prototype.addRange = function (left, right) { - const n = this.intervals.length - const tmp = [] - for (let i = 0; i <= n; i++) { - const cur = this.intervals[i] - - if (i == n || cur[0] > right) { - tmp.push([left, right]) - while (i < n) tmp.push(this.intervals[i++]) - } else if (cur[1] < left) tmp.push(cur) - else { - left = Math.min(left, cur[0]) - right = Math.max(right, cur[1]) - } - } - this.intervals = tmp -} - -/** - * @param {number} left - * @param {number} right - * @return {boolean} - */ -RangeModule.prototype.queryRange = function (left, right) { - const n = this.intervals.length - let l = 0, - r = n - 1 - while (l <= r) { - let m = ~~(l + (r - l) / 2) - if (this.intervals[m][0] >= right) r = m - 1 - else if (this.intervals[m][1] <= left) l = m + 1 - else return this.intervals[m][0] <= left && this.intervals[m][1] >= right - } - return false -} - -/** - * @param {number} left - * @param {number} right - * @return {void} - */ -RangeModule.prototype.removeRange = function (left, right) { - const n = this.intervals.length - const tmp = [] - for (let i = 0; i < n; i++) { - const cur = this.intervals[i] - if (cur[1] <= left || cur[0] >= right) tmp.push(cur) - else { - if (cur[0] < left) tmp.push([cur[0], left]) - if (cur[1] > right) tmp.push([right, cur[1]]) - } - } - this.intervals = tmp -} - -/** - * Your RangeModule object will be instantiated and called as such: - * var obj = new RangeModule() - * obj.addRange(left,right) - * var param_2 = obj.queryRange(left,right) - * obj.removeRange(left,right) - */ - -// another - -const RangeModule = function () { - this.intervals = [] -} - -/** - * @param {number} left - * @param {number} right - * @return {void} - */ -RangeModule.prototype.addRange = function (left, right) { - const tmp = [] - const n = this.intervals.length - for(let i = 0; i <= n; i++) { - const cur = this.intervals[i] - if(i === n || cur[0] > right) { - tmp.push([left, right]) - while(i < n) tmp.push(this.intervals[i++]) - }else if(cur[1] < left) { - tmp.push(cur) - }else { - // cur[0] <= right - // left <= cur[1] - left = Math.min(left, cur[0]) - right = Math.max(right, cur[1]) - } - } - // console.log(tmp) - this.intervals = tmp -} - -/** - * @param {number} left - * @param {number} right - * @return {boolean} - */ -RangeModule.prototype.queryRange = function (left, right) { - const n = this.intervals.length, arr = this.intervals - let l = 0, r = n - 1 - while(l <= r) { - const mid = ~~(l + (r - l) / 2) - if(arr[mid][0] >= right) r = mid - 1 - else if(arr[mid][1] <= left) l = mid + 1 - else return arr[mid][0] <= left && arr[mid][1] >= right - } - - return false -} - -/** - * @param {number} left - * @param {number} right - * @return {void} - */ -RangeModule.prototype.removeRange = function (left, right) { - const tmp = [] - const n = this.intervals.length - - for(let i = 0; i < n; i++) { - const cur = this.intervals[i] - if(cur[1] < left) { - tmp.push(cur) - }else if(cur[0] > right) tmp.push(cur) - else { - // left <= cur[1] - // cur[0] <= right - if(left > cur[0]) tmp.push([cur[0], left]) - if(right < cur[1]) tmp.push([right, cur[1]]) - } - } - // console.log(tmp) - this.intervals = tmp -} - -/** - * Your RangeModule object will be instantiated and called as such: - * var obj = new RangeModule() - * obj.addRange(left,right) - * var param_2 = obj.queryRange(left,right) - * obj.removeRange(left,right) - */ - diff --git a/715.range-module.js b/715.range-module.js new file mode 100644 index 00000000..ff229572 --- /dev/null +++ b/715.range-module.js @@ -0,0 +1,94 @@ + +const RangeModule = function() { + this.st = new SegmentTree(); +}; + +/** + * @param {number} left + * @param {number} right + * @return {void} + */ +RangeModule.prototype.addRange = function(left, right) { + this.st.add(left, right); +}; + +/** + * @param {number} left + * @param {number} right + * @return {boolean} + */ +RangeModule.prototype.queryRange = function(left, right) { + return this.st.query(left, right); +}; + +/** + * @param {number} left + * @param {number} right + * @return {void} + */ +RangeModule.prototype.removeRange = function(left, right) { + this.st.remove(left, right); +}; + +/** + * Your RangeModule object will be instantiated and called as such: + * var obj = new RangeModule() + * obj.addRange(left,right) + * var param_2 = obj.queryRange(left,right) + * obj.removeRange(left,right) + */ +class SegNode { + constructor(l, r, state) { + this.l = l; + this.r = r; + this.state = state; + this.left = null; + this.right = null; + } +} + +function SegmentTree() { + let root = new SegNode(0, 1e9, false); + return { update, query, add, remove } + function update(node, l, r, state) { + if (l <= node.l && r >= node.r) { + node.state = state; + node.left = null; + node.right = null; + return node.state; + } + if (l >= node.r || r <= node.l) return node.state; + let mid = node.l + parseInt((node.r - node.l) / 2); + if (node.left == null) { + node.left = new SegNode(node.l, mid, node.state); + node.right = new SegNode(mid, node.r, node.state); + } + let left = update(node.left, l, r, state); + let right = update(node.right, l, r, state); + node.state = left && right; + return node.state; + } + function query(l, r) { + return dfs(root, l, r); + } + function dfs(node, l, r) { + if (l >= node.r || r <= node.l) return true; + if ((l <= node.l && r >= node.r) || (node.left == null)) return node.state; + let mid = node.l + parseInt((node.r - node.l) / 2); + if (r <= mid) { + return dfs(node.left, l, r); + } else if (l >= mid) { + return dfs(node.right, l, r); + } else { + return dfs(node.left, l, r) && dfs(node.right, l, r); + } + } + function add(l, r) { + update(root, l, r, true); + } + function remove(l, r) { + update(root, l, r, false); + } +} + + diff --git a/716-max-stack.js b/716.max-stack.js similarity index 100% rename from 716-max-stack.js rename to 716.max-stack.js diff --git a/717-1-bit-and-2-bit-characters.js b/717-1-bit-and-2-bit-characters.js deleted file mode 100755 index 44c488b8..00000000 --- a/717-1-bit-and-2-bit-characters.js +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @param {number[]} bits - * @return {boolean} - */ -const isOneBitCharacter = function(bits) { - let ones = 0; - //Starting from one but last, as last one is always 0. - for (let i = bits.length - 2; i >= 0 && bits[i] != 0; i--) { - ones++; - } - return ones % 2 > 0 ? false : true; -}; diff --git a/717.1-bit-and-2-bit-characters.js b/717.1-bit-and-2-bit-characters.js new file mode 100644 index 00000000..e0e5b084 --- /dev/null +++ b/717.1-bit-and-2-bit-characters.js @@ -0,0 +1,12 @@ +/** + * @param {number[]} bits + * @return {boolean} + */ +const isOneBitCharacter = function(bits) { + let ones = 0; + //Starting from one but last, as last one is always 0. + for (let i = bits.length - 2; i >= 0 && bits[i] != 0; i--) { + ones++; + } + return ones % 2 > 0 ? false : true; +}; diff --git a/718-maximum-length-of-repeated-subarray.js b/718-maximum-length-of-repeated-subarray.js deleted file mode 100755 index 7db5b0ba..00000000 --- a/718-maximum-length-of-repeated-subarray.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @param {number[]} A - * @param {number[]} B - * @return {number} - */ -const findLength = function(A, B) { - let ans = 0; - let memo = []; - for (let i = 0; i < A.length + 1; i++) { - memo[i] = Array(B.length + 1).fill(0); - } - for (let i = A.length - 1; i >= 0; --i) { - for (let j = B.length - 1; j >= 0; --j) { - if (A[i] == B[j]) { - memo[i][j] = memo[i + 1][j + 1] + 1; - if (ans < memo[i][j]) ans = memo[i][j]; - } - } - } - return ans; -}; diff --git a/718.maximum-length-of-repeated-subarray.js b/718.maximum-length-of-repeated-subarray.js new file mode 100644 index 00000000..314caf10 --- /dev/null +++ b/718.maximum-length-of-repeated-subarray.js @@ -0,0 +1,21 @@ +/** + * @param {number[]} A + * @param {number[]} B + * @return {number} + */ +const findLength = function(A, B) { + let ans = 0; + let memo = []; + for (let i = 0; i < A.length + 1; i++) { + memo[i] = Array(B.length + 1).fill(0); + } + for (let i = A.length - 1; i >= 0; --i) { + for (let j = B.length - 1; j >= 0; --j) { + if (A[i] == B[j]) { + memo[i][j] = memo[i + 1][j + 1] + 1; + if (ans < memo[i][j]) ans = memo[i][j]; + } + } + } + return ans; +}; diff --git a/719-find-k-th-smallest-pair-distance.js b/719-find-k-th-smallest-pair-distance.js deleted file mode 100644 index 63e8a619..00000000 --- a/719-find-k-th-smallest-pair-distance.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -function smallestDistancePair(nums, k) { - nums.sort((a, b) => a - b) - let l = 0, n = nums.length, r = nums[n - 1] - nums[0] - - let res = 0 - while(l < r) { - let cnt = 0, mid = l + ((r - l) >> 1) - for(let i = 0, j = 0; i < n; i++) { - while(j < n && nums[j] <= nums[i] + mid) j++ - cnt += j - 1 - i - } - if(cnt < k) l = mid + 1 - else r = mid - } - - return l -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const smallestDistancePair = function(nums, k) { - nums.sort((a, b) => a - b) - let lo = 0 - let hi = nums[nums.length - 1] - nums[0] - while (lo < hi) { - let mi = Math.floor((lo + hi) / 2) - let count = 0 - let left = 0 - for (let right = 0; right < nums.length; right++) { - while (nums[right] - nums[left] > mi) left++ - count += right - left - } - //count = number of pairs with distance <= mi - if (count >= k) hi = mi - else lo = mi + 1 - } - return lo -} diff --git a/719.find-k-th-smallest-pair-distance.js b/719.find-k-th-smallest-pair-distance.js new file mode 100644 index 00000000..354e832a --- /dev/null +++ b/719.find-k-th-smallest-pair-distance.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +function smallestDistancePair(nums, k) { + nums.sort((a, b) => a - b) + let l = 0, n = nums.length, r = nums[n - 1] - nums[0] + + let res = 0 + while(l < r) { + let cnt = 0, mid = l + ((r - l) >> 1) + for(let i = 0, j = 0; i < n; i++) { + while(j < n && nums[j] <= nums[i] + mid) j++ + cnt += j - 1 - i + } + if(cnt < k) l = mid + 1 + else r = mid + } + + return l +} + diff --git a/72-edit-distance.js b/72-edit-distance.js deleted file mode 100644 index f9e41c89..00000000 --- a/72-edit-distance.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @param {string} word1 - * @param {string} word2 - * @return {number} - */ -const minDistance = function(word1, word2) { - let m = word1.length, n = word2.length; - const dp = Array.from({length: m + 1}, ()=> new Array(n+ 1).fill(0)) - for (let i = 1; i <= m; i++) { - dp[i][0] = i; - } - for (let j = 1; j <= n; j++) { - dp[0][j] = j; - } - for (let i = 1; i <= m; i++) { - for (let j = 1; j <= n; j++) { - if (word1[i - 1] === word2[j - 1]) { - dp[i][j] = dp[i - 1][j - 1]; - } else { - dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i][j - 1], dp[i - 1][j])) + 1; - } - } - } - return dp[m][n]; -}; - -// another - -/** - * @param {string} word1 - * @param {string} word2 - * @return {number} - */ -const minDistance = function(word1, word2) { - const m = word1.length, n = word2.length - const dp = Array(n + 1).fill(0) - for(let i = 1; i <= n; i++) dp[i] = i - let pre = 0 - for(let i = 1; i <= m; i++) { - pre = dp[0] - dp[0] = i - for(let j = 1; j <= n; j++) { - let tmp = dp[j] - if(word1[i - 1] === word2[j - 1]) { - dp[j] = pre - } else { - dp[j] = Math.min(pre, dp[j], dp[j - 1]) + 1 - } - pre = tmp - } - } - - return dp[n] -}; diff --git a/72.edit-distance.js b/72.edit-distance.js new file mode 100644 index 00000000..5fa327b9 --- /dev/null +++ b/72.edit-distance.js @@ -0,0 +1,26 @@ +/** + * @param {string} word1 + * @param {string} word2 + * @return {number} + */ +const minDistance = function(word1, word2) { + let m = word1.length, n = word2.length; + const dp = Array.from({length: m + 1}, ()=> new Array(n+ 1).fill(0)) + for (let i = 1; i <= m; i++) { + dp[i][0] = i; + } + for (let j = 1; j <= n; j++) { + dp[0][j] = j; + } + for (let i = 1; i <= m; i++) { + for (let j = 1; j <= n; j++) { + if (word1[i - 1] === word2[j - 1]) { + dp[i][j] = dp[i - 1][j - 1]; + } else { + dp[i][j] = Math.min(dp[i - 1][j - 1], Math.min(dp[i][j - 1], dp[i - 1][j])) + 1; + } + } + } + return dp[m][n]; +}; + diff --git a/720-longest-word-in-dictionary.js b/720.longest-word-in-dictionary.js similarity index 100% rename from 720-longest-word-in-dictionary.js rename to 720.longest-word-in-dictionary.js diff --git a/721-accounts-merge.js b/721.accounts-merge.js similarity index 100% rename from 721-accounts-merge.js rename to 721.accounts-merge.js diff --git a/722-remove-comments.js b/722.remove-comments.js similarity index 100% rename from 722-remove-comments.js rename to 722.remove-comments.js diff --git a/723-candy-crush.js b/723-candy-crush.js deleted file mode 100644 index 1d5f7f56..00000000 --- a/723-candy-crush.js +++ /dev/null @@ -1,139 +0,0 @@ -/** - * @param {number[][]} board - * @return {number[][]} - */ -const candyCrush = function (board) { - while (true) { - let moreToCrush = false - for (let i = 0; i < board.length; i++) { - for (let j = 0; j < board[0].length; j++) { - if (board[i][j] > 0) { - moreToCrush = - flagForCrush(board, i, j, board[i][j], 0, true, false) || - moreToCrush - moreToCrush = - flagForCrush(board, i, j, board[i][j], 0, false, true) || - moreToCrush - } - } - } - if (!moreToCrush) break - crush(board) - inflictGravity(board) - } - return board -} -const flagForCrush = function (board, i, j, target, count, right, down) { - if ( - j === board[0].length || - i === board.length || - Math.abs(board[i][j]) !== Math.abs(target) - ) { - return count >= 3 - } - - let shouldFlagIndexRight = flagForCrush( - board, - i, - j + 1, - target, - right ? count + 1 : 1, - true, - false - ) - let shouldFlagIndexDown = flagForCrush( - board, - i + 1, - j, - target, - down ? count + 1 : 1, - false, - true - ) - - if ((shouldFlagIndexRight && right) || (shouldFlagIndexDown && down)) { - board[i][j] = -Math.abs(board[i][j]) - return true - } - - return false -} -const crush = function (board) { - for (let i = 0; i < board.length; i++) { - for (let j = 0; j < board[0].length; j++) { - if (board[i][j] < 0) board[i][j] = 0 - } - } -} -const inflictGravity = function (board) { - for (let j = 0; j < board[0].length; j++) { - let st = board.length - 1 - let end = board.length - 2 - while (end >= 0) { - if (board[st][j] === 0 && board[end][j] !== 0) { - let temp = board[st][j] - board[st][j] = board[end][j] - board[end][j] = temp - st-- - } else if (board[st][j] !== 0) { - st-- - } - end-- - } - } -} - -// another - -/** - * @param {number[][]} board - * @return {number[][]} - */ -const candyCrush = function (board) { - const N = board.length, - M = board[0].length - let found = true - while (found) { - found = false - for (let i = 0; i < N; i++) { - for (let j = 0; j < M; j++) { - const val = Math.abs(board[i][j]) - if (val === 0) continue - if ( - j < M - 2 && - Math.abs(board[i][j + 1]) === val && - Math.abs(board[i][j + 2]) === val - ) { - found = true - let ind = j - while (ind < Math.min(M, j + 3) && Math.abs(board[i][ind]) === val) - board[i][ind++] = -val - } - if ( - i < N - 2 && - Math.abs(board[i + 1][j]) === val && - Math.abs(board[i + 2][j]) === val - ) { - found = true - let ind = i - while (ind < Math.min(N, i + 3) && Math.abs(board[ind][j]) === val) - board[ind++][j] = -val - } - } - } - if (found) { - // move positive values to the bottom, then set the rest to 0 - for (let j = 0; j < M; j++) { - let storeInd = N - 1 - for (let i = N - 1; i >= 0; i--) { - if (board[i][j] > 0) { - board[storeInd--][j] = board[i][j] - } - } - for (let k = storeInd; k >= 0; k--) board[k][j] = 0 - } - } - } - return board -} - diff --git a/723.candy-crush.js b/723.candy-crush.js new file mode 100644 index 00000000..5ffd78ee --- /dev/null +++ b/723.candy-crush.js @@ -0,0 +1,85 @@ +/** + * @param {number[][]} board + * @return {number[][]} + */ +const candyCrush = function (board) { + while (true) { + let moreToCrush = false + for (let i = 0; i < board.length; i++) { + for (let j = 0; j < board[0].length; j++) { + if (board[i][j] > 0) { + moreToCrush = + flagForCrush(board, i, j, board[i][j], 0, true, false) || + moreToCrush + moreToCrush = + flagForCrush(board, i, j, board[i][j], 0, false, true) || + moreToCrush + } + } + } + if (!moreToCrush) break + crush(board) + inflictGravity(board) + } + return board +} +const flagForCrush = function (board, i, j, target, count, right, down) { + if ( + j === board[0].length || + i === board.length || + Math.abs(board[i][j]) !== Math.abs(target) + ) { + return count >= 3 + } + + let shouldFlagIndexRight = flagForCrush( + board, + i, + j + 1, + target, + right ? count + 1 : 1, + true, + false + ) + let shouldFlagIndexDown = flagForCrush( + board, + i + 1, + j, + target, + down ? count + 1 : 1, + false, + true + ) + + if ((shouldFlagIndexRight && right) || (shouldFlagIndexDown && down)) { + board[i][j] = -Math.abs(board[i][j]) + return true + } + + return false +} +const crush = function (board) { + for (let i = 0; i < board.length; i++) { + for (let j = 0; j < board[0].length; j++) { + if (board[i][j] < 0) board[i][j] = 0 + } + } +} +const inflictGravity = function (board) { + for (let j = 0; j < board[0].length; j++) { + let st = board.length - 1 + let end = board.length - 2 + while (end >= 0) { + if (board[st][j] === 0 && board[end][j] !== 0) { + let temp = board[st][j] + board[st][j] = board[end][j] + board[end][j] = temp + st-- + } else if (board[st][j] !== 0) { + st-- + } + end-- + } + } +} + diff --git a/724-find-pivot-index.js b/724.find-pivot-index.js similarity index 100% rename from 724-find-pivot-index.js rename to 724.find-pivot-index.js diff --git a/725-split-linked-list-in-parts.js b/725-split-linked-list-in-parts.js deleted file mode 100755 index 2762c3f9..00000000 --- a/725-split-linked-list-in-parts.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} root - * @param {number} k - * @return {ListNode[]} - */ -const splitListToParts = function(root, k) { - let cur = root; - let N = 0; - while (cur != null) { - cur = cur.next; - N++; - } - let width = Math.floor(N / k), - rem = N % k; - let ans = []; - cur = root; - for (let i = 0; i < k; ++i) { - let head = cur; - for (let j = 0; j < width + (i < rem ? 1 : 0) - 1; ++j) { - if (cur != null) cur = cur.next; - } - if (cur != null) { - let prev = cur; - cur = cur.next; - prev.next = null; - } - ans[i] = head; - } - return ans; -}; diff --git a/725.split-linked-list-in-parts.js b/725.split-linked-list-in-parts.js new file mode 100644 index 00000000..a476a66f --- /dev/null +++ b/725.split-linked-list-in-parts.js @@ -0,0 +1,37 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} root + * @param {number} k + * @return {ListNode[]} + */ +const splitListToParts = function(root, k) { + let cur = root; + let N = 0; + while (cur != null) { + cur = cur.next; + N++; + } + let width = Math.floor(N / k), + rem = N % k; + let ans = []; + cur = root; + for (let i = 0; i < k; ++i) { + let head = cur; + for (let j = 0; j < width + (i < rem ? 1 : 0) - 1; ++j) { + if (cur != null) cur = cur.next; + } + if (cur != null) { + let prev = cur; + cur = cur.next; + prev.next = null; + } + ans[i] = head; + } + return ans; +}; diff --git a/726-number-of-atoms.js b/726.number-of-atoms.js similarity index 100% rename from 726-number-of-atoms.js rename to 726.number-of-atoms.js diff --git a/727-minimum-window-subsequence.js b/727-minimum-window-subsequence.js deleted file mode 100644 index 635bc00f..00000000 --- a/727-minimum-window-subsequence.js +++ /dev/null @@ -1,162 +0,0 @@ -/** - * @param {string} s1 - * @param {string} s2 - * @return {string} - */ -const minWindow = function (s1, s2) { - const S = s1,T=s2 - let m = T.length, n = S.length; - let dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); - for (let j = 0; j <= n; j++) { - dp[0][j] = j + 1; - } - for (let i = 1; i <= m; i++) { - for (let j = 1; j <= n; j++) { - if (T.charAt(i - 1) == S.charAt(j - 1)) { - dp[i][j] = dp[i - 1][j - 1]; - } else { - dp[i][j] = dp[i][j - 1]; - } - } - } - - let start = 0, len = n + 1; - for (let j = 1; j <= n; j++) { - if (dp[m][j] != 0) { - if (j - dp[m][j] + 1 < len) { - start = dp[m][j] - 1; - len = j - dp[m][j] + 1; - } - } - } - return len == n + 1 ? "" : S.substring(start, start + len); -} - -// another - -/** - * @param {string} s1 - * @param {string} s2 - * @return {string} - */ -const minWindow = function (s1, s2) { - let n1 = s1.length, - n2 = s2.length, - s1Idx = 0, - s2Idx = 0, - start = -1, - len = n1 + 1 - while (s1Idx < n1) { - if (s1[s1Idx] === s2[s2Idx]) { - if (s2Idx === n2 - 1) { - const end = s1Idx - while (s2Idx >= 0) { - while (s1[s1Idx] !== s2[s2Idx]) s1Idx-- - s2Idx-- - s1Idx-- - } - const tmp = end - s1Idx - if (tmp < len) { - len = tmp - start = s1Idx + 1 - } - s2Idx++ - s1Idx += 2 - } else { - s2Idx++ - s1Idx++ - } - } else s1Idx++ - } - return start === -1 ? '' : s1.slice(start, start + len) -} - -// another - -/** - * @param {string} s1 - * @param {string} s2 - * @return {string} - */ -const minWindow = function(s1, s2) { - let res = '', n = s1.length, m = s2.length - if(s1 === '' || s2 === '') return res - let minLen = Infinity - let right = 0 - while(right < n) { - let tIndex = 0 - while(right < n) { - if(s1[right] === s2[tIndex]) tIndex++ - if(tIndex === m) break - right++ - } - if(right === n) break - let left = right - tIndex = m - 1 - while(left >= 0) { - if(s1[left] === s2[tIndex]) { - tIndex-- - } - if(tIndex < 0) break - left-- - } - - if(right - left + 1 < minLen) { - minLen = right - left + 1 - res = s1.slice(left, right + 1) - } - right = left + 1 - } - - return res -}; - -// another - -/** - * @param {string} S - * @param {string} T - * @return {string} - */ -const minWindow = function (S, T) { - if (S.length === 0 || T.length === 0) { - return '' - } - let right = 0 - let minLen = Number.MAX_VALUE - let result = '' - while (right < S.length) { - let tIndex = 0 - while (right < S.length) { - if (S.charAt(right) === T.charAt(tIndex)) { - tIndex++ - } - if (tIndex === T.length) { - break - } - right++ - } - if (right === S.length) { - break - } - let left = right - tIndex = T.length - 1 - while (left >= 0) { - if (S.charAt(left) === T.charAt(tIndex)) { - tIndex-- - } - if (tIndex < 0) { - break - } - left-- - } - if (right - left + 1 < minLen) { - minLen = right - left + 1 - result = S.slice(left, right + 1) - } - // we have to move right pointer to the next position of left pointer, NOT the next position - // of right pointer - right = left + 1 - } - return result -} diff --git a/727.minimum-window-subsequence.js b/727.minimum-window-subsequence.js new file mode 100644 index 00000000..77a9b830 --- /dev/null +++ b/727.minimum-window-subsequence.js @@ -0,0 +1,34 @@ +/** + * @param {string} s1 + * @param {string} s2 + * @return {string} + */ +const minWindow = function (s1, s2) { + const S = s1,T=s2 + let m = T.length, n = S.length; + let dp = Array.from({ length: m + 1 }, () => Array(n + 1).fill(0)); + for (let j = 0; j <= n; j++) { + dp[0][j] = j + 1; + } + for (let i = 1; i <= m; i++) { + for (let j = 1; j <= n; j++) { + if (T.charAt(i - 1) == S.charAt(j - 1)) { + dp[i][j] = dp[i - 1][j - 1]; + } else { + dp[i][j] = dp[i][j - 1]; + } + } + } + + let start = 0, len = n + 1; + for (let j = 1; j <= n; j++) { + if (dp[m][j] != 0) { + if (j - dp[m][j] + 1 < len) { + start = dp[m][j] - 1; + len = j - dp[m][j] + 1; + } + } + } + return len == n + 1 ? "" : S.substring(start, start + len); +} + diff --git a/729-my-calendar-i.js b/729-my-calendar-i.js deleted file mode 100644 index 22425c94..00000000 --- a/729-my-calendar-i.js +++ /dev/null @@ -1,74 +0,0 @@ -const MyCalendar = function () { - this.root = null -} - -const Node = function (start, end) { - this.start = start - this.end = end - this.left = null - this.right = null -} - -Node.prototype.insert = function (node) { - if (node.start >= this.end) { - if (this.right === null) { - this.right = node - return true - } - return this.right.insert(node) - } else if (node.end <= this.start) { - if (this.left === null) { - this.left = node - return true - } - return this.left.insert(node) - } else { - return false - } -} - -/** - * @param {number} start - * @param {number} end - * @return {boolean} - */ -MyCalendar.prototype.book = function (start, end) { - const newNode = new Node(start, end) - if (this.root === null) { - this.root = newNode - return true - } else { - return this.root.insert(newNode) - } -} - -/** - * Your MyCalendar object will be instantiated and called as such: - * var obj = new MyCalendar() - * var param_1 = obj.book(start,end) - */ - -// another - -const MyCalendar = function() { - this.s = new Set() -}; - -/** - * @param {number} start - * @param {number} end - * @return {boolean} - */ -MyCalendar.prototype.book = function(start, end) { - for(let e of this.s) { - if(Math.max(start, e[0]) < Math.min(end, e[1])) return false - } - this.s.add([start, end]) - return true -}; - -/** - * Your MyCalendar object will be instantiated and called as such: - * var obj = new MyCalendar() - * var param_1 = obj.book(start,end) - */ diff --git a/729.my-calendar-i.js b/729.my-calendar-i.js new file mode 100644 index 00000000..223fd1d3 --- /dev/null +++ b/729.my-calendar-i.js @@ -0,0 +1,50 @@ +const MyCalendar = function () { + this.root = null +} + +const Node = function (start, end) { + this.start = start + this.end = end + this.left = null + this.right = null +} + +Node.prototype.insert = function (node) { + if (node.start >= this.end) { + if (this.right === null) { + this.right = node + return true + } + return this.right.insert(node) + } else if (node.end <= this.start) { + if (this.left === null) { + this.left = node + return true + } + return this.left.insert(node) + } else { + return false + } +} + +/** + * @param {number} start + * @param {number} end + * @return {boolean} + */ +MyCalendar.prototype.book = function (start, end) { + const newNode = new Node(start, end) + if (this.root === null) { + this.root = newNode + return true + } else { + return this.root.insert(newNode) + } +} + +/** + * Your MyCalendar object will be instantiated and called as such: + * var obj = new MyCalendar() + * var param_1 = obj.book(start,end) + */ + diff --git a/73-set-matrix-zeroes.js b/73.set-matrix-zeroes.js similarity index 100% rename from 73-set-matrix-zeroes.js rename to 73.set-matrix-zeroes.js diff --git a/730-count-different-palindromic-subsequences.js b/730.count-different-palindromic-subsequences.js similarity index 100% rename from 730-count-different-palindromic-subsequences.js rename to 730.count-different-palindromic-subsequences.js diff --git a/731-my-calendar-ii.js b/731.my-calendar-ii.js similarity index 100% rename from 731-my-calendar-ii.js rename to 731.my-calendar-ii.js diff --git a/732-my-calendar-iii.js b/732-my-calendar-iii.js deleted file mode 100644 index ad5f21cc..00000000 --- a/732-my-calendar-iii.js +++ /dev/null @@ -1,120 +0,0 @@ -const find = (cals, time, count) => { - let l = 0 - let r = cals.length - let mid - while (l < r) { - mid = Math.trunc((l + r) / 2) - if (cals[mid][0] === time) { - cals[mid][1] += count - return - } else if (cals[mid][0] < time) { - l = mid + 1 - } else { - r = mid - } - } - cals.splice(l, 0, [time, count]) -} -const MyCalendarThree = function() { - this.cals = [] -} - -/** - * @param {number} start - * @param {number} end - * @return {number} - */ -MyCalendarThree.prototype.book = function(start, end) { - let idx = find(this.cals, start, 1) - idx = find(this.cals, end, -1) - let count = 0 - let max = 0 - for (let cal of this.cals) { - count += cal[1] - max = Math.max(max, count) - } - return max -} - -/** - * Your MyCalendarThree object will be instantiated and called as such: - * var obj = new MyCalendarThree() - * var param_1 = obj.book(start,end) - */ - -// another - - -var MyCalendarThree = function() { - this.st = new SegmentTree(0, 10 ** 9); -}; - -/** - * @param {number} start - * @param {number} end - * @return {number} - */ -MyCalendarThree.prototype.book = function(start, end) { - this.st.add(start, end); - return this.st.getMax(); -}; - -/** - * Your MyCalendarThree object will be instantiated and called as such: - * var obj = new MyCalendarThree() - * var param_1 = obj.book(start,end) - */ - -class SegmentTree { - constructor(start, end) { - this.root = new TreeNode(start, end); - } - - add(qs, qe, node=this.root) { - - // completely outside of query range - if(qs > node.end || qe <= node.start) { - return node.val; - } - - // completely covered by query range - if(qs <= node.start && qe > node.end) { - node.booked += 1; - node.val += 1; - return node.val; - } - - let mid = (node.start + node.end)/2 >> 0; - - if(!node.left) { - node.left = new TreeNode(node.start, mid); - } - - if(!node.right) { - node.right = new TreeNode(mid+1, node.end); - } - - node.val = Math.max( - this.add(qs, qe, node.left), - this.add(qs, qe, node.right), - ) + node.booked; - - return node.val; - - } - - getMax() { - return this.root.val; - } - -} - -class TreeNode { - constructor(start, end) { - this.start = start; - this.end = end; - this.val = 0; - this.booked = 0; - this.left = this.right = null; - } -} diff --git a/732.my-calendar-iii.js b/732.my-calendar-iii.js new file mode 100644 index 00000000..b1974adc --- /dev/null +++ b/732.my-calendar-iii.js @@ -0,0 +1,44 @@ +const find = (cals, time, count) => { + let l = 0 + let r = cals.length + let mid + while (l < r) { + mid = Math.trunc((l + r) / 2) + if (cals[mid][0] === time) { + cals[mid][1] += count + return + } else if (cals[mid][0] < time) { + l = mid + 1 + } else { + r = mid + } + } + cals.splice(l, 0, [time, count]) +} +const MyCalendarThree = function() { + this.cals = [] +} + +/** + * @param {number} start + * @param {number} end + * @return {number} + */ +MyCalendarThree.prototype.book = function(start, end) { + let idx = find(this.cals, start, 1) + idx = find(this.cals, end, -1) + let count = 0 + let max = 0 + for (let cal of this.cals) { + count += cal[1] + max = Math.max(max, count) + } + return max +} + +/** + * Your MyCalendarThree object will be instantiated and called as such: + * var obj = new MyCalendarThree() + * var param_1 = obj.book(start,end) + */ + diff --git a/733-flood-fill.js b/733-flood-fill.js deleted file mode 100644 index 528c5f6e..00000000 --- a/733-flood-fill.js +++ /dev/null @@ -1,72 +0,0 @@ -/** - * @param {number[][]} image - * @param {number} sr - * @param {number} sc - * @param {number} newColor - * @return {number[][]} - */ -const floodFill = function(image, sr, sc, newColor, firstColor = image[sr][sc]) { - if ( - sr < 0 || - sc < 0 || - sr >= image.length || - sc >= image[sr].length || - image[sr][sc] !== firstColor || - image[sr][sc] === newColor - ) { - return image - } - - image[sr][sc] = newColor - - floodFill(image, sr + 1, sc, newColor, firstColor) - floodFill(image, sr - 1, sc, newColor, firstColor) - floodFill(image, sr, sc + 1, newColor, firstColor) - floodFill(image, sr, sc - 1, newColor, firstColor) - - return image -} - -// another - -/** - * @param {number[][]} image - * @param {number} sr - * @param {number} sc - * @param {number} newColor - * @return {number[][]} - */ -const floodFill = function ( - image, - sr, - sc, - newColor, - firstColor = image[sr][sc] -) { - const dirs = [0, -1, 0, 1, 0] - const rows = image.length - const cols = image[0].length - const q = [[sr, sc]] - while (q.length) { - const len = q.length - for (let i = 0; i < len; i++) { - const cur = q.shift() - image[cur[0]][cur[1]] = newColor - for (let j = 0; j < 4; j++) { - const [nr, nc] = [cur[0] + dirs[j], cur[1] + dirs[j + 1]] - if ( - nr >= 0 && - nr < rows && - nc >= 0 && - nc < cols && - image[nr][nc] === firstColor && - image[nr][nc] !== newColor - ) { - q.push([nr, nc]) - } - } - } - } - return image -} - diff --git a/733.flood-fill.js b/733.flood-fill.js new file mode 100644 index 00000000..2aa01d2c --- /dev/null +++ b/733.flood-fill.js @@ -0,0 +1,29 @@ +/** + * @param {number[][]} image + * @param {number} sr + * @param {number} sc + * @param {number} newColor + * @return {number[][]} + */ +const floodFill = function(image, sr, sc, newColor, firstColor = image[sr][sc]) { + if ( + sr < 0 || + sc < 0 || + sr >= image.length || + sc >= image[sr].length || + image[sr][sc] !== firstColor || + image[sr][sc] === newColor + ) { + return image + } + + image[sr][sc] = newColor + + floodFill(image, sr + 1, sc, newColor, firstColor) + floodFill(image, sr - 1, sc, newColor, firstColor) + floodFill(image, sr, sc + 1, newColor, firstColor) + floodFill(image, sr, sc - 1, newColor, firstColor) + + return image +} + diff --git a/734-sentence-similarity.js b/734.sentence-similarity.js similarity index 100% rename from 734-sentence-similarity.js rename to 734.sentence-similarity.js diff --git a/735-asteroid-collision.js b/735-asteroid-collision.js deleted file mode 100644 index f48a26b0..00000000 --- a/735-asteroid-collision.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * @param {number[]} asteroids - * @return {number[]} - */ -const asteroidCollision = function(asteroids) { - const stk = [], n = asteroids.length, {abs} = Math - for(const e of asteroids) { - while(stk.length && stk.at(-1) > 0 && e < 0 && -e > stk.at(-1)) { - stk.pop() - } - if(stk.length && stk.at(-1) > 0 && e < 0 && -e === stk.at(-1)) { - stk.pop() - }else if(stk.length && stk.at(-1) > 0 && e < 0 && -e < stk.at(-1)) { - - }else stk.push(e) - } - return stk -}; - -// another - - -/** - * @param {number[]} asteroids - * @return {number[]} - */ -const asteroidCollision = function(asteroids) { - const positive = [] - const res = [] - for(let i = 0; i < asteroids.length; i++) { - if (asteroids[i] > 0) { - positive.push(i) - } else { - const negVal = asteroids[i]; - - while(positive.length > 0 && asteroids[ positive[positive.length - 1] ] + negVal < 0 ) { - asteroids[ positive[positive.length - 1] ] = undefined - positive.pop() - } - - if (positive.length > 0) { - if (asteroids[ positive[positive.length - 1] ] + negVal > 0) { - asteroids[i] = undefined - } else if(asteroids[ positive[positive.length - 1] ] + negVal === 0) { - asteroids[i] = undefined - asteroids[ positive[positive.length - 1] ] = undefined - positive.pop() - } - } - } - } - return asteroids.filter(el => el !== undefined) -}; diff --git a/735.asteroid-collision.js b/735.asteroid-collision.js new file mode 100644 index 00000000..f3e6f364 --- /dev/null +++ b/735.asteroid-collision.js @@ -0,0 +1,19 @@ +/** + * @param {number[]} asteroids + * @return {number[]} + */ +const asteroidCollision = function(asteroids) { + const stk = [], n = asteroids.length, {abs} = Math + for(const e of asteroids) { + while(stk.length && stk.at(-1) > 0 && e < 0 && -e > stk.at(-1)) { + stk.pop() + } + if(stk.length && stk.at(-1) > 0 && e < 0 && -e === stk.at(-1)) { + stk.pop() + }else if(stk.length && stk.at(-1) > 0 && e < 0 && -e < stk.at(-1)) { + + }else stk.push(e) + } + return stk +}; + diff --git a/736-parse-lisp-expression.js b/736-parse-lisp-expression.js deleted file mode 100644 index 71dd2132..00000000 --- a/736-parse-lisp-expression.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @param {string} expression - * @return {number} - */ -const evaluate = (x) => - e( - JSON.parse( - x.replace(/[() ]|([a-z][a-z0-9]*)/g, (m) => - m === '(' ? '[' : m === ')' ? ']' : m === ' ' ? ',' : `"${m}"` - ) - ) - ) -const e = (x, v = []) => - ({ - string: () => v.find((y) => y[0] === x)[1], - number: () => x, - object: () => - ({ - add: () => e(x[1], v) + e(x[2], v), - mult: () => e(x[1], v) * e(x[2], v), - let: () => - e( - x[x.length - 1], - x - .slice(1, -1) - .reduce( - ({ v, t }, z) => - t ? { v: [[t, e(z, v)], ...v] } : { v, t: z }, - { v } - ).v - ), - }[x[0]]()), - }[typeof x]()) - -// another - -/** - * @param {string} expression - * @return {number} - */ -const evaluate = function (expression) { - const tokens = tokenizer(expression) - let i = 0 - function exec(scope) { - let value = null - const next = tokens[i++] - if (next === '(') { - scope = enter(scope) - switch (tokens[i++]) { - case 'add': - const a = exec(scope) - const b = exec(scope) - value = a + b - break - case 'mult': - const x = exec(scope) - const y = exec(scope) - value = x * y - break - case 'let': - while (tokens[i] !== '(' && tokens[i + 1] !== ')') { - scope.variables[tokens[i++]] = exec(scope) - } - value = exec(scope) - break - } - scope = exit(scope) - i++ - } else if (isNumber(next)) { - value = Number(next) - } else { - // Find variable in current scope otherwise go to parent - let t = scope - while (t) { - if (next in t.variables) { - value = t.variables[next] - break - } - t = t.parent - } - } - return value - } - return exec(newScope()) -} -function tokenizer(expression) { - const tokens = [] - let token = '' - for (const c of expression) { - if (c === '(' || c === ')') { - if (token) tokens.push(token) - tokens.push(c) - token = '' - } else if (c === ' ') { - if (token) tokens.push(token) - token = '' - } else { - token += c - } - } - if (token) { - tokens.push(token) - } - return tokens -} -function isNumber(n) { - return !isNaN(n) -} -function newScope() { - return { parent: null, variables: {} } -} -function enter(scope) { - const next = newScope() - next.parent = scope - return next -} -function exit(scope) { - return scope.parent -} diff --git a/736.parse-lisp-expression.js b/736.parse-lisp-expression.js new file mode 100644 index 00000000..6347e895 --- /dev/null +++ b/736.parse-lisp-expression.js @@ -0,0 +1,34 @@ +/** + * @param {string} expression + * @return {number} + */ +const evaluate = (x) => + e( + JSON.parse( + x.replace(/[() ]|([a-z][a-z0-9]*)/g, (m) => + m === '(' ? '[' : m === ')' ? ']' : m === ' ' ? ',' : `"${m}"` + ) + ) + ) +const e = (x, v = []) => + ({ + string: () => v.find((y) => y[0] === x)[1], + number: () => x, + object: () => + ({ + add: () => e(x[1], v) + e(x[2], v), + mult: () => e(x[1], v) * e(x[2], v), + let: () => + e( + x[x.length - 1], + x + .slice(1, -1) + .reduce( + ({ v, t }, z) => + t ? { v: [[t, e(z, v)], ...v] } : { v, t: z }, + { v } + ).v + ), + }[x[0]]()), + }[typeof x]()) + diff --git a/737-sentence-similarity-ii.js b/737.sentence-similarity-ii.js similarity index 100% rename from 737-sentence-similarity-ii.js rename to 737.sentence-similarity-ii.js diff --git a/738-monotone-increasing-digits.js b/738.monotone-increasing-digits.js similarity index 100% rename from 738-monotone-increasing-digits.js rename to 738.monotone-increasing-digits.js diff --git a/739-daily-temperatures.js b/739.daily-temperatures.js similarity index 100% rename from 739-daily-temperatures.js rename to 739.daily-temperatures.js diff --git a/74-search-a-2d-matrix.js b/74.search-a-2d-matrix.js similarity index 100% rename from 74-search-a-2d-matrix.js rename to 74.search-a-2d-matrix.js diff --git a/740-delete-and-earn.js b/740.delete-and-earn.js similarity index 100% rename from 740-delete-and-earn.js rename to 740.delete-and-earn.js diff --git a/741-cherry-pickup.js b/741.cherry-pickup.js similarity index 100% rename from 741-cherry-pickup.js rename to 741.cherry-pickup.js diff --git a/742-closest-leaf-in-a-binary-tree.js b/742.closest-leaf-in-a-binary-tree.js similarity index 100% rename from 742-closest-leaf-in-a-binary-tree.js rename to 742.closest-leaf-in-a-binary-tree.js diff --git a/743-network-delay-time.js b/743-network-delay-time.js deleted file mode 100644 index bf562c67..00000000 --- a/743-network-delay-time.js +++ /dev/null @@ -1,251 +0,0 @@ -/** - * @param {number[][]} times - * @param {number} n - * @param {number} k - * @return {number} - */ -const networkDelayTime = function(times, n, k) { - const graph = {} - for(const [u, v, w] of times) { - if(graph[u] == null) graph[u] = [] - graph[u][v] = w - } - const visited = new Array(n + 1).fill(false) - const pq = new PQ((a, b) => a[0] < b[0]) - pq.push([0, k]) - let res = 0 - while(!pq.isEmpty()) { - const [dist, cur] = pq.pop() - if(visited[cur]) continue - visited[cur] = true - n-- - res = dist - if(graph[cur]) { - for(const nxt of Object.keys(graph[cur])) { - pq.push([res + graph[cur][nxt], nxt]) - } - } - } - return n === 0 ? res : -1 -}; - -class PQ { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -/** - * @param {number[][]} times - * @param {number} N - * @param {number} K - * @return {number} - */ -const networkDelayTime = function (times, N, K) { - const mins = new Array(N).fill(Infinity) - mins[K - 1] = 0 - for (let i = 0; i < N; i++) { - for (let [u, v, t] of times) { - if (mins[u - 1] === Infinity) continue - if (mins[v - 1] > mins[u - 1] + t) { - mins[v - 1] = mins[u - 1] + t - } - } - } - return mins.includes(Infinity) ? -1 : Math.max(...mins) -} - -// another - -/** - * @param {number[][]} times - * @param {number} N - * @param {number} K - * @return {number} - */ -const networkDelayTime = function(times, N, K) { - const distances = new Array(N).fill(Infinity); - distances[K - 1] = 0; - - for(let i = 0 ; i < N -1 ; i++){ - let counter = 0; - for(let j = 0 ; j < times.length ; j++){ - const source = times[j][0]; - const target = times[j][1]; - const weight = times[j][2]; - if(distances[source - 1] + weight < distances[target - 1]){ - distances[target - 1] = distances[source - 1] + weight; - counter++ - } - } - if(counter === 0) break - } - - const res = Math.max(...distances); - return res === Infinity ? -1 : res; -}; - -// another - -/** - * @param {number[][]} times - * @param {number} N - * @param {number} K - * @return {number} - */ -const networkDelayTime = function (times, N, K) { - const hash = {} - for(const [u, v, t] of times) { - if(hash[u] == null) hash[u] = {} - hash[u][v] = t - } - const pq = new PriorityQueue((a, b) => a[0] < b[0]) - pq.push([0, K]) - const visited = Array.from(N + 1) - let res = 0 - while(!pq.isEmpty()) { - const [dist, cur] = pq.pop() - if(visited[cur]) continue - visited[cur] = true - res = dist - N-- - if(hash[cur]) { - for(let next of Object.keys(hash[cur])) { - pq.push([dist + hash[cur][next], next]) - } - } - } - return N === 0 ? res : -1 -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/743.network-delay-time.js b/743.network-delay-time.js new file mode 100644 index 00000000..94314ef9 --- /dev/null +++ b/743.network-delay-time.js @@ -0,0 +1,99 @@ +/** + * @param {number[][]} times + * @param {number} n + * @param {number} k + * @return {number} + */ +const networkDelayTime = function(times, n, k) { + const graph = {} + for(const [u, v, w] of times) { + if(graph[u] == null) graph[u] = [] + graph[u][v] = w + } + const visited = new Array(n + 1).fill(false) + const pq = new PQ((a, b) => a[0] < b[0]) + pq.push([0, k]) + let res = 0 + while(!pq.isEmpty()) { + const [dist, cur] = pq.pop() + if(visited[cur]) continue + visited[cur] = true + n-- + res = dist + if(graph[cur]) { + for(const nxt of Object.keys(graph[cur])) { + pq.push([res + graph[cur][nxt], nxt]) + } + } + } + return n === 0 ? res : -1 +}; + +class PQ { + constructor(comparator = (a, b) => a > b) { + this.heap = [] + this.top = 0 + this.comparator = comparator + } + size() { + return this.heap.length + } + isEmpty() { + return this.size() === 0 + } + peek() { + return this.heap[this.top] + } + push(...values) { + values.forEach((value) => { + this.heap.push(value) + this.siftUp() + }) + return this.size() + } + pop() { + const poppedValue = this.peek() + const bottom = this.size() - 1 + if (bottom > this.top) { + this.swap(this.top, bottom) + } + this.heap.pop() + this.siftDown() + return poppedValue + } + replace(value) { + const replacedValue = this.peek() + this.heap[this.top] = value + this.siftDown() + return replacedValue + } + + parent = (i) => ((i + 1) >>> 1) - 1 + left = (i) => (i << 1) + 1 + right = (i) => (i + 1) << 1 + greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) + swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) + siftUp = () => { + let node = this.size() - 1 + while (node > this.top && this.greater(node, this.parent(node))) { + this.swap(node, this.parent(node)) + node = this.parent(node) + } + } + siftDown = () => { + let node = this.top + while ( + (this.left(node) < this.size() && this.greater(this.left(node), node)) || + (this.right(node) < this.size() && this.greater(this.right(node), node)) + ) { + let maxChild = + this.right(node) < this.size() && + this.greater(this.right(node), this.left(node)) + ? this.right(node) + : this.left(node) + this.swap(node, maxChild) + node = maxChild + } + } +} + diff --git a/744-find-smallest-letter-greater-than-target.js b/744.find-smallest-letter-greater-than-target.js similarity index 100% rename from 744-find-smallest-letter-greater-than-target.js rename to 744.find-smallest-letter-greater-than-target.js diff --git a/745-prefix-and-suffix-search.js b/745.prefix-and-suffix-search.js similarity index 100% rename from 745-prefix-and-suffix-search.js rename to 745.prefix-and-suffix-search.js diff --git a/746-min-cost-climbing-stairs.js b/746-min-cost-climbing-stairs.js deleted file mode 100755 index b2f7b419..00000000 --- a/746-min-cost-climbing-stairs.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @param {number[]} cost - * @return {number} - */ -const minCostClimbingStairs = function(cost) { - let f1 = cost[0]; - let f2 = cost[1]; - for (let i = 2; i < cost.length; i++) { - let f_cur = cost[i] + Math.min(f1, f2); - f1 = f2; - f2 = f_cur; - } - return Math.min(f1, f2); -}; diff --git a/746.min-cost-climbing-stairs.js b/746.min-cost-climbing-stairs.js new file mode 100644 index 00000000..3d4f6161 --- /dev/null +++ b/746.min-cost-climbing-stairs.js @@ -0,0 +1,14 @@ +/** + * @param {number[]} cost + * @return {number} + */ +const minCostClimbingStairs = function(cost) { + let f1 = cost[0]; + let f2 = cost[1]; + for (let i = 2; i < cost.length; i++) { + let f_cur = cost[i] + Math.min(f1, f2); + f1 = f2; + f2 = f_cur; + } + return Math.min(f1, f2); +}; diff --git a/747-largest-number-at-least-twice-of-others.js b/747.largest-number-at-least-twice-of-others.js similarity index 100% rename from 747-largest-number-at-least-twice-of-others.js rename to 747.largest-number-at-least-twice-of-others.js diff --git a/748-shortest-completing-word.js b/748-shortest-completing-word.js deleted file mode 100644 index b791dcc9..00000000 --- a/748-shortest-completing-word.js +++ /dev/null @@ -1,65 +0,0 @@ -/** - * @param {string} licensePlate - * @param {string[]} words - * @return {string} - */ -const shortestCompletingWord = function(licensePlate, words) { - const letters = licensePlate - .replace(/\d/g, '') - .replace(/ /g, '') - .toLowerCase() - .split('') - let matchingWords = words.filter(word => { - let completingWord = true - letters.forEach(letter => { - let letterIndex = word.indexOf(letter) - if (letterIndex > -1) { - let re = new RegExp(letter) - word = word.replace(re, '') - } else { - completingWord = false - } - }) - return completingWord - }) - const wordLengths = matchingWords.map(word => word.length) - return matchingWords[wordLengths.indexOf(Math.min.apply(Math, wordLengths))] -} - -// another - -/** - * @param {string} licensePlate - * @param {string[]} words - * @return {string} - */ -const shortestCompletingWord = function(licensePlate, words) { - licensePlate = licensePlate.toLowerCase() - const plateCount = Array(26).fill(0) - let plateLength = 0 - for (let i = 0; i < licensePlate.length; i += 1) { - const code = licensePlate.charCodeAt(i) - if (code < 97 || code > 122) { - continue - } - plateCount[code - 97] += 1 - plateLength += 1 - } - const longerOrEqualWords = words.filter(word => word.length >= plateLength) - return longerOrEqualWords.reduce((shortest, word) => { - if (shortest && shortest.length <= word.length) { - return shortest - } - const wordCount = Array(26).fill(0) - for (let i = 0; i < word.length; i += 1) { - const code = word.charCodeAt(i) - wordCount[code - 97] += 1 - } - for (let i = 0; i < 26; i += 1) { - if (wordCount[i] - plateCount[i] < 0) { - return shortest - } - } - return word - }, null) -} diff --git a/748.shortest-completing-word.js b/748.shortest-completing-word.js new file mode 100644 index 00000000..64dbc291 --- /dev/null +++ b/748.shortest-completing-word.js @@ -0,0 +1,28 @@ +/** + * @param {string} licensePlate + * @param {string[]} words + * @return {string} + */ +const shortestCompletingWord = function(licensePlate, words) { + const letters = licensePlate + .replace(/\d/g, '') + .replace(/ /g, '') + .toLowerCase() + .split('') + let matchingWords = words.filter(word => { + let completingWord = true + letters.forEach(letter => { + let letterIndex = word.indexOf(letter) + if (letterIndex > -1) { + let re = new RegExp(letter) + word = word.replace(re, '') + } else { + completingWord = false + } + }) + return completingWord + }) + const wordLengths = matchingWords.map(word => word.length) + return matchingWords[wordLengths.indexOf(Math.min.apply(Math, wordLengths))] +} + diff --git a/749-contain-virus.js b/749-contain-virus.js deleted file mode 100644 index 7a6bec2c..00000000 --- a/749-contain-virus.js +++ /dev/null @@ -1,261 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const containVirus = function (grid) { - let ans = 0 - while (true) { - const walls = model(grid) - if (walls === 0) break - ans += walls - } - return ans - function model(grid) { - const m = grid.length, - n = grid[0].length - const virus = [], - toInfect = [] - const visited = Array.from({ length: m }, () => Array(n).fill(0)) - const walls = [] - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - if (grid[i][j] === 1 && visited[i][j] === 0) { - virus.push(new Set()) - toInfect.push(new Set()) - walls.push([0]) - dfs( - grid, - visited, - virus[virus.length - 1], - toInfect[toInfect.length - 1], - walls[walls.length - 1], - i, - j - ) - } - } - } - let maxArea = 0, - idx = -1 - for (let i = 0; i < toInfect.length; i++) { - if (toInfect[i].size > maxArea) { - maxArea = toInfect[i].size - idx = i - } - } - if (idx === -1) return 0 - for (let i = 0; i < toInfect.length; i++) { - if (i !== idx) { - for (let key of toInfect[i]) grid[(key / n) >> 0][key % n] = 1 - } else { - for (let key of virus[i]) grid[(key / n) >> 0][key % n] = -1 - } - } - return walls[idx][0] - } - function dfs(grid, visited, virus, toInfect, wall, row, col) { - const m = grid.length, - n = grid[0].length - if (row < 0 || row >= m || col < 0 || col >= n || visited[row][col] === 1) - return - if (grid[row][col] === 1) { - visited[row][col] = 1 - virus.add(row * n + col) - const dir = [0, -1, 0, 1, 0] - for (let i = 0; i < 4; i++) - dfs( - grid, - visited, - virus, - toInfect, - wall, - row + dir[i], - col + dir[i + 1] - ) - } else if (grid[row][col] === 0) { - wall[0]++ - toInfect.add(row * n + col) - } - } -} - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -const containVirus = (grid) => { - const m = grid.length; - const n = grid[0].length; - let ans = 0; - while (true) { - // list of regions can spread virus - const regions = []; - const visited = Array.from({ length: m }, () => Array(n).fill(false)); - for (let i = 0; i < m; i++) { - for (let j = 0; j < n; j++) { - if (grid[i][j] === 1 && !visited[i][j]) { - const region = new Region(); - dfs(grid, i, j, region, visited); - if (region.uninfected.size > 0) regions.push(region); - } - } - } - - if (regions.length === 0) break; - regions.sort((a, b) => a.uninfected.size - b.uninfected.size); - let idx = -1, wall = -Infinity - for(let i = 0, len = regions.length; i < len; i++) { - if(regions[i].uninfected.size > wall) { - wall = regions[i].uninfected.size - idx = i - } - } - const mostToBeInfected = regions[idx] - ans += mostToBeInfected.wallNeeded - regions.splice(idx, 1) - for (let x of mostToBeInfected.infected) { - let i = (x / n) >> 0, - j = x % n; - grid[i][j] = 2; - } - - for (let region of regions) { - for (let x of region.uninfected) { - let i = (x / n) >> 0, - j = x % n; - grid[i][j] = 1; - } - } - } - - return ans; - function dfs(grid, i, j, region, visited) { - if (i < 0 || i == m || j < 0 || j == n) return; - - if (grid[i][j] === 1 && !visited[i][j]) { - visited[i][j] = true; - region.infected.add(i * n + j); - dfs(grid, i - 1, j, region, visited); - dfs(grid, i + 1, j, region, visited); - dfs(grid, i, j - 1, region, visited); - dfs(grid, i, j + 1, region, visited); - } else if (grid[i][j] === 0) { - region.wallNeeded += 1; - region.uninfected.add(i * n + j); - } - } -}; -class Region { - constructor() { - this.wallNeeded = 0; - this.infected = new Set(); - this.uninfected = new Set(); - } -} - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -const containVirus = function (grid) { - const infected = 1 - const healthy = 0 - const quarantined = 2 - const directions = [ - [1, 0], - [-1, 0], - [0, 1], - [0, -1], - ] - const mod = 100 - const encode = (row, col) => row + col * mod - const decode = (num) => [num % mod, Math.floor(num / mod)] - const disjointSet = {} - for (let row = 0; row < grid.length; row++) { - for (let col = 0; col < grid[row].length; col++) { - const coord = encode(row, col) - disjointSet[coord] = coord - if (grid[row][col] === 0) continue - if (grid[row][col - 1] === 1) union(coord, encode(row, col - 1)) - if (row > 0 && grid[row - 1][col] === 1) - union(coord, encode(row - 1, col)) - } - } - let numWalls = 0 - while (true) { - const impact = quarantineAndContaminate() - if (impact === 0) return numWalls - numWalls += impact - spreadVirus() - } - function find(coord) { - return (disjointSet[coord] = - disjointSet[coord] === coord ? coord : find(disjointSet[coord])) - } - function union(coord, toCoord) { - return (disjointSet[find(coord)] = find(toCoord)) - } - function quarantineAndContaminate() { - const impact = new Map() - for (let row = 0; row < grid.length; row++) { - for (let col = 0; col < grid[row].length; col++) { - if (grid[row][col] !== infected) continue - const root = find(encode(row, col)) - if (!impact.has(root)) impact.set(root, new Set()) - for (let [down, right] of directions) { - if (grid[row + down] && grid[row + down][col + right] === healthy) { - impact.get(root).add(encode(row + down, col + right)) - } - } - } - } - let impactedCoords = new Set() - let root = null - for (let [node, coords] of impact) { - if (impactedCoords.size < coords.size) { - impactedCoords = coords - root = node - } - } - if (impactedCoords.size === 0) return 0 - return quarantine(...decode(root)) - } - function quarantine(row, col) { - if (row < 0 || row >= grid.length || col < 0 || col >= grid[0].length) - return 0 - if (grid[row][col] === 2) return 0 - if (grid[row][col] === 0) return 1 - let totalWalls = 0 - grid[row][col] = 2 - for (let [down, right] of directions) { - totalWalls += quarantine(row + down, col + right) - } - return totalWalls - } - function spreadVirus() { - const infectedCoords = new Set() - for (let row = 0; row < grid.length; row++) { - for (let col = 0; col < grid[row].length; col++) { - if (grid[row][col] !== healthy) continue - for (let [down, right] of directions) { - if (grid[row + down] && grid[row + down][col + right] === infected) { - infectedCoords.add(encode(row, col)) - } - } - } - } - for (let coord of infectedCoords) { - const [row, col] = decode(coord) - grid[row][col] = 1 - for (let [down, right] of directions) { - if (grid[row + down] && grid[row + down][col + right] === 1) { - union(coord, encode(row + down, col + right)) - } - } - } - } -} diff --git a/749.contain-virus.js b/749.contain-virus.js new file mode 100644 index 00000000..2b430f2f --- /dev/null +++ b/749.contain-virus.js @@ -0,0 +1,81 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const containVirus = function (grid) { + let ans = 0 + while (true) { + const walls = model(grid) + if (walls === 0) break + ans += walls + } + return ans + function model(grid) { + const m = grid.length, + n = grid[0].length + const virus = [], + toInfect = [] + const visited = Array.from({ length: m }, () => Array(n).fill(0)) + const walls = [] + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] === 1 && visited[i][j] === 0) { + virus.push(new Set()) + toInfect.push(new Set()) + walls.push([0]) + dfs( + grid, + visited, + virus[virus.length - 1], + toInfect[toInfect.length - 1], + walls[walls.length - 1], + i, + j + ) + } + } + } + let maxArea = 0, + idx = -1 + for (let i = 0; i < toInfect.length; i++) { + if (toInfect[i].size > maxArea) { + maxArea = toInfect[i].size + idx = i + } + } + if (idx === -1) return 0 + for (let i = 0; i < toInfect.length; i++) { + if (i !== idx) { + for (let key of toInfect[i]) grid[(key / n) >> 0][key % n] = 1 + } else { + for (let key of virus[i]) grid[(key / n) >> 0][key % n] = -1 + } + } + return walls[idx][0] + } + function dfs(grid, visited, virus, toInfect, wall, row, col) { + const m = grid.length, + n = grid[0].length + if (row < 0 || row >= m || col < 0 || col >= n || visited[row][col] === 1) + return + if (grid[row][col] === 1) { + visited[row][col] = 1 + virus.add(row * n + col) + const dir = [0, -1, 0, 1, 0] + for (let i = 0; i < 4; i++) + dfs( + grid, + visited, + virus, + toInfect, + wall, + row + dir[i], + col + dir[i + 1] + ) + } else if (grid[row][col] === 0) { + wall[0]++ + toInfect.add(row * n + col) + } + } +} + diff --git a/75-sort-colors.js b/75.sort-colors.js similarity index 100% rename from 75-sort-colors.js rename to 75.sort-colors.js diff --git a/750-number-of-corner-rectangles.js b/750-number-of-corner-rectangles.js deleted file mode 100644 index 8f21c4a9..00000000 --- a/750-number-of-corner-rectangles.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const countCornerRectangles = function (grid) { - let ans = 0 - for (let i = 0; i < grid.length - 1; i++) { - for (let j = i + 1; j < grid.length; j++) { - let counter = 0 - for (let k = 0; k < grid[0].length; k++) { - if (grid[i][k] === 1 && grid[j][k] === 1) counter++ - } - ans += (counter * (counter - 1)) / 2 - } - } - return ans -} - -// another - -// optimized - -/** - * @param {number[][]} grid - * @return {number} - */ -const countCornerRectangles = function (grid) { - let ans = 0 - let largeLoopLen, smLoopLen, r - if(grid.length > grid[0].length) { - r = false - largeLoopLen = grid.length - smLoopLen = grid[0].length - } else { - r = true - largeLoopLen = grid[0].length - smLoopLen = grid.length - } - for (let i = 0; i < smLoopLen - 1; i++) { - for (let j = i + 1; j < smLoopLen; j++) { - let counter = 0 - for (let k = 0; k < largeLoopLen; k++) { - if(r) { - if (grid[i][k] === 1 && grid[j][k] === 1) counter++ - } else { - if (grid[k][i] === 1 && grid[k][j] === 1) counter++ - } - - } - ans += (counter * (counter - 1)) / 2 - } - } - return ans -} diff --git a/750.number-of-corner-rectangles.js b/750.number-of-corner-rectangles.js new file mode 100644 index 00000000..2247858f --- /dev/null +++ b/750.number-of-corner-rectangles.js @@ -0,0 +1,18 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const countCornerRectangles = function (grid) { + let ans = 0 + for (let i = 0; i < grid.length - 1; i++) { + for (let j = i + 1; j < grid.length; j++) { + let counter = 0 + for (let k = 0; k < grid[0].length; k++) { + if (grid[i][k] === 1 && grid[j][k] === 1) counter++ + } + ans += (counter * (counter - 1)) / 2 + } + } + return ans +} + diff --git a/751-ip-to-cidr.js b/751.ip-to-cidr.js similarity index 100% rename from 751-ip-to-cidr.js rename to 751.ip-to-cidr.js diff --git a/752-open-the-lock.js b/752-open-the-lock.js deleted file mode 100755 index 26747c8c..00000000 --- a/752-open-the-lock.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @param {string[]} deadends - * @param {string} target - * @return {number} - */ -const openLock = function(deadends, target, count = 0) { - let deadSet = new Set(deadends); - let visited = new Set(); - if (deadSet.has("0000")) { - return -1; - } - - let q = []; - q.push("0000"); - visited.add("0000"); - - let steps = 0; - while (q.length > 0) { - let len = q.length; - - for (let j = 0; j < len; j++) { - let cur = q.shift(); - - for (let i = 0; i < 4; i++) { - let slot = parseInt(cur[i]); - let before = cur.substr(0, i); - let after = cur.substr(i + 1); - - let left = (10 + slot - 1) % 10; - let leftCode = before + left + after; - if (!visited.has(leftCode) && !deadSet.has(leftCode)) { - if (leftCode === target) { - return steps + 1; - } - - visited.add(leftCode); - q.push(leftCode); - } - - let right = (10 + slot + 1) % 10; - let rightCode = before + right + after; - if (!visited.has(rightCode) && !deadSet.has(rightCode)) { - if (rightCode === target) { - return steps + 1; - } - - visited.add(rightCode); - q.push(rightCode); - } - } - } - steps++; - } - - return -1; -}; diff --git a/752.open-the-lock.js b/752.open-the-lock.js new file mode 100644 index 00000000..53c151e0 --- /dev/null +++ b/752.open-the-lock.js @@ -0,0 +1,56 @@ +/** + * @param {string[]} deadends + * @param {string} target + * @return {number} + */ +const openLock = function(deadends, target, count = 0) { + let deadSet = new Set(deadends); + let visited = new Set(); + if (deadSet.has("0000")) { + return -1; + } + + let q = []; + q.push("0000"); + visited.add("0000"); + + let steps = 0; + while (q.length > 0) { + let len = q.length; + + for (let j = 0; j < len; j++) { + let cur = q.shift(); + + for (let i = 0; i < 4; i++) { + let slot = parseInt(cur[i]); + let before = cur.substr(0, i); + let after = cur.substr(i + 1); + + let left = (10 + slot - 1) % 10; + let leftCode = before + left + after; + if (!visited.has(leftCode) && !deadSet.has(leftCode)) { + if (leftCode === target) { + return steps + 1; + } + + visited.add(leftCode); + q.push(leftCode); + } + + let right = (10 + slot + 1) % 10; + let rightCode = before + right + after; + if (!visited.has(rightCode) && !deadSet.has(rightCode)) { + if (rightCode === target) { + return steps + 1; + } + + visited.add(rightCode); + q.push(rightCode); + } + } + } + steps++; + } + + return -1; +}; diff --git a/754-reach-a-number.js b/754.reach-a-number.js similarity index 100% rename from 754-reach-a-number.js rename to 754.reach-a-number.js diff --git a/755-pour-water.js b/755-pour-water.js deleted file mode 100644 index 1cacf38d..00000000 --- a/755-pour-water.js +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @param {number[]} heights - * @param {number} V - * @param {number} K - * @return {number[]} - */ -const pourWater = function (heights, V, K) { - if (!V) return heights - let bottom = K - //iterate through from k to find thee lowest bottom - for (let i = K; i >= 0; i--) { - if (heights[i] > heights[bottom]) break - if (heights[i] < heights[bottom]) bottom = i - } - //if bottom is not k increase height of bottom - //and run again but decrease water droplet V by one - if (bottom !== K) { - heights[bottom]++ - return pourWater(heights, V - 1, K) - } - for (let i = K + 1; i < heights.length; i++) { - if (heights[i] > heights[bottom]) break - if (heights[i] < heights[bottom]) bottom = i - } - heights[bottom]++ - return pourWater(heights, V - 1, K) -} - -// another - -/** - * @param {number[]} heights - * @param {number} V - * @param {number} K - * @return {number[]} - */ -const pourWater = function (heights, V, K) { - let cur = K - for (let i = 0; i < V; i++) { - // Move left - while (cur > 0 && heights[cur - 1] <= heights[cur]) { - cur-- - } - // Move right - while (cur < heights.length - 1 && heights[cur + 1] <= heights[cur]) { - cur++ - } - // Move left to K - while(cur > K && heights[cur - 1] === heights[cur]) { - cur-- - } - heights[cur]++ - } - return heights -} - diff --git a/755.pour-water.js b/755.pour-water.js new file mode 100644 index 00000000..4ae60f4e --- /dev/null +++ b/755.pour-water.js @@ -0,0 +1,28 @@ +/** + * @param {number[]} heights + * @param {number} V + * @param {number} K + * @return {number[]} + */ +const pourWater = function (heights, V, K) { + if (!V) return heights + let bottom = K + //iterate through from k to find thee lowest bottom + for (let i = K; i >= 0; i--) { + if (heights[i] > heights[bottom]) break + if (heights[i] < heights[bottom]) bottom = i + } + //if bottom is not k increase height of bottom + //and run again but decrease water droplet V by one + if (bottom !== K) { + heights[bottom]++ + return pourWater(heights, V - 1, K) + } + for (let i = K + 1; i < heights.length; i++) { + if (heights[i] > heights[bottom]) break + if (heights[i] < heights[bottom]) bottom = i + } + heights[bottom]++ + return pourWater(heights, V - 1, K) +} + diff --git a/756-pyramid-transition-matrix.js b/756.pyramid-transition-matrix.js similarity index 100% rename from 756-pyramid-transition-matrix.js rename to 756.pyramid-transition-matrix.js diff --git a/757-set-intersection-size-at-least-two.js b/757-set-intersection-size-at-least-two.js deleted file mode 100644 index c89077ec..00000000 --- a/757-set-intersection-size-at-least-two.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @param {number[][]} intervals - * @return {number} - */ -const intersectionSizeTwo = function(intervals) { - let highest = Number.NEGATIVE_INFINITY; - let secondHighest = Number.NEGATIVE_INFINITY; - return intervals - .sort((a, b) => a[1] - b[1]) - .reduce((sum, interval) => { - if (interval[0] > secondHighest) { - secondHighest = interval[1]; - highest = interval[1] - 1; - return sum + 2; - } - else if (interval[0] > highest) { - highest = secondHighest; - secondHighest = interval[1]; - return sum + 1; - } - return sum; - }, 0); -}; - -// another - -/** - * @param {number[][]} intervals - * @return {number} - */ -const intersectionSizeTwo = function(intervals) { - intervals.sort((a, b) => a[1] - b[1]); - - let n = intervals.length; - if (n === 0) return 0; - - let count = 2; - let last = intervals[0][1]; - let sec_last = intervals[0][1] - 1; - - for (let i = 1; i < n; i++) { - if (intervals[i][0] <= sec_last) continue; - else if (intervals[i][0] <= last) { - sec_last = last; - last = intervals[i][1]; - count++; - } else { - last = intervals[i][1]; - sec_last = intervals[i][1] - 1; - count += 2; - } - } - return count; -}; - -// another - -/** - * @param {number[][]} intervals - * @return {number} - */ -const intersectionSizeTwo = function (intervals) { - if (intervals.length === 1) return 2 - intervals.sort((a, b) => (a[1] !== b[1] ? a[1] - b[1] : b[0] - a[0])) - let right = intervals[0][1] - let left = right - 1 - let result = 2 - for (let i = 1, len = intervals.length; i < len; i++) { - const curr = intervals[i] - if (curr[0] <= right && curr[0] > left) { - result++ - left = right - right = curr[1] - } else if (curr[0] > right) { - result += 2 - left = curr[1] - 1 - right = curr[1] - } - } - - return result -} - diff --git a/757.set-intersection-size-at-least-two.js b/757.set-intersection-size-at-least-two.js new file mode 100644 index 00000000..4c890c22 --- /dev/null +++ b/757.set-intersection-size-at-least-two.js @@ -0,0 +1,24 @@ +/** + * @param {number[][]} intervals + * @return {number} + */ +const intersectionSizeTwo = function(intervals) { + let highest = Number.NEGATIVE_INFINITY; + let secondHighest = Number.NEGATIVE_INFINITY; + return intervals + .sort((a, b) => a[1] - b[1]) + .reduce((sum, interval) => { + if (interval[0] > secondHighest) { + secondHighest = interval[1]; + highest = interval[1] - 1; + return sum + 2; + } + else if (interval[0] > highest) { + highest = secondHighest; + secondHighest = interval[1]; + return sum + 1; + } + return sum; + }, 0); +}; + diff --git a/758-bold-words-in-string.js b/758.bold-words-in-string.js similarity index 100% rename from 758-bold-words-in-string.js rename to 758.bold-words-in-string.js diff --git a/759-employee-free-time.js b/759-employee-free-time.js deleted file mode 100644 index 1bb666d6..00000000 --- a/759-employee-free-time.js +++ /dev/null @@ -1,181 +0,0 @@ -/** - -We are given a list schedule of employees, which represents the working time for each employee. - -Each employee has a list of non-overlapping Intervals, and these intervals are in sorted order. - -Return the list of finite intervals representing common, positive-length free time for all employees, -also in sorted order. - -(Even though we are representing Intervals in the form [x, y], the objects inside are Intervals, -not lists or arrays. For example, schedule[0][0].start = 1, schedule[0][0].end = 2, -and schedule[0][0][0] is not defined). Also, we wouldn't include intervals like [5, 5] in our answer, -as they have zero length. - -Example 1: - -Input: schedule = [[[1,2],[5,6]],[[1,3]],[[4,10]]] -Output: [[3,4]] -Explanation: There are a total of three employees, and all common -free time intervals would be [-inf, 1], [3, 4], [10, inf]. -We discard any intervals that contain inf as they aren't finite. -Example 2: - -Input: schedule = [[[1,3],[6,7]],[[2,4]],[[2,5],[9,12]]] -Output: [[5,6],[7,9]] - -Constraints: - -1 <= schedule.length , schedule[i].length <= 50 -0 <= schedule[i].start < schedule[i].end <= 10^8 - -*/ - - -/** - * // Definition for an Interval. - * function Interval(start, end) { - * this.start = start; - * this.end = end; - * }; - */ -/** - * // Definition for an Interval. - * function Interval(start, end) { - * this.start = start; - * this.end = end; - * }; - */ - -/** - * @param {Interval[][]} schedule - * @return {Interval[]} - */ -const employeeFreeTime = function(schedule) { - const n = schedule.length - const time = mergeSort(schedule, 0, n - 1) - const free = [] - let end = time[0].end - for(let i = 1; i < time.length; i++) { - if(time[i].start > end) { - free.push(new Interval(end, time[i].start)) - } - end = Math.max(end, time[i].end) - } - return free -} - -function mergeSort(schedule, l, r) { - if(l === r) return schedule[l] - const mid = l + ((r - l) >> 1) - const left = mergeSort(schedule, l, mid) - const right = mergeSort(schedule, mid + 1, r) - return merge(left, right) -} - -function merge(A, B) { - const res = [] - const m = A.length, n = B.length - let i = 0, j = 0 - while(i < m || j < n) { - if(i === m) { - res.push(B[j++]) - } else if(j === n) { - res.push(A[i++]) - } else if(A[i].start < B[j].start) { - res.push(A[i++]) - } else { - res.push(B[j++]) - } - } - return res -} - - -// another - -const employeeFreeTime = function(schedule) { - const intervals = [] - schedule.forEach(s => s.forEach(t => intervals.push(t))) - intervals.sort((a, b) => - a.start !== b.start ? a.start - b.start : a.end - b.end - ) - let i1 = intervals[0] - const res = [] - for (let interval of intervals.slice(1)) { - let i2 = interval - if (i1.end >= i2.start) { - i1.end = Math.max(i1.end, i2.end) - } else { - res.push(new Interval(i1.end, i2.start)) - i1 = i2 - } - } - return res -} - -// another - -/** - * // Definition for an Interval. - * function Interval(start, end) { - * this.start = start; - * this.end = end; - * }; - */ - -/** - * @param {Interval[][]} schedule - * @return {Interval[]} - */ -const employeeFreeTime = function (schedule) { - const res = [], timeLine = [] - schedule.forEach(e => timeLine.push(...e)) - timeLine.sort((a, b) => a.start - b.start) - let tmp = timeLine[0] - for(let i = 1, n = timeLine.length; i < n; i++) { - const el = timeLine[i] - if(el.start > tmp.end) { - res.push(new Interval(tmp.end, el.start)) - tmp = el - } else { - tmp = el.end > tmp.end ? el : tmp - } - } - return res -} - -// another - -/** - * // Definition for an Interval. - * function Interval(start, end) { - * this.start = start; - * this.end = end; - * }; - */ - -/** - * @param {Interval[][]} schedule - * @return {Interval[]} - */ -var employeeFreeTime = function(schedule) { - const arr = schedule.reduce((ac, e) => { - ac.push(...e) - return ac - }, []) - arr.sort((a, b) => a.start - b.start || b.end - a.end) - const n = arr.length - const res = [] - let end = arr[0].end - for(let i = 1; i < n; i++) { - const cur = arr[i] - if(cur.start > end) { - res.push(new Interval(end, cur.start)) - } - - end = Math.max(end, cur.end) - } - - return res -}; diff --git a/759.employee-free-time.js b/759.employee-free-time.js new file mode 100644 index 00000000..78f6c014 --- /dev/null +++ b/759.employee-free-time.js @@ -0,0 +1,94 @@ +/** + +We are given a list schedule of employees, which represents the working time for each employee. + +Each employee has a list of non-overlapping Intervals, and these intervals are in sorted order. + +Return the list of finite intervals representing common, positive-length free time for all employees, +also in sorted order. + +(Even though we are representing Intervals in the form [x, y], the objects inside are Intervals, +not lists or arrays. For example, schedule[0][0].start = 1, schedule[0][0].end = 2, +and schedule[0][0][0] is not defined). Also, we wouldn't include intervals like [5, 5] in our answer, +as they have zero length. + +Example 1: + +Input: schedule = [[[1,2],[5,6]],[[1,3]],[[4,10]]] +Output: [[3,4]] +Explanation: There are a total of three employees, and all common +free time intervals would be [-inf, 1], [3, 4], [10, inf]. +We discard any intervals that contain inf as they aren't finite. +Example 2: + +Input: schedule = [[[1,3],[6,7]],[[2,4]],[[2,5],[9,12]]] +Output: [[5,6],[7,9]] + +Constraints: + +1 <= schedule.length , schedule[i].length <= 50 +0 <= schedule[i].start < schedule[i].end <= 10^8 + +*/ + + +/** + * // Definition for an Interval. + * function Interval(start, end) { + * this.start = start; + * this.end = end; + * }; + */ +/** + * // Definition for an Interval. + * function Interval(start, end) { + * this.start = start; + * this.end = end; + * }; + */ + +/** + * @param {Interval[][]} schedule + * @return {Interval[]} + */ +const employeeFreeTime = function(schedule) { + const n = schedule.length + const time = mergeSort(schedule, 0, n - 1) + const free = [] + let end = time[0].end + for(let i = 1; i < time.length; i++) { + if(time[i].start > end) { + free.push(new Interval(end, time[i].start)) + } + end = Math.max(end, time[i].end) + } + return free +} + +function mergeSort(schedule, l, r) { + if(l === r) return schedule[l] + const mid = l + ((r - l) >> 1) + const left = mergeSort(schedule, l, mid) + const right = mergeSort(schedule, mid + 1, r) + return merge(left, right) +} + +function merge(A, B) { + const res = [] + const m = A.length, n = B.length + let i = 0, j = 0 + while(i < m || j < n) { + if(i === m) { + res.push(B[j++]) + } else if(j === n) { + res.push(A[i++]) + } else if(A[i].start < B[j].start) { + res.push(A[i++]) + } else { + res.push(B[j++]) + } + } + return res +} + + diff --git a/76-minimum-window-substring.js b/76.minimum-window-substring.js similarity index 100% rename from 76-minimum-window-substring.js rename to 76.minimum-window-substring.js diff --git a/760-find-anagram-mappings.js b/760.find-anagram-mappings.js similarity index 100% rename from 760-find-anagram-mappings.js rename to 760.find-anagram-mappings.js diff --git a/761-special-binary-string.js b/761.special-binary-string.js similarity index 100% rename from 761-special-binary-string.js rename to 761.special-binary-string.js diff --git a/762-prime-number-of-set-bits-in-binary-representation.js b/762.prime-number-of-set-bits-in-binary-representation.js old mode 100755 new mode 100644 similarity index 100% rename from 762-prime-number-of-set-bits-in-binary-representation.js rename to 762.prime-number-of-set-bits-in-binary-representation.js diff --git a/763-partition-labels.js b/763.partition-labels.js similarity index 100% rename from 763-partition-labels.js rename to 763.partition-labels.js diff --git a/764-largest-plus-sign.js b/764.largest-plus-sign.js similarity index 100% rename from 764-largest-plus-sign.js rename to 764.largest-plus-sign.js diff --git a/765-couples-holding-hands.js b/765-couples-holding-hands.js deleted file mode 100644 index 3b5aa4d9..00000000 --- a/765-couples-holding-hands.js +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @param {number[]} row - * @return {number} - */ -const minSwapsCouples = function (row) { - let res = 0, - N = row.length - const ptn = new Array(N).fill(0) - const pos = new Array(N).fill(0) - for (let i = 0; i < N; i++) { - ptn[i] = i % 2 === 0 ? i + 1 : i - 1 - pos[row[i]] = i - } - for (let i = 0; i < N; i++) { - for (let j = ptn[pos[ptn[row[i]]]]; i !== j; j = ptn[pos[ptn[row[i]]]]) { - swap(row, i, j) - swap(pos, row[i], row[j]) - res++ - } - } - return res -} - -function swap(arr, i, j) { - ;[arr[i], arr[j]] = [arr[j], arr[i]] -} - -// another - -/** - * @param {number[]} row - * @return {number} - */ -const minSwapsCouples = function (row) { - const parents = Array.from({ length: row.length / 2 }, (_, i) => i) - const positions = new Map() - for (let i = 0; i < row.length / 2; i++) { - const left = Math.floor(row[i * 2] / 2) - const right = Math.floor(row[i * 2 + 1] / 2) - if (positions.has(left)) { - union(i, positions.get(left)) - } else { - positions.set(left, i) - } - if (positions.has(right)) { - union(i, positions.get(right)) - } else { - positions.set(right, i) - } - } - - const uniqueRoots = new Set() - for (const parent of parents) { - uniqueRoots.add(find(parent)) - } - return parents.length - uniqueRoots.size - - function union(a, b) { - const aRoot = find(a) - const bRoot = find(b) - parents[aRoot] = bRoot - } - function root(x) { - while (x !== parents[x]) { - parents[x] = parents[parents[x]] - x = parents[x] - } - return x - } - function find(node) { - return root(node) - } -} - -// another - -/** - * @param {number[]} row - * @return {number} - */ -const minSwapsCouples = function (row) { - let res = 0 - const n = row.length - const ptn = Array(n).fill(0), pos = Array(n).fill(0) - - for(let i = 0; i < n; i++) { - ptn[i] = (i % 2 === 0 ? i + 1 : i - 1) - pos[row[i]] = i - } - - for (let i = 0; i < n ;i++) { - for (let j = ptn[pos[ptn[row[i]]]]; i != j; j = ptn[pos[ptn[row[i]]]]) { - swap(row, i, j); - swap(pos, row[i], row[j]); - res++; - } - } - - return res - - function swap(arr, i, j) { - const val = arr[i] - arr[i] = arr[j] - arr[j] = val - } -} diff --git a/765.couples-holding-hands.js b/765.couples-holding-hands.js new file mode 100644 index 00000000..13dbbf7d --- /dev/null +++ b/765.couples-holding-hands.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} row + * @return {number} + */ +const minSwapsCouples = function (row) { + let res = 0, + N = row.length + const ptn = new Array(N).fill(0) + const pos = new Array(N).fill(0) + for (let i = 0; i < N; i++) { + ptn[i] = i % 2 === 0 ? i + 1 : i - 1 + pos[row[i]] = i + } + for (let i = 0; i < N; i++) { + for (let j = ptn[pos[ptn[row[i]]]]; i !== j; j = ptn[pos[ptn[row[i]]]]) { + swap(row, i, j) + swap(pos, row[i], row[j]) + res++ + } + } + return res +} + +function swap(arr, i, j) { + ;[arr[i], arr[j]] = [arr[j], arr[i]] +} + diff --git a/766-toeplitz-matrix.js b/766-toeplitz-matrix.js deleted file mode 100755 index 19b658a1..00000000 --- a/766-toeplitz-matrix.js +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @param {number[][]} matrix - * @return {boolean} - */ -const isToeplitzMatrix = function(matrix) { - for (let r = 0; r < matrix.length; r++) { - for (let c = 0; c < matrix[0].length; c++) { - if (r > 0 && c > 0 && matrix[r - 1][c - 1] !== matrix[r][c]) { - return false; - } - } - } - return true; -}; - -console.log(isToeplitzMatrix([[1, 2, 3, 4], [5, 1, 2, 3], [9, 5, 1, 2]])); - -console.log(isToeplitzMatrix([[1, 2], [2, 2]])); diff --git a/766.toeplitz-matrix.js b/766.toeplitz-matrix.js new file mode 100644 index 00000000..b292c61b --- /dev/null +++ b/766.toeplitz-matrix.js @@ -0,0 +1,18 @@ +/** + * @param {number[][]} matrix + * @return {boolean} + */ +const isToeplitzMatrix = function(matrix) { + for (let r = 0; r < matrix.length; r++) { + for (let c = 0; c < matrix[0].length; c++) { + if (r > 0 && c > 0 && matrix[r - 1][c - 1] !== matrix[r][c]) { + return false; + } + } + } + return true; +}; + +console.log(isToeplitzMatrix([[1, 2, 3, 4], [5, 1, 2, 3], [9, 5, 1, 2]])); + +console.log(isToeplitzMatrix([[1, 2], [2, 2]])); diff --git a/767-reorganize-string.js b/767-reorganize-string.js deleted file mode 100644 index be449e84..00000000 --- a/767-reorganize-string.js +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @param {string} s - * @return {string} - */ -const reorganizeString = function (s) { - const freq = Array(26).fill(0) - const a = 'a'.charCodeAt(0), n = s.length - for(const e of s) { - freq[e.charCodeAt(0) - a]++ - } - let max = 0, maxIdx = 0 - for(let i = 0; i < 26; i++) { - if(freq[i] > max) { - max = freq[i] - maxIdx = i - } - } - - if(max > (n + 1) / 2) return '' - - const res = Array(n) - - let idx = 0 - while(freq[maxIdx]) { - res[idx] = String.fromCharCode(a + maxIdx) - idx += 2 - freq[maxIdx]-- - } - - for(let i = 0; i < 26; i++) { - while(freq[i]) { - if(idx >= n) idx = 1 - res[idx] = String.fromCharCode(i + a) - idx += 2 - freq[i]-- - } - } - - return res.join('') -} - -// another - - -/** - * @param {string} S - * @return {string} - */ -const reorganizeString = function(S) { - if (!S || S.length <= 1) { - return S; - } - const freqs = Array(26).fill(0); - const acode = 'a'.charCodeAt(0); - for (let i = 0, n = S.length; i < n; i++) { - const index = S.charCodeAt(i) - acode; - freqs[index]++; - if (freqs[index] > Math.ceil(n / 2)) { - return ''; - } - } - const list = []; - for (let i = 0, n = S.length; i < 26; i++) { - if (freqs[i] === 0) { - continue; - } - list.push({ch: String.fromCharCode(i + acode), freq: freqs[i]}); - } - list.sort((l1, l2) => l2.freq - l1.freq); - const parts = []; - for (let i = 0, n = list[0].freq; i < n; i++) { - parts.push(list[0].ch); - } - let idx = 0; - for (let i = 1, n = list.length; i < n; i++) { - for (let j = 0, m = list[i].freq; j < m; j++) { - idx %= list[0].freq; - parts[idx++] += list[i].ch; - } - } - return parts.join(''); -}; - -// another - -/** - * @param {string} s - * @return {string} - */ -const reorganizeString = function(s) { - const arr = Array(26).fill(0), a = 'a'.charCodeAt(0) - for(let ch of s) arr[ch.charCodeAt(0) - a]++ - let max = 0, idx = -1 - for(let i = 0; i < 26; i++) { - if(arr[i] > max) { - max = arr[i] - idx = i - } - } - const n = s.length - const res = Array(n) - if(max > (n + 1) / 2) return '' - - let i = 0 - while(arr[idx] > 0) { - res[i] = String.fromCharCode(a + idx) - i += 2 - arr[idx]-- - } - - for(let j = 0; j < 26; j++) { - while(arr[j]) { - if(i >= n) i = 1 - res[i] = String.fromCharCode(a + j) - i += 2 - arr[j]-- - } - } - return res.join('') -}; diff --git a/767.reorganize-string.js b/767.reorganize-string.js new file mode 100644 index 00000000..758188f9 --- /dev/null +++ b/767.reorganize-string.js @@ -0,0 +1,41 @@ +/** + * @param {string} s + * @return {string} + */ +const reorganizeString = function (s) { + const freq = Array(26).fill(0) + const a = 'a'.charCodeAt(0), n = s.length + for(const e of s) { + freq[e.charCodeAt(0) - a]++ + } + let max = 0, maxIdx = 0 + for(let i = 0; i < 26; i++) { + if(freq[i] > max) { + max = freq[i] + maxIdx = i + } + } + + if(max > (n + 1) / 2) return '' + + const res = Array(n) + + let idx = 0 + while(freq[maxIdx]) { + res[idx] = String.fromCharCode(a + maxIdx) + idx += 2 + freq[maxIdx]-- + } + + for(let i = 0; i < 26; i++) { + while(freq[i]) { + if(idx >= n) idx = 1 + res[idx] = String.fromCharCode(i + a) + idx += 2 + freq[i]-- + } + } + + return res.join('') +} + diff --git a/768-max-chunks-to-make-sorted-II.js b/768-max-chunks-to-make-sorted-II.js deleted file mode 100755 index 41df4238..00000000 --- a/768-max-chunks-to-make-sorted-II.js +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @param {number[]} arr - * @return {number} - */ -const maxChunksToSorted = function(arr) { - const clonedArr = arr.slice(0); - let sum1 = 0; - let sum2 = 0; - let res = 0; - clonedArr.sort((a, b) => a - b); - for (let i = 0; i < arr.length; i++) { - sum1 += arr[i]; - sum2 += clonedArr[i]; - if (sum1 === sum2) res += 1; - } - return res; -}; diff --git a/768.max-chunks-to-make-sorted-II.js b/768.max-chunks-to-make-sorted-II.js new file mode 100644 index 00000000..e3c8b47e --- /dev/null +++ b/768.max-chunks-to-make-sorted-II.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} arr + * @return {number} + */ +const maxChunksToSorted = function(arr) { + const clonedArr = arr.slice(0); + let sum1 = 0; + let sum2 = 0; + let res = 0; + clonedArr.sort((a, b) => a - b); + for (let i = 0; i < arr.length; i++) { + sum1 += arr[i]; + sum2 += clonedArr[i]; + if (sum1 === sum2) res += 1; + } + return res; +}; diff --git a/769-max-chunks-to-make-sorted.js b/769-max-chunks-to-make-sorted.js deleted file mode 100755 index 0620c32e..00000000 --- a/769-max-chunks-to-make-sorted.js +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @param {number[]} arr - * @return {number} - */ -const maxChunksToSorted = function(arr) { - let res = 0; - let max = 0; - for (let i = 0; i < arr.length; i++) { - max = Math.max(max, arr[i]); - if (max === i) res += 1; - } - return res; -}; diff --git a/769.max-chunks-to-make-sorted.js b/769.max-chunks-to-make-sorted.js new file mode 100644 index 00000000..6b1af0d1 --- /dev/null +++ b/769.max-chunks-to-make-sorted.js @@ -0,0 +1,13 @@ +/** + * @param {number[]} arr + * @return {number} + */ +const maxChunksToSorted = function(arr) { + let res = 0; + let max = 0; + for (let i = 0; i < arr.length; i++) { + max = Math.max(max, arr[i]); + if (max === i) res += 1; + } + return res; +}; diff --git a/77-combinations.js b/77-combinations.js deleted file mode 100755 index 6cae4560..00000000 --- a/77-combinations.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @param {number} n - * @param {number} k - * @return {number[][]} - */ -const combine = function(n, k) { - const res = []; - bt(res, [], 1, n, k); - return res; -}; - -function bt(res, tmp, start, n, k) { - if (k === 0) { - res.push(tmp.slice(0)); - return; - } - for (let i = start; i <= n - k + 1; i++) { - tmp.push(i); - bt(res, tmp, i + 1, n, k - 1); - tmp.pop(); - } -} diff --git a/77.combinations.js b/77.combinations.js new file mode 100644 index 00000000..dbc7f79d --- /dev/null +++ b/77.combinations.js @@ -0,0 +1,22 @@ +/** + * @param {number} n + * @param {number} k + * @return {number[][]} + */ +const combine = function(n, k) { + const res = []; + bt(res, [], 1, n, k); + return res; +}; + +function bt(res, tmp, start, n, k) { + if (k === 0) { + res.push(tmp.slice(0)); + return; + } + for (let i = start; i <= n - k + 1; i++) { + tmp.push(i); + bt(res, tmp, i + 1, n, k - 1); + tmp.pop(); + } +} diff --git a/770-basic-calculator-iv.js b/770.basic-calculator-iv.js similarity index 100% rename from 770-basic-calculator-iv.js rename to 770.basic-calculator-iv.js diff --git a/771-jewels-and-stones.js b/771.jewels-and-stones.js similarity index 100% rename from 771-jewels-and-stones.js rename to 771.jewels-and-stones.js diff --git a/772-basic-calculator-iii.js b/772.basic-calculator-iii.js similarity index 100% rename from 772-basic-calculator-iii.js rename to 772.basic-calculator-iii.js diff --git a/773-sliding-puzzle.js b/773-sliding-puzzle.js deleted file mode 100755 index 04913069..00000000 --- a/773-sliding-puzzle.js +++ /dev/null @@ -1,51 +0,0 @@ -/** - * @param {number[][]} board - * @return {number} - */ -const slidingPuzzle = function(board) { - const target = "123450"; - let start = ""; - for (let i = 0; i < board.length; i++) { - for (let j = 0; j < board[0].length; j++) { - start += board[i][j]; - } - } - const visited = {}; - // all the positions 0 can be swapped to - const dirs = [[1, 3], [0, 2, 4], [1, 5], [0, 4], [1, 3, 5], [2, 4]]; - const queue = []; - queue.push(start); - visited[start] = true; - let res = 0; - while (queue.length !== 0) { - // level count, has to use size control here, otherwise not needed - let size = queue.length; - for (let i = 0; i < size; i++) { - let cur = queue.shift(); - if (cur === target) { - return res; - } - let zero = cur.indexOf("0"); - // swap if possible - for (let dir of dirs[zero]) { - let next = swap(cur, zero, dir); - if (visited.hasOwnProperty(next)) { - continue; - } - visited[next] = true; - queue.push(next); - } - } - res++; - } - return -1; -}; - -function swap(str, i, j) { - const arr = str.split(""); - const ic = str[i]; - const jc = str[j]; - arr.splice(i, 1, jc); - arr.splice(j, 1, ic); - return arr.join(""); -} diff --git a/773.sliding-puzzle.js b/773.sliding-puzzle.js new file mode 100644 index 00000000..8efe7639 --- /dev/null +++ b/773.sliding-puzzle.js @@ -0,0 +1,51 @@ +/** + * @param {number[][]} board + * @return {number} + */ +const slidingPuzzle = function(board) { + const target = "123450"; + let start = ""; + for (let i = 0; i < board.length; i++) { + for (let j = 0; j < board[0].length; j++) { + start += board[i][j]; + } + } + const visited = {}; + // all the positions 0 can be swapped to + const dirs = [[1, 3], [0, 2, 4], [1, 5], [0, 4], [1, 3, 5], [2, 4]]; + const queue = []; + queue.push(start); + visited[start] = true; + let res = 0; + while (queue.length !== 0) { + // level count, has to use size control here, otherwise not needed + let size = queue.length; + for (let i = 0; i < size; i++) { + let cur = queue.shift(); + if (cur === target) { + return res; + } + let zero = cur.indexOf("0"); + // swap if possible + for (let dir of dirs[zero]) { + let next = swap(cur, zero, dir); + if (visited.hasOwnProperty(next)) { + continue; + } + visited[next] = true; + queue.push(next); + } + } + res++; + } + return -1; +}; + +function swap(str, i, j) { + const arr = str.split(""); + const ic = str[i]; + const jc = str[j]; + arr.splice(i, 1, jc); + arr.splice(j, 1, ic); + return arr.join(""); +} diff --git a/774-minimize-max-distance-to-gas-station.js b/774-minimize-max-distance-to-gas-station.js deleted file mode 100644 index 20ee5131..00000000 --- a/774-minimize-max-distance-to-gas-station.js +++ /dev/null @@ -1,132 +0,0 @@ -/** - * @param {number[]} stations - * @param {number} K - * @return {number} - */ -const minmaxGasDist = function (stations, K) { - const dis = [] - let min = 0 - let max = 1e8 - for (let i = 0; i < stations.length - 1; i++) { - dis.push(stations[i + 1] - stations[i]) - } - while (max - min > 1e-6) { - const mid = min + (max - min) / 2 - if (possible(dis, mid, K)) { - max = mid - } else { - min = mid - } - } - return min -} - -const possible = (dis, res, K) => { - let need = 0 - for (let i = 0; i < dis.length; i++) { - need += dis[i] <= res ? 0 : Math.floor(dis[i] / res) - } - return need <= K -} - -// another - -/** - * @param {number[]} stations - * @param {number} k - * @return {number} - */ -const minmaxGasDist = function(stations, k) { - const pq = new PriorityQueue((a, b) => a[0] > b[0]) - for(let i = 1, n = stations.length; i < n; i++) { - const delta = stations[i] - stations[i - 1] - pq.push([delta, delta, 1]) - } - const limit = (stations[stations.length - 1] - stations[0]) / k - // console.log(pq.heap) - while(k>0) { - let [delta, gap, num] = pq.pop() - - let v = gap / (num + 1) - while(k > 0 && gap / (num + 1) > limit) { - k-- - num++ - } - - v = gap / ++num - k-- - - pq.push([v, gap, num]) - } - - return pq.peek()[0] -}; - - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/774.minimize-max-distance-to-gas-station.js b/774.minimize-max-distance-to-gas-station.js new file mode 100644 index 00000000..36387977 --- /dev/null +++ b/774.minimize-max-distance-to-gas-station.js @@ -0,0 +1,31 @@ +/** + * @param {number[]} stations + * @param {number} K + * @return {number} + */ +const minmaxGasDist = function (stations, K) { + const dis = [] + let min = 0 + let max = 1e8 + for (let i = 0; i < stations.length - 1; i++) { + dis.push(stations[i + 1] - stations[i]) + } + while (max - min > 1e-6) { + const mid = min + (max - min) / 2 + if (possible(dis, mid, K)) { + max = mid + } else { + min = mid + } + } + return min +} + +const possible = (dis, res, K) => { + let need = 0 + for (let i = 0; i < dis.length; i++) { + need += dis[i] <= res ? 0 : Math.floor(dis[i] / res) + } + return need <= K +} + diff --git a/775-global-and-local-inversions.js b/775-global-and-local-inversions.js deleted file mode 100644 index 1616fc00..00000000 --- a/775-global-and-local-inversions.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @param {number[]} A - * @return {boolean} - */ -const isIdealPermutation = function(A) { - if(A.length === 1 || A.length === 2) return true - let max = A[0] - for(let i = 0, len = A.length; i < len - 2; i++) { - max = Math.max(max, A[i]) - if(max > A[i + 2]) return false - } - return true; -}; - -// another - -/** - * @param {number[]} A - * @return {boolean} - */ -const isIdealPermutation = function(A) { - if(A.length === 1 || A.length === 2) return true - for(let i = 0, len = A.length; i < len; i++) { - if(Math.abs(A[i] - i) > 1) return false - } - return true; -}; diff --git a/775.global-and-local-inversions.js b/775.global-and-local-inversions.js new file mode 100644 index 00000000..62f0d7c5 --- /dev/null +++ b/775.global-and-local-inversions.js @@ -0,0 +1,14 @@ +/** + * @param {number[]} A + * @return {boolean} + */ +const isIdealPermutation = function(A) { + if(A.length === 1 || A.length === 2) return true + let max = A[0] + for(let i = 0, len = A.length; i < len - 2; i++) { + max = Math.max(max, A[i]) + if(max > A[i + 2]) return false + } + return true; +}; + diff --git a/776-split-bst.js b/776.split-bst.js similarity index 100% rename from 776-split-bst.js rename to 776.split-bst.js diff --git a/777-swap-adjacent-in-lr-string.js b/777.swap-adjacent-in-lr-string.js similarity index 100% rename from 777-swap-adjacent-in-lr-string.js rename to 777.swap-adjacent-in-lr-string.js diff --git a/778-swim-in-rising-water.js b/778-swim-in-rising-water.js deleted file mode 100644 index 43f52c67..00000000 --- a/778-swim-in-rising-water.js +++ /dev/null @@ -1,125 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const swimInWater = function(grid) { - let n = grid.length; - let low = grid[0][0], - hi = n * n - 1; - while (low < hi) { - let mid = low + Math.floor((hi - low) / 2); - if (valid(grid, mid)) hi = mid; - else low = mid + 1; - } - return low; -}; - -function valid(grid, waterHeight) { - let n = grid.length; - const visited = Array.from(new Array(n), el => new Array(n).fill(0)); - const dir = [-1, 0, 1, 0, -1]; - return dfs(grid, visited, dir, waterHeight, 0, 0, n); -} -function dfs(grid, visited, dir, waterHeight, row, col, n) { - visited[row][col] = 1; - for (let i = 0; i < 4; ++i) { - let r = row + dir[i], - c = col + dir[i + 1]; - if ( - r >= 0 && - r < n && - c >= 0 && - c < n && - visited[r][c] == 0 && - grid[r][c] <= waterHeight - ) { - if (r == n - 1 && c == n - 1) return true; - if (dfs(grid, visited, dir, waterHeight, r, c, n)) return true; - } - } - return false; -} - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -const dirs = [[-1, 0], [1, 0], [0, 1], [0, -1]]; -const swimInWater = grid => { - let time = 0; - let N = grid.length; - const visited = new Set(); - while (!visited.has(N * N - 1)) { - visited.clear(); - dfs(grid, 0, 0, time, visited); - time++; - } - return time - 1; -}; - -function dfs(grid, i, j, time, visited) { - if ( - i < 0 || - i > grid.length - 1 || - j < 0 || - j > grid[0].length - 1 || - grid[i][j] > time || - visited.has(i * grid.length + j) - ) - return; - visited.add(i * grid.length + j); - for (let dir of dirs) { - dfs(grid, i + dir[0], j + dir[1], time, visited); - } -} - - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -class UnionFind { - constructor(N) { - this.id = []; - for (let i = 0; i < N; i++) { - this.id[i] = i; - } - } - - root(i) { - while (i != this.id[i]) { - this.id[i] = this.id[this.id[i]]; - i = this.id[i]; - } - return i; - } - isConnected(p, q) { - return this.root(p) === this.root(q); - } - union(p, q) { - if (this.isConnected(p, q)) return; - this.id[this.root(p)] = this.root(q); - } -} -const swimInWater = grid => { - const N = grid.length; - const uf = new UnionFind(N * N); - let time = 0; - while (!uf.isConnected(0, N * N - 1)) { - for (let i = 0; i < N; i++) { - for (let j = 0; j < N; j++) { - if (grid[i][j] > time) continue; - if (i < N - 1 && grid[i + 1][j] <= time) - uf.union(i * N + j, i * N + j + N); - if (j < N - 1 && grid[i][j + 1] <= time) - uf.union(i * N + j, i * N + j + 1); - } - } - time++; - } - return time - 1; -}; diff --git a/778.swim-in-rising-water.js b/778.swim-in-rising-water.js new file mode 100644 index 00000000..1b874e30 --- /dev/null +++ b/778.swim-in-rising-water.js @@ -0,0 +1,42 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const swimInWater = function(grid) { + let n = grid.length; + let low = grid[0][0], + hi = n * n - 1; + while (low < hi) { + let mid = low + Math.floor((hi - low) / 2); + if (valid(grid, mid)) hi = mid; + else low = mid + 1; + } + return low; +}; + +function valid(grid, waterHeight) { + let n = grid.length; + const visited = Array.from(new Array(n), el => new Array(n).fill(0)); + const dir = [-1, 0, 1, 0, -1]; + return dfs(grid, visited, dir, waterHeight, 0, 0, n); +} +function dfs(grid, visited, dir, waterHeight, row, col, n) { + visited[row][col] = 1; + for (let i = 0; i < 4; ++i) { + let r = row + dir[i], + c = col + dir[i + 1]; + if ( + r >= 0 && + r < n && + c >= 0 && + c < n && + visited[r][c] == 0 && + grid[r][c] <= waterHeight + ) { + if (r == n - 1 && c == n - 1) return true; + if (dfs(grid, visited, dir, waterHeight, r, c, n)) return true; + } + } + return false; +} + diff --git a/779-k-th-symbol-in-grammar.js b/779.k-th-symbol-in-grammar.js similarity index 100% rename from 779-k-th-symbol-in-grammar.js rename to 779.k-th-symbol-in-grammar.js diff --git a/78-subsets.js b/78-subsets.js deleted file mode 100755 index 5467e85d..00000000 --- a/78-subsets.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[][]} - */ - -function subsets(nums) { - const list = []; - const len = nums.length; - const subsetNum = Math.pow(2, len); - for (let n = 0; n < subsetNum; n++) { - list[n] = []; - } - for (let i = 0; i < len; i++) { - for (let j = 0; j < subsetNum; j++) { - if ((j >> i) & 1) { - list[j].push(nums[i]); - } - } - } - return list; -} - -console.log(subsets([1, 2, 3])); - -// another - -/** - * @param {number[]} nums - * @return {number[][]} - */ - -function subsets(nums) { - const subs = [[]] - for (let num of nums) { - const n = subs.length - for (let i = 0; i < n; i++) { - subs.push(subs[i].slice(0)) - subs[subs.length - 1].push(num) - } - } - return subs -} diff --git a/78.subsets.js b/78.subsets.js new file mode 100644 index 00000000..af3fbdff --- /dev/null +++ b/78.subsets.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} nums + * @return {number[][]} + */ + +function subsets(nums) { + const list = []; + const len = nums.length; + const subsetNum = Math.pow(2, len); + for (let n = 0; n < subsetNum; n++) { + list[n] = []; + } + for (let i = 0; i < len; i++) { + for (let j = 0; j < subsetNum; j++) { + if ((j >> i) & 1) { + list[j].push(nums[i]); + } + } + } + return list; +} + +console.log(subsets([1, 2, 3])); + diff --git a/780-reaching-points.js b/780.reaching-points.js similarity index 100% rename from 780-reaching-points.js rename to 780.reaching-points.js diff --git a/782-transform-to-chessboard.js b/782.transform-to-chessboard.js similarity index 100% rename from 782-transform-to-chessboard.js rename to 782.transform-to-chessboard.js diff --git a/783-minimum-distance-between-BST-nodes.js b/783-minimum-distance-between-BST-nodes.js deleted file mode 100755 index 1bc9b2db..00000000 --- a/783-minimum-distance-between-BST-nodes.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const minDiffInBST = function(root) { - if (root === null) return 0; - let min = Number.MAX_SAFE_INTEGER, - res = []; - const bst = (node, res) => { - if (!node) return; - bst(node.left, res); - res.push(node.val); - bst(node.right, res); - }; - bst(root, res); - for (let i = 1; i < res.length; i++) { - min = Math.min(min, res[i] - res[i - 1]); - } - return min; -}; diff --git a/783.minimum-distance-between-BST-nodes.js b/783.minimum-distance-between-BST-nodes.js new file mode 100644 index 00000000..1e5b2469 --- /dev/null +++ b/783.minimum-distance-between-BST-nodes.js @@ -0,0 +1,27 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +const minDiffInBST = function(root) { + if (root === null) return 0; + let min = Number.MAX_SAFE_INTEGER, + res = []; + const bst = (node, res) => { + if (!node) return; + bst(node.left, res); + res.push(node.val); + bst(node.right, res); + }; + bst(root, res); + for (let i = 1; i < res.length; i++) { + min = Math.min(min, res[i] - res[i - 1]); + } + return min; +}; diff --git a/784-letter-case-permutation.js b/784.letter-case-permutation.js similarity index 100% rename from 784-letter-case-permutation.js rename to 784.letter-case-permutation.js diff --git a/785-is-graph-bipartite.js b/785.is-graph-bipartite.js similarity index 100% rename from 785-is-graph-bipartite.js rename to 785.is-graph-bipartite.js diff --git a/786-k-th-smallest-prime-fraction.js b/786.k-th-smallest-prime-fraction.js similarity index 100% rename from 786-k-th-smallest-prime-fraction.js rename to 786.k-th-smallest-prime-fraction.js diff --git a/787-cheapest-flights-within-k-stops.js b/787-cheapest-flights-within-k-stops.js deleted file mode 100644 index c0cd2f99..00000000 --- a/787-cheapest-flights-within-k-stops.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @param {number} n - * @param {number[][]} flights - * @param {number} src - * @param {number} dst - * @param {number} K - * @return {number} - */ - -const findCheapestPrice = function(n, flights, src, dst, K) { - let mn = new Array(n + 1).fill(Infinity); - mn[src] = 0; - for(let k = 0; k < K + 1; k++){ - let newmn = [].concat(mn); - for(let i = 0; i < flights.length; i++){ - let f = flights[i], a = f[0], b = f[1], c = f[2]; - newmn[b] = Math.min(newmn[b], mn[a] + c); - } - mn = [].concat(newmn); - } - return mn[dst] != Infinity ? mn[dst] : -1 -} - -// another -const findCheapestPrice = function(n, flights, src, dst, K) { - const map = []; - flights.forEach(([s, d, p]) => { - map[s] = map[s] || []; - map[s][d] = p; - }); - let min = Infinity; - const p = find(src, 0, 0); - return p === Infinity ? -1 : p; - - function find(s, p, c) { - if (s === dst) { - return p; - } - const l = map[s]; - if (c > K || p > min || !l) { - return Infinity; - } - l.forEach((p1, d) => { - min = Math.min(min, find(d, p + p1, c + 1)); - }); - return min; - } -}; diff --git a/787.cheapest-flights-within-k-stops.js b/787.cheapest-flights-within-k-stops.js new file mode 100644 index 00000000..b95ebbdb --- /dev/null +++ b/787.cheapest-flights-within-k-stops.js @@ -0,0 +1,23 @@ +/** + * @param {number} n + * @param {number[][]} flights + * @param {number} src + * @param {number} dst + * @param {number} K + * @return {number} + */ + +const findCheapestPrice = function(n, flights, src, dst, K) { + let mn = new Array(n + 1).fill(Infinity); + mn[src] = 0; + for(let k = 0; k < K + 1; k++){ + let newmn = [].concat(mn); + for(let i = 0; i < flights.length; i++){ + let f = flights[i], a = f[0], b = f[1], c = f[2]; + newmn[b] = Math.min(newmn[b], mn[a] + c); + } + mn = [].concat(newmn); + } + return mn[dst] != Infinity ? mn[dst] : -1 +} + diff --git a/788-rotated-digits.js b/788.rotated-digits.js similarity index 100% rename from 788-rotated-digits.js rename to 788.rotated-digits.js diff --git a/789-escape-the-ghosts.js b/789.escape-the-ghosts.js similarity index 100% rename from 789-escape-the-ghosts.js rename to 789.escape-the-ghosts.js diff --git a/79-word-search.js b/79-word-search.js deleted file mode 100644 index d109fa4b..00000000 --- a/79-word-search.js +++ /dev/null @@ -1,79 +0,0 @@ -/** - * @param {character[][]} board - * @param {string} word - * @return {boolean} - */ -const exist = function(board, word) { - const dirs = [[0, 1], [0, -1], [-1, 0], [1, 0]]; - for (let j = 0; j < board.length; j++) { - for (let i = 0; i < board[0].length; i++) { - let res = dfs(board, i, j, dirs, word, 0); - if (res) { - return true; - } - } - } - return false; -}; - -function dfs(board, x, y, dirs, word, start) { - if (start >= word.length) return true; - if (x < 0 || y < 0 || x >= board[0].length || y >= board.length) return false; - if (word[start] !== board[y][x] || board[y][x] === "#") return false; - - let res = false; - let c = board[y][x]; - board[y][x] = "#"; - for (let el of dirs) { - let posx = x + el[0]; - let posy = y + el[1]; - res = res || dfs(board, posx, posy, dirs, word, start + 1); - if (res) return true; - } - board[y][x] = c; - - return false; -} - -// time complexity: O(M * N * 3^L), where L is the length of word. -// we have a visited array and we never go back, so 3 directions - -// another - -/** - * @param {character[][]} board - * @param {string} word - * @return {boolean} - */ -const exist = function(board, word) { - if (!word || !board || board.length === 0) return false - const dirs = [[-1, 0], [1, 0], [0, -1], [0, 1]] - for (let row = 0; row < board.length; row++) { - for (let col = 0; col < board[row].length; col++) { - if (searchWord(board, row, col, word, 0, dirs)) return true - } - } - return false -} - -const searchWord = (board, row, col, word, widx, dirs) => { - if (widx === word.length) return true - if ( - row < 0 || - col < 0 || - row === board.length || - col === board[0].length || - board[row][col] === null || - board[row][col] !== word[widx] - ) return false - - const ch = board[row][col] - board[row][col] = null // mark visited - - for (let dir of dirs) { - if (searchWord(board, row + dir[0], col + dir[1], word, widx + 1, dirs)) { - return true - } - } - board[row][col] = ch // recover -} diff --git a/79.word-search.js b/79.word-search.js new file mode 100644 index 00000000..69308415 --- /dev/null +++ b/79.word-search.js @@ -0,0 +1,40 @@ +/** + * @param {character[][]} board + * @param {string} word + * @return {boolean} + */ +const exist = function(board, word) { + const dirs = [[0, 1], [0, -1], [-1, 0], [1, 0]]; + for (let j = 0; j < board.length; j++) { + for (let i = 0; i < board[0].length; i++) { + let res = dfs(board, i, j, dirs, word, 0); + if (res) { + return true; + } + } + } + return false; +}; + +function dfs(board, x, y, dirs, word, start) { + if (start >= word.length) return true; + if (x < 0 || y < 0 || x >= board[0].length || y >= board.length) return false; + if (word[start] !== board[y][x] || board[y][x] === "#") return false; + + let res = false; + let c = board[y][x]; + board[y][x] = "#"; + for (let el of dirs) { + let posx = x + el[0]; + let posy = y + el[1]; + res = res || dfs(board, posx, posy, dirs, word, start + 1); + if (res) return true; + } + board[y][x] = c; + + return false; +} + +// time complexity: O(M * N * 3^L), where L is the length of word. +// we have a visited array and we never go back, so 3 directions + diff --git a/791-custom-sort-string.js b/791-custom-sort-string.js deleted file mode 100755 index 2dcf544f..00000000 --- a/791-custom-sort-string.js +++ /dev/null @@ -1,46 +0,0 @@ -/** - * @param {string} S - * @param {string} T - * @return {string} - */ -const customSortString = function(S, T) { - const arr = []; - const remaining = []; - const hash = {}; - for (let i = 0; i < S.length; i++) { - if (T.indexOf(S.charAt(i)) !== -1) { - arr.push(S.charAt(i)); - } - } - let char; - for (let j = 0; j < T.length; j++) { - char = T.charAt(j); - if (arr.indexOf(char) === -1 && remaining.indexOf(char) === -1) { - remaining.push(char); - } - hash[char] = hash.hasOwnProperty(char) ? hash[char] + 1 : 1; - } - return `${genPart(arr, hash)}${genPart(remaining, hash)}`; -}; - -function constructStr(char, num) { - let str = ""; - for (let i = 0; i < num; i++) { - str += char; - } - return str; -} - -function genPart(arr, hash) { - return arr.reduce((ac, el) => { - return ac + constructStr(el, hash[el]); - }, ""); -} - -console.log(customSortString("kqep", "pekeq")); -console.log( - customSortString( - "hucw", - "utzoampdgkalexslxoqfkdjoczajxtuhqyxvlfatmptqdsochtdzgypsfkgqwbgqbcamdqnqztaqhqanirikahtmalzqjjxtqfnh" - ) -); diff --git a/791.custom-sort-string.js b/791.custom-sort-string.js new file mode 100644 index 00000000..42d165bf --- /dev/null +++ b/791.custom-sort-string.js @@ -0,0 +1,46 @@ +/** + * @param {string} S + * @param {string} T + * @return {string} + */ +const customSortString = function(S, T) { + const arr = []; + const remaining = []; + const hash = {}; + for (let i = 0; i < S.length; i++) { + if (T.indexOf(S.charAt(i)) !== -1) { + arr.push(S.charAt(i)); + } + } + let char; + for (let j = 0; j < T.length; j++) { + char = T.charAt(j); + if (arr.indexOf(char) === -1 && remaining.indexOf(char) === -1) { + remaining.push(char); + } + hash[char] = hash.hasOwnProperty(char) ? hash[char] + 1 : 1; + } + return `${genPart(arr, hash)}${genPart(remaining, hash)}`; +}; + +function constructStr(char, num) { + let str = ""; + for (let i = 0; i < num; i++) { + str += char; + } + return str; +} + +function genPart(arr, hash) { + return arr.reduce((ac, el) => { + return ac + constructStr(el, hash[el]); + }, ""); +} + +console.log(customSortString("kqep", "pekeq")); +console.log( + customSortString( + "hucw", + "utzoampdgkalexslxoqfkdjoczajxtuhqyxvlfatmptqdsochtdzgypsfkgqwbgqbcamdqnqztaqhqanirikahtmalzqjjxtqfnh" + ) +); diff --git a/792-number-of-matching-subsequences.js b/792-number-of-matching-subsequences.js deleted file mode 100644 index 0fc3d939..00000000 --- a/792-number-of-matching-subsequences.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @param {string} s - * @param {string[]} words - * @return {number} - */ -const numMatchingSubseq = function(s, words) { - const hash = {} - for(let w of words) { - if(hash[w[0]] == null) hash[w[0]] = [] - const it = w[Symbol.iterator]() - hash[w[0]].push( it ) - it.next() - } - let res = 0 - for(let ch of s) { - const advance = hash[ch] || [] - hash[ch] = [] - for(let it of advance) { - const obj = it.next() - if(obj.done === false) { - if(hash[obj.value] == null) hash[obj.value] = [] - hash[obj.value].push(it) - } else { - res++ - } - } - } - - return res -}; - -// another - -/** - * @param {string} S - * @param {string[]} words - * @return {number} - */ -const numMatchingSubseq = function(S, words) { - let res=0; - for(let i=0;i= L && A[i] <= R) { - res += i - j + 1 - count = i - j + 1 - } else if(A[i] < L) { - res += count - } else { - j = i + 1 - count = 0 - } - } - return res -}; - -// another - -/** - * @param {number[]} nums - * @param {number} left - * @param {number} right - * @return {number} - */ -const numSubarrayBoundedMax = function(nums, left, right) { - let prev = -1, dp = 0, res = 0 - for(let i = 0, n = nums.length; i < n; i++) { - const cur = nums[i] - if(cur < left) res += dp - else if(cur > right) { - dp = 0 - prev = i - } else { - dp = i - prev - res += dp - } - } - return res -}; diff --git a/795.number-of-subarrays-with-bounded-maximum.js b/795.number-of-subarrays-with-bounded-maximum.js new file mode 100644 index 00000000..e25d12d5 --- /dev/null +++ b/795.number-of-subarrays-with-bounded-maximum.js @@ -0,0 +1,24 @@ +/** + * @param {number[]} A + * @param {number} L + * @param {number} R + * @return {number} + */ +const numSubarrayBoundedMax = function(A, L, R) { + let res = 0; + let j = 0; + let count = 0; + for(let i = 0; i < A.length; i++) { + if(A[i] >= L && A[i] <= R) { + res += i - j + 1 + count = i - j + 1 + } else if(A[i] < L) { + res += count + } else { + j = i + 1 + count = 0 + } + } + return res +}; + diff --git a/796-rotate-string.js b/796-rotate-string.js deleted file mode 100755 index 407664e8..00000000 --- a/796-rotate-string.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * @param {string} A - * @param {string} B - * @return {boolean} - */ -const rotateString = function(A, B) { - if (A.length != B.length) return false; - return A.concat(A).includes(B); -}; diff --git a/796.rotate-string.js b/796.rotate-string.js new file mode 100644 index 00000000..335e0893 --- /dev/null +++ b/796.rotate-string.js @@ -0,0 +1,9 @@ +/** + * @param {string} A + * @param {string} B + * @return {boolean} + */ +const rotateString = function(A, B) { + if (A.length != B.length) return false; + return A.concat(A).includes(B); +}; diff --git a/797-all-paths-from-source-to-target.js b/797.all-paths-from-source-to-target.js similarity index 100% rename from 797-all-paths-from-source-to-target.js rename to 797.all-paths-from-source-to-target.js diff --git a/798-smallest-rotation-with-highest-score.js b/798-smallest-rotation-with-highest-score.js deleted file mode 100644 index a76fca03..00000000 --- a/798-smallest-rotation-with-highest-score.js +++ /dev/null @@ -1,49 +0,0 @@ -/** - * @param {number[]} A - * @return {number} - */ -const bestRotation = function(A) { - const N = A.length - const bad = new Array(N).fill(0) - for (let i = 0; i < N; ++i) { - let left = (i - A[i] + 1 + N) % N - let right = (i + 1) % N - bad[left]-- - bad[right]++ - if (left > right) bad[0]-- - } - - let best = -N - let ans = 0, - cur = 0 - for (let i = 0; i < N; ++i) { - cur += bad[i] - if (cur > best) { - best = cur - ans = i - } - } - return ans -} - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -var bestRotation = function(nums) { - const n = nums.length - const arr = Array(n).fill(0) - for(let i = 0; i < n; i++) { - arr[(i - nums[i] + 1 + n) % n] -= 1 - } - let res = 0 - for(let i = 1; i < n; i++) { - arr[i] += arr[i - 1] + 1 - if(arr[i] > arr[res]) res = i - } - return res -}; - - diff --git a/798.smallest-rotation-with-highest-score.js b/798.smallest-rotation-with-highest-score.js new file mode 100644 index 00000000..1eb13553 --- /dev/null +++ b/798.smallest-rotation-with-highest-score.js @@ -0,0 +1,28 @@ +/** + * @param {number[]} A + * @return {number} + */ +const bestRotation = function(A) { + const N = A.length + const bad = new Array(N).fill(0) + for (let i = 0; i < N; ++i) { + let left = (i - A[i] + 1 + N) % N + let right = (i + 1) % N + bad[left]-- + bad[right]++ + if (left > right) bad[0]-- + } + + let best = -N + let ans = 0, + cur = 0 + for (let i = 0; i < N; ++i) { + cur += bad[i] + if (cur > best) { + best = cur + ans = i + } + } + return ans +} + diff --git a/799-champagne-tower.js b/799.champagne-tower.js similarity index 100% rename from 799-champagne-tower.js rename to 799.champagne-tower.js diff --git a/8-string-to-integer-(atoi).js b/8-string-to-integer-(atoi).js deleted file mode 100755 index aa0ff301..00000000 --- a/8-string-to-integer-(atoi).js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {string} str - * @return {number} - */ -const myAtoi = function(str) { - return Math.max(Math.min(parseInt(str) || 0, 2147483647), -2147483648); -}; - -// anotther - -/** - * @param {string} s - * @return {number} - */ -const myAtoi = function(s) { - let n = s.length, i = 0, j = 0, sign = 1; - if(n === 0) { - return 0; - } - while(i < n && s[i] === ' ') { - i++; - } - if(i < n && (s[i] === '-' || s[i] === '+')) { - sign = (s[i] === '-') ? -1 : 1; - i++; - } - j = i - while(i < n) { - if(Number.isInteger(parseInt(s[i]))) i++; - else break; - } - let result = parseInt(s.slice(j, i)) - if(isNaN(result)) return 0 - if(sign * result < -(2**31)) return -(2**31); - else if(sign * result > (2**31-1)) return 2**31-1; - else return sign * result; -}; diff --git a/8.string-to-integer-(atoi).js b/8.string-to-integer-(atoi).js new file mode 100644 index 00000000..485a042b --- /dev/null +++ b/8.string-to-integer-(atoi).js @@ -0,0 +1,37 @@ +/** + * @param {string} str + * @return {number} + */ +const myAtoi = function(str) { + return Math.max(Math.min(parseInt(str) || 0, 2147483647), -2147483648); +}; + +// anotther + +/** + * @param {string} s + * @return {number} + */ +const myAtoi = function(s) { + let n = s.length, i = 0, j = 0, sign = 1; + if(n === 0) { + return 0; + } + while(i < n && s[i] === ' ') { + i++; + } + if(i < n && (s[i] === '-' || s[i] === '+')) { + sign = (s[i] === '-') ? -1 : 1; + i++; + } + j = i + while(i < n) { + if(Number.isInteger(parseInt(s[i]))) i++; + else break; + } + let result = parseInt(s.slice(j, i)) + if(isNaN(result)) return 0 + if(sign * result < -(2**31)) return -(2**31); + else if(sign * result > (2**31-1)) return 2**31-1; + else return sign * result; +}; diff --git a/80-remove-duplicates-from-sorted-array-ii.js b/80.remove-duplicates-from-sorted-array-ii.js similarity index 100% rename from 80-remove-duplicates-from-sorted-array-ii.js rename to 80.remove-duplicates-from-sorted-array-ii.js diff --git a/800-similar-rgb-color.js b/800.similar-rgb-color.js similarity index 100% rename from 800-similar-rgb-color.js rename to 800.similar-rgb-color.js diff --git a/801-minimum-swaps-to-make-sequences-increasing.js b/801.minimum-swaps-to-make-sequences-increasing.js similarity index 100% rename from 801-minimum-swaps-to-make-sequences-increasing.js rename to 801.minimum-swaps-to-make-sequences-increasing.js diff --git a/802-find-eventual-safe-states.js b/802-find-eventual-safe-states.js deleted file mode 100644 index f1d74624..00000000 --- a/802-find-eventual-safe-states.js +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @param {number[][]} graph - * @return {number[]} - */ -const eventualSafeNodes = function (graph) { - const ing = {}, - n = graph.length - const outDegree = Array(n).fill(0) - let q = [] - for (let i = 0; i < n; i++) { - outDegree[i] = graph[i].length - if (outDegree[i] === 0) { - q.push(i) - } - for (const e of graph[i]) { - if (ing[e] == null) ing[e] = [] - ing[e].push(i) - } - } - - for (const term of q) { - for (const come of ing[term] || []) { - outDegree[come]-- - if (outDegree[come] === 0) q.push(come) - } - } - q.sort((a, b) => a - b) - return q -} - -// another - - -/** - * @param {number[][]} graph - * @return {number[]} - */ -const eventualSafeNodes = function(graph) { - const n = graph.length, memo = {}, visited = new Set(), res = [] - for(let i = 0; i < n; i++) { - if(!dfs(graph, i, memo, visited)) res.push(i) - } - return res -}; - -function dfs(graph, node, memo, visited) { - if(memo[node] != null) return memo[node] - let hasCycle = false - visited.add(node) - for(let e of graph[node]) { - if(visited.has(e) || dfs(graph, e, memo, visited)) { - hasCycle = true - break - } - } - visited.delete(node) - memo[node] = hasCycle - return hasCycle -} - -// another - -/** - * @param {number[][]} graph - * @return {number[]} - */ -const eventualSafeNodes = function(graph) { - const res = [] - if(graph == null || graph.length === 0) return res - const n = graph.length - const color = Array(n).fill(0) - for(let i = 0; i < n; i++) { - if(bt(graph, i, color)) res.push(i) - } - return res - - function bt(graph, start, color) { - if(color[start] !== 0) return color[start] === 1 - color[start] = 2 - for(let next of graph[start]) { - if(!bt(graph, next, color)) return false - } - color[start] = 1 - return true - } -}; diff --git a/802.find-eventual-safe-states.js b/802.find-eventual-safe-states.js new file mode 100644 index 00000000..17c44edc --- /dev/null +++ b/802.find-eventual-safe-states.js @@ -0,0 +1,30 @@ +/** + * @param {number[][]} graph + * @return {number[]} + */ +const eventualSafeNodes = function (graph) { + const ing = {}, + n = graph.length + const outDegree = Array(n).fill(0) + let q = [] + for (let i = 0; i < n; i++) { + outDegree[i] = graph[i].length + if (outDegree[i] === 0) { + q.push(i) + } + for (const e of graph[i]) { + if (ing[e] == null) ing[e] = [] + ing[e].push(i) + } + } + + for (const term of q) { + for (const come of ing[term] || []) { + outDegree[come]-- + if (outDegree[come] === 0) q.push(come) + } + } + q.sort((a, b) => a - b) + return q +} + diff --git a/803-bricks-falling-when-hit.js b/803-bricks-falling-when-hit.js deleted file mode 100644 index 36c09fe0..00000000 --- a/803-bricks-falling-when-hit.js +++ /dev/null @@ -1,253 +0,0 @@ -/** - * @param {number[][]} grid - * @param {number[][]} hits - * @return {number[]} - */ -const hitBricks = function (grid, hits) { - const n = grid[0].length - const m = hits.length - const res = new Array(m).fill(0) - for (const [r, c] of hits) { - if (grid[r][c] == 1) grid[r][c] = 0 - else grid[r][c] = -1 - } - for (let j = 0; j < n; j++) { - getConnectedCount(grid, 0, j) - } - for (let i = m - 1; i >= 0; i--) { - const [r, c] = hits[i] - if (grid[r][c] == -1) continue - grid[r][c] = 1 - if (isConnectedToTop(grid, r, c)) { - res[i] = getConnectedCount(grid, r, c) - 1 - } - } - return res -} -const isConnectedToTop = (grid, i, j) => { - if (i == 0) return true - const dircs = [ - [-1, 0], - [1, 0], - [0, -1], - [0, 1], - ] - for (const [dx, dy] of dircs) { - const nx = i + dx - const ny = j + dy - if ( - 0 <= nx && - nx < grid.length && - 0 <= ny && - ny < grid[0].length && - grid[nx][ny] == 2 - ) { - return true - } - } - return false -} - -const getConnectedCount = (grid, i, j) => { - if ( - i < 0 || - i >= grid.length || - j < 0 || - j >= grid[0].length || - grid[i][j] != 1 - ) - return 0 - let count = 1 - grid[i][j] = 2 - count += - getConnectedCount(grid, i + 1, j) + - getConnectedCount(grid, i - 1, j) + - getConnectedCount(grid, i, j + 1) + - getConnectedCount(grid, i, j - 1) - return count -} - -// another - -/** - * @param {number[][]} grid - * @param {number[][]} hits - * @return {number[]} - */ -const hitBricks = function (grid, hits) { - const SPACE = 0 - const BRICK = 1 - const WILL_HIT = 2 - const DIRECTIONS = [ - [0, 1], - [1, 0], - [0, -1], - [-1, 0], - ] - const rows = grid.length - const cols = grid[0].length - const ds = new DisjointSet(rows * cols + 1) - - for (const [hitR, hitC] of hits) { - if (grid[hitR][hitC] === BRICK) { - grid[hitR][hitC] = WILL_HIT - } - } - - function hash(r, c) { - return r * cols + c + 1 - } - - function unionAround(r, c) { - const hashed = hash(r, c) - for (const [rDiff, cDiff] of DIRECTIONS) { - const rNext = r + rDiff - const cNext = c + cDiff - if (grid[rNext] !== undefined && grid[rNext][cNext] === BRICK) { - ds.union(hashed, hash(rNext, cNext)) - } - } - if (r === 0) ds.union(0, hashed) - } - for (let i = 0; i < grid.length; i++) { - for (let j = 0; j < grid[i].length; j++) { - if (grid[i][j] === BRICK) unionAround(i, j) - } - } - let numBricksLeft = ds.size[ds.find(0)] - const numBricksDropped = new Array(hits.length) - // backwards - for (let i = hits.length - 1; i >= 0; i--) { - const [hitR, hitC] = hits[i] - if (grid[hitR][hitC] === WILL_HIT) { - grid[hitR][hitC] = BRICK - unionAround(hitR, hitC) - const newNumBricksLeft = ds.size[ds.find(0)] - numBricksDropped[i] = Math.max(newNumBricksLeft - numBricksLeft - 1, 0) - numBricksLeft = newNumBricksLeft - } else { - numBricksDropped[i] = 0 - } - } - return numBricksDropped -} - -class DisjointSet { - constructor(n) { - this.size = new Array(n).fill(1) - this.parent = new Array(n) - for (let i = 0; i < n; i++) { - this.parent[i] = i - } - } - find(x) { - if (x === this.parent[x]) return x - this.parent[x] = this.find(this.parent[x]) - - return this.parent[x] - } - union(x, y) { - const rootX = this.find(x) - const rootY = this.find(y) - if (rootX !== rootY) { - // attach X onto Y - this.parent[rootX] = rootY - this.size[rootY] += this.size[rootX] - } - } -} - -// another - -/** - * @param {number[][]} grid - * @param {number[][]} hits - * @return {number[]} - */ -const hitBricks = function(grid, hits) { - const res = Array(hits.length).fill(0), dirs = [-1, 0, 1, 0, -1] - for(let [r, c] of hits) { - grid[r][c] -= 1 - } - for(let i = 0; i < grid[0].length; i++) { - dfs(0, i, grid) - } - for(let i = hits.length - 1; i >= 0; i--) { - const [r, c] = hits[i] - grid[r][c] += 1 - if(grid[r][c] === 1 && isConnected(r, c, grid, dirs)) { - res[i] = dfs(r, c, grid) - 1 - } - } - return res -} -function dfs(i, j, grid) { - if(i < 0 || i >= grid.length || j < 0 || j >= grid[0].length || grid[i][j] !== 1) return 0 - grid[i][j] = 2 - return 1 + dfs(i + 1, j, grid) + dfs(i - 1, j, grid) + dfs(i, j + 1, grid) + dfs(i, j - 1, grid) -} -function isConnected(i, j, grid, dirs) { - if(i === 0) return true - for(let k = 1; k < dirs.length; k++) { - const r = i + dirs[k - 1], c = j + dirs[k] - if(r >= 0 && r < grid.length && c >= 0 && c < grid[0].length && grid[r][c] === 2) { - return true - } - } - return false -} - -// another - -/** - * @param {number[][]} grid - * @param {number[][]} hits - * @return {number[]} - */ -const hitBricks = function (grid, hits) { - const m = grid.length, - n = grid[0].length, - res = Array(hits.length).fill(0), - dirs = [ - [-1, 0], - [1, 0], - [0, 1], - [0, -1], - ]; - for (let [r, c] of hits) grid[r][c] -= 1; - - for (let i = 0; i < n; i++) dfs(grid, 0, i, m, n, dirs); - - for (let i = hits.length - 1; i >= 0; i--) { - const [r, c] = hits[i]; - grid[r][c] += 1; - if (grid[r][c] === 1 && connected(grid, r, c, m, n, dirs)) { - res[i] = dfs(grid, r, c, m, n, dirs) - 1; - } - } - - return res; -}; - -function dfs(grid, i, j, m, n, dirs) { - if (i < 0 || i >= m || j < 0 || j >= n || grid[i][j] !== 1) return 0; - grid[i][j] = 2; - let res = 1; - for (let [dr, dc] of dirs) { - res += dfs(grid, i + dr, j + dc, m, n, dirs); - } - return res; -} - -function connected(grid, i, j, m, n, dirs) { - if (i === 0) return true; - for (let [dr, dc] of dirs) { - const nr = i + dr, - nc = j + dc; - if (nr >= 0 && nr < m && nc >= 0 && nc < n && grid[nr][nc] === 2) - return true; - } - - return false; -} - diff --git a/803.bricks-falling-when-hit.js b/803.bricks-falling-when-hit.js new file mode 100644 index 00000000..819ad42d --- /dev/null +++ b/803.bricks-falling-when-hit.js @@ -0,0 +1,69 @@ +/** + * @param {number[][]} grid + * @param {number[][]} hits + * @return {number[]} + */ +const hitBricks = function (grid, hits) { + const n = grid[0].length + const m = hits.length + const res = new Array(m).fill(0) + for (const [r, c] of hits) { + if (grid[r][c] == 1) grid[r][c] = 0 + else grid[r][c] = -1 + } + for (let j = 0; j < n; j++) { + getConnectedCount(grid, 0, j) + } + for (let i = m - 1; i >= 0; i--) { + const [r, c] = hits[i] + if (grid[r][c] == -1) continue + grid[r][c] = 1 + if (isConnectedToTop(grid, r, c)) { + res[i] = getConnectedCount(grid, r, c) - 1 + } + } + return res +} +const isConnectedToTop = (grid, i, j) => { + if (i == 0) return true + const dircs = [ + [-1, 0], + [1, 0], + [0, -1], + [0, 1], + ] + for (const [dx, dy] of dircs) { + const nx = i + dx + const ny = j + dy + if ( + 0 <= nx && + nx < grid.length && + 0 <= ny && + ny < grid[0].length && + grid[nx][ny] == 2 + ) { + return true + } + } + return false +} + +const getConnectedCount = (grid, i, j) => { + if ( + i < 0 || + i >= grid.length || + j < 0 || + j >= grid[0].length || + grid[i][j] != 1 + ) + return 0 + let count = 1 + grid[i][j] = 2 + count += + getConnectedCount(grid, i + 1, j) + + getConnectedCount(grid, i - 1, j) + + getConnectedCount(grid, i, j + 1) + + getConnectedCount(grid, i, j - 1) + return count +} + diff --git a/805-split-array-with-same-average.js b/805.split-array-with-same-average.js similarity index 100% rename from 805-split-array-with-same-average.js rename to 805.split-array-with-same-average.js diff --git a/81-search-in-rotated-sorted-array-ii.js b/81.search-in-rotated-sorted-array-ii.js similarity index 100% rename from 81-search-in-rotated-sorted-array-ii.js rename to 81.search-in-rotated-sorted-array-ii.js diff --git a/810-chalkboard-xor-game.js b/810.chalkboard-xor-game.js similarity index 100% rename from 810-chalkboard-xor-game.js rename to 810.chalkboard-xor-game.js diff --git a/812-largest-triangle-area.js b/812.largest-triangle-area.js similarity index 100% rename from 812-largest-triangle-area.js rename to 812.largest-triangle-area.js diff --git a/813-largest-sum-of-averages.js b/813.largest-sum-of-averages.js similarity index 100% rename from 813-largest-sum-of-averages.js rename to 813.largest-sum-of-averages.js diff --git a/815-bus-routes.js b/815.bus-routes.js similarity index 100% rename from 815-bus-routes.js rename to 815.bus-routes.js diff --git a/818-race-car.js b/818.race-car.js similarity index 100% rename from 818-race-car.js rename to 818.race-car.js diff --git a/819-most-common-word.js b/819.most-common-word.js similarity index 100% rename from 819-most-common-word.js rename to 819.most-common-word.js diff --git a/82-remove-duplicates-from-sorted-list-ii.js b/82.remove-duplicates-from-sorted-list-ii.js similarity index 100% rename from 82-remove-duplicates-from-sorted-list-ii.js rename to 82.remove-duplicates-from-sorted-list-ii.js diff --git a/821-shortest-distance-to-a-character.js b/821-shortest-distance-to-a-character.js deleted file mode 100755 index 13ed0ff4..00000000 --- a/821-shortest-distance-to-a-character.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @param {string} S - * @param {character} C - * @return {number[]} - */ -const shortestToChar = function(S, C) { - const res = []; - const idxArr = []; - for (let i = 0; i < S.length; i++) { - S.charAt(i) === C ? idxArr.push(i) : null; - } - let coordIdx = 0; - let nextCoordIdx = 1; - let val; - for (let idx = 0; idx < S.length; idx++) { - if (S.charAt(idx) === C) { - val = 0; - nextCoordIdx = idxArr[coordIdx + 1] == null ? coordIdx : coordIdx + 1; - if ( - Math.abs(idxArr[coordIdx] - idx) >= Math.abs(idxArr[nextCoordIdx] - idx) - ) { - coordIdx = idxArr[coordIdx + 1] == null ? coordIdx : coordIdx + 1; - } - } else { - nextCoordIdx = idxArr[coordIdx + 1] == null ? coordIdx : coordIdx + 1; - if ( - Math.abs(idxArr[coordIdx] - idx) < Math.abs(idxArr[nextCoordIdx] - idx) - ) { - val = Math.abs(idxArr[coordIdx] - idx); - } else { - val = Math.abs(idxArr[nextCoordIdx] - idx); - coordIdx = idxArr[coordIdx + 1] == null ? coordIdx : coordIdx + 1; - } - } - res[idx] = val; - } - return res; -}; - -console.log(shortestToChar("aaab", "b")); -console.log(shortestToChar("bbba", "b")); diff --git a/821.shortest-distance-to-a-character.js b/821.shortest-distance-to-a-character.js new file mode 100644 index 00000000..baaf13f8 --- /dev/null +++ b/821.shortest-distance-to-a-character.js @@ -0,0 +1,41 @@ +/** + * @param {string} S + * @param {character} C + * @return {number[]} + */ +const shortestToChar = function(S, C) { + const res = []; + const idxArr = []; + for (let i = 0; i < S.length; i++) { + S.charAt(i) === C ? idxArr.push(i) : null; + } + let coordIdx = 0; + let nextCoordIdx = 1; + let val; + for (let idx = 0; idx < S.length; idx++) { + if (S.charAt(idx) === C) { + val = 0; + nextCoordIdx = idxArr[coordIdx + 1] == null ? coordIdx : coordIdx + 1; + if ( + Math.abs(idxArr[coordIdx] - idx) >= Math.abs(idxArr[nextCoordIdx] - idx) + ) { + coordIdx = idxArr[coordIdx + 1] == null ? coordIdx : coordIdx + 1; + } + } else { + nextCoordIdx = idxArr[coordIdx + 1] == null ? coordIdx : coordIdx + 1; + if ( + Math.abs(idxArr[coordIdx] - idx) < Math.abs(idxArr[nextCoordIdx] - idx) + ) { + val = Math.abs(idxArr[coordIdx] - idx); + } else { + val = Math.abs(idxArr[nextCoordIdx] - idx); + coordIdx = idxArr[coordIdx + 1] == null ? coordIdx : coordIdx + 1; + } + } + res[idx] = val; + } + return res; +}; + +console.log(shortestToChar("aaab", "b")); +console.log(shortestToChar("bbba", "b")); diff --git a/823-binary-trees-with-factors.js b/823.binary-trees-with-factors.js similarity index 100% rename from 823-binary-trees-with-factors.js rename to 823.binary-trees-with-factors.js diff --git a/824-goat-latin.js b/824.goat-latin.js similarity index 100% rename from 824-goat-latin.js rename to 824.goat-latin.js diff --git a/826-most-profit-assigning-work.js b/826.most-profit-assigning-work.js similarity index 100% rename from 826-most-profit-assigning-work.js rename to 826.most-profit-assigning-work.js diff --git a/827-making-a-large-island.js b/827.making-a-large-island.js similarity index 100% rename from 827-making-a-large-island.js rename to 827.making-a-large-island.js diff --git a/828-unique-letter-string.js b/828-unique-letter-string.js deleted file mode 100644 index 62fa088a..00000000 --- a/828-unique-letter-string.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const uniqueLetterString = function(s) { - const n = s.length - const arr = Array.from({ length: 26 }, () => Array(2).fill(-1)) - const A = 'A'.charCodeAt(0) - let res = 0 - for(let i = 0; i < n; i++) { - const idx = s.charCodeAt(i) - A - res += (i - arr[idx][1]) * (arr[idx][1] - arr[idx][0]) - arr[idx] = [arr[idx][1], i] - } - - for(let i = 0; i < 26; i++) { - res += (n - arr[i][1]) * (arr[i][1] - arr[i][0]) - } - - return res -}; - -// another - -/** - * @param {string} S - * @return {number} - */ -const uniqueLetterString = function(S) { - const s = S.split('') - let res = 0 - for (let n = S.length, i = 0, l = 0, r = 0; i < n; i++) { - for (l = i - 1; l >= 0 && s[l] != s[i]; l--); - for (r = i + 1; r < n && s[r] != s[i]; r++); - res += (r - i) * (i - l) - } - return res % (10 ** 9 + 7) -} - -// another - -/** - * @param {string} S - * @return {number} - */ -const uniqueLetterString = function(S) { - const len = S.length - if (len === 0) return 0 - if (len === 1) return 1 - let count = 0 - let lastP = new Array(26).fill(0) - let lastLastP = new Array(26).fill(0) - let pre = 0 - for (let i = 0; i < len; i++) { - let idx = S.charCodeAt(i) - 'A'.charCodeAt(0) - pre += i - lastP[idx] + 1 - pre -= lastP[idx] - lastLastP[idx] - count += pre - lastLastP[idx] = lastP[idx] - lastP[idx] = i + 1 - } - return count % 1000000007 -} diff --git a/828.unique-letter-string.js b/828.unique-letter-string.js new file mode 100644 index 00000000..6f91ed88 --- /dev/null +++ b/828.unique-letter-string.js @@ -0,0 +1,22 @@ +/** + * @param {string} s + * @return {number} + */ +const uniqueLetterString = function(s) { + const n = s.length + const arr = Array.from({ length: 26 }, () => Array(2).fill(-1)) + const A = 'A'.charCodeAt(0) + let res = 0 + for(let i = 0; i < n; i++) { + const idx = s.charCodeAt(i) - A + res += (i - arr[idx][1]) * (arr[idx][1] - arr[idx][0]) + arr[idx] = [arr[idx][1], i] + } + + for(let i = 0; i < 26; i++) { + res += (n - arr[i][1]) * (arr[i][1] - arr[i][0]) + } + + return res +}; + diff --git a/829-consecutive-numbers-sum.js b/829-consecutive-numbers-sum.js deleted file mode 100644 index e2d5e98f..00000000 --- a/829-consecutive-numbers-sum.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @param {number} N - * @return {number} - */ -const consecutiveNumbersSum = function (N) { - let count = 1 - for (let k = 2; k < Math.sqrt(2 * N); k++) { - if ((N - (k * (k - 1)) / 2) % k === 0) count++ - } - return count -} - -// another - -/** - * @param {number} N - * @return {number} - */ -const consecutiveNumbersSum = function(N) { - let res = 0 - for(let i = 1; i <= N; i++) { - const diff = i * (i - 1) / 2 - const nd = N - diff - if(nd <= 0) break - if(nd % i === 0) res++ - } - - return res -}; diff --git a/829.consecutive-numbers-sum.js b/829.consecutive-numbers-sum.js new file mode 100644 index 00000000..139bbfb9 --- /dev/null +++ b/829.consecutive-numbers-sum.js @@ -0,0 +1,12 @@ +/** + * @param {number} N + * @return {number} + */ +const consecutiveNumbersSum = function (N) { + let count = 1 + for (let k = 2; k < Math.sqrt(2 * N); k++) { + if ((N - (k * (k - 1)) / 2) % k === 0) count++ + } + return count +} + diff --git a/83-remove-duplicates-from-sorted-list.js b/83-remove-duplicates-from-sorted-list.js deleted file mode 100755 index 6339d4e7..00000000 --- a/83-remove-duplicates-from-sorted-list.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @return {ListNode} - */ -const deleteDuplicates = function(head) { - let current = head; - while (current !== null && current.next !== null) { - if (current.val === current.next.val) { - current.next = current.next.next; - } else { - current = current.next; - } - } - return head; -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @return {ListNode} - */ -const deleteDuplicates = function(head) { - let prev = null, cur = head - while(cur) { - if(prev && prev.val === cur.val) { - prev.next = cur.next - cur = cur.next - } else { - prev = cur - cur = cur.next - } - } - return head -}; - diff --git a/83.remove-duplicates-from-sorted-list.js b/83.remove-duplicates-from-sorted-list.js new file mode 100644 index 00000000..236e1dfa --- /dev/null +++ b/83.remove-duplicates-from-sorted-list.js @@ -0,0 +1,23 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @return {ListNode} + */ +const deleteDuplicates = function(head) { + let current = head; + while (current !== null && current.next !== null) { + if (current.val === current.next.val) { + current.next = current.next.next; + } else { + current = current.next; + } + } + return head; +}; + diff --git a/830-positions-of-large-groups.js b/830-positions-of-large-groups.js deleted file mode 100755 index a828815d..00000000 --- a/830-positions-of-large-groups.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {string} S - * @return {number[][]} - */ -const largeGroupPositions = function(S) { - if (S.length === 0) return []; - let prevChar = S[0]; - let curChar = S[0]; - let curStartIdx = 0; - let curCount = 1; - const res = []; - let tmpChar; - for (let i = 1; i < S.length; i++) { - tmpChar = S[i]; - if (tmpChar === prevChar) { - curCount += 1; - } else { - if (curCount >= 3) { - res.push([curStartIdx, curStartIdx + curCount - 1]); - } - - prevChar = S[i]; - curStartIdx = i; - curCount = 1; - } - } - - if (curCount >= 3) { - res.push([curStartIdx, curStartIdx + curCount - 1]); - } - - return res; -}; - -console.log(largeGroupPositions("aaa")); -console.log(largeGroupPositions("abbxxxxzzy")); -console.log(largeGroupPositions("abcdddeeeeaabbbcd")); diff --git a/830.positions-of-large-groups.js b/830.positions-of-large-groups.js new file mode 100644 index 00000000..4c7fb231 --- /dev/null +++ b/830.positions-of-large-groups.js @@ -0,0 +1,37 @@ +/** + * @param {string} S + * @return {number[][]} + */ +const largeGroupPositions = function(S) { + if (S.length === 0) return []; + let prevChar = S[0]; + let curChar = S[0]; + let curStartIdx = 0; + let curCount = 1; + const res = []; + let tmpChar; + for (let i = 1; i < S.length; i++) { + tmpChar = S[i]; + if (tmpChar === prevChar) { + curCount += 1; + } else { + if (curCount >= 3) { + res.push([curStartIdx, curStartIdx + curCount - 1]); + } + + prevChar = S[i]; + curStartIdx = i; + curCount = 1; + } + } + + if (curCount >= 3) { + res.push([curStartIdx, curStartIdx + curCount - 1]); + } + + return res; +}; + +console.log(largeGroupPositions("aaa")); +console.log(largeGroupPositions("abbxxxxzzy")); +console.log(largeGroupPositions("abcdddeeeeaabbbcd")); diff --git a/834-sum-of-distances-in-tree.js b/834.sum-of-distances-in-tree.js similarity index 100% rename from 834-sum-of-distances-in-tree.js rename to 834.sum-of-distances-in-tree.js diff --git a/835-image-overlap.js b/835.image-overlap.js similarity index 100% rename from 835-image-overlap.js rename to 835.image-overlap.js diff --git a/836-rectangle-overlap.js b/836.rectangle-overlap.js old mode 100755 new mode 100644 similarity index 100% rename from 836-rectangle-overlap.js rename to 836.rectangle-overlap.js diff --git a/837-new-21-game.js b/837.new-21-game.js old mode 100755 new mode 100644 similarity index 100% rename from 837-new-21-game.js rename to 837.new-21-game.js diff --git a/839-similar-string-groups.js b/839.similar-string-groups.js similarity index 100% rename from 839-similar-string-groups.js rename to 839.similar-string-groups.js diff --git a/84-largest-rectangle-in-histogram.js b/84-largest-rectangle-in-histogram.js deleted file mode 100644 index a05263fe..00000000 --- a/84-largest-rectangle-in-histogram.js +++ /dev/null @@ -1,81 +0,0 @@ -/** - * @param {number[]} heights - * @return {number} - */ -const largestRectangleArea = function(heights) { - let height = heights; - if (height == null || height.length == 0) { - return 0; - } - const lessFromLeft = new Array(height.length).fill(0); - const lessFromRight = new Array(height.length).fill(0); - lessFromRight[height.length - 1] = height.length; - lessFromLeft[0] = -1; - for (let i = 1; i < height.length; i++) { - let p = i - 1; - while (p >= 0 && height[p] >= height[i]) { - p = lessFromLeft[p]; - } - lessFromLeft[i] = p; - } - for (let i = height.length - 2; i >= 0; i--) { - let p = i + 1; - while (p < height.length && height[p] >= height[i]) { - p = lessFromRight[p]; - } - lessFromRight[i] = p; - } - let maxArea = 0; - for (let i = 0; i < height.length; i++) { - maxArea = Math.max( - maxArea, - height[i] * (lessFromRight[i] - lessFromLeft[i] - 1) - ); - } - return maxArea; -}; - - -// another - -/** - * @param {number[]} heights - * @return {number} - */ -const largestRectangleArea = function(heights) { - if (!heights.length) return 0; - let stack = []; - let max = 0; - for (let i = 0, cur, len = heights.length; i <= len; i++) { - cur = i === len ? -1 : heights[i]; - while (stack.length && cur < heights[stack[stack.length - 1]]) { - let index = stack.pop(); - let h = heights[index]; - let w = !stack.length ? i : i - stack[stack.length - 1] - 1; - max = Math.max(max, h * w); - } - stack.push(i); - } - return max; -}; - -// another - -/** - * @param {number[]} heights - * @return {number} - */ -const largestRectangleArea = function(heights) { - heights.push(0) - const st = [], n = heights.length - let res = 0 - for(let i = 0; i <= n; i++) { - while(st.length && heights[st[st.length - 1]] >= heights[i]) { - const top = st.pop() - const pre = st.length ? st[st.length - 1] : -1 - res = Math.max(res, heights[top] * (i - pre - 1)) - } - st.push(i) - } - return res -}; diff --git a/84.largest-rectangle-in-histogram.js b/84.largest-rectangle-in-histogram.js new file mode 100644 index 00000000..e27acd17 --- /dev/null +++ b/84.largest-rectangle-in-histogram.js @@ -0,0 +1,38 @@ +/** + * @param {number[]} heights + * @return {number} + */ +const largestRectangleArea = function(heights) { + let height = heights; + if (height == null || height.length == 0) { + return 0; + } + const lessFromLeft = new Array(height.length).fill(0); + const lessFromRight = new Array(height.length).fill(0); + lessFromRight[height.length - 1] = height.length; + lessFromLeft[0] = -1; + for (let i = 1; i < height.length; i++) { + let p = i - 1; + while (p >= 0 && height[p] >= height[i]) { + p = lessFromLeft[p]; + } + lessFromLeft[i] = p; + } + for (let i = height.length - 2; i >= 0; i--) { + let p = i + 1; + while (p < height.length && height[p] >= height[i]) { + p = lessFromRight[p]; + } + lessFromRight[i] = p; + } + let maxArea = 0; + for (let i = 0; i < height.length; i++) { + maxArea = Math.max( + maxArea, + height[i] * (lessFromRight[i] - lessFromLeft[i] - 1) + ); + } + return maxArea; +}; + + diff --git a/841-keys-and-rooms.js b/841-keys-and-rooms.js deleted file mode 100755 index a4ae46de..00000000 --- a/841-keys-and-rooms.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * @param {number[][]} rooms - * @return {boolean} - */ -const canVisitAllRooms = function(rooms) { - const stack = []; - const seen = []; - for (let i = 0; i < rooms.length; i++) { - seen[i] = false; - } - seen[0] = true; - stack.push(0); - while (stack.length) { - let node = stack.pop(); - for (let el of rooms[node]) { - if (!seen[el]) { - seen[el] = true; - stack.push(el); - } - } - } - for (let el of seen) { - if (!el) return false; - } - return true; -}; diff --git a/841.keys-and-rooms.js b/841.keys-and-rooms.js new file mode 100644 index 00000000..e66723cc --- /dev/null +++ b/841.keys-and-rooms.js @@ -0,0 +1,26 @@ +/** + * @param {number[][]} rooms + * @return {boolean} + */ +const canVisitAllRooms = function(rooms) { + const stack = []; + const seen = []; + for (let i = 0; i < rooms.length; i++) { + seen[i] = false; + } + seen[0] = true; + stack.push(0); + while (stack.length) { + let node = stack.pop(); + for (let el of rooms[node]) { + if (!seen[el]) { + seen[el] = true; + stack.push(el); + } + } + } + for (let el of seen) { + if (!el) return false; + } + return true; +}; diff --git a/843-guess-the-word.js b/843.guess-the-word.js similarity index 100% rename from 843-guess-the-word.js rename to 843.guess-the-word.js diff --git a/844-backspace-string-compare.js b/844.backspace-string-compare.js similarity index 100% rename from 844-backspace-string-compare.js rename to 844.backspace-string-compare.js diff --git a/845-longest-mountain-in-array.js b/845.longest-mountain-in-array.js similarity index 100% rename from 845-longest-mountain-in-array.js rename to 845.longest-mountain-in-array.js diff --git a/847-shortest-path-visiting-all-nodes.js b/847.shortest-path-visiting-all-nodes.js similarity index 100% rename from 847-shortest-path-visiting-all-nodes.js rename to 847.shortest-path-visiting-all-nodes.js diff --git a/848-shifting-letters.js b/848.shifting-letters.js similarity index 100% rename from 848-shifting-letters.js rename to 848.shifting-letters.js diff --git a/849-maximize-distance-to-closest-person.js b/849.maximize-distance-to-closest-person.js similarity index 100% rename from 849-maximize-distance-to-closest-person.js rename to 849.maximize-distance-to-closest-person.js diff --git a/85-maximal-rectangle.js b/85-maximal-rectangle.js deleted file mode 100644 index fd57a2d6..00000000 --- a/85-maximal-rectangle.js +++ /dev/null @@ -1,119 +0,0 @@ -/** - * @param {character[][]} matrix - * @return {number} - */ -const maximalRectangle = function(matrix) { - const m = matrix.length, n = matrix[0].length - const left = Array(n).fill(0) - const right = Array(n).fill(n - 1) - const height = Array(n).fill(0) - - let res = 0 - - for(let i = 0; i < m; i++) { - let l = 0, r = n - 1 - for(let j = 0; j < n; j++) { - if(matrix[i][j] === '1') left[j] = Math.max(left[j], l) - else { - left[j] = 0 - l = j + 1 - } - } - - for(let j = n - 1; j >= 0; j--) { - if(matrix[i][j] === '1') right[j] = Math.min(right[j], r) - else { - right[j] = n - 1 - r = j - 1 - } - } - - for(let j = 0; j < n; j++) { - height[j] = matrix[i][j] === '1' ? height[j] + 1 : 0 - res = Math.max(res, (right[j] - left[j] + 1) * height[j]) - } - - // console.log(left, right, height) - } - - return res -}; - -// another - - -/** - * @param {character[][]} matrix - * @return {number} - */ -const maximalRectangle = function(matrix) { - if(matrix.length === 0) return 0; - const m = matrix.length; // rows - const n = matrix[0].length; // cols - const left = new Array(n).fill(0) - const right = new Array(n).fill(n) - const height = new Array(n).fill(0); - let maxA = 0; - for(let i = 0; i < m; i++) { - let cur_left = 0, cur_right = n; - // compute height (can do this from either side) - for(let j = 0; j < n; j++) { - if(matrix[i][j] === '1') height[j]++; - else height[j] = 0; - } - // compute left (from left to right) - for(let j = 0; j < n; j++) { - if(matrix[i][j] ==='1') left[j] = Math.max(left[j], cur_left); - else {left[j] = 0; cur_left = j + 1;} - } - // compute right (from right to left) - for(let j = n - 1; j >= 0; j--) { - if(matrix[i][j] === '1') right[j] = Math.min(right[j], cur_right); - else {right[j] = n; cur_right = j;} - } - // compute the area of rectangle (can do this from either side) - for(let j = 0; j < n; j++) { - maxA = Math.max(maxA, (right[j] - left[j]) * height[j]); - } - } - return maxA; -}; - -// another - -/** - * @param {character[][]} matrix - * @return {number} - */ -const maximalRectangle = function(matrix) { - if (matrix == null || matrix.length === 0 || matrix[0] == null || matrix[0].length === 0) return 0; - let m = matrix.length, n = matrix[0].length, maxArea = 0; - - const left = new Array(n).fill(0) - const right = new Array(n).fill(n - 1) - const height = new Array(n).fill(0) - for (let i = 0; i < m; i++) { - let rB = n - 1; - for (let j = n - 1; j >= 0; j--) { - if (matrix[i][j] === '1') { - right[j] = Math.min(right[j], rB); - } else { - right[j] = n - 1; - rB = j - 1; - } - } - let lB = 0; - for (let j = 0; j < n; j++) { - if (matrix[i][j] === '1') { - left[j] = Math.max(left[j], lB); - height[j]++; - maxArea = Math.max(maxArea, height[j] * (right[j] - left[j] + 1)); - } else { - height[j] = 0; - left[j] = 0; - lB = j + 1; - } - } - } - return maxArea; -}; diff --git a/85.maximal-rectangle.js b/85.maximal-rectangle.js new file mode 100644 index 00000000..d0e314b7 --- /dev/null +++ b/85.maximal-rectangle.js @@ -0,0 +1,41 @@ +/** + * @param {character[][]} matrix + * @return {number} + */ +const maximalRectangle = function(matrix) { + const m = matrix.length, n = matrix[0].length + const left = Array(n).fill(0) + const right = Array(n).fill(n - 1) + const height = Array(n).fill(0) + + let res = 0 + + for(let i = 0; i < m; i++) { + let l = 0, r = n - 1 + for(let j = 0; j < n; j++) { + if(matrix[i][j] === '1') left[j] = Math.max(left[j], l) + else { + left[j] = 0 + l = j + 1 + } + } + + for(let j = n - 1; j >= 0; j--) { + if(matrix[i][j] === '1') right[j] = Math.min(right[j], r) + else { + right[j] = n - 1 + r = j - 1 + } + } + + for(let j = 0; j < n; j++) { + height[j] = matrix[i][j] === '1' ? height[j] + 1 : 0 + res = Math.max(res, (right[j] - left[j] + 1) * height[j]) + } + + // console.log(left, right, height) + } + + return res +}; + diff --git a/850-rectangle-area-ii.js b/850.rectangle-area-ii.js similarity index 100% rename from 850-rectangle-area-ii.js rename to 850.rectangle-area-ii.js diff --git a/854-k-similar-strings.js b/854.k-similar-strings.js similarity index 100% rename from 854-k-similar-strings.js rename to 854.k-similar-strings.js diff --git a/855-exam-room.js b/855.exam-room.js similarity index 100% rename from 855-exam-room.js rename to 855.exam-room.js diff --git a/856-score-of-parentheses.js b/856.score-of-parentheses.js old mode 100755 new mode 100644 similarity index 100% rename from 856-score-of-parentheses.js rename to 856.score-of-parentheses.js diff --git a/857-minimum-cost-to-hire-k-workers.js b/857-minimum-cost-to-hire-k-workers.js deleted file mode 100644 index 76914b01..00000000 --- a/857-minimum-cost-to-hire-k-workers.js +++ /dev/null @@ -1,98 +0,0 @@ -/** - * @param {number[]} quality - * @param {number[]} wage - * @param {number} K - * @return {number} - */ -const mincostToHireWorkers = function(quality, wage, K) { - const workers = [], n = quality.length; - for (let i = 0; i < n; i++) { - workers[i] = { ratio: wage[i] / quality[i], quality: quality[i] } - } - workers.sort((a, b) => a.ratio - b.ratio); - const heap = new MaxPriorityQueue({ priority: x => x.quality }); - let totalQuality = 0, res = Infinity; - while (workers.length) { - const curWorker = workers.shift(); - totalQuality += curWorker.quality; - heap.enqueue(curWorker); - - if (heap.size() > K) { - totalQuality -= heap.dequeue().element.quality; - } - if (heap.size() === K) { - res = Math.min(res, curWorker.ratio * totalQuality) - } - } - return res; -}; - - - -// another - -/** - * @param {number[]} quality - * @param {number[]} wage - * @param {number} K - * @return {number} - */ -const mincostToHireWorkers = function(quality, wage, K) { - const workers = Array.from({length: quality.length}, () => new Array(2)); - for (let i = 0; i < quality.length; ++i) workers[i] = [wage[i] / quality[i], quality[i]]; - workers.sort((a, b) => a[0] - b[0]) - let res = Number.MAX_VALUE, qsum = 0; - const queue = [] - for (let worker of workers) { - qsum += worker[1]; - insert(queue, -worker[1]) - if (queue.length > K) qsum += queue.shift(); - if (queue.length === K) res = Math.min(res, qsum * worker[0]); - } - return res; -}; - -function insert(arr, el) { - for(let i = 0; i < arr.length; i++) { - if(arr[i] > el) { - arr.splice(i, 0, el) - return - } - } - arr.push(el) -} - -// another - -/** - * @param {number[]} quality - * @param {number[]} wage - * @param {number} K - * @return {number} - */ -const mincostToHireWorkers = function(quality, wage, K) { - const workers = [], n = wage.length - for(let i = 0; i < n; i++) { - workers.push([wage[i] / quality[i], quality[i]]) - } - // wage[i] / wage[j] = quality[i] / quality[j] - // wage[i] * quality[j] = wage[j] * quality[i] - // wage[i] / quality[i] = wage[j] / quality[j] - workers.sort((a, b) => a[0] - b[0]) - const pq = new MaxPriorityQueue({ priority: (w) => w.quality }) - let res = Infinity, qualitySum = 0 - for(const worker of workers) { - const [ratio, quality] = worker - qualitySum += quality - pq.enqueue({ quality }) - - if(pq.size() > K) { - qualitySum -= pq.dequeue().element.quality - } - if(pq.size() === K) res = Math.min(res, qualitySum * ratio) - } - - return res -}; - - diff --git a/857.minimum-cost-to-hire-k-workers.js b/857.minimum-cost-to-hire-k-workers.js new file mode 100644 index 00000000..6ce4b01c --- /dev/null +++ b/857.minimum-cost-to-hire-k-workers.js @@ -0,0 +1,31 @@ +/** + * @param {number[]} quality + * @param {number[]} wage + * @param {number} K + * @return {number} + */ +const mincostToHireWorkers = function(quality, wage, K) { + const workers = [], n = quality.length; + for (let i = 0; i < n; i++) { + workers[i] = { ratio: wage[i] / quality[i], quality: quality[i] } + } + workers.sort((a, b) => a.ratio - b.ratio); + const heap = new MaxPriorityQueue({ priority: x => x.quality }); + let totalQuality = 0, res = Infinity; + while (workers.length) { + const curWorker = workers.shift(); + totalQuality += curWorker.quality; + heap.enqueue(curWorker); + + if (heap.size() > K) { + totalQuality -= heap.dequeue().element.quality; + } + if (heap.size() === K) { + res = Math.min(res, curWorker.ratio * totalQuality) + } + } + return res; +}; + + + diff --git a/858-mirror-reflection.js b/858-mirror-reflection.js deleted file mode 100755 index d02c43ea..00000000 --- a/858-mirror-reflection.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * @param {number} p - * @param {number} q - * @return {number} - */ -const mirrorReflection = function(p, q) { - while (p % 2 === 0 && q % 2 === 0) { - p /= 2; - q /= 2; - } - - if (p % 2 === 0) { - return 2; - } else if (q % 2 === 0) { - return 0; - } else { - return 1; - } -}; diff --git a/858.mirror-reflection.js b/858.mirror-reflection.js new file mode 100644 index 00000000..361404d1 --- /dev/null +++ b/858.mirror-reflection.js @@ -0,0 +1,19 @@ +/** + * @param {number} p + * @param {number} q + * @return {number} + */ +const mirrorReflection = function(p, q) { + while (p % 2 === 0 && q % 2 === 0) { + p /= 2; + q /= 2; + } + + if (p % 2 === 0) { + return 2; + } else if (q % 2 === 0) { + return 0; + } else { + return 1; + } +}; diff --git a/859-buddy-strings.js b/859.buddy-strings.js similarity index 100% rename from 859-buddy-strings.js rename to 859.buddy-strings.js diff --git a/86-partition-list.js b/86-partition-list.js deleted file mode 100644 index d326dfa9..00000000 --- a/86-partition-list.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @param {number} x - * @return {ListNode} - */ -const partition = function(head, x) { - const leftHead = new ListNode(); - const rightHead = new ListNode(); - let left = leftHead; - let right = rightHead; - - // split list into two sides, left if val < x, else right - for (let node = head; node !== null; node = node.next) { - if (node.val < x) { - left.next = node; - left = node; - } else { - right.next = node; - right = node; - } - } - - // combine the two sides - left.next = rightHead.next; - right.next = null; - - return leftHead.next; -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @param {number} x - * @return {ListNode} - */ -const partition = function(head, x) { - const left = [] - const right = [] - let containX = false - let cur = head - while(cur !== null) { - if (containX === true) { - if (cur.val < x) { - left.push(cur) - } else { - right.push(cur) - } - } else { - if (cur.val >= x) { - containX = true - right.push(cur) - } else { - left.push(cur) - } - } - cur = cur.next - } - const arr = left.concat(right) - - for(let i = 0; i < arr.length; i++) { - if (i === arr.length - 1) { - arr[i].next = null - } else { - arr[i].next = arr[i+1] - } - } - return arr[0] == null ? null : arr[0] -}; diff --git a/86.partition-list.js b/86.partition-list.js new file mode 100644 index 00000000..ca6afd8b --- /dev/null +++ b/86.partition-list.js @@ -0,0 +1,36 @@ +/** + * Definition for singly-linked list. + * function ListNode(val) { + * this.val = val; + * this.next = null; + * } + */ +/** + * @param {ListNode} head + * @param {number} x + * @return {ListNode} + */ +const partition = function(head, x) { + const leftHead = new ListNode(); + const rightHead = new ListNode(); + let left = leftHead; + let right = rightHead; + + // split list into two sides, left if val < x, else right + for (let node = head; node !== null; node = node.next) { + if (node.val < x) { + left.next = node; + left = node; + } else { + right.next = node; + right = node; + } + } + + // combine the two sides + left.next = rightHead.next; + right.next = null; + + return leftHead.next; +}; + diff --git a/860-lemonade-change.js b/860-lemonade-change.js deleted file mode 100755 index 57d282e0..00000000 --- a/860-lemonade-change.js +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @param {number[]} bills - * @return {boolean} - */ -const lemonadeChange = function(bills) { - let five = 0; - let ten = 0; - for (let el of bills) { - if (el === 5) { - five += 1; - } else if (el === 10) { - if (five < 1) return false; - five -= 1; - ten += 1; - } else { - if (five > 0 && ten > 0) { - five -= 1; - ten -= 1; - } else if (five >= 3) { - five -= 3; - } else { - return false; - } - } - } - - return true; -}; diff --git a/860.lemonade-change.js b/860.lemonade-change.js new file mode 100644 index 00000000..eaed3e73 --- /dev/null +++ b/860.lemonade-change.js @@ -0,0 +1,28 @@ +/** + * @param {number[]} bills + * @return {boolean} + */ +const lemonadeChange = function(bills) { + let five = 0; + let ten = 0; + for (let el of bills) { + if (el === 5) { + five += 1; + } else if (el === 10) { + if (five < 1) return false; + five -= 1; + ten += 1; + } else { + if (five > 0 && ten > 0) { + five -= 1; + ten -= 1; + } else if (five >= 3) { + five -= 3; + } else { + return false; + } + } + } + + return true; +}; diff --git a/861-score-after-flipping-matrix.js b/861-score-after-flipping-matrix.js deleted file mode 100644 index 4c57cb6c..00000000 --- a/861-score-after-flipping-matrix.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const matrixScore = function(grid) { - const m = grid.length, n = grid[0].length - let res = 0 - res += m * (1 << (n - 1)) - for(let j = 1; j < n; j++) { - let same = 0 - for(let i = 0; i < m; i++) { - if(grid[i][0] === grid[i][j]) same++ - } - res += Math.max(same, m - same) * (1 << (n - 1 - j)) - } - - return res -}; - -// another - -/** - * @param {number[][]} grid - * @return {number} - */ -const matrixScore = function(grid) { - const m = grid.length, n = grid[0].length - for(let i = 0; i < m; i++) { - if(grid[i][0] === 0) flipRow(i) - } - - for(let i = 0; i < n; i++) { - if(cntCol(i, 0) > cntCol(i, 1)) flipCol(i) - } - - let res = 0 - // console.log(grid) - for(const row of grid) { - res += parseInt(row.join(''), 2) - } - - return res - - - function flipRow(idx) { - for(let i = 0; i < n; i++) { - if(grid[idx][i] === 0) grid[idx][i] = 1 - else grid[idx][i] = 0 - } - } - - function cntCol(idx, target) { - let res = 0 - for(let i = 0; i < m; i++) { - if(grid[i][idx] === target) res++ - } - // console.log(res) - return res - } - - function flipCol(idx) { - for(let i = 0; i < m; i++) { - if(grid[i][idx] === 0) grid[i][idx] = 1 - else grid[i][idx] = 0 - } - } -}; diff --git a/861.score-after-flipping-matrix.js b/861.score-after-flipping-matrix.js new file mode 100644 index 00000000..a7268107 --- /dev/null +++ b/861.score-after-flipping-matrix.js @@ -0,0 +1,19 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const matrixScore = function(grid) { + const m = grid.length, n = grid[0].length + let res = 0 + res += m * (1 << (n - 1)) + for(let j = 1; j < n; j++) { + let same = 0 + for(let i = 0; i < m; i++) { + if(grid[i][0] === grid[i][j]) same++ + } + res += Math.max(same, m - same) * (1 << (n - 1 - j)) + } + + return res +}; + diff --git a/862-shortest-subarray-with-sum-at-least-k.js b/862-shortest-subarray-with-sum-at-least-k.js deleted file mode 100644 index e09e2839..00000000 --- a/862-shortest-subarray-with-sum-at-least-k.js +++ /dev/null @@ -1,57 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const shortestSubarray = function(nums, k) { - const q = [], n = nums.length - let res = Infinity, sum = 0 - const prefix = [] - for(let i = 0; i < n; i++) { - sum += nums[i] - prefix.push(sum) - if(sum >= k) res = Math.min(res, i + 1) - } - - for(let i = 0; i < n; i++) { - while(q.length && prefix[i] <= prefix[q[q.length - 1]]) q.pop() - while(q.length && prefix[i] - prefix[q[0]] >= k) { - res = Math.min(res, i - q[0]) - q.shift() - } - - q.push(i) - } - - return res === Infinity ? -1 : res -}; - -// another - -/** - * @param {number[]} A - * @param {number} K - * @return {number} - */ -const shortestSubarray = function(A, K) { - const N = A.length - const P = new Array(N+1).fill(0) - - for(let i = 0; i < N; i++) { - P[i+1] = P[i] + A[i] - } - - let ans = N + 1 - const monoq = [] - for(let y = 0; y < P.length; y++) { - while(monoq.length > 0 && P[y] <= P[monoq[monoq.length - 1]] ) { - monoq.pop() - } - while(monoq.length > 0 && P[y] >= P[monoq[0]] + K ) { - ans = Math.min(ans, y - monoq.shift()) - } - monoq.push(y) - } - - return ans < N + 1 ? ans : -1 -}; diff --git a/862.shortest-subarray-with-sum-at-least-k.js b/862.shortest-subarray-with-sum-at-least-k.js new file mode 100644 index 00000000..095c1844 --- /dev/null +++ b/862.shortest-subarray-with-sum-at-least-k.js @@ -0,0 +1,28 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const shortestSubarray = function(nums, k) { + const q = [], n = nums.length + let res = Infinity, sum = 0 + const prefix = [] + for(let i = 0; i < n; i++) { + sum += nums[i] + prefix.push(sum) + if(sum >= k) res = Math.min(res, i + 1) + } + + for(let i = 0; i < n; i++) { + while(q.length && prefix[i] <= prefix[q[q.length - 1]]) q.pop() + while(q.length && prefix[i] - prefix[q[0]] >= k) { + res = Math.min(res, i - q[0]) + q.shift() + } + + q.push(i) + } + + return res === Infinity ? -1 : res +}; + diff --git a/863-all-nodes-distance-k-in-binary-tree.js b/863-all-nodes-distance-k-in-binary-tree.js deleted file mode 100644 index 51fc2e8f..00000000 --- a/863-all-nodes-distance-k-in-binary-tree.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {TreeNode} target - * @param {number} K - * @return {number[]} - */ -const distanceK = function(root, target, K) { - const map = new Map(); - const res = []; - if (target == null || K < 0 || root == null) return res; - buildGraph(root, null); - const visited = new Set(); - const q = []; - visited.add(target); - q.push(target); - while (q.length) { - const len = q.length; - if (K === 0) { - for (let i = 0; i < len; i++) res.push(q.shift().val); - return res; - } - for (let i = 0; i < len; i++) { - const el = q.shift(); - for (let e of map.get(el)) { - if (visited.has(e)) continue; - visited.add(e); - q.push(e); - } - } - K--; - } - return res; - - function buildGraph(node, parent) { - if (node === null) return; - if (!map.has(node)) { - map.set(node, []); - if (parent !== null) { - map.get(node).push(parent); - if (!map.has(parent)) map.set(parent, []); - map.get(parent).push(node); - } - buildGraph(node.left, node); - buildGraph(node.right, node); - } - } -}; - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {TreeNode} target - * @param {number} K - * @return {number[]} - */ -const distanceK = function(root, target, K) { - let res = [] - dfs(root, target, K, res) - return res -} - -function dfs(node, target, k, res) { - if (node === null) return -1 - if (node === target) { - getRes(node, 0, k, res) - return 1 - } - let left = dfs(node.left, target, k, res) - let right = dfs(node.right, target, k, res) - if (left !== -1) { - if (left === k) res.push(node.val) - getRes(node.right, left + 1, k, res) - return left + 1 - } - if (right !== -1) { - if (right === k) res.push(node.val) - getRes(node.left, right + 1, k, res) - return right + 1 - } - return -1 -} - -function getRes(node, dist, k, res) { - if (node === null) return - if (dist === k) return res.push(node.val) - getRes(node.left, dist + 1, k, res) - getRes(node.right, dist + 1, k, res) -} diff --git a/863.all-nodes-distance-k-in-binary-tree.js b/863.all-nodes-distance-k-in-binary-tree.js new file mode 100644 index 00000000..dd5f0d13 --- /dev/null +++ b/863.all-nodes-distance-k-in-binary-tree.js @@ -0,0 +1,55 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @param {TreeNode} target + * @param {number} K + * @return {number[]} + */ +const distanceK = function(root, target, K) { + const map = new Map(); + const res = []; + if (target == null || K < 0 || root == null) return res; + buildGraph(root, null); + const visited = new Set(); + const q = []; + visited.add(target); + q.push(target); + while (q.length) { + const len = q.length; + if (K === 0) { + for (let i = 0; i < len; i++) res.push(q.shift().val); + return res; + } + for (let i = 0; i < len; i++) { + const el = q.shift(); + for (let e of map.get(el)) { + if (visited.has(e)) continue; + visited.add(e); + q.push(e); + } + } + K--; + } + return res; + + function buildGraph(node, parent) { + if (node === null) return; + if (!map.has(node)) { + map.set(node, []); + if (parent !== null) { + map.get(node).push(parent); + if (!map.has(parent)) map.set(parent, []); + map.get(parent).push(node); + } + buildGraph(node.left, node); + buildGraph(node.right, node); + } + } +}; + diff --git a/864-shortest-path-to-get-all-keys.js b/864.shortest-path-to-get-all-keys.js similarity index 100% rename from 864-shortest-path-to-get-all-keys.js rename to 864.shortest-path-to-get-all-keys.js diff --git a/865-smallest-subtree-with-all-the-deepest-nodes.js b/865-smallest-subtree-with-all-the-deepest-nodes.js deleted file mode 100755 index cea0b7a0..00000000 --- a/865-smallest-subtree-with-all-the-deepest-nodes.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode} - */ -const subtreeWithAllDeepest = function(root) { - return dfs(root).node; -}; - -function dfs(node) { - if (node == null) return new result(null, 0); - const l = dfs(node.left); - const r = dfs(node.right); - if (l.dist > r.dist) return new result(l.node, l.dist + 1); - if (l.dist < r.dist) return new result(r.node, r.dist + 1); - return new result(node, l.dist + 1); -} - -function result(node, dist) { - this.node = node; - this.dist = dist; -} - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @return {TreeNode} - */ -const subtreeWithAllDeepest = function(root) { - let res = null, maxDepth = 0 - dfs(root, 0) - - return res - - function dfs(node, depth) { - if(node == null) return depth - 1 - - const left = dfs(node.left, depth + 1) - const right = dfs(node.right, depth + 1) - maxDepth = Math.max(maxDepth, left, right) - - if(left === maxDepth && right === maxDepth) { - res = node - } - return Math.max(left, right) - } -}; diff --git a/865.smallest-subtree-with-all-the-deepest-nodes.js b/865.smallest-subtree-with-all-the-deepest-nodes.js new file mode 100644 index 00000000..6ae65569 --- /dev/null +++ b/865.smallest-subtree-with-all-the-deepest-nodes.js @@ -0,0 +1,29 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {TreeNode} + */ +const subtreeWithAllDeepest = function(root) { + return dfs(root).node; +}; + +function dfs(node) { + if (node == null) return new result(null, 0); + const l = dfs(node.left); + const r = dfs(node.right); + if (l.dist > r.dist) return new result(l.node, l.dist + 1); + if (l.dist < r.dist) return new result(r.node, r.dist + 1); + return new result(node, l.dist + 1); +} + +function result(node, dist) { + this.node = node; + this.dist = dist; +} + diff --git a/866-prime-palindrome.js b/866-prime-palindrome.js deleted file mode 100644 index 78d70c50..00000000 --- a/866-prime-palindrome.js +++ /dev/null @@ -1,73 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const primePalindrome = function(n) { - if(n >= 8 && n <= 11) return 11 - const rev = str => str.split('').reverse().join('') - for (let i = 1; i < 1e5; i++) { - let left = `${i}`, right = rev(left).slice(1) - let num = +(left + right) - if (num >= n && isPrime(num)) return num - } - return -1 - - function isPrime(num) { - if(num < 2 || num % 2 === 0) return num === 2 - for(let i = 3; i * i <= num; i += 2) { - if(num % i === 0) return false - } - return true - } -}; - -// another - -/** - * @param {number} N - * @return {number} - */ -const primePalindrome = function(N) { - if(N >= 8 && N <= 11) return 11 - for(let x = 1; x < 100000; x++) { - let s = '' + x, r = s.split('').reverse().join('') - let y = +(s + r.slice(1)) - if(y >= N && isPrime(y)) return y - } - return -1 -}; - -function isPrime(x) { - if(x < 2 || x % 2 === 0) return x === 2 - for(let i = 3; i * i <= x; i += 2) { - if(x % i === 0) return false - } - return true -} - -// another - - -/** - * @param {number} n - * @return {number} - */ -const primePalindrome = function(n) { - if(n >= 8 && n <= 11) return 11 - - const rev = num => `${num}`.split('').reverse().join('') - for(let i = 1; i < 1e5; i++) { - let left = i, right = rev(left).slice(1) - const tmp = +(left + right) - if(tmp >= n && isPrime(tmp)) return tmp - } - - function isPrime(num) { - if(num <= 2) return num === 2 - if(num % 2 === 0) return false - for(let i = 3; i ** 2 <= num; i += 2) { - if(num % i === 0) return false - } - return true - } -}; diff --git a/866.prime-palindrome.js b/866.prime-palindrome.js new file mode 100644 index 00000000..2379eaab --- /dev/null +++ b/866.prime-palindrome.js @@ -0,0 +1,23 @@ +/** + * @param {number} n + * @return {number} + */ +const primePalindrome = function(n) { + if(n >= 8 && n <= 11) return 11 + const rev = str => str.split('').reverse().join('') + for (let i = 1; i < 1e5; i++) { + let left = `${i}`, right = rev(left).slice(1) + let num = +(left + right) + if (num >= n && isPrime(num)) return num + } + return -1 + + function isPrime(num) { + if(num < 2 || num % 2 === 0) return num === 2 + for(let i = 3; i * i <= num; i += 2) { + if(num % i === 0) return false + } + return true + } +}; + diff --git a/868-binary-gap.js b/868-binary-gap.js deleted file mode 100755 index bfafb7fa..00000000 --- a/868-binary-gap.js +++ /dev/null @@ -1,22 +0,0 @@ -/** - * @param {number} N - * @return {number} - */ -const binaryGap = function(N) { - const bin = (N >>> 0).toString(2); - const idxArr = []; - for (let i = 0; i < bin.length; i++) { - const num = bin.charAt(i); - if (num === "1") { - idxArr.push(i); - } - } - let maxConLen = 0; - for (let idx = 0; idx < idxArr.length - 1; idx++) { - if (idxArr[idx + 1] - idxArr[idx] > maxConLen) { - maxConLen = idxArr[idx + 1] - idxArr[idx]; - } - } - - return maxConLen; -}; diff --git a/868.binary-gap.js b/868.binary-gap.js new file mode 100644 index 00000000..0034c853 --- /dev/null +++ b/868.binary-gap.js @@ -0,0 +1,22 @@ +/** + * @param {number} N + * @return {number} + */ +const binaryGap = function(N) { + const bin = (N >>> 0).toString(2); + const idxArr = []; + for (let i = 0; i < bin.length; i++) { + const num = bin.charAt(i); + if (num === "1") { + idxArr.push(i); + } + } + let maxConLen = 0; + for (let idx = 0; idx < idxArr.length - 1; idx++) { + if (idxArr[idx + 1] - idxArr[idx] > maxConLen) { + maxConLen = idxArr[idx + 1] - idxArr[idx]; + } + } + + return maxConLen; +}; diff --git a/869-reordered-power-of-2.js b/869-reordered-power-of-2.js deleted file mode 100755 index 910b20eb..00000000 --- a/869-reordered-power-of-2.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @param {number} N - * @return {boolean} - */ -const reorderedPowerOf2 = function(N) { - const A = count(N); - for (let i = 0; i < 31; i++) { - if (arrayEqual(A, count(1 << i))) return true; - } - return false; -}; - -function count(num) { - const res = []; - while (num > 0) { - addOne(res, num % 10); - num = parseInt(num / 10); - } - return res; -} -function addOne(arr, idx) { - if (arr[idx]) { - arr[idx] += 1; - return; - } - arr[idx] = 1; -} -function arrayEqual(a1, a2) { - return JSON.stringify(a1) === JSON.stringify(a2); -} - -console.log(reorderedPowerOf2(1)); -console.log(reorderedPowerOf2(10)); -console.log(reorderedPowerOf2(16)); -console.log(reorderedPowerOf2(24)); -console.log(reorderedPowerOf2(46)); diff --git a/869.reordered-power-of-2.js b/869.reordered-power-of-2.js new file mode 100644 index 00000000..e6b28435 --- /dev/null +++ b/869.reordered-power-of-2.js @@ -0,0 +1,36 @@ +/** + * @param {number} N + * @return {boolean} + */ +const reorderedPowerOf2 = function(N) { + const A = count(N); + for (let i = 0; i < 31; i++) { + if (arrayEqual(A, count(1 << i))) return true; + } + return false; +}; + +function count(num) { + const res = []; + while (num > 0) { + addOne(res, num % 10); + num = parseInt(num / 10); + } + return res; +} +function addOne(arr, idx) { + if (arr[idx]) { + arr[idx] += 1; + return; + } + arr[idx] = 1; +} +function arrayEqual(a1, a2) { + return JSON.stringify(a1) === JSON.stringify(a2); +} + +console.log(reorderedPowerOf2(1)); +console.log(reorderedPowerOf2(10)); +console.log(reorderedPowerOf2(16)); +console.log(reorderedPowerOf2(24)); +console.log(reorderedPowerOf2(46)); diff --git a/87-scramble-string.js b/87.scramble-string.js similarity index 100% rename from 87-scramble-string.js rename to 87.scramble-string.js diff --git a/870-advantage-shuffle.js b/870.advantage-shuffle.js similarity index 100% rename from 870-advantage-shuffle.js rename to 870.advantage-shuffle.js diff --git a/871-minimum-number-of-refueling-stops.js b/871.minimum-number-of-refueling-stops.js similarity index 100% rename from 871-minimum-number-of-refueling-stops.js rename to 871.minimum-number-of-refueling-stops.js diff --git a/873-length-of-longest-fibonacci-subsequence.js b/873-length-of-longest-fibonacci-subsequence.js deleted file mode 100755 index 02c244a0..00000000 --- a/873-length-of-longest-fibonacci-subsequence.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @param {number[]} A - * @return {number} - */ -const lenLongestFibSubseq = function(A) { - const n = A.length; - let max = 0; - const dp = Array(n).map(el => Array(n).fill(0)); - for (let i = 1; i < n; i++) { - let l = 0, - r = i - 1; - while (l < r) { - let sum = A[l] + A[r]; - if (sum > A[i]) { - r--; - } else if (sum < A[i]) { - l++; - } else { - dp[r][i] = dp[l][r] + 1; - max = Math.max(max, dp[r][i]); - r--; - l++; - } - } - } - return max == 0 ? 0 : max + 2; -}; diff --git a/873.length-of-longest-fibonacci-subsequence.js b/873.length-of-longest-fibonacci-subsequence.js new file mode 100644 index 00000000..e892ced4 --- /dev/null +++ b/873.length-of-longest-fibonacci-subsequence.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} A + * @return {number} + */ +const lenLongestFibSubseq = function(A) { + const n = A.length; + let max = 0; + const dp = Array(n).map(el => Array(n).fill(0)); + for (let i = 1; i < n; i++) { + let l = 0, + r = i - 1; + while (l < r) { + let sum = A[l] + A[r]; + if (sum > A[i]) { + r--; + } else if (sum < A[i]) { + l++; + } else { + dp[r][i] = dp[l][r] + 1; + max = Math.max(max, dp[r][i]); + r--; + l++; + } + } + } + return max == 0 ? 0 : max + 2; +}; diff --git a/874-walking-robot-simulation.js b/874.walking-robot-simulation.js similarity index 100% rename from 874-walking-robot-simulation.js rename to 874.walking-robot-simulation.js diff --git a/875-koko-eating-bananas.js b/875.koko-eating-bananas.js similarity index 100% rename from 875-koko-eating-bananas.js rename to 875.koko-eating-bananas.js diff --git a/876-middle-of-the-linked-list.js b/876.middle-of-the-linked-list.js similarity index 100% rename from 876-middle-of-the-linked-list.js rename to 876.middle-of-the-linked-list.js diff --git a/878-nth-magical-number.js b/878-nth-magical-number.js deleted file mode 100644 index 5442069e..00000000 --- a/878-nth-magical-number.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {number} N - * @param {number} A - * @param {number} B - * @return {number} - */ -const gcd = (x, y) => { - while (y > 0) [x, y] = [y, x % y] - return x -} -const lcm = (x, y) => (x * y) / gcd(x, y) -const nthMagicalNumber = function(N, A, B) { - let l = lcm(A, B) - const seq = {} - for (let i = 1; i < Math.floor(l / A) + 1; i++) seq[i * A] = 1 - for (let i = 1; i < Math.floor(l / B) + 1; i++) seq[i * B] = 1 - const arr = Object.keys(seq) - .sort((a, b) => a - b) - .map(el => +el) - let idx = N % arr.length === 0 ? arr.length - 1 : (N % arr.length) - 1 - let res = Math.floor((N - 1) / arr.length) * arr[arr.length - 1] + arr[idx] - return res % (1e9 + 7) -} - -// another - -const nthMagicalNumber = function(N, A, B) { - const gcd = (x, y) => { - if (x == 0) return y - return gcd(y % x, x) - } - const MOD = 1e9 + 7 - const L = (A / gcd(A, B)) * B - let lo = 0 - let hi = 1e15 - while (lo < hi) { - let mi = lo + Math.trunc((hi - lo) / 2) - if (Math.trunc(mi / A) + Math.trunc(mi / B) - Math.trunc(mi / L) < N) lo = mi + 1 - else hi = mi - } - return lo % MOD -} diff --git a/878.nth-magical-number.js b/878.nth-magical-number.js new file mode 100644 index 00000000..d82d18de --- /dev/null +++ b/878.nth-magical-number.js @@ -0,0 +1,24 @@ +/** + * @param {number} N + * @param {number} A + * @param {number} B + * @return {number} + */ +const gcd = (x, y) => { + while (y > 0) [x, y] = [y, x % y] + return x +} +const lcm = (x, y) => (x * y) / gcd(x, y) +const nthMagicalNumber = function(N, A, B) { + let l = lcm(A, B) + const seq = {} + for (let i = 1; i < Math.floor(l / A) + 1; i++) seq[i * A] = 1 + for (let i = 1; i < Math.floor(l / B) + 1; i++) seq[i * B] = 1 + const arr = Object.keys(seq) + .sort((a, b) => a - b) + .map(el => +el) + let idx = N % arr.length === 0 ? arr.length - 1 : (N % arr.length) - 1 + let res = Math.floor((N - 1) / arr.length) * arr[arr.length - 1] + arr[idx] + return res % (1e9 + 7) +} + diff --git a/879-profitable-schemes.js b/879.profitable-schemes.js similarity index 100% rename from 879-profitable-schemes.js rename to 879.profitable-schemes.js diff --git a/88-merge-sorted-array.js b/88.merge-sorted-array.js similarity index 100% rename from 88-merge-sorted-array.js rename to 88.merge-sorted-array.js diff --git a/880-decoded-string-at-index.js b/880.decoded-string-at-index.js similarity index 100% rename from 880-decoded-string-at-index.js rename to 880.decoded-string-at-index.js diff --git a/881-boats-to-save-people.js b/881.boats-to-save-people.js similarity index 100% rename from 881-boats-to-save-people.js rename to 881.boats-to-save-people.js diff --git a/882-reachable-nodes-in-subdivided-graph.js b/882-reachable-nodes-in-subdivided-graph.js deleted file mode 100644 index f83ea6f7..00000000 --- a/882-reachable-nodes-in-subdivided-graph.js +++ /dev/null @@ -1,310 +0,0 @@ -/** - * @param {number[][]} edges - * @param {number} maxMoves - * @param {number} n - * @return {number} - */ -const reachableNodes = function(edges, maxMoves, n) { - let res = 0, - heap = new Heap(), - state = new Array(n).fill(0), - graph = Array.from(new Array(n), () => []), - distance = new Array(n).fill(Number.MAX_SAFE_INTEGER); - for (let [u, v, d] of edges) { - graph[u].push([v, d]); - graph[v].push([u, d]); - } - distance[0] = 0; - heap.insert([0, distance[0]]); - while (heap.length != 0) { - let t = heap.remove(); - if (state[t[0]] === 1) continue; - if (distance[t[0]] <= maxMoves) res++; - state[t[0]] = 1; - for (let i of graph[t[0]]) { - if (distance[i[0]] > distance[t[0]] + i[1] + 1) { - distance[i[0]] = distance[t[0]] + i[1] + 1; - heap.insert([i[0], distance[i[0]]]); - } - } - } - for (let [u, v, d] of edges) { - let a = maxMoves - distance[u] >= 0 ? maxMoves - distance[u] : 0, - b = maxMoves - distance[v] >= 0 ? maxMoves - distance[v] : 0; - res += Math.min(d, a + b); - } - return res; -}; - -class Heap { - constructor() { - this.heap = []; - } - - get length() { - return this.heap.length; - } - - compare(i, j) { - if (!this.heap[j]) return false; - return this.heap[i][1] > this.heap[j][1]; - } - - swap(i, j) { - const temp = this.heap[i]; - this.heap[i] = this.heap[j]; - this.heap[j] = temp; - } - - insert(num) { - this.heap.push(num); - let idx = this.length - 1; - let parent = (idx - 1) >> 1; - while (idx !== 0 && this.compare(parent, idx)) { - this.swap(parent, idx); - idx = parent; - parent = (idx - 1) >> 1; - } - } - - remove() { - if (this.length === 1) return this.heap.pop(); - let res = this.heap[0], - idx = 0, - left = 1 | (idx << 1), - right = (1 + idx) << 1; - this.heap[0] = this.heap.pop(); - while (this.compare(idx, left) || this.compare(idx, right)) { - if (this.compare(left, right)) { - this.swap(idx, right); - idx = right; - } else { - this.swap(idx, left); - idx = left; - } - left = 1 | (idx << 1); - right = (1 + idx) << 1; - } - return res; - } -} - -// another - -/** - * @param {number[][]} edges - * @param {number} M - * @param {number} N - * @return {number} - */ -const reachableNodes = function (edges, M, N) { - const graph = Array.from({ length: N }, () => Array(N).fill(-1)) - for (let edge of edges) { - graph[edge[0]][edge[1]] = edge[2] - graph[edge[1]][edge[0]] = edge[2] - } - let result = 0 - const pq = new PriorityQueue((a, b) => a[1] > b[1]) - const visited = new Array(N).fill(false) - pq.push([0, M]) - while (!pq.isEmpty()) { - const cur = pq.pop() - const start = cur[0] - const move = cur[1] - if (visited[start]) { - continue - } - visited[start] = true - result++ - for (let i = 0; i < N; i++) { - if (graph[start][i] > -1) { - if (move > graph[start][i] && !visited[i]) { - pq.push([i, move - graph[start][i] - 1]) - } - graph[i][start] -= Math.min(move, graph[start][i]) - result += Math.min(move, graph[start][i]) - } - } - } - return result -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -// time complexity: -// Dijkstra + Heap is O(E log E) -// worst case: O(N ^ 2 * log (N ^ 2)) -/** - * @param {number[][]} edges - * @param {number} M - * @param {number} N - * @return {number} - */ -const reachableNodes = function(edges, M, N) { - const graph = {} - for(const [u,v,c] of edges) { - if(graph[u] == null) graph[u] = {} - if(graph[v] == null) graph[v] = {} - graph[u][v] = c - graph[v][u] = c - } - const pq = new PriorityQueue((a, b) => a[0] > b[0]) - pq.push([M, 0]) - const visited = {} - while(!pq.isEmpty()) { - const [moves, i] = pq.pop() - if(visited[i] == null) { - visited[i] = moves - for(const k of Object.keys(graph[i] || {})) { - const remain = moves - graph[i][k] - 1 - if(visited[k] == null && remain >= 0) { - pq.push([remain, k]) - } - } - } - } - let res = 0 - res += Object.keys(visited).length - for(const [u, v, c] of edges) { - const a = visited[u] || 0, b = visited[v] || 0 - res += Math.min(a + b, c) - } - - return res -}; - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} diff --git a/882.reachable-nodes-in-subdivided-graph.js b/882.reachable-nodes-in-subdivided-graph.js new file mode 100644 index 00000000..e28e9115 --- /dev/null +++ b/882.reachable-nodes-in-subdivided-graph.js @@ -0,0 +1,91 @@ +/** + * @param {number[][]} edges + * @param {number} maxMoves + * @param {number} n + * @return {number} + */ +const reachableNodes = function(edges, maxMoves, n) { + let res = 0, + heap = new Heap(), + state = new Array(n).fill(0), + graph = Array.from(new Array(n), () => []), + distance = new Array(n).fill(Number.MAX_SAFE_INTEGER); + for (let [u, v, d] of edges) { + graph[u].push([v, d]); + graph[v].push([u, d]); + } + distance[0] = 0; + heap.insert([0, distance[0]]); + while (heap.length != 0) { + let t = heap.remove(); + if (state[t[0]] === 1) continue; + if (distance[t[0]] <= maxMoves) res++; + state[t[0]] = 1; + for (let i of graph[t[0]]) { + if (distance[i[0]] > distance[t[0]] + i[1] + 1) { + distance[i[0]] = distance[t[0]] + i[1] + 1; + heap.insert([i[0], distance[i[0]]]); + } + } + } + for (let [u, v, d] of edges) { + let a = maxMoves - distance[u] >= 0 ? maxMoves - distance[u] : 0, + b = maxMoves - distance[v] >= 0 ? maxMoves - distance[v] : 0; + res += Math.min(d, a + b); + } + return res; +}; + +class Heap { + constructor() { + this.heap = []; + } + + get length() { + return this.heap.length; + } + + compare(i, j) { + if (!this.heap[j]) return false; + return this.heap[i][1] > this.heap[j][1]; + } + + swap(i, j) { + const temp = this.heap[i]; + this.heap[i] = this.heap[j]; + this.heap[j] = temp; + } + + insert(num) { + this.heap.push(num); + let idx = this.length - 1; + let parent = (idx - 1) >> 1; + while (idx !== 0 && this.compare(parent, idx)) { + this.swap(parent, idx); + idx = parent; + parent = (idx - 1) >> 1; + } + } + + remove() { + if (this.length === 1) return this.heap.pop(); + let res = this.heap[0], + idx = 0, + left = 1 | (idx << 1), + right = (1 + idx) << 1; + this.heap[0] = this.heap.pop(); + while (this.compare(idx, left) || this.compare(idx, right)) { + if (this.compare(left, right)) { + this.swap(idx, right); + idx = right; + } else { + this.swap(idx, left); + idx = left; + } + left = 1 | (idx << 1); + right = (1 + idx) << 1; + } + return res; + } +} + diff --git a/883-projection-area-of-3d-shapes.js b/883.projection-area-of-3d-shapes.js similarity index 100% rename from 883-projection-area-of-3d-shapes.js rename to 883.projection-area-of-3d-shapes.js diff --git a/884-uncommon-words-from-two-sentences.js b/884.uncommon-words-from-two-sentences.js similarity index 100% rename from 884-uncommon-words-from-two-sentences.js rename to 884.uncommon-words-from-two-sentences.js diff --git a/886-possible-bipartition.js b/886-possible-bipartition.js deleted file mode 100644 index 0d1748fa..00000000 --- a/886-possible-bipartition.js +++ /dev/null @@ -1,71 +0,0 @@ -/** - * @param {number} N - * @param {number[][]} dislikes - * @return {boolean} - */ -const possibleBipartition = function (N, dislikes) { - const graph = [] - for (let i = 0; i <= N; i++) { - graph[i] = [] - } - for (let el of dislikes) { - graph[el[0]].push(el[1]) - graph[el[1]].push(el[0]) - } - const color = new Array(N + 1).fill(0) - for (let i = 1; i <= N; i++) { - if (color[i] == 0) { - color[i] = 1 - const q = [] - q.push(i) - while (q.length > 0) { - let cur = q.shift() - for (let j of graph[cur]) { - if (color[j] == 0) { - color[j] = color[cur] == 1 ? 2 : 1 - q.push(j) - } else { - if (color[j] == color[cur]) return false - } - } - } - } - } - return true -} - -// another - -/** - * @param {number} N - * @param {number[][]} dislikes - * @return {boolean} - */ -const possibleBipartition = function (N, dislikes) { - const graph = new Array(N + 1) - for (const [a, b] of dislikes) { - if (!graph[a]) graph[a] = [] - graph[a].push(b) - if (!graph[b]) graph[b] = [] - graph[b].push(a) - } - - const colors = new Array(N + 1) - const dfs = (node, color = 0) => { - colors[node] = color - const nextColor = color ^ 1 - const children = graph[node] || [] - for (const child of children) { - if (colors[child] !== undefined) { - if (colors[child] !== nextColor) return false - } else { - if (!dfs(child, nextColor)) return false - } - } - return true - } - for (let i = 1; i <= N; i++) { - if (colors[i] === undefined && !dfs(i)) return false - } - return true -} diff --git a/886.possible-bipartition.js b/886.possible-bipartition.js new file mode 100644 index 00000000..126b144c --- /dev/null +++ b/886.possible-bipartition.js @@ -0,0 +1,36 @@ +/** + * @param {number} N + * @param {number[][]} dislikes + * @return {boolean} + */ +const possibleBipartition = function (N, dislikes) { + const graph = [] + for (let i = 0; i <= N; i++) { + graph[i] = [] + } + for (let el of dislikes) { + graph[el[0]].push(el[1]) + graph[el[1]].push(el[0]) + } + const color = new Array(N + 1).fill(0) + for (let i = 1; i <= N; i++) { + if (color[i] == 0) { + color[i] = 1 + const q = [] + q.push(i) + while (q.length > 0) { + let cur = q.shift() + for (let j of graph[cur]) { + if (color[j] == 0) { + color[j] = color[cur] == 1 ? 2 : 1 + q.push(j) + } else { + if (color[j] == color[cur]) return false + } + } + } + } + } + return true +} + diff --git a/887-super-egg-drop.js b/887-super-egg-drop.js deleted file mode 100644 index cf5a5eb5..00000000 --- a/887-super-egg-drop.js +++ /dev/null @@ -1,66 +0,0 @@ -/** - * @param {number} K - * @param {number} N - * @return {number} - */ - -const superEggDrop = function(K, N) { - let lo = 1, - hi = N, - mi - while (lo < hi) { - mi = ((lo + hi) / 2) >> 0 - if (f(mi, K, N) < N) lo = mi + 1 - else hi = mi - } - return lo -} - -function f(x, K, N) { - let ans = 0, - r = 1, - i = 1 - for (let i = 1; i <= K; ++i) { - r = ((r * (x - i + 1)) / i) >> 0 - ans += r - if (ans >= N) break - } - return ans -} - -// another - -const superEggDrop = function(K, N) { - const dp = Array.from({ length: K + 1 }, () => new Array(N + 1).fill(0)) - return helper(K, N, dp) -} -function helper(K, N, memo) { - if (N <= 1) { - return N - } - if (K === 1) { - return N - } - if (memo[K][N] > 0) { - return memo[K][N] - } - - let low = 1, - high = N, - result = N - while (low < high) { - let mid = Math.floor(low + (high - low) / 2) - let left = helper(K - 1, mid - 1, memo) - let right = helper(K, N - mid, memo) - result = Math.min(result, Math.max(left, right) + 1) - if (left === right) { - break - } else if (left < right) { - low = mid + 1 - } else { - high = mid - } - } - memo[K][N] = result - return result -} diff --git a/887.super-egg-drop.js b/887.super-egg-drop.js new file mode 100644 index 00000000..aebeb367 --- /dev/null +++ b/887.super-egg-drop.js @@ -0,0 +1,30 @@ +/** + * @param {number} K + * @param {number} N + * @return {number} + */ + +const superEggDrop = function(K, N) { + let lo = 1, + hi = N, + mi + while (lo < hi) { + mi = ((lo + hi) / 2) >> 0 + if (f(mi, K, N) < N) lo = mi + 1 + else hi = mi + } + return lo +} + +function f(x, K, N) { + let ans = 0, + r = 1, + i = 1 + for (let i = 1; i <= K; ++i) { + r = ((r * (x - i + 1)) / i) >> 0 + ans += r + if (ans >= N) break + } + return ans +} + diff --git a/888-fair-candy-swap.js b/888.fair-candy-swap.js similarity index 100% rename from 888-fair-candy-swap.js rename to 888.fair-candy-swap.js diff --git a/889-construct-binary-tree-from-preorder-and-postorder-traversal.js b/889.construct-binary-tree-from-preorder-and-postorder-traversal.js similarity index 100% rename from 889-construct-binary-tree-from-preorder-and-postorder-traversal.js rename to 889.construct-binary-tree-from-preorder-and-postorder-traversal.js diff --git a/89-gray-code.js b/89-gray-code.js deleted file mode 100644 index 862a618a..00000000 --- a/89-gray-code.js +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @param {number} n - * @return {number[]} - */ -const grayCode = function(n) { - if (n === 0) { - return [0] - } - const temp = grayCode(n - 1) - const nums = [].concat(temp) - const addNum = 1 << (n - 1) - for (let i = temp.length - 1; i >= 0; i--) { - nums.push(addNum + temp[i]) - } - return nums -} - -// another - -/** - * @param {number} n - * @return {number[]} - */ -const grayCode = function(n) { - const arr = [] - arr.push(0) - for (let i = 0; i < n; i++) { - let inc = 1 << i - for (let j = arr.length - 1; j >= 0; j--) { - arr.push(arr[j] + inc) - } - } - return arr -} - -// another - -/** - * @param {number} n - * @return {number[]} - */ -const grayCode = function(n) { - return n - ? (x => [...x, ...x.map((v, i) => x[x.length - 1 - i] + x.length)])( - grayCode(n - 1) - ) - : [0] -} diff --git a/89.gray-code.js b/89.gray-code.js new file mode 100644 index 00000000..28e15b40 --- /dev/null +++ b/89.gray-code.js @@ -0,0 +1,17 @@ +/** + * @param {number} n + * @return {number[]} + */ +const grayCode = function(n) { + if (n === 0) { + return [0] + } + const temp = grayCode(n - 1) + const nums = [].concat(temp) + const addNum = 1 << (n - 1) + for (let i = temp.length - 1; i >= 0; i--) { + nums.push(addNum + temp[i]) + } + return nums +} + diff --git a/890-find-and-replace-pattern.js b/890.find-and-replace-pattern.js similarity index 100% rename from 890-find-and-replace-pattern.js rename to 890.find-and-replace-pattern.js diff --git a/891-sum-of-subsequence-widths.js b/891.sum-of-subsequence-widths.js similarity index 100% rename from 891-sum-of-subsequence-widths.js rename to 891.sum-of-subsequence-widths.js diff --git a/892-surface-area-of-3d-shapes.js b/892.surface-area-of-3d-shapes.js similarity index 100% rename from 892-surface-area-of-3d-shapes.js rename to 892.surface-area-of-3d-shapes.js diff --git a/893-groups-of-special-equivalent-strings.js b/893-groups-of-special-equivalent-strings.js deleted file mode 100644 index 79e402f6..00000000 --- a/893-groups-of-special-equivalent-strings.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @param {string[]} A - * @return {number} - */ -const numSpecialEquivGroups = function(A) { - return new Set( - A.map(word => - [...word] - .reduce((counter, c, i) => { - counter[c.charCodeAt(0) - "a".charCodeAt(0) + 26 * (i % 2)]++; - return counter; - }, new Array(52).fill(0)) - .join("-") - ) - ).size; -}; - -// another - -/** - * @param {string[]} A - * @return {number} - */ -const numSpecialEquivGroups = function(A) { - const result = new Set(); - for (let i of A) { - let arr = i.split(""); - let res = [[], []]; - for (let j = 0; j < arr.length; j++) { - res[j & 1].push(arr[j]); - } - result.add(res[0].sort().join("") + res[1].sort().join("")); - } - return result.size; -}; diff --git a/893.groups-of-special-equivalent-strings.js b/893.groups-of-special-equivalent-strings.js new file mode 100644 index 00000000..e68ecd39 --- /dev/null +++ b/893.groups-of-special-equivalent-strings.js @@ -0,0 +1,17 @@ +/** + * @param {string[]} A + * @return {number} + */ +const numSpecialEquivGroups = function(A) { + return new Set( + A.map(word => + [...word] + .reduce((counter, c, i) => { + counter[c.charCodeAt(0) - "a".charCodeAt(0) + 26 * (i % 2)]++; + return counter; + }, new Array(52).fill(0)) + .join("-") + ) + ).size; +}; + diff --git a/894-all-possible-full-binary-trees.js b/894.all-possible-full-binary-trees.js similarity index 100% rename from 894-all-possible-full-binary-trees.js rename to 894.all-possible-full-binary-trees.js diff --git a/895-maximum-frequency-stack.js b/895.maximum-frequency-stack.js similarity index 100% rename from 895-maximum-frequency-stack.js rename to 895.maximum-frequency-stack.js diff --git a/896-monotonic-array.js b/896-monotonic-array.js deleted file mode 100644 index 03a547f6..00000000 --- a/896-monotonic-array.js +++ /dev/null @@ -1,37 +0,0 @@ -/** - * @param {number[]} nums - * @return {boolean} - */ -const isMonotonic = function(nums) { - return inc(nums) || dec(nums) -}; - -function inc(nums) { - if(nums == null || nums.length <= 1) return true - for(let i = 1, n = nums.length; i < n; i++) { - if(nums[i] < nums[i - 1]) return false - } - return true -} -function dec(nums) { - if(nums == null || nums.length <= 1) return true - for(let i = 1, n = nums.length; i < n; i++) { - if(nums[i] > nums[i - 1]) return false - } - return true -} - -// another - -/** - * @param {number[]} nums - * @return {boolean} - */ -const isMonotonic = function(nums) { - let inc = true, dec = true - for(let i = 1, n = nums.length; i < n; i++) { - inc &= nums[i] >= nums[i - 1] - dec &= nums[i] <= nums[i - 1] - } - return inc || dec -}; diff --git a/896.monotonic-array.js b/896.monotonic-array.js new file mode 100644 index 00000000..ef3d3cf4 --- /dev/null +++ b/896.monotonic-array.js @@ -0,0 +1,23 @@ +/** + * @param {number[]} nums + * @return {boolean} + */ +const isMonotonic = function(nums) { + return inc(nums) || dec(nums) +}; + +function inc(nums) { + if(nums == null || nums.length <= 1) return true + for(let i = 1, n = nums.length; i < n; i++) { + if(nums[i] < nums[i - 1]) return false + } + return true +} +function dec(nums) { + if(nums == null || nums.length <= 1) return true + for(let i = 1, n = nums.length; i < n; i++) { + if(nums[i] > nums[i - 1]) return false + } + return true +} + diff --git a/897-increasing-order-search-tree.js b/897.increasing-order-search-tree.js similarity index 100% rename from 897-increasing-order-search-tree.js rename to 897.increasing-order-search-tree.js diff --git a/898-bitwise-ors-of-subarrays.js b/898.bitwise-ors-of-subarrays.js similarity index 100% rename from 898-bitwise-ors-of-subarrays.js rename to 898.bitwise-ors-of-subarrays.js diff --git a/899-orderly-queue.js b/899.orderly-queue.js similarity index 100% rename from 899-orderly-queue.js rename to 899.orderly-queue.js diff --git a/9-palindrome-number.js b/9-palindrome-number.js deleted file mode 100755 index c0ad42be..00000000 --- a/9-palindrome-number.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @param {number} x - * @return {boolean} - */ -const isPalindrome = function(x) { - if (x < 0) return false; - const rev = reverseNum(x); - return x === rev; -}; - -function reverseNum(num) { - let n = num; - let rev = 0; - let dig; - while (num > 0) { - dig = num % 10; - rev = rev * 10 + dig; - num = Math.floor(num / 10); - } - return rev; -} diff --git a/9.palindrome-number.js b/9.palindrome-number.js new file mode 100644 index 00000000..c0d5d1c9 --- /dev/null +++ b/9.palindrome-number.js @@ -0,0 +1,21 @@ +/** + * @param {number} x + * @return {boolean} + */ +const isPalindrome = function(x) { + if (x < 0) return false; + const rev = reverseNum(x); + return x === rev; +}; + +function reverseNum(num) { + let n = num; + let rev = 0; + let dig; + while (num > 0) { + dig = num % 10; + rev = rev * 10 + dig; + num = Math.floor(num / 10); + } + return rev; +} diff --git a/90-subsets-II.js b/90-subsets-II.js deleted file mode 100755 index ac3cd152..00000000 --- a/90-subsets-II.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @param {number[]} nums - * @return {number[][]} - */ -const subsetsWithDup = function(nums) { - nums.sort((a, b) => a - b); - const res = []; - bt(res, nums, [], 0); - return res; -}; - -function bt(res, nums, arr, start) { - res.push(arr.slice(0)); - for (let i = start; i < nums.length; i++) { - if (i === start || nums[i] !== nums[i - 1]) { - arr.push(nums[i]); - bt(res, nums, arr, i + 1); - arr.pop(); - } - } -} diff --git a/90.subsets-II.js b/90.subsets-II.js new file mode 100644 index 00000000..ddc33cca --- /dev/null +++ b/90.subsets-II.js @@ -0,0 +1,21 @@ +/** + * @param {number[]} nums + * @return {number[][]} + */ +const subsetsWithDup = function(nums) { + nums.sort((a, b) => a - b); + const res = []; + bt(res, nums, [], 0); + return res; +}; + +function bt(res, nums, arr, start) { + res.push(arr.slice(0)); + for (let i = start; i < nums.length; i++) { + if (i === start || nums[i] !== nums[i - 1]) { + arr.push(nums[i]); + bt(res, nums, arr, i + 1); + arr.pop(); + } + } +} diff --git a/901-online-stock-span.js b/901.online-stock-span.js similarity index 100% rename from 901-online-stock-span.js rename to 901.online-stock-span.js diff --git a/902-numbers-at-most-n-given-digit-set.js b/902-numbers-at-most-n-given-digit-set.js deleted file mode 100644 index 2e5da545..00000000 --- a/902-numbers-at-most-n-given-digit-set.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @param {string[]} digits - * @param {number} n - * @return {number} - */ -const atMostNGivenDigitSet = function(digits, n) { - let res = 0 - const str = `${n}`, len = str.length - const { pow } = Math, base = digits.length - for(let i = 1; i < len; i++) { - res += pow(base, i) - } - - dfs(0) - - return res - - function dfs(pos) { - if(pos === len) { - res++ - return - } - for(const ch of digits) { - if(str[pos] > ch) { - res += pow(base, len - 1 - pos) - } else if(str[pos] === ch) { - dfs(pos + 1) - } else break - } - } -}; - -// another - - -/** - * @param {string[]} digits - * @param {number} n - * @return {number} - */ -const atMostNGivenDigitSet = function(digits, n) { - const str = '' + n, { pow } = Math - const len = str.length, dsize = digits.length - let res = 0 - - for(let i = 1; i < len; i++) { - res += pow(dsize, i) - } - - for(let i = 0; i < len; i++) { - let sameNum = false - for(const d of digits) { - if(+d < +str[i]) { - res += pow(dsize, len - i - 1) - } else if(+d === +str[i]) sameNum = true - } - if(sameNum === false) return res - } - - return res + 1 -}; diff --git a/902.numbers-at-most-n-given-digit-set.js b/902.numbers-at-most-n-given-digit-set.js new file mode 100644 index 00000000..74b1d68b --- /dev/null +++ b/902.numbers-at-most-n-given-digit-set.js @@ -0,0 +1,32 @@ +/** + * @param {string[]} digits + * @param {number} n + * @return {number} + */ +const atMostNGivenDigitSet = function(digits, n) { + let res = 0 + const str = `${n}`, len = str.length + const { pow } = Math, base = digits.length + for(let i = 1; i < len; i++) { + res += pow(base, i) + } + + dfs(0) + + return res + + function dfs(pos) { + if(pos === len) { + res++ + return + } + for(const ch of digits) { + if(str[pos] > ch) { + res += pow(base, len - 1 - pos) + } else if(str[pos] === ch) { + dfs(pos + 1) + } else break + } + } +}; + diff --git a/903-valid-permutations-for-di-sequence.js b/903-valid-permutations-for-di-sequence.js deleted file mode 100644 index 13844712..00000000 --- a/903-valid-permutations-for-di-sequence.js +++ /dev/null @@ -1,90 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const numPermsDISequence = function(s) { - const mod = 1e9 + 7 - const n = s.length - const dp = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0)) - s = '#' + s - dp[0][0] = 1 - for(let i = 1; i <= n; i++) { - const ch = s[i] - for(let j = 0; j <= i; j++) { - if(ch === 'I') { - for(let k = 0; k < j; k++) { - dp[i][j] += dp[i - 1][k] - dp[i][j] %= mod - } - } else { - for(let k = j; k < i; k++) { - dp[i][j] += dp[i - 1][k] - dp[i][j] %= mod - } - } - } - } - - - let res = 0 - - for(let i = 0; i <= n; i++) { - res = (res + dp[n][i]) % mod - } - - return res -}; - - -// another - - -/** - * @param {string} s - * @return {number} - */ -const numPermsDISequence = function(s) { - const n = s.length, mod = 1e9 + 7 - const dp = Array.from({ length: n + 1}, () => Array(n + 1).fill(0)) - dp[0][0] = 1 - for(let i = 1; i <= n; i++) { - for(let j = 0; j <= i; j++) { - if(s[i - 1] === 'D') { - for(let k = j; k <= i - 1; k++) { - dp[i][j] = (dp[i][j] + dp[i - 1][k]) % mod - } - } else { - for(let k = 0; k < j; k++) { - dp[i][j] = (dp[i][j] + dp[i - 1][k]) % mod - } - } - } - } - let res = 0 - for(let i = 0; i <= n; i++) { - res = (res + dp[n][i]) % mod - } - - return res -}; - -// another - -/** - * @param {string} S - * @return {number} - */ -const numPermsDISequence = function(S) { - let n = S.length, - mod = 10 ** 9 + 7 - const dp = Array.from({ length: n + 1 }, () => new Array(n + 1).fill(0)) - for (let j = 0; j <= n; j++) dp[0][j] = 1 - for (let i = 0; i < n; i++) - if (S.charAt(i) === 'I') - for (let j = 0, cur = 0; j < n - i; j++) - dp[i + 1][j] = cur = (cur + dp[i][j]) % mod - else - for (let j = n - i - 1, cur = 0; j >= 0; j--) - dp[i + 1][j] = cur = (cur + dp[i][j + 1]) % mod - return dp[n][0] -} diff --git a/903.valid-permutations-for-di-sequence.js b/903.valid-permutations-for-di-sequence.js new file mode 100644 index 00000000..05cf40bf --- /dev/null +++ b/903.valid-permutations-for-di-sequence.js @@ -0,0 +1,38 @@ +/** + * @param {string} s + * @return {number} + */ +const numPermsDISequence = function(s) { + const mod = 1e9 + 7 + const n = s.length + const dp = Array.from({ length: n + 1 }, () => Array(n + 1).fill(0)) + s = '#' + s + dp[0][0] = 1 + for(let i = 1; i <= n; i++) { + const ch = s[i] + for(let j = 0; j <= i; j++) { + if(ch === 'I') { + for(let k = 0; k < j; k++) { + dp[i][j] += dp[i - 1][k] + dp[i][j] %= mod + } + } else { + for(let k = j; k < i; k++) { + dp[i][j] += dp[i - 1][k] + dp[i][j] %= mod + } + } + } + } + + + let res = 0 + + for(let i = 0; i <= n; i++) { + res = (res + dp[n][i]) % mod + } + + return res +}; + + diff --git a/904-fruit-into-baskets.js b/904.fruit-into-baskets.js similarity index 100% rename from 904-fruit-into-baskets.js rename to 904.fruit-into-baskets.js diff --git a/905-sort-array-by-parity.js b/905.sort-array-by-parity.js similarity index 100% rename from 905-sort-array-by-parity.js rename to 905.sort-array-by-parity.js diff --git a/906-super-palindromes.js b/906-super-palindromes.js deleted file mode 100644 index 9b97b889..00000000 --- a/906-super-palindromes.js +++ /dev/null @@ -1,200 +0,0 @@ -/** - * @param {string} L - * @param {string} R - * @return {number} - */ -const superpalindromesInRange = function (L, R) { - // My idea was to take the root of L and R and then generate all palindromes between those numbers, - // and then put those palindromes to power 2 and check if those are palindrome as well. - - // The generation of palindromes is done like this: - // Lets say i want all palindromes of length 4, then i take all numbers of length 2. - // I reverse the length 2 numbers and concatenate them with themselves. - // So "19" becomes "19" + "91". For odd length I do the same, - // but put a for loop around them that puts nrs 0 - 9 inside them. - // So "19" + "0" + "91", then "19" + "1" + "91", etc. - - // Next I loop through the generated palindromes and just check whether they are - // inside sqrt(L) and sqrt(R). (sqrt(L) < palin < sqrt(R)) - // For every palin within sqrt(L) and sqrt(R), i put the palin to power 2 - // (with BigInt!) and then check if that is a palindrome. If so, then count++; - - const sqL = Math.sqrt(L) - const sqR = Math.sqrt(R) - const sqR_Length = parseInt(sqR).toString(10).length - // counting the valid super-palindromes - let palins = 0 - // L is a superpalindrome - if ( - isPalindrome(L) && - sqL === parseInt(sqL) && - isPalindrome(sqL.toString(10)) - ) - palins++ - // R is a superpalindrome - if ( - isPalindrome(R) && - sqR === parseInt(sqR) && - isPalindrome(sqR.toString(10)) - ) - palins++ - - let end - if (sqR === parseInt(sqR)) { - // or else the loop will possibly add R as well - end = parseInt(sqR) - 1 - } else { - end = parseInt(Math.floor(sqR)) - } - - let begin - if (sqL === parseInt(sqL)) { - // or else the loop will possibly add R as well - begin = parseInt(sqL) + 1 - } else { - begin = parseInt(Math.ceil(sqL)) - } - - // account for superpalins with for single digit 'sub-palins' - if (begin <= 1 && end >= 1) palins++ // 1 - if (begin <= 2 && end >= 2) palins++ // 4 - if (begin <= 3 && end >= 3) palins++ // 9 - const length = sqR_Length - const even = length % 2 === 0 - const half = Math.floor(length / 2) - const pow10Half = Math.pow(10, half) // 10 or 100 or 1000, etc - const pow10HalfMinOne = Math.pow(10, half - 1) - let pal = '' // init - let palinStr = '' // init - let palin = -1 // init - for (let i = 1, leni = pow10Half; i < leni; i++) { - pal = i.toString(10) - pal.padStart(half - pal.length, '0') - palReverse = reverseStr(pal) - // generate even length palindrome - palinStr = pal + palReverse - palin = parseInt(palinStr) - if (palin >= begin && palin <= end) { - if (isPalindromeInt(BigInt(palin) * BigInt(palin))) { - palins++ - } - } - // If I generate all palindromes up until some even length, - // lets say 4, then last step is to do length 2 + length 2 (19 + 91), - // and not the 19 + 0 + 91 step that generates odd length palindromes. - if (even && i >= pow10HalfMinOne) { - continue - } - for (let j = 0, lenj = 10; j < lenj; j++) { - // generate odd length palindrome - palinStr = pal + j + palReverse - palin = parseInt(palinStr) - if (palin >= begin && palin <= end) { - if (isPalindromeInt(BigInt(palin) * BigInt(palin))) { - palins++ - } - } - } - } - return palins -} - -const reverseStr = function (str) { - return str.split('').reverse().join('') -} - -const isPalindromeInt = function (nr) { - nr = nr.toString(10) - return nr === nr.split('').reverse().join('') -} -const isPalindrome = function (nr) { - return nr === nr.split('').reverse().join('') -} - -// another - -/** - * @param {string} left - * @param {string} right - * @return {number} - */ - const superpalindromesInRange = function(left, right) { - const palindromes = [] - let res = 0 - for(let i = 1; i < 10; i++) { - palindromes.push(`${i}`) - } - for(let i = 1; i < 1e4; i++) { - let l = `${i}`, r = l.split('').reverse().join('') - palindromes.push(`${l}${r}`) - for(let j = 0; j < 10; j++) { - palindromes.push(`${l}${j}${r}`) - } - } - - for(let p of palindromes) { - const square = BigInt(p) * BigInt(p) - if(!isPalindrome(`${square}`)) continue - if(BigInt(left) <= square && square <= BigInt(right)) res++ - } - - return res - - function isPalindrome(str) { - let i = 0; - let j = str.length - 1; - while (i < j) { - if (str.charAt(i) !== str.charAt(j)) { - return false; - } - i++; - j--; - } - return true; - } -}; - -// another - -/** - * @param {string} left - * @param {string} right - * @return {number} - */ -const superpalindromesInRange = function (left, right) { - let ans = 9 >= left && 9 <= right ? 1 : 0 - - const isPal = (str) => { - for (let i = 0, j = str.length - 1; i < j; i++, j--) - if (str.charAt(i) !== str.charAt(j)) return false - return true - } - - for (let dig = 1; dig < 10; dig++) { - let isOdd = dig % 2 && dig !== 1, - innerLen = (dig >> 1) - 1, - innerLim = Math.max(1, 2 ** innerLen), - midPos = dig >> 1, - midLim = isOdd ? 3 : 1 - for (let edge = 1; edge < 3; edge++) { - let pal = new Uint8Array(dig) - ;(pal[0] = edge), (pal[dig - 1] = edge) - if (edge === 2) (innerLim = 1), (midLim = Math.min(midLim, 2)) - for (let inner = 0; inner < innerLim; inner++) { - if (inner > 0) { - let innerStr = inner.toString(2).padStart(innerLen, '0') - for (let i = 0; i < innerLen; i++) - (pal[1 + i] = innerStr[i]), (pal[dig - 2 - i] = innerStr[i]) - } - for (let mid = 0; mid < midLim; mid++) { - if (isOdd) pal[midPos] = mid - let palin = ~~pal.join(''), - square = BigInt(palin) * BigInt(palin) - if (square > right) return ans - if (square >= left && isPal(square.toString())) ans++ - } - } - } - } - return ans -} diff --git a/906.super-palindromes.js b/906.super-palindromes.js new file mode 100644 index 00000000..a3e9844c --- /dev/null +++ b/906.super-palindromes.js @@ -0,0 +1,113 @@ +/** + * @param {string} L + * @param {string} R + * @return {number} + */ +const superpalindromesInRange = function (L, R) { + // My idea was to take the root of L and R and then generate all palindromes between those numbers, + // and then put those palindromes to power 2 and check if those are palindrome as well. + + // The generation of palindromes is done like this: + // Lets say i want all palindromes of length 4, then i take all numbers of length 2. + // I reverse the length 2 numbers and concatenate them with themselves. + // So "19" becomes "19" + "91". For odd length I do the same, + // but put a for loop around them that puts nrs 0 - 9 inside them. + // So "19" + "0" + "91", then "19" + "1" + "91", etc. + + // Next I loop through the generated palindromes and just check whether they are + // inside sqrt(L) and sqrt(R). (sqrt(L) < palin < sqrt(R)) + // For every palin within sqrt(L) and sqrt(R), i put the palin to power 2 + // (with BigInt!) and then check if that is a palindrome. If so, then count++; + + const sqL = Math.sqrt(L) + const sqR = Math.sqrt(R) + const sqR_Length = parseInt(sqR).toString(10).length + // counting the valid super-palindromes + let palins = 0 + // L is a superpalindrome + if ( + isPalindrome(L) && + sqL === parseInt(sqL) && + isPalindrome(sqL.toString(10)) + ) + palins++ + // R is a superpalindrome + if ( + isPalindrome(R) && + sqR === parseInt(sqR) && + isPalindrome(sqR.toString(10)) + ) + palins++ + + let end + if (sqR === parseInt(sqR)) { + // or else the loop will possibly add R as well + end = parseInt(sqR) - 1 + } else { + end = parseInt(Math.floor(sqR)) + } + + let begin + if (sqL === parseInt(sqL)) { + // or else the loop will possibly add R as well + begin = parseInt(sqL) + 1 + } else { + begin = parseInt(Math.ceil(sqL)) + } + + // account for superpalins with for single digit 'sub-palins' + if (begin <= 1 && end >= 1) palins++ // 1 + if (begin <= 2 && end >= 2) palins++ // 4 + if (begin <= 3 && end >= 3) palins++ // 9 + const length = sqR_Length + const even = length % 2 === 0 + const half = Math.floor(length / 2) + const pow10Half = Math.pow(10, half) // 10 or 100 or 1000, etc + const pow10HalfMinOne = Math.pow(10, half - 1) + let pal = '' // init + let palinStr = '' // init + let palin = -1 // init + for (let i = 1, leni = pow10Half; i < leni; i++) { + pal = i.toString(10) + pal.padStart(half - pal.length, '0') + palReverse = reverseStr(pal) + // generate even length palindrome + palinStr = pal + palReverse + palin = parseInt(palinStr) + if (palin >= begin && palin <= end) { + if (isPalindromeInt(BigInt(palin) * BigInt(palin))) { + palins++ + } + } + // If I generate all palindromes up until some even length, + // lets say 4, then last step is to do length 2 + length 2 (19 + 91), + // and not the 19 + 0 + 91 step that generates odd length palindromes. + if (even && i >= pow10HalfMinOne) { + continue + } + for (let j = 0, lenj = 10; j < lenj; j++) { + // generate odd length palindrome + palinStr = pal + j + palReverse + palin = parseInt(palinStr) + if (palin >= begin && palin <= end) { + if (isPalindromeInt(BigInt(palin) * BigInt(palin))) { + palins++ + } + } + } + } + return palins +} + +const reverseStr = function (str) { + return str.split('').reverse().join('') +} + +const isPalindromeInt = function (nr) { + nr = nr.toString(10) + return nr === nr.split('').reverse().join('') +} +const isPalindrome = function (nr) { + return nr === nr.split('').reverse().join('') +} + diff --git a/907-sum-of-subarray-minimums.js b/907-sum-of-subarray-minimums.js deleted file mode 100644 index 52e0a139..00000000 --- a/907-sum-of-subarray-minimums.js +++ /dev/null @@ -1,69 +0,0 @@ - -/** - * @param {number[]} arr - * @return {number} - */ - const sumSubarrayMins = function (arr) { - const n = arr.length - const mod = 1e9 + 7, stk = [] - const left = Array(n), right = Array(n) - for(let i = 0; i< n; i++) { - left[i] = i + 1 - right[i] = n - i - } - let res = 0 - for(let i = 0; i < n; i++) { - while(stk.length && arr[stk[stk.length - 1]] > arr[i]) { - const idx = stk.pop() - right[idx] = i - idx - } - if (stk.length) left[i] = i - stk[stk.length - 1] - stk.push(i) - - } - for(let i = 0; i < n; i++) { - res = (res + arr[i] * left[i] * right[i]) % mod - } - - return res -} - -// another - -/** - * @param {number[]} arr - * @return {number} - */ -const sumSubarrayMins = function (arr) { - const n = arr.length, - s1 = [], - s2 = [], - left = Array(n), - right = Array(n) - for (let i = 0; i < n; i++) { - let cnt = 1 - while (s1.length && s1[s1.length - 1][0] > arr[i]) { - cnt += s1.pop()[1] - } - left[i] = cnt - s1.push([arr[i], cnt]) - } - - for (let i = n - 1; i >= 0; i--) { - let cnt = 1 - while (s2.length && s2[s2.length - 1][0] >= arr[i]) { - cnt += s2.pop()[1] - } - right[i] = cnt - s2.push([arr[i], cnt]) - } - let res = 0 - const mod = 1e9 + 7 - for (let i = 0; i < n; i++) { - // left[i] number of starting positions - // right[i] number of ending positions - res = (res + arr[i] * left[i] * right[i]) % mod - } - - return res -} diff --git a/907.sum-of-subarray-minimums.js b/907.sum-of-subarray-minimums.js new file mode 100644 index 00000000..55c9c425 --- /dev/null +++ b/907.sum-of-subarray-minimums.js @@ -0,0 +1,30 @@ + +/** + * @param {number[]} arr + * @return {number} + */ + const sumSubarrayMins = function (arr) { + const n = arr.length + const mod = 1e9 + 7, stk = [] + const left = Array(n), right = Array(n) + for(let i = 0; i< n; i++) { + left[i] = i + 1 + right[i] = n - i + } + let res = 0 + for(let i = 0; i < n; i++) { + while(stk.length && arr[stk[stk.length - 1]] > arr[i]) { + const idx = stk.pop() + right[idx] = i - idx + } + if (stk.length) left[i] = i - stk[stk.length - 1] + stk.push(i) + + } + for(let i = 0; i < n; i++) { + res = (res + arr[i] * left[i] * right[i]) % mod + } + + return res +} + diff --git a/908-smallest-range-i.js b/908.smallest-range-i.js similarity index 100% rename from 908-smallest-range-i.js rename to 908.smallest-range-i.js diff --git a/91-decode-ways.js b/91-decode-ways.js deleted file mode 100644 index 300145d2..00000000 --- a/91-decode-ways.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const numDecodings = function(s) { - if(s == null || s.length === 0) return 1 - if(s[0] === '0') return 0 - const set = new Set() - const n = s.length - for(let i = 1; i <= 26; i++) { - set.add(`${i}`) - } - const dp = Array(n + 1).fill(0) - dp[0] = dp[1] = 1 - for(let i = 2; i <= n; i++) { - if(set.has(s[i - 2] + s[i - 1])) dp[i] += dp[i - 2] - if(set.has(s[i - 1])) dp[i] += dp[i - 1] - } - return dp[n] -}; - - -// another - -/** - * @param {string} s - * @return {number} - */ -const numDecodings = function(s) { - if (s.length === 0) return 0 - const N = s.length - const dp = Array(N + 1).fill(0) - dp[0] = 1 - dp[1] = s[0] === "0" ? 0 : 1 - for (let i = 2; i <= N; i++) { - if (s[i - 1] !== "0") { - dp[i] += dp[i - 1] - } - if (s[i - 2] === "1" || (s[i - 2] === "2" && s[i - 1] <= "6")) { - dp[i] += dp[i - 2] - } - } - return dp[N] -} diff --git a/91.decode-ways.js b/91.decode-ways.js new file mode 100644 index 00000000..282d4a69 --- /dev/null +++ b/91.decode-ways.js @@ -0,0 +1,22 @@ +/** + * @param {string} s + * @return {number} + */ +const numDecodings = function(s) { + if(s == null || s.length === 0) return 1 + if(s[0] === '0') return 0 + const set = new Set() + const n = s.length + for(let i = 1; i <= 26; i++) { + set.add(`${i}`) + } + const dp = Array(n + 1).fill(0) + dp[0] = dp[1] = 1 + for(let i = 2; i <= n; i++) { + if(set.has(s[i - 2] + s[i - 1])) dp[i] += dp[i - 2] + if(set.has(s[i - 1])) dp[i] += dp[i - 1] + } + return dp[n] +}; + + diff --git a/910-smallest-range-ii.js b/910.smallest-range-ii.js similarity index 100% rename from 910-smallest-range-ii.js rename to 910.smallest-range-ii.js diff --git a/912-sort-an-array.js b/912.sort-an-array.js similarity index 100% rename from 912-sort-an-array.js rename to 912.sort-an-array.js diff --git a/913-cat-and-mouse.js b/913.cat-and-mouse.js similarity index 100% rename from 913-cat-and-mouse.js rename to 913.cat-and-mouse.js diff --git a/914-x-of-a-kind-in-a-deck-of-cards.js b/914.x-of-a-kind-in-a-deck-of-cards.js similarity index 100% rename from 914-x-of-a-kind-in-a-deck-of-cards.js rename to 914.x-of-a-kind-in-a-deck-of-cards.js diff --git a/915-partition-array-into-disjoint-intervals.js b/915.partition-array-into-disjoint-intervals.js similarity index 100% rename from 915-partition-array-into-disjoint-intervals.js rename to 915.partition-array-into-disjoint-intervals.js diff --git a/916-word-subsets.js b/916-word-subsets.js deleted file mode 100755 index bc1f6e13..00000000 --- a/916-word-subsets.js +++ /dev/null @@ -1,32 +0,0 @@ -/** - * @param {string[]} A - * @param {string[]} B - * @return {string[]} - */ -const wordSubsets = function(A, B) { - function counter(s) { - let count = Array(26).fill(0); - for (let i = 0; i < s.length; i++) count[s.charCodeAt(i) - 97]++; - return count; - } - let aux = Array(26).fill(0); - let result = []; - for (let i = 0; i < B.length; i++) { - let count = counter(B[i]); - for (let i = 0; i < 26; i++) { - aux[i] = Math.max(aux[i], count[i]); - } - } - for (let i = 0; i < A.length; i++) { - let count = counter(A[i]); - let flag = true; - for (let j = 0; j < 26; j++) { - if (aux[j] > 0 && count[j] - aux[j] < 0) { - flag = false; - break; - } - } - if (flag) result.push(A[i]); - } - return result; -}; diff --git a/916.word-subsets.js b/916.word-subsets.js new file mode 100644 index 00000000..572f5942 --- /dev/null +++ b/916.word-subsets.js @@ -0,0 +1,32 @@ +/** + * @param {string[]} A + * @param {string[]} B + * @return {string[]} + */ +const wordSubsets = function(A, B) { + function counter(s) { + let count = Array(26).fill(0); + for (let i = 0; i < s.length; i++) count[s.charCodeAt(i) - 97]++; + return count; + } + let aux = Array(26).fill(0); + let result = []; + for (let i = 0; i < B.length; i++) { + let count = counter(B[i]); + for (let i = 0; i < 26; i++) { + aux[i] = Math.max(aux[i], count[i]); + } + } + for (let i = 0; i < A.length; i++) { + let count = counter(A[i]); + let flag = true; + for (let j = 0; j < 26; j++) { + if (aux[j] > 0 && count[j] - aux[j] < 0) { + flag = false; + break; + } + } + if (flag) result.push(A[i]); + } + return result; +}; diff --git a/917-reverse-only-letters.js b/917.reverse-only-letters.js similarity index 100% rename from 917-reverse-only-letters.js rename to 917.reverse-only-letters.js diff --git a/918-maximum-sum-circular-subarray.js b/918.maximum-sum-circular-subarray.js similarity index 100% rename from 918-maximum-sum-circular-subarray.js rename to 918.maximum-sum-circular-subarray.js diff --git a/919-complete-binary-tree-inserter.js b/919.complete-binary-tree-inserter.js similarity index 100% rename from 919-complete-binary-tree-inserter.js rename to 919.complete-binary-tree-inserter.js diff --git a/92-reverse-linked-list-ii.js b/92-reverse-linked-list-ii.js deleted file mode 100644 index 8b30ebfb..00000000 --- a/92-reverse-linked-list-ii.js +++ /dev/null @@ -1,236 +0,0 @@ -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @param {number} left - * @param {number} right - * @return {ListNode} - */ -const reverseBetween = function(head, left, right) { - if(head == null) return head - const dummy = new ListNode(null, head) - let num = 0, cur = head - while (cur) { - num++ - cur = cur.next - } - let idx = 0, pre = null - cur = dummy - while (idx < right && idx <= num) { - if (idx === left - 1) pre = cur - if (idx >= left) { - const tmp = pre.next - pre.next = cur.next - cur.next = cur.next.next - pre.next.next = tmp - } - - if (idx < left) cur = cur.next - idx++ - } - return dummy.next -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val) { - * this.val = val; - * this.next = null; - * } - */ -/** - * @param {ListNode} head - * @param {number} m - * @param {number} n - * @return {ListNode} - */ -const reverseBetween = function(head, m, n) { - // Empty list - if (head == null) { - return null; - } - - // Move the two pointers until they reach the proper starting point - // in the list. - let cur = head, prev = null; - while (m > 1) { - prev = cur; - cur = cur.next; - m--; - n--; - } - - // The two pointers that will fix the final connections. - let con = prev, tail = cur; - - // Iteratively reverse the nodes until n becomes 0. - let third = null; - while (n > 0) { - third = cur.next; - cur.next = prev; - prev = cur; - cur = third; - n--; - } - - // Adjust the final connections as explained in the algorithm - if (con != null) { - con.next = prev; - } else { - head = prev; - } - - tail.next = cur; - return head; -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @param {number} m - * @param {number} n - * @return {ListNode} - */ -const reverseBetween = function(head, m, n) { - if (!head) return null; - const dummy = new ListNode(0); - dummy.next = head; - let pre = dummy; - for (let i = 0; i < m-1; i++) pre = pre.next - let start = pre.next; - let then = start.next; - - for (let i = 0; i < n-m; i++) { - start.next = then.next - then.next = pre.next - pre.next = then; - then = start.next; - } - return dummy.next; -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @param {number} left - * @param {number} right - * @return {ListNode} - */ -const reverseBetween = function(head, left, right) { - if(head == null || left === right) return head - const dummy = new ListNode() - dummy.next = head - let tail = null, p = dummy - for(let i = 1; i < left; i++) { - p = p.next - } - tail = p.next - let tmp - for(let i = 0; i < right - left; i++) { - tmp = p.next - p.next = tail.next - tail.next = tail.next.next - p.next.next = tmp - } - - return dummy.next -}; - -// another - -/** - * @param {ListNode} head - * @param {number} left - * @param {number} right - * @return {ListNode} - */ -const reverseBetween = function(head, left, right) { - if(head == null) return head - if(left === right) return head - let cur = head, prev = null - let step = 1 - while(step !== left) { - prev = cur - cur = cur.next - step++ - } - let l = cur - while(step !== right) { - cur = cur.next - step++ - } - let r = cur, next = cur.next - // reverse - - let start = l, p = null - while(start !== r) { - let n = start.next - start.next = p - p = start - start = n - } - - r.next = p - l.next = next - if(prev) prev.next = r - - return prev ? head : r -}; - -// another - -/** - * Definition for singly-linked list. - * function ListNode(val, next) { - * this.val = (val===undefined ? 0 : val) - * this.next = (next===undefined ? null : next) - * } - */ -/** - * @param {ListNode} head - * @param {number} left - * @param {number} right - * @return {ListNode} - */ -const reverseBetween = function(head, left, right) { - if(head == null) return head - const dummy = new ListNode() - dummy.next = head - - let p = dummy - for(let i = 0; i < left - 1; i++) { - p = p.next - } - let tail = p.next, tmp = null - for(let i = 0; i < right - left; i++) { - tmp = p.next - p.next = tail.next - tail.next = tail.next.next - p.next.next = tmp - } - - return dummy.next -}; diff --git a/92.reverse-linked-list-ii.js b/92.reverse-linked-list-ii.js new file mode 100644 index 00000000..687b4d45 --- /dev/null +++ b/92.reverse-linked-list-ii.js @@ -0,0 +1,38 @@ +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} head + * @param {number} left + * @param {number} right + * @return {ListNode} + */ +const reverseBetween = function(head, left, right) { + if(head == null) return head + const dummy = new ListNode(null, head) + let num = 0, cur = head + while (cur) { + num++ + cur = cur.next + } + let idx = 0, pre = null + cur = dummy + while (idx < right && idx <= num) { + if (idx === left - 1) pre = cur + if (idx >= left) { + const tmp = pre.next + pre.next = cur.next + cur.next = cur.next.next + pre.next.next = tmp + } + + if (idx < left) cur = cur.next + idx++ + } + return dummy.next +}; + diff --git a/920-number-of-music-playlists.js b/920.number-of-music-playlists.js similarity index 100% rename from 920-number-of-music-playlists.js rename to 920.number-of-music-playlists.js diff --git a/921-minimum-add-to-make-parentheses-valid.js b/921.minimum-add-to-make-parentheses-valid.js similarity index 100% rename from 921-minimum-add-to-make-parentheses-valid.js rename to 921.minimum-add-to-make-parentheses-valid.js diff --git a/922-sort-array-by-parity-ii.js b/922.sort-array-by-parity-ii.js similarity index 100% rename from 922-sort-array-by-parity-ii.js rename to 922.sort-array-by-parity-ii.js diff --git a/923-3sum-with-multiplicity.js b/923.3sum-with-multiplicity.js similarity index 100% rename from 923-3sum-with-multiplicity.js rename to 923.3sum-with-multiplicity.js diff --git a/924-minimize-malware-spread.js b/924.minimize-malware-spread.js similarity index 100% rename from 924-minimize-malware-spread.js rename to 924.minimize-malware-spread.js diff --git a/925-long-pressed-name.js b/925.long-pressed-name.js similarity index 100% rename from 925-long-pressed-name.js rename to 925.long-pressed-name.js diff --git a/926-flip-string-to-monotone-increasing.js b/926-flip-string-to-monotone-increasing.js deleted file mode 100644 index 71f6bfff..00000000 --- a/926-flip-string-to-monotone-increasing.js +++ /dev/null @@ -1,45 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const minFlipsMonoIncr = function(s) { - const n = s.length - let res = 0, oneCnt = 0 - for(const e of s) { - if(e === '1') oneCnt++ - else { - const stayZero = oneCnt - const flipToOne = res + 1 - res = Math.min(stayZero, flipToOne) - } - } - - return res -}; - -// another - - -/** - * @param {string} s - * @return {number} - */ -const minFlipsMonoIncr = function(s) { - const n = s.length - const arr = Array(n).fill(0) - let oneCnt = 0 - for(let i = 0; i < n; i++) { - if(s[i] === '1') oneCnt++ - arr[i] = oneCnt - } - const zeroCnt = n - oneCnt - let res = Infinity - - for(let i = 0; i < n; i++) { - const cnt = arr[i] - const tmp = cnt + (zeroCnt - (i + 1 - cnt)) - res = Math.min(res, tmp) - } - res = Math.min(res, oneCnt, zeroCnt) - return res -}; diff --git a/926.flip-string-to-monotone-increasing.js b/926.flip-string-to-monotone-increasing.js new file mode 100644 index 00000000..1f728f48 --- /dev/null +++ b/926.flip-string-to-monotone-increasing.js @@ -0,0 +1,19 @@ +/** + * @param {string} s + * @return {number} + */ +const minFlipsMonoIncr = function(s) { + const n = s.length + let res = 0, oneCnt = 0 + for(const e of s) { + if(e === '1') oneCnt++ + else { + const stayZero = oneCnt + const flipToOne = res + 1 + res = Math.min(stayZero, flipToOne) + } + } + + return res +}; + diff --git a/927-three-equal-parts.js b/927.three-equal-parts.js similarity index 100% rename from 927-three-equal-parts.js rename to 927.three-equal-parts.js diff --git a/928-minimize-malware-spread-ii.js b/928-minimize-malware-spread-ii.js deleted file mode 100644 index dbe1249e..00000000 --- a/928-minimize-malware-spread-ii.js +++ /dev/null @@ -1,96 +0,0 @@ -/** - * @param {number[][]} graph - * @param {number[]} initial - * @return {number} - */ -var minMalwareSpread = function (graph, initial) { - const map = new Map() // node -> initial nodes infect this node - for (let i of initial) { - const visited = new Set(initial) - const q = [] - q.push(i) - while (q.length) { - let cur = q.shift() - for (let j = 0; j < graph[cur].length; j++) { - if (graph[cur][j] == 1) { - if (!visited.has(j)) { - visited.add(j) - q.push(j) - - if (map.get(j) == null) map.set(j, []) - map.get(j).push(i) - } - } - } - } - } - - const res = Array(graph.length).fill(0) // node -> safe nodes it infects - for (let node of map.keys()) { - if (map.get(node).length == 1) { - let i = map.get(node)[0] - res[i]++ - } - } - let max = 0 - let removed = -1 - for (let i = 0; i < res.length; i++) { - if (res[i] > max) { - max = res[i] - removed = i - } - } - initial.sort((a, b) => a - b) - return removed == -1 ? initial[0] : removed -} - -// another - -/** - * @param {number[][]} graph - * @param {number[]} initial - * @return {number} - */ -const minMalwareSpread = function (graph, initial) { - const map = new Map(), n = graph.length - for(let init of initial) { - const visited = new Set(initial) - const q = [init] - while(q.length) { - const cur = q.pop() - for(let i = 0; i < n; i++) { - if(graph[cur][i] === 1 && !visited.has(i)) { - visited.add(i) - q.push(i) - if(map.get(i) == null) map.set(i, []) - map.get(i).push(init) - } - } - } - } - - let res = 0, max = -1 - const arr = Array(n) - for(let [k,v] of map) { - if(v.length === 1) { - if(arr[v[0]] == null) arr[v[0]] = 0 - arr[v[0]]++ - } - } - - for(let k = 0; k < n; k++) { - const v = arr[k] - if(v > max) { - max = v - res = +k - } - } - - let min = Infinity - for(let e of initial) { - if(e < min) min = e - } - return max === -1 ? min: res - -} - diff --git a/928.minimize-malware-spread-ii.js b/928.minimize-malware-spread-ii.js new file mode 100644 index 00000000..e9195d47 --- /dev/null +++ b/928.minimize-malware-spread-ii.js @@ -0,0 +1,46 @@ +/** + * @param {number[][]} graph + * @param {number[]} initial + * @return {number} + */ +var minMalwareSpread = function (graph, initial) { + const map = new Map() // node -> initial nodes infect this node + for (let i of initial) { + const visited = new Set(initial) + const q = [] + q.push(i) + while (q.length) { + let cur = q.shift() + for (let j = 0; j < graph[cur].length; j++) { + if (graph[cur][j] == 1) { + if (!visited.has(j)) { + visited.add(j) + q.push(j) + + if (map.get(j) == null) map.set(j, []) + map.get(j).push(i) + } + } + } + } + } + + const res = Array(graph.length).fill(0) // node -> safe nodes it infects + for (let node of map.keys()) { + if (map.get(node).length == 1) { + let i = map.get(node)[0] + res[i]++ + } + } + let max = 0 + let removed = -1 + for (let i = 0; i < res.length; i++) { + if (res[i] > max) { + max = res[i] + removed = i + } + } + initial.sort((a, b) => a - b) + return removed == -1 ? initial[0] : removed +} + diff --git a/929-unique-email-addresses.js b/929.unique-email-addresses.js similarity index 100% rename from 929-unique-email-addresses.js rename to 929.unique-email-addresses.js diff --git a/93-restore-ip-addresses.js b/93-restore-ip-addresses.js deleted file mode 100644 index c2eb14a9..00000000 --- a/93-restore-ip-addresses.js +++ /dev/null @@ -1,61 +0,0 @@ -/** - * @param {string} s - * @return {string[]} - */ -const restoreIpAddresses = function(s) { - if (s.length < 4 || s.length > 12) return []; - const res = []; - let ans = ""; - for (let a = 1; a <= 3; a++) { - for (let b = 1; b <= 3; b++) { - for (let c = 1; c <= 3; c++) { - for (let d = 1; d <= 3; d++) { - if (a + b + c + d === s.length) { - let A = +s.substr(0, a); - let B = +s.substr(a, b); - let C = +s.substr(a + b, c); - let D = +s.substr(a + b + c, d); - if (A <= 255 && B <= 255 && C <= 255 && D <= 255) { - if ( - ((ans = A + "." + B + "." + C + "." + D).length === s.length + 3) - ) { - res.push(ans); - } - } - } - } - } - } - } - return res; -}; - -// another method - -/** - * @param {string} s - * @return {string[]} - */ -const restoreIpAddresses = function(s) { - const ans = []; - const stack = []; - let ipstr; - const len = s.length; - function restoreIp(start) { - if (stack.length > 4) return; - if (stack.length === 4 && start > len - 1) { - ans.push(stack.slice().join(".")); - return; - } - for (let i = start; i < start + 3; i++) { - if (i > len - 1) return; - ipstr = s.substring(start, i + 1); - if ((ipstr[0] === "0" && ipstr.length !== 1) || ipstr > 255) return; - stack.push(ipstr); - restoreIp(i + 1); - stack.pop(); - } - } - restoreIp(0); - return ans; -}; diff --git a/93.restore-ip-addresses.js b/93.restore-ip-addresses.js new file mode 100644 index 00000000..0a794382 --- /dev/null +++ b/93.restore-ip-addresses.js @@ -0,0 +1,32 @@ +/** + * @param {string} s + * @return {string[]} + */ +const restoreIpAddresses = function(s) { + if (s.length < 4 || s.length > 12) return []; + const res = []; + let ans = ""; + for (let a = 1; a <= 3; a++) { + for (let b = 1; b <= 3; b++) { + for (let c = 1; c <= 3; c++) { + for (let d = 1; d <= 3; d++) { + if (a + b + c + d === s.length) { + let A = +s.substr(0, a); + let B = +s.substr(a, b); + let C = +s.substr(a + b, c); + let D = +s.substr(a + b + c, d); + if (A <= 255 && B <= 255 && C <= 255 && D <= 255) { + if ( + ((ans = A + "." + B + "." + C + "." + D).length === s.length + 3) + ) { + res.push(ans); + } + } + } + } + } + } + } + return res; +}; + diff --git a/930-binary-subarrays-with-sum.js b/930-binary-subarrays-with-sum.js deleted file mode 100644 index 785bf86c..00000000 --- a/930-binary-subarrays-with-sum.js +++ /dev/null @@ -1,43 +0,0 @@ -/** - * @param {number[]} A - * @param {number} S - * @return {number} - */ -const numSubarraysWithSum = function(A, S) { - if(A === null || A.length == 0) return 0; - const freq = new Array(A.length + 1).fill(0) - let ans = 0; - let sum = 0; - for(let i = 0; i < A.length; i++) { - sum += A[i]; - let index = sum - S; - if(index >= 0) ans += freq[index]; - if(sum == S) ans++; - freq[sum]++; - } - return ans; -}; - -// another - -/** - * @param {number[]} nums - * @param {number} goal - * @return {number} - */ -const numSubarraysWithSum = function(nums, goal) { - const hash = {} - const n = nums.length - let res = 0, sum = 0 - for(let i = 0; i < n; i++) { - const cur = nums[i] - sum += cur - const pre = sum - goal - if(hash[sum] == null) hash[sum] = 0 - if(hash[pre] != null) res += hash[pre] - if(sum === goal) res++ - hash[sum]++ - } - - return res -}; diff --git a/930.binary-subarrays-with-sum.js b/930.binary-subarrays-with-sum.js new file mode 100644 index 00000000..cfc74d4a --- /dev/null +++ b/930.binary-subarrays-with-sum.js @@ -0,0 +1,20 @@ +/** + * @param {number[]} A + * @param {number} S + * @return {number} + */ +const numSubarraysWithSum = function(A, S) { + if(A === null || A.length == 0) return 0; + const freq = new Array(A.length + 1).fill(0) + let ans = 0; + let sum = 0; + for(let i = 0; i < A.length; i++) { + sum += A[i]; + let index = sum - S; + if(index >= 0) ans += freq[index]; + if(sum == S) ans++; + freq[sum]++; + } + return ans; +}; + diff --git a/931-minimum-falling-path-sum.js b/931-minimum-falling-path-sum.js deleted file mode 100644 index d41ece0e..00000000 --- a/931-minimum-falling-path-sum.js +++ /dev/null @@ -1,44 +0,0 @@ -/** - * @param {number[][]} A - * @return {number} - */ -const minFallingPathSum = function(A) { - for (let i = 1, rows = A.length; i < rows; i++) { - for (let j = 0, cols = A[0].length; j < cols; j++) { - A[i][j] += Math.min( - getValueOrMax(A, i - 1, j - 1), - getValueOrMax(A, i - 1, j), - getValueOrMax(A, i - 1, j + 1) - ); - } - } - return Math.min(...A[A.length - 1]); -}; - -function getValueOrMax(A, i, j) { - return A[i][j] !== undefined ? A[i][j] : Number.MAX_VALUE; -} - -// another - -/** - * @param {number[][]} A - * @return {number} - */ -const minFallingPathSum = function(A) { - for (let i = A.length - 2; i >= 0; i -= 1) { - for (let j = 0; j < A[i].length; j += 1) { - A[i][j] += Math.min( - getValueOrMax(A, i + 1, j - 1), - getValueOrMax(A, i + 1, j), - getValueOrMax(A, i + 1, j + 1) - ) - } - } - return Math.min(...A[0]) - } - - function getValueOrMax(A, i, j) { - return A[i][j] !== undefined ? A[i][j] : Number.MAX_VALUE - } - diff --git a/931.minimum-falling-path-sum.js b/931.minimum-falling-path-sum.js new file mode 100644 index 00000000..78fb4148 --- /dev/null +++ b/931.minimum-falling-path-sum.js @@ -0,0 +1,21 @@ +/** + * @param {number[][]} A + * @return {number} + */ +const minFallingPathSum = function(A) { + for (let i = 1, rows = A.length; i < rows; i++) { + for (let j = 0, cols = A[0].length; j < cols; j++) { + A[i][j] += Math.min( + getValueOrMax(A, i - 1, j - 1), + getValueOrMax(A, i - 1, j), + getValueOrMax(A, i - 1, j + 1) + ); + } + } + return Math.min(...A[A.length - 1]); +}; + +function getValueOrMax(A, i, j) { + return A[i][j] !== undefined ? A[i][j] : Number.MAX_VALUE; +} + diff --git a/932-beautiful-array.js b/932.beautiful-array.js similarity index 100% rename from 932-beautiful-array.js rename to 932.beautiful-array.js diff --git a/933-number-of-recent-calls.js b/933.number-of-recent-calls.js similarity index 100% rename from 933-number-of-recent-calls.js rename to 933.number-of-recent-calls.js diff --git a/934-shortest-bridge.js b/934.shortest-bridge.js similarity index 100% rename from 934-shortest-bridge.js rename to 934.shortest-bridge.js diff --git a/936-stamping-the-sequence.js b/936.stamping-the-sequence.js similarity index 100% rename from 936-stamping-the-sequence.js rename to 936.stamping-the-sequence.js diff --git a/937-reorder-data-in-log-files.js b/937-reorder-data-in-log-files.js deleted file mode 100644 index aa103f4e..00000000 --- a/937-reorder-data-in-log-files.js +++ /dev/null @@ -1,62 +0,0 @@ -/** - * @param {string[]} logs - * @return {string[]} - */ -const reorderLogFiles = function(logs) { - const letterLog = [], - digitLog = [] - for (let log of logs) { - if (isNaN(log.split(' ')[1])) { - letterLog.push(log) - } else { - digitLog.push(log) - } - } - letterLog.sort((log1, log2) => { - let body1 = log1.slice(log1.indexOf(' ')) - let body2 = log2.slice(log2.indexOf(' ')) - if (body1 === body2) { - return log1.split(' ')[0] > log2.split(' ')[0] ? 1 : -1 - } else { - return body1 > body2 ? 1 : -1 - } - }) - return [...letterLog, ...digitLog] -} - -// another - -/** - * @param {string[]} logs - * @return {string[]} - */ -const reorderLogFiles = function(logs) { - if(logs == null || logs.length === 0) return [] - const ll = [] - const dl = [] - const zero = '0'.charCodeAt(0) - const nine = '9'.charCodeAt(0) - for(let e of logs) { - const arr = e.split(' ') - if(arr[1].charCodeAt(0) >= zero && arr[1].charCodeAt(0) <= nine) { - dl.push(arr) - } else { - ll.push(arr) - } - } - const rll = ll.map(el => { - const r = el.slice(1).join(' ') - return [el[0], r] - }).sort((a, b) => { - if(a[1] < b[1]) return -1 - else if(a[1] > b[1]) return 1 - else { - if(`${a[0]} ${a[1]}` > `${b[0]} ${b[1]}`) return 1 - else if(`${a[0]} ${a[1]}` < `${b[0]} ${b[1]}`) return -1 - else return 0 - } - }).map(el => el.join(' ')) - - const rdl = dl.map(el => el.join(' ')) - return rll.concat(rdl) -}; diff --git a/937.reorder-data-in-log-files.js b/937.reorder-data-in-log-files.js new file mode 100644 index 00000000..54cf644e --- /dev/null +++ b/937.reorder-data-in-log-files.js @@ -0,0 +1,26 @@ +/** + * @param {string[]} logs + * @return {string[]} + */ +const reorderLogFiles = function(logs) { + const letterLog = [], + digitLog = [] + for (let log of logs) { + if (isNaN(log.split(' ')[1])) { + letterLog.push(log) + } else { + digitLog.push(log) + } + } + letterLog.sort((log1, log2) => { + let body1 = log1.slice(log1.indexOf(' ')) + let body2 = log2.slice(log2.indexOf(' ')) + if (body1 === body2) { + return log1.split(' ')[0] > log2.split(' ')[0] ? 1 : -1 + } else { + return body1 > body2 ? 1 : -1 + } + }) + return [...letterLog, ...digitLog] +} + diff --git a/938-range-sum-of-bst.js b/938.range-sum-of-bst.js similarity index 100% rename from 938-range-sum-of-bst.js rename to 938.range-sum-of-bst.js diff --git a/939-minimum-area-rectangle.js b/939-minimum-area-rectangle.js deleted file mode 100644 index 722d4940..00000000 --- a/939-minimum-area-rectangle.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @param {number[][]} points - * @return {number} - */ -const minAreaRect = function(points) { - const xmap = {}, ymap = {} - points.forEach(e => { - const [x, y] = e - if(!xmap.hasOwnProperty(x)) xmap[x] = new Set() - if(!ymap.hasOwnProperty(y)) ymap[y] = new Set() - xmap[x].add(y) - ymap[y].add(x) - }) - let res = Infinity - for(let i = 0, len = points.length; i < len - 1; i++) { - const [x, y] = points[i] - for(let j = i + 1; j < len; j++) { - const [x1, y1] = points[j] - if(x === x1 || y === y1) continue - let area = Infinity - if(xmap[x].has(y1) && ymap[y].has(x1)) area = Math.abs(x - x1) * Math.abs(y - y1) - else continue - res = Math.min(res, area) - } - } - return res === Infinity ? 0 : res -}; - -// another - -/** - * @param {number[][]} points - * @return {number} - */ -const minAreaRect = function (points) { - let ans = Infinity - const isPoint = {} - points.forEach(([x, y]) => (isPoint[x * 40000 + y] = true)) - for (let idx1 = 0; idx1 < points.length - 1; idx1++) { - const [x1, y1] = points[idx1] - for (let idx2 = idx1 + 1; idx2 < points.length; idx2++) { - const [x2, y2] = points[idx2] - const area = Math.abs((x1 - x2) * (y1 - y2)) - if (area === 0 || area >= ans) continue - if (isPoint[x1 * 40000 + y2] && isPoint[x2 * 40000 + y1]) ans = area - } - } - return ans !== Infinity ? ans : 0 -} - diff --git a/939.minimum-area-rectangle.js b/939.minimum-area-rectangle.js new file mode 100644 index 00000000..2bb96a2c --- /dev/null +++ b/939.minimum-area-rectangle.js @@ -0,0 +1,28 @@ +/** + * @param {number[][]} points + * @return {number} + */ +const minAreaRect = function(points) { + const xmap = {}, ymap = {} + points.forEach(e => { + const [x, y] = e + if(!xmap.hasOwnProperty(x)) xmap[x] = new Set() + if(!ymap.hasOwnProperty(y)) ymap[y] = new Set() + xmap[x].add(y) + ymap[y].add(x) + }) + let res = Infinity + for(let i = 0, len = points.length; i < len - 1; i++) { + const [x, y] = points[i] + for(let j = i + 1; j < len; j++) { + const [x1, y1] = points[j] + if(x === x1 || y === y1) continue + let area = Infinity + if(xmap[x].has(y1) && ymap[y].has(x1)) area = Math.abs(x - x1) * Math.abs(y - y1) + else continue + res = Math.min(res, area) + } + } + return res === Infinity ? 0 : res +}; + diff --git a/94-binary-tree-inorder-traversal.js b/94-binary-tree-inorder-traversal.js deleted file mode 100755 index 0c15eb87..00000000 --- a/94-binary-tree-inorder-traversal.js +++ /dev/null @@ -1,27 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number[]} - */ -const inorderTraversal = function(root) { - const res = []; - if (root == null) return res; - traversal(root, res); - return res; -}; - -function traversal(node, res) { - if (node.left) { - traversal(node.left, res); - } - res.push(node.val); - if (node.right) { - traversal(node.right, res); - } -} diff --git a/94.binary-tree-inorder-traversal.js b/94.binary-tree-inorder-traversal.js new file mode 100644 index 00000000..e3a4e78c --- /dev/null +++ b/94.binary-tree-inorder-traversal.js @@ -0,0 +1,27 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number[]} + */ +const inorderTraversal = function(root) { + const res = []; + if (root == null) return res; + traversal(root, res); + return res; +}; + +function traversal(node, res) { + if (node.left) { + traversal(node.left, res); + } + res.push(node.val); + if (node.right) { + traversal(node.right, res); + } +} diff --git a/940-distinct-subsequences-ii.js b/940-distinct-subsequences-ii.js deleted file mode 100644 index 723acd12..00000000 --- a/940-distinct-subsequences-ii.js +++ /dev/null @@ -1,52 +0,0 @@ -/** - * @param {string} s - * @return {number} - */ -const distinctSubseqII = function(s) { - const n = s.length, - dp = Array(26).fill(0), - a = 'a'.charCodeAt(0), - mod = 1e9 + 7 - let res = 0 - for(let ch of s) { - const idx = ch.charCodeAt(0) - a - let tmp = 0 - for(let i = 0; i < 26; i++) tmp = (tmp + dp[i]) % mod - tmp = (tmp + 1) % mod - dp[idx] = tmp - } - return dp.reduce((ac, e) => (ac + e) % mod, 0) -}; - -// another - -/** - * @param {string} S - * @return {number} - */ -const distinctSubseqII = function(S) { - // let end = new Array(26).fill(0), res = 0, added = 0, mod = 10 ** 9 + 7; - // const aCode = ('a').charCodeAt(0) - // for (let c of S) { - // added = (res + 1 - end[c.charCodeAt(0) - aCode]) % mod; - // res = (res + added) % mod; - // end[c.charCodeAt(0) - aCode] = (end[c.charCodeAt(0) - aCode] + added) % mod; - // } - // return (res + mod) % mod; - const m = new Map(), - dp = [1], - M = 1000000007 - for (let i = 0; i < S.length; i++) { - const c = S.charAt(i) - let prev = 0 - if (m.has(c)) { - prev = dp[m.get(c)] - } - m.set(c, i) - dp.push((((dp[i] * 2) % M) - prev) % M) - if (dp[i + 1] < 0) { - dp[i + 1] += M - } - } - return dp[S.length] - 1 -} diff --git a/940.distinct-subsequences-ii.js b/940.distinct-subsequences-ii.js new file mode 100644 index 00000000..9dc68e6b --- /dev/null +++ b/940.distinct-subsequences-ii.js @@ -0,0 +1,20 @@ +/** + * @param {string} s + * @return {number} + */ +const distinctSubseqII = function(s) { + const n = s.length, + dp = Array(26).fill(0), + a = 'a'.charCodeAt(0), + mod = 1e9 + 7 + let res = 0 + for(let ch of s) { + const idx = ch.charCodeAt(0) - a + let tmp = 0 + for(let i = 0; i < 26; i++) tmp = (tmp + dp[i]) % mod + tmp = (tmp + 1) % mod + dp[idx] = tmp + } + return dp.reduce((ac, e) => (ac + e) % mod, 0) +}; + diff --git a/941-valid-mountain-array.js b/941.valid-mountain-array.js similarity index 100% rename from 941-valid-mountain-array.js rename to 941.valid-mountain-array.js diff --git a/942-di-string-match.js b/942-di-string-match.js deleted file mode 100644 index 7fee2f08..00000000 --- a/942-di-string-match.js +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @param {string} S - * @return {number[]} - */ -const diStringMatch = function(S) { - const N = S.length - const arr = [] - for(let i = 0; i <= N; i++) { - arr[i] = i - } - const res = [] - for(let i = 0; i < N; i++) { - if(S[i] === 'I') { - res.push(arr.shift()) - } else if(S[i] === 'D') { - res.push(arr.pop()) - } - } - res.push(arr.pop()) - return res -}; - -// another - -/* - -it is greedy and one pass !! -so every time when we meet an I, we need to keep in mind that we may meet another I later, -so the safest way is use the smallest number available. same idea when we meet D, -so in order to keep us safe, we always take largest one available, until we traverse the whole string. -And since the available numbers are sorted(from 0 to S.length()), -so we can set two pointers one starts from the head(smallest number), -another from the ends(largest number), then we begin to fill the res array. - -*/ - -/** - * @param {string} s - * @return {number[]} - */ -const diStringMatch = function(s) { - const n = s.length - let l = 0, r = n - const res = [] - for(let i = 0; i < n; i++) { - res.push(s[i] === 'I' ? l++ : r--) - } - res.push(r) - return res -}; diff --git a/942.di-string-match.js b/942.di-string-match.js new file mode 100644 index 00000000..3b028de0 --- /dev/null +++ b/942.di-string-match.js @@ -0,0 +1,22 @@ +/** + * @param {string} S + * @return {number[]} + */ +const diStringMatch = function(S) { + const N = S.length + const arr = [] + for(let i = 0; i <= N; i++) { + arr[i] = i + } + const res = [] + for(let i = 0; i < N; i++) { + if(S[i] === 'I') { + res.push(arr.shift()) + } else if(S[i] === 'D') { + res.push(arr.pop()) + } + } + res.push(arr.pop()) + return res +}; + diff --git a/943-find-the-shortest-superstring.js b/943.find-the-shortest-superstring.js similarity index 100% rename from 943-find-the-shortest-superstring.js rename to 943.find-the-shortest-superstring.js diff --git a/944-delete-columns-to-make-sorted.js b/944.delete-columns-to-make-sorted.js similarity index 100% rename from 944-delete-columns-to-make-sorted.js rename to 944.delete-columns-to-make-sorted.js diff --git a/945-minimum-increment-to-make-array-unique.js b/945-minimum-increment-to-make-array-unique.js deleted file mode 100644 index 0ce8f909..00000000 --- a/945-minimum-increment-to-make-array-unique.js +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const minIncrementForUnique = function(nums) { - const seen = new Set() - const queue = [] - let res = 0 - for(const e of nums) { - if(!seen.has(e)) seen.add(e) - else queue.push(e) - } - queue.sort((a, b) => b - a) - for(let i = 0; i <= 1e5 || queue.length; i++) { - if(!seen.has(i) && i > last(queue)) { - res += i - queue.pop() - } - } - - return res - - function last(arr) { - return arr[arr.length - 1] - } -}; - -// another - -/** - * @param {number[]} nums - * @return {number} - */ -const minIncrementForUnique = function(nums) { - let res = 0, nxt = 0 - nums.sort((a, b) => a - b) - for(const e of nums) { - res += Math.max(0, nxt - e) - nxt = Math.max(nxt, e) + 1 - } - - return res -}; diff --git a/945.minimum-increment-to-make-array-unique.js b/945.minimum-increment-to-make-array-unique.js new file mode 100644 index 00000000..55d5fb21 --- /dev/null +++ b/945.minimum-increment-to-make-array-unique.js @@ -0,0 +1,26 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const minIncrementForUnique = function(nums) { + const seen = new Set() + const queue = [] + let res = 0 + for(const e of nums) { + if(!seen.has(e)) seen.add(e) + else queue.push(e) + } + queue.sort((a, b) => b - a) + for(let i = 0; i <= 1e5 || queue.length; i++) { + if(!seen.has(i) && i > last(queue)) { + res += i - queue.pop() + } + } + + return res + + function last(arr) { + return arr[arr.length - 1] + } +}; + diff --git a/946-validate-stack-sequences.js b/946.validate-stack-sequences.js similarity index 100% rename from 946-validate-stack-sequences.js rename to 946.validate-stack-sequences.js diff --git a/947-most-stones-removed-with-same-row-or-column.js b/947.most-stones-removed-with-same-row-or-column.js similarity index 100% rename from 947-most-stones-removed-with-same-row-or-column.js rename to 947.most-stones-removed-with-same-row-or-column.js diff --git a/948-bag-of-tokens.js b/948.bag-of-tokens.js similarity index 100% rename from 948-bag-of-tokens.js rename to 948.bag-of-tokens.js diff --git a/949-largest-time-for-given-digits.js b/949.largest-time-for-given-digits.js similarity index 100% rename from 949-largest-time-for-given-digits.js rename to 949.largest-time-for-given-digits.js diff --git a/95-unique-binary-search-trees-ii.js b/95.unique-binary-search-trees-ii.js similarity index 100% rename from 95-unique-binary-search-trees-ii.js rename to 95.unique-binary-search-trees-ii.js diff --git a/950-reveal-cards-in-increasing-order.js b/950.reveal-cards-in-increasing-order.js similarity index 100% rename from 950-reveal-cards-in-increasing-order.js rename to 950.reveal-cards-in-increasing-order.js diff --git a/951-flip-equivalent-binary-trees.js b/951.flip-equivalent-binary-trees.js similarity index 100% rename from 951-flip-equivalent-binary-trees.js rename to 951.flip-equivalent-binary-trees.js diff --git a/952-largest-component-size-by-common-factor.js b/952-largest-component-size-by-common-factor.js deleted file mode 100644 index c01f0348..00000000 --- a/952-largest-component-size-by-common-factor.js +++ /dev/null @@ -1,130 +0,0 @@ -/** - * @param {number[]} nums - * @return {number} - */ -const largestComponentSize = function (nums) { - const { sqrt } = Math - const n = nums.length - const uf = new UF(n) - const primes = {} - for (let i = 0; i < n; i++) { - const num = nums[i] - const prSet = primesSet(num) - for (const e of prSet) { - if (primes[e] == null) primes[e] = [] - primes[e].push(i) - } - } - - const vals = Object.values(primes) - for(const idxArr of vals) { - const len = idxArr.length - for(let i = 0; i < len - 1; i++) { - uf.union(idxArr[i], idxArr[i + 1]) - } - } - let res = 0 - const hash = {} - for(let i = 0; i < n; i++) { - const root = uf.find(i) - if(hash[root] == null) hash[root] = 0 - hash[root]++ - } - return Math.max(...Object.values(hash)) - - function primesSet(n) { - const limit = ~~(sqrt(n) + 1) - for (let i = 2; i < limit; i++) { - if (n % i === 0) { - const res = primesSet(n / i) - res.add(i) - return res - } - } - return new Set([n]) - } -} - -class UF { - constructor(n) { - this.root = Array(n) - .fill(null) - .map((_, i) => i) - } - find(x) { - if (this.root[x] !== x) { - this.root[x] = this.find(this.root[x]) - } - return this.root[x] - } - union(x, y) { - const xr = this.find(x) - const yr = this.find(y) - this.root[yr] = xr - } -} - -// another - - -/** - * @param {number[]} A - * @return {number} - */ -class UF { - constructor(N) { - this.parent = [] - this.size = [] - this.max = 1 - for (let i = 0; i < N; i++) { - this.parent[i] = i - this.size[i] = 1 - } - } - find(x) { - if (x === this.parent[x]) { - return x - } - return (this.parent[x] = this.find(this.parent[x])) - } - union(x, y) { - let rootX = this.find(x) - let rootY = this.find(y) - if (rootX != rootY) { - this.parent[rootX] = rootY - this.size[rootY] += this.size[rootX] - this.max = Math.max(this.max, this.size[rootY]) - } - } -} -const largestComponentSize = A => { - let N = A.length - const map = {} // key is the factor, val is the node index - const uf = new UF(N) - for (let i = 0; i < N; i++) { - let a = A[i] - for (let j = 2; j * j <= a; j++) { - if (a % j == 0) { - if (!map.hasOwnProperty(j)) { - //this means that no index has claimed the factor yet - map[j] = i - } else { - //this means that one index already claimed, so union that one with current - uf.union(i, map[j]) - } - if (!map.hasOwnProperty(a / j)) { - map[a / j] = i - } else { - uf.union(i, map[a / j]) - } - } - } - if (!map.hasOwnProperty(a)) { - //a could be factor too. Don't miss this - map[a] = i - } else { - uf.union(i, map[a]) - } - } - return uf.max -} diff --git a/952.largest-component-size-by-common-factor.js b/952.largest-component-size-by-common-factor.js new file mode 100644 index 00000000..0df178f4 --- /dev/null +++ b/952.largest-component-size-by-common-factor.js @@ -0,0 +1,66 @@ +/** + * @param {number[]} nums + * @return {number} + */ +const largestComponentSize = function (nums) { + const { sqrt } = Math + const n = nums.length + const uf = new UF(n) + const primes = {} + for (let i = 0; i < n; i++) { + const num = nums[i] + const prSet = primesSet(num) + for (const e of prSet) { + if (primes[e] == null) primes[e] = [] + primes[e].push(i) + } + } + + const vals = Object.values(primes) + for(const idxArr of vals) { + const len = idxArr.length + for(let i = 0; i < len - 1; i++) { + uf.union(idxArr[i], idxArr[i + 1]) + } + } + let res = 0 + const hash = {} + for(let i = 0; i < n; i++) { + const root = uf.find(i) + if(hash[root] == null) hash[root] = 0 + hash[root]++ + } + return Math.max(...Object.values(hash)) + + function primesSet(n) { + const limit = ~~(sqrt(n) + 1) + for (let i = 2; i < limit; i++) { + if (n % i === 0) { + const res = primesSet(n / i) + res.add(i) + return res + } + } + return new Set([n]) + } +} + +class UF { + constructor(n) { + this.root = Array(n) + .fill(null) + .map((_, i) => i) + } + find(x) { + if (this.root[x] !== x) { + this.root[x] = this.find(this.root[x]) + } + return this.root[x] + } + union(x, y) { + const xr = this.find(x) + const yr = this.find(y) + this.root[yr] = xr + } +} + diff --git a/953-verifying-an-alien-dictionary.js b/953.verifying-an-alien-dictionary.js similarity index 100% rename from 953-verifying-an-alien-dictionary.js rename to 953.verifying-an-alien-dictionary.js diff --git a/954-array-of-doubled-pairs.js b/954.array-of-doubled-pairs.js similarity index 100% rename from 954-array-of-doubled-pairs.js rename to 954.array-of-doubled-pairs.js diff --git a/955-delete-columns-to-make-sorted-ii.js b/955-delete-columns-to-make-sorted-ii.js deleted file mode 100644 index 0a9b4f52..00000000 --- a/955-delete-columns-to-make-sorted-ii.js +++ /dev/null @@ -1,67 +0,0 @@ -/** - * @param {string[]} A - * @return {number} - */ -const minDeletionSize = function (A) { - let res = 0, - i, - j //n: 有多少个字符串,对应i. m:每个字符串的长度,对应j - const n = A.length, - m = A[0].length, - sorted = new Array(n - 1).fill(false) - for (j = 0; j < m; ++j) { - //从第一个字符到最后一个字符 - for (i = 0; i < n - 1; ++i) { - //i从第一个字到最后一个字 - if (!sorted[i] && A[i].charAt(j) > A[i + 1].charAt(j)) { - res++ - break - } - } - if (i < n - 1) continue - - //假设输入是["xgag","xfba","yfac"] - //那么第一轮j=0,比较第一列: x=xf,进入if条件语句,所以res = 1, break - //然后第三轮j=2,aa,这里b虽然>a,但是由于sorted[xfb] = true,所以不会进入到上面的循环体,然后sorted[xga] = true - //然后第四轮j=3,这一轮已经不再重要,因为通过前面几轮 sorted[0] = true, sorted[1] = true, 这意味着已经实现了排序,所以res最终结果就是1 - - for ( - i = 0; - i < n - 1; - ++i //这一段代码结合最外面的循环可以用作比较string大小的通用代码 - ) - if (A[i].charAt(j) < A[i + 1].charAt(j)) sorted[i] = true - } - return res -} - -// another - -/** - * @param {string[]} A - * @return {number} - */ -const minDeletionSize = function (A) { - const set = new Set() - const m = A.length - let res = 0 - if(m === 0) return 0 - const n = A[0].length - for(j = 0; j < n; j++) { - if(set.size === m - 1) return res - for(i = 0; i < m - 1; i++) { - if(!set.has(i) && A[i][j] > A[i + 1][j]) { - res++ - break - } - } - if(i < m - 1) continue - for(i = 0; i < m - 1; i++) { - if(A[i][j] < A[i + 1][j]) set.add(i) - } - } - - return res -} - diff --git a/955.delete-columns-to-make-sorted-ii.js b/955.delete-columns-to-make-sorted-ii.js new file mode 100644 index 00000000..47629720 --- /dev/null +++ b/955.delete-columns-to-make-sorted-ii.js @@ -0,0 +1,38 @@ +/** + * @param {string[]} A + * @return {number} + */ +const minDeletionSize = function (A) { + let res = 0, + i, + j //n: 有多少个字符串,对应i. m:每个字符串的长度,对应j + const n = A.length, + m = A[0].length, + sorted = new Array(n - 1).fill(false) + for (j = 0; j < m; ++j) { + //从第一个字符到最后一个字符 + for (i = 0; i < n - 1; ++i) { + //i从第一个字到最后一个字 + if (!sorted[i] && A[i].charAt(j) > A[i + 1].charAt(j)) { + res++ + break + } + } + if (i < n - 1) continue + + //假设输入是["xgag","xfba","yfac"] + //那么第一轮j=0,比较第一列: x=xf,进入if条件语句,所以res = 1, break + //然后第三轮j=2,aa,这里b虽然>a,但是由于sorted[xfb] = true,所以不会进入到上面的循环体,然后sorted[xga] = true + //然后第四轮j=3,这一轮已经不再重要,因为通过前面几轮 sorted[0] = true, sorted[1] = true, 这意味着已经实现了排序,所以res最终结果就是1 + + for ( + i = 0; + i < n - 1; + ++i //这一段代码结合最外面的循环可以用作比较string大小的通用代码 + ) + if (A[i].charAt(j) < A[i + 1].charAt(j)) sorted[i] = true + } + return res +} + diff --git a/956-tallest-billboard.js b/956.tallest-billboard.js similarity index 100% rename from 956-tallest-billboard.js rename to 956.tallest-billboard.js diff --git a/957-prison-cells-after-n-days.js b/957.prison-cells-after-n-days.js similarity index 100% rename from 957-prison-cells-after-n-days.js rename to 957.prison-cells-after-n-days.js diff --git a/958-check-completeness-of-a-binary-tree.js b/958.check-completeness-of-a-binary-tree.js similarity index 100% rename from 958-check-completeness-of-a-binary-tree.js rename to 958.check-completeness-of-a-binary-tree.js diff --git a/959-regions-cut-by-slashes.js b/959.regions-cut-by-slashes.js similarity index 100% rename from 959-regions-cut-by-slashes.js rename to 959.regions-cut-by-slashes.js diff --git a/96-unique-binary-search-trees.js b/96-unique-binary-search-trees.js deleted file mode 100644 index 59e886d5..00000000 --- a/96-unique-binary-search-trees.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * @param {number} n - * @return {number} - */ -const numTrees = function(n) { - const arr = new Array(n + 1).fill(0) - arr[0] = arr[1] = 1 - for (let i = 2; i <= n; i++) { - for (let j = 1; j <= i; j++) { - arr[i] += arr[j - 1] * arr[i - j] - } - } - return arr[n] -} - -// another - -/** - * @param {number} n - * @return {number} - */ -const numTrees = function(n) { - const hash = { - 0: 1, - 1: 1 - } - return doNumTrees(n, hash) -} - -function doNumTrees(n, hash) { - if (hash[n]) return hash[n] - let sum = 0 - for (let i = 1; i <= n; i++) { - const left = doNumTrees(i - 1, hash) - const right = doNumTrees(n - i, hash) - sum += left * right - } - hash[n] = sum - return sum -} diff --git a/96.unique-binary-search-trees.js b/96.unique-binary-search-trees.js new file mode 100644 index 00000000..5016ca31 --- /dev/null +++ b/96.unique-binary-search-trees.js @@ -0,0 +1,15 @@ +/** + * @param {number} n + * @return {number} + */ +const numTrees = function(n) { + const arr = new Array(n + 1).fill(0) + arr[0] = arr[1] = 1 + for (let i = 2; i <= n; i++) { + for (let j = 1; j <= i; j++) { + arr[i] += arr[j - 1] * arr[i - j] + } + } + return arr[n] +} + diff --git a/960-delete-columns-to-make-sorted-iii.js b/960-delete-columns-to-make-sorted-iii.js deleted file mode 100644 index e1054b33..00000000 --- a/960-delete-columns-to-make-sorted-iii.js +++ /dev/null @@ -1,36 +0,0 @@ -/** - * @param {string[]} A - * @return {number} - */ -const minDeletionSize = function(A) { - const dp = new Array(A[0].length).fill(1) - for (let i = 0; i < A[0].length; i++) { - for (let j = 0; j < i; j++) { - for (let k = 0; k <= A.length; k++) { - if (k === A.length) dp[i] = Math.max(dp[i], dp[j] + 1) - else if (A[k][j] > A[k][i]) break - } - } - } - return A[0].length - Math.max(...dp) -} - -// another - -const minDeletionSize = function(A) { - const rows = A.length - const cols = A[0].length - let res = cols - 1 - let k - const dp = new Array(cols).fill(1) - for (let i = 0; i < cols; i++) { - for (let j = 0; j < i; j++) { - for (k = 0; k < rows; k++) { - if (A[k][j] > A[k][i]) break - } - if (k === rows && dp[j] + 1 > dp[i]) dp[i] = dp[j] + 1 - } - res = Math.min(res, cols - dp[i]) - } - return res -} diff --git a/960.delete-columns-to-make-sorted-iii.js b/960.delete-columns-to-make-sorted-iii.js new file mode 100644 index 00000000..c4787a58 --- /dev/null +++ b/960.delete-columns-to-make-sorted-iii.js @@ -0,0 +1,17 @@ +/** + * @param {string[]} A + * @return {number} + */ +const minDeletionSize = function(A) { + const dp = new Array(A[0].length).fill(1) + for (let i = 0; i < A[0].length; i++) { + for (let j = 0; j < i; j++) { + for (let k = 0; k <= A.length; k++) { + if (k === A.length) dp[i] = Math.max(dp[i], dp[j] + 1) + else if (A[k][j] > A[k][i]) break + } + } + } + return A[0].length - Math.max(...dp) +} + diff --git a/961-n-repeated-element-in-size-2n-array.js b/961.n-repeated-element-in-size-2n-array.js similarity index 100% rename from 961-n-repeated-element-in-size-2n-array.js rename to 961.n-repeated-element-in-size-2n-array.js diff --git a/964-least-operators-to-express-number.js b/964-least-operators-to-express-number.js deleted file mode 100644 index aaccd462..00000000 --- a/964-least-operators-to-express-number.js +++ /dev/null @@ -1,54 +0,0 @@ -/** - * @param {number} x - * @param {number} target - * @return {number} - */ - -const leastOpsExpressTarget = function(x, target) { - let pows = [1] - while (pows[pows.length - 1] < target) { - pows.push(pows[pows.length - 1] * x) - } - let dp = {} - for (let i = 0; i < pows.length; i++) { - dp[pows[i]] = Math.abs(i - 1) + 1 - } - let dpFunc = (t, unit) => { - if (t <= 0) return 0 - if (dp[t]) return dp[t] - let cur = t % (unit * x) - let count = dp[unit] - let pos = dpFunc(t - cur, unit * x) + (cur / unit) * count - let neg = dpFunc(t + x * unit - cur, unit * x) + (x - cur / unit) * count - dp[t] = Math.min(pos, neg) - return dp[t] - } - return dpFunc(target, 1) - 1 -} - - -// another - -const leastOpsExpressTarget = function(x, y) { - let pos = 0, - neg = 0, - k = 0, - pos2, - neg2, - cur - while (y > 0) { - cur = y % x - y = (y / x) >> 0 - if (k > 0) { - pos2 = Math.min(cur * k + pos, (cur + 1) * k + neg) - neg2 = Math.min((x - cur) * k + pos, (x - cur - 1) * k + neg) - pos = pos2 - neg = neg2 - } else { - pos = cur * 2 - neg = (x - cur) * 2 - } - k++ - } - return Math.min(pos, k + neg) - 1 -} diff --git a/964.least-operators-to-express-number.js b/964.least-operators-to-express-number.js new file mode 100644 index 00000000..ab1bb258 --- /dev/null +++ b/964.least-operators-to-express-number.js @@ -0,0 +1,29 @@ +/** + * @param {number} x + * @param {number} target + * @return {number} + */ + +const leastOpsExpressTarget = function(x, target) { + let pows = [1] + while (pows[pows.length - 1] < target) { + pows.push(pows[pows.length - 1] * x) + } + let dp = {} + for (let i = 0; i < pows.length; i++) { + dp[pows[i]] = Math.abs(i - 1) + 1 + } + let dpFunc = (t, unit) => { + if (t <= 0) return 0 + if (dp[t]) return dp[t] + let cur = t % (unit * x) + let count = dp[unit] + let pos = dpFunc(t - cur, unit * x) + (cur / unit) * count + let neg = dpFunc(t + x * unit - cur, unit * x) + (x - cur / unit) * count + dp[t] = Math.min(pos, neg) + return dp[t] + } + return dpFunc(target, 1) - 1 +} + + diff --git a/965-univalued-binary-tree.js b/965.univalued-binary-tree.js similarity index 100% rename from 965-univalued-binary-tree.js rename to 965.univalued-binary-tree.js diff --git a/967-numbers-with-same-consecutive-differences.js b/967.numbers-with-same-consecutive-differences.js similarity index 100% rename from 967-numbers-with-same-consecutive-differences.js rename to 967.numbers-with-same-consecutive-differences.js diff --git a/968-binary-tree-cameras.js b/968-binary-tree-cameras.js deleted file mode 100644 index fa629c7d..00000000 --- a/968-binary-tree-cameras.js +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {number} - */ -const minCameraCover = function(root) { - if (root === null) return 0; - let max = 0; - return (helper(root) < 1 ? 1 : 0) + max; - function helper(root) { - if (root === null) return 2; - if (root.left === null && root.right === null) return 0; - let left = helper(root.left); - let right = helper(root.right); - if (left === 0 || right === 0) { - max++; - return 1; - } - return left === 1 || right === 1 ? 2 : 0; - } -}; - - // another - -/** - * @param {TreeNode} root - * @return {number} - */ -const minCameraCover = function(root) { - let ans = 0 - const covered = new Set([null]) - dfs(root, null) - return ans - function dfs(node, parent) { - if (node) { - dfs(node.left, node) - dfs(node.right, node) - if ( - !( - (parent || covered.has(node)) && - covered.has(node.left) && - covered.has(node.right) - ) - ) { - ans += 1 - covered - .add(node) - .add(parent) - .add(node.left) - .add(node.right) - } - } - } -}; diff --git a/968.binary-tree-cameras.js b/968.binary-tree-cameras.js new file mode 100644 index 00000000..bfdb9c8e --- /dev/null +++ b/968.binary-tree-cameras.js @@ -0,0 +1,28 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {number} + */ +const minCameraCover = function(root) { + if (root === null) return 0; + let max = 0; + return (helper(root) < 1 ? 1 : 0) + max; + function helper(root) { + if (root === null) return 2; + if (root.left === null && root.right === null) return 0; + let left = helper(root.left); + let right = helper(root.right); + if (left === 0 || right === 0) { + max++; + return 1; + } + return left === 1 || right === 1 ? 2 : 0; + } +}; + diff --git a/969-pancake-sorting.js b/969.pancake-sorting.js similarity index 100% rename from 969-pancake-sorting.js rename to 969.pancake-sorting.js diff --git a/97-interleaving-string.js b/97.interleaving-string.js similarity index 100% rename from 97-interleaving-string.js rename to 97.interleaving-string.js diff --git a/971-flip-binary-tree-to-match-preorder-traversal.js b/971.flip-binary-tree-to-match-preorder-traversal.js similarity index 100% rename from 971-flip-binary-tree-to-match-preorder-traversal.js rename to 971.flip-binary-tree-to-match-preorder-traversal.js diff --git a/972-equal-rational-numbers.js b/972.equal-rational-numbers.js similarity index 100% rename from 972-equal-rational-numbers.js rename to 972.equal-rational-numbers.js diff --git a/973-k-closest-points-to-origin.js b/973-k-closest-points-to-origin.js deleted file mode 100644 index b02f1611..00000000 --- a/973-k-closest-points-to-origin.js +++ /dev/null @@ -1,168 +0,0 @@ -/** - * @param {number[][]} points - * @param {number} K - * @return {number[][]} - */ -const kClosest = (points, K) => { - let len = points.length, - l = 0, - r = len - 1 - while (l <= r) { - let mid = helper(points, l, r) - if (mid === K) break - if (mid < K) { - l = mid + 1 - } else { - r = mid - 1 - } - } - return points.slice(0, K) -} - -function helper(A, l, r) { - let pivot = A[l] - let ll = l - while (l < r) { - while (l < r && compare(A[r], pivot) >= 0) r-- - while (l < r && compare(A[l], pivot) <= 0) l++ - swap(A, l, r) - } - swap(A, ll, l) - return l -} -function swap(arr, i, j) { - let tmp = arr[i] - arr[i] = arr[j] - arr[j] = tmp -} - -function compare(p1, p2) { - return p1[0] * p1[0] + p1[1] * p1[1] - p2[0] * p2[0] - p2[1] * p2[1] -} - - -// another - -/** - * @param {number[][]} points - * @param {number} K - * @return {number[][]} - */ -const kClosest = (points, K) => { - const pq = new PriorityQueue( - (p1, p2) => p1[0] * p1[0] + p1[1] * p1[1] > p2[0] * p2[0] + p2[1] * p2[1] - ) - for (let p of points) { - pq.push(p) - if (pq.size() > K) { - pq.pop() - } - } - const res = new Array(K) - while (K > 0) { - res[--K] = pq.pop() - } - return res -} - -class PriorityQueue { - constructor(comparator = (a, b) => a > b) { - this.heap = [] - this.top = 0 - this.comparator = comparator - } - size() { - return this.heap.length - } - isEmpty() { - return this.size() === 0 - } - peek() { - return this.heap[this.top] - } - push(...values) { - values.forEach((value) => { - this.heap.push(value) - this.siftUp() - }) - return this.size() - } - pop() { - const poppedValue = this.peek() - const bottom = this.size() - 1 - if (bottom > this.top) { - this.swap(this.top, bottom) - } - this.heap.pop() - this.siftDown() - return poppedValue - } - replace(value) { - const replacedValue = this.peek() - this.heap[this.top] = value - this.siftDown() - return replacedValue - } - - parent = (i) => ((i + 1) >>> 1) - 1 - left = (i) => (i << 1) + 1 - right = (i) => (i + 1) << 1 - greater = (i, j) => this.comparator(this.heap[i], this.heap[j]) - swap = (i, j) => ([this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]) - siftUp = () => { - let node = this.size() - 1 - while (node > this.top && this.greater(node, this.parent(node))) { - this.swap(node, this.parent(node)) - node = this.parent(node) - } - } - siftDown = () => { - let node = this.top - while ( - (this.left(node) < this.size() && this.greater(this.left(node), node)) || - (this.right(node) < this.size() && this.greater(this.right(node), node)) - ) { - let maxChild = - this.right(node) < this.size() && - this.greater(this.right(node), this.left(node)) - ? this.right(node) - : this.left(node) - this.swap(node, maxChild) - node = maxChild - } - } -} - -// another - -/** - * @param {number[][]} points - * @param {number} k - * @return {number[][]} - */ -const kClosest = function(points, k) { - let len = points.length, l = 0, r = len - 1 - while (l <= r) { - let mid = helper(points, l, r) - if (mid === k) break - if (mid < k) l = mid + 1 - else r = mid - 1 - } - return points.slice(0, k) - - function helper(arr, l, r) { - const pivot = arr[l] - while(l < r) { - while(l < r && cmp(arr[r], pivot) >= 0) r-- - arr[l] = arr[r] - while(l < r && cmp(arr[l], pivot) <= 0) l++ - arr[r] = arr[l] - } - arr[l] = pivot - return l - } - - function cmp(a, b) { - return a[0] * a[0] + a[1] * a[1] - b[0] * b[0] - b[1] * b[1] - } -}; diff --git a/973.k-closest-points-to-origin.js b/973.k-closest-points-to-origin.js new file mode 100644 index 00000000..915fae11 --- /dev/null +++ b/973.k-closest-points-to-origin.js @@ -0,0 +1,43 @@ +/** + * @param {number[][]} points + * @param {number} K + * @return {number[][]} + */ +const kClosest = (points, K) => { + let len = points.length, + l = 0, + r = len - 1 + while (l <= r) { + let mid = helper(points, l, r) + if (mid === K) break + if (mid < K) { + l = mid + 1 + } else { + r = mid - 1 + } + } + return points.slice(0, K) +} + +function helper(A, l, r) { + let pivot = A[l] + let ll = l + while (l < r) { + while (l < r && compare(A[r], pivot) >= 0) r-- + while (l < r && compare(A[l], pivot) <= 0) l++ + swap(A, l, r) + } + swap(A, ll, l) + return l +} +function swap(arr, i, j) { + let tmp = arr[i] + arr[i] = arr[j] + arr[j] = tmp +} + +function compare(p1, p2) { + return p1[0] * p1[0] + p1[1] * p1[1] - p2[0] * p2[0] - p2[1] * p2[1] +} + + diff --git a/974-subarray-sums-divisible-by-k.js b/974-subarray-sums-divisible-by-k.js deleted file mode 100644 index 26306870..00000000 --- a/974-subarray-sums-divisible-by-k.js +++ /dev/null @@ -1,35 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const subarraysDivByK = function (nums, k) { - const memo = {0: 1} - let sum = 0, res = 0 - for(const e of nums) { - sum += e - const remain = ( sum % k + k) % k - res += memo[remain] ?? 0 - memo[remain] = (memo[remain] ?? 0) + 1 - } - return res -} - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const subarraysDivByK = function(nums, k) { - const memo = {0: 1} - let sum = 0, res = 0 - for(const e of nums) { - sum += e - const remain = (k - (sum % k)) % k - res += memo[remain] ?? 0 - memo[remain] = (memo[remain] ?? 0) + 1 - } - return res -}; diff --git a/974.subarray-sums-divisible-by-k.js b/974.subarray-sums-divisible-by-k.js new file mode 100644 index 00000000..12688369 --- /dev/null +++ b/974.subarray-sums-divisible-by-k.js @@ -0,0 +1,17 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const subarraysDivByK = function (nums, k) { + const memo = {0: 1} + let sum = 0, res = 0 + for(const e of nums) { + sum += e + const remain = ( sum % k + k) % k + res += memo[remain] ?? 0 + memo[remain] = (memo[remain] ?? 0) + 1 + } + return res +} + diff --git a/975-odd-even-jump.js b/975.odd-even-jump.js similarity index 100% rename from 975-odd-even-jump.js rename to 975.odd-even-jump.js diff --git a/976-largest-perimeter-triangle.js b/976.largest-perimeter-triangle.js similarity index 100% rename from 976-largest-perimeter-triangle.js rename to 976.largest-perimeter-triangle.js diff --git a/977-squares-of-a-sorted-array.js b/977.squares-of-a-sorted-array.js similarity index 100% rename from 977-squares-of-a-sorted-array.js rename to 977.squares-of-a-sorted-array.js diff --git a/978-longest-turbulent-subarray.js b/978.longest-turbulent-subarray.js similarity index 100% rename from 978-longest-turbulent-subarray.js rename to 978.longest-turbulent-subarray.js diff --git a/979-distribute-coins-in-binary-tree.js b/979.distribute-coins-in-binary-tree.js similarity index 100% rename from 979-distribute-coins-in-binary-tree.js rename to 979.distribute-coins-in-binary-tree.js diff --git a/98-validate-binary-search-tree.js b/98.validate-binary-search-tree.js similarity index 100% rename from 98-validate-binary-search-tree.js rename to 98.validate-binary-search-tree.js diff --git a/980-unique-paths-iii.js b/980.unique-paths-iii.js similarity index 100% rename from 980-unique-paths-iii.js rename to 980.unique-paths-iii.js diff --git a/981-time-based-key-value-store.js b/981-time-based-key-value-store.js deleted file mode 100644 index 67101e69..00000000 --- a/981-time-based-key-value-store.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Initialize your data structure here. - */ -const TimeMap = function() { - this.hash = {} -}; - -/** - * @param {string} key - * @param {string} value - * @param {number} timestamp - * @return {void} - */ -TimeMap.prototype.set = function(key, value, timestamp) { - if(this.hash[key] == null) this.hash[key] = [] - this.hash[key].push([value, timestamp]) -}; - -/** - * @param {string} key - * @param {number} timestamp - * @return {string} - */ -TimeMap.prototype.get = function(key, timestamp) { - if(this.hash[key] == null) return '' - const arr = this.hash[key] - - let l = 0, r = arr.length - 1; - while(l <= r) { - const pick = Math.floor((l + r) / 2); - if (arr[pick][1] < timestamp) { - l = pick + 1; - } else if (arr[pick][1] > timestamp) { - r = pick - 1 - } else { - return arr[pick][0]; - } - } - return arr[r]?.[0] || '' -}; - -/** - * Your TimeMap object will be instantiated and called as such: - * var obj = new TimeMap() - * obj.set(key,value,timestamp) - * var param_2 = obj.get(key,timestamp) - */ - -// another - -/** - * Initialize your data structure here. - */ -const TimeMap = function() { - this.hash = {} -}; - -/** - * @param {string} key - * @param {string} value - * @param {number} timestamp - * @return {void} - */ -TimeMap.prototype.set = function(key, value, timestamp) { - if(this.hash[key] == null) this.hash[key] = [] - this.hash[key].push([value, timestamp]) -}; - -/** - * @param {string} key - * @param {number} timestamp - * @return {string} - */ -TimeMap.prototype.get = function(key, timestamp) { - if(this.hash[key] == null) return '' - const arr = this.hash[key] - - let l = 0, r = arr.length - while(l < r) { - const mid = l + ((r - l) >> 1) - if(arr[mid][1] <= timestamp) { - l = mid + 1 - } else { - r = mid - } - } - - if(r === 0) return '' - return arr[r - 1][0] -}; - -/** - * Your TimeMap object will be instantiated and called as such: - * var obj = new TimeMap() - * obj.set(key,value,timestamp) - * var param_2 = obj.get(key,timestamp) - */ diff --git a/981.time-based-key-value-store.js b/981.time-based-key-value-store.js new file mode 100644 index 00000000..34b06332 --- /dev/null +++ b/981.time-based-key-value-store.js @@ -0,0 +1,48 @@ +/** + * Initialize your data structure here. + */ +const TimeMap = function() { + this.hash = {} +}; + +/** + * @param {string} key + * @param {string} value + * @param {number} timestamp + * @return {void} + */ +TimeMap.prototype.set = function(key, value, timestamp) { + if(this.hash[key] == null) this.hash[key] = [] + this.hash[key].push([value, timestamp]) +}; + +/** + * @param {string} key + * @param {number} timestamp + * @return {string} + */ +TimeMap.prototype.get = function(key, timestamp) { + if(this.hash[key] == null) return '' + const arr = this.hash[key] + + let l = 0, r = arr.length - 1; + while(l <= r) { + const pick = Math.floor((l + r) / 2); + if (arr[pick][1] < timestamp) { + l = pick + 1; + } else if (arr[pick][1] > timestamp) { + r = pick - 1 + } else { + return arr[pick][0]; + } + } + return arr[r]?.[0] || '' +}; + +/** + * Your TimeMap object will be instantiated and called as such: + * var obj = new TimeMap() + * obj.set(key,value,timestamp) + * var param_2 = obj.get(key,timestamp) + */ + diff --git a/982-triples-with-bitwise-and-equal-to-zero.js b/982.triples-with-bitwise-and-equal-to-zero.js similarity index 100% rename from 982-triples-with-bitwise-and-equal-to-zero.js rename to 982.triples-with-bitwise-and-equal-to-zero.js diff --git a/983-minimum-cost-for-tickets.js b/983.minimum-cost-for-tickets.js similarity index 100% rename from 983-minimum-cost-for-tickets.js rename to 983.minimum-cost-for-tickets.js diff --git a/984-string-without-aaa-or-bbb.js b/984-string-without-aaa-or-bbb.js deleted file mode 100644 index b5996159..00000000 --- a/984-string-without-aaa-or-bbb.js +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @param {number} a - * @param {number} b - * @return {string} - */ -const strWithout3a3b = function (a, b) { - let res = '' - - while(a > 0 || b > 0) { - if(endsWith(res, 'aa')) { - res += 'b' - b-- - } else if(endsWith(res, 'bb')) { - res += 'a' - a-- - } else if(a >= b) { - res += 'a' - a-- - } else { - res += 'b' - b-- - } - } - - return res - - function endsWith(str, sub) { - let i = str.length - 1, j = sub.length - 1 - for(; i >=0 && j >= 0;i--,j--) { - if(str[i] !== sub[j]) return false - } - if(j >= 0) return false - - return true - } -} - -// another - - -/** - * @param {number} a - * @param {number} b - * @return {string} - */ -const strWithout3a3b = function(a, b) { - let m = a, n = b, ch1 = 'a', ch2 = 'b' - if(b > a) { - m = b, n = a, ch1 = 'b', ch2 = 'a' - } - let res = '' - while(m-- > 0) { - res += ch1 - if(m > n) { - res += ch1 - m-- - } - if(n > 0) { - res += ch2 - n-- - } - } - return res -}; - -// another - -/** - * @param {number} a - * @param {number} b - * @return {string} - */ -const strWithout3a3b = function (a, b, ac = 'a', bc = 'b') { - const delta = a - b - let res = '' - if (delta < 0) { - return strWithout3a3b(b, a, 'b', 'a') - } else { - while(a-- > 0) { - res += ac - if(a > b) res += ac, a-- - if(b-- > 0) res += bc - } - } - - return res -} diff --git a/984.string-without-aaa-or-bbb.js b/984.string-without-aaa-or-bbb.js new file mode 100644 index 00000000..1bae95b5 --- /dev/null +++ b/984.string-without-aaa-or-bbb.js @@ -0,0 +1,37 @@ +/** + * @param {number} a + * @param {number} b + * @return {string} + */ +const strWithout3a3b = function (a, b) { + let res = '' + + while(a > 0 || b > 0) { + if(endsWith(res, 'aa')) { + res += 'b' + b-- + } else if(endsWith(res, 'bb')) { + res += 'a' + a-- + } else if(a >= b) { + res += 'a' + a-- + } else { + res += 'b' + b-- + } + } + + return res + + function endsWith(str, sub) { + let i = str.length - 1, j = sub.length - 1 + for(; i >=0 && j >= 0;i--,j--) { + if(str[i] !== sub[j]) return false + } + if(j >= 0) return false + + return true + } +} + diff --git a/985-sum-of-even-numbers-after-queries.js b/985-sum-of-even-numbers-after-queries.js deleted file mode 100644 index cfd5693d..00000000 --- a/985-sum-of-even-numbers-after-queries.js +++ /dev/null @@ -1,33 +0,0 @@ -/** - * @param {number[]} A - * @param {number[][]} queries - * @return {number[]} - */ -const sumEvenAfterQueries = function(A, queries) { - const res = [] - for(let i = 0; i < queries.length; i++) { - A[queries[i][1]] += queries[i][0] - res.push(sum(A)) - } - return res -}; - -function sum(arr) { - return arr.reduce((ac, el) => ac + (el % 2 === 0 ? el : 0), 0) -} - -// another, better - -const sumEvenAfterQueries = function(A, queries) { - let sum = A.reduce((acc, cur) => cur%2 == 0 ? acc + cur : acc, 0); - return queries.map((q) => { - let i = q[1]; - let s = A[i] + q[0]; - if(s%2 === 0) { - sum += q[0]; - if(A[i]%2 !== 0) sum += A[i]; - } else if(A[i]%2 === 0) sum -= A[i]; - A[i] = s; - return sum; - }); -}; diff --git a/985.sum-of-even-numbers-after-queries.js b/985.sum-of-even-numbers-after-queries.js new file mode 100644 index 00000000..49e78140 --- /dev/null +++ b/985.sum-of-even-numbers-after-queries.js @@ -0,0 +1,18 @@ +/** + * @param {number[]} A + * @param {number[][]} queries + * @return {number[]} + */ +const sumEvenAfterQueries = function(A, queries) { + const res = [] + for(let i = 0; i < queries.length; i++) { + A[queries[i][1]] += queries[i][0] + res.push(sum(A)) + } + return res +}; + +function sum(arr) { + return arr.reduce((ac, el) => ac + (el % 2 === 0 ? el : 0), 0) +} + diff --git a/986-interval-list-intersections.js b/986.interval-list-intersections.js similarity index 100% rename from 986-interval-list-intersections.js rename to 986.interval-list-intersections.js diff --git a/987-vertical-order-traversal-of-a-binary-tree.js b/987.vertical-order-traversal-of-a-binary-tree.js similarity index 100% rename from 987-vertical-order-traversal-of-a-binary-tree.js rename to 987.vertical-order-traversal-of-a-binary-tree.js diff --git a/988-smallest-string-starting-from-leaf.js b/988-smallest-string-starting-from-leaf.js deleted file mode 100644 index 9ee8c1d1..00000000 --- a/988-smallest-string-starting-from-leaf.js +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {string} - */ -const smallestFromLeaf = function(root) { - const res = [] - chk(root, [], res) - res.sort() - return res[0] -}; - -function chk(node, path, res) { - if(node == null) return - path.push(node.val) - if(node.left == null && node.right == null) { - res.push(arrToStr( path.slice(0).reverse() )) - return - } - chk(node.left, path.slice(0), res) - chk(node.right, path.slice(0), res) -} - -function numToChar(num) { - const str = 'abcdefghijklmnopqrstuvwxyz' - return str[num] -} - -function arrToStr(arr) { - let res = '' - for(let i = 0; i < arr.length; i++) { - res += numToChar(arr[i]) - } - return res -} - -// another - -const smallestFromLeaf = function(root) { - if (!root) return '' - const char = String.fromCharCode(97 + root.val) - let left = smallestFromLeaf(root.left) - let right = smallestFromLeaf(root.right) - if (!left) return right + char - if (!right) return left + char - return (left < right ? left : right) + char -}; diff --git a/988.smallest-string-starting-from-leaf.js b/988.smallest-string-starting-from-leaf.js new file mode 100644 index 00000000..38fbba88 --- /dev/null +++ b/988.smallest-string-starting-from-leaf.js @@ -0,0 +1,42 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {string} + */ +const smallestFromLeaf = function(root) { + const res = [] + chk(root, [], res) + res.sort() + return res[0] +}; + +function chk(node, path, res) { + if(node == null) return + path.push(node.val) + if(node.left == null && node.right == null) { + res.push(arrToStr( path.slice(0).reverse() )) + return + } + chk(node.left, path.slice(0), res) + chk(node.right, path.slice(0), res) +} + +function numToChar(num) { + const str = 'abcdefghijklmnopqrstuvwxyz' + return str[num] +} + +function arrToStr(arr) { + let res = '' + for(let i = 0; i < arr.length; i++) { + res += numToChar(arr[i]) + } + return res +} + diff --git a/989-add-to-array-form-of-integer.js b/989.add-to-array-form-of-integer.js similarity index 100% rename from 989-add-to-array-form-of-integer.js rename to 989.add-to-array-form-of-integer.js diff --git a/99-recover-binary-search-tree.js b/99-recover-binary-search-tree.js deleted file mode 100644 index 0a197248..00000000 --- a/99-recover-binary-search-tree.js +++ /dev/null @@ -1,82 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @return {void} Do not return anything, modify root in-place instead. - */ -const recoverTree = function(root) { - let node1, node2; - let prev = new TreeNode(-Infinity); - traverse(root); - swap(node1, node2) - - function traverse(node) { - if (!node) return; - traverse(node.left); - if (node.val < prev.val) { - node2 = node; - if (!node1) node1 = prev; - } - prev = node; - traverse(node.right); - } - - function swap(node1, node2) { - let temp = node1.val - node1.val = node2.val - node2.val = temp - } -} - -// another - -const recoverTree = function(root) { - const eNodes = []; - if (root == null) return; - let current = root; - let pre; - let previous = null; - while (current != null) { - if (current.left == null) { - if (previous != null && previous.val > current.val) { - eNodes.push(previous); - eNodes.push(current); - } - previous = current; - current = current.right; - } else { - pre = current.left; - while (pre.right != null && pre.right.val != current.val) { - pre = pre.right; - } - - if (pre.right == null) { - pre.right = current; - current = current.left; - } else { - if (previous != null && previous.val > current.val) { - eNodes.push(previous); - eNodes.push(current); - } - pre.right = null; - previous = current; - current = current.right; - } - } - } - if (eNodes.length == 2) { - pre = eNodes[0]; - current = eNodes[1]; - } else { - pre = eNodes[0]; - current = eNodes[3]; - } - let temp = pre.val; - pre.val = current.val; - current.val = temp; -}; diff --git a/99.recover-binary-search-tree.js b/99.recover-binary-search-tree.js new file mode 100644 index 00000000..fbc4b395 --- /dev/null +++ b/99.recover-binary-search-tree.js @@ -0,0 +1,35 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ +/** + * @param {TreeNode} root + * @return {void} Do not return anything, modify root in-place instead. + */ +const recoverTree = function(root) { + let node1, node2; + let prev = new TreeNode(-Infinity); + traverse(root); + swap(node1, node2) + + function traverse(node) { + if (!node) return; + traverse(node.left); + if (node.val < prev.val) { + node2 = node; + if (!node1) node1 = prev; + } + prev = node; + traverse(node.right); + } + + function swap(node1, node2) { + let temp = node1.val + node1.val = node2.val + node2.val = temp + } +} + diff --git a/990-satisfiability-of-equality-equations.js b/990-satisfiability-of-equality-equations.js deleted file mode 100644 index 8c1a6c76..00000000 --- a/990-satisfiability-of-equality-equations.js +++ /dev/null @@ -1,63 +0,0 @@ -/** - * @param {string[]} equations - * @return {boolean} - */ -const equationsPossible = function(equations) { - const uf = new Array(26).fill(0); - const aCode = ('a').charCodeAt(0) - - for (let i = 0; i < 26; ++i) uf[i] = i; - for (let e of equations) - if (e.charAt(1) === '=') - uf[find(e.charCodeAt(0) - aCode)] = find(e.charCodeAt(3) - aCode); - for (let e of equations) - if (e.charAt(1) === '!' && find(e.charCodeAt(0) - aCode) === find(e.charCodeAt(3) - aCode)) - return false; - return true; - - - function find(x) { - if (x != uf[x]) uf[x] = find(uf[x]); - return uf[x]; - } -}; - - -// another - -/** - * @param {string[]} equations - * @return {boolean} - */ -const equationsPossible = function(equations) { - const num = 26 - const visited = new Array(num).fill(false) - const color = new Array(num).fill(-1) - const adj = Array.from(new Array(num), el => []) - const aCode = ('a').charCodeAt(0) - for(let el of equations) { - if(el[1] === '=') { - adj[el[0].charCodeAt(0) - aCode].push(el[3].charCodeAt(0) - aCode) - adj[el[3].charCodeAt(0) - aCode].push(el[0].charCodeAt(0) - aCode) - } - } - let c = 0 - for(let i = 0; i < num; i++) { - !visited[i] && dfs(i, c) - c++ - } - for(let el of equations) { - if(el[1] === '!' && color[el[0].charCodeAt(0) - aCode] === color[el[3].charCodeAt(0) - aCode]) { - return false - } - } - return true - - function dfs(idx, val) { - visited[idx] = true - color[idx] = val - for(let el of adj[idx]) { - !visited[el] && dfs(el, val) - } - } -}; diff --git a/990.satisfiability-of-equality-equations.js b/990.satisfiability-of-equality-equations.js new file mode 100644 index 00000000..a489269d --- /dev/null +++ b/990.satisfiability-of-equality-equations.js @@ -0,0 +1,25 @@ +/** + * @param {string[]} equations + * @return {boolean} + */ +const equationsPossible = function(equations) { + const uf = new Array(26).fill(0); + const aCode = ('a').charCodeAt(0) + + for (let i = 0; i < 26; ++i) uf[i] = i; + for (let e of equations) + if (e.charAt(1) === '=') + uf[find(e.charCodeAt(0) - aCode)] = find(e.charCodeAt(3) - aCode); + for (let e of equations) + if (e.charAt(1) === '!' && find(e.charCodeAt(0) - aCode) === find(e.charCodeAt(3) - aCode)) + return false; + return true; + + + function find(x) { + if (x != uf[x]) uf[x] = find(uf[x]); + return uf[x]; + } +}; + + diff --git a/992-subarrays-with-k-different-integers.js b/992-subarrays-with-k-different-integers.js deleted file mode 100644 index f597e751..00000000 --- a/992-subarrays-with-k-different-integers.js +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const subarraysWithKDistinct = function(nums, k) { - return mostK(k) - mostK(k - 1) - function mostK(limit) { - const map = new Map() - let i = 0, j = 0, res = 0 - const n = nums.length - for(; j< n; j++) { - const e = nums[j] - map.set(e, (map.get(e) || 0) + 1) - while(map.size > limit) { - const tmp = nums[i] - map.set(tmp, (map.get(tmp) || 0) - 1) - if(map.get(tmp) === 0) map.delete(tmp) - i++ - } - res += j - i + 1 - } - - return res - } -}; - -// another - -/** - * @param {number[]} A - * @param {number} K - * @return {number} - */ -const subarraysWithKDistinct = function(A, K) { - let res = 0 - let prefix = 0 - const m = new Array(A.length + 1).fill(0) - for (let i = 0, j = 0, cnt = 0, len = A.length; i < len; i++) { - if (m[A[i]]++ === 0) cnt++ - if (cnt > K) { - m[A[j++]]-- - cnt-- - prefix = 0 - } - while (m[A[j]] > 1) { - prefix++ - m[A[j++]]-- - } - if (cnt === K) res += prefix + 1 - } - return res -} - -// another - -/** - * @param {number[]} A - * @param {number} K - * @return {number} - */ -const subarraysWithKDistinct = function (A, K) { - return mostK(K) - mostK(K - 1) - function mostK(num) { - const m = {}, len = A.length - let i = 0, j = 0, res = 0 - for(j = 0; j < len; j++) { - if(!m[A[j]]) m[A[j]] = 0, num-- - m[A[j]]++ - while(num < 0) { - m[A[i]]-- - if(!m[A[i]]) num++ - i++ - } - res += j - i + 1 - } - return res - } -} - diff --git a/992.subarrays-with-k-different-integers.js b/992.subarrays-with-k-different-integers.js new file mode 100644 index 00000000..c88ad6b8 --- /dev/null +++ b/992.subarrays-with-k-different-integers.js @@ -0,0 +1,27 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const subarraysWithKDistinct = function(nums, k) { + return mostK(k) - mostK(k - 1) + function mostK(limit) { + const map = new Map() + let i = 0, j = 0, res = 0 + const n = nums.length + for(; j< n; j++) { + const e = nums[j] + map.set(e, (map.get(e) || 0) + 1) + while(map.size > limit) { + const tmp = nums[i] + map.set(tmp, (map.get(tmp) || 0) - 1) + if(map.get(tmp) === 0) map.delete(tmp) + i++ + } + res += j - i + 1 + } + + return res + } +}; + diff --git a/993.cousins-in-binary-tree.js b/993.cousins-in-binary-tree.js deleted file mode 100644 index 82cbd579..00000000 --- a/993.cousins-in-binary-tree.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Definition for a binary tree node. - * function TreeNode(val, left, right) { - * this.val = (val===undefined ? 0 : val) - * this.left = (left===undefined ? null : left) - * this.right = (right===undefined ? null : right) - * } - */ -/** - * @param {TreeNode} root - * @param {number} x - * @param {number} y - * @return {boolean} - */ -const isCousins = (root, x, y, depth = 1, P = {}, D = {}) => { - let q = [root] - while (q.length) { - let K = q.length - while (K--) { - let p = q.shift() - if (p.left) { - if (p.left.val === x) (P.x = p.val), (D.x = depth) - if (p.left.val === y) (P.y = p.val), (D.y = depth) - q.push(p.left) - } - if (p.right) { - if (p.right.val === x) (P.x = p.val), (D.x = depth) - if (p.right.val === y) (P.y = p.val), (D.y = depth) - q.push(p.right) - } - } - ++depth - } - return P.x !== P.y && D.x === D.y -} - - -// another - -/** - * Definition for a binary tree node. - * function TreeNode(val) { - * this.val = val; - * this.left = this.right = null; - * } - */ -/** - * @param {TreeNode} root - * @param {number} x - * @param {number} y - * @return {boolean} - */ -const isCousins = function(root, x, y) { - if(root == null) return false - const res = [] - chk(root, x, [], res) - chk(root, y, [], res) - if(res.length < 2) return false - return chkRes(res, x, y) -}; -function chkRes(arr, x, y) { - let ci = 0, xi = -1, yi = -1 - let len = Math.max(arr[0].length, arr[1].length) - for(let i = 0; i < len; i++) { - if(arr[0][i] === arr[1][i]) ci = i - if(arr[0][i] === x || arr[1][i] === x) xi = i - if(arr[0][i] === y || arr[1][i] === y) yi = i - } - if(xi - yi === 0 && xi - ci > 1) { - return true - } else { - return false - } -} - -function chk(node, val, path, res) { - if(node == null) return - path.push(node.val) - if(node.val === val) { - res.push(path.slice(0)) - return - } - chk(node.left, val, path.slice(0), res) - chk(node.right, val, path.slice(0), res) -} diff --git a/993.cousins.in-binary-tree.js b/993.cousins.in-binary-tree.js new file mode 100644 index 00000000..002702f0 --- /dev/null +++ b/993.cousins.in-binary-tree.js @@ -0,0 +1,37 @@ +/** + * Definition for a binary tree node. + * function TreeNode(val, left, right) { + * this.val = (val===undefined ? 0 : val) + * this.left = (left===undefined ? null : left) + * this.right = (right===undefined ? null : right) + * } + */ +/** + * @param {TreeNode} root + * @param {number} x + * @param {number} y + * @return {boolean} + */ +const isCousins = (root, x, y, depth = 1, P = {}, D = {}) => { + let q = [root] + while (q.length) { + let K = q.length + while (K--) { + let p = q.shift() + if (p.left) { + if (p.left.val === x) (P.x = p.val), (D.x = depth) + if (p.left.val === y) (P.y = p.val), (D.y = depth) + q.push(p.left) + } + if (p.right) { + if (p.right.val === x) (P.x = p.val), (D.x = depth) + if (p.right.val === y) (P.y = p.val), (D.y = depth) + q.push(p.right) + } + } + ++depth + } + return P.x !== P.y && D.x === D.y +} + + diff --git a/994-rotting-oranges.js b/994-rotting-oranges.js deleted file mode 100644 index 2fa9a406..00000000 --- a/994-rotting-oranges.js +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @param {number[][]} grid - * @return {number} - */ -const orangesRotting = function(grid) { - const m = grid.length, n = grid[0].length - const dirs = [[-1, 0], [1, 0], [0, -1], [0, 1]] - const visited = new Set() - let q = [] - let num = 0 - for(let i = 0; i < m; i++) { - for(let j = 0; j < n; j++) { - if(grid[i][j] === 2) q.push([i, j]), visited.add(`${i},${j}`) - if(grid[i][j] !== 0) num++ - } - } - let res = 0 - while(q.length) { - const size = q.length - const tmp = [] - for(let i = 0; i < size; i++) { - const [x, y] = q[i] - for(let [dx, dy] of dirs) { - const nx = x + dx, ny = y + dy - if(nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] === 1 && !visited.has(`${nx},${ny}`)) { - tmp.push([nx, ny]) - visited.add(`${nx},${ny}`) - } - } - } - q = tmp - if(q.length) res++ - } - return visited.size === num ? res : -1 -}; - -// another - - -/** - * @param {number[][]} grid - * @return {number} - */ -const orangesRotting = function(grid) { - let count = 0 - const p = {s: 2} - const rows = grid.length - const cols = grid[0].length - while(!chk(grid, rows, cols)) { - loop(grid, rows, cols, p) - count++ - if(count> rows * cols) return -1 - } - - return count -}; - -function loop(grid, rows, cols, p) { - let cur = p.s - let next = cur + 1 - for(let i = 0; i < rows; i++) { - for(let j = 0; j < cols; j++) { - if(grid[i][j] === cur) rotten(i, j, grid, next) - } - } - p.s += 1 -} - -function rotten(row, col, grid, p) { - if(grid[row] && col > 0 && grid[row][col - 1] === 1) grid[row][col - 1] = p - if(grid[row] && col < (grid[0] || []).length - 1 && grid[row][col + 1] === 1) grid[row][col + 1] = p - if(grid[row] && row > 0 && grid[row - 1][col] === 1) grid[row - 1][col] = p - if(grid[row] && row < grid.length - 1 && grid[row + 1][col] === 1) grid[row + 1][col] = p -} - -function chk(grid, rows, cols) { - for(let i = 0; i < rows; i++) { - for(let j = 0; j < cols; j++) { - if(grid[i][j] === 1) return false - } - } - return true -} diff --git a/994.rotting-oranges.js b/994.rotting-oranges.js new file mode 100644 index 00000000..6a3c972c --- /dev/null +++ b/994.rotting-oranges.js @@ -0,0 +1,36 @@ +/** + * @param {number[][]} grid + * @return {number} + */ +const orangesRotting = function(grid) { + const m = grid.length, n = grid[0].length + const dirs = [[-1, 0], [1, 0], [0, -1], [0, 1]] + const visited = new Set() + let q = [] + let num = 0 + for(let i = 0; i < m; i++) { + for(let j = 0; j < n; j++) { + if(grid[i][j] === 2) q.push([i, j]), visited.add(`${i},${j}`) + if(grid[i][j] !== 0) num++ + } + } + let res = 0 + while(q.length) { + const size = q.length + const tmp = [] + for(let i = 0; i < size; i++) { + const [x, y] = q[i] + for(let [dx, dy] of dirs) { + const nx = x + dx, ny = y + dy + if(nx >= 0 && nx < m && ny >= 0 && ny < n && grid[nx][ny] === 1 && !visited.has(`${nx},${ny}`)) { + tmp.push([nx, ny]) + visited.add(`${nx},${ny}`) + } + } + } + q = tmp + if(q.length) res++ + } + return visited.size === num ? res : -1 +}; + diff --git a/995-minimum-number-of-k-consecutive-bit-flips.js b/995-minimum-number-of-k-consecutive-bit-flips.js deleted file mode 100644 index 90a4ad92..00000000 --- a/995-minimum-number-of-k-consecutive-bit-flips.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const minKBitFlips = function(nums, k) { - let cur = 0, res = 0 - const n = nums.length - for(let i = 0; i < n; i++) { - if(i >= k && nums[i - k] === 2) cur-- - if(cur % 2 === nums[i]) { - if(i + k > n) return -1 - nums[i] = 2 - cur++ - res++ - } - } - return res -}; - -// another - -/** - * @param {number[]} A - * @param {number} K - * @return {number} - */ -const minKBitFlips = function(A, K) { - let cur = 0, res = 0; - for (let i = 0; i < A.length; ++i) { - if (i >= K) cur -= (A[i - K] / 2) >> 0; - if ((cur & 1 ^ A[i]) === 0) { - if (i + K > A.length) return -1; - A[i] += 2; - cur++; - res++; - } - } - return res; -}; - -// another - -/** - * @param {number[]} nums - * @param {number} k - * @return {number} - */ -const minKBitFlips = function(nums, k) { - const n = nums.length, q = [] - let res = 0 - for(let i = 0; i < n; i++) { - if(nums[i] === 0) { - if(q.length === 0 || q.length % 2 === 0) { - res++ - q.push(i + k - 1) - } - } else { - if(q.length % 2 === 1) { - res++ - q.push(i + k - 1) - } - } - if(q.length && i >= q[0]) q.shift() - } - return q.length ? -1 : res -}; - diff --git a/995.minimum-number-of-k-consecutive-bit-flips.js b/995.minimum-number-of-k-consecutive-bit-flips.js new file mode 100644 index 00000000..3cc4825e --- /dev/null +++ b/995.minimum-number-of-k-consecutive-bit-flips.js @@ -0,0 +1,20 @@ +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +const minKBitFlips = function(nums, k) { + let cur = 0, res = 0 + const n = nums.length + for(let i = 0; i < n; i++) { + if(i >= k && nums[i - k] === 2) cur-- + if(cur % 2 === nums[i]) { + if(i + k > n) return -1 + nums[i] = 2 + cur++ + res++ + } + } + return res +}; + diff --git a/996-number-of-squareful-arrays.js b/996.number-of-squareful-arrays.js similarity index 100% rename from 996-number-of-squareful-arrays.js rename to 996.number-of-squareful-arrays.js diff --git a/997-find-the-town-judge.js b/997-find-the-town-judge.js deleted file mode 100644 index 55b28506..00000000 --- a/997-find-the-town-judge.js +++ /dev/null @@ -1,41 +0,0 @@ -/** - * @param {number} N - * @param {number[][]} trust - * @return {number} - */ -const findJudge = function(N, trust) { - const arr = new Array(N + 1).fill(0) - for(let [t, ted] of trust) { - arr[t]-- - arr[ted]++ - } - for(let i = 1; i <= N; i++) { - if(arr[i] === N - 1) return i - } - return -1 -}; - -// another - -/** - * @param {number} N - * @param {number[][]} trust - * @return {number} - */ -const findJudge = function(N, trust) { - const m = new Map() - for(let i = 1; i<= N; i++) { - const e = new Map() - e.set('t', new Set()) - e.set('ted', new Set()) - m.set(i, e) - } - for(let [t, ted] of trust) { - m.get(t).get('t').add(ted) - m.get(ted).get('ted').add(t) - } - for(let [k,v] of m) { - if(v.get('t').size === 0 && v.get('ted').size === N - 1) return k - } - return -1 -}; diff --git a/997.find-the-town-judge.js b/997.find-the-town-judge.js new file mode 100644 index 00000000..1339c2b7 --- /dev/null +++ b/997.find-the-town-judge.js @@ -0,0 +1,17 @@ +/** + * @param {number} N + * @param {number[][]} trust + * @return {number} + */ +const findJudge = function(N, trust) { + const arr = new Array(N + 1).fill(0) + for(let [t, ted] of trust) { + arr[t]-- + arr[ted]++ + } + for(let i = 1; i <= N; i++) { + if(arr[i] === N - 1) return i + } + return -1 +}; + diff --git a/999-available-captures-for-rook.js b/999.available-captures-for-rook.js similarity index 100% rename from 999-available-captures-for-rook.js rename to 999.available-captures-for-rook.js diff --git a/TBD-leftmost-column-with-at-least-a-one.js b/TBD-leftmost-column-with-at-least-a-one.js deleted file mode 100644 index bfd5e911..00000000 --- a/TBD-leftmost-column-with-at-least-a-one.js +++ /dev/null @@ -1,34 +0,0 @@ -/** - * // This is the BinaryMatrix's API interface. - * // You should not implement it, or speculate about its implementation - * function BinaryMatrix() { - * @param {integer} x, y - * @return {integer} - * this.get = function(x, y) { - * ... - * }; - * - * @return {[integer, integer]} - * this.dimensions = function() { - * ... - * }; - * }; - */ - -/** - * @param {BinaryMatrix} binaryMatrix - * @return {number} - */ -const leftMostColumnWithOne = function (binaryMatrix) { - const [rows, cols] = binaryMatrix.dimensions() - let candidate = -1 - for (let r = 0, c = cols - 1; r < rows && c >= 0; ) { - if (binaryMatrix.get(r, c) === 1) { - candidate = c - c-- - } else { - r++ - } - } - return candidate -} diff --git a/clean-dataset.py b/clean-dataset.py new file mode 100644 index 00000000..d8e8c8a1 --- /dev/null +++ b/clean-dataset.py @@ -0,0 +1,17 @@ +import glob +import os + +js_files = glob.glob('*.js') +for js_file in js_files: + with open(js_file, 'r', encoding='utf-8') as f: + src_lines = f.readlines() + # Find indices of lines that contain // another + line_sep = [i for i, line in enumerate(src_lines) if '// another' in line or '//another' in line] + if len(line_sep) > 0: + new_lines = src_lines[:line_sep[0]] + # Rewrite the file + with open(js_file, 'w', encoding='utf-8') as f: + f.writelines(new_lines) + # Rename the file - replace first '-' with '.' + new_name = js_file.replace('-', '.', 1) + os.rename(js_file, new_name) diff --git a/tmp.js b/tmp.js deleted file mode 100644 index 4e53563a..00000000 --- a/tmp.js +++ /dev/null @@ -1,141 +0,0 @@ -/** - * @param {string} s - * @return {boolean} - */ -var isDecomposable = function(s) { - let hasTwo = false - let i = 0 - let j = 0 - - while(j < s.length) { - while(j + 1 < s.length && s[j + 1] === s[i]) { - j += 1 - } - - if (((j - i + 1) % 3) === 2) { - if (!hasTwo) { - hasTwo = true - } else { - return false - } - } else if (((j - i + 1) % 3) === 1) { - return false - } - j++ - i = j - } - - return hasTwo -}; - - -class Solution { -public: - vector longestCommomSubsequence(vector>& arrays) { - int n = arrays.size(); - vector nums = vector(100); // 100 possible numbers as stated in the question - for (int i = 0; i < n; i++) { - for (int j = 0; j < arrays[i].size(); j++) { - nums[arrays[i][j] - 1]++; // count occurrences - } - } - vector ans; - for (int i = 0; i < 100; i++) { - if (nums[i] == n) ans.push_back(i + 1); // save it if it appears in every array - } - return ans; - } -}; - -class Solution { - public int[] findMaximums(int[] nums) { - if(nums == null || nums.length == 0) return nums; - // calc the [l, r] for each ele where in [l, r]: ele is the min value - int len = nums.length; - TreeSet idx = new TreeSet<>(); - Integer[] indices = new Integer[len]; - for(int i = 0; i < len; i++) indices[i] = i; - Arrays.sort(indices, (l, r) -> nums[l] - nums[r]); - int prev = -1; - int[] ranges = new int[len]; - Queue sameLevel = new LinkedList<>(); - int[] ans = new int[len]; - for(int i = 0; i < len; i++) { - if(nums[indices[i]] > prev) { - while(!sameLevel.isEmpty()) { - idx.add(sameLevel.poll()); - } - } - Integer l = idx.lower(indices[i]); - Integer r = idx.higher(indices[i]); - ranges[indices[i]] = (r == null?len - 1:r - 1) - (l == null?0:l + 1) + 1; - prev = nums[indices[i]]; - sameLevel.add(indices[i]); - } - // we iterate ranges from maximum to minimum to construct the ans array - int j = len - 1; - for(int i = len - 1; i >= 0; i--) { - while(j >= 0 && ranges[indices[j]] < len - i) { - j--; - } - ans[len - 1 - i] = nums[indices[j]]; - } - return ans; - } -} - -class Solution: - def minDayskVariants(self, points: List[List[int]], k: int) -> int: - lo = 0 - hi = int(1e9) - - # binary search check helper function - def check(day): - lines = collections.defaultdict(collections.Counter) - - # 2d sweep line - for x, y in points: - lbx, lby = (x, y - day) # left point - ubx, uby = (x - day, y) # bottom point - - # lbx + lby == ubx + uby == new x axis's open line - lines[lbx+lby][lby-lbx] += 1 - lines[ubx+uby][uby-ubx+1] -= 1 # - - # lbx + lby == ubx + uby == new x axis's close line - lbx, lby = (x + day, y) # right point - ubx, uby = (x, y + day) # upper point - lines[lbx+lby+1][lby-lbx] -= 1 - lines[ubx+uby+1][uby-ubx+1] += 1 - - # hold a new ranges to sweep all lines from left to right on new x axis - ranges = collections.Counter() - - # for every critical points on new x axis (it's a diag on the original axis), - # add the sweep lines on new y axis - for diag in sorted(lines): - for num in sorted(lines[diag]): - cnt = lines[diag][num] - ranges[num] += cnt - - # for every critical points, check whether there is an area having - # overlapping points >= k - cur = 0 - for num in sorted(ranges): - cnt = ranges[num] - cur += cnt - - if cur >= k: - return True - - return False - - # binary search - while lo < hi: - mid = (lo + hi) // 2 - if check(mid): - hi = mid - else: - lo = mid + 1 - - return lo