diff --git a/README.md b/README.md index d7421e39..ca4318ab 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 2,000+ LeetCode solutions in JavaScript +# 2,750+ LeetCode solutions in JavaScript [https://leetcodejavascript.com](https://leetcodejavascript.com) @@ -161,19 +161,27 @@ 153|[Find Minimum in Rotated Sorted Array](./solutions/0153-find-minimum-in-rotated-sorted-array.js)|Medium| 154|[Find Minimum in Rotated Sorted Array II](./solutions/0154-find-minimum-in-rotated-sorted-array-ii.js)|Hard| 155|[Min Stack](./solutions/0155-min-stack.js)|Medium| +156|[Binary Tree Upside Down](./solutions/0156-binary-tree-upside-down.js)|Medium| +157|[Read N Characters Given Read4](./solutions/0157-read-n-characters-given-read4.js)|Easy| +158|[Read N Characters Given read4 II - Call Multiple Times](./solutions/0158-read-n-characters-given-read4-ii-call-multiple-times.js)|Hard| +159|[Longest Substring with At Most Two Distinct Characters](./solutions/0159-longest-substring-with-at-most-two-distinct-characters.js)|Medium| 160|[Intersection of Two Linked Lists](./solutions/0160-intersection-of-two-linked-lists.js)|Medium| +161|[One Edit Distance](./solutions/0161-one-edit-distance.js)|Medium| 162|[Find Peak Element](./solutions/0162-find-peak-element.js)|Medium| +163|[Missing Ranges](./solutions/0163-missing-ranges.js)|Easy| 164|[Maximum Gap](./solutions/0164-maximum-gap.js)|Medium| 165|[Compare Version Numbers](./solutions/0165-compare-version-numbers.js)|Medium| 166|[Fraction to Recurring Decimal](./solutions/0166-fraction-to-recurring-decimal.js)|Medium| 167|[Two Sum II - Input Array Is Sorted](./solutions/0167-two-sum-ii-input-array-is-sorted.js)|Easy| 168|[Excel Sheet Column Title](./solutions/0168-excel-sheet-column-title.js)|Easy| 169|[Majority Element](./solutions/0169-majority-element.js)|Easy| +170|[Two Sum III - Data structure design](./solutions/0170-two-sum-iii-data-structure-design.js)|Easy| 171|[Excel Sheet Column Number](./solutions/0171-excel-sheet-column-number.js)|Easy| 172|[Factorial Trailing Zeroes](./solutions/0172-factorial-trailing-zeroes.js)|Medium| 173|[Binary Search Tree Iterator](./solutions/0173-binary-search-tree-iterator.js)|Medium| 174|[Dungeon Game](./solutions/0174-dungeon-game.js)|Hard| 179|[Largest Number](./solutions/0179-largest-number.js)|Medium| +186|[Reverse Words in a String II](./solutions/0186-reverse-words-in-a-string-ii.js)|Medium| 187|[Repeated DNA Sequences](./solutions/0187-repeated-dna-sequences.js)|Medium| 188|[Best Time to Buy and Sell Stock IV](./solutions/0188-best-time-to-buy-and-sell-stock-iv.js)|Hard| 189|[Rotate Array](./solutions/0189-rotate-array.js)|Medium| @@ -224,44 +232,88 @@ 240|[Search a 2D Matrix II](./solutions/0240-search-a-2d-matrix-ii.js)|Medium| 241|[Different Ways to Add Parentheses](./solutions/0241-different-ways-to-add-parentheses.js)|Medium| 242|[Valid Anagram](./solutions/0242-valid-anagram.js)|Easy| +243|[Shortest Word Distance](./solutions/0243-shortest-word-distance.js)|Easy| +244|[Shortest Word Distance II](./solutions/0244-shortest-word-distance-ii.js)|Medium| +245|[Shortest Word Distance III](./solutions/0245-shortest-word-distance-iii.js)|Medium| +246|[Strobogrammatic Number](./solutions/0246-strobogrammatic-number.js)|Easy| +247|[Strobogrammatic Number II](./solutions/0247-strobogrammatic-number-ii.js)|Medium| +248|[Strobogrammatic Number III](./solutions/0248-strobogrammatic-number-iii.js)|Hard| +249|[Group Shifted Strings](./solutions/0249-group-shifted-strings.js)|Medium| +250|[Count Univalue Subtrees](./solutions/0250-count-univalue-subtrees.js)|Medium| +251|[Flatten 2D Vector](./solutions/0251-flatten-2d-vector.js)|Medium| +252|[Meeting Rooms](./solutions/0252-meeting-rooms.js)|Easy| +253|[Meeting Rooms II](./solutions/0253-meeting-rooms-ii.js)|Medium| +254|[Factor Combinations](./solutions/0254-factor-combinations.js)|Medium| +255|[Verify Preorder Sequence in Binary Search Tree](./solutions/0255-verify-preorder-sequence-in-binary-search-tree.js)|Medium| +256|[Paint House](./solutions/0256-paint-house.js)|Medium| 257|[Binary Tree Paths](./solutions/0257-binary-tree-paths.js)|Easy| 258|[Add Digits](./solutions/0258-add-digits.js)|Easy| +259|[3Sum Smaller](./solutions/0259-3sum-smaller.js)|Medium| 260|[Single Number III](./solutions/0260-single-number-iii.js)|Medium| +261|[Graph Valid Tree](./solutions/0261-graph-valid-tree.js)|Medium| 263|[Ugly Number](./solutions/0263-ugly-number.js)|Easy| 264|[Ugly Number II](./solutions/0264-ugly-number-ii.js)|Medium| +265|[Paint House II](./solutions/0265-paint-house-ii.js)|Hard| +266|[Palindrome Permutation](./solutions/0266-palindrome-permutation.js)|Easy| +267|[Palindrome Permutation II](./solutions/0267-palindrome-permutation-ii.js)|Medium| 268|[Missing Number](./solutions/0268-missing-number.js)|Easy| +269|[Alien Dictionary](./solutions/0269-alien-dictionary.js)|Hard| +270|[Closest Binary Search Tree Value](./solutions/0270-closest-binary-search-tree-value.js)|Easy| +271|[Encode and Decode Strings](./solutions/0271-encode-and-decode-strings.js)|Medium| +272|[Closest Binary Search Tree Value II](./solutions/0272-closest-binary-search-tree-value-ii.js)|Hard| 273|[Integer to English Words](./solutions/0273-integer-to-english-words.js)|Hard| 274|[H-Index](./solutions/0274-h-index.js)|Medium| 275|[H-Index II](./solutions/0275-h-index-ii.js)|Medium| +276|[Paint Fence](./solutions/0276-paint-fence.js)|Medium| +277|[Find the Celebrity](./solutions/0277-find-the-celebrity.js)|Medium| 278|[First Bad Version](./solutions/0278-first-bad-version.js)|Medium| 279|[Perfect Squares](./solutions/0279-perfect-squares.js)|Medium| +280|[Wiggle Sort](./solutions/0280-wiggle-sort.js)|Medium| +281|[Zigzag Iterator](./solutions/0281-zigzag-iterator.js)|Medium| 282|[Expression Add Operators](./solutions/0282-expression-add-operators.js)|Hard| 283|[Move Zeroes](./solutions/0283-move-zeroes.js)|Easy| 284|[Peeking Iterator](./solutions/0284-peeking-iterator.js)|Medium| +285|[Inorder Successor in BST](./solutions/0285-inorder-successor-in-bst.js)|Medium| +286|[Walls and Gates](./solutions/0286-walls-and-gates.js)|Medium| 287|[Find the Duplicate Number](./solutions/0287-find-the-duplicate-number.js)|Medium| +288|[Unique Word Abbreviation](./solutions/0288-unique-word-abbreviation.js)|Medium| 289|[Game of Life](./solutions/0289-game-of-life.js)|Medium| 290|[Word Pattern](./solutions/0290-word-pattern.js)|Easy| +291|[Word Pattern II](./solutions/0291-word-pattern-ii.js)|Medium| 292|[Nim Game](./solutions/0292-nim-game.js)|Easy| +293|[Flip Game](./solutions/0293-flip-game.js)|Easy| +294|[Flip Game II](./solutions/0294-flip-game-ii.js)|Medium| 295|[Find Median from Data Stream](./solutions/0295-find-median-from-data-stream.js)|Hard| +296|[Best Meeting Point](./solutions/0296-best-meeting-point.js)|Hard| 297|[Serialize and Deserialize Binary Tree](./solutions/0297-serialize-and-deserialize-binary-tree.js)|Hard| +298|[Binary Tree Longest Consecutive Sequence](./solutions/0298-binary-tree-longest-consecutive-sequence.js)|Medium| 299|[Bulls and Cows](./solutions/0299-bulls-and-cows.js)|Medium| 300|[Longest Increasing Subsequence](./solutions/0300-longest-increasing-subsequence.js)|Medium| 301|[Remove Invalid Parentheses](./solutions/0301-remove-invalid-parentheses.js)|Hard| +302|[Smallest Rectangle Enclosing Black Pixels](./solutions/0302-smallest-rectangle-enclosing-black-pixels.js)|Hard| 303|[Range Sum Query - Immutable](./solutions/0303-range-sum-query-immutable.js)|Easy| 304|[Range Sum Query 2D - Immutable](./solutions/0304-range-sum-query-2d-immutable.js)|Medium| +305|[Number of Islands II](./solutions/0305-number-of-islands-ii.js)|Hard| 306|[Additive Number](./solutions/0306-additive-number.js)|Medium| 307|[Range Sum Query - Mutable](./solutions/0307-range-sum-query-mutable.js)|Medium| +308|[Range Sum Query 2D - Mutable](./solutions/0308-range-sum-query-2d-mutable.js)|Medium| 309|[Best Time to Buy and Sell Stock with Cooldown](./solutions/0309-best-time-to-buy-and-sell-stock-with-cooldown.js)|Medium| 310|[Minimum Height Trees](./solutions/0310-minimum-height-trees.js)|Medium| +311|[Sparse Matrix Multiplication](./solutions/0311-sparse-matrix-multiplication.js)|Medium| 312|[Burst Balloons](./solutions/0312-burst-balloons.js)|Hard| 313|[Super Ugly Number](./solutions/0313-super-ugly-number.js)|Medium| +314|[Binary Tree Vertical Order Traversal](./solutions/0314-binary-tree-vertical-order-traversal.js)|Medium| 315|[Count of Smaller Numbers After Self](./solutions/0315-count-of-smaller-numbers-after-self.js)|Hard| 316|[Remove Duplicate Letters](./solutions/0316-remove-duplicate-letters.js)|Medium| +317|[Shortest Distance from All Buildings](./solutions/0317-shortest-distance-from-all-buildings.js)|Hard| 318|[Maximum Product of Word Lengths](./solutions/0318-maximum-product-of-word-lengths.js)|Medium| 319|[Bulb Switcher](./solutions/0319-bulb-switcher.js)|Medium| +320|[Generalized Abbreviation](./solutions/0320-generalized-abbreviation.js)|Medium| 321|[Create Maximum Number](./solutions/0321-create-maximum-number.js)|Hard| 322|[Coin Change](./solutions/0322-coin-change.js)|Medium| +323|[Number of Connected Components in an Undirected Graph](./solutions/0323-number-of-connected-components-in-an-undirected-graph.js)|Medium| 324|[Wiggle Sort II](./solutions/0324-wiggle-sort-ii.js)|Medium| +325|[Maximum Size Subarray Sum Equals k](./solutions/0325-maximum-size-subarray-sum-equals-k.js)|Medium| 326|[Power of Three](./solutions/0326-power-of-three.js)|Easy| 327|[Count of Range Sum](./solutions/0327-count-of-range-sum.js)|Hard| 328|[Odd Even Linked List](./solutions/0328-odd-even-linked-list.js)|Medium| @@ -269,27 +321,44 @@ 330|[Patching Array](./solutions/0330-patching-array.js)|Hard| 331|[Verify Preorder Serialization of a Binary Tree](./solutions/0331-verify-preorder-serialization-of-a-binary-tree.js)|Medium| 332|[Reconstruct Itinerary](./solutions/0332-reconstruct-itinerary.js)|Hard| +333|[Largest BST Subtree](./solutions/0333-largest-bst-subtree.js)|Medium| 334|[Increasing Triplet Subsequence](./solutions/0334-increasing-triplet-subsequence.js)|Medium| 335|[Self Crossing](./solutions/0335-self-crossing.js)|Hard| 336|[Palindrome Pairs](./solutions/0336-palindrome-pairs.js)|Hard| 337|[House Robber III](./solutions/0337-house-robber-iii.js)|Medium| 338|[Counting Bits](./solutions/0338-counting-bits.js)|Easy| +339|[Nested List Weight Sum](./solutions/0339-nested-list-weight-sum.js)|Medium| +340|[Longest Substring with At Most K Distinct Characters](./solutions/0340-longest-substring-with-at-most-k-distinct-characters.js)|Medium| 341|[Flatten Nested List Iterator](./solutions/0341-flatten-nested-list-iterator.js)|Medium| 342|[Power of Four](./solutions/0342-power-of-four.js)|Easy| 343|[Integer Break](./solutions/0343-integer-break.js)|Medium| 344|[Reverse String](./solutions/0344-reverse-string.js)|Easy| 345|[Reverse Vowels of a String](./solutions/0345-reverse-vowels-of-a-string.js)|Easy| +346|[Moving Average from Data Stream](./solutions/0346-moving-average-from-data-stream.js)|Easy| 347|[Top K Frequent Elements](./solutions/0347-top-k-frequent-elements.js)|Medium| +348|[Design Tic-Tac-Toe](./solutions/0348-design-tic-tac-toe.js)|Medium| 349|[Intersection of Two Arrays](./solutions/0349-intersection-of-two-arrays.js)|Easy| 350|[Intersection of Two Arrays II](./solutions/0350-intersection-of-two-arrays-ii.js)|Easy| +351|[Android Unlock Patterns](./solutions/0351-android-unlock-patterns.js)|Medium| 352|[Data Stream as Disjoint Intervals](./solutions/0352-data-stream-as-disjoint-intervals.js)|Hard| +353|[Design Snake Game](./solutions/0353-design-snake-game.js)|Medium| 354|[Russian Doll Envelopes](./solutions/0354-russian-doll-envelopes.js)|Hard| 355|[Design Twitter](./solutions/0355-design-twitter.js)|Medium| +356|[Line Reflection](./solutions/0356-line-reflection.js)|Medium| 357|[Count Numbers with Unique Digits](./solutions/0357-count-numbers-with-unique-digits.js)|Medium| +358|[Rearrange String k Distance Apart](./solutions/0358-rearrange-string-k-distance-apart.js)|Hard| +359|[Logger Rate Limiter](./solutions/0359-logger-rate-limiter.js)|Easy| +360|[Sort Transformed Array](./solutions/0360-sort-transformed-array.js)|Medium| +361|[Bomb Enemy](./solutions/0361-bomb-enemy.js)|Medium| +362|[Design Hit Counter](./solutions/0362-design-hit-counter.js)|Medium| 363|[Max Sum of Rectangle No Larger Than K](./solutions/0363-max-sum-of-rectangle-no-larger-than-k.js)|Hard| +364|[Nested List Weight Sum II](./solutions/0364-nested-list-weight-sum-ii.js)|Medium| 365|[Water and Jug Problem](./solutions/0365-water-and-jug-problem.js)|Medium| +366|[Find Leaves of Binary Tree](./solutions/0366-find-leaves-of-binary-tree.js)|Medium| 367|[Valid Perfect Square](./solutions/0367-valid-perfect-square.js)|Easy| 368|[Largest Divisible Subset](./solutions/0368-largest-divisible-subset.js)|Medium| +369|[Plus One Linked List](./solutions/0369-plus-one-linked-list.js)|Medium| +370|[Range Addition](./solutions/0370-range-addition.js)|Medium| 371|[Sum of Two Integers](./solutions/0371-sum-of-two-integers.js)|Medium| 372|[Super Pow](./solutions/0372-super-pow.js)|Medium| 373|[Find K Pairs with Smallest Sums](./solutions/0373-find-k-pairs-with-smallest-sums.js)|Medium| @@ -298,6 +367,7 @@ 376|[Wiggle Subsequence](./solutions/0376-wiggle-subsequence.js)|Medium| 377|[Combination Sum IV](./solutions/0377-combination-sum-iv.js)|Medium| 378|[Kth Smallest Element in a Sorted Matrix](./solutions/0378-kth-smallest-element-in-a-sorted-matrix.js)|Medium| +379|[Design Phone Directory](./solutions/0379-design-phone-directory.js)|Medium| 380|[Insert Delete GetRandom O(1)](./solutions/0380-insert-delete-getrandom-o1.js)|Medium| 381|[Insert Delete GetRandom O(1) - Duplicates allowed](./solutions/0381-insert-delete-getrandom-o1-duplicates-allowed.js)|Hard| 382|[Linked List Random Node](./solutions/0382-linked-list-random-node.js)|Medium| @@ -326,22 +396,30 @@ 405|[Convert a Number to Hexadecimal](./solutions/0405-convert-a-number-to-hexadecimal.js)|Easy| 406|[Queue Reconstruction by Height](./solutions/0406-queue-reconstruction-by-height.js)|Medium| 407|[Trapping Rain Water II](./solutions/0407-trapping-rain-water-ii.js)|Hard| +408|[Valid Word Abbreviation](./solutions/0408-valid-word-abbreviation.js)|Easy| 409|[Longest Palindrome](./solutions/0409-longest-palindrome.js)|Easy| 410|[Split Array Largest Sum](./solutions/0410-split-array-largest-sum.js)|Hard| +411|[Minimum Unique Word Abbreviation](./solutions/0411-minimum-unique-word-abbreviation.js)|Hard| 412|[Fizz Buzz](./solutions/0412-fizz-buzz.js)|Easy| 413|[Arithmetic Slices](./solutions/0413-arithmetic-slices.js)|Medium| 414|[Third Maximum Number](./solutions/0414-third-maximum-number.js)|Easy| 415|[Add Strings](./solutions/0415-add-strings.js)|Easy| 416|[Partition Equal Subset Sum](./solutions/0416-partition-equal-subset-sum.js)|Medium| 417|[Pacific Atlantic Water Flow](./solutions/0417-pacific-atlantic-water-flow.js)|Medium| +418|[Sentence Screen Fitting](./solutions/0418-sentence-screen-fitting.js)|Medium| 419|[Battleships in a Board](./solutions/0419-battleships-in-a-board.js)|Medium| 420|[Strong Password Checker](./solutions/0420-strong-password-checker.js)|Hard| 421|[Maximum XOR of Two Numbers in an Array](./solutions/0421-maximum-xor-of-two-numbers-in-an-array.js)|Medium| +422|[Valid Word Square](./solutions/0422-valid-word-square.js)|Easy| 423|[Reconstruct Original Digits from English](./solutions/0423-reconstruct-original-digits-from-english.js)|Medium| 424|[Longest Repeating Character Replacement](./solutions/0424-longest-repeating-character-replacement.js)|Medium| +425|[Word Squares](./solutions/0425-word-squares.js)|Hard| +426|[Convert Binary Search Tree to Sorted Doubly Linked List](./solutions/0426-convert-binary-search-tree-to-sorted-doubly-linked-list.js)|Medium| 427|[Construct Quad Tree](./solutions/0427-construct-quad-tree.js)|Medium| +428|[Serialize and Deserialize N-ary Tree](./solutions/0428-serialize-and-deserialize-n-ary-tree.js)|Hard| 429|[N-ary Tree Level Order Traversal](./solutions/0429-n-ary-tree-level-order-traversal.js)|Medium| 430|[Flatten a Multilevel Doubly Linked List](./solutions/0430-flatten-a-multilevel-doubly-linked-list.js)|Medium| +431|[Encode N-ary Tree to Binary Tree](./solutions/0431-encode-n-ary-tree-to-binary-tree.js)|Hard| 432|[All O`one Data Structure](./solutions/0432-all-oone-data-structure.js)|Hard| 433|[Minimum Genetic Mutation](./solutions/0433-minimum-genetic-mutation.js)|Medium| 434|[Number of Segments in a String](./solutions/0434-number-of-segments-in-a-string.js)|Easy| @@ -349,10 +427,12 @@ 436|[Find Right Interval](./solutions/0436-find-right-interval.js)|Medium| 437|[Path Sum III](./solutions/0437-path-sum-iii.js)|Medium| 438|[Find All Anagrams in a String](./solutions/0438-find-all-anagrams-in-a-string.js)|Medium| +439|[Ternary Expression Parser](./solutions/0439-ternary-expression-parser.js)|Medium| 440|[K-th Smallest in Lexicographical Order](./solutions/0440-k-th-smallest-in-lexicographical-order.js)|Hard| 441|[Arranging Coins](./solutions/0441-arranging-coins.js)|Easy| 442|[Find All Duplicates in an Array](./solutions/0442-find-all-duplicates-in-an-array.js)|Medium| 443|[String Compression](./solutions/0443-string-compression.js)|Medium| +444|[Sequence Reconstruction](./solutions/0444-sequence-reconstruction.js)|Medium| 445|[Add Two Numbers II](./solutions/0445-add-two-numbers-ii.js)|Medium| 446|[Arithmetic Slices II - Subsequence](./solutions/0446-arithmetic-slices-ii-subsequence.js)|Hard| 447|[Number of Boomerangs](./solutions/0447-number-of-boomerangs.js)|Medium| @@ -373,10 +453,13 @@ 462|[Minimum Moves to Equal Array Elements II](./solutions/0462-minimum-moves-to-equal-array-elements-ii.js)|Medium| 463|[Island Perimeter](./solutions/0463-island-perimeter.js)|Medium| 464|[Can I Win](./solutions/0464-can-i-win.js)|Medium| +465|[Optimal Account Balancing](./solutions/0465-optimal-account-balancing.js)|Hard| 466|[Count The Repetitions](./solutions/0466-count-the-repetitions.js)|Hard| 467|[Unique Substrings in Wraparound String](./solutions/0467-unique-substrings-in-wraparound-string.js)|Medium| 468|[Validate IP Address](./solutions/0468-validate-ip-address.js)|Medium| +469|[Convex Polygon](./solutions/0469-convex-polygon.js)|Medium| 470|[Implement Rand10() Using Rand7()](./solutions/0470-implement-rand10-using-rand7.js)|Medium| +471|[Encode String with Shortest Length](./solutions/0471-encode-string-with-shortest-length.js)|Hard| 472|[Concatenated Words](./solutions/0472-concatenated-words.js)|Hard| 473|[Matchsticks to Square](./solutions/0473-matchsticks-to-square.js)|Medium| 474|[Ones and Zeroes](./solutions/0474-ones-and-zeroes.js)|Medium| @@ -389,9 +472,13 @@ 481|[Magical String](./solutions/0481-magical-string.js)|Medium| 482|[License Key Formatting](./solutions/0482-license-key-formatting.js)|Easy| 483|[Smallest Good Base](./solutions/0483-smallest-good-base.js)|Hard| +484|[Find Permutation](./solutions/0484-find-permutation.js)|Medium| 485|[Max Consecutive Ones](./solutions/0485-max-consecutive-ones.js)|Easy| 486|[Predict the Winner](./solutions/0486-predict-the-winner.js)|Medium| +487|[Max Consecutive Ones II](./solutions/0487-max-consecutive-ones-ii.js)|Medium| 488|[Zuma Game](./solutions/0488-zuma-game.js)|Hard| +489|[Robot Room Cleaner](./solutions/0489-robot-room-cleaner.js)|Hard| +490|[The Maze](./solutions/0490-the-maze.js)|Medium| 491|[Non-decreasing Subsequences](./solutions/0491-non-decreasing-subsequences.js)|Medium| 492|[Construct the Rectangle](./solutions/0492-construct-the-rectangle.js)|Easy| 493|[Reverse Pairs](./solutions/0493-reverse-pairs.js)|Hard| @@ -400,15 +487,18 @@ 496|[Next Greater Element I](./solutions/0496-next-greater-element-i.js)|Easy| 497|[Random Point in Non-overlapping Rectangles](./solutions/0497-random-point-in-non-overlapping-rectangles.js)|Medium| 498|[Diagonal Traverse](./solutions/0498-diagonal-traverse.js)|Medium| +499|[The Maze III](./solutions/0499-the-maze-iii.js)|Hard| 500|[Keyboard Row](./solutions/0500-keyboard-row.js)|Easy| 501|[Find Mode in Binary Search Tree](./solutions/0501-find-mode-in-binary-search-tree.js)|Easy| 502|[IPO](./solutions/0502-ipo.js)|Hard| 503|[Next Greater Element II](./solutions/0503-next-greater-element-ii.js)|Medium| 504|[Base 7](./solutions/0504-base-7.js)|Easy| +505|[The Maze II](./solutions/0505-the-maze-ii.js)|Medium| 506|[Relative Ranks](./solutions/0506-relative-ranks.js)|Easy| 507|[Perfect Number](./solutions/0507-perfect-number.js)|Easy| 508|[Most Frequent Subtree Sum](./solutions/0508-most-frequent-subtree-sum.js)|Medium| 509|[Fibonacci Number](./solutions/0509-fibonacci-number.js)|Easy| +510|[Inorder Successor in BST II](./solutions/0510-inorder-successor-in-bst-ii.js)|Medium| 513|[Find Bottom Left Tree Value](./solutions/0513-find-bottom-left-tree-value.js)|Medium| 514|[Freedom Trail](./solutions/0514-freedom-trail.js)|Hard| 515|[Find Largest Value in Each Tree Row](./solutions/0515-find-largest-value-in-each-tree-row.js)|Medium| @@ -423,11 +513,15 @@ 524|[Longest Word in Dictionary through Deleting](./solutions/0524-longest-word-in-dictionary-through-deleting.js)|Medium| 525|[Contiguous Array](./solutions/0525-contiguous-array.js)|Medium| 526|[Beautiful Arrangement](./solutions/0526-beautiful-arrangement.js)|Medium| +527|[Word Abbreviation](./solutions/0527-word-abbreviation.js)|Hard| 528|[Random Pick with Weight](./solutions/0528-random-pick-with-weight.js)|Medium| 529|[Minesweeper](./solutions/0529-minesweeper.js)|Medium| 530|[Minimum Absolute Difference in BST](./solutions/0530-minimum-absolute-difference-in-bst.js)|Easy| +531|[Lonely Pixel I](./solutions/0531-lonely-pixel-i.js)|Medium| 532|[K-diff Pairs in an Array](./solutions/0532-k-diff-pairs-in-an-array.js)|Medium| +533|[Lonely Pixel II](./solutions/0533-lonely-pixel-ii.js)|Medium| 535|[Encode and Decode TinyURL](./solutions/0535-encode-and-decode-tinyurl.js)|Medium| +536|[Construct Binary Tree from String](./solutions/0536-construct-binary-tree-from-string.js)|Medium| 537|[Complex Number Multiplication](./solutions/0537-complex-number-multiplication.js)|Medium| 538|[Convert BST to Greater Tree](./solutions/0538-convert-bst-to-greater-tree.js)|Medium| 539|[Minimum Time Difference](./solutions/0539-minimum-time-difference.js)|Medium| @@ -435,29 +529,39 @@ 541|[Reverse String II](./solutions/0541-reverse-string-ii.js)|Easy| 542|[01 Matrix](./solutions/0542-01-matrix.js)|Medium| 543|[Diameter of Binary Tree](./solutions/0543-diameter-of-binary-tree.js)|Easy| +544|[Output Contest Matches](./solutions/0544-output-contest-matches.js)|Medium| +545|[Boundary of Binary Tree](./solutions/0545-boundary-of-binary-tree.js)|Medium| 546|[Remove Boxes](./solutions/0546-remove-boxes.js)|Hard| 547|[Number of Provinces](./solutions/0547-number-of-provinces.js)|Medium| +548|[Split Array with Equal Sum](./solutions/0548-split-array-with-equal-sum.js)|Hard| +549|[Binary Tree Longest Consecutive Sequence II](./solutions/0549-binary-tree-longest-consecutive-sequence-ii.js)|Medium| 551|[Student Attendance Record I](./solutions/0551-student-attendance-record-i.js)|Easy| 552|[Student Attendance Record II](./solutions/0552-student-attendance-record-ii.js)|Hard| 553|[Optimal Division](./solutions/0553-optimal-division.js)|Medium| 554|[Brick Wall](./solutions/0554-brick-wall.js)|Medium| +555|[Split Concatenated Strings](./solutions/0555-split-concatenated-strings.js)|Medium| 556|[Next Greater Element III](./solutions/0556-next-greater-element-iii.js)|Medium| 557|[Reverse Words in a String III](./solutions/0557-reverse-words-in-a-string-iii.js)|Easy| 558|[Logical OR of Two Binary Grids Represented as Quad-Trees](./solutions/0558-logical-or-of-two-binary-grids-represented-as-quad-trees.js)|Medium| 559|[Maximum Depth of N-ary Tree](./solutions/0559-maximum-depth-of-n-ary-tree.js)|Easy| 560|[Subarray Sum Equals K](./solutions/0560-subarray-sum-equals-k.js)|Medium| 561|[Array Partition](./solutions/0561-array-partition.js)|Easy| +562|[Longest Line of Consecutive One in Matrix](./solutions/0562-longest-line-of-consecutive-one-in-matrix.js)|Medium| 563|[Binary Tree Tilt](./solutions/0563-binary-tree-tilt.js)|Easy| 564|[Find the Closest Palindrome](./solutions/0564-find-the-closest-palindrome.js)|Hard| 565|[Array Nesting](./solutions/0565-array-nesting.js)|Medium| 566|[Reshape the Matrix](./solutions/0566-reshape-the-matrix.js)|Easy| 567|[Permutation in String](./solutions/0567-permutation-in-string.js)|Medium| +568|[Maximum Vacation Days](./solutions/0568-maximum-vacation-days.js)|Hard| 572|[Subtree of Another Tree](./solutions/0572-subtree-of-another-tree.js)|Easy| +573|[Squirrel Simulation](./solutions/0573-squirrel-simulation.js)|Medium| 575|[Distribute Candies](./solutions/0575-distribute-candies.js)|Easy| 576|[Out of Boundary Paths](./solutions/0576-out-of-boundary-paths.js)|Medium| 581|[Shortest Unsorted Continuous Subarray](./solutions/0581-shortest-unsorted-continuous-subarray.js)|Medium| +582|[Kill Process](./solutions/0582-kill-process.js)|Medium| 583|[Delete Operation for Two Strings](./solutions/0583-delete-operation-for-two-strings.js)|Medium| 587|[Erect the Fence](./solutions/0587-erect-the-fence.js)|Hard| +588|[Design In-Memory File System](./solutions/0588-design-in-memory-file-system.js)|Hard| 589|[N-ary Tree Preorder Traversal](./solutions/0589-n-ary-tree-preorder-traversal.js)|Easy| 590|[N-ary Tree Postorder Traversal](./solutions/0590-n-ary-tree-postorder-traversal.js)|Easy| 591|[Tag Validator](./solutions/0591-tag-validator.js)|Hard| @@ -467,44 +571,57 @@ 598|[Range Addition II](./solutions/0598-range-addition-ii.js)|Easy| 599|[Minimum Index Sum of Two Lists](./solutions/0599-minimum-index-sum-of-two-lists.js)|Easy| 600|[Non-negative Integers without Consecutive Ones](./solutions/0600-non-negative-integers-without-consecutive-ones.js)|Hard| +604|[Design Compressed String Iterator](./solutions/0604-design-compressed-string-iterator.js)|Easy| 605|[Can Place Flowers](./solutions/0605-can-place-flowers.js)|Easy| 606|[Construct String from Binary Tree](./solutions/0606-construct-string-from-binary-tree.js)|Easy| 609|[Find Duplicate File in System](./solutions/0609-find-duplicate-file-in-system.js)|Medium| 611|[Valid Triangle Number](./solutions/0611-valid-triangle-number.js)|Medium| +616|[Add Bold Tag in String](./solutions/0616-add-bold-tag-in-string.js)|Medium| 617|[Merge Two Binary Trees](./solutions/0617-merge-two-binary-trees.js)|Easy| 621|[Task Scheduler](./solutions/0621-task-scheduler.js)|Medium| 622|[Design Circular Queue](./solutions/0622-design-circular-queue.js)|Medium| 623|[Add One Row to Tree](./solutions/0623-add-one-row-to-tree.js)|Medium| 624|[Maximum Distance in Arrays](./solutions/0624-maximum-distance-in-arrays.js)|Medium| +625|[Minimum Factorization](./solutions/0625-minimum-factorization.js)|Medium| 628|[Maximum Product of Three Numbers](./solutions/0628-maximum-product-of-three-numbers.js)|Easy| 629|[K Inverse Pairs Array](./solutions/0629-k-inverse-pairs-array.js)|Hard| 630|[Course Schedule III](./solutions/0630-course-schedule-iii.js)|Hard| +631|[Design Excel Sum Formula](./solutions/0631-design-excel-sum-formula.js)|Hard| 632|[Smallest Range Covering Elements from K Lists](./solutions/0632-smallest-range-covering-elements-from-k-lists.js)|Hard| 633|[Sum of Square Numbers](./solutions/0633-sum-of-square-numbers.js)|Medium| +634|[Find the Derangement of An Array](./solutions/0634-find-the-derangement-of-an-array.js)|Medium| +635|[Design Log Storage System](./solutions/0635-design-log-storage-system.js)|Medium| 636|[Exclusive Time of Functions](./solutions/0636-exclusive-time-of-functions.js)|Medium| 637|[Average of Levels in Binary Tree](./solutions/0637-average-of-levels-in-binary-tree.js)|Easy| 638|[Shopping Offers](./solutions/0638-shopping-offers.js)|Medium| 639|[Decode Ways II](./solutions/0639-decode-ways-ii.js)|Hard| 640|[Solve the Equation](./solutions/0640-solve-the-equation.js)|Medium| 641|[Design Circular Deque](./solutions/0641-design-circular-deque.js)|Medium| +642|[Design Search Autocomplete System](./solutions/0642-design-search-autocomplete-system.js)|Hard| 643|[Maximum Average Subarray I](./solutions/0643-maximum-average-subarray-i.js)|Easy| +644|[Maximum Average Subarray II](./solutions/0644-maximum-average-subarray-ii.js)|Hard| 645|[Set Mismatch](./solutions/0645-set-mismatch.js)|Medium| 646|[Maximum Length of Pair Chain](./solutions/0646-maximum-length-of-pair-chain.js)|Medium| 647|[Palindromic Substrings](./solutions/0647-palindromic-substrings.js)|Medium| 648|[Replace Words](./solutions/0648-replace-words.js)|Medium| 649|[Dota2 Senate](./solutions/0649-dota2-senate.js)|Medium| 650|[2 Keys Keyboard](./solutions/0650-2-keys-keyboard.js)|Medium| +651|[4 Keys Keyboard](./solutions/0651-4-keys-keyboard.js)|Medium| 652|[Find Duplicate Subtrees](./solutions/0652-find-duplicate-subtrees.js)|Medium| 653|[Two Sum IV - Input is a BST](./solutions/0653-two-sum-iv-input-is-a-bst.js)|Easy| 654|[Maximum Binary Tree](./solutions/0654-maximum-binary-tree.js)|Medium| 655|[Print Binary Tree](./solutions/0655-print-binary-tree.js)|Medium| +656|[Coin Path](./solutions/0656-coin-path.js)|Hard| 657|[Robot Return to Origin](./solutions/0657-robot-return-to-origin.js)|Easy| 658|[Find K Closest Elements](./solutions/0658-find-k-closest-elements.js)|Medium| 659|[Split Array into Consecutive Subsequences](./solutions/0659-split-array-into-consecutive-subsequences.js)|Medium| +660|[Remove 9](./solutions/0660-remove-9.js)|Hard| 661|[Image Smoother](./solutions/0661-image-smoother.js)|Easy| 662|[Maximum Width of Binary Tree](./solutions/0662-maximum-width-of-binary-tree.js)|Medium| +663|[Equal Tree Partition](./solutions/0663-equal-tree-partition.js)|Medium| 664|[Strange Printer](./solutions/0664-strange-printer.js)|Hard| 665|[Non-decreasing Array](./solutions/0665-non-decreasing-array.js)|Medium| +666|[Path Sum IV](./solutions/0666-path-sum-iv.js)|Medium| 667|[Beautiful Arrangement II](./solutions/0667-beautiful-arrangement-ii.js)|Medium| 668|[Kth Smallest Number in Multiplication Table](./solutions/0668-kth-smallest-number-in-multiplication-table.js)|Hard| 669|[Trim a Binary Search Tree](./solutions/0669-trim-a-binary-search-tree.js)|Medium| @@ -519,7 +636,9 @@ 678|[Valid Parenthesis String](./solutions/0678-valid-parenthesis-string.js)|Medium| 679|[24 Game](./solutions/0679-24-game.js)|Hard| 680|[Valid Palindrome II](./solutions/0680-valid-palindrome-ii.js)|Easy| +681|[Next Closest Time](./solutions/0681-next-closest-time.js)|Medium| 682|[Baseball Game](./solutions/0682-baseball-game.js)|Easy| +683|[K Empty Slots](./solutions/0683-k-empty-slots.js)|Hard| 684|[Redundant Connection](./solutions/0684-redundant-connection.js)|Medium| 685|[Redundant Connection II](./solutions/0685-redundant-connection-ii.js)|Hard| 686|[Repeated String Match](./solutions/0686-repeated-string-match.js)|Easy| @@ -530,6 +649,7 @@ 691|[Stickers to Spell Word](./solutions/0691-stickers-to-spell-word.js)|Hard| 692|[Top K Frequent Words](./solutions/0692-top-k-frequent-words.js)|Medium| 693|[Binary Number with Alternating Bits](./solutions/0693-binary-number-with-alternating-bits.js)|Easy| +694|[Number of Distinct Islands](./solutions/0694-number-of-distinct-islands.js)|Medium| 695|[Max Area of Island](./solutions/0695-max-area-of-island.js)|Medium| 696|[Count Binary Substrings](./solutions/0696-count-binary-substrings.js)|Easy| 697|[Degree of an Array](./solutions/0697-degree-of-an-array.js)|Easy| @@ -537,38 +657,47 @@ 699|[Falling Squares](./solutions/0699-falling-squares.js)|Hard| 700|[Search in a Binary Search Tree](./solutions/0700-search-in-a-binary-search-tree.js)|Easy| 701|[Insert into a Binary Search Tree](./solutions/0701-insert-into-a-binary-search-tree.js)|Medium| +702|[Search in a Sorted Array of Unknown Size](./solutions/0702-search-in-a-sorted-array-of-unknown-size.js)|Medium| 703|[Kth Largest Element in a Stream](./solutions/0703-kth-largest-element-in-a-stream.js)|Easy| 704|[Binary Search](./solutions/0704-binary-search.js)|Easy| 705|[Design HashSet](./solutions/0705-design-hashset.js)|Easy| 706|[Design HashMap](./solutions/0706-design-hashmap.js)|Easy| 707|[Design Linked List](./solutions/0707-design-linked-list.js)|Medium| +708|[Insert into a Sorted Circular Linked List](./solutions/0708-insert-into-a-sorted-circular-linked-list.js)|Medium| 709|[To Lower Case](./solutions/0709-to-lower-case.js)|Easy| 710|[Random Pick with Blacklist](./solutions/0710-random-pick-with-blacklist.js)|Hard| +711|[Number of Distinct Islands II](./solutions/0711-number-of-distinct-islands-ii.js)|Hard| 712|[Minimum ASCII Delete Sum for Two Strings](./solutions/0712-minimum-ascii-delete-sum-for-two-strings.js)|Medium| 713|[Subarray Product Less Than K](./solutions/0713-subarray-product-less-than-k.js)|Medium| 714|[Best Time to Buy and Sell Stock with Transaction Fee](./solutions/0714-best-time-to-buy-and-sell-stock-with-transaction-fee.js)|Medium| 715|[Range Module](./solutions/0715-range-module.js)|Hard| +716|[Max Stack](./solutions/0716-max-stack.js)|Hard| 717|[1-bit and 2-bit Characters](./solutions/0717-1-bit-and-2-bit-characters.js)|Easy| 718|[Maximum Length of Repeated Subarray](./solutions/0718-maximum-length-of-repeated-subarray.js)|Medium| 719|[Find K-th Smallest Pair Distance](./solutions/0719-find-k-th-smallest-pair-distance.js)|Hard| 720|[Longest Word in Dictionary](./solutions/0720-longest-word-in-dictionary.js)|Medium| 721|[Accounts Merge](./solutions/0721-accounts-merge.js)|Medium| 722|[Remove Comments](./solutions/0722-remove-comments.js)|Medium| +723|[Candy Crush](./solutions/0723-candy-crush.js)|Medium| 724|[Find Pivot Index](./solutions/0724-find-pivot-index.js)|Easy| 725|[Split Linked List in Parts](./solutions/0725-split-linked-list-in-parts.js)|Medium| 726|[Number of Atoms](./solutions/0726-number-of-atoms.js)|Hard| +727|[Minimum Window Subsequence](./solutions/0727-minimum-window-subsequence.js)|Hard| 728|[Self Dividing Numbers](./solutions/0728-self-dividing-numbers.js)|Easy| 729|[My Calendar I](./solutions/0729-my-calendar-i.js)|Medium| 730|[Count Different Palindromic Subsequences](./solutions/0730-count-different-palindromic-subsequences.js)|Hard| 731|[My Calendar II](./solutions/0731-my-calendar-ii.js)|Medium| 732|[My Calendar III](./solutions/0732-my-calendar-iii.js)|Hard| 733|[Flood Fill](./solutions/0733-flood-fill.js)|Easy| +734|[Sentence Similarity](./solutions/0734-sentence-similarity.js)|Easy| 735|[Asteroid Collision](./solutions/0735-asteroid-collision.js)|Medium| 736|[Parse Lisp Expression](./solutions/0736-parse-lisp-expression.js)|Hard| +737|[Sentence Similarity II](./solutions/0737-sentence-similarity-ii.js)|Medium| 738|[Monotone Increasing Digits](./solutions/0738-monotone-increasing-digits.js)|Medium| 739|[Daily Temperatures](./solutions/0739-daily-temperatures.js)|Medium| 740|[Delete and Earn](./solutions/0740-delete-and-earn.js)|Medium| 741|[Cherry Pickup](./solutions/0741-cherry-pickup.js)|Hard| +742|[Closest Leaf in a Binary Tree](./solutions/0742-closest-leaf-in-a-binary-tree.js)|Medium| 743|[Network Delay Time](./solutions/0743-network-delay-time.js)|Medium| 744|[Find Smallest Letter Greater Than Target](./solutions/0744-find-smallest-letter-greater-than-target.js)|Easy| 745|[Prefix and Suffix Search](./solutions/0745-prefix-and-suffix-search.js)|Hard| @@ -576,11 +705,17 @@ 747|[Largest Number At Least Twice of Others](./solutions/0747-largest-number-at-least-twice-of-others.js)|Easy| 748|[Shortest Completing Word](./solutions/0748-shortest-completing-word.js)|Easy| 749|[Contain Virus](./solutions/0749-contain-virus.js)|Hard| +750|[Number Of Corner Rectangles](./solutions/0750-number-of-corner-rectangles.js)|Medium| +751|[IP to CIDR](./solutions/0751-ip-to-cidr.js)|Medium| 752|[Open the Lock](./solutions/0752-open-the-lock.js)|Medium| 753|[Cracking the Safe](./solutions/0753-cracking-the-safe.js)|Hard| 754|[Reach a Number](./solutions/0754-reach-a-number.js)|Medium| +755|[Pour Water](./solutions/0755-pour-water.js)|Medium| 756|[Pyramid Transition Matrix](./solutions/0756-pyramid-transition-matrix.js)|Medium| 757|[Set Intersection Size At Least Two](./solutions/0757-set-intersection-size-at-least-two.js)|Hard| +758|[Bold Words in String](./solutions/0758-bold-words-in-string.js)|Medium| +759|[Employee Free Time](./solutions/0759-employee-free-time.js)|Hard| +760|[Find Anagram Mappings](./solutions/0760-find-anagram-mappings.js)|Easy| 761|[Special Binary String](./solutions/0761-special-binary-string.js)|Hard| 762|[Prime Number of Set Bits in Binary Representation](./solutions/0762-prime-number-of-set-bits-in-binary-representation.js)|Easy| 763|[Partition Labels](./solutions/0763-partition-labels.js)|Medium| @@ -592,8 +727,11 @@ 769|[Max Chunks To Make Sorted](./solutions/0769-max-chunks-to-make-sorted.js)|Medium| 770|[Basic Calculator IV](./solutions/0770-basic-calculator-iv.js)|Hard| 771|[Jewels and Stones](./solutions/0771-jewels-and-stones.js)|Easy| +772|[Basic Calculator III](./solutions/0772-basic-calculator-iii.js)|Hard| 773|[Sliding Puzzle](./solutions/0773-sliding-puzzle.js)|Hard| +774|[Minimize Max Distance to Gas Station](./solutions/0774-minimize-max-distance-to-gas-station.js)|Hard| 775|[Global and Local Inversions](./solutions/0775-global-and-local-inversions.js)|Medium| +776|[Split BST](./solutions/0776-split-bst.js)|Medium| 777|[Swap Adjacent in LR String](./solutions/0777-swap-adjacent-in-lr-string.js)|Medium| 778|[Swim in Rising Water](./solutions/0778-swim-in-rising-water.js)|Hard| 779|[K-th Symbol in Grammar](./solutions/0779-k-th-symbol-in-grammar.js)|Medium| @@ -617,6 +755,7 @@ 797|[All Paths From Source to Target](./solutions/0797-all-paths-from-source-to-target.js)|Medium| 798|[Smallest Rotation with Highest Score](./solutions/0798-smallest-rotation-with-highest-score.js)|Hard| 799|[Champagne Tower](./solutions/0799-champagne-tower.js)|Medium| +800|[Similar RGB Color](./solutions/0800-similar-rgb-color.js)|Easy| 801|[Minimum Swaps To Make Sequences Increasing](./solutions/0801-minimum-swaps-to-make-sequences-increasing.js)|Hard| 802|[Find Eventual Safe States](./solutions/0802-find-eventual-safe-states.js)|Medium| 803|[Bricks Falling When Hit](./solutions/0803-bricks-falling-when-hit.js)|Hard| @@ -869,7 +1008,19 @@ 1052|[Grumpy Bookstore Owner](./solutions/1052-grumpy-bookstore-owner.js)|Medium| 1053|[Previous Permutation With One Swap](./solutions/1053-previous-permutation-with-one-swap.js)|Medium| 1054|[Distant Barcodes](./solutions/1054-distant-barcodes.js)|Medium| +1055|[Shortest Way to Form String](./solutions/1055-shortest-way-to-form-string.js)|Medium| +1056|[Confusing Number](./solutions/1056-confusing-number.js)|Easy| +1057|[Campus Bikes](./solutions/1057-campus-bikes.js)|Medium| +1058|[Minimize Rounding Error to Meet Target](./solutions/1058-minimize-rounding-error-to-meet-target.js)|Medium| +1059|[All Paths from Source Lead to Destination](./solutions/1059-all-paths-from-source-lead-to-destination.js)|Medium| +1060|[Missing Element in Sorted Array](./solutions/1060-missing-element-in-sorted-array.js)|Medium| 1061|[Lexicographically Smallest Equivalent String](./solutions/1061-lexicographically-smallest-equivalent-string.js)|Medium| +1062|[Longest Repeating Substring](./solutions/1062-longest-repeating-substring.js)|Medium| +1063|[Number of Valid Subarrays](./solutions/1063-number-of-valid-subarrays.js)|Hard| +1064|[Fixed Point](./solutions/1064-fixed-point.js)|Easy| +1065|[Index Pairs of a String](./solutions/1065-index-pairs-of-a-string.js)|Easy| +1066|[Campus Bikes II](./solutions/1066-campus-bikes-ii.js)|Medium| +1067|[Digit Count in Range](./solutions/1067-digit-count-in-range.js)|Hard| 1071|[Greatest Common Divisor of Strings](./solutions/1071-greatest-common-divisor-of-strings.js)|Easy| 1072|[Flip Columns For Maximum Number of Equal Rows](./solutions/1072-flip-columns-for-maximum-number-of-equal-rows.js)|Medium| 1073|[Adding Two Negabinary Numbers](./solutions/1073-adding-two-negabinary-numbers.js)|Medium| @@ -878,6 +1029,10 @@ 1079|[Letter Tile Possibilities](./solutions/1079-letter-tile-possibilities.js)|Medium| 1080|[Insufficient Nodes in Root to Leaf Paths](./solutions/1080-insufficient-nodes-in-root-to-leaf-paths.js)|Medium| 1081|[Smallest Subsequence of Distinct Characters](./solutions/1081-smallest-subsequence-of-distinct-characters.js)|Medium| +1085|[Sum of Digits in the Minimum Number](./solutions/1085-sum-of-digits-in-the-minimum-number.js)|Easy| +1086|[High Five](./solutions/1086-high-five.js)|Easy| +1087|[Brace Expansion](./solutions/1087-brace-expansion.js)|Medium| +1088|[Confusing Number II](./solutions/1088-confusing-number-ii.js)|Hard| 1089|[Duplicate Zeros](./solutions/1089-duplicate-zeros.js)|Easy| 1090|[Largest Values From Labels](./solutions/1090-largest-values-from-labels.js)|Medium| 1091|[Shortest Path in Binary Matrix](./solutions/1091-shortest-path-in-binary-matrix.js)|Medium| @@ -886,6 +1041,10 @@ 1094|[Car Pooling](./solutions/1094-car-pooling.js)|Medium| 1095|[Find in Mountain Array](./solutions/1095-find-in-mountain-array.js)|Hard| 1096|[Brace Expansion II](./solutions/1096-brace-expansion-ii.js)|Hard| +1099|[Two Sum Less Than K](./solutions/1099-two-sum-less-than-k.js)|Easy| +1100|[Find K-Length Substrings With No Repeated Characters](./solutions/1100-find-k-length-substrings-with-no-repeated-characters.js)|Medium| +1101|[The Earliest Moment When Everyone Become Friends](./solutions/1101-the-earliest-moment-when-everyone-become-friends.js)|Medium| +1102|[Path With Maximum Minimum Value](./solutions/1102-path-with-maximum-minimum-value.js)|Medium| 1103|[Distribute Candies to People](./solutions/1103-distribute-candies-to-people.js)|Easy| 1104|[Path In Zigzag Labelled Binary Tree](./solutions/1104-path-in-zigzag-labelled-binary-tree.js)|Medium| 1105|[Filling Bookcase Shelves](./solutions/1105-filling-bookcase-shelves.js)|Medium| @@ -894,6 +1053,10 @@ 1109|[Corporate Flight Bookings](./solutions/1109-corporate-flight-bookings.js)|Medium| 1110|[Delete Nodes And Return Forest](./solutions/1110-delete-nodes-and-return-forest.js)|Medium| 1111|[Maximum Nesting Depth of Two Valid Parentheses Strings](./solutions/1111-maximum-nesting-depth-of-two-valid-parentheses-strings.js)|Medium| +1118|[Number of Days in a Month](./solutions/1118-number-of-days-in-a-month.js)|Easy| +1119|[Remove Vowels from a String](./solutions/1119-remove-vowels-from-a-string.js)|Easy| +1120|[Maximum Average Subtree](./solutions/1120-maximum-average-subtree.js)|Medium| +1121|[Divide Array Into Increasing Sequences](./solutions/1121-divide-array-into-increasing-sequences.js)|Hard| 1122|[Relative Sort Array](./solutions/1122-relative-sort-array.js)|Easy| 1123|[Lowest Common Ancestor of Deepest Leaves](./solutions/1123-lowest-common-ancestor-of-deepest-leaves.js)|Medium| 1124|[Longest Well-Performing Interval](./solutions/1124-longest-well-performing-interval.js)|Medium| @@ -902,6 +1065,10 @@ 1129|[Shortest Path with Alternating Colors](./solutions/1129-shortest-path-with-alternating-colors.js)|Medium| 1130|[Minimum Cost Tree From Leaf Values](./solutions/1130-minimum-cost-tree-from-leaf-values.js)|Medium| 1131|[Maximum of Absolute Value Expression](./solutions/1131-maximum-of-absolute-value-expression.js)|Medium| +1133|[Largest Unique Number](./solutions/1133-largest-unique-number.js)|Easy| +1134|[Armstrong Number](./solutions/1134-armstrong-number.js)|Easy| +1135|[Connecting Cities With Minimum Cost](./solutions/1135-connecting-cities-with-minimum-cost.js)|Medium| +1136|[Parallel Courses](./solutions/1136-parallel-courses.js)|Medium| 1137|[N-th Tribonacci Number](./solutions/1137-n-th-tribonacci-number.js)|Easy| 1138|[Alphabet Board Path](./solutions/1138-alphabet-board-path.js)|Medium| 1139|[Largest 1-Bordered Square](./solutions/1139-largest-1-bordered-square.js)|Medium| @@ -911,6 +1078,10 @@ 1145|[Binary Tree Coloring Game](./solutions/1145-binary-tree-coloring-game.js)|Medium| 1146|[Snapshot Array](./solutions/1146-snapshot-array.js)|Medium| 1147|[Longest Chunked Palindrome Decomposition](./solutions/1147-longest-chunked-palindrome-decomposition.js)|Hard| +1150|[Check If a Number Is Majority Element in a Sorted Array](./solutions/1150-check-if-a-number-is-majority-element-in-a-sorted-array.js)|Easy| +1151|[Minimum Swaps to Group All 1's Together](./solutions/1151-minimum-swaps-to-group-all-1s-together.js)|Medium| +1152|[Analyze User Website Visit Pattern](./solutions/1152-analyze-user-website-visit-pattern.js)|Medium| +1153|[String Transforms Into Another String](./solutions/1153-string-transforms-into-another-string.js)|Hard| 1154|[Day of the Year](./solutions/1154-day-of-the-year.js)|Easy| 1155|[Number of Dice Rolls With Target Sum](./solutions/1155-number-of-dice-rolls-with-target-sum.js)|Medium| 1156|[Swap For Longest Repeated Character Substring](./solutions/1156-swap-for-longest-repeated-character-substring.js)|Medium| @@ -919,13 +1090,22 @@ 1161|[Maximum Level Sum of a Binary Tree](./solutions/1161-maximum-level-sum-of-a-binary-tree.js)|Medium| 1162|[As Far from Land as Possible](./solutions/1162-as-far-from-land-as-possible.js)|Medium| 1163|[Last Substring in Lexicographical Order](./solutions/1163-last-substring-in-lexicographical-order.js)|Hard| +1165|[Single-Row Keyboard](./solutions/1165-single-row-keyboard.js)|Easy| +1166|[Design File System](./solutions/1166-design-file-system.js)|Medium| +1167|[Minimum Cost to Connect Sticks](./solutions/1167-minimum-cost-to-connect-sticks.js)|Medium| +1168|[Optimize Water Distribution in a Village](./solutions/1168-optimize-water-distribution-in-a-village.js)|Hard| 1169|[Invalid Transactions](./solutions/1169-invalid-transactions.js)|Medium| 1170|[Compare Strings by Frequency of the Smallest Character](./solutions/1170-compare-strings-by-frequency-of-the-smallest-character.js)|Medium| 1171|[Remove Zero Sum Consecutive Nodes from Linked List](./solutions/1171-remove-zero-sum-consecutive-nodes-from-linked-list.js)|Medium| 1172|[Dinner Plate Stacks](./solutions/1172-dinner-plate-stacks.js)|Hard| 1175|[Prime Arrangements](./solutions/1175-prime-arrangements.js)|Easy| +1176|[Diet Plan Performance](./solutions/1176-diet-plan-performance.js)|Easy| 1177|[Can Make Palindrome from Substring](./solutions/1177-can-make-palindrome-from-substring.js)|Medium| 1178|[Number of Valid Words for Each Puzzle](./solutions/1178-number-of-valid-words-for-each-puzzle.js)|Hard| +1180|[Count Substrings with Only One Distinct Letter](./solutions/1180-count-substrings-with-only-one-distinct-letter.js)|Easy| +1181|[Before and After Puzzle](./solutions/1181-before-and-after-puzzle.js)|Medium| +1182|[Shortest Distance to Target Color](./solutions/1182-shortest-distance-to-target-color.js)|Medium| +1183|[Maximum Number of Ones](./solutions/1183-maximum-number-of-ones.js)|Hard| 1184|[Distance Between Bus Stops](./solutions/1184-distance-between-bus-stops.js)|Easy| 1185|[Day of the Week](./solutions/1185-day-of-the-week.js)|Easy| 1186|[Maximum Subarray Sum with One Deletion](./solutions/1186-maximum-subarray-sum-with-one-deletion.js)|Medium| @@ -934,6 +1114,10 @@ 1190|[Reverse Substrings Between Each Pair of Parentheses](./solutions/1190-reverse-substrings-between-each-pair-of-parentheses.js)|Medium| 1191|[K-Concatenation Maximum Sum](./solutions/1191-k-concatenation-maximum-sum.js)|Medium| 1192|[Critical Connections in a Network](./solutions/1192-critical-connections-in-a-network.js)|Hard| +1196|[How Many Apples Can You Put into the Basket](./solutions/1196-how-many-apples-can-you-put-into-the-basket.js)|Easy| +1197|[Minimum Knight Moves](./solutions/1197-minimum-knight-moves.js)|Medium| +1198|[Find Smallest Common Element in All Rows](./solutions/1198-find-smallest-common-element-in-all-rows.js)|Medium| +1199|[Minimum Time to Build Blocks](./solutions/1199-minimum-time-to-build-blocks.js)|Hard| 1200|[Minimum Absolute Difference](./solutions/1200-minimum-absolute-difference.js)|Easy| 1201|[Ugly Number III](./solutions/1201-ugly-number-iii.js)|Medium| 1202|[Smallest String With Swaps](./solutions/1202-smallest-string-with-swaps.js)|Medium| @@ -943,6 +1127,10 @@ 1208|[Get Equal Substrings Within Budget](./solutions/1208-get-equal-substrings-within-budget.js)|Medium| 1209|[Remove All Adjacent Duplicates in String II](./solutions/1209-remove-all-adjacent-duplicates-in-string-ii.js)|Medium| 1210|[Minimum Moves to Reach Target with Rotations](./solutions/1210-minimum-moves-to-reach-target-with-rotations.js)|Hard| +1213|[Intersection of Three Sorted Arrays](./solutions/1213-intersection-of-three-sorted-arrays.js)|Easy| +1214|[Two Sum BSTs](./solutions/1214-two-sum-bsts.js)|Medium| +1215|[Stepping Numbers](./solutions/1215-stepping-numbers.js)|Medium| +1216|[Valid Palindrome III](./solutions/1216-valid-palindrome-iii.js)|Hard| 1217|[Minimum Cost to Move Chips to The Same Position](./solutions/1217-minimum-cost-to-move-chips-to-the-same-position.js)|Easy| 1218|[Longest Arithmetic Subsequence of Given Difference](./solutions/1218-longest-arithmetic-subsequence-of-given-difference.js)|Medium| 1219|[Path with Maximum Gold](./solutions/1219-path-with-maximum-gold.js)|Medium| @@ -952,14 +1140,23 @@ 1223|[Dice Roll Simulation](./solutions/1223-dice-roll-simulation.js)|Hard| 1224|[Maximum Equal Frequency](./solutions/1224-maximum-equal-frequency.js)|Hard| 1227|[Airplane Seat Assignment Probability](./solutions/1227-airplane-seat-assignment-probability.js)|Medium| +1228|[Missing Number In Arithmetic Progression](./solutions/1228-missing-number-in-arithmetic-progression.js)|Easy| +1229|[Meeting Scheduler](./solutions/1229-meeting-scheduler.js)|Medium| +1230|[Toss Strange Coins](./solutions/1230-toss-strange-coins.js)|Medium| +1231|[Divide Chocolate](./solutions/1231-divide-chocolate.js)|Hard| 1232|[Check If It Is a Straight Line](./solutions/1232-check-if-it-is-a-straight-line.js)|Easy| 1233|[Remove Sub-Folders from the Filesystem](./solutions/1233-remove-sub-folders-from-the-filesystem.js)|Medium| 1234|[Replace the Substring for Balanced String](./solutions/1234-replace-the-substring-for-balanced-string.js)|Medium| 1235|[Maximum Profit in Job Scheduling](./solutions/1235-maximum-profit-in-job-scheduling.js)|Hard| +1236|[Web Crawler](./solutions/1236-web-crawler.js)|Medium| 1237|[Find Positive Integer Solution for a Given Equation](./solutions/1237-find-positive-integer-solution-for-a-given-equation.js)|Medium| 1238|[Circular Permutation in Binary Representation](./solutions/1238-circular-permutation-in-binary-representation.js)|Medium| 1239|[Maximum Length of a Concatenated String with Unique Characters](./solutions/1239-maximum-length-of-a-concatenated-string-with-unique-characters.js)|Medium| 1240|[Tiling a Rectangle with the Fewest Squares](./solutions/1240-tiling-a-rectangle-with-the-fewest-squares.js)|Hard| +1243|[Array Transformation](./solutions/1243-array-transformation.js)|Easy| +1244|[Design A Leaderboard](./solutions/1244-design-a-leaderboard.js)|Medium| +1245|[Tree Diameter](./solutions/1245-tree-diameter.js)|Medium| +1246|[Palindrome Removal](./solutions/1246-palindrome-removal.js)|Hard| 1247|[Minimum Swaps to Make Strings Equal](./solutions/1247-minimum-swaps-to-make-strings-equal.js)|Medium| 1248|[Count Number of Nice Subarrays](./solutions/1248-count-number-of-nice-subarrays.js)|Medium| 1249|[Minimum Remove to Make Valid Parentheses](./solutions/1249-minimum-remove-to-make-valid-parentheses.js)|Medium| @@ -968,14 +1165,23 @@ 1253|[Reconstruct a 2-Row Binary Matrix](./solutions/1253-reconstruct-a-2-row-binary-matrix.js)|Medium| 1254|[Number of Closed Islands](./solutions/1254-number-of-closed-islands.js)|Medium| 1255|[Maximum Score Words Formed by Letters](./solutions/1255-maximum-score-words-formed-by-letters.js)|Hard| +1256|[Encode Number](./solutions/1256-encode-number.js)|Medium| +1257|[Smallest Common Region](./solutions/1257-smallest-common-region.js)|Medium| +1258|[Synonymous Sentences](./solutions/1258-synonymous-sentences.js)|Medium| +1259|[Handshakes That Don't Cross](./solutions/1259-handshakes-that-dont-cross.js)|Hard| 1260|[Shift 2D Grid](./solutions/1260-shift-2d-grid.js)|Easy| 1261|[Find Elements in a Contaminated Binary Tree](./solutions/1261-find-elements-in-a-contaminated-binary-tree.js)|Medium| 1262|[Greatest Sum Divisible by Three](./solutions/1262-greatest-sum-divisible-by-three.js)|Medium| 1263|[Minimum Moves to Move a Box to Their Target Location](./solutions/1263-minimum-moves-to-move-a-box-to-their-target-location.js)|Hard| +1265|[Print Immutable Linked List in Reverse](./solutions/1265-print-immutable-linked-list-in-reverse.js)|Medium| 1266|[Minimum Time Visiting All Points](./solutions/1266-minimum-time-visiting-all-points.js)|Easy| 1267|[Count Servers that Communicate](./solutions/1267-count-servers-that-communicate.js)|Medium| 1268|[Search Suggestions System](./solutions/1268-search-suggestions-system.js)|Medium| 1269|[Number of Ways to Stay in the Same Place After Some Steps](./solutions/1269-number-of-ways-to-stay-in-the-same-place-after-some-steps.js)|Hard| +1271|[Hexspeak](./solutions/1271-hexspeak.js)|Easy| +1272|[Remove Interval](./solutions/1272-remove-interval.js)|Medium| +1273|[Delete Tree Nodes](./solutions/1273-delete-tree-nodes.js)|Medium| +1274|[Number of Ships in a Rectangle](./solutions/1274-number-of-ships-in-a-rectangle.js)|Hard| 1275|[Find Winner on a Tic Tac Toe Game](./solutions/1275-find-winner-on-a-tic-tac-toe-game.js)|Easy| 1276|[Number of Burgers with No Waste of Ingredients](./solutions/1276-number-of-burgers-with-no-waste-of-ingredients.js)|Medium| 1277|[Count Square Submatrices with All Ones](./solutions/1277-count-square-submatrices-with-all-ones.js)|Medium| @@ -1105,6 +1311,11 @@ 1423|[Maximum Points You Can Obtain from Cards](./solutions/1423-maximum-points-you-can-obtain-from-cards.js)|Medium| 1424|[Diagonal Traverse II](./solutions/1424-diagonal-traverse-ii.js)|Medium| 1425|[Constrained Subsequence Sum](./solutions/1425-constrained-subsequence-sum.js)|Hard| +1426|[Counting Elements](./solutions/1426-counting-elements.js)|Easy| +1427|[Perform String Shifts](./solutions/1427-perform-string-shifts.js)|Easy| +1428|[Leftmost Column with at Least a One](./solutions/1428-leftmost-column-with-at-least-a-one.js)|Medium| +1429|[First Unique Number](./solutions/1429-first-unique-number.js)|Medium| +1430|[Check If a String Is a Valid Sequence from Root to Leaves Path in a Binary Tree](./solutions/1430-check-if-a-string-is-a-valid-sequence-from-root-to-leaves-path-in-a-binary-tree.js)|Medium| 1431|[Kids With the Greatest Number of Candies](./solutions/1431-kids-with-the-greatest-number-of-candies.js)|Easy| 1432|[Max Difference You Can Get From Changing an Integer](./solutions/1432-max-difference-you-can-get-from-changing-an-integer.js)|Medium| 1433|[Check If a String Can Break Another String](./solutions/1433-check-if-a-string-can-break-another-string.js)|Medium| @@ -1137,10 +1348,12 @@ 1465|[Maximum Area of a Piece of Cake After Horizontal and Vertical Cuts](./solutions/1465-maximum-area-of-a-piece-of-cake-after-horizontal-and-vertical-cuts.js)|Medium| 1466|[Reorder Routes to Make All Paths Lead to the City Zero](./solutions/1466-reorder-routes-to-make-all-paths-lead-to-the-city-zero.js)|Medium| 1467|[Probability of a Two Boxes Having The Same Number of Distinct Balls](./solutions/1467-probability-of-a-two-boxes-having-the-same-number-of-distinct-balls.js)|Hard| +1469|[Find All The Lonely Nodes](./solutions/1469-find-all-the-lonely-nodes.js)|Easy| 1470|[Shuffle the Array](./solutions/1470-shuffle-the-array.js)|Easy| 1471|[The k Strongest Values in an Array](./solutions/1471-the-k-strongest-values-in-an-array.js)|Medium| 1472|[Design Browser History](./solutions/1472-design-browser-history.js)|Medium| 1473|[Paint House III](./solutions/1473-paint-house-iii.js)|Hard| +1474|[Delete N Nodes After M Nodes of a Linked List](./solutions/1474-delete-n-nodes-after-m-nodes-of-a-linked-list.js)|Easy| 1475|[Final Prices With a Special Discount in a Shop](./solutions/1475-final-prices-with-a-special-discount-in-a-shop.js)|Easy| 1476|[Subrectangle Queries](./solutions/1476-subrectangle-queries.js)|Medium| 1477|[Find Two Non-overlapping Sub-arrays Each With Target Sum](./solutions/1477-find-two-non-overlapping-sub-arrays-each-with-target-sum.js)|Medium| @@ -1149,10 +1362,12 @@ 1481|[Least Number of Unique Integers after K Removals](./solutions/1481-least-number-of-unique-integers-after-k-removals.js)|Medium| 1482|[Minimum Number of Days to Make m Bouquets](./solutions/1482-minimum-number-of-days-to-make-m-bouquets.js)|Medium| 1483|[Kth Ancestor of a Tree Node](./solutions/1483-kth-ancestor-of-a-tree-node.js)|Hard| +1485|[Clone Binary Tree With Random Pointer](./solutions/1485-clone-binary-tree-with-random-pointer.js)|Medium| 1486|[XOR Operation in an Array](./solutions/1486-xor-operation-in-an-array.js)|Easy| 1487|[Making File Names Unique](./solutions/1487-making-file-names-unique.js)|Medium| 1488|[Avoid Flood in The City](./solutions/1488-avoid-flood-in-the-city.js)|Medium| 1489|[Find Critical and Pseudo-Critical Edges in Minimum Spanning Tree](./solutions/1489-find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree.js)|Hard| +1490|[Clone N-ary Tree](./solutions/1490-clone-n-ary-tree.js)|Medium| 1491|[Average Salary Excluding the Minimum and Maximum Salary](./solutions/1491-average-salary-excluding-the-minimum-and-maximum-salary.js)|Easy| 1492|[The kth Factor of n](./solutions/1492-the-kth-factor-of-n.js)|Medium| 1493|[Longest Subarray of 1's After Deleting One Element](./solutions/1493-longest-subarray-of-1s-after-deleting-one-element.js)|Medium| @@ -1161,10 +1376,12 @@ 1497|[Check If Array Pairs Are Divisible by k](./solutions/1497-check-if-array-pairs-are-divisible-by-k.js)|Medium| 1498|[Number of Subsequences That Satisfy the Given Sum Condition](./solutions/1498-number-of-subsequences-that-satisfy-the-given-sum-condition.js)|Medium| 1499|[Max Value of Equation](./solutions/1499-max-value-of-equation.js)|Hard| +1500|[Design a File Sharing System](./solutions/1500-design-a-file-sharing-system.js)|Medium| 1502|[Can Make Arithmetic Progression From Sequence](./solutions/1502-can-make-arithmetic-progression-from-sequence.js)|Easy| 1503|[Last Moment Before All Ants Fall Out of a Plank](./solutions/1503-last-moment-before-all-ants-fall-out-of-a-plank.js)|Medium| 1504|[Count Submatrices With All Ones](./solutions/1504-count-submatrices-with-all-ones.js)|Medium| 1505|[Minimum Possible Integer After at Most K Adjacent Swaps On Digits](./solutions/1505-minimum-possible-integer-after-at-most-k-adjacent-swaps-on-digits.js)|Hard| +1506|[Find Root of N-Ary Tree](./solutions/1506-find-root-of-n-ary-tree.js)|Medium| 1507|[Reformat Date](./solutions/1507-reformat-date.js)|Easy| 1508|[Range Sum of Sorted Subarray Sums](./solutions/1508-range-sum-of-sorted-subarray-sums.js)|Medium| 1509|[Minimum Difference Between Largest and Smallest Value in Three Moves](./solutions/1509-minimum-difference-between-largest-and-smallest-value-in-three-moves.js)|Medium| @@ -1173,10 +1390,12 @@ 1513|[Number of Substrings With Only 1s](./solutions/1513-number-of-substrings-with-only-1s.js)|Medium| 1514|[Path with Maximum Probability](./solutions/1514-path-with-maximum-probability.js)|Medium| 1515|[Best Position for a Service Centre](./solutions/1515-best-position-for-a-service-centre.js)|Hard| +1516|[Move Sub-Tree of N-Ary Tree](./solutions/1516-move-sub-tree-of-n-ary-tree.js)|Hard| 1518|[Water Bottles](./solutions/1518-water-bottles.js)|Easy| 1519|[Number of Nodes in the Sub-Tree With the Same Label](./solutions/1519-number-of-nodes-in-the-sub-tree-with-the-same-label.js)|Medium| 1520|[Maximum Number of Non-Overlapping Substrings](./solutions/1520-maximum-number-of-non-overlapping-substrings.js)|Hard| 1521|[Find a Value of a Mysterious Function Closest to Target](./solutions/1521-find-a-value-of-a-mysterious-function-closest-to-target.js)|Hard| +1522|[Diameter of N-Ary Tree](./solutions/1522-diameter-of-n-ary-tree.js)|Medium| 1523|[Count Odd Numbers in an Interval Range](./solutions/1523-count-odd-numbers-in-an-interval-range.js)|Easy| 1524|[Number of Sub-arrays With Odd Sum](./solutions/1524-number-of-sub-arrays-with-odd-sum.js)|Medium| 1525|[Number of Good Ways to Split a String](./solutions/1525-number-of-good-ways-to-split-a-string.js)|Medium| @@ -1185,10 +1404,12 @@ 1529|[Minimum Suffix Flips](./solutions/1529-minimum-suffix-flips.js)|Medium| 1530|[Number of Good Leaf Nodes Pairs](./solutions/1530-number-of-good-leaf-nodes-pairs.js)|Medium| 1531|[String Compression II](./solutions/1531-string-compression-ii.js)|Hard| +1533|[Find the Index of the Large Integer](./solutions/1533-find-the-index-of-the-large-integer.js)|Medium| 1534|[Count Good Triplets](./solutions/1534-count-good-triplets.js)|Easy| 1535|[Find the Winner of an Array Game](./solutions/1535-find-the-winner-of-an-array-game.js)|Medium| 1536|[Minimum Swaps to Arrange a Binary Grid](./solutions/1536-minimum-swaps-to-arrange-a-binary-grid.js)|Medium| 1537|[Get the Maximum Score](./solutions/1537-get-the-maximum-score.js)|Hard| +1538|[Guess the Majority in a Hidden Array](./solutions/1538-guess-the-majority-in-a-hidden-array.js)|Medium| 1539|[Kth Missing Positive Number](./solutions/1539-kth-missing-positive-number.js)|Easy| 1540|[Can Convert String in K Moves](./solutions/1540-can-convert-string-in-k-moves.js)|Medium| 1541|[Minimum Insertions to Balance a Parentheses String](./solutions/1541-minimum-insertions-to-balance-a-parentheses-string.js)|Medium| @@ -1197,10 +1418,12 @@ 1545|[Find Kth Bit in Nth Binary String](./solutions/1545-find-kth-bit-in-nth-binary-string.js)|Medium| 1546|[Maximum Number of Non-Overlapping Subarrays With Sum Equals Target](./solutions/1546-maximum-number-of-non-overlapping-subarrays-with-sum-equals-target.js)|Medium| 1547|[Minimum Cost to Cut a Stick](./solutions/1547-minimum-cost-to-cut-a-stick.js)|Hard| +1548|[The Most Similar Path in a Graph](./solutions/1548-the-most-similar-path-in-a-graph.js)|Hard| 1550|[Three Consecutive Odds](./solutions/1550-three-consecutive-odds.js)|Easy| 1551|[Minimum Operations to Make Array Equal](./solutions/1551-minimum-operations-to-make-array-equal.js)|Medium| 1552|[Magnetic Force Between Two Balls](./solutions/1552-magnetic-force-between-two-balls.js)|Medium| 1553|[Minimum Number of Days to Eat N Oranges](./solutions/1553-minimum-number-of-days-to-eat-n-oranges.js)|Hard| +1554|[Strings Differ by One Character](./solutions/1554-strings-differ-by-one-character.js)|Medium| 1556|[Thousand Separator](./solutions/1556-thousand-separator.js)|Easy| 1557|[Minimum Number of Vertices to Reach All Nodes](./solutions/1557-minimum-number-of-vertices-to-reach-all-nodes.js)|Medium| 1558|[Minimum Numbers of Function Calls to Make Target Array](./solutions/1558-minimum-numbers-of-function-calls-to-make-target-array.js)|Medium| @@ -1209,10 +1432,12 @@ 1561|[Maximum Number of Coins You Can Get](./solutions/1561-maximum-number-of-coins-you-can-get.js)|Medium| 1562|[Find Latest Group of Size M](./solutions/1562-find-latest-group-of-size-m.js)|Medium| 1563|[Stone Game V](./solutions/1563-stone-game-v.js)|Hard| +1564|[Put Boxes Into the Warehouse I](./solutions/1564-put-boxes-into-the-warehouse-i.js)|Medium| 1566|[Detect Pattern of Length M Repeated K or More Times](./solutions/1566-detect-pattern-of-length-m-repeated-k-or-more-times.js)|Easy| 1567|[Maximum Length of Subarray With Positive Product](./solutions/1567-maximum-length-of-subarray-with-positive-product.js)|Medium| 1568|[Minimum Number of Days to Disconnect Island](./solutions/1568-minimum-number-of-days-to-disconnect-island.js)|Hard| 1569|[Number of Ways to Reorder Array to Get Same BST](./solutions/1569-number-of-ways-to-reorder-array-to-get-same-bst.js)|Hard| +1570|[Dot Product of Two Sparse Vectors](./solutions/1570-dot-product-of-two-sparse-vectors.js)|Medium| 1572|[Matrix Diagonal Sum](./solutions/1572-matrix-diagonal-sum.js)|Easy| 1573|[Number of Ways to Split a String](./solutions/1573-number-of-ways-to-split-a-string.js)|Medium| 1574|[Shortest Subarray to be Removed to Make Array Sorted](./solutions/1574-shortest-subarray-to-be-removed-to-make-array-sorted.js)|Medium| @@ -1221,10 +1446,12 @@ 1577|[Number of Ways Where Square of Number Is Equal to Product of Two Numbers](./solutions/1577-number-of-ways-where-square-of-number-is-equal-to-product-of-two-numbers.js)|Medium| 1578|[Minimum Time to Make Rope Colorful](./solutions/1578-minimum-time-to-make-rope-colorful.js)|Medium| 1579|[Remove Max Number of Edges to Keep Graph Fully Traversable](./solutions/1579-remove-max-number-of-edges-to-keep-graph-fully-traversable.js)|Hard| +1580|[Put Boxes Into the Warehouse II](./solutions/1580-put-boxes-into-the-warehouse-ii.js)|Medium| 1582|[Special Positions in a Binary Matrix](./solutions/1582-special-positions-in-a-binary-matrix.js)|Easy| 1583|[Count Unhappy Friends](./solutions/1583-count-unhappy-friends.js)|Medium| 1584|[Min Cost to Connect All Points](./solutions/1584-min-cost-to-connect-all-points.js)|Medium| 1585|[Check If String Is Transformable With Substring Sort Operations](./solutions/1585-check-if-string-is-transformable-with-substring-sort-operations.js)|Hard| +1586|[Binary Search Tree Iterator II](./solutions/1586-binary-search-tree-iterator-ii.js)|Medium| 1588|[Sum of All Odd Length Subarrays](./solutions/1588-sum-of-all-odd-length-subarrays.js)|Easy| 1589|[Maximum Sum Obtained of Any Permutation](./solutions/1589-maximum-sum-obtained-of-any-permutation.js)|Medium| 1590|[Make Sum Divisible by P](./solutions/1590-make-sum-divisible-by-p.js)|Medium| @@ -1233,10 +1460,12 @@ 1593|[Split a String Into the Max Number of Unique Substrings](./solutions/1593-split-a-string-into-the-max-number-of-unique-substrings.js)|Medium| 1594|[Maximum Non Negative Product in a Matrix](./solutions/1594-maximum-non-negative-product-in-a-matrix.js)|Medium| 1595|[Minimum Cost to Connect Two Groups of Points](./solutions/1595-minimum-cost-to-connect-two-groups-of-points.js)|Hard| +1597|[Build Binary Expression Tree From Infix Expression](./solutions/1597-build-binary-expression-tree-from-infix-expression.js)|Hard| 1598|[Crawler Log Folder](./solutions/1598-crawler-log-folder.js)|Easy| 1599|[Maximum Profit of Operating a Centennial Wheel](./solutions/1599-maximum-profit-of-operating-a-centennial-wheel.js)|Medium| 1600|[Throne Inheritance](./solutions/1600-throne-inheritance.js)|Medium| 1601|[Maximum Number of Achievable Transfer Requests](./solutions/1601-maximum-number-of-achievable-transfer-requests.js)|Hard| +1602|[Find Nearest Right Node in Binary Tree](./solutions/1602-find-nearest-right-node-in-binary-tree.js)|Medium| 1603|[Design Parking System](./solutions/1603-design-parking-system.js)|Easy| 1604|[Alert Using Same Key-Card Three or More Times in a One Hour Period](./solutions/1604-alert-using-same-key-card-three-or-more-times-in-a-one-hour-period.js)|Medium| 1605|[Find Valid Matrix Given Row and Column Sums](./solutions/1605-find-valid-matrix-given-row-and-column-sums.js)|Medium| @@ -1245,10 +1474,12 @@ 1609|[Even Odd Tree](./solutions/1609-even-odd-tree.js)|Medium| 1610|[Maximum Number of Visible Points](./solutions/1610-maximum-number-of-visible-points.js)|Hard| 1611|[Minimum One Bit Operations to Make Integers Zero](./solutions/1611-minimum-one-bit-operations-to-make-integers-zero.js)|Hard| +1612|[Check If Two Expression Trees are Equivalent](./solutions/1612-check-if-two-expression-trees-are-equivalent.js)|Medium| 1614|[Maximum Nesting Depth of the Parentheses](./solutions/1614-maximum-nesting-depth-of-the-parentheses.js)|Easy| 1615|[Maximal Network Rank](./solutions/1615-maximal-network-rank.js)|Medium| 1616|[Split Two Strings to Make Palindrome](./solutions/1616-split-two-strings-to-make-palindrome.js)|Medium| 1617|[Count Subtrees With Max Distance Between Cities](./solutions/1617-count-subtrees-with-max-distance-between-cities.js)|Hard| +1618|[Maximum Font to Fit a Sentence in a Screen](./solutions/1618-maximum-font-to-fit-a-sentence-in-a-screen.js)|Medium| 1619|[Mean of Array After Removing Some Elements](./solutions/1619-mean-of-array-after-removing-some-elements.js)|Easy| 1620|[Coordinate With Maximum Network Quality](./solutions/1620-coordinate-with-maximum-network-quality.js)|Medium| 1621|[Number of Sets of K Non-Overlapping Line Segments](./solutions/1621-number-of-sets-of-k-non-overlapping-line-segments.js)|Medium| @@ -1257,10 +1488,12 @@ 1625|[Lexicographically Smallest String After Applying Operations](./solutions/1625-lexicographically-smallest-string-after-applying-operations.js)|Medium| 1626|[Best Team With No Conflicts](./solutions/1626-best-team-with-no-conflicts.js)|Medium| 1627|[Graph Connectivity With Threshold](./solutions/1627-graph-connectivity-with-threshold.js)|Hard| +1628|[Design an Expression Tree With Evaluate Function](./solutions/1628-design-an-expression-tree-with-evaluate-function.js)|Medium| 1629|[Slowest Key](./solutions/1629-slowest-key.js)|Easy| 1630|[Arithmetic Subarrays](./solutions/1630-arithmetic-subarrays.js)|Medium| 1631|[Path With Minimum Effort](./solutions/1631-path-with-minimum-effort.js)|Medium| 1632|[Rank Transform of a Matrix](./solutions/1632-rank-transform-of-a-matrix.js)|Hard| +1634|[Add Two Polynomials Represented as Linked Lists](./solutions/1634-add-two-polynomials-represented-as-linked-lists.js)|Medium| 1636|[Sort Array by Increasing Frequency](./solutions/1636-sort-array-by-increasing-frequency.js)|Easy| 1637|[Widest Vertical Area Between Two Points Containing No Points](./solutions/1637-widest-vertical-area-between-two-points-containing-no-points.js)|Easy| 1638|[Count Substrings That Differ by One Character](./solutions/1638-count-substrings-that-differ-by-one-character.js)|Medium| @@ -1269,10 +1502,12 @@ 1641|[Count Sorted Vowel Strings](./solutions/1641-count-sorted-vowel-strings.js)|Medium| 1642|[Furthest Building You Can Reach](./solutions/1642-furthest-building-you-can-reach.js)|Medium| 1643|[Kth Smallest Instructions](./solutions/1643-kth-smallest-instructions.js)|Hard| +1644|[Lowest Common Ancestor of a Binary Tree II](./solutions/1644-lowest-common-ancestor-of-a-binary-tree-ii.js)|Medium| 1646|[Get Maximum in Generated Array](./solutions/1646-get-maximum-in-generated-array.js)|Easy| 1647|[Minimum Deletions to Make Character Frequencies Unique](./solutions/1647-minimum-deletions-to-make-character-frequencies-unique.js)|Medium| 1648|[Sell Diminishing-Valued Colored Balls](./solutions/1648-sell-diminishing-valued-colored-balls.js)|Medium| 1649|[Create Sorted Array through Instructions](./solutions/1649-create-sorted-array-through-instructions.js)|Hard| +1650|[Lowest Common Ancestor of a Binary Tree III](./solutions/1650-lowest-common-ancestor-of-a-binary-tree-iii.js)|Medium| 1652|[Defuse the Bomb](./solutions/1652-defuse-the-bomb.js)|Easy| 1653|[Minimum Deletions to Make String Balanced](./solutions/1653-minimum-deletions-to-make-string-balanced.js)|Medium| 1654|[Minimum Jumps to Reach Home](./solutions/1654-minimum-jumps-to-reach-home.js)|Medium| @@ -1281,10 +1516,12 @@ 1657|[Determine if Two Strings Are Close](./solutions/1657-determine-if-two-strings-are-close.js)|Medium| 1658|[Minimum Operations to Reduce X to Zero](./solutions/1658-minimum-operations-to-reduce-x-to-zero.js)|Medium| 1659|[Maximize Grid Happiness](./solutions/1659-maximize-grid-happiness.js)|Hard| +1660|[Correct a Binary Tree](./solutions/1660-correct-a-binary-tree.js)|Medium| 1662|[Check If Two String Arrays are Equivalent](./solutions/1662-check-if-two-string-arrays-are-equivalent.js)|Easy| 1663|[Smallest String With A Given Numeric Value](./solutions/1663-smallest-string-with-a-given-numeric-value.js)|Medium| 1664|[Ways to Make a Fair Array](./solutions/1664-ways-to-make-a-fair-array.js)|Medium| 1665|[Minimum Initial Energy to Finish Tasks](./solutions/1665-minimum-initial-energy-to-finish-tasks.js)|Hard| +1666|[Change the Root of a Binary Tree](./solutions/1666-change-the-root-of-a-binary-tree.js)|Medium| 1668|[Maximum Repeating Substring](./solutions/1668-maximum-repeating-substring.js)|Easy| 1669|[Merge In Between Linked Lists](./solutions/1669-merge-in-between-linked-lists.js)|Medium| 1670|[Design Front Middle Back Queue](./solutions/1670-design-front-middle-back-queue.js)|Medium| @@ -1293,10 +1530,12 @@ 1673|[Find the Most Competitive Subsequence](./solutions/1673-find-the-most-competitive-subsequence.js)|Medium| 1674|[Minimum Moves to Make Array Complementary](./solutions/1674-minimum-moves-to-make-array-complementary.js)|Medium| 1675|[Minimize Deviation in Array](./solutions/1675-minimize-deviation-in-array.js)|Hard| +1676|[Lowest Common Ancestor of a Binary Tree IV](./solutions/1676-lowest-common-ancestor-of-a-binary-tree-iv.js)|Medium| 1678|[Goal Parser Interpretation](./solutions/1678-goal-parser-interpretation.js)|Easy| 1679|[Max Number of K-Sum Pairs](./solutions/1679-max-number-of-k-sum-pairs.js)|Medium| 1680|[Concatenation of Consecutive Binary Numbers](./solutions/1680-concatenation-of-consecutive-binary-numbers.js)|Medium| 1681|[Minimum Incompatibility](./solutions/1681-minimum-incompatibility.js)|Hard| +1682|[Longest Palindromic Subsequence II](./solutions/1682-longest-palindromic-subsequence-ii.js)|Medium| 1684|[Count the Number of Consistent Strings](./solutions/1684-count-the-number-of-consistent-strings.js)|Easy| 1685|[Sum of Absolute Differences in a Sorted Array](./solutions/1685-sum-of-absolute-differences-in-a-sorted-array.js)|Medium| 1686|[Stone Game VI](./solutions/1686-stone-game-vi.js)|Medium| @@ -1305,10 +1544,12 @@ 1689|[Partitioning Into Minimum Number Of Deci-Binary Numbers](./solutions/1689-partitioning-into-minimum-number-of-deci-binary-numbers.js)|Medium| 1690|[Stone Game VII](./solutions/1690-stone-game-vii.js)|Medium| 1691|[Maximum Height by Stacking Cuboids](./solutions/1691-maximum-height-by-stacking-cuboids.js)|Hard| +1692|[Count Ways to Distribute Candies](./solutions/1692-count-ways-to-distribute-candies.js)|Hard| 1694|[Reformat Phone Number](./solutions/1694-reformat-phone-number.js)|Easy| 1695|[Maximum Erasure Value](./solutions/1695-maximum-erasure-value.js)|Medium| 1696|[Jump Game VI](./solutions/1696-jump-game-vi.js)|Medium| 1697|[Checking Existence of Edge Length Limited Paths](./solutions/1697-checking-existence-of-edge-length-limited-paths.js)|Hard| +1698|[Number of Distinct Substrings in a String](./solutions/1698-number-of-distinct-substrings-in-a-string.js)|Medium| 1700|[Number of Students Unable to Eat Lunch](./solutions/1700-number-of-students-unable-to-eat-lunch.js)|Easy| 1701|[Average Waiting Time](./solutions/1701-average-waiting-time.js)|Medium| 1702|[Maximum Binary String After Change](./solutions/1702-maximum-binary-string-after-change.js)|Medium| @@ -1317,10 +1558,12 @@ 1705|[Maximum Number of Eaten Apples](./solutions/1705-maximum-number-of-eaten-apples.js)|Medium| 1706|[Where Will the Ball Fall](./solutions/1706-where-will-the-ball-fall.js)|Medium| 1707|[Maximum XOR With an Element From Array](./solutions/1707-maximum-xor-with-an-element-from-array.js)|Hard| +1708|[Largest Subarray Length K](./solutions/1708-largest-subarray-length-k.js)|Easy| 1710|[Maximum Units on a Truck](./solutions/1710-maximum-units-on-a-truck.js)|Easy| 1711|[Count Good Meals](./solutions/1711-count-good-meals.js)|Medium| 1712|[Ways to Split Array Into Three Subarrays](./solutions/1712-ways-to-split-array-into-three-subarrays.js)|Medium| 1713|[Minimum Operations to Make a Subsequence](./solutions/1713-minimum-operations-to-make-a-subsequence.js)|Hard| +1714|[Sum Of Special Evenly-Spaced Elements In Array](./solutions/1714-sum-of-special-evenly-spaced-elements-in-array.js)|Hard| 1716|[Calculate Money in Leetcode Bank](./solutions/1716-calculate-money-in-leetcode-bank.js)|Easy| 1717|[Maximum Score From Removing Substrings](./solutions/1717-maximum-score-from-removing-substrings.js)|Medium| 1718|[Construct the Lexicographically Largest Valid Sequence](./solutions/1718-construct-the-lexicographically-largest-valid-sequence.js)|Medium| @@ -1329,10 +1572,12 @@ 1721|[Swapping Nodes in a Linked List](./solutions/1721-swapping-nodes-in-a-linked-list.js)|Medium| 1722|[Minimize Hamming Distance After Swap Operations](./solutions/1722-minimize-hamming-distance-after-swap-operations.js)|Medium| 1723|[Find Minimum Time to Finish All Jobs](./solutions/1723-find-minimum-time-to-finish-all-jobs.js)|Hard| +1724|[Checking Existence of Edge Length Limited Paths II](./solutions/1724-checking-existence-of-edge-length-limited-paths-ii.js)|Hard| 1725|[Number Of Rectangles That Can Form The Largest Square](./solutions/1725-number-of-rectangles-that-can-form-the-largest-square.js)|Easy| 1726|[Tuple with Same Product](./solutions/1726-tuple-with-same-product.js)|Medium| 1727|[Largest Submatrix With Rearrangements](./solutions/1727-largest-submatrix-with-rearrangements.js)|Medium| 1728|[Cat and Mouse II](./solutions/1728-cat-and-mouse-ii.js)|Hard| +1730|[Shortest Path to Get Food](./solutions/1730-shortest-path-to-get-food.js)|Medium| 1732|[Find the Highest Altitude](./solutions/1732-find-the-highest-altitude.js)|Easy| 1733|[Minimum Number of People to Teach](./solutions/1733-minimum-number-of-people-to-teach.js)|Medium| 1734|[Decode XORed Permutation](./solutions/1734-decode-xored-permutation.js)|Medium| @@ -1341,10 +1586,12 @@ 1737|[Change Minimum Characters to Satisfy One of Three Conditions](./solutions/1737-change-minimum-characters-to-satisfy-one-of-three-conditions.js)|Medium| 1738|[Find Kth Largest XOR Coordinate Value](./solutions/1738-find-kth-largest-xor-coordinate-value.js)|Medium| 1739|[Building Boxes](./solutions/1739-building-boxes.js)|Hard| +1740|[Find Distance in a Binary Tree](./solutions/1740-find-distance-in-a-binary-tree.js)|Medium| 1742|[Maximum Number of Balls in a Box](./solutions/1742-maximum-number-of-balls-in-a-box.js)|Easy| 1743|[Restore the Array From Adjacent Pairs](./solutions/1743-restore-the-array-from-adjacent-pairs.js)|Medium| 1744|[Can You Eat Your Favorite Candy on Your Favorite Day?](./solutions/1744-can-you-eat-your-favorite-candy-on-your-favorite-day.js)|Medium| 1745|[Palindrome Partitioning IV](./solutions/1745-palindrome-partitioning-iv.js)|Hard| +1746|[Maximum Subarray Sum After One Operation](./solutions/1746-maximum-subarray-sum-after-one-operation.js)|Medium| 1748|[Sum of Unique Elements](./solutions/1748-sum-of-unique-elements.js)|Easy| 1749|[Maximum Absolute Sum of Any Subarray](./solutions/1749-maximum-absolute-sum-of-any-subarray.js)|Medium| 1750|[Minimum Length of String After Deleting Similar Ends](./solutions/1750-minimum-length-of-string-after-deleting-similar-ends.js)|Medium| @@ -1353,10 +1600,12 @@ 1753|[Maximum Score From Removing Stones](./solutions/1753-maximum-score-from-removing-stones.js)|Medium| 1754|[Largest Merge Of Two Strings](./solutions/1754-largest-merge-of-two-strings.js)|Medium| 1755|[Closest Subsequence Sum](./solutions/1755-closest-subsequence-sum.js)|Hard| +1756|[Design Most Recently Used Queue](./solutions/1756-design-most-recently-used-queue.js)|Medium| 1758|[Minimum Changes To Make Alternating Binary String](./solutions/1758-minimum-changes-to-make-alternating-binary-string.js)|Easy| 1759|[Count Number of Homogenous Substrings](./solutions/1759-count-number-of-homogenous-substrings.js)|Medium| 1760|[Minimum Limit of Balls in a Bag](./solutions/1760-minimum-limit-of-balls-in-a-bag.js)|Medium| 1761|[Minimum Degree of a Connected Trio in a Graph](./solutions/1761-minimum-degree-of-a-connected-trio-in-a-graph.js)|Hard| +1762|[Buildings With an Ocean View](./solutions/1762-buildings-with-an-ocean-view.js)|Medium| 1763|[Longest Nice Substring](./solutions/1763-longest-nice-substring.js)|Easy| 1764|[Form Array by Concatenating Subarrays of Another Array](./solutions/1764-form-array-by-concatenating-subarrays-of-another-array.js)|Medium| 1765|[Map of Highest Peak](./solutions/1765-map-of-highest-peak.js)|Medium| @@ -1365,10 +1614,12 @@ 1769|[Minimum Number of Operations to Move All Balls to Each Box](./solutions/1769-minimum-number-of-operations-to-move-all-balls-to-each-box.js)|Medium| 1770|[Maximum Score from Performing Multiplication Operations](./solutions/1770-maximum-score-from-performing-multiplication-operations.js)|Hard| 1771|[Maximize Palindrome Length From Subsequences](./solutions/1771-maximize-palindrome-length-from-subsequences.js)|Hard| +1772|[Sort Features by Popularity](./solutions/1772-sort-features-by-popularity.js)|Medium| 1773|[Count Items Matching a Rule](./solutions/1773-count-items-matching-a-rule.js)|Easy| 1774|[Closest Dessert Cost](./solutions/1774-closest-dessert-cost.js)|Medium| 1775|[Equal Sum Arrays With Minimum Number of Operations](./solutions/1775-equal-sum-arrays-with-minimum-number-of-operations.js)|Medium| 1776|[Car Fleet II](./solutions/1776-car-fleet-ii.js)|Hard| +1778|[Shortest Path in a Hidden Grid](./solutions/1778-shortest-path-in-a-hidden-grid.js)|Medium| 1779|[Find Nearest Point That Has the Same X or Y Coordinate](./solutions/1779-find-nearest-point-that-has-the-same-x-or-y-coordinate.js)|Easy| 1780|[Check if Number is a Sum of Powers of Three](./solutions/1780-check-if-number-is-a-sum-of-powers-of-three.js)|Medium| 1781|[Sum of Beauty of All Substrings](./solutions/1781-sum-of-beauty-of-all-substrings.js)|Medium| @@ -1377,10 +1628,12 @@ 1785|[Minimum Elements to Add to Form a Given Sum](./solutions/1785-minimum-elements-to-add-to-form-a-given-sum.js)|Medium| 1786|[Number of Restricted Paths From First to Last Node](./solutions/1786-number-of-restricted-paths-from-first-to-last-node.js)|Medium| 1787|[Make the XOR of All Segments Equal to Zero](./solutions/1787-make-the-xor-of-all-segments-equal-to-zero.js)|Hard| +1788|[Maximize the Beauty of the Garden](./solutions/1788-maximize-the-beauty-of-the-garden.js)|Hard| 1790|[Check if One String Swap Can Make Strings Equal](./solutions/1790-check-if-one-string-swap-can-make-strings-equal.js)|Easy| 1791|[Find Center of Star Graph](./solutions/1791-find-center-of-star-graph.js)|Easy| 1792|[Maximum Average Pass Ratio](./solutions/1792-maximum-average-pass-ratio.js)|Medium| 1793|[Maximum Score of a Good Subarray](./solutions/1793-maximum-score-of-a-good-subarray.js)|Hard| +1794|[Count Pairs of Equal Substrings With Minimum Difference](./solutions/1794-count-pairs-of-equal-substrings-with-minimum-difference.js)|Medium| 1796|[Second Largest Digit in a String](./solutions/1796-second-largest-digit-in-a-string.js)|Easy| 1797|[Design Authentication Manager](./solutions/1797-design-authentication-manager.js)|Medium| 1798|[Maximum Number of Consecutive Values You Can Make](./solutions/1798-maximum-number-of-consecutive-values-you-can-make.js)|Medium| @@ -1389,10 +1642,12 @@ 1801|[Number of Orders in the Backlog](./solutions/1801-number-of-orders-in-the-backlog.js)|Medium| 1802|[Maximum Value at a Given Index in a Bounded Array](./solutions/1802-maximum-value-at-a-given-index-in-a-bounded-array.js)|Medium| 1803|[Count Pairs With XOR in a Range](./solutions/1803-count-pairs-with-xor-in-a-range.js)|Hard| +1804|[Implement Trie II (Prefix Tree)](./solutions/1804-implement-trie-ii-prefix-tree.js)|Medium| 1805|[Number of Different Integers in a String](./solutions/1805-number-of-different-integers-in-a-string.js)|Easy| 1806|[Minimum Number of Operations to Reinitialize a Permutation](./solutions/1806-minimum-number-of-operations-to-reinitialize-a-permutation.js)|Medium| 1807|[Evaluate the Bracket Pairs of a String](./solutions/1807-evaluate-the-bracket-pairs-of-a-string.js)|Medium| 1808|[Maximize Number of Nice Divisors](./solutions/1808-maximize-number-of-nice-divisors.js)|Hard| +1810|[Minimum Path Cost in a Hidden Grid](./solutions/1810-minimum-path-cost-in-a-hidden-grid.js)|Medium| 1812|[Determine Color of a Chessboard Square](./solutions/1812-determine-color-of-a-chessboard-square.js)|Easy| 1813|[Sentence Similarity III](./solutions/1813-sentence-similarity-iii.js)|Medium| 1814|[Count Nice Pairs in an Array](./solutions/1814-count-nice-pairs-in-an-array.js)|Medium| @@ -1401,10 +1656,12 @@ 1817|[Finding the Users Active Minutes](./solutions/1817-finding-the-users-active-minutes.js)|Medium| 1818|[Minimum Absolute Sum Difference](./solutions/1818-minimum-absolute-sum-difference.js)|Medium| 1819|[Number of Different Subsequences GCDs](./solutions/1819-number-of-different-subsequences-gcds.js)|Hard| +1820|[Maximum Number of Accepted Invitations](./solutions/1820-maximum-number-of-accepted-invitations.js)|Medium| 1822|[Sign of the Product of an Array](./solutions/1822-sign-of-the-product-of-an-array.js)|Easy| 1823|[Find the Winner of the Circular Game](./solutions/1823-find-the-winner-of-the-circular-game.js)|Medium| 1824|[Minimum Sideway Jumps](./solutions/1824-minimum-sideway-jumps.js)|Medium| 1825|[Finding MK Average](./solutions/1825-finding-mk-average.js)|Hard| +1826|[Faulty Sensor](./solutions/1826-faulty-sensor.js)|Easy| 1827|[Minimum Operations to Make the Array Increasing](./solutions/1827-minimum-operations-to-make-the-array-increasing.js)|Easy| 1828|[Queries on Number of Points Inside a Circle](./solutions/1828-queries-on-number-of-points-inside-a-circle.js)|Medium| 1829|[Maximum XOR for Each Query](./solutions/1829-maximum-xor-for-each-query.js)|Medium| @@ -1413,10 +1670,12 @@ 1833|[Maximum Ice Cream Bars](./solutions/1833-maximum-ice-cream-bars.js)|Medium| 1834|[Single-Threaded CPU](./solutions/1834-single-threaded-cpu.js)|Medium| 1835|[Find XOR Sum of All Pairs Bitwise AND](./solutions/1835-find-xor-sum-of-all-pairs-bitwise-and.js)|Hard| +1836|[Remove Duplicates From an Unsorted Linked List](./solutions/1836-remove-duplicates-from-an-unsorted-linked-list.js)|Medium| 1837|[Sum of Digits in Base K](./solutions/1837-sum-of-digits-in-base-k.js)|Easy| 1838|[Frequency of the Most Frequent Element](./solutions/1838-frequency-of-the-most-frequent-element.js)|Medium| 1839|[Longest Substring Of All Vowels in Order](./solutions/1839-longest-substring-of-all-vowels-in-order.js)|Medium| 1840|[Maximum Building Height](./solutions/1840-maximum-building-height.js)|Hard| +1842|[Next Palindrome Using Same Digits](./solutions/1842-next-palindrome-using-same-digits.js)|Hard| 1844|[Replace All Digits with Characters](./solutions/1844-replace-all-digits-with-characters.js)|Easy| 1845|[Seat Reservation Manager](./solutions/1845-seat-reservation-manager.js)|Medium| 1846|[Maximum Element After Decreasing and Rearranging](./solutions/1846-maximum-element-after-decreasing-and-rearranging.js)|Medium| @@ -1425,10 +1684,12 @@ 1849|[Splitting a String Into Descending Consecutive Values](./solutions/1849-splitting-a-string-into-descending-consecutive-values.js)|Medium| 1850|[Minimum Adjacent Swaps to Reach the Kth Smallest Number](./solutions/1850-minimum-adjacent-swaps-to-reach-the-kth-smallest-number.js)|Medium| 1851|[Minimum Interval to Include Each Query](./solutions/1851-minimum-interval-to-include-each-query.js)|Hard| +1852|[Distinct Numbers in Each Subarray](./solutions/1852-distinct-numbers-in-each-subarray.js)|Medium| 1854|[Maximum Population Year](./solutions/1854-maximum-population-year.js)|Easy| 1855|[Maximum Distance Between a Pair of Values](./solutions/1855-maximum-distance-between-a-pair-of-values.js)|Medium| 1856|[Maximum Subarray Min-Product](./solutions/1856-maximum-subarray-min-product.js)|Medium| 1857|[Largest Color Value in a Directed Graph](./solutions/1857-largest-color-value-in-a-directed-graph.js)|Hard| +1858|[Longest Word With All Prefixes](./solutions/1858-longest-word-with-all-prefixes.js)|Medium| 1859|[Sorting the Sentence](./solutions/1859-sorting-the-sentence.js)|Easy| 1860|[Incremental Memory Leak](./solutions/1860-incremental-memory-leak.js)|Medium| 1861|[Rotating the Box](./solutions/1861-rotating-the-box.js)|Medium| @@ -1437,10 +1698,12 @@ 1864|[Minimum Number of Swaps to Make the Binary String Alternating](./solutions/1864-minimum-number-of-swaps-to-make-the-binary-string-alternating.js)|Medium| 1865|[Finding Pairs With a Certain Sum](./solutions/1865-finding-pairs-with-a-certain-sum.js)|Medium| 1866|[Number of Ways to Rearrange Sticks With K Sticks Visible](./solutions/1866-number-of-ways-to-rearrange-sticks-with-k-sticks-visible.js)|Hard| +1868|[Product of Two Run-Length Encoded Arrays](./solutions/1868-product-of-two-run-length-encoded-arrays.js)|Medium| 1869|[Longer Contiguous Segments of Ones than Zeros](./solutions/1869-longer-contiguous-segments-of-ones-than-zeros.js)|Easy| 1870|[Minimum Speed to Arrive on Time](./solutions/1870-minimum-speed-to-arrive-on-time.js)|Medium| 1871|[Jump Game VII](./solutions/1871-jump-game-vii.js)|Medium| 1872|[Stone Game VIII](./solutions/1872-stone-game-viii.js)|Hard| +1874|[Minimize Product Sum of Two Arrays](./solutions/1874-minimize-product-sum-of-two-arrays.js)|Medium| 1876|[Substrings of Size Three with Distinct Characters](./solutions/1876-substrings-of-size-three-with-distinct-characters.js)|Easy| 1877|[Minimize Maximum Pair Sum in Array](./solutions/1877-minimize-maximum-pair-sum-in-array.js)|Medium| 1878|[Get Biggest Three Rhombus Sums in a Grid](./solutions/1878-get-biggest-three-rhombus-sums-in-a-grid.js)|Medium| @@ -1450,10 +1713,12 @@ 1882|[Process Tasks Using Servers](./solutions/1882-process-tasks-using-servers.js)|Medium| 1883|[Minimum Skips to Arrive at Meeting On Time](./solutions/1883-minimum-skips-to-arrive-at-meeting-on-time.js)|Hard| 1884|[Egg Drop With 2 Eggs and N Floors](./solutions/1884-egg-drop-with-2-eggs-and-n-floors.js)|Medium| +1885|[Count Pairs in Two Arrays](./solutions/1885-count-pairs-in-two-arrays.js)|Medium| 1886|[Determine Whether Matrix Can Be Obtained By Rotation](./solutions/1886-determine-whether-matrix-can-be-obtained-by-rotation.js)|Easy| 1887|[Reduction Operations to Make the Array Elements Equal](./solutions/1887-reduction-operations-to-make-the-array-elements-equal.js)|Medium| 1888|[Minimum Number of Flips to Make the Binary String Alternating](./solutions/1888-minimum-number-of-flips-to-make-the-binary-string-alternating.js)|Medium| 1889|[Minimum Space Wasted From Packaging](./solutions/1889-minimum-space-wasted-from-packaging.js)|Hard| +1891|[Cutting Ribbons](./solutions/1891-cutting-ribbons.js)|Medium| 1893|[Check if All the Integers in a Range Are Covered](./solutions/1893-check-if-all-the-integers-in-a-range-are-covered.js)|Easy| 1894|[Find the Student that Will Replace the Chalk](./solutions/1894-find-the-student-that-will-replace-the-chalk.js)|Medium| 1895|[Largest Magic Square](./solutions/1895-largest-magic-square.js)|Medium| @@ -1463,10 +1728,12 @@ 1899|[Merge Triplets to Form Target Triplet](./solutions/1899-merge-triplets-to-form-target-triplet.js)|Medium| 1900|[The Earliest and Latest Rounds Where Players Compete](./solutions/1900-the-earliest-and-latest-rounds-where-players-compete.js)|Hard| 1901|[Find a Peak Element II](./solutions/1901-find-a-peak-element-ii.js)|Medium| +1902|[Depth of BST Given Insertion Order](./solutions/1902-depth-of-bst-given-insertion-order.js)|Medium| 1903|[Largest Odd Number in String](./solutions/1903-largest-odd-number-in-string.js)|Easy| 1904|[The Number of Full Rounds You Have Played](./solutions/1904-the-number-of-full-rounds-you-have-played.js)|Medium| 1905|[Count Sub Islands](./solutions/1905-count-sub-islands.js)|Medium| 1906|[Minimum Absolute Difference Queries](./solutions/1906-minimum-absolute-difference-queries.js)|Medium| +1908|[Game of Nim](./solutions/1908-game-of-nim.js)|Medium| 1909|[Remove One Element to Make the Array Strictly Increasing](./solutions/1909-remove-one-element-to-make-the-array-strictly-increasing.js)|Easy| 1910|[Remove All Occurrences of a Substring](./solutions/1910-remove-all-occurrences-of-a-substring.js)|Medium| 1911|[Maximum Alternating Subsequence Sum](./solutions/1911-maximum-alternating-subsequence-sum.js)|Medium| @@ -1475,10 +1742,12 @@ 1914|[Cyclically Rotating a Grid](./solutions/1914-cyclically-rotating-a-grid.js)|Medium| 1915|[Number of Wonderful Substrings](./solutions/1915-number-of-wonderful-substrings.js)|Medium| 1916|[Count Ways to Build Rooms in an Ant Colony](./solutions/1916-count-ways-to-build-rooms-in-an-ant-colony.js)|Hard| +1918|[Kth Smallest Subarray Sum](./solutions/1918-kth-smallest-subarray-sum.js)|Medium| 1920|[Build Array from Permutation](./solutions/1920-build-array-from-permutation.js)|Easy| 1921|[Eliminate Maximum Number of Monsters](./solutions/1921-eliminate-maximum-number-of-monsters.js)|Medium| 1922|[Count Good Numbers](./solutions/1922-count-good-numbers.js)|Medium| 1923|[Longest Common Subpath](./solutions/1923-longest-common-subpath.js)|Hard| +1924|[Erect the Fence II](./solutions/1924-erect-the-fence-ii.js)|Hard| 1925|[Count Square Sum Triples](./solutions/1925-count-square-sum-triples.js)|Easy| 1926|[Nearest Exit from Entrance in Maze](./solutions/1926-nearest-exit-from-entrance-in-maze.js)|Medium| 1927|[Sum Game](./solutions/1927-sum-game.js)|Medium| @@ -1487,33 +1756,41 @@ 1930|[Unique Length-3 Palindromic Subsequences](./solutions/1930-unique-length-3-palindromic-subsequences.js)|Medium| 1931|[Painting a Grid With Three Different Colors](./solutions/1931-painting-a-grid-with-three-different-colors.js)|Hard| 1932|[Merge BSTs to Create Single BST](./solutions/1932-merge-bsts-to-create-single-bst.js)|Hard| +1933|[Check if String Is Decomposable Into Value-Equal Substrings](./solutions/1933-check-if-string-is-decomposable-into-value-equal-substrings.js)|Easy| 1935|[Maximum Number of Words You Can Type](./solutions/1935-maximum-number-of-words-you-can-type.js)|Easy| 1936|[Add Minimum Number of Rungs](./solutions/1936-add-minimum-number-of-rungs.js)|Medium| 1937|[Maximum Number of Points with Cost](./solutions/1937-maximum-number-of-points-with-cost.js)|Medium| 1938|[Maximum Genetic Difference Query](./solutions/1938-maximum-genetic-difference-query.js)|Hard| +1940|[Longest Common Subsequence Between Sorted Arrays](./solutions/1940-longest-common-subsequence-between-sorted-arrays.js)|Medium| 1941|[Check if All Characters Have Equal Number of Occurrences](./solutions/1941-check-if-all-characters-have-equal-number-of-occurrences.js)|Easy| +1942|[The Number of the Smallest Unoccupied Chair](./solutions/1942-the-number-of-the-smallest-unoccupied-chair.js)|Medium| 1943|[Describe the Painting](./solutions/1943-describe-the-painting.js)|Medium| 1944|[Number of Visible People in a Queue](./solutions/1944-number-of-visible-people-in-a-queue.js)|Hard| 1945|[Sum of Digits of String After Convert](./solutions/1945-sum-of-digits-of-string-after-convert.js)|Easy| 1946|[Largest Number After Mutating Substring](./solutions/1946-largest-number-after-mutating-substring.js)|Medium| 1947|[Maximum Compatibility Score Sum](./solutions/1947-maximum-compatibility-score-sum.js)|Medium| 1948|[Delete Duplicate Folders in System](./solutions/1948-delete-duplicate-folders-in-system.js)|Hard| +1950|[Maximum of Minimum Values in All Subarrays](./solutions/1950-maximum-of-minimum-values-in-all-subarrays.js)|Medium| 1952|[Three Divisors](./solutions/1952-three-divisors.js)|Easy| 1953|[Maximum Number of Weeks for Which You Can Work](./solutions/1953-maximum-number-of-weeks-for-which-you-can-work.js)|Medium| 1954|[Minimum Garden Perimeter to Collect Enough Apples](./solutions/1954-minimum-garden-perimeter-to-collect-enough-apples.js)|Medium| 1955|[Count Number of Special Subsequences](./solutions/1955-count-number-of-special-subsequences.js)|Hard| +1956|[Minimum Time For K Virus Variants to Spread](./solutions/1956-minimum-time-for-k-virus-variants-to-spread.js)|Hard| 1957|[Delete Characters to Make Fancy String](./solutions/1957-delete-characters-to-make-fancy-string.js)|Easy| 1958|[Check if Move is Legal](./solutions/1958-check-if-move-is-legal.js)|Medium| 1959|[Minimum Total Space Wasted With K Resizing Operations](./solutions/1959-minimum-total-space-wasted-with-k-resizing-operations.js)|Medium| 1960|[Maximum Product of the Length of Two Palindromic Substrings](./solutions/1960-maximum-product-of-the-length-of-two-palindromic-substrings.js)|Hard| 1961|[Check If String Is a Prefix of Array](./solutions/1961-check-if-string-is-a-prefix-of-array.js)|Easy| +1962|[Remove Stones to Minimize the Total](./solutions/1962-remove-stones-to-minimize-the-total.js)|Medium| 1963|[Minimum Number of Swaps to Make the String Balanced](./solutions/1963-minimum-number-of-swaps-to-make-the-string-balanced.js)|Medium| 1964|[Find the Longest Valid Obstacle Course at Each Position](./solutions/1964-find-the-longest-valid-obstacle-course-at-each-position.js)|Hard| +1966|[Binary Searchable Numbers in an Unsorted Array](./solutions/1966-binary-searchable-numbers-in-an-unsorted-array.js)|Medium| 1967|[Number of Strings That Appear as Substrings in Word](./solutions/1967-number-of-strings-that-appear-as-substrings-in-word.js)|Easy| 1968|[Array With Elements Not Equal to Average of Neighbors](./solutions/1968-array-with-elements-not-equal-to-average-of-neighbors.js)|Medium| 1969|[Minimum Non-Zero Product of the Array Elements](./solutions/1969-minimum-non-zero-product-of-the-array-elements.js)|Medium| 1970|[Last Day Where You Can Still Cross](./solutions/1970-last-day-where-you-can-still-cross.js)|Hard| 1971|[Find if Path Exists in Graph](./solutions/1971-find-if-path-exists-in-graph.js)|Easy| +1973|[Count Nodes Equal to Sum of Descendants](./solutions/1973-count-nodes-equal-to-sum-of-descendants.js)|Medium| 1974|[Minimum Time to Type Word Using Special Typewriter](./solutions/1974-minimum-time-to-type-word-using-special-typewriter.js)|Easy| 1975|[Maximum Matrix Sum](./solutions/1975-maximum-matrix-sum.js)|Medium| 1976|[Number of Ways to Arrive at Destination](./solutions/1976-number-of-ways-to-arrive-at-destination.js)|Medium| @@ -1522,10 +1799,12 @@ 1980|[Find Unique Binary String](./solutions/1980-find-unique-binary-string.js)|Medium| 1981|[Minimize the Difference Between Target and Chosen Elements](./solutions/1981-minimize-the-difference-between-target-and-chosen-elements.js)|Medium| 1982|[Find Array Given Subset Sums](./solutions/1982-find-array-given-subset-sums.js)|Hard| +1983|[Widest Pair of Indices With Equal Range Sum](./solutions/1983-widest-pair-of-indices-with-equal-range-sum.js)|Medium| 1984|[Minimum Difference Between Highest and Lowest of K Scores](./solutions/1984-minimum-difference-between-highest-and-lowest-of-k-scores.js)|Easy| 1985|[Find the Kth Largest Integer in the Array](./solutions/1985-find-the-kth-largest-integer-in-the-array.js)|Medium| 1986|[Minimum Number of Work Sessions to Finish the Tasks](./solutions/1986-minimum-number-of-work-sessions-to-finish-the-tasks.js)|Medium| 1987|[Number of Unique Good Subsequences](./solutions/1987-number-of-unique-good-subsequences.js)|Hard| +1989|[Maximum Number of People That Can Be Caught in Tag](./solutions/1989-maximum-number-of-people-that-can-be-caught-in-tag.js)|Medium| 1991|[Find the Middle Index in Array](./solutions/1991-find-the-middle-index-in-array.js)|Easy| 1992|[Find All Groups of Farmland](./solutions/1992-find-all-groups-of-farmland.js)|Medium| 1993|[Operations on Tree](./solutions/1993-operations-on-tree.js)|Medium| @@ -1534,10 +1813,12 @@ 1996|[The Number of Weak Characters in the Game](./solutions/1996-the-number-of-weak-characters-in-the-game.js)|Medium| 1997|[First Day Where You Have Been in All the Rooms](./solutions/1997-first-day-where-you-have-been-in-all-the-rooms.js)|Medium| 1998|[GCD Sort of an Array](./solutions/1998-gcd-sort-of-an-array.js)|Hard| +1999|[Smallest Greater Multiple Made of Two Digits](./solutions/1999-smallest-greater-multiple-made-of-two-digits.js)|Medium| 2000|[Reverse Prefix of Word](./solutions/2000-reverse-prefix-of-word.js)|Easy| 2001|[Number of Pairs of Interchangeable Rectangles](./solutions/2001-number-of-pairs-of-interchangeable-rectangles.js)|Medium| 2002|[Maximum Product of the Length of Two Palindromic Subsequences](./solutions/2002-maximum-product-of-the-length-of-two-palindromic-subsequences.js)|Medium| 2003|[Smallest Missing Genetic Value in Each Subtree](./solutions/2003-smallest-missing-genetic-value-in-each-subtree.js)|Hard| +2005|[Subtree Removal Game with Fibonacci Tree](./solutions/2005-subtree-removal-game-with-fibonacci-tree.js)|Hard| 2006|[Count Number of Pairs With Absolute Difference K](./solutions/2006-count-number-of-pairs-with-absolute-difference-k.js)|Easy| 2007|[Find Original Array From Doubled Array](./solutions/2007-find-original-array-from-doubled-array.js)|Medium| 2008|[Maximum Earnings From Taxi](./solutions/2008-maximum-earnings-from-taxi.js)|Medium| @@ -1546,10 +1827,12 @@ 2012|[Sum of Beauty in the Array](./solutions/2012-sum-of-beauty-in-the-array.js)|Medium| 2013|[Detect Squares](./solutions/2013-detect-squares.js)|Medium| 2014|[Longest Subsequence Repeated k Times](./solutions/2014-longest-subsequence-repeated-k-times.js)|Hard| +2015|[Average Height of Buildings in Each Segment](./solutions/2015-average-height-of-buildings-in-each-segment.js)|Medium| 2016|[Maximum Difference Between Increasing Elements](./solutions/2016-maximum-difference-between-increasing-elements.js)|Easy| 2017|[Grid Game](./solutions/2017-grid-game.js)|Medium| 2018|[Check if Word Can Be Placed In Crossword](./solutions/2018-check-if-word-can-be-placed-in-crossword.js)|Medium| 2019|[The Score of Students Solving Math Expression](./solutions/2019-the-score-of-students-solving-math-expression.js)|Hard| +2021|[Brightest Position on Street](./solutions/2021-brightest-position-on-street.js)|Medium| 2022|[Convert 1D Array Into 2D Array](./solutions/2022-convert-1d-array-into-2d-array.js)|Easy| 2023|[Number of Pairs of Strings With Concatenation Equal to Target](./solutions/2023-number-of-pairs-of-strings-with-concatenation-equal-to-target.js)|Medium| 2024|[Maximize the Confusion of an Exam](./solutions/2024-maximize-the-confusion-of-an-exam.js)|Medium| @@ -1558,9 +1841,12 @@ 2028|[Find Missing Observations](./solutions/2028-find-missing-observations.js)|Medium| 2029|[Stone Game IX](./solutions/2029-stone-game-ix.js)|Medium| 2030|[Smallest K-Length Subsequence With Occurrences of a Letter](./solutions/2030-smallest-k-length-subsequence-with-occurrences-of-a-letter.js)|Hard| +2031|[Count Subarrays With More Ones Than Zeros](./solutions/2031-count-subarrays-with-more-ones-than-zeros.js)|Medium| 2032|[Two Out of Three](./solutions/2032-two-out-of-three.js)|Easy| 2033|[Minimum Operations to Make a Uni-Value Grid](./solutions/2033-minimum-operations-to-make-a-uni-value-grid.js)|Medium| +2034|[Stock Price Fluctuation](./solutions/2034-stock-price-fluctuation.js)|Medium| 2035|[Partition Array Into Two Arrays to Minimize Sum Difference](./solutions/2035-partition-array-into-two-arrays-to-minimize-sum-difference.js)|Hard| +2036|[Maximum Alternating Subarray Sum](./solutions/2036-maximum-alternating-subarray-sum.js)|Medium| 2037|[Minimum Number of Moves to Seat Everyone](./solutions/2037-minimum-number-of-moves-to-seat-everyone.js)|Easy| 2038|[Remove Colored Pieces if Both Neighbors are the Same Color](./solutions/2038-remove-colored-pieces-if-both-neighbors-are-the-same-color.js)|Medium| 2039|[The Time When the Network Becomes Idle](./solutions/2039-the-time-when-the-network-becomes-idle.js)|Medium| @@ -1569,32 +1855,40 @@ 2043|[Simple Bank System](./solutions/2043-simple-bank-system.js)|Medium| 2044|[Count Number of Maximum Bitwise-OR Subsets](./solutions/2044-count-number-of-maximum-bitwise-or-subsets.js)|Medium| 2045|[Second Minimum Time to Reach Destination](./solutions/2045-second-minimum-time-to-reach-destination.js)|Hard| +2046|[Sort Linked List Already Sorted Using Absolute Values](./solutions/2046-sort-linked-list-already-sorted-using-absolute-values.js)|Medium| 2047|[Number of Valid Words in a Sentence](./solutions/2047-number-of-valid-words-in-a-sentence.js)|Easy| 2048|[Next Greater Numerically Balanced Number](./solutions/2048-next-greater-numerically-balanced-number.js)|Medium| 2049|[Count Nodes With the Highest Score](./solutions/2049-count-nodes-with-the-highest-score.js)|Medium| 2050|[Parallel Courses III](./solutions/2050-parallel-courses-iii.js)|Hard| +2052|[Minimum Cost to Separate Sentence Into Rows](./solutions/2052-minimum-cost-to-separate-sentence-into-rows.js)|Medium| 2053|[Kth Distinct String in an Array](./solutions/2053-kth-distinct-string-in-an-array.js)|Medium| +2054|[Two Best Non-Overlapping Events](./solutions/2054-two-best-non-overlapping-events.js)|Medium| 2055|[Plates Between Candles](./solutions/2055-plates-between-candles.js)|Medium| 2056|[Number of Valid Move Combinations On Chessboard](./solutions/2056-number-of-valid-move-combinations-on-chessboard.js)|Hard| 2057|[Smallest Index With Equal Value](./solutions/2057-smallest-index-with-equal-value.js)|Easy| 2058|[Find the Minimum and Maximum Number of Nodes Between Critical Points](./solutions/2058-find-the-minimum-and-maximum-number-of-nodes-between-critical-points.js)|Medium| 2059|[Minimum Operations to Convert Number](./solutions/2059-minimum-operations-to-convert-number.js)|Medium| 2060|[Check if an Original String Exists Given Two Encoded Strings](./solutions/2060-check-if-an-original-string-exists-given-two-encoded-strings.js)|Hard| +2061|[Number of Spaces Cleaning Robot Cleaned](./solutions/2061-number-of-spaces-cleaning-robot-cleaned.js)|Medium| 2062|[Count Vowel Substrings of a String](./solutions/2062-count-vowel-substrings-of-a-string.js)|Easy| 2063|[Vowels of All Substrings](./solutions/2063-vowels-of-all-substrings.js)|Medium| 2064|[Minimized Maximum of Products Distributed to Any Store](./solutions/2064-minimized-maximum-of-products-distributed-to-any-store.js)|Medium| 2065|[Maximum Path Quality of a Graph](./solutions/2065-maximum-path-quality-of-a-graph.js)|Hard| +2067|[Number of Equal Count Substrings](./solutions/2067-number-of-equal-count-substrings.js)|Medium| 2068|[Check Whether Two Strings are Almost Equivalent](./solutions/2068-check-whether-two-strings-are-almost-equivalent.js)|Easy| 2069|[Walking Robot Simulation II](./solutions/2069-walking-robot-simulation-ii.js)|Medium| 2070|[Most Beautiful Item for Each Query](./solutions/2070-most-beautiful-item-for-each-query.js)|Medium| 2071|[Maximum Number of Tasks You Can Assign](./solutions/2071-maximum-number-of-tasks-you-can-assign.js)|Hard| +2073|[Time Needed to Buy Tickets](./solutions/2073-time-needed-to-buy-tickets.js)|Easy| 2074|[Reverse Nodes in Even Length Groups](./solutions/2074-reverse-nodes-in-even-length-groups.js)|Medium| 2075|[Decode the Slanted Ciphertext](./solutions/2075-decode-the-slanted-ciphertext.js)|Medium| 2076|[Process Restricted Friend Requests](./solutions/2076-process-restricted-friend-requests.js)|Hard| +2077|[Paths in Maze That Lead to Same Room](./solutions/2077-paths-in-maze-that-lead-to-same-room.js)|Medium| 2078|[Two Furthest Houses With Different Colors](./solutions/2078-two-furthest-houses-with-different-colors.js)|Easy| 2079|[Watering Plants](./solutions/2079-watering-plants.js)|Medium| 2080|[Range Frequency Queries](./solutions/2080-range-frequency-queries.js)|Medium| 2081|[Sum of k-Mirror Numbers](./solutions/2081-sum-of-k-mirror-numbers.js)|Hard| +2083|[Substrings That Begin and End With the Same Letter](./solutions/2083-substrings-that-begin-and-end-with-the-same-letter.js)|Medium| 2085|[Count Common Words With One Occurrence](./solutions/2085-count-common-words-with-one-occurrence.js)|Easy| 2086|[Minimum Number of Food Buckets to Feed the Hamsters](./solutions/2086-minimum-number-of-food-buckets-to-feed-the-hamsters.js)|Medium| 2087|[Minimum Cost Homecoming of a Robot in a Grid](./solutions/2087-minimum-cost-homecoming-of-a-robot-in-a-grid.js)|Medium| @@ -1603,21 +1897,26 @@ 2090|[K Radius Subarray Averages](./solutions/2090-k-radius-subarray-averages.js)|Medium| 2091|[Removing Minimum and Maximum From Array](./solutions/2091-removing-minimum-and-maximum-from-array.js)|Medium| 2092|[Find All People With Secret](./solutions/2092-find-all-people-with-secret.js)|Hard| +2093|[Minimum Cost to Reach City With Discounts](./solutions/2093-minimum-cost-to-reach-city-with-discounts.js)|Medium| 2094|[Finding 3-Digit Even Numbers](./solutions/2094-finding-3-digit-even-numbers.js)|Easy| 2095|[Delete the Middle Node of a Linked List](./solutions/2095-delete-the-middle-node-of-a-linked-list.js)|Medium| 2096|[Step-By-Step Directions From a Binary Tree Node to Another](./solutions/2096-step-by-step-directions-from-a-binary-tree-node-to-another.js)|Medium| 2097|[Valid Arrangement of Pairs](./solutions/2097-valid-arrangement-of-pairs.js)|Hard| +2098|[Subsequence of Size K With the Largest Even Sum](./solutions/2098-subsequence-of-size-k-with-the-largest-even-sum.js)|Medium| 2099|[Find Subsequence of Length K With the Largest Sum](./solutions/2099-find-subsequence-of-length-k-with-the-largest-sum.js)|Medium| 2100|[Find Good Days to Rob the Bank](./solutions/2100-find-good-days-to-rob-the-bank.js)|Medium| 2101|[Detonate the Maximum Bombs](./solutions/2101-detonate-the-maximum-bombs.js)|Medium| +2102|[Sequentially Ordinal Rank Tracker](./solutions/2102-sequentially-ordinal-rank-tracker.js)|Hard| 2103|[Rings and Rods](./solutions/2103-rings-and-rods.js)|Easy| 2104|[Sum of Subarray Ranges](./solutions/2104-sum-of-subarray-ranges.js)|Medium| 2105|[Watering Plants II](./solutions/2105-watering-plants-ii.js)|Medium| 2106|[Maximum Fruits Harvested After at Most K Steps](./solutions/2106-maximum-fruits-harvested-after-at-most-k-steps.js)|Hard| +2107|[Number of Unique Flavors After Sharing K Candies](./solutions/2107-number-of-unique-flavors-after-sharing-k-candies.js)|Medium| 2108|[Find First Palindromic String in the Array](./solutions/2108-find-first-palindromic-string-in-the-array.js)|Easy| 2109|[Adding Spaces to a String](./solutions/2109-adding-spaces-to-a-string.js)|Medium| 2110|[Number of Smooth Descent Periods of a Stock](./solutions/2110-number-of-smooth-descent-periods-of-a-stock.js)|Medium| 2111|[Minimum Operations to Make the Array K-Increasing](./solutions/2111-minimum-operations-to-make-the-array-k-increasing.js)|Hard| +2113|[Elements in Array After Removing and Replacing Elements](./solutions/2113-elements-in-array-after-removing-and-replacing-elements.js)|Medium| 2114|[Maximum Number of Words Found in Sentences](./solutions/2114-maximum-number-of-words-found-in-sentences.js)|Easy| 2115|[Find All Possible Recipes from Given Supplies](./solutions/2115-find-all-possible-recipes-from-given-supplies.js)|Medium| 2116|[Check if a Parentheses String Can Be Valid](./solutions/2116-check-if-a-parentheses-string-can-be-valid.js)|Medium| @@ -1626,10 +1925,12 @@ 2120|[Execution of All Suffix Instructions Staying in a Grid](./solutions/2120-execution-of-all-suffix-instructions-staying-in-a-grid.js)|Medium| 2121|[Intervals Between Identical Elements](./solutions/2121-intervals-between-identical-elements.js)|Medium| 2122|[Recover the Original Array](./solutions/2122-recover-the-original-array.js)|Hard| +2123|[Minimum Operations to Remove Adjacent Ones in Matrix](./solutions/2123-minimum-operations-to-remove-adjacent-ones-in-matrix.js)|Hard| 2124|[Check if All A's Appears Before All B's](./solutions/2124-check-if-all-as-appears-before-all-bs.js)|Easy| 2125|[Number of Laser Beams in a Bank](./solutions/2125-number-of-laser-beams-in-a-bank.js)|Medium| 2126|[Destroying Asteroids](./solutions/2126-destroying-asteroids.js)|Medium| 2127|[Maximum Employees to Be Invited to a Meeting](./solutions/2127-maximum-employees-to-be-invited-to-a-meeting.js)|Hard| +2128|[Remove All Ones With Row and Column Flips](./solutions/2128-remove-all-ones-with-row-and-column-flips.js)|Medium| 2129|[Capitalize the Title](./solutions/2129-capitalize-the-title.js)|Easy| 2130|[Maximum Twin Sum of a Linked List](./solutions/2130-maximum-twin-sum-of-a-linked-list.js)|Medium| 2131|[Longest Palindrome by Concatenating Two Letter Words](./solutions/2131-longest-palindrome-by-concatenating-two-letter-words.js)|Medium| @@ -1638,43 +1939,54 @@ 2134|[Minimum Swaps to Group All 1's Together II](./solutions/2134-minimum-swaps-to-group-all-1s-together-ii.js)|Medium| 2135|[Count Words Obtained After Adding a Letter](./solutions/2135-count-words-obtained-after-adding-a-letter.js)|Medium| 2136|[Earliest Possible Day of Full Bloom](./solutions/2136-earliest-possible-day-of-full-bloom.js)|Hard| +2137|[Pour Water Between Buckets to Make Water Levels Equal](./solutions/2137-pour-water-between-buckets-to-make-water-levels-equal.js)|Medium| 2138|[Divide a String Into Groups of Size k](./solutions/2138-divide-a-string-into-groups-of-size-k.js)|Easy| 2139|[Minimum Moves to Reach Target Score](./solutions/2139-minimum-moves-to-reach-target-score.js)|Medium| 2140|[Solving Questions With Brainpower](./solutions/2140-solving-questions-with-brainpower.js)|Medium| 2141|[Maximum Running Time of N Computers](./solutions/2141-maximum-running-time-of-n-computers.js)|Hard| +2143|[Choose Numbers From Two Arrays in Range](./solutions/2143-choose-numbers-from-two-arrays-in-range.js)|Hard| 2144|[Minimum Cost of Buying Candies With Discount](./solutions/2144-minimum-cost-of-buying-candies-with-discount.js)|Easy| 2145|[Count the Hidden Sequences](./solutions/2145-count-the-hidden-sequences.js)|Medium| +2146|[K Highest Ranked Items Within a Price Range](./solutions/2146-k-highest-ranked-items-within-a-price-range.js)|Medium| 2147|[Number of Ways to Divide a Long Corridor](./solutions/2147-number-of-ways-to-divide-a-long-corridor.js)|Hard| 2148|[Count Elements With Strictly Smaller and Greater Elements](./solutions/2148-count-elements-with-strictly-smaller-and-greater-elements.js)|Easy| 2149|[Rearrange Array Elements by Sign](./solutions/2149-rearrange-array-elements-by-sign.js)|Medium| 2150|[Find All Lonely Numbers in the Array](./solutions/2150-find-all-lonely-numbers-in-the-array.js)|Medium| 2151|[Maximum Good People Based on Statements](./solutions/2151-maximum-good-people-based-on-statements.js)|Hard| +2152|[Minimum Number of Lines to Cover Points](./solutions/2152-minimum-number-of-lines-to-cover-points.js)|Medium| 2154|[Keep Multiplying Found Values by Two](./solutions/2154-keep-multiplying-found-values-by-two.js)|Easy| 2155|[All Divisions With the Highest Score of a Binary Array](./solutions/2155-all-divisions-with-the-highest-score-of-a-binary-array.js)|Medium| 2156|[Find Substring With Given Hash Value](./solutions/2156-find-substring-with-given-hash-value.js)|Hard| 2157|[Groups of Strings](./solutions/2157-groups-of-strings.js)|Hard| +2158|[Amount of New Area Painted Each Day](./solutions/2158-amount-of-new-area-painted-each-day.js)|Hard| 2160|[Minimum Sum of Four Digit Number After Splitting Digits](./solutions/2160-minimum-sum-of-four-digit-number-after-splitting-digits.js)|Easy| 2161|[Partition Array According to Given Pivot](./solutions/2161-partition-array-according-to-given-pivot.js)|Medium| 2162|[Minimum Cost to Set Cooking Time](./solutions/2162-minimum-cost-to-set-cooking-time.js)|Medium| +2163|[Minimum Difference in Sums After Removal of Elements](./solutions/2163-minimum-difference-in-sums-after-removal-of-elements.js)|Hard| 2164|[Sort Even and Odd Indices Independently](./solutions/2164-sort-even-and-odd-indices-independently.js)|Easy| 2165|[Smallest Value of the Rearranged Number](./solutions/2165-smallest-value-of-the-rearranged-number.js)|Medium| 2166|[Design Bitset](./solutions/2166-design-bitset.js)|Medium| 2167|[Minimum Time to Remove All Cars Containing Illegal Goods](./solutions/2167-minimum-time-to-remove-all-cars-containing-illegal-goods.js)|Hard| +2168|[Unique Substrings With Equal Digit Frequency](./solutions/2168-unique-substrings-with-equal-digit-frequency.js)|Medium| 2169|[Count Operations to Obtain Zero](./solutions/2169-count-operations-to-obtain-zero.js)|Easy| 2170|[Minimum Operations to Make the Array Alternating](./solutions/2170-minimum-operations-to-make-the-array-alternating.js)|Medium| 2171|[Removing Minimum Number of Magic Beans](./solutions/2171-removing-minimum-number-of-magic-beans.js)|Medium| 2172|[Maximum AND Sum of Array](./solutions/2172-maximum-and-sum-of-array.js)|Hard| +2174|[Remove All Ones With Row and Column Flips II](./solutions/2174-remove-all-ones-with-row-and-column-flips-ii.js)|Medium| 2176|[Count Equal and Divisible Pairs in an Array](./solutions/2176-count-equal-and-divisible-pairs-in-an-array.js)|Easy| 2177|[Find Three Consecutive Integers That Sum to a Given Number](./solutions/2177-find-three-consecutive-integers-that-sum-to-a-given-number.js)|Medium| 2178|[Maximum Split of Positive Even Integers](./solutions/2178-maximum-split-of-positive-even-integers.js)|Medium| 2179|[Count Good Triplets in an Array](./solutions/2179-count-good-triplets-in-an-array.js)|Hard| 2180|[Count Integers With Even Digit Sum](./solutions/2180-count-integers-with-even-digit-sum.js)|Easy| 2181|[Merge Nodes in Between Zeros](./solutions/2181-merge-nodes-in-between-zeros.js)|Medium| +2182|[Construct String With Repeat Limit](./solutions/2182-construct-string-with-repeat-limit.js)|Medium| 2183|[Count Array Pairs Divisible by K](./solutions/2183-count-array-pairs-divisible-by-k.js)|Hard| +2184|[Number of Ways to Build Sturdy Brick Wall](./solutions/2184-number-of-ways-to-build-sturdy-brick-wall.js)|Medium| 2185|[Counting Words With a Given Prefix](./solutions/2185-counting-words-with-a-given-prefix.js)|Easy| 2186|[Minimum Number of Steps to Make Two Strings Anagram II](./solutions/2186-minimum-number-of-steps-to-make-two-strings-anagram-ii.js)|Medium| 2187|[Minimum Time to Complete Trips](./solutions/2187-minimum-time-to-complete-trips.js)|Medium| 2188|[Minimum Time to Finish the Race](./solutions/2188-minimum-time-to-finish-the-race.js)|Hard| +2189|[Number of Ways to Build House of Cards](./solutions/2189-number-of-ways-to-build-house-of-cards.js)|Medium| 2190|[Most Frequent Number Following Key In an Array](./solutions/2190-most-frequent-number-following-key-in-an-array.js)|Easy| 2191|[Sort the Jumbled Numbers](./solutions/2191-sort-the-jumbled-numbers.js)|Medium| 2192|[All Ancestors of a Node in a Directed Acyclic Graph](./solutions/2192-all-ancestors-of-a-node-in-a-directed-acyclic-graph.js)|Medium| @@ -1683,21 +1995,26 @@ 2195|[Append K Integers With Minimal Sum](./solutions/2195-append-k-integers-with-minimal-sum.js)|Medium| 2196|[Create Binary Tree From Descriptions](./solutions/2196-create-binary-tree-from-descriptions.js)|Medium| 2197|[Replace Non-Coprime Numbers in Array](./solutions/2197-replace-non-coprime-numbers-in-array.js)|Hard| +2198|[Number of Single Divisor Triplets](./solutions/2198-number-of-single-divisor-triplets.js)|Medium| 2200|[Find All K-Distant Indices in an Array](./solutions/2200-find-all-k-distant-indices-in-an-array.js)|Easy| 2201|[Count Artifacts That Can Be Extracted](./solutions/2201-count-artifacts-that-can-be-extracted.js)|Medium| 2202|[Maximize the Topmost Element After K Moves](./solutions/2202-maximize-the-topmost-element-after-k-moves.js)|Medium| 2203|[Minimum Weighted Subgraph With the Required Paths](./solutions/2203-minimum-weighted-subgraph-with-the-required-paths.js)|Hard| +2204|[Distance to a Cycle in Undirected Graph](./solutions/2204-distance-to-a-cycle-in-undirected-graph.js)|Hard| 2206|[Divide Array Into Equal Pairs](./solutions/2206-divide-array-into-equal-pairs.js)|Easy| 2207|[Maximize Number of Subsequences in a String](./solutions/2207-maximize-number-of-subsequences-in-a-string.js)|Medium| +2208|[Minimum Operations to Halve Array Sum](./solutions/2208-minimum-operations-to-halve-array-sum.js)|Medium| 2209|[Minimum White Tiles After Covering With Carpets](./solutions/2209-minimum-white-tiles-after-covering-with-carpets.js)|Hard| 2210|[Count Hills and Valleys in an Array](./solutions/2210-count-hills-and-valleys-in-an-array.js)|Easy| 2211|[Count Collisions on a Road](./solutions/2211-count-collisions-on-a-road.js)|Medium| 2212|[Maximum Points in an Archery Competition](./solutions/2212-maximum-points-in-an-archery-competition.js)|Medium| 2213|[Longest Substring of One Repeating Character](./solutions/2213-longest-substring-of-one-repeating-character.js)|Hard| +2214|[Minimum Health to Beat Game](./solutions/2214-minimum-health-to-beat-game.js)|Medium| 2215|[Find the Difference of Two Arrays](./solutions/2215-find-the-difference-of-two-arrays.js)|Easy| 2216|[Minimum Deletions to Make Array Beautiful](./solutions/2216-minimum-deletions-to-make-array-beautiful.js)|Medium| 2217|[Find Palindrome With Fixed Length](./solutions/2217-find-palindrome-with-fixed-length.js)|Medium| 2218|[Maximum Value of K Coins From Piles](./solutions/2218-maximum-value-of-k-coins-from-piles.js)|Hard| +2219|[Maximum Sum Score of Array](./solutions/2219-maximum-sum-score-of-array.js)|Medium| 2220|[Minimum Bit Flips to Convert Number](./solutions/2220-minimum-bit-flips-to-convert-number.js)|Easy| 2221|[Find Triangular Sum of an Array](./solutions/2221-find-triangular-sum-of-an-array.js)|Medium| 2222|[Number of Ways to Select Buildings](./solutions/2222-number-of-ways-to-select-buildings.js)|Medium| @@ -1706,10 +2023,14 @@ 2225|[Find Players With Zero or One Losses](./solutions/2225-find-players-with-zero-or-one-losses.js)|Medium| 2226|[Maximum Candies Allocated to K Children](./solutions/2226-maximum-candies-allocated-to-k-children.js)|Medium| 2227|[Encrypt and Decrypt Strings](./solutions/2227-encrypt-and-decrypt-strings.js)|Hard| +2229|[Check if an Array Is Consecutive](./solutions/2229-check-if-an-array-is-consecutive.js)|Easy| +2231|[Largest Number After Digit Swaps by Parity](./solutions/2231-largest-number-after-digit-swaps-by-parity.js)|Easy| 2232|[Minimize Result by Adding Parentheses to Expression](./solutions/2232-minimize-result-by-adding-parentheses-to-expression.js)|Medium| +2233|[Maximum Product After K Increments](./solutions/2233-maximum-product-after-k-increments.js)|Medium| 2234|[Maximum Total Beauty of the Gardens](./solutions/2234-maximum-total-beauty-of-the-gardens.js)|Hard| 2235|[Add Two Integers](./solutions/2235-add-two-integers.js)|Easy| 2236|[Root Equals Sum of Children](./solutions/2236-root-equals-sum-of-children.js)|Easy| +2237|[Count Positions on Street With Required Brightness](./solutions/2237-count-positions-on-street-with-required-brightness.js)|Medium| 2239|[Find Closest Number to Zero](./solutions/2239-find-closest-number-to-zero.js)|Easy| 2240|[Number of Ways to Buy Pens and Pencils](./solutions/2240-number-of-ways-to-buy-pens-and-pencils.js)|Medium| 2241|[Design an ATM Machine](./solutions/2241-design-an-atm-machine.js)|Medium| @@ -1718,10 +2039,12 @@ 2244|[Minimum Rounds to Complete All Tasks](./solutions/2244-minimum-rounds-to-complete-all-tasks.js)|Medium| 2245|[Maximum Trailing Zeros in a Cornered Path](./solutions/2245-maximum-trailing-zeros-in-a-cornered-path.js)|Medium| 2246|[Longest Path With Different Adjacent Characters](./solutions/2246-longest-path-with-different-adjacent-characters.js)|Hard| +2247|[Maximum Cost of Trip With K Highways](./solutions/2247-maximum-cost-of-trip-with-k-highways.js)|Hard| 2248|[Intersection of Multiple Arrays](./solutions/2248-intersection-of-multiple-arrays.js)|Easy| 2249|[Count Lattice Points Inside a Circle](./solutions/2249-count-lattice-points-inside-a-circle.js)|Medium| 2250|[Count Number of Rectangles Containing Each Point](./solutions/2250-count-number-of-rectangles-containing-each-point.js)|Medium| 2251|[Number of Flowers in Full Bloom](./solutions/2251-number-of-flowers-in-full-bloom.js)|Hard| +2254|[Design Video Sharing Platform](./solutions/2254-design-video-sharing-platform.js)|Hard| 2255|[Count Prefixes of a Given String](./solutions/2255-count-prefixes-of-a-given-string.js)|Easy| 2256|[Minimum Average Difference](./solutions/2256-minimum-average-difference.js)|Medium| 2257|[Count Unguarded Cells in the Grid](./solutions/2257-count-unguarded-cells-in-the-grid.js)|Medium| @@ -1730,10 +2053,12 @@ 2260|[Minimum Consecutive Cards to Pick Up](./solutions/2260-minimum-consecutive-cards-to-pick-up.js)|Medium| 2261|[K Divisible Elements Subarrays](./solutions/2261-k-divisible-elements-subarrays.js)|Medium| 2262|[Total Appeal of A String](./solutions/2262-total-appeal-of-a-string.js)|Hard| +2263|[Make Array Non-decreasing or Non-increasing](./solutions/2263-make-array-non-decreasing-or-non-increasing.js)|Hard| 2264|[Largest 3-Same-Digit Number in String](./solutions/2264-largest-3-same-digit-number-in-string.js)|Easy| 2265|[Count Nodes Equal to Average of Subtree](./solutions/2265-count-nodes-equal-to-average-of-subtree.js)|Medium| 2266|[Count Number of Texts](./solutions/2266-count-number-of-texts.js)|Medium| 2267|[Check if There Is a Valid Parentheses String Path](./solutions/2267-check-if-there-is-a-valid-parentheses-string-path.js)|Hard| +2268|[Minimum Number of Keypresses](./solutions/2268-minimum-number-of-keypresses.js)|Medium| 2269|[Find the K-Beauty of a Number](./solutions/2269-find-the-k-beauty-of-a-number.js)|Easy| 2270|[Number of Ways to Split Array](./solutions/2270-number-of-ways-to-split-array.js)|Medium| 2271|[Maximum White Tiles Covered by a Carpet](./solutions/2271-maximum-white-tiles-covered-by-a-carpet.js)|Medium| @@ -1741,17 +2066,27 @@ 2273|[Find Resultant Array After Removing Anagrams](./solutions/2273-find-resultant-array-after-removing-anagrams.js)|Easy| 2274|[Maximum Consecutive Floors Without Special Floors](./solutions/2274-maximum-consecutive-floors-without-special-floors.js)|Medium| 2275|[Largest Combination With Bitwise AND Greater Than Zero](./solutions/2275-largest-combination-with-bitwise-and-greater-than-zero.js)|Medium| +2276|[Count Integers in Intervals](./solutions/2276-count-integers-in-intervals.js)|Hard| +2277|[Closest Node to Path in Tree](./solutions/2277-closest-node-to-path-in-tree.js)|Hard| 2278|[Percentage of Letter in String](./solutions/2278-percentage-of-letter-in-string.js)|Easy| 2279|[Maximum Bags With Full Capacity of Rocks](./solutions/2279-maximum-bags-with-full-capacity-of-rocks.js)|Medium| 2280|[Minimum Lines to Represent a Line Chart](./solutions/2280-minimum-lines-to-represent-a-line-chart.js)|Medium| +2281|[Sum of Total Strength of Wizards](./solutions/2281-sum-of-total-strength-of-wizards.js)|Hard| +2282|[Number of People That Can Be Seen in a Grid](./solutions/2282-number-of-people-that-can-be-seen-in-a-grid.js)|Medium| 2283|[Check if Number Has Equal Digit Count and Digit Value](./solutions/2283-check-if-number-has-equal-digit-count-and-digit-value.js)|Easy| 2284|[Sender With Largest Word Count](./solutions/2284-sender-with-largest-word-count.js)|Medium| +2285|[Maximum Total Importance of Roads](./solutions/2285-maximum-total-importance-of-roads.js)|Medium| +2286|[Booking Concert Tickets in Groups](./solutions/2286-booking-concert-tickets-in-groups.js)|Hard| 2287|[Rearrange Characters to Make Target String](./solutions/2287-rearrange-characters-to-make-target-string.js)|Easy| 2288|[Apply Discount to Prices](./solutions/2288-apply-discount-to-prices.js)|Medium| +2289|[Steps to Make Array Non-decreasing](./solutions/2289-steps-to-make-array-non-decreasing.js)|Medium| +2290|[Minimum Obstacle Removal to Reach Corner](./solutions/2290-minimum-obstacle-removal-to-reach-corner.js)|Hard| +2291|[Maximum Profit From Trading Stocks](./solutions/2291-maximum-profit-from-trading-stocks.js)|Medium| 2293|[Min Max Game](./solutions/2293-min-max-game.js)|Easy| 2294|[Partition Array Such That Maximum Difference Is K](./solutions/2294-partition-array-such-that-maximum-difference-is-k.js)|Medium| 2295|[Replace Elements in an Array](./solutions/2295-replace-elements-in-an-array.js)|Medium| 2296|[Design a Text Editor](./solutions/2296-design-a-text-editor.js)|Hard| +2297|[Jump Game VIII](./solutions/2297-jump-game-viii.js)|Medium| 2299|[Strong Password Checker II](./solutions/2299-strong-password-checker-ii.js)|Easy| 2300|[Successful Pairs of Spells and Potions](./solutions/2300-successful-pairs-of-spells-and-potions.js)|Medium| 2301|[Match Substring After Replacement](./solutions/2301-match-substring-after-replacement.js)|Hard| @@ -1760,8 +2095,12 @@ 2304|[Minimum Path Cost in a Grid](./solutions/2304-minimum-path-cost-in-a-grid.js)|Medium| 2305|[Fair Distribution of Cookies](./solutions/2305-fair-distribution-of-cookies.js)|Medium| 2306|[Naming a Company](./solutions/2306-naming-a-company.js)|Hard| +2307|[Check for Contradictions in Equations](./solutions/2307-check-for-contradictions-in-equations.js)|Hard| 2309|[Greatest English Letter in Upper and Lower Case](./solutions/2309-greatest-english-letter-in-upper-and-lower-case.js)|Easy| +2310|[Sum of Numbers With Units Digit K](./solutions/2310-sum-of-numbers-with-units-digit-k.js)|Medium| +2311|[Longest Binary Subsequence Less Than or Equal to K](./solutions/2311-longest-binary-subsequence-less-than-or-equal-to-k.js)|Medium| 2312|[Selling Pieces of Wood](./solutions/2312-selling-pieces-of-wood.js)|Hard| +2313|[Minimum Flips in Binary Tree to Get Result](./solutions/2313-minimum-flips-in-binary-tree-to-get-result.js)|Hard| 2315|[Count Asterisks](./solutions/2315-count-asterisks.js)|Easy| 2316|[Count Unreachable Pairs of Nodes in an Undirected Graph](./solutions/2316-count-unreachable-pairs-of-nodes-in-an-undirected-graph.js)|Medium| 2317|[Maximum XOR After Operations](./solutions/2317-maximum-xor-after-operations.js)|Medium| @@ -1770,26 +2109,40 @@ 2320|[Count Number of Ways to Place Houses](./solutions/2320-count-number-of-ways-to-place-houses.js)|Medium| 2321|[Maximum Score Of Spliced Array](./solutions/2321-maximum-score-of-spliced-array.js)|Hard| 2322|[Minimum Score After Removals on a Tree](./solutions/2322-minimum-score-after-removals-on-a-tree.js)|Hard| +2323|[Find Minimum Time to Finish All Jobs II](./solutions/2323-find-minimum-time-to-finish-all-jobs-ii.js)|Medium| 2325|[Decode the Message](./solutions/2325-decode-the-message.js)|Easy| 2326|[Spiral Matrix IV](./solutions/2326-spiral-matrix-iv.js)|Medium| +2327|[Number of People Aware of a Secret](./solutions/2327-number-of-people-aware-of-a-secret.js)|Medium| 2328|[Number of Increasing Paths in a Grid](./solutions/2328-number-of-increasing-paths-in-a-grid.js)|Hard| +2330|[Valid Palindrome IV](./solutions/2330-valid-palindrome-iv.js)|Medium| 2331|[Evaluate Boolean Binary Tree](./solutions/2331-evaluate-boolean-binary-tree.js)|Easy| +2332|[The Latest Time to Catch a Bus](./solutions/2332-the-latest-time-to-catch-a-bus.js)|Medium| +2333|[Minimum Sum of Squared Difference](./solutions/2333-minimum-sum-of-squared-difference.js)|Medium| 2334|[Subarray With Elements Greater Than Varying Threshold](./solutions/2334-subarray-with-elements-greater-than-varying-threshold.js)|Hard| +2335|[Minimum Amount of Time to Fill Cups](./solutions/2335-minimum-amount-of-time-to-fill-cups.js)|Easy| 2336|[Smallest Number in Infinite Set](./solutions/2336-smallest-number-in-infinite-set.js)|Medium| 2337|[Move Pieces to Obtain a String](./solutions/2337-move-pieces-to-obtain-a-string.js)|Medium| 2338|[Count the Number of Ideal Arrays](./solutions/2338-count-the-number-of-ideal-arrays.js)|Hard| +2340|[Minimum Adjacent Swaps to Make a Valid Array](./solutions/2340-minimum-adjacent-swaps-to-make-a-valid-array.js)|Medium| 2341|[Maximum Number of Pairs in Array](./solutions/2341-maximum-number-of-pairs-in-array.js)|Easy| 2342|[Max Sum of a Pair With Equal Sum of Digits](./solutions/2342-max-sum-of-a-pair-with-equal-sum-of-digits.js)|Medium| +2343|[Query Kth Smallest Trimmed Number](./solutions/2343-query-kth-smallest-trimmed-number.js)|Medium| +2344|[Minimum Deletions to Make Array Divisible](./solutions/2344-minimum-deletions-to-make-array-divisible.js)|Hard| +2345|[Finding the Number of Visible Mountains](./solutions/2345-finding-the-number-of-visible-mountains.js)|Medium| 2347|[Best Poker Hand](./solutions/2347-best-poker-hand.js)|Easy| 2348|[Number of Zero-Filled Subarrays](./solutions/2348-number-of-zero-filled-subarrays.js)|Medium| 2349|[Design a Number Container System](./solutions/2349-design-a-number-container-system.js)|Medium| 2350|[Shortest Impossible Sequence of Rolls](./solutions/2350-shortest-impossible-sequence-of-rolls.js)|Hard| 2351|[First Letter to Appear Twice](./solutions/2351-first-letter-to-appear-twice.js)|Easy| 2352|[Equal Row and Column Pairs](./solutions/2352-equal-row-and-column-pairs.js)|Medium| +2353|[Design a Food Rating System](./solutions/2353-design-a-food-rating-system.js)|Medium| 2354|[Number of Excellent Pairs](./solutions/2354-number-of-excellent-pairs.js)|Hard| +2355|[Maximum Number of Books You Can Take](./solutions/2355-maximum-number-of-books-you-can-take.js)|Hard| +2357|[Make Array Zero by Subtracting Equal Amounts](./solutions/2357-make-array-zero-by-subtracting-equal-amounts.js)|Easy| 2358|[Maximum Number of Groups Entering a Competition](./solutions/2358-maximum-number-of-groups-entering-a-competition.js)|Medium| 2359|[Find Closest Node to Given Two Nodes](./solutions/2359-find-closest-node-to-given-two-nodes.js)|Medium| 2360|[Longest Cycle in a Graph](./solutions/2360-longest-cycle-in-a-graph.js)|Hard| +2361|[Minimum Costs Using the Train Line](./solutions/2361-minimum-costs-using-the-train-line.js)|Hard| 2363|[Merge Similar Items](./solutions/2363-merge-similar-items.js)|Easy| 2364|[Count Number of Bad Pairs](./solutions/2364-count-number-of-bad-pairs.js)|Medium| 2365|[Task Scheduler II](./solutions/2365-task-scheduler-ii.js)|Medium| @@ -1798,26 +2151,40 @@ 2368|[Reachable Nodes With Restrictions](./solutions/2368-reachable-nodes-with-restrictions.js)|Medium| 2369|[Check if There is a Valid Partition For The Array](./solutions/2369-check-if-there-is-a-valid-partition-for-the-array.js)|Medium| 2370|[Longest Ideal Subsequence](./solutions/2370-longest-ideal-subsequence.js)|Medium| +2371|[Minimize Maximum Value in a Grid](./solutions/2371-minimize-maximum-value-in-a-grid.js)|Hard| 2373|[Largest Local Values in a Matrix](./solutions/2373-largest-local-values-in-a-matrix.js)|Easy| 2374|[Node With Highest Edge Score](./solutions/2374-node-with-highest-edge-score.js)|Medium| 2375|[Construct Smallest Number From DI String](./solutions/2375-construct-smallest-number-from-di-string.js)|Medium| +2376|[Count Special Integers](./solutions/2376-count-special-integers.js)|Hard| +2378|[Choose Edges to Maximize Score in a Tree](./solutions/2378-choose-edges-to-maximize-score-in-a-tree.js)|Medium| 2379|[Minimum Recolors to Get K Consecutive Black Blocks](./solutions/2379-minimum-recolors-to-get-k-consecutive-black-blocks.js)|Easy| 2380|[Time Needed to Rearrange a Binary String](./solutions/2380-time-needed-to-rearrange-a-binary-string.js)|Medium| 2381|[Shifting Letters II](./solutions/2381-shifting-letters-ii.js)|Medium| 2382|[Maximum Segment Sum After Removals](./solutions/2382-maximum-segment-sum-after-removals.js)|Hard| 2383|[Minimum Hours of Training to Win a Competition](./solutions/2383-minimum-hours-of-training-to-win-a-competition.js)|Easy| +2384|[Largest Palindromic Number](./solutions/2384-largest-palindromic-number.js)|Medium| 2385|[Amount of Time for Binary Tree to Be Infected](./solutions/2385-amount-of-time-for-binary-tree-to-be-infected.js)|Medium| +2386|[Find the K-Sum of an Array](./solutions/2386-find-the-k-sum-of-an-array.js)|Hard| +2387|[Median of a Row Wise Sorted Matrix](./solutions/2387-median-of-a-row-wise-sorted-matrix.js)|Medium| 2389|[Longest Subsequence With Limited Sum](./solutions/2389-longest-subsequence-with-limited-sum.js)|Easy| 2390|[Removing Stars From a String](./solutions/2390-removing-stars-from-a-string.js)|Medium| 2391|[Minimum Amount of Time to Collect Garbage](./solutions/2391-minimum-amount-of-time-to-collect-garbage.js)|Medium| 2392|[Build a Matrix With Conditions](./solutions/2392-build-a-matrix-with-conditions.js)|Hard| +2393|[Count Strictly Increasing Subarrays](./solutions/2393-count-strictly-increasing-subarrays.js)|Medium| 2395|[Find Subarrays With Equal Sum](./solutions/2395-find-subarrays-with-equal-sum.js)|Easy| 2396|[Strictly Palindromic Number](./solutions/2396-strictly-palindromic-number.js)|Medium| 2397|[Maximum Rows Covered by Columns](./solutions/2397-maximum-rows-covered-by-columns.js)|Medium| +2398|[Maximum Number of Robots Within Budget](./solutions/2398-maximum-number-of-robots-within-budget.js)|Hard| 2399|[Check Distances Between Same Letters](./solutions/2399-check-distances-between-same-letters.js)|Easy| +2400|[Number of Ways to Reach a Position After Exactly k Steps](./solutions/2400-number-of-ways-to-reach-a-position-after-exactly-k-steps.js)|Medium| 2401|[Longest Nice Subarray](./solutions/2401-longest-nice-subarray.js)|Medium| +2402|[Meeting Rooms III](./solutions/2402-meeting-rooms-iii.js)|Hard| +2403|[Minimum Time to Kill All Monsters](./solutions/2403-minimum-time-to-kill-all-monsters.js)|Hard| 2404|[Most Frequent Even Element](./solutions/2404-most-frequent-even-element.js)|Easy| 2405|[Optimal Partition of String](./solutions/2405-optimal-partition-of-string.js)|Medium| +2406|[Divide Intervals Into Minimum Number of Groups](./solutions/2406-divide-intervals-into-minimum-number-of-groups.js)|Medium| +2407|[Longest Increasing Subsequence II](./solutions/2407-longest-increasing-subsequence-ii.js)|Hard| +2408|[Design SQL](./solutions/2408-design-sql.js)|Medium| 2409|[Count Days Spent Together](./solutions/2409-count-days-spent-together.js)|Easy| 2410|[Maximum Matching of Players With Trainers](./solutions/2410-maximum-matching-of-players-with-trainers.js)|Medium| 2411|[Smallest Subarrays With Maximum Bitwise OR](./solutions/2411-smallest-subarrays-with-maximum-bitwise-or.js)|Medium| @@ -1826,18 +2193,23 @@ 2414|[Length of the Longest Alphabetical Continuous Substring](./solutions/2414-length-of-the-longest-alphabetical-continuous-substring.js)|Medium| 2415|[Reverse Odd Levels of Binary Tree](./solutions/2415-reverse-odd-levels-of-binary-tree.js)|Medium| 2416|[Sum of Prefix Scores of Strings](./solutions/2416-sum-of-prefix-scores-of-strings.js)|Hard| +2417|[Closest Fair Integer](./solutions/2417-closest-fair-integer.js)|Medium| 2418|[Sort the People](./solutions/2418-sort-the-people.js)|Easy| 2419|[Longest Subarray With Maximum Bitwise AND](./solutions/2419-longest-subarray-with-maximum-bitwise-and.js)|Medium| +2420|[Find All Good Indices](./solutions/2420-find-all-good-indices.js)|Medium| 2421|[Number of Good Paths](./solutions/2421-number-of-good-paths.js)|Hard| +2422|[Merge Operations to Turn Array Into a Palindrome](./solutions/2422-merge-operations-to-turn-array-into-a-palindrome.js)|Medium| 2425|[Bitwise XOR of All Pairings](./solutions/2425-bitwise-xor-of-all-pairings.js)|Medium| 2426|[Number of Pairs Satisfying Inequality](./solutions/2426-number-of-pairs-satisfying-inequality.js)|Hard| 2427|[Number of Common Factors](./solutions/2427-number-of-common-factors.js)|Easy| 2428|[Maximum Sum of an Hourglass](./solutions/2428-maximum-sum-of-an-hourglass.js)|Medium| 2429|[Minimize XOR](./solutions/2429-minimize-xor.js)|Medium| +2431|[Maximize Total Tastiness of Purchased Fruits](./solutions/2431-maximize-total-tastiness-of-purchased-fruits.js)|Medium| 2432|[The Employee That Worked on the Longest Task](./solutions/2432-the-employee-that-worked-on-the-longest-task.js)|Easy| 2433|[Find The Original Array of Prefix Xor](./solutions/2433-find-the-original-array-of-prefix-xor.js)|Medium| 2434|[Using a Robot to Print the Lexicographically Smallest String](./solutions/2434-using-a-robot-to-print-the-lexicographically-smallest-string.js)|Medium| 2435|[Paths in Matrix Whose Sum Is Divisible by K](./solutions/2435-paths-in-matrix-whose-sum-is-divisible-by-k.js)|Hard| +2436|[Minimum Split Into Subarrays With GCD Greater Than One](./solutions/2436-minimum-split-into-subarrays-with-gcd-greater-than-one.js)|Medium| 2437|[Number of Valid Clock Times](./solutions/2437-number-of-valid-clock-times.js)|Easy| 2438|[Range Product Queries of Powers](./solutions/2438-range-product-queries-of-powers.js)|Medium| 2439|[Minimize Maximum of Array](./solutions/2439-minimize-maximum-of-array.js)|Medium| @@ -1846,61 +2218,82 @@ 2442|[Count Number of Distinct Integers After Reverse Operations](./solutions/2442-count-number-of-distinct-integers-after-reverse-operations.js)|Medium| 2443|[Sum of Number and Its Reverse](./solutions/2443-sum-of-number-and-its-reverse.js)|Medium| 2444|[Count Subarrays With Fixed Bounds](./solutions/2444-count-subarrays-with-fixed-bounds.js)|Hard| +2445|[Number of Nodes With Value One](./solutions/2445-number-of-nodes-with-value-one.js)|Medium| 2446|[Determine if Two Events Have Conflict](./solutions/2446-determine-if-two-events-have-conflict.js)|Easy| 2447|[Number of Subarrays With GCD Equal to K](./solutions/2447-number-of-subarrays-with-gcd-equal-to-k.js)|Medium| 2448|[Minimum Cost to Make Array Equal](./solutions/2448-minimum-cost-to-make-array-equal.js)|Hard| 2449|[Minimum Number of Operations to Make Arrays Similar](./solutions/2449-minimum-number-of-operations-to-make-arrays-similar.js)|Hard| +2450|[Number of Distinct Binary Strings After Applying Operations](./solutions/2450-number-of-distinct-binary-strings-after-applying-operations.js)|Medium| 2451|[Odd String Difference](./solutions/2451-odd-string-difference.js)|Easy| 2452|[Words Within Two Edits of Dictionary](./solutions/2452-words-within-two-edits-of-dictionary.js)|Medium| 2453|[Destroy Sequential Targets](./solutions/2453-destroy-sequential-targets.js)|Medium| 2455|[Average Value of Even Numbers That Are Divisible by Three](./solutions/2455-average-value-of-even-numbers-that-are-divisible-by-three.js)|Easy| +2456|[Most Popular Video Creator](./solutions/2456-most-popular-video-creator.js)|Medium| 2458|[Height of Binary Tree After Subtree Removal Queries](./solutions/2458-height-of-binary-tree-after-subtree-removal-queries.js)|Hard| +2459|[Sort Array by Moving Items to Empty Space](./solutions/2459-sort-array-by-moving-items-to-empty-space.js)|Hard| 2460|[Apply Operations to an Array](./solutions/2460-apply-operations-to-an-array.js)|Easy| 2461|[Maximum Sum of Distinct Subarrays With Length K](./solutions/2461-maximum-sum-of-distinct-subarrays-with-length-k.js)|Medium| 2462|[Total Cost to Hire K Workers](./solutions/2462-total-cost-to-hire-k-workers.js)|Medium| 2463|[Minimum Total Distance Traveled](./solutions/2463-minimum-total-distance-traveled.js)|Hard| +2464|[Minimum Subarrays in a Valid Split](./solutions/2464-minimum-subarrays-in-a-valid-split.js)|Medium| 2465|[Number of Distinct Averages](./solutions/2465-number-of-distinct-averages.js)|Easy| 2466|[Count Ways To Build Good Strings](./solutions/2466-count-ways-to-build-good-strings.js)|Medium| 2467|[Most Profitable Path in a Tree](./solutions/2467-most-profitable-path-in-a-tree.js)|Medium| 2468|[Split Message Based on Limit](./solutions/2468-split-message-based-on-limit.js)|Hard| 2469|[Convert the Temperature](./solutions/2469-convert-the-temperature.js)|Easy| +2470|[Number of Subarrays With LCM Equal to K](./solutions/2470-number-of-subarrays-with-lcm-equal-to-k.js)|Medium| 2471|[Minimum Number of Operations to Sort a Binary Tree by Level](./solutions/2471-minimum-number-of-operations-to-sort-a-binary-tree-by-level.js)|Medium| 2472|[Maximum Number of Non-overlapping Palindrome Substrings](./solutions/2472-maximum-number-of-non-overlapping-palindrome-substrings.js)|Hard| +2473|[Minimum Cost to Buy Apples](./solutions/2473-minimum-cost-to-buy-apples.js)|Medium| 2475|[Number of Unequal Triplets in Array](./solutions/2475-number-of-unequal-triplets-in-array.js)|Easy| 2476|[Closest Nodes Queries in a Binary Search Tree](./solutions/2476-closest-nodes-queries-in-a-binary-search-tree.js)|Medium| 2477|[Minimum Fuel Cost to Report to the Capital](./solutions/2477-minimum-fuel-cost-to-report-to-the-capital.js)|Medium| +2479|[Maximum XOR of Two Non-Overlapping Subtrees](./solutions/2479-maximum-xor-of-two-non-overlapping-subtrees.js)|Hard| 2481|[Minimum Cuts to Divide a Circle](./solutions/2481-minimum-cuts-to-divide-a-circle.js)|Easy| 2482|[Difference Between Ones and Zeros in Row and Column](./solutions/2482-difference-between-ones-and-zeros-in-row-and-column.js)|Medium| 2483|[Minimum Penalty for a Shop](./solutions/2483-minimum-penalty-for-a-shop.js)|Medium| +2484|[Count Palindromic Subsequences](./solutions/2484-count-palindromic-subsequences.js)|Hard| 2485|[Find the Pivot Integer](./solutions/2485-find-the-pivot-integer.js)|Easy| 2486|[Append Characters to String to Make Subsequence](./solutions/2486-append-characters-to-string-to-make-subsequence.js)|Medium| 2487|[Remove Nodes From Linked List](./solutions/2487-remove-nodes-from-linked-list.js)|Medium| 2488|[Count Subarrays With Median K](./solutions/2488-count-subarrays-with-median-k.js)|Hard| +2489|[Number of Substrings With Fixed Ratio](./solutions/2489-number-of-substrings-with-fixed-ratio.js)|Medium| 2490|[Circular Sentence](./solutions/2490-circular-sentence.js)|Easy| 2491|[Divide Players Into Teams of Equal Skill](./solutions/2491-divide-players-into-teams-of-equal-skill.js)|Medium| 2492|[Minimum Score of a Path Between Two Cities](./solutions/2492-minimum-score-of-a-path-between-two-cities.js)|Medium| 2493|[Divide Nodes Into the Maximum Number of Groups](./solutions/2493-divide-nodes-into-the-maximum-number-of-groups.js)|Hard| +2495|[Number of Subarrays Having Even Product](./solutions/2495-number-of-subarrays-having-even-product.js)|Medium| 2496|[Maximum Value of a String in an Array](./solutions/2496-maximum-value-of-a-string-in-an-array.js)|Easy| 2498|[Frog Jump II](./solutions/2498-frog-jump-ii.js)|Medium| 2499|[Minimum Total Cost to Make Arrays Unequal](./solutions/2499-minimum-total-cost-to-make-arrays-unequal.js)|Hard| +2500|[Delete Greatest Value in Each Row](./solutions/2500-delete-greatest-value-in-each-row.js)|Easy| 2501|[Longest Square Streak in an Array](./solutions/2501-longest-square-streak-in-an-array.js)|Medium| 2502|[Design Memory Allocator](./solutions/2502-design-memory-allocator.js)|Medium| 2503|[Maximum Number of Points From Grid Queries](./solutions/2503-maximum-number-of-points-from-grid-queries.js)|Hard| +2505|[Bitwise OR of All Subsequence Sums](./solutions/2505-bitwise-or-of-all-subsequence-sums.js)|Medium| 2506|[Count Pairs Of Similar Strings](./solutions/2506-count-pairs-of-similar-strings.js)|Easy| 2507|[Smallest Value After Replacing With Sum of Prime Factors](./solutions/2507-smallest-value-after-replacing-with-sum-of-prime-factors.js)|Medium| 2509|[Cycle Length Queries in a Tree](./solutions/2509-cycle-length-queries-in-a-tree.js)|Hard| +2510|[Check if There is a Path With Equal Number of 0's And 1's](./solutions/2510-check-if-there-is-a-path-with-equal-number-of-0s-and-1s.js)|Medium| +2511|[Maximum Enemy Forts That Can Be Captured](./solutions/2511-maximum-enemy-forts-that-can-be-captured.js)|Easy| +2512|[Reward Top K Students](./solutions/2512-reward-top-k-students.js)|Medium| 2515|[Shortest Distance to Target String in a Circular Array](./solutions/2515-shortest-distance-to-target-string-in-a-circular-array.js)|Easy| 2516|[Take K of Each Character From Left and Right](./solutions/2516-take-k-of-each-character-from-left-and-right.js)|Medium| 2517|[Maximum Tastiness of Candy Basket](./solutions/2517-maximum-tastiness-of-candy-basket.js)|Medium| +2519|[Count the Number of K-Big Indices](./solutions/2519-count-the-number-of-k-big-indices.js)|Hard| 2520|[Count the Digits That Divide a Number](./solutions/2520-count-the-digits-that-divide-a-number.js)|Easy| 2521|[Distinct Prime Factors of Product of Array](./solutions/2521-distinct-prime-factors-of-product-of-array.js)|Medium| 2522|[Partition String Into Substrings With Values at Most K](./solutions/2522-partition-string-into-substrings-with-values-at-most-k.js)|Medium| 2523|[Closest Prime Numbers in Range](./solutions/2523-closest-prime-numbers-in-range.js)|Medium| +2524|[Maximum Frequency Score of a Subarray](./solutions/2524-maximum-frequency-score-of-a-subarray.js)|Hard| 2527|[Find Xor-Beauty of Array](./solutions/2527-find-xor-beauty-of-array.js)|Medium| 2529|[Maximum Count of Positive Integer and Negative Integer](./solutions/2529-maximum-count-of-positive-integer-and-negative-integer.js)|Easy| +2533|[Number of Good Binary Strings](./solutions/2533-number-of-good-binary-strings.js)|Medium| +2534|[Time Taken to Cross the Door](./solutions/2534-time-taken-to-cross-the-door.js)|Hard| 2535|[Difference Between Element Sum and Digit Sum of an Array](./solutions/2535-difference-between-element-sum-and-digit-sum-of-an-array.js)|Easy| 2536|[Increment Submatrices by One](./solutions/2536-increment-submatrices-by-one.js)|Medium| 2537|[Count the Number of Good Subarrays](./solutions/2537-count-the-number-of-good-subarrays.js)|Medium| +2539|[Count the Number of Good Subsequences](./solutions/2539-count-the-number-of-good-subsequences.js)|Medium| 2540|[Minimum Common Value](./solutions/2540-minimum-common-value.js)|Easy| 2542|[Maximum Subsequence Score](./solutions/2542-maximum-subsequence-score.js)|Medium| 2543|[Check if Point Is Reachable](./solutions/2543-check-if-point-is-reachable.js)|Hard| @@ -1908,12 +2301,15 @@ 2545|[Sort the Students by Their Kth Score](./solutions/2545-sort-the-students-by-their-kth-score.js)|Medium| 2546|[Apply Bitwise Operations to Make Strings Equal](./solutions/2546-apply-bitwise-operations-to-make-strings-equal.js)|Medium| 2547|[Minimum Cost to Split an Array](./solutions/2547-minimum-cost-to-split-an-array.js)|Hard| +2548|[Maximum Price to Fill a Bag](./solutions/2548-maximum-price-to-fill-a-bag.js)|Medium| 2549|[Count Distinct Numbers on Board](./solutions/2549-count-distinct-numbers-on-board.js)|Easy| 2551|[Put Marbles in Bags](./solutions/2551-put-marbles-in-bags.js)|Hard| 2553|[Separate the Digits in an Array](./solutions/2553-separate-the-digits-in-an-array.js)|Easy| 2554|[Maximum Number of Integers to Choose From a Range I](./solutions/2554-maximum-number-of-integers-to-choose-from-a-range-i.js)|Medium| +2557|[Maximum Number of Integers to Choose From a Range II](./solutions/2557-maximum-number-of-integers-to-choose-from-a-range-ii.js)|Medium| 2559|[Count Vowel Strings in Ranges](./solutions/2559-count-vowel-strings-in-ranges.js)|Medium| 2560|[House Robber IV](./solutions/2560-house-robber-iv.js)|Medium| +2561|[Rearranging Fruits](./solutions/2561-rearranging-fruits.js)|Hard| 2562|[Find the Array Concatenation Value](./solutions/2562-find-the-array-concatenation-value.js)|Easy| 2563|[Count the Number of Fair Pairs](./solutions/2563-count-the-number-of-fair-pairs.js)|Medium| 2566|[Maximum Difference by Remapping a Digit](./solutions/2566-maximum-difference-by-remapping-a-digit.js)|Easy| @@ -1922,6 +2318,7 @@ 2570|[Merge Two 2D Arrays by Summing Values](./solutions/2570-merge-two-2d-arrays-by-summing-values.js)|Easy| 2571|[Minimum Operations to Reduce an Integer to 0](./solutions/2571-minimum-operations-to-reduce-an-integer-to-0.js)|Medium| 2574|[Left and Right Sum Differences](./solutions/2574-left-and-right-sum-differences.js)|Easy| +2576|[Find the Maximum Number of Marked Indices](./solutions/2576-find-the-maximum-number-of-marked-indices.js)|Medium| 2578|[Split With Minimum Sum](./solutions/2578-split-with-minimum-sum.js)|Easy| 2579|[Count Total Number of Colored Cells](./solutions/2579-count-total-number-of-colored-cells.js)|Medium| 2581|[Count Number of Possible Root Nodes](./solutions/2581-count-number-of-possible-root-nodes.js)|Hard| @@ -1931,17 +2328,22 @@ 2586|[Count the Number of Vowel Strings in Range](./solutions/2586-count-the-number-of-vowel-strings-in-range.js)|Easy| 2587|[Rearrange Array to Maximize Prefix Score](./solutions/2587-rearrange-array-to-maximize-prefix-score.js)|Medium| 2588|[Count the Number of Beautiful Subarrays](./solutions/2588-count-the-number-of-beautiful-subarrays.js)|Medium| +2590|[Design a Todo List](./solutions/2590-design-a-todo-list.js)|Medium| 2592|[Maximize Greatness of an Array](./solutions/2592-maximize-greatness-of-an-array.js)|Medium| 2594|[Minimum Time to Repair Cars](./solutions/2594-minimum-time-to-repair-cars.js)|Medium| 2595|[Number of Even and Odd Bits](./solutions/2595-number-of-even-and-odd-bits.js)|Easy| 2596|[Check Knight Tour Configuration](./solutions/2596-check-knight-tour-configuration.js)|Medium| 2597|[The Number of Beautiful Subsets](./solutions/2597-the-number-of-beautiful-subsets.js)|Medium| +2598|[Smallest Missing Non-negative Integer After Operations](./solutions/2598-smallest-missing-non-negative-integer-after-operations.js)|Medium| +2599|[Make the Prefix Sum Non-negative](./solutions/2599-make-the-prefix-sum-non-negative.js)|Medium| 2600|[K Items With the Maximum Sum](./solutions/2600-k-items-with-the-maximum-sum.js)|Easy| 2601|[Prime Subtraction Operation](./solutions/2601-prime-subtraction-operation.js)|Medium| +2604|[Minimum Time to Eat All Grains](./solutions/2604-minimum-time-to-eat-all-grains.js)|Hard| 2605|[Form Smallest Number From Two Digit Arrays](./solutions/2605-form-smallest-number-from-two-digit-arrays.js)|Easy| 2606|[Find the Substring With Maximum Cost](./solutions/2606-find-the-substring-with-maximum-cost.js)|Medium| 2609|[Find the Longest Balanced Substring of a Binary String](./solutions/2609-find-the-longest-balanced-substring-of-a-binary-string.js)|Easy| 2610|[Convert an Array Into a 2D Array With Conditions](./solutions/2610-convert-an-array-into-a-2d-array-with-conditions.js)|Medium| +2613|[Beautiful Pairs](./solutions/2613-beautiful-pairs.js)|Hard| 2615|[Sum of Distances](./solutions/2615-sum-of-distances.js)|Medium| 2616|[Minimize the Maximum Difference of Pairs](./solutions/2616-minimize-the-maximum-difference-of-pairs.js)|Medium| 2618|[Check if Object Instance of Class](./solutions/2618-check-if-object-instance-of-class.js)|Medium| @@ -1954,33 +2356,45 @@ 2625|[Flatten Deeply Nested Array](./solutions/2625-flatten-deeply-nested-array.js)|Medium| 2626|[Array Reduce Transformation](./solutions/2626-array-reduce-transformation.js)|Easy| 2627|[Debounce](./solutions/2627-debounce.js)|Medium| +2628|[JSON Deep Equal](./solutions/2628-json-deep-equal.js)|Medium| 2629|[Function Composition](./solutions/2629-function-composition.js)|Easy| 2630|[Memoize II](./solutions/2630-memoize-ii.js)|Hard| 2631|[Group By](./solutions/2631-group-by.js)|Medium| +2632|[Curry](./solutions/2632-curry.js)|Medium| +2633|[Convert Object to JSON String](./solutions/2633-convert-object-to-json-string.js)|Medium| 2634|[Filter Elements from Array](./solutions/2634-filter-elements-from-array.js)|Easy| 2635|[Apply Transform Over Each Element in Array](./solutions/2635-apply-transform-over-each-element-in-array.js)|Easy| +2636|[Promise Pool](./solutions/2636-promise-pool.js)|Medium| 2637|[Promise Time Limit](./solutions/2637-promise-time-limit.js)|Medium| +2638|[Count the Number of K-Free Subsets](./solutions/2638-count-the-number-of-k-free-subsets.js)|Medium| 2639|[Find the Width of Columns of a Grid](./solutions/2639-find-the-width-of-columns-of-a-grid.js)|Easy| 2640|[Find the Score of All Prefixes of an Array](./solutions/2640-find-the-score-of-all-prefixes-of-an-array.js)|Medium| 2641|[Cousins in Binary Tree II](./solutions/2641-cousins-in-binary-tree-ii.js)|Medium| 2643|[Row With Maximum Ones](./solutions/2643-row-with-maximum-ones.js)|Easy| 2644|[Find the Maximum Divisibility Score](./solutions/2644-find-the-maximum-divisibility-score.js)|Easy| 2645|[Minimum Additions to Make Valid String](./solutions/2645-minimum-additions-to-make-valid-string.js)|Medium| +2646|[Minimize the Total Price of the Trips](./solutions/2646-minimize-the-total-price-of-the-trips.js)|Hard| +2647|[Color the Triangle Red](./solutions/2647-color-the-triangle-red.js)|Hard| 2648|[Generate Fibonacci Sequence](./solutions/2648-generate-fibonacci-sequence.js)|Easy| 2649|[Nested Array Generator](./solutions/2649-nested-array-generator.js)|Medium| 2650|[Design Cancellable Function](./solutions/2650-design-cancellable-function.js)|Hard| 2651|[Calculate Delayed Arrival Time](./solutions/2651-calculate-delayed-arrival-time.js)|Easy| 2652|[Sum Multiples](./solutions/2652-sum-multiples.js)|Easy| +2655|[Find Maximal Uncovered Ranges](./solutions/2655-find-maximal-uncovered-ranges.js)|Medium| 2656|[Maximum Sum With Exactly K Elements](./solutions/2656-maximum-sum-with-exactly-k-elements.js)|Easy| 2657|[Find the Prefix Common Array of Two Arrays](./solutions/2657-find-the-prefix-common-array-of-two-arrays.js)|Medium| 2658|[Maximum Number of Fish in a Grid](./solutions/2658-maximum-number-of-fish-in-a-grid.js)|Medium| 2661|[First Completely Painted Row or Column](./solutions/2661-first-completely-painted-row-or-column.js)|Medium| +2664|[The Knight’s Tour](./solutions/2664-the-knights-tour.js)|Medium| 2665|[Counter II](./solutions/2665-counter-ii.js)|Easy| 2666|[Allow One Function Call](./solutions/2666-allow-one-function-call.js)|Easy| 2667|[Create Hello World Function](./solutions/2667-create-hello-world-function.js)|Easy| 2670|[Find the Distinct Difference Array](./solutions/2670-find-the-distinct-difference-array.js)|Easy| 2672|[Number of Adjacent Elements With the Same Color](./solutions/2672-number-of-adjacent-elements-with-the-same-color.js)|Medium| 2673|[Make Costs of Paths Equal in a Binary Tree](./solutions/2673-make-costs-of-paths-equal-in-a-binary-tree.js)|Medium| +2674|[Split a Circular Linked List](./solutions/2674-split-a-circular-linked-list.js)|Medium| +2675|[Array of Objects to Matrix](./solutions/2675-array-of-objects-to-matrix.js)|Hard| +2676|[Throttle](./solutions/2676-throttle.js)|Medium| 2677|[Chunk Array](./solutions/2677-chunk-array.js)|Easy| 2678|[Number of Senior Citizens](./solutions/2678-number-of-senior-citizens.js)|Easy| 2680|[Maximum OR](./solutions/2680-maximum-or.js)|Medium| @@ -1988,18 +2402,31 @@ 2683|[Neighboring Bitwise XOR](./solutions/2683-neighboring-bitwise-xor.js)|Medium| 2684|[Maximum Number of Moves in a Grid](./solutions/2684-maximum-number-of-moves-in-a-grid.js)|Medium| 2685|[Count the Number of Complete Components](./solutions/2685-count-the-number-of-complete-components.js)|Medium| +2689|[Extract Kth Character From The Rope Tree](./solutions/2689-extract-kth-character-from-the-rope-tree.js)|Easy| +2690|[Infinite Method Object](./solutions/2690-infinite-method-object.js)|Easy| +2691|[Immutability Helper](./solutions/2691-immutability-helper.js)|Hard| +2692|[Make Object Immutable](./solutions/2692-make-object-immutable.js)|Medium| 2693|[Call Function with Custom Context](./solutions/2693-call-function-with-custom-context.js)|Medium| 2694|[Event Emitter](./solutions/2694-event-emitter.js)|Medium| 2695|[Array Wrapper](./solutions/2695-array-wrapper.js)|Easy| 2696|[Minimum String Length After Removing Substrings](./solutions/2696-minimum-string-length-after-removing-substrings.js)|Easy| 2697|[Lexicographically Smallest Palindrome](./solutions/2697-lexicographically-smallest-palindrome.js)|Easy| 2698|[Find the Punishment Number of an Integer](./solutions/2698-find-the-punishment-number-of-an-integer.js)|Medium| +2700|[Differences Between Two Objects](./solutions/2700-differences-between-two-objects.js)|Medium| +2702|[Minimum Operations to Make Numbers Non-positive](./solutions/2702-minimum-operations-to-make-numbers-non-positive.js)|Hard| 2703|[Return Length of Arguments Passed](./solutions/2703-return-length-of-arguments-passed.js)|Easy| 2704|[To Be Or Not To Be](./solutions/2704-to-be-or-not-to-be.js)|Easy| 2705|[Compact Object](./solutions/2705-compact-object.js)|Medium| 2706|[Buy Two Chocolates](./solutions/2706-buy-two-chocolates.js)|Easy| 2707|[Extra Characters in a String](./solutions/2707-extra-characters-in-a-string.js)|Medium| +2709|[Greatest Common Divisor Traversal](./solutions/2709-greatest-common-divisor-traversal.js)|Hard| +2710|[Remove Trailing Zeros From a String](./solutions/2710-remove-trailing-zeros-from-a-string.js)|Easy| +2711|[Difference of Number of Distinct Values on Diagonals](./solutions/2711-difference-of-number-of-distinct-values-on-diagonals.js)|Medium| +2712|[Minimum Cost to Make All Characters Equal](./solutions/2712-minimum-cost-to-make-all-characters-equal.js)|Medium| +2714|[Find Shortest Path with K Hops](./solutions/2714-find-shortest-path-with-k-hops.js)|Hard| 2715|[Timeout Cancellation](./solutions/2715-timeout-cancellation.js)|Easy| +2716|[Minimize String Length](./solutions/2716-minimize-string-length.js)|Easy| +2717|[Semi-Ordered Permutation](./solutions/2717-semi-ordered-permutation.js)|Easy| 2721|[Execute Asynchronous Functions in Parallel](./solutions/2721-execute-asynchronous-functions-in-parallel.js)|Medium| 2722|[Join Two Arrays by ID](./solutions/2722-join-two-arrays-by-id.js)|Medium| 2723|[Add Two Promises](./solutions/2723-add-two-promises.js)|Easy| @@ -2007,60 +2434,354 @@ 2725|[Interval Cancellation](./solutions/2725-interval-cancellation.js)|Easy| 2726|[Calculator with Method Chaining](./solutions/2726-calculator-with-method-chaining.js)|Easy| 2727|[Is Object Empty](./solutions/2727-is-object-empty.js)|Easy| +2728|[Count Houses in a Circular Street](./solutions/2728-count-houses-in-a-circular-street.js)|Easy| +2729|[Check if The Number is Fascinating](./solutions/2729-check-if-the-number-is-fascinating.js)|Easy| +2732|[Find a Good Subset of the Matrix](./solutions/2732-find-a-good-subset-of-the-matrix.js)|Hard| +2733|[Neither Minimum nor Maximum](./solutions/2733-neither-minimum-nor-maximum.js)|Easy| +2737|[Find the Closest Marked Node](./solutions/2737-find-the-closest-marked-node.js)|Medium| +2739|[Total Distance Traveled](./solutions/2739-total-distance-traveled.js)|Easy| +2740|[Find the Value of the Partition](./solutions/2740-find-the-value-of-the-partition.js)|Medium| +2742|[Painting the Walls](./solutions/2742-painting-the-walls.js)|Hard| +2743|[Count Substrings Without Repeating Character](./solutions/2743-count-substrings-without-repeating-character.js)|Medium| +2744|[Find Maximum Number of String Pairs](./solutions/2744-find-maximum-number-of-string-pairs.js)|Easy| +2745|[Construct the Longest New String](./solutions/2745-construct-the-longest-new-string.js)|Medium| +2748|[Number of Beautiful Pairs](./solutions/2748-number-of-beautiful-pairs.js)|Easy| +2749|[Minimum Operations to Make the Integer Zero](./solutions/2749-minimum-operations-to-make-the-integer-zero.js)|Medium| +2751|[Robot Collisions](./solutions/2751-robot-collisions.js)|Hard| +2753|[Count Houses in a Circular Street II](./solutions/2753-count-houses-in-a-circular-street-ii.js)|Hard| +2754|[Bind Function to Context](./solutions/2754-bind-function-to-context.js)|Medium| +2755|[Deep Merge of Two Objects](./solutions/2755-deep-merge-of-two-objects.js)|Medium| +2756|[Query Batching](./solutions/2756-query-batching.js)|Hard| +2757|[Generate Circular Array Values](./solutions/2757-generate-circular-array-values.js)|Medium| +2758|[Next Day](./solutions/2758-next-day.js)|Easy| +2759|[Convert JSON String to Object](./solutions/2759-convert-json-string-to-object.js)|Hard| +2763|[Sum of Imbalance Numbers of All Subarrays](./solutions/2763-sum-of-imbalance-numbers-of-all-subarrays.js)|Hard| +2764|[Is Array a Preorder of Some ‌Binary Tree](./solutions/2764-is-array-a-preorder-of-some-binary-tree.js)|Medium| +2766|[Relocate Marbles](./solutions/2766-relocate-marbles.js)|Medium| +2767|[Partition String Into Minimum Beautiful Substrings](./solutions/2767-partition-string-into-minimum-beautiful-substrings.js)|Medium| +2769|[Find the Maximum Achievable Number](./solutions/2769-find-the-maximum-achievable-number.js)|Easy| +2773|[Height of Special Binary Tree](./solutions/2773-height-of-special-binary-tree.js)|Medium| +2774|[Array Upper Bound](./solutions/2774-array-upper-bound.js)|Easy| +2775|[Undefined to Null](./solutions/2775-undefined-to-null.js)|Medium| +2776|[Convert Callback Based Function to Promise Based Function](./solutions/2776-convert-callback-based-function-to-promise-based-function.js)|Medium| +2777|[Date Range Generator](./solutions/2777-date-range-generator.js)|Medium| +2778|[Sum of Squares of Special Elements](./solutions/2778-sum-of-squares-of-special-elements.js)|Easy| +2779|[Maximum Beauty of an Array After Applying Operation](./solutions/2779-maximum-beauty-of-an-array-after-applying-operation.js)|Medium| 2780|[Minimum Index of a Valid Split](./solutions/2780-minimum-index-of-a-valid-split.js)|Medium| +2782|[Number of Unique Categories](./solutions/2782-number-of-unique-categories.js)|Medium| +2784|[Check if Array is Good](./solutions/2784-check-if-array-is-good.js)|Easy| +2785|[Sort Vowels in a String](./solutions/2785-sort-vowels-in-a-string.js)|Medium| +2787|[Ways to Express an Integer as Sum of Powers](./solutions/2787-ways-to-express-an-integer-as-sum-of-powers.js)|Medium| +2788|[Split Strings by Separator](./solutions/2788-split-strings-by-separator.js)|Easy| +2789|[Largest Element in an Array after Merge Operations](./solutions/2789-largest-element-in-an-array-after-merge-operations.js)|Medium| +2791|[Count Paths That Can Form a Palindrome in a Tree](./solutions/2791-count-paths-that-can-form-a-palindrome-in-a-tree.js)|Hard| +2792|[Count Nodes That Are Great Enough](./solutions/2792-count-nodes-that-are-great-enough.js)|Hard| +2794|[Create Object from Two Arrays](./solutions/2794-create-object-from-two-arrays.js)|Easy| +2795|[Parallel Execution of Promises for Individual Results Retrieval](./solutions/2795-parallel-execution-of-promises-for-individual-results-retrieval.js)|Medium| +2796|[Repeat String](./solutions/2796-repeat-string.js)|Easy| +2797|[Partial Function with Placeholders](./solutions/2797-partial-function-with-placeholders.js)|Easy| +2798|[Number of Employees Who Met the Target](./solutions/2798-number-of-employees-who-met-the-target.js)|Easy| 2799|[Count Complete Subarrays in an Array](./solutions/2799-count-complete-subarrays-in-an-array.js)|Medium| +2802|[Find The K-th Lucky Number](./solutions/2802-find-the-k-th-lucky-number.js)|Medium| +2803|[Factorial Generator](./solutions/2803-factorial-generator.js)|Easy| +2804|[Array Prototype ForEach](./solutions/2804-array-prototype-foreach.js)|Easy| +2805|[Custom Interval](./solutions/2805-custom-interval.js)|Medium| +2806|[Account Balance After Rounded Purchase](./solutions/2806-account-balance-after-rounded-purchase.js)|Easy| +2807|[Insert Greatest Common Divisors in Linked List](./solutions/2807-insert-greatest-common-divisors-in-linked-list.js)|Medium| +2810|[Faulty Keyboard](./solutions/2810-faulty-keyboard.js)|Easy| +2814|[Minimum Time Takes to Reach Destination Without Drowning](./solutions/2814-minimum-time-takes-to-reach-destination-without-drowning.js)|Hard| +2815|[Max Pair Sum in an Array](./solutions/2815-max-pair-sum-in-an-array.js)|Easy| +2816|[Double a Number Represented as a Linked List](./solutions/2816-double-a-number-represented-as-a-linked-list.js)|Medium| 2818|[Apply Operations to Maximize Score](./solutions/2818-apply-operations-to-maximize-score.js)|Hard| +2819|[Minimum Relative Loss After Buying Chocolates](./solutions/2819-minimum-relative-loss-after-buying-chocolates.js)|Hard| +2821|[Delay the Resolution of Each Promise](./solutions/2821-delay-the-resolution-of-each-promise.js)|Medium| +2822|[Inversion of Object](./solutions/2822-inversion-of-object.js)|Easy| +2823|[Deep Object Filter](./solutions/2823-deep-object-filter.js)|Medium| +2824|[Count Pairs Whose Sum is Less than Target](./solutions/2824-count-pairs-whose-sum-is-less-than-target.js)|Easy| +2825|[Make String a Subsequence Using Cyclic Increments](./solutions/2825-make-string-a-subsequence-using-cyclic-increments.js)|Medium| +2826|[Sorting Three Groups](./solutions/2826-sorting-three-groups.js)|Medium| +2828|[Check if a String Is an Acronym of Words](./solutions/2828-check-if-a-string-is-an-acronym-of-words.js)|Easy| +2829|[Determine the Minimum Sum of a k-avoiding Array](./solutions/2829-determine-the-minimum-sum-of-a-k-avoiding-array.js)|Medium| +2832|[Maximal Range That Each Element Is Maximum in It](./solutions/2832-maximal-range-that-each-element-is-maximum-in-it.js)|Medium| +2833|[Furthest Point From Origin](./solutions/2833-furthest-point-from-origin.js)|Easy| +2838|[Maximum Coins Heroes Can Collect](./solutions/2838-maximum-coins-heroes-can-collect.js)|Medium| +2839|[Check if Strings Can be Made Equal With Operations I](./solutions/2839-check-if-strings-can-be-made-equal-with-operations-i.js)|Easy| +2840|[Check if Strings Can be Made Equal With Operations II](./solutions/2840-check-if-strings-can-be-made-equal-with-operations-ii.js)|Medium| +2841|[Maximum Sum of Almost Unique Subarray](./solutions/2841-maximum-sum-of-almost-unique-subarray.js)|Medium| 2843|[Count Symmetric Integers](./solutions/2843-count-symmetric-integers.js)|Easy| 2845|[Count of Interesting Subarrays](./solutions/2845-count-of-interesting-subarrays.js)|Medium| +2846|[Minimum Edge Weight Equilibrium Queries in a Tree](./solutions/2846-minimum-edge-weight-equilibrium-queries-in-a-tree.js)|Hard| +2847|[Smallest Number With Given Digit Product](./solutions/2847-smallest-number-with-given-digit-product.js)|Medium| +2848|[Points That Intersect With Cars](./solutions/2848-points-that-intersect-with-cars.js)|Easy| +2850|[Minimum Moves to Spread Stones Over Grid](./solutions/2850-minimum-moves-to-spread-stones-over-grid.js)|Medium| +2852|[Sum of Remoteness of All Cells](./solutions/2852-sum-of-remoteness-of-all-cells.js)|Medium| +2855|[Minimum Right Shifts to Sort the Array](./solutions/2855-minimum-right-shifts-to-sort-the-array.js)|Easy| +2858|[Minimum Edge Reversals So Every Node Is Reachable](./solutions/2858-minimum-edge-reversals-so-every-node-is-reachable.js)|Hard| +2859|[Sum of Values at Indices With K Set Bits](./solutions/2859-sum-of-values-at-indices-with-k-set-bits.js)|Easy| +2860|[Happy Students](./solutions/2860-happy-students.js)|Medium| +2862|[Maximum Element-Sum of a Complete Subset of Indices](./solutions/2862-maximum-element-sum-of-a-complete-subset-of-indices.js)|Hard| +2863|[Maximum Length of Semi-Decreasing Subarrays](./solutions/2863-maximum-length-of-semi-decreasing-subarrays.js)|Medium| +2864|[Maximum Odd Binary Number](./solutions/2864-maximum-odd-binary-number.js)|Easy| +2865|[Beautiful Towers I](./solutions/2865-beautiful-towers-i.js)|Medium| +2868|[The Wording Game](./solutions/2868-the-wording-game.js)|Hard| +2869|[Minimum Operations to Collect Elements](./solutions/2869-minimum-operations-to-collect-elements.js)|Easy| +2870|[Minimum Number of Operations to Make Array Empty](./solutions/2870-minimum-number-of-operations-to-make-array-empty.js)|Medium| +2871|[Split Array Into Maximum Number of Subarrays](./solutions/2871-split-array-into-maximum-number-of-subarrays.js)|Medium| +2872|[Maximum Number of K-Divisible Components](./solutions/2872-maximum-number-of-k-divisible-components.js)|Hard| 2873|[Maximum Value of an Ordered Triplet I](./solutions/2873-maximum-value-of-an-ordered-triplet-i.js)|Easy| 2874|[Maximum Value of an Ordered Triplet II](./solutions/2874-maximum-value-of-an-ordered-triplet-ii.js)|Medium| +2892|[Minimizing Array After Replacing Pairs With Their Product](./solutions/2892-minimizing-array-after-replacing-pairs-with-their-product.js)|Medium| 2894|[Divisible and Non-divisible Sums Difference](./solutions/2894-divisible-and-non-divisible-sums-difference.js)|Easy| +2895|[Minimum Processing Time](./solutions/2895-minimum-processing-time.js)|Medium| +2897|[Apply Operations on Array to Maximize Sum of Squares](./solutions/2897-apply-operations-on-array-to-maximize-sum-of-squares.js)|Hard| +2898|[Maximum Linear Stock Score](./solutions/2898-maximum-linear-stock-score.js)|Medium| +2899|[Last Visited Integers](./solutions/2899-last-visited-integers.js)|Easy| 2900|[Longest Unequal Adjacent Groups Subsequence I](./solutions/2900-longest-unequal-adjacent-groups-subsequence-i.js)|Easy| 2901|[Longest Unequal Adjacent Groups Subsequence II](./solutions/2901-longest-unequal-adjacent-groups-subsequence-ii.js)|Medium| +2903|[Find Indices With Index and Value Difference I](./solutions/2903-find-indices-with-index-and-value-difference-i.js)|Easy| +2904|[Shortest and Lexicographically Smallest Beautiful String](./solutions/2904-shortest-and-lexicographically-smallest-beautiful-string.js)|Medium| +2907|[Maximum Profitable Triplets With Increasing Prices I](./solutions/2907-maximum-profitable-triplets-with-increasing-prices-i.js)|Medium| +2908|[Minimum Sum of Mountain Triplets I](./solutions/2908-minimum-sum-of-mountain-triplets-i.js)|Easy| +2909|[Minimum Sum of Mountain Triplets II](./solutions/2909-minimum-sum-of-mountain-triplets-ii.js)|Medium| +2912|[Number of Ways to Reach Destination in the Grid](./solutions/2912-number-of-ways-to-reach-destination-in-the-grid.js)|Hard| +2913|[Subarrays Distinct Element Sum of Squares I](./solutions/2913-subarrays-distinct-element-sum-of-squares-i.js)|Easy| +2914|[Minimum Number of Changes to Make Binary String Beautiful](./solutions/2914-minimum-number-of-changes-to-make-binary-string-beautiful.js)|Medium| +2917|[Find the K-or of an Array](./solutions/2917-find-the-k-or-of-an-array.js)|Easy| 2918|[Minimum Equal Sum of Two Arrays After Replacing Zeros](./solutions/2918-minimum-equal-sum-of-two-arrays-after-replacing-zeros.js)|Medium| +2921|[Maximum Profitable Triplets With Increasing Prices II](./solutions/2921-maximum-profitable-triplets-with-increasing-prices-ii.js)|Hard| +2923|[Find Champion I](./solutions/2923-find-champion-i.js)|Easy| +2924|[Find Champion II](./solutions/2924-find-champion-ii.js)|Medium| +2925|[Maximum Score After Applying Operations on a Tree](./solutions/2925-maximum-score-after-applying-operations-on-a-tree.js)|Medium| +2927|[Distribute Candies Among Children III](./solutions/2927-distribute-candies-among-children-iii.js)|Hard| +2928|[Distribute Candies Among Children I](./solutions/2928-distribute-candies-among-children-i.js)|Easy| +2929|[Distribute Candies Among Children II](./solutions/2929-distribute-candies-among-children-ii.js)|Medium| +2932|[Maximum Strong Pair XOR I](./solutions/2932-maximum-strong-pair-xor-i.js)|Easy| +2933|[High-Access Employees](./solutions/2933-high-access-employees.js)|Medium| +2934|[Minimum Operations to Maximize Last Elements in Arrays](./solutions/2934-minimum-operations-to-maximize-last-elements-in-arrays.js)|Medium| +2936|[Number of Equal Numbers Blocks](./solutions/2936-number-of-equal-numbers-blocks.js)|Medium| +2937|[Make Three Strings Equal](./solutions/2937-make-three-strings-equal.js)|Easy| +2938|[Separate Black and White Balls](./solutions/2938-separate-black-and-white-balls.js)|Medium| +2941|[Maximum GCD-Sum of a Subarray](./solutions/2941-maximum-gcd-sum-of-a-subarray.js)|Hard| 2942|[Find Words Containing Character](./solutions/2942-find-words-containing-character.js)|Easy| +2946|[Matrix Similarity After Cyclic Shifts](./solutions/2946-matrix-similarity-after-cyclic-shifts.js)|Easy| +2947|[Count Beautiful Substrings I](./solutions/2947-count-beautiful-substrings-i.js)|Medium| 2948|[Make Lexicographically Smallest Array by Swapping Elements](./solutions/2948-make-lexicographically-smallest-array-by-swapping-elements.js)|Medium| +2950|[Number of Divisible Substrings](./solutions/2950-number-of-divisible-substrings.js)|Medium| +2951|[Find the Peaks](./solutions/2951-find-the-peaks.js)|Easy| +2952|[Minimum Number of Coins to be Added](./solutions/2952-minimum-number-of-coins-to-be-added.js)|Medium| +2955|[Number of Same-End Substrings](./solutions/2955-number-of-same-end-substrings.js)|Medium| +2956|[Find Common Elements Between Two Arrays](./solutions/2956-find-common-elements-between-two-arrays.js)|Easy| +2957|[Remove Adjacent Almost-Equal Characters](./solutions/2957-remove-adjacent-almost-equal-characters.js)|Medium| +2958|[Length of Longest Subarray With at Most K Frequency](./solutions/2958-length-of-longest-subarray-with-at-most-k-frequency.js)|Medium| +2960|[Count Tested Devices After Test Operations](./solutions/2960-count-tested-devices-after-test-operations.js)|Easy| +2961|[Double Modular Exponentiation](./solutions/2961-double-modular-exponentiation.js)|Medium| 2962|[Count Subarrays Where Max Element Appears at Least K Times](./solutions/2962-count-subarrays-where-max-element-appears-at-least-k-times.js)|Medium| +2963|[Count the Number of Good Partitions](./solutions/2963-count-the-number-of-good-partitions.js)|Hard| +2964|[Number of Divisible Triplet Sums](./solutions/2964-number-of-divisible-triplet-sums.js)|Medium| 2965|[Find Missing and Repeated Values](./solutions/2965-find-missing-and-repeated-values.js)|Easy| +2966|[Divide Array Into Arrays With Max Difference](./solutions/2966-divide-array-into-arrays-with-max-difference.js)|Medium| +2969|[Minimum Number of Coins for Fruits II](./solutions/2969-minimum-number-of-coins-for-fruits-ii.js)|Hard| +2970|[Count the Number of Incremovable Subarrays I](./solutions/2970-count-the-number-of-incremovable-subarrays-i.js)|Easy| +2971|[Find Polygon With the Largest Perimeter](./solutions/2971-find-polygon-with-the-largest-perimeter.js)|Medium| +2976|[Minimum Cost to Convert String I](./solutions/2976-minimum-cost-to-convert-string-i.js)|Medium| +2979|[Most Expensive Item That Can Not Be Bought](./solutions/2979-most-expensive-item-that-can-not-be-bought.js)|Medium| +2980|[Check if Bitwise OR Has Trailing Zeros](./solutions/2980-check-if-bitwise-or-has-trailing-zeros.js)|Easy| +2981|[Find Longest Special Substring That Occurs Thrice I](./solutions/2981-find-longest-special-substring-that-occurs-thrice-i.js)|Medium| +2992|[Number of Self-Divisible Permutations](./solutions/2992-number-of-self-divisible-permutations.js)|Medium| +2997|[Minimum Number of Operations to Make Array XOR Equal to K](./solutions/2997-minimum-number-of-operations-to-make-array-xor-equal-to-k.js)|Medium| +2998|[Minimum Number of Operations to Make X and Y Equal](./solutions/2998-minimum-number-of-operations-to-make-x-and-y-equal.js)|Medium| 2999|[Count the Number of Powerful Integers](./solutions/2999-count-the-number-of-powerful-integers.js)|Hard| +3000|[Maximum Area of Longest Diagonal Rectangle](./solutions/3000-maximum-area-of-longest-diagonal-rectangle.js)|Easy| +3002|[Maximum Size of a Set After Removals](./solutions/3002-maximum-size-of-a-set-after-removals.js)|Medium| +3004|[Maximum Subtree of the Same Color](./solutions/3004-maximum-subtree-of-the-same-color.js)|Medium| +3005|[Count Elements With Maximum Frequency](./solutions/3005-count-elements-with-maximum-frequency.js)|Easy| +3009|[Maximum Number of Intersections on the Chart](./solutions/3009-maximum-number-of-intersections-on-the-chart.js)|Hard| +3010|[Divide an Array Into Subarrays With Minimum Cost I](./solutions/3010-divide-an-array-into-subarrays-with-minimum-cost-i.js)|Easy| +3011|[Find if Array Can Be Sorted](./solutions/3011-find-if-array-can-be-sorted.js)|Medium| +3014|[Minimum Number of Pushes to Type Word I](./solutions/3014-minimum-number-of-pushes-to-type-word-i.js)|Easy| +3015|[Count the Number of Houses at a Certain Distance I](./solutions/3015-count-the-number-of-houses-at-a-certain-distance-i.js)|Medium| +3016|[Minimum Number of Pushes to Type Word II](./solutions/3016-minimum-number-of-pushes-to-type-word-ii.js)|Medium| +3018|[Maximum Number of Removal Queries That Can Be Processed I](./solutions/3018-maximum-number-of-removal-queries-that-can-be-processed-i.js)|Hard| +3019|[Number of Changing Keys](./solutions/3019-number-of-changing-keys.js)|Easy| +3021|[Alice and Bob Playing Flower Game](./solutions/3021-alice-and-bob-playing-flower-game.js)|Medium| +3023|[Find Pattern in Infinite Stream I](./solutions/3023-find-pattern-in-infinite-stream-i.js)|Medium| 3024|[Type of Triangle](./solutions/3024-type-of-triangle.js)|Easy| +3025|[Find the Number of Ways to Place People I](./solutions/3025-find-the-number-of-ways-to-place-people-i.js)|Medium| +3027|[Find the Number of Ways to Place People II](./solutions/3027-find-the-number-of-ways-to-place-people-ii.js)|Hard| +3028|[Ant on the Boundary](./solutions/3028-ant-on-the-boundary.js)|Easy| +3029|[Minimum Time to Revert Word to Initial State I](./solutions/3029-minimum-time-to-revert-word-to-initial-state-i.js)|Medium| +3030|[Find the Grid of Region Average](./solutions/3030-find-the-grid-of-region-average.js)|Medium| +3032|[Count Numbers With Unique Digits II](./solutions/3032-count-numbers-with-unique-digits-ii.js)|Easy| +3033|[Modify the Matrix](./solutions/3033-modify-the-matrix.js)|Easy| +3034|[Number of Subarrays That Match a Pattern I](./solutions/3034-number-of-subarrays-that-match-a-pattern-i.js)|Medium| +3035|[Maximum Palindromes After Operations](./solutions/3035-maximum-palindromes-after-operations.js)|Medium| +3037|[Find Pattern in Infinite Stream II](./solutions/3037-find-pattern-in-infinite-stream-ii.js)|Hard| +3038|[Maximum Number of Operations With the Same Score I](./solutions/3038-maximum-number-of-operations-with-the-same-score-i.js)|Easy| +3039|[Apply Operations to Make String Empty](./solutions/3039-apply-operations-to-make-string-empty.js)|Medium| 3042|[Count Prefix and Suffix Pairs I](./solutions/3042-count-prefix-and-suffix-pairs-i.js)|Easy| +3043|[Find the Length of the Longest Common Prefix](./solutions/3043-find-the-length-of-the-longest-common-prefix.js)|Medium| +3044|[Most Frequent Prime](./solutions/3044-most-frequent-prime.js)|Medium| +3046|[Split the Array](./solutions/3046-split-the-array.js)|Easy| +3047|[Find the Largest Area of Square Inside Two Rectangles](./solutions/3047-find-the-largest-area-of-square-inside-two-rectangles.js)|Medium| +3062|[Winner of the Linked List Game](./solutions/3062-winner-of-the-linked-list-game.js)|Easy| +3063|[Linked List Frequency](./solutions/3063-linked-list-frequency.js)|Easy| +3064|[Guess the Number Using Bitwise Questions I](./solutions/3064-guess-the-number-using-bitwise-questions-i.js)|Medium| +3065|[Minimum Operations to Exceed Threshold Value I](./solutions/3065-minimum-operations-to-exceed-threshold-value-i.js)|Easy| 3066|[Minimum Operations to Exceed Threshold Value II](./solutions/3066-minimum-operations-to-exceed-threshold-value-ii.js)|Medium| +3067|[Count Pairs of Connectable Servers in a Weighted Tree Network](./solutions/3067-count-pairs-of-connectable-servers-in-a-weighted-tree-network.js)|Medium| 3068|[Find the Maximum Sum of Node Values](./solutions/3068-find-the-maximum-sum-of-node-values.js)|Hard| +3069|[Distribute Elements Into Two Arrays I](./solutions/3069-distribute-elements-into-two-arrays-i.js)|Easy| +3070|[Count Submatrices with Top-Left Element and Sum Less Than k](./solutions/3070-count-submatrices-with-top-left-element-and-sum-less-than-k.js)|Medium| +3071|[Minimum Operations to Write the Letter Y on a Grid](./solutions/3071-minimum-operations-to-write-the-letter-y-on-a-grid.js)|Medium| +3073|[Maximum Increasing Triplet Value](./solutions/3073-maximum-increasing-triplet-value.js)|Medium| +3074|[Apple Redistribution into Boxes](./solutions/3074-apple-redistribution-into-boxes.js)|Easy| +3075|[Maximize Happiness of Selected Children](./solutions/3075-maximize-happiness-of-selected-children.js)|Medium| +3076|[Shortest Uncommon Substring in an Array](./solutions/3076-shortest-uncommon-substring-in-an-array.js)|Medium| +3078|[Match Alphanumerical Pattern in Matrix I](./solutions/3078-match-alphanumerical-pattern-in-matrix-i.js)|Medium| +3079|[Find the Sum of Encrypted Integers](./solutions/3079-find-the-sum-of-encrypted-integers.js)|Easy| +3083|[Existence of a Substring in a String and Its Reverse](./solutions/3083-existence-of-a-substring-in-a-string-and-its-reverse.js)|Easy| +3084|[Count Substrings Starting and Ending with Given Character](./solutions/3084-count-substrings-starting-and-ending-with-given-character.js)|Medium| +3085|[Minimum Deletions to Make String K-Special](./solutions/3085-minimum-deletions-to-make-string-k-special.js)|Medium| +3088|[Make String Anti-palindrome](./solutions/3088-make-string-anti-palindrome.js)|Hard| +3090|[Maximum Length Substring With Two Occurrences](./solutions/3090-maximum-length-substring-with-two-occurrences.js)|Easy| +3091|[Apply Operations to Make Sum of Array Greater Than or Equal to k](./solutions/3091-apply-operations-to-make-sum-of-array-greater-than-or-equal-to-k.js)|Medium| +3094|[Guess the Number Using Bitwise Questions II](./solutions/3094-guess-the-number-using-bitwise-questions-ii.js)|Medium| +3095|[Shortest Subarray With OR at Least K I](./solutions/3095-shortest-subarray-with-or-at-least-k-i.js)|Easy| +3097|[Shortest Subarray With OR at Least K II](./solutions/3097-shortest-subarray-with-or-at-least-k-ii.js)|Medium| +3099|[Harshad Number](./solutions/3099-harshad-number.js)|Easy| +3100|[Water Bottles II](./solutions/3100-water-bottles-ii.js)|Medium| +3104|[Find Longest Self-Contained Substring](./solutions/3104-find-longest-self-contained-substring.js)|Hard| 3105|[Longest Strictly Increasing or Strictly Decreasing Subarray](./solutions/3105-longest-strictly-increasing-or-strictly-decreasing-subarray.js)|Easy| 3108|[Minimum Cost Walk in Weighted Graph](./solutions/3108-minimum-cost-walk-in-weighted-graph.js)|Hard| +3109|[Find the Index of Permutation](./solutions/3109-find-the-index-of-permutation.js)|Medium| 3110|[Score of a String](./solutions/3110-score-of-a-string.js)|Easy| +3119|[Maximum Number of Potholes That Can Be Fixed](./solutions/3119-maximum-number-of-potholes-that-can-be-fixed.js)|Medium| +3125|[Maximum Number That Makes Result of Bitwise AND Zero](./solutions/3125-maximum-number-that-makes-result-of-bitwise-and-zero.js)|Medium| +3135|[Equalize Strings by Adding or Removing Characters at Ends](./solutions/3135-equalize-strings-by-adding-or-removing-characters-at-ends.js)|Medium| +3136|[Valid Word](./solutions/3136-valid-word.js)|Easy| +3141|[Maximum Hamming Distances](./solutions/3141-maximum-hamming-distances.js)|Hard| +3147|[Taking Maximum Energy From the Mystic Dungeon](./solutions/3147-taking-maximum-energy-from-the-mystic-dungeon.js)|Medium| 3151|[Special Array I](./solutions/3151-special-array-i.js)|Easy| +3155|[Maximum Number of Upgradable Servers](./solutions/3155-maximum-number-of-upgradable-servers.js)|Medium| +3157|[Find the Level of Tree with Minimum Sum](./solutions/3157-find-the-level-of-tree-with-minimum-sum.js)|Medium| 3160|[Find the Number of Distinct Colors Among the Balls](./solutions/3160-find-the-number-of-distinct-colors-among-the-balls.js)|Medium| +3167|[Better Compression of String](./solutions/3167-better-compression-of-string.js)|Medium| 3169|[Count Days Without Meetings](./solutions/3169-count-days-without-meetings.js)|Medium| +3170|[Lexicographically Minimum String After Removing Stars](./solutions/3170-lexicographically-minimum-string-after-removing-stars.js)|Medium| +3173|[Bitwise OR of Adjacent Elements](./solutions/3173-bitwise-or-of-adjacent-elements.js)|Easy| 3174|[Clear Digits](./solutions/3174-clear-digits.js)|Easy| 3178|[Find the Child Who Has the Ball After K Seconds](./solutions/3178-find-the-child-who-has-the-ball-after-k-seconds.js)|Easy| +3183|[The Number of Ways to Make the Sum](./solutions/3183-the-number-of-ways-to-make-the-sum.js)|Medium| +3186|[Maximum Total Damage With Spell Casting](./solutions/3186-maximum-total-damage-with-spell-casting.js)|Medium| +3189|[Minimum Moves to Get a Peaceful Board](./solutions/3189-minimum-moves-to-get-a-peaceful-board.js)|Medium| 3191|[Minimum Operations to Make Binary Array Elements Equal to One I](./solutions/3191-minimum-operations-to-make-binary-array-elements-equal-to-one-i.js)|Medium| +3195|[Find the Minimum Area to Cover All Ones I](./solutions/3195-find-the-minimum-area-to-cover-all-ones-i.js)|Medium| +3197|[Find the Minimum Area to Cover All Ones II](./solutions/3197-find-the-minimum-area-to-cover-all-ones-ii.js)|Hard| +3199|[Count Triplets with Even XOR Set Bits I](./solutions/3199-count-triplets-with-even-xor-set-bits-i.js)|Easy| +3201|[Find the Maximum Length of Valid Subsequence I](./solutions/3201-find-the-maximum-length-of-valid-subsequence-i.js)|Medium| +3202|[Find the Maximum Length of Valid Subsequence II](./solutions/3202-find-the-maximum-length-of-valid-subsequence-ii.js)|Medium| +3205|[Maximum Array Hopping Score I](./solutions/3205-maximum-array-hopping-score-i.js)|Medium| 3208|[Alternating Groups II](./solutions/3208-alternating-groups-ii.js)|Medium| +3215|[Count Triplets with Even XOR Set Bits II](./solutions/3215-count-triplets-with-even-xor-set-bits-ii.js)|Medium| +3217|[Delete Nodes From Linked List Present in Array](./solutions/3217-delete-nodes-from-linked-list-present-in-array.js)|Medium| +3221|[Maximum Array Hopping Score II](./solutions/3221-maximum-array-hopping-score-ii.js)|Medium| 3223|[Minimum Length of String After Operations](./solutions/3223-minimum-length-of-string-after-operations.js)|Medium| +3227|[Vowels Game in a String](./solutions/3227-vowels-game-in-a-string.js)|Medium| +3231|[Minimum Number of Increasing Subsequence to Be Removed](./solutions/3231-minimum-number-of-increasing-subsequence-to-be-removed.js)|Hard| +3237|[Alt and Tab Simulation](./solutions/3237-alt-and-tab-simulation.js)|Medium| +3247|[Number of Subsequences with Odd Sum](./solutions/3247-number-of-subsequences-with-odd-sum.js)|Medium| +3253|[Construct String with Minimum Cost (Easy)](./solutions/3253-construct-string-with-minimum-cost-easy.js)|Medium| +3263|[Convert Doubly Linked List to Array I](./solutions/3263-convert-doubly-linked-list-to-array-i.js)|Easy| +3269|[Constructing Two Increasing Arrays](./solutions/3269-constructing-two-increasing-arrays.js)|Hard| 3272|[Find the Count of Good Integers](./solutions/3272-find-the-count-of-good-integers.js)|Hard| +3279|[Maximum Total Area Occupied by Pistons](./solutions/3279-maximum-total-area-occupied-by-pistons.js)|Hard| +3284|[Sum of Consecutive Subarrays](./solutions/3284-sum-of-consecutive-subarrays.js)|Medium| +3289|[The Two Sneaky Numbers of Digitville](./solutions/3289-the-two-sneaky-numbers-of-digitville.js)|Easy| +3294|[Convert Doubly Linked List to Array II](./solutions/3294-convert-doubly-linked-list-to-array-ii.js)|Medium| +3299|[Sum of Consecutive Subsequences](./solutions/3299-sum-of-consecutive-subsequences.js)|Hard| +3304|[Find the K-th Character in String Game I](./solutions/3304-find-the-k-th-character-in-string-game-i.js)|Easy| 3306|[Count of Substrings Containing Every Vowel and K Consonants II](./solutions/3306-count-of-substrings-containing-every-vowel-and-k-consonants-ii.js)|Medium| +3307|[Find the K-th Character in String Game II](./solutions/3307-find-the-k-th-character-in-string-game-ii.js)|Hard| +3313|[Find the Last Marked Nodes in Tree](./solutions/3313-find-the-last-marked-nodes-in-tree.js)|Hard| +3318|[Find X-Sum of All K-Long Subarrays I](./solutions/3318-find-x-sum-of-all-k-long-subarrays-i.js)|Easy| +3323|[Minimize Connected Groups by Inserting Interval](./solutions/3323-minimize-connected-groups-by-inserting-interval.js)|Medium| +3329|[Count Substrings With K-Frequency Characters II](./solutions/3329-count-substrings-with-k-frequency-characters-ii.js)|Hard| +3330|[Find the Original Typed String I](./solutions/3330-find-the-original-typed-string-i.js)|Easy| +3333|[Find the Original Typed String II](./solutions/3333-find-the-original-typed-string-ii.js)|Hard| 3335|[Total Characters in String After Transformations I](./solutions/3335-total-characters-in-string-after-transformations-i.js)|Medium| 3337|[Total Characters in String After Transformations II](./solutions/3337-total-characters-in-string-after-transformations-ii.js)|Hard| +3339|[Find the Number of K-Even Arrays](./solutions/3339-find-the-number-of-k-even-arrays.js)|Medium| 3341|[Find Minimum Time to Reach Last Room I](./solutions/3341-find-minimum-time-to-reach-last-room-i.js)|Medium| 3342|[Find Minimum Time to Reach Last Room II](./solutions/3342-find-minimum-time-to-reach-last-room-ii.js)|Medium| 3343|[Count Number of Balanced Permutations](./solutions/3343-count-number-of-balanced-permutations.js)|Hard| +3344|[Maximum Sized Array](./solutions/3344-maximum-sized-array.js)|Medium| +3346|[Maximum Frequency of an Element After Performing Operations I](./solutions/3346-maximum-frequency-of-an-element-after-performing-operations-i.js)|Medium| +3347|[Maximum Frequency of an Element After Performing Operations II](./solutions/3347-maximum-frequency-of-an-element-after-performing-operations-ii.js)|Hard| +3349|[Adjacent Increasing Subarrays Detection I](./solutions/3349-adjacent-increasing-subarrays-detection-i.js)|Easy| +3350|[Adjacent Increasing Subarrays Detection II](./solutions/3350-adjacent-increasing-subarrays-detection-ii.js)|Medium| +3353|[Minimum Total Operations](./solutions/3353-minimum-total-operations.js)|Easy| +3354|[Make Array Elements Equal to Zero](./solutions/3354-make-array-elements-equal-to-zero.js)|Easy| 3355|[Zero Array Transformation I](./solutions/3355-zero-array-transformation-i.js)|Medium| 3356|[Zero Array Transformation II](./solutions/3356-zero-array-transformation-ii.js)|Medium| +3359|[Find Sorted Submatrices With Maximum Element at Most K](./solutions/3359-find-sorted-submatrices-with-maximum-element-at-most-k.js)|Hard| 3362|[Zero Array Transformation III](./solutions/3362-zero-array-transformation-iii.js)|Medium| +3363|[Find the Maximum Number of Fruits Collected](./solutions/3363-find-the-maximum-number-of-fruits-collected.js)|Hard| +3369|[Design an Array Statistics Tracker](./solutions/3369-design-an-array-statistics-tracker.js)|Hard| +3370|[Smallest Number With All Set Bits](./solutions/3370-smallest-number-with-all-set-bits.js)|Easy| 3372|[Maximize the Number of Target Nodes After Connecting Trees I](./solutions/3372-maximize-the-number-of-target-nodes-after-connecting-trees-i.js)|Medium| 3373|[Maximize the Number of Target Nodes After Connecting Trees II](./solutions/3373-maximize-the-number-of-target-nodes-after-connecting-trees-ii.js)|Hard| 3375|[Minimum Operations to Make Array Values Equal to K](./solutions/3375-minimum-operations-to-make-array-values-equal-to-k.js)|Easy| +3383|[Minimum Runes to Add to Cast Spell](./solutions/3383-minimum-runes-to-add-to-cast-spell.js)|Hard| +3385|[Minimum Time to Break Locks II](./solutions/3385-minimum-time-to-break-locks-ii.js)|Hard| +3391|[Design a 3D Binary Matrix with Efficient Layer Tracking](./solutions/3391-design-a-3d-binary-matrix-with-efficient-layer-tracking.js)|Medium| 3392|[Count Subarrays of Length Three With a Condition](./solutions/3392-count-subarrays-of-length-three-with-a-condition.js)|Easy| 3394|[Check if Grid can be Cut into Sections](./solutions/3394-check-if-grid-can-be-cut-into-sections.js)|Medium| 3396|[Minimum Number of Operations to Make Elements in Array Distinct](./solutions/3396-minimum-number-of-operations-to-make-elements-in-array-distinct.js)|Easy| 3397|[Maximum Number of Distinct Elements After Operations](./solutions/3397-maximum-number-of-distinct-elements-after-operations.js)|Medium| +3400|[Maximum Number of Matching Indices After Right Shifts](./solutions/3400-maximum-number-of-matching-indices-after-right-shifts.js)|Medium| 3402|[Minimum Operations to Make Columns Strictly Increasing](./solutions/3402-minimum-operations-to-make-columns-strictly-increasing.js)|Easy| +3403|[Find the Lexicographically Largest String From the Box I](./solutions/3403-find-the-lexicographically-largest-string-from-the-box-i.js)|Medium| +3405|[Count the Number of Arrays with K Matching Adjacent Elements](./solutions/3405-count-the-number-of-arrays-with-k-matching-adjacent-elements.js)|Hard| +3406|[Find the Lexicographically Largest String From the Box II](./solutions/3406-find-the-lexicographically-largest-string-from-the-box-ii.js)|Hard| +3408|[Design Task Manager](./solutions/3408-design-task-manager.js)|Medium| +3416|[Subsequences with a Unique Middle Mode II](./solutions/3416-subsequences-with-a-unique-middle-mode-ii.js)|Hard| +3422|[Minimum Operations to Make Subarray Elements Equal](./solutions/3422-minimum-operations-to-make-subarray-elements-equal.js)|Medium| +3423|[Maximum Difference Between Adjacent Elements in a Circular Array](./solutions/3423-maximum-difference-between-adjacent-elements-in-a-circular-array.js)|Easy| +3431|[Minimum Unlocked Indices to Sort Nums](./solutions/3431-minimum-unlocked-indices-to-sort-nums.js)|Medium| +3437|[Permutations III](./solutions/3437-permutations-iii.js)|Medium| +3439|[Reschedule Meetings for Maximum Free Time I](./solutions/3439-reschedule-meetings-for-maximum-free-time-i.js)|Medium| +3440|[Reschedule Meetings for Maximum Free Time II](./solutions/3440-reschedule-meetings-for-maximum-free-time-ii.js)|Medium| +3442|[Maximum Difference Between Even and Odd Frequency I](./solutions/3442-maximum-difference-between-even-and-odd-frequency-i.js)|Easy| +3443|[Maximum Manhattan Distance After K Changes](./solutions/3443-maximum-manhattan-distance-after-k-changes.js)|Medium| +3445|[Maximum Difference Between Even and Odd Frequency II](./solutions/3445-maximum-difference-between-even-and-odd-frequency-ii.js)|Hard| +3446|[Sort Matrix by Diagonals](./solutions/3446-sort-matrix-by-diagonals.js)|Medium| +3450|[Maximum Students on a Single Bench](./solutions/3450-maximum-students-on-a-single-bench.js)|Easy| 3452|[Sum of Good Numbers](./solutions/3452-sum-of-good-numbers.js)|Easy| +3460|[Longest Common Prefix After at Most One Removal](./solutions/3460-longest-common-prefix-after-at-most-one-removal.js)|Medium| 3461|[Check If Digits Are Equal in String After Operations I](./solutions/3461-check-if-digits-are-equal-in-string-after-operations-i.js)|Easy| 3462|[Maximum Sum With at Most K Elements](./solutions/3462-maximum-sum-with-at-most-k-elements.js)|Medium| 3463|[Check If Digits Are Equal in String After Operations II](./solutions/3463-check-if-digits-are-equal-in-string-after-operations-ii.js)|Hard| 3464|[Maximize the Distance Between Points on a Square](./solutions/3464-maximize-the-distance-between-points-on-a-square.js)|Hard| +3466|[Maximum Coin Collection](./solutions/3466-maximum-coin-collection.js)|Medium| +3476|[Maximize Profit from Task Assignment](./solutions/3476-maximize-profit-from-task-assignment.js)|Medium| +3477|[Fruits Into Baskets II](./solutions/3477-fruits-into-baskets-ii.js)|Easy| +3479|[Fruits Into Baskets III](./solutions/3479-fruits-into-baskets-iii.js)|Medium| +3480|[Maximize Subarrays After Removing One Conflicting Pair](./solutions/3480-maximize-subarrays-after-removing-one-conflicting-pair.js)|Hard| +3481|[Apply Substitutions](./solutions/3481-apply-substitutions.js)|Medium| +3484|[Design Spreadsheet](./solutions/3484-design-spreadsheet.js)|Medium| +3487|[Maximum Unique Subarray Sum After Deletion](./solutions/3487-maximum-unique-subarray-sum-after-deletion.js)|Easy| +3491|[Phone Number Prefix](./solutions/3491-phone-number-prefix.js)|Easy| +3494|[Find the Minimum Amount of Time to Brew Potions](./solutions/3494-find-the-minimum-amount-of-time-to-brew-potions.js)|Medium| +3495|[Minimum Operations to Make Array Elements Zero](./solutions/3495-minimum-operations-to-make-array-elements-zero.js)|Hard| +3496|[Maximize Score After Pair Deletions](./solutions/3496-maximize-score-after-pair-deletions.js)|Medium| +3506|[Find Time Required to Eliminate Bacterial Strains](./solutions/3506-find-time-required-to-eliminate-bacterial-strains.js)|Hard| +3508|[Implement Router](./solutions/3508-implement-router.js)|Medium| +3511|[Make a Positive Array](./solutions/3511-make-a-positive-array.js)|Medium| +3516|[Find Closest Person](./solutions/3516-find-closest-person.js)|Easy| +3520|[Minimum Threshold for Inversion Pairs Count](./solutions/3520-minimum-threshold-for-inversion-pairs-count.js)|Medium| +3535|[Unit Conversion II](./solutions/3535-unit-conversion-ii.js)|Medium| +3539|[Find Sum of Array Product of Magical Sequences](./solutions/3539-find-sum-of-array-product-of-magical-sequences.js)|Hard| +3541|[Find Most Frequent Vowel and Consonant](./solutions/3541-find-most-frequent-vowel-and-consonant.js)|Easy| ## License diff --git a/solutions/0156-binary-tree-upside-down.js b/solutions/0156-binary-tree-upside-down.js new file mode 100644 index 00000000..77bfd8ce --- /dev/null +++ b/solutions/0156-binary-tree-upside-down.js @@ -0,0 +1,39 @@ +/** + * 156. Binary Tree Upside Down + * https://leetcode.com/problems/binary-tree-upside-down/ + * Difficulty: Medium + * + * Given the root of a binary tree, turn the tree upside down and return the new root. + * + * You can turn a binary tree upside down with the following steps: + * - The original left child becomes the new root. + * - The original root becomes the new right child. + * - The original right child becomes the new left child. + * + * The mentioned steps are done level by level. It is guaranteed that every right node has + * a sibling (a left node with the same parent) and has no children. + */ + +/** + * 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} + */ +var upsideDownBinaryTree = function(root) { + if (!root || !root.left) 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/solutions/0157-read-n-characters-given-read4.js b/solutions/0157-read-n-characters-given-read4.js new file mode 100644 index 00000000..0074fec8 --- /dev/null +++ b/solutions/0157-read-n-characters-given-read4.js @@ -0,0 +1,48 @@ +/** + * 157. Read N Characters Given Read4 + * https://leetcode.com/problems/read-n-characters-given-read4/ + * Difficulty: Easy + * + * Given a file and assume that you can only read the file using a given method read4, implement + * a method to read n characters. + * + * Method read4: + * - The API read4 reads four consecutive characters from file, then writes those characters into + * the buffer array buf4. + * + * The return value is the number of actual characters read. + * + * Note that read4() has its own file pointer, much like FILE *fp in C. + */ + +/** + * @param {function} read4() + * @return {function} + */ +var solution = function(read4) { + let cache = []; + let cacheIndex = 0; + let cacheSize = 0; + + /** + * @param {character[]} buf Destination buffer + * @param {number} n Number of characters to read + * @return {number} The number of actual characters read + */ + return function(buf, n) { + let charsRead = 0; + + while (charsRead < n) { + if (cacheIndex >= cacheSize) { + cache = new Array(4); + cacheSize = read4(cache); + cacheIndex = 0; + if (cacheSize === 0) break; + } + + buf[charsRead++] = cache[cacheIndex++]; + } + + return charsRead; + }; +}; diff --git a/solutions/0158-read-n-characters-given-read4-ii-call-multiple-times.js b/solutions/0158-read-n-characters-given-read4-ii-call-multiple-times.js new file mode 100644 index 00000000..9fdd7b54 --- /dev/null +++ b/solutions/0158-read-n-characters-given-read4-ii-call-multiple-times.js @@ -0,0 +1,48 @@ +/** + * 158. Read N Characters Given read4 II - Call Multiple Times + * https://leetcode.com/problems/read-n-characters-given-read4-ii-call-multiple-times/ + * Difficulty: Hard + * + * Given a file and assume that you can only read the file using a given method read4, implement + * a method read to read n characters. Your method read may be called multiple times. + * + * Method read4: + * - The API read4 reads four consecutive characters from file, then writes those characters into + * the buffer array buf4. + * + * The return value is the number of actual characters read. + * + * Note that read4() has its own file pointer, much like FILE *fp in C. + */ + +/** + * @param {function} read4() + * @return {function} + */ +var solution = function(read4) { + let cache = []; + let cacheIndex = 0; + let cacheSize = 0; + + /** + * @param {character[]} buf Destination buffer + * @param {number} n Number of characters to read + * @return {number} The number of actual characters read + */ + return function(buf, n) { + let charsRead = 0; + + while (charsRead < n) { + if (cacheIndex >= cacheSize) { + cache = new Array(4); + cacheSize = read4(cache); + cacheIndex = 0; + if (cacheSize === 0) break; + } + + buf[charsRead++] = cache[cacheIndex++]; + } + + return charsRead; + }; +}; diff --git a/solutions/0159-longest-substring-with-at-most-two-distinct-characters.js b/solutions/0159-longest-substring-with-at-most-two-distinct-characters.js new file mode 100644 index 00000000..8e023114 --- /dev/null +++ b/solutions/0159-longest-substring-with-at-most-two-distinct-characters.js @@ -0,0 +1,34 @@ +/** + * 159. Longest Substring with At Most Two Distinct Characters + * https://leetcode.com/problems/longest-substring-with-at-most-two-distinct-characters/ + * Difficulty: Medium + * + * Given a string s, return the length of the longest substring that contains at most two + * distinct characters. + */ + +/** + * @param {string} s + * @return {number} + */ +var lengthOfLongestSubstringTwoDistinct = function(s) { + const map = new Map(); + let maxLength = 0; + let start = 0; + + for (let end = 0; end < s.length; end++) { + map.set(s[end], (map.get(s[end]) || 0) + 1); + + while (map.size > 2) { + map.set(s[start], map.get(s[start]) - 1); + if (map.get(s[start]) === 0) { + map.delete(s[start]); + } + start++; + } + + maxLength = Math.max(maxLength, end - start + 1); + } + + return maxLength; +}; diff --git a/solutions/0161-one-edit-distance.js b/solutions/0161-one-edit-distance.js new file mode 100644 index 00000000..cb69f9ec --- /dev/null +++ b/solutions/0161-one-edit-distance.js @@ -0,0 +1,36 @@ +/** + * 161. One Edit Distance + * https://leetcode.com/problems/one-edit-distance/ + * Difficulty: Medium + * + * Given two strings s and t, return true if they are both one edit distance apart, otherwise + * return false. + * + * A string s is said to be one distance apart from a string t if you can: + * - Insert exactly one character into s to get t. + * - Delete exactly one character from s to get t. + * - Replace exactly one character of s with a different character to get t. + */ + +/** + * @param {string} s + * @param {string} t + * @return {boolean} + */ +var isOneEditDistance = function(s, t) { + if (s === t) return false; + const sLength = s.length; + const tLength = t.length; + if (Math.abs(sLength - tLength) > 1) return false; + + if (sLength > tLength) return isOneEditDistance(t, s); + + let i = 0; + while (i < sLength && s[i] === t[i]) i++; + + if (sLength === tLength) { + return i < sLength && s.slice(i + 1) === t.slice(i + 1); + } + + return s.slice(i) === t.slice(i + 1); +}; diff --git a/solutions/0163-missing-ranges.js b/solutions/0163-missing-ranges.js new file mode 100644 index 00000000..717b6edb --- /dev/null +++ b/solutions/0163-missing-ranges.js @@ -0,0 +1,35 @@ +/** + * 163. Missing Ranges + * https://leetcode.com/problems/missing-ranges/ + * Difficulty: Easy + * + * You are given an inclusive range [lower, upper] and a sorted unique integer array nums, + * where all elements are within the inclusive range. + * + * A number x is considered missing if x is in the range [lower, upper] and x is not in nums. + * + * Return the shortest sorted list of ranges that exactly covers all the missing numbers. + * That is, no element of nums is included in any of the ranges, and each missing number + * is covered by one of the ranges. + */ + +/** + * @param {number[]} nums + * @param {number} lower + * @param {number} upper + * @return {number[][]} + */ +var findMissingRanges = function(nums, lower, upper) { + const result = []; + let prev = lower - 1; + + for (let i = 0; i <= nums.length; i++) { + const curr = i < nums.length ? nums[i] : upper + 1; + if (curr - prev > 1) { + result.push([prev + 1, curr - 1]); + } + prev = curr; + } + + return result; +}; diff --git a/solutions/0170-two-sum-iii-data-structure-design.js b/solutions/0170-two-sum-iii-data-structure-design.js new file mode 100644 index 00000000..f0cd8777 --- /dev/null +++ b/solutions/0170-two-sum-iii-data-structure-design.js @@ -0,0 +1,42 @@ +/** + * 170. Two Sum III - Data structure design + * https://leetcode.com/problems/two-sum-iii-data-structure-design/ + * Difficulty: Easy + * + * Design a data structure that accepts a stream of integers and checks if it has a pair of + * integers that sum up to a particular value. + * + * Implement the TwoSum class: + * - TwoSum() Initializes the TwoSum object, with an empty array initially. + * - void add(int number) Adds number to the data structure. + * - boolean find(int value) Returns true if there exists any pair of numbers whose sum is equal + * to value, otherwise, it returns false. + */ + +var TwoSum = function() { + this.numCount = new Map(); +}; + +/** + * @param {number} number + * @return {void} + */ +TwoSum.prototype.add = function(number) { + this.numCount.set(number, (this.numCount.get(number) || 0) + 1); +}; + +/** + * @param {number} value + * @return {boolean} + */ +TwoSum.prototype.find = function(value) { + for (const num of this.numCount.keys()) { + const complement = value - num; + if (complement === num) { + if (this.numCount.get(num) > 1) return true; + } else if (this.numCount.has(complement)) { + return true; + } + } + return false; +}; diff --git a/solutions/0186-reverse-words-in-a-string-ii.js b/solutions/0186-reverse-words-in-a-string-ii.js new file mode 100644 index 00000000..ebc713fa --- /dev/null +++ b/solutions/0186-reverse-words-in-a-string-ii.js @@ -0,0 +1,40 @@ +/** + * 186. Reverse Words in a String II + * https://leetcode.com/problems/reverse-words-in-a-string-ii/ + * Difficulty: Medium + * + * Given a character array s, reverse the order of the words. + * + * A word is defined as a sequence of non-space characters. The words in s will be separated + * by a single space. + * + * Your code must solve the problem in-place, i.e. without allocating extra space. + */ + +/** + * @param {character[]} s + * @return {void} Do not return anything, modify s in-place instead. + */ +var reverseWords = function(s) { + let left = 0; + let right = s.length - 1; + + while (left < right) { + [s[left], s[right]] = [s[right], s[left]]; + left++; + right--; + } + + left = 0; + for (let i = 0; i <= s.length; i++) { + if (i === s.length || s[i] === ' ') { + right = i - 1; + while (left < right) { + [s[left], s[right]] = [s[right], s[left]]; + left++; + right--; + } + left = i + 1; + } + } +}; diff --git a/solutions/0243-shortest-word-distance.js b/solutions/0243-shortest-word-distance.js new file mode 100644 index 00000000..d05ac820 --- /dev/null +++ b/solutions/0243-shortest-word-distance.js @@ -0,0 +1,36 @@ +/** + * 243. Shortest Word Distance + * https://leetcode.com/problems/shortest-word-distance/ + * Difficulty: Easy + * + * Given an array of strings wordsDict and two different strings that already exist in the array + * word1 and word2, return the shortest distance between these two words in the list. + */ + +/** + * @param {string[]} wordsDict + * @param {string} word1 + * @param {string} word2 + * @return {number} + */ +var shortestDistance = function(wordsDict, word1, word2) { + let result = Infinity; + let index1 = -1; + let index2 = -1; + + for (let i = 0; i < wordsDict.length; i++) { + if (wordsDict[i] === word1) { + index1 = i; + if (index2 !== -1) { + result = Math.min(result, index1 - index2); + } + } else if (wordsDict[i] === word2) { + index2 = i; + if (index1 !== -1) { + result = Math.min(result, index2 - index1); + } + } + } + + return result; +}; diff --git a/solutions/0244-shortest-word-distance-ii.js b/solutions/0244-shortest-word-distance-ii.js new file mode 100644 index 00000000..3d66d604 --- /dev/null +++ b/solutions/0244-shortest-word-distance-ii.js @@ -0,0 +1,50 @@ +/** + * 244. Shortest Word Distance II + * https://leetcode.com/problems/shortest-word-distance-ii/ + * Difficulty: Medium + * + * Design a data structure that will be initialized with a string array, and then it should + * answer queries of the shortest distance between two different strings from the array. + * + * Implement the WordDistance class: + * - WordDistance(String[] wordsDict) initializes the object with the strings array wordsDict. + * - int shortest(String word1, String word2) returns the shortest distance between word1 and + * word2 in the array wordsDict. + */ + +/** + * @param {string[]} wordsDict + */ +var WordDistance = function(wordsDict) { + this.wordIndices = new Map(); + for (let i = 0; i < wordsDict.length; i++) { + if (!this.wordIndices.has(wordsDict[i])) { + this.wordIndices.set(wordsDict[i], []); + } + this.wordIndices.get(wordsDict[i]).push(i); + } +}; + +/** + * @param {string} word1 + * @param {string} word2 + * @return {number} + */ +WordDistance.prototype.shortest = function(word1, word2) { + const indices1 = this.wordIndices.get(word1); + const indices2 = this.wordIndices.get(word2); + let minDistance = Infinity; + let i = 0; + let j = 0; + + while (i < indices1.length && j < indices2.length) { + minDistance = Math.min(minDistance, Math.abs(indices1[i] - indices2[j])); + if (indices1[i] < indices2[j]) { + i++; + } else { + j++; + } + } + + return minDistance; +}; diff --git a/solutions/0245-shortest-word-distance-iii.js b/solutions/0245-shortest-word-distance-iii.js new file mode 100644 index 00000000..0e1c24f5 --- /dev/null +++ b/solutions/0245-shortest-word-distance-iii.js @@ -0,0 +1,46 @@ +/** + * 245. Shortest Word Distance III + * https://leetcode.com/problems/shortest-word-distance-iii/ + * Difficulty: Medium + * + * Given an array of strings wordsDict and two strings that already exist in the array word1 + * and word2, return the shortest distance between the occurrence of these two words in the list. + * + * Note that word1 and word2 may be the same. It is guaranteed that they represent two individual + * words in the list. + */ + +/** + * @param {string[]} wordsDict + * @param {string} word1 + * @param {string} word2 + * @return {number} + */ +var shortestWordDistance = function(wordsDict, word1, word2) { + let result = Infinity; + let lastWord1Index = -1; + let lastWord2Index = -1; + const areSameWords = word1 === word2; + + for (let index = 0; index < wordsDict.length; index++) { + const currentWord = wordsDict[index]; + + if (currentWord === word1) { + if (areSameWords) { + if (lastWord1Index !== -1) { + result = Math.min(result, index - lastWord1Index); + } + } else if (lastWord2Index !== -1) { + result = Math.min(result, index - lastWord2Index); + } + lastWord1Index = index; + } else if (!areSameWords && currentWord === word2) { + if (lastWord1Index !== -1) { + result = Math.min(result, index - lastWord1Index); + } + lastWord2Index = index; + } + } + + return result; +}; diff --git a/solutions/0246-strobogrammatic-number.js b/solutions/0246-strobogrammatic-number.js new file mode 100644 index 00000000..19c3ab46 --- /dev/null +++ b/solutions/0246-strobogrammatic-number.js @@ -0,0 +1,40 @@ +/** + * 246. Strobogrammatic Number + * https://leetcode.com/problems/strobogrammatic-number/ + * Difficulty: Easy + * + * Given a string num which represents an integer, return true if num is a strobogrammatic number. + * + * A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked at + * upside down). + */ + +/** + * @param {string} num + * @return {boolean} + */ +var isStrobogrammatic = function(num) { + const validPairs = new Map([ + ['0', '0'], + ['1', '1'], + ['6', '9'], + ['8', '8'], + ['9', '6'] + ]); + let left = 0; + let right = num.length - 1; + + while (left <= right) { + const leftDigit = num[left]; + const rightDigit = num[right]; + + if (!validPairs.has(leftDigit) || validPairs.get(leftDigit) !== rightDigit) { + return false; + } + + left++; + right--; + } + + return true; +}; diff --git a/solutions/0247-strobogrammatic-number-ii.js b/solutions/0247-strobogrammatic-number-ii.js new file mode 100644 index 00000000..d8ebf09a --- /dev/null +++ b/solutions/0247-strobogrammatic-number-ii.js @@ -0,0 +1,43 @@ +/** + * 247. Strobogrammatic Number II + * https://leetcode.com/problems/strobogrammatic-number-ii/ + * Difficulty: Medium + * + * Given an integer n, return all the strobogrammatic numbers that are of length n. You may + * return the answer in any order. + * + * A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked + * at upside down). + */ + +/** + * @param {number} n + * @return {string[]} + */ +var findStrobogrammatic = function(n) { + const pairs = [ + ['0', '0'], + ['1', '1'], + ['6', '9'], + ['8', '8'], + ['9', '6'] + ]; + + return generateStrobogrammatic(n, n); + + function generateStrobogrammatic(length, finalLength) { + if (length === 0) return ['']; + if (length === 1) return ['0', '1', '8']; + + const result = []; + const subNumbers = generateStrobogrammatic(length - 2, finalLength); + for (const [left, right] of pairs) { + for (const sub of subNumbers) { + if (length === finalLength && left === '0') continue; + result.push(left + sub + right); + } + } + + return result; + } +}; diff --git a/solutions/0248-strobogrammatic-number-iii.js b/solutions/0248-strobogrammatic-number-iii.js new file mode 100644 index 00000000..d20b8dda --- /dev/null +++ b/solutions/0248-strobogrammatic-number-iii.js @@ -0,0 +1,65 @@ +/** + * 248. Strobogrammatic Number III + * https://leetcode.com/problems/strobogrammatic-number-iii/ + * Difficulty: Hard + * + * Given two strings low and high that represent two integers low and high where low <= high, + * return the number of strobogrammatic numbers in the range [low, high]. + * + * A strobogrammatic number is a number that looks the same when rotated 180 degrees (looked + * at upside down). + */ + +/** + * @param {string} low + * @param {string} high + * @return {number} + */ +var strobogrammaticInRange = function(low, high) { + const pairs = [ + ['0', '0'], + ['1', '1'], + ['6', '9'], + ['8', '8'], + ['9', '6'] + ]; + + function generateStrobogrammatic(length, isOuter) { + if (length === 0) return ['']; + if (length === 1) return ['0', '1', '8']; + + const result = []; + const subNumbers = generateStrobogrammatic(length - 2, false); + + for (const [left, right] of pairs) { + for (const sub of subNumbers) { + if (isOuter && left === '0') continue; + result.push(left + sub + right); + } + } + + return result; + } + + function countInRange(num, lowVal, highVal) { + if (num.length < lowVal.length || num.length > highVal.length) return false; + if (num.length === lowVal.length && num < lowVal) return false; + if (num.length === highVal.length && num > highVal) return false; + return true; + } + + let count = 0; + const lowLength = low.length; + const highLength = high.length; + + for (let len = lowLength; len <= highLength; len++) { + const numbers = generateStrobogrammatic(len, true); + for (const num of numbers) { + if (countInRange(num, low, high)) { + count++; + } + } + } + + return count; +}; diff --git a/solutions/0249-group-shifted-strings.js b/solutions/0249-group-shifted-strings.js new file mode 100644 index 00000000..cbcfaf26 --- /dev/null +++ b/solutions/0249-group-shifted-strings.js @@ -0,0 +1,49 @@ +/** + * 249. Group Shifted Strings + * https://leetcode.com/problems/group-shifted-strings/ + * Difficulty: Medium + * + * Perform the following shift operations on a string: + * - Right shift: Replace every letter with the successive letter of the English alphabet, where + * 'z' is replaced by 'a'. For example, "abc" can be right-shifted to "bcd" or "xyz" can be + * right-shifted to "yza". + * - Left shift: Replace every letter with the preceding letter of the English alphabet, where + * 'a' is replaced by 'z'. For example, "bcd" can be left-shifted to "abc" or "yza" can be + * left-shifted to "xyz". + * + * We can keep shifting the string in both directions to form an endless shifting sequence. + * - For example, shift "abc" to form the sequence: ... <-> "abc" <-> "bcd" <-> ... <-> "xyz" + * <-> "yza" <-> .... <-> "zab" <-> "abc" <-> ... + * + * You are given an array of strings strings, group together all strings[i] that belong to the same + * shifting sequence. You may return the answer in any order. + */ + +/** + * @param {string[]} strings + * @return {string[][]} + */ +var groupStrings = function(strings) { + const groups = new Map(); + + for (const str of strings) { + const key = getShiftKey(str); + if (!groups.has(key)) { + groups.set(key, []); + } + groups.get(key).push(str); + } + + return Array.from(groups.values()); + + function getShiftKey(str) { + if (str.length === 1) return 'single'; + const key = []; + for (let i = 1; i < str.length; i++) { + let diff = str.charCodeAt(i) - str.charCodeAt(i - 1); + if (diff < 0) diff += 26; + key.push(diff); + } + return key.join(','); + } +}; diff --git a/solutions/0250-count-univalue-subtrees.js b/solutions/0250-count-univalue-subtrees.js new file mode 100644 index 00000000..8a8e14ff --- /dev/null +++ b/solutions/0250-count-univalue-subtrees.js @@ -0,0 +1,44 @@ +/** + * 250. Count Univalue Subtrees + * https://leetcode.com/problems/count-univalue-subtrees/ + * Difficulty: Medium + * + * Given the root of a binary tree, return the number of uni-value subtrees. + * + * A uni-value subtree means all nodes of the subtree have the same value. + */ + +/** + * 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} + */ +var countUnivalSubtrees = function(root) { + let count = 0; + traverse(root); + return count; + + function isUnival(node, value) { + if (!node) return true; + + if (node.val !== value) return false; + + return isUnival(node.left, value) && isUnival(node.right, value); + } + + function traverse(node) { + if (!node) return; + + if (isUnival(node, node.val)) count++; + + traverse(node.left); + traverse(node.right); + } +}; diff --git a/solutions/0251-flatten-2d-vector.js b/solutions/0251-flatten-2d-vector.js new file mode 100644 index 00000000..612cc921 --- /dev/null +++ b/solutions/0251-flatten-2d-vector.js @@ -0,0 +1,44 @@ +/** + * 251. Flatten 2D Vector + * https://leetcode.com/problems/flatten-2d-vector/ + * Difficulty: Medium + * + * Design an iterator to flatten a 2D vector. It should support the next and hasNext operations. + * + * Implement the Vector2D class: + * - Vector2D(int[][] vec) initializes the object with the 2D vector vec. + * - next() returns the next element from the 2D vector and moves the pointer one step forward. + * You may assume that all the calls to next are valid. + * - hasNext() returns true if there are still some elements in the vector, and false otherwise. + */ + +/** + * @param {number[][]} vec + */ +var Vector2D = function(vec) { + this.vector = vec; + this.row = 0; + this.col = 0; +}; + +/** + * @return {number} + */ +Vector2D.prototype.next = function() { + while (this.row < this.vector.length && this.col >= this.vector[this.row].length) { + this.row++; + this.col = 0; + } + return this.vector[this.row][this.col++]; +}; + +/** + * @return {boolean} + */ +Vector2D.prototype.hasNext = function() { + while (this.row < this.vector.length && this.col >= this.vector[this.row].length) { + this.row++; + this.col = 0; + } + return this.row < this.vector.length; +}; diff --git a/solutions/0252-meeting-rooms.js b/solutions/0252-meeting-rooms.js new file mode 100644 index 00000000..09045654 --- /dev/null +++ b/solutions/0252-meeting-rooms.js @@ -0,0 +1,24 @@ +/** + * 252. Meeting Rooms + * https://leetcode.com/problems/meeting-rooms/ + * Difficulty: Easy + * + * Given an array of meeting time intervals where intervals[i] = [starti, endi], determine + * if a person could attend all meetings. + */ + +/** + * @param {number[][]} intervals + * @return {boolean} + */ +var canAttendMeetings = function(intervals) { + intervals.sort((a, b) => a[0] - b[0]); + + for (let i = 1; i < intervals.length; i++) { + if (intervals[i][0] < intervals[i - 1][1]) { + return false; + } + } + + return true; +}; diff --git a/solutions/0253-meeting-rooms-ii.js b/solutions/0253-meeting-rooms-ii.js new file mode 100644 index 00000000..2c08e7e3 --- /dev/null +++ b/solutions/0253-meeting-rooms-ii.js @@ -0,0 +1,34 @@ +/** + * 253. Meeting Rooms II + * https://leetcode.com/problems/meeting-rooms-ii/ + * Difficulty: Medium + * + * Given an array of meeting time intervals intervals where intervals[i] = [starti, endi], + * return the minimum number of conference rooms required. + */ + +/** + * @param {number[][]} intervals + * @return {number} + */ +var minMeetingRooms = function(intervals) { + const starts = intervals.map(([start]) => start).sort((a, b) => a - b); + const ends = intervals.map(([, end]) => end).sort((a, b) => a - b); + let rooms = 0; + let startIndex = 0; + let endIndex = 0; + let result = 0; + + while (startIndex < intervals.length) { + if (starts[startIndex] < ends[endIndex]) { + rooms++; + result = Math.max(result, rooms); + startIndex++; + } else { + rooms--; + endIndex++; + } + } + + return result; +}; diff --git a/solutions/0254-factor-combinations.js b/solutions/0254-factor-combinations.js new file mode 100644 index 00000000..ab66abba --- /dev/null +++ b/solutions/0254-factor-combinations.js @@ -0,0 +1,36 @@ +/** + * 254. Factor Combinations + * https://leetcode.com/problems/factor-combinations/ + * Difficulty: Medium + * + * Numbers can be regarded as the product of their factors. + * + * For example, 8 = 2 x 2 x 2 = 2 x 4. + * + * Given an integer n, return all possible combinations of its factors. You may return the + * answer in any order. + * + * Note that the factors should be in the range [2, n - 1]. + */ + +/** + * @param {number} n + * @return {number[][]} + */ +var getFactors = function(n) { + const result = []; + findFactors(n, 2, []); + return result; + + function findFactors(currentNum, start, combination) { + for (let i = start; i * i <= currentNum; i++) { + if (currentNum % i === 0) { + const nextNum = currentNum / i; + if (nextNum >= i && nextNum < currentNum) { + result.push([...combination, i, nextNum]); + findFactors(nextNum, i, [...combination, i]); + } + } + } + } +}; diff --git a/solutions/0255-verify-preorder-sequence-in-binary-search-tree.js b/solutions/0255-verify-preorder-sequence-in-binary-search-tree.js new file mode 100644 index 00000000..2e502211 --- /dev/null +++ b/solutions/0255-verify-preorder-sequence-in-binary-search-tree.js @@ -0,0 +1,27 @@ +/** + * 255. Verify Preorder Sequence in Binary Search Tree + * https://leetcode.com/problems/verify-preorder-sequence-in-binary-search-tree/ + * Difficulty: Medium + * + * Given an array of unique integers preorder, return true if it is the correct preorder + * traversal sequence of a binary search tree. + */ + +/** + * @param {number[]} preorder + * @return {boolean} + */ +var verifyPreorder = function(preorder) { + let minLimit = -Infinity; + const stack = []; + + for (const value of preorder) { + while (stack.length && stack[stack.length - 1] < value) { + minLimit = stack.pop(); + } + if (value <= minLimit) return false; + stack.push(value); + } + + return true; +}; diff --git a/solutions/0256-paint-house.js b/solutions/0256-paint-house.js new file mode 100644 index 00000000..c37cc991 --- /dev/null +++ b/solutions/0256-paint-house.js @@ -0,0 +1,34 @@ +/** + * 256. Paint House + * https://leetcode.com/problems/paint-house/ + * Difficulty: Medium + * + * There is a row of n houses, where each house can be painted one of three colors: red, blue, + * or green. The cost of painting each house with a certain color is different. You have to + * paint all the houses such that no two adjacent houses have the same color. + * + * The cost of painting each house with a certain color is represented by an n x 3 cost matrix + * costs. + * - For example, costs[0][0] is the cost of painting house 0 with the color red; costs[1][2] + * is the cost of painting house 1 with color green, and so on... + * + * Return the minimum cost to paint all houses. + */ + +/** + * @param {number[][]} costs + * @return {number} + */ +var minCost = function(costs) { + let prev = [...costs[0]]; + + for (let i = 1; i < costs.length; i++) { + prev = [ + costs[i][0] + Math.min(prev[1], prev[2]), + costs[i][1] + Math.min(prev[0], prev[2]), + costs[i][2] + Math.min(prev[0], prev[1]) + ]; + } + + return Math.min(...prev); +}; diff --git a/solutions/0259-3sum-smaller.js b/solutions/0259-3sum-smaller.js new file mode 100644 index 00000000..89e0d4b5 --- /dev/null +++ b/solutions/0259-3sum-smaller.js @@ -0,0 +1,36 @@ +/** + * 259. 3Sum Smaller + * https://leetcode.com/problems/3sum-smaller/ + * Difficulty: Medium + * + * Given an array of n integers nums and an integer target, find the number of index triplets + * i, j, k with 0 <= i < j < k < n that satisfy the condition nums[i] + nums[j] + nums[k] < target. + */ + +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +var threeSumSmaller = function(nums, target) { + nums.sort((a, b) => a - b); + const n = nums.length; + let result = 0; + + for (let i = 0; i < n - 2; i++) { + let left = i + 1; + let right = n - 1; + + while (left < right) { + const sum = nums[i] + nums[left] + nums[right]; + if (sum < target) { + result += right - left; + left++; + } else { + right--; + } + } + } + + return result; +}; diff --git a/solutions/0261-graph-valid-tree.js b/solutions/0261-graph-valid-tree.js new file mode 100644 index 00000000..483b2345 --- /dev/null +++ b/solutions/0261-graph-valid-tree.js @@ -0,0 +1,45 @@ +/** + * 261. Graph Valid Tree + * https://leetcode.com/problems/graph-valid-tree/ + * Difficulty: Medium + * + * You have a graph of n nodes labeled from 0 to n - 1. You are given an integer n and a list of + * edges where edges[i] = [ai, bi] indicates that there is an undirected edge between nodes ai + * and bi in the graph. + * + * Return true if the edges of the given graph make up a valid tree, and false otherwise. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @return {boolean} + */ +var validTree = function(n, edges) { + const parent = new Array(n).fill(-1); + + for (const [u, v] of edges) { + if (!union(u, v)) return false; + } + + let components = 0; + for (let i = 0; i < n; i++) { + if (parent[i] === -1) components++; + if (components > 1) return false; + } + + return edges.length === n - 1; + + function find(x) { + if (parent[x] === -1) return x; + return parent[x] = find(parent[x]); + } + + function union(x, y) { + const rootX = find(x); + const rootY = find(y); + if (rootX === rootY) return false; + parent[rootX] = rootY; + return true; + } +}; diff --git a/solutions/0265-paint-house-ii.js b/solutions/0265-paint-house-ii.js new file mode 100644 index 00000000..6a883f10 --- /dev/null +++ b/solutions/0265-paint-house-ii.js @@ -0,0 +1,51 @@ +/** + * 265. Paint House II + * https://leetcode.com/problems/paint-house-ii/ + * Difficulty: Hard + * + * There are a row of n houses, each house can be painted with one of the k colors. The cost of + * painting each house with a certain color is different. You have to paint all the houses such + * that no two adjacent houses have the same color. + * + * The cost of painting each house with a certain color is represented by an n x k cost matrix + * costs. + * - For example, costs[0][0] is the cost of painting house 0 with color 0; costs[1][2] is the + * cost of painting house 1 with color 2, and so on... + * + * Return the minimum cost to paint all houses. + */ + +/** + * @param {number[][]} costs + * @return {number} + */ +var minCostII = function(costs) { + const n = costs.length; + const k = costs[0].length; + let prev = [...costs[0]]; + + for (let i = 1; i < n; i++) { + const curr = new Array(k); + let min1 = Infinity; + let min2 = Infinity; + let index = -1; + + for (let j = 0; j < k; j++) { + if (prev[j] < min1) { + min2 = min1; + min1 = prev[j]; + index = j; + } else if (prev[j] < min2) { + min2 = prev[j]; + } + } + + for (let j = 0; j < k; j++) { + curr[j] = costs[i][j] + (j === index ? min2 : min1); + } + + prev = curr; + } + + return Math.min(...prev); +}; diff --git a/solutions/0266-palindrome-permutation.js b/solutions/0266-palindrome-permutation.js new file mode 100644 index 00000000..9f710d28 --- /dev/null +++ b/solutions/0266-palindrome-permutation.js @@ -0,0 +1,28 @@ +/** + * 266. Palindrome Permutation + * https://leetcode.com/problems/palindrome-permutation/ + * Difficulty: Easy + * + * Given a string s, return true if a permutation of the string could form a palindrome + * and false otherwise. + */ + +/** + * @param {string} s + * @return {boolean} + */ +var canPermutePalindrome = function(s) { + const map = new Map(); + + for (const char of s) { + map.set(char, (map.get(char) || 0) + 1); + } + + let oddCount = 0; + for (const count of map.values()) { + if (count % 2 !== 0) oddCount++; + if (oddCount > 1) return false; + } + + return true; +}; diff --git a/solutions/0267-palindrome-permutation-ii.js b/solutions/0267-palindrome-permutation-ii.js new file mode 100644 index 00000000..6f1127c0 --- /dev/null +++ b/solutions/0267-palindrome-permutation-ii.js @@ -0,0 +1,62 @@ +/** + * 267. Palindrome Permutation II + * https://leetcode.com/problems/palindrome-permutation-ii/ + * Difficulty: Medium + * + * Given a string s, return all the palindromic permutations (without duplicates) of it. + * + * You may return the answer in any order. If s has no palindromic permutation, return an + * empty list. + */ + +/** + * @param {string} s + * @return {string[]} + */ +var generatePalindromes = function(s) { + const map = new Map(); + for (const char of s) { + map.set(char, (map.get(char) || 0) + 1); + } + + let oddChar = ''; + const half = []; + let oddCount = 0; + + for (const [char, count] of map) { + if (count % 2) { + oddCount++; + oddChar = char; + } + for (let i = 0; i < Math.floor(count / 2); i++) { + half.push(char); + } + } + + if (oddCount > 1) return []; + + const result = new Set(); + + half.sort(); + permute(half, [], new Array(half.length).fill(false)); + return Array.from(result); + + function permute(chars, current, used) { + if (current.length === chars.length) { + const palindrome = current.join('') + oddChar + current.reverse().join(''); + result.add(palindrome); + current.reverse(); + return; + } + + for (let i = 0; i < chars.length; i++) { + if (!used[i] && (i === 0 || chars[i] !== chars[i - 1] || used[i - 1])) { + used[i] = true; + current.push(chars[i]); + permute(chars, current, used); + current.pop(); + used[i] = false; + } + } + } +}; diff --git a/solutions/0269-alien-dictionary.js b/solutions/0269-alien-dictionary.js new file mode 100644 index 00000000..00e19ca3 --- /dev/null +++ b/solutions/0269-alien-dictionary.js @@ -0,0 +1,73 @@ +/** + * 269. Alien Dictionary + * https://leetcode.com/problems/alien-dictionary/ + * Difficulty: Hard + * + * There is a new alien language that uses the English alphabet. However, the order of the + * letters is unknown to you. + * + * You are given a list of strings words from the alien language's dictionary. Now it is + * claimed that the strings in words are sorted lexicographically by the rules of this new + * language. + * + * If this claim is incorrect, and the given arrangement of string in words cannot correspond + * to any order of letters, return "". + * + * Otherwise, return a string of the unique letters in the new alien language sorted in + * lexicographically increasing order by the new language's rules. If there are multiple + * solutions, return any of them. + */ + +/** + * @param {string[]} words + * @return {string} + */ +var alienOrder = function(words) { + const graph = new Map(); + const inDegree = new Map(); + + for (const word of words) { + for (const char of word) { + if (!graph.has(char)) { + graph.set(char, new Set()); + inDegree.set(char, 0); + } + } + } + + for (let i = 1; i < words.length; i++) { + const prev = words[i - 1]; + const curr = words[i]; + const minLen = Math.min(prev.length, curr.length); + + if (prev.length > curr.length && prev.startsWith(curr)) return ''; + + for (let j = 0; j < minLen; j++) { + if (prev[j] !== curr[j]) { + if (!graph.get(prev[j]).has(curr[j])) { + graph.get(prev[j]).add(curr[j]); + inDegree.set(curr[j], inDegree.get(curr[j]) + 1); + } + break; + } + } + } + + const queue = []; + for (const [char, degree] of inDegree) { + if (degree === 0) queue.push(char); + } + + let result = ''; + while (queue.length) { + const char = queue.shift(); + result += char; + + for (const next of graph.get(char)) { + inDegree.set(next, inDegree.get(next) - 1); + if (inDegree.get(next) === 0) queue.push(next); + } + } + + return result.length === graph.size ? result : ''; +}; diff --git a/solutions/0270-closest-binary-search-tree-value.js b/solutions/0270-closest-binary-search-tree-value.js new file mode 100644 index 00000000..b0e78a8e --- /dev/null +++ b/solutions/0270-closest-binary-search-tree-value.js @@ -0,0 +1,36 @@ +/** + * 270. Closest Binary Search Tree Value + * https://leetcode.com/problems/closest-binary-search-tree-value/ + * Difficulty: Easy + * + * Given the root of a binary search tree and a target value, return the value in the BST that + * is closest to the target. If there are multiple answers, print the smallest. + */ + +/** + * 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 {number} + */ +var closestValue = function(root, target) { + let closest = root.val; + + while (root) { + closest = Math.abs(root.val - target) < Math.abs(closest - target) + || (Math.abs(root.val - target) === Math.abs(closest - target) && root.val < closest) + ? root.val + : closest; + + root = target < root.val ? root.left : root.right; + } + + return closest; +}; diff --git a/solutions/0271-encode-and-decode-strings.js b/solutions/0271-encode-and-decode-strings.js new file mode 100644 index 00000000..e32296b3 --- /dev/null +++ b/solutions/0271-encode-and-decode-strings.js @@ -0,0 +1,58 @@ +/** + * 271. Encode and Decode Strings + * https://leetcode.com/problems/encode-and-decode-strings/ + * Difficulty: Medium + * + * Design an algorithm to encode a list of strings to a string. The encoded string is then sent over + * the network and is decoded back to the original list of strings. + * + * Machine 1 (sender) has the function: + * string encode(vector strs) { + * // ... your code + * return encoded_string; + * } + * Machine 2 (receiver) has the function: + * vector decode(string s) { + * //... your code + * return strs; + * } + * So Machine 1 does: + * string encoded_string = encode(strs); + * and Machine 2 does: + * vector strs2 = decode(encoded_string); + * strs2 in Machine 2 should be the same as strs in Machine 1. + * + * Implement the encode and decode methods. + * + * You are not allowed to solve the problem using any serialize methods (such as eval). + */ + +/** + * Encodes a list of strings to a single string. + * + * @param {string[]} strs + * @return {string} + */ +var encode = function(strs) { + return strs.map(str => `${str.length}:${str}`).join(''); +}; + +/** + * Decodes a single string to a list of strings. + * + * @param {string} s + * @return {string[]} + */ +var decode = function(s) { + const result = []; + let i = 0; + + while (i < s.length) { + const colon = s.indexOf(':', i); + const len = parseInt(s.slice(i, colon)); + result.push(s.slice(colon + 1, colon + 1 + len)); + i = colon + 1 + len; + } + + return result; +}; diff --git a/solutions/0272-closest-binary-search-tree-value-ii.js b/solutions/0272-closest-binary-search-tree-value-ii.js new file mode 100644 index 00000000..b3a6b27b --- /dev/null +++ b/solutions/0272-closest-binary-search-tree-value-ii.js @@ -0,0 +1,41 @@ +/** + * 272. Closest Binary Search Tree Value II + * https://leetcode.com/problems/closest-binary-search-tree-value-ii/ + * Difficulty: Hard + * + * Given the root of a binary search tree, a target value, and an integer k, return the k values + * in the BST that are closest to the target. You may return the answer in any order. + * + * You are guaranteed to have only one unique set of k values in the BST that are closest to the + * target. + */ + +/** + * 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 + * @param {number} k + * @return {number[]} + */ +var closestKValues = function(root, target, k) { + const values = []; + + inOrder(root); + + values.sort((a, b) => Math.abs(a - target) - Math.abs(b - target)); + return values.slice(0, k); + + function inOrder(node) { + if (!node) return; + inOrder(node.left); + values.push(node.val); + inOrder(node.right); + } +}; diff --git a/solutions/0276-paint-fence.js b/solutions/0276-paint-fence.js new file mode 100644 index 00000000..c19bb08a --- /dev/null +++ b/solutions/0276-paint-fence.js @@ -0,0 +1,33 @@ +/** + * 276. Paint Fence + * https://leetcode.com/problems/paint-fence/ + * Difficulty: Medium + * + * You are painting a fence of n posts with k different colors. You must paint the posts following + * these rules: + * - Every post must be painted exactly one color. + * - There cannot be three or more consecutive posts with the same color. + * + * Given the two integers n and k, return the number of ways you can paint the fence. + */ + +/** + * @param {number} n + * @param {number} k + * @return {number} + */ +var numWays = function(n, k) { + if (n === 1) return k; + if (n === 2) return k * k; + + let same = k; + let diff = k * (k - 1); + + for (let i = 3; i <= n; i++) { + const prevSame = same; + same = diff; + diff = (prevSame + diff) * (k - 1); + } + + return same + diff; +}; diff --git a/solutions/0277-find-the-celebrity.js b/solutions/0277-find-the-celebrity.js new file mode 100644 index 00000000..ad6f71a4 --- /dev/null +++ b/solutions/0277-find-the-celebrity.js @@ -0,0 +1,53 @@ +/** + * 277. Find the Celebrity + * https://leetcode.com/problems/find-the-celebrity/ + * Difficulty: Medium + * + * Suppose you are at a party with n people labeled from 0 to n - 1 and among them, there may + * exist one celebrity. The definition of a celebrity is that all the other n - 1 people know + * the celebrity, but the celebrity does not know any of them. + * + * Now you want to find out who the celebrity is or verify that there is not one. You are only + * allowed to ask questions like: "Hi, A. Do you know B?" to get information about whether A + * knows B. You need to find out the celebrity (or verify there is not one) by asking as few + * questions as possible (in the asymptotic sense). + * + * You are given an integer n and a helper function bool knows(a, b) that tells you whether a + * knows b. Implement a function int findCelebrity(n). There will be exactly one celebrity if + * they are at the party. + * + * Return the celebrity's label if there is a celebrity at the party. If there is no celebrity, + * return -1. + * + * Note that the n x n 2D array graph given as input is not directly available to you, and + * instead only accessible through the helper function knows. graph[i][j] == 1 represents + * person i knows person j, wherease graph[i][j] == 0 represents person j does not know person i. + */ + +/** + * @param {function} knows() + * @return {function} + */ +var solution = function(knows) { + /** + * @param {integer} n Total people + * @return {integer} The celebrity + */ + return function(n) { + 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; + } + } + + return candidate; + }; +}; diff --git a/solutions/0280-wiggle-sort.js b/solutions/0280-wiggle-sort.js new file mode 100644 index 00000000..2f2aee91 --- /dev/null +++ b/solutions/0280-wiggle-sort.js @@ -0,0 +1,25 @@ +/** + * 280. Wiggle Sort + * https://leetcode.com/problems/wiggle-sort/ + * Difficulty: Medium + * + * Given an integer array nums, reorder it such that nums[0] <= nums[1] >= nums[2] <= nums[3].... + * + * You may assume the input array always has a valid answer. + */ + +/** + * @param {number[]} nums + * @return {void} Do not return anything, modify nums in-place instead. + */ +var wiggleSort = function(nums) { + const n = nums.length; + + for (let i = 0; i < n - 1; i++) { + if (i % 2 === 0 && nums[i] > nums[i + 1]) { + [nums[i], nums[i + 1]] = [nums[i + 1], nums[i]]; + } else if (i % 2 === 1 && nums[i] < nums[i + 1]) { + [nums[i], nums[i + 1]] = [nums[i + 1], nums[i]]; + } + } +}; diff --git a/solutions/0281-zigzag-iterator.js b/solutions/0281-zigzag-iterator.js new file mode 100644 index 00000000..ce71c1d5 --- /dev/null +++ b/solutions/0281-zigzag-iterator.js @@ -0,0 +1,49 @@ +/** + * 281. Zigzag Iterator + * https://leetcode.com/problems/zigzag-iterator/ + * Difficulty: Medium + * + * Given two vectors of integers v1 and v2, implement an iterator to return their elements + * alternately. + * + * Implement the ZigzagIterator class: + * - ZigzagIterator(List v1, List v2) initializes the object with the two vectors + * v1 and v2. + * - boolean hasNext() returns true if the iterator still has elements, and false otherwise. + * - int next() returns the current element of the iterator and moves the iterator to the + * next element. + */ + +/** + * @constructor + * @param {Integer[]} v1 + * @param {Integer[]} v2 + */ +var ZigzagIterator = function ZigzagIterator(v1, v2) { + this.queue = []; + if (v1.length) this.queue.push([v1, 0]); + if (v2.length) this.queue.push([v2, 0]); +}; + +/** + * @this ZigzagIterator + * @returns {boolean} + */ +ZigzagIterator.prototype.hasNext = function hasNext() { + return this.queue.length > 0; +}; + +/** + * @this ZigzagIterator + * @returns {integer} + */ +ZigzagIterator.prototype.next = function next() { + const [vector, index] = this.queue.shift(); + const value = vector[index]; + + if (index + 1 < vector.length) { + this.queue.push([vector, index + 1]); + } + + return value; +}; diff --git a/solutions/0285-inorder-successor-in-bst.js b/solutions/0285-inorder-successor-in-bst.js new file mode 100644 index 00000000..d589f0e4 --- /dev/null +++ b/solutions/0285-inorder-successor-in-bst.js @@ -0,0 +1,35 @@ +/** + * 285. Inorder Successor in BST + * https://leetcode.com/problems/inorder-successor-in-bst/ + * Difficulty: Medium + * + * Given the root of a binary search tree and a node p in it, return the in-order successor of + * that node in the BST. If the given node has no in-order successor in the tree, return null. + * + * The successor of a node p is the node with the smallest key greater than p.val. + */ + +/** + * 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} + */ +var inorderSuccessor = function(root, p) { + let successor = null; + while (root) { + if (p.val < root.val) { + successor = root; + root = root.left; + } else { + root = root.right; + } + } + return successor; +}; diff --git a/solutions/0286-walls-and-gates.js b/solutions/0286-walls-and-gates.js new file mode 100644 index 00000000..13440941 --- /dev/null +++ b/solutions/0286-walls-and-gates.js @@ -0,0 +1,49 @@ +/** + * 286. Walls and Gates + * https://leetcode.com/problems/walls-and-gates/ + * Difficulty: Medium + * + * You are given an m x n grid rooms 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. + */ + +/** + * @param {number[][]} rooms + * @return {void} Do not return anything, modify rooms in-place instead. + */ +var wallsAndGates = function(rooms) { + const rows = rooms.length; + const cols = rooms[0].length; + const queue = []; + const INF = 2147483647; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (rooms[i][j] === 0) { + queue.push([i, j]); + } + } + } + + const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]; + while (queue.length) { + const [row, col] = queue.shift(); + + for (const [dr, dc] of directions) { + const newRow = row + dr; + const newCol = col + dc; + + if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols + && rooms[newRow][newCol] === INF) { + rooms[newRow][newCol] = rooms[row][col] + 1; + queue.push([newRow, newCol]); + } + } + } +}; diff --git a/solutions/0288-unique-word-abbreviation.js b/solutions/0288-unique-word-abbreviation.js new file mode 100644 index 00000000..886f3b29 --- /dev/null +++ b/solutions/0288-unique-word-abbreviation.js @@ -0,0 +1,57 @@ +/** + * 288. Unique Word Abbreviation + * https://leetcode.com/problems/unique-word-abbreviation/ + * Difficulty: Medium + * + * The abbreviation of a word is a concatenation of its first letter, the number of characters + * between the first and last letter, and its last letter. If a word has only two characters, + * then it is an abbreviation of itself. + * + * For example: + * - dog --> d1g because there is one letter between the first letter 'd' and the last letter 'g'. + * - internationalization --> i18n because there are 18 letters between the first letter 'i' and + * the last letter 'n'. + * - it --> it because any word with only two characters is an abbreviation of itself. + * + * Implement the ValidWordAbbr class: + * - ValidWordAbbr(String[] dictionary) Initializes the object with a dictionary of words. + * - boolean isUnique(string word) Returns true if either of the following conditions are met + * (otherwise returns false): + * - There is no word in dictionary whose abbreviation is equal to word's abbreviation. + * - For any word in dictionary whose abbreviation is equal to word's abbreviation, that word + * and word are the same. + */ + +/** + * @param {string[]} dictionary + */ +var ValidWordAbbr = function(dictionary) { + this.abbrMap = new Map(); + + for (const word of dictionary) { + const abbr = this.getAbbreviation(word); + if (!this.abbrMap.has(abbr)) { + this.abbrMap.set(abbr, new Set()); + } + this.abbrMap.get(abbr).add(word); + } +}; + +/** + * @param {string} word + * @return {string} + */ +ValidWordAbbr.prototype.getAbbreviation = function(word) { + if (word.length <= 2) return word; + return word[0] + (word.length - 2) + word[word.length - 1]; +}; + +/** + * @param {string} word + * @return {boolean} + */ +ValidWordAbbr.prototype.isUnique = function(word) { + const abbr = this.getAbbreviation(word); + const words = this.abbrMap.get(abbr); + return !words || (words.size === 1 && words.has(word)); +}; diff --git a/solutions/0291-word-pattern-ii.js b/solutions/0291-word-pattern-ii.js new file mode 100644 index 00000000..83e7eca5 --- /dev/null +++ b/solutions/0291-word-pattern-ii.js @@ -0,0 +1,51 @@ +/** + * 291. Word Pattern II + * https://leetcode.com/problems/word-pattern-ii/ + * Difficulty: Medium + * + * Given a pattern and a string s, return true if s matches the pattern. + * + * A string s matches a pattern if there is some bijective mapping of single characters to + * non-empty strings such that if each character in pattern is replaced by the string it + * maps to, then the resulting string is s. A bijective mapping means that no two characters + * map to the same string, and no character maps to two different strings. + */ + +/** + * @param {string} pattern + * @param {string} s + * @return {boolean} + */ +var wordPatternMatch = function(pattern, s) { + const charToWord = new Map(); + const usedWords = new Set(); + + return backtrack(0, 0); + + function backtrack(patIndex, strIndex) { + if (patIndex === pattern.length && strIndex === s.length) return true; + if (patIndex >= pattern.length || strIndex >= s.length) return false; + + const char = pattern[patIndex]; + if (charToWord.has(char)) { + const word = charToWord.get(char); + if (!s.startsWith(word, strIndex)) return false; + return backtrack(patIndex + 1, strIndex + word.length); + } + + for (let i = strIndex + 1; i <= s.length; i++) { + const word = s.slice(strIndex, i); + if (usedWords.has(word)) continue; + + charToWord.set(char, word); + usedWords.add(word); + + if (backtrack(patIndex + 1, strIndex + word.length)) return true; + + charToWord.delete(char); + usedWords.delete(word); + } + + return false; + } +}; diff --git a/solutions/0293-flip-game.js b/solutions/0293-flip-game.js new file mode 100644 index 00000000..8fe0485a --- /dev/null +++ b/solutions/0293-flip-game.js @@ -0,0 +1,32 @@ +/** + * 293. Flip Game + * https://leetcode.com/problems/flip-game/ + * Difficulty: Easy + * + * You are playing a Flip Game with your friend. + * + * You are given a string currentState that contains only '+' and '-'. You and your friend take + * turns to flip two consecutive "++" into "--". The game ends when a person can no longer make + * a move, and therefore the other person will be the winner. + * + * Return all possible states of the string currentState after one valid move. You may return + * the answer in any order. If there is no valid move, return an empty list []. + */ + +/** + * @param {string} currentState + * @return {string[]} + */ +var generatePossibleNextMoves = function(currentState) { + const results = []; + + for (let i = 0; i < currentState.length - 1; i++) { + if (currentState[i] === '+' && currentState[i + 1] === '+') { + results.push( + currentState.slice(0, i) + '--' + currentState.slice(i + 2) + ); + } + } + + return results; +}; diff --git a/solutions/0294-flip-game-ii.js b/solutions/0294-flip-game-ii.js new file mode 100644 index 00000000..d4baf073 --- /dev/null +++ b/solutions/0294-flip-game-ii.js @@ -0,0 +1,40 @@ +/** + * 294. Flip Game II + * https://leetcode.com/problems/flip-game-ii/ + * Difficulty: Medium + * + * You are playing a Flip Game with your friend. + * + * You are given a string currentState that contains only '+' and '-'. You and your friend take + * turns to flip two consecutive "++" into "--". The game ends when a person can no longer make + * a move, and therefore the other person will be the winner. + * + * Return true if the starting player can guarantee a win, and false otherwise. + */ + +/** + * @param {string} currentState + * @return {boolean} + */ +var canWin = function(currentState) { + const map = new Map(); + + return canWinFrom(currentState); + + function canWinFrom(state) { + if (map.has(state)) return map.get(state); + + for (let i = 0; i < state.length - 1; i++) { + if (state[i] === '+' && state[i + 1] === '+') { + const nextState = state.slice(0, i) + '--' + state.slice(i + 2); + if (!canWinFrom(nextState)) { + map.set(state, true); + return true; + } + } + } + + map.set(state, false); + return false; + } +}; diff --git a/solutions/0296-best-meeting-point.js b/solutions/0296-best-meeting-point.js new file mode 100644 index 00000000..d31e660b --- /dev/null +++ b/solutions/0296-best-meeting-point.js @@ -0,0 +1,42 @@ +/** + * 296. Best Meeting Point + * https://leetcode.com/problems/best-meeting-point/ + * Difficulty: Hard + * + * Given an m x n binary grid grid where each 1 marks the home of one friend, return the minimal + * total travel distance. + * + * The total travel distance is the sum of the distances between the houses of the friends and + * the meeting point. + * + * The distance is calculated using Manhattan Distance, where + * distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var minTotalDistance = function(grid) { + const rows = []; + const cols = []; + + for (let i = 0; i < grid.length; i++) { + for (let j = 0; j < grid[0].length; j++) { + if (grid[i][j] === 1) { + rows.push(i); + cols.push(j); + } + } + } + + rows.sort((a, b) => a - b); + cols.sort((a, b) => a - b); + + let result = 0; + for (let i = 0; i < rows.length; i++) { + result += Math.abs(rows[i] - rows[Math.floor(rows.length / 2)]); + result += Math.abs(cols[i] - cols[Math.floor(cols.length / 2)]); + } + return result; +}; diff --git a/solutions/0298-binary-tree-longest-consecutive-sequence.js b/solutions/0298-binary-tree-longest-consecutive-sequence.js new file mode 100644 index 00000000..642f88bc --- /dev/null +++ b/solutions/0298-binary-tree-longest-consecutive-sequence.js @@ -0,0 +1,40 @@ +/** + * 298. Binary Tree Longest Consecutive Sequence + * https://leetcode.com/problems/binary-tree-longest-consecutive-sequence/ + * Difficulty: Medium + * + * Given the root of a binary tree, return the length of the longest consecutive sequence path. + * + * A consecutive sequence path is a path where the values increase by one along the path. + * + * Note that the path can start at any node in the tree, and you cannot go from a node to its + * parent in the path. + */ + +/** + * 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} + */ +var longestConsecutive = function(root) { + let result = 0; + traverse(root, root.val - 1, 0); + return result; + + function traverse(node, parentValue, length) { + if (!node) return; + + const currentLength = parentValue + 1 === node.val ? length + 1 : 1; + result = Math.max(result, currentLength); + + traverse(node.left, node.val, currentLength); + traverse(node.right, node.val, currentLength); + } +}; diff --git a/solutions/0302-smallest-rectangle-enclosing-black-pixels.js b/solutions/0302-smallest-rectangle-enclosing-black-pixels.js new file mode 100644 index 00000000..76de7a6e --- /dev/null +++ b/solutions/0302-smallest-rectangle-enclosing-black-pixels.js @@ -0,0 +1,63 @@ +/** + * 302. Smallest Rectangle Enclosing Black Pixels + * https://leetcode.com/problems/smallest-rectangle-enclosing-black-pixels/ + * Difficulty: Hard + * + * You are given an m x n binary matrix image where 0 represents a white pixel and 1 represents + * a black pixel. + * + * The black pixels are connected (i.e., there is only one black region). Pixels are connected + * horizontally and vertically. + * + * Given two integers x and y that represents the location of one of the black pixels, return + * the area of the smallest (axis-aligned) rectangle that encloses all black pixels. + * + * You must write an algorithm with less than O(mn) runtime complexity + */ + +/** + * @param {character[][]} image + * @param {number} x + * @param {number} y + * @return {number} + */ +var minArea = function(image, x, y) { + const rows = image.length; + const cols = image[0].length; + const top = binarySearch(0, x, true, true); + const bottom = binarySearch(x, rows - 1, true, false); + const left = binarySearch(0, y, false, true); + const right = binarySearch(y, cols - 1, false, false); + + return (bottom - top + 1) * (right - left + 1); + + function binarySearch(start, end, isRow, isMin) { + let result = isMin ? end : start; + while (start <= end) { + const mid = Math.floor((start + end) / 2); + let hasBlack = false; + for (let i = 0; i < (isRow ? cols : rows); i++) { + const pixel = isRow ? image[mid][i] : image[i][mid]; + if (pixel === '1') { + hasBlack = true; + break; + } + } + if (hasBlack) { + result = mid; + if (isMin) { + end = mid - 1; + } else { + start = mid + 1; + } + } else { + if (isMin) { + start = mid + 1; + } else { + end = mid - 1; + } + } + } + return result; + } +}; diff --git a/solutions/0305-number-of-islands-ii.js b/solutions/0305-number-of-islands-ii.js new file mode 100644 index 00000000..e5f5cd28 --- /dev/null +++ b/solutions/0305-number-of-islands-ii.js @@ -0,0 +1,86 @@ +/** + * 305. Number of Islands II + * https://leetcode.com/problems/number-of-islands-ii/ + * Difficulty: Hard + * + * You are given an empty 2D binary grid grid of size m x n. The grid represents a map where 0's + * represent water and 1's represent land. Initially, all the cells of grid are water cells + * (i.e., all the cells are 0's). + * + * We may perform an add land operation which turns the water at position into a land. You are + * given an array positions where positions[i] = [ri, ci] is the position (ri, ci) at which we + * should operate the ith operation. + * + * Return an array of integers answer where answer[i] is the number of islands after turning + * the cell (ri, ci) into a land. + * + * An island is surrounded by water and is formed by connecting adjacent lands horizontally + * or vertically. You may assume all four edges of the grid are all surrounded by water. + */ + +/** + * @param {number} m + * @param {number} n + * @param {number[][]} positions + * @return {number[]} + */ +var numIslands2 = function(m, n, positions) { + const parent = new Map(); + const rank = new Map(); + const result = []; + const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]; + let islandCount = 0; + + for (const [row, col] of positions) { + const current = row * n + col; + if (parent.has(current)) { + result.push(islandCount); + continue; + } + islandCount++; + parent.set(current, current); + rank.set(current, 0); + + for (const [dr, dc] of directions) { + const newRow = row + dr; + const newCol = col + dc; + if (newRow >= 0 && newRow < m && newCol >= 0 && newCol < n) { + const neighbor = newRow * n + newCol; + if (parent.has(neighbor)) { + union(current, neighbor); + } + } + } + result.push(islandCount); + } + + return result; + + function find(node) { + if (!parent.has(node)) { + parent.set(node, node); + rank.set(node, 0); + } + if (parent.get(node) !== node) { + parent.set(node, find(parent.get(node))); + } + return parent.get(node); + } + + function union(node1, node2) { + const root1 = find(node1); + const root2 = find(node2); + if (root1 === root2) return; + const rank1 = rank.get(root1); + const rank2 = rank.get(root2); + if (rank1 < rank2) { + parent.set(root1, root2); + } else if (rank1 > rank2) { + parent.set(root2, root1); + } else { + parent.set(root2, root1); + rank.set(root1, rank1 + 1); + } + islandCount--; + } +}; diff --git a/solutions/0308-range-sum-query-2d-mutable.js b/solutions/0308-range-sum-query-2d-mutable.js new file mode 100644 index 00000000..670caca6 --- /dev/null +++ b/solutions/0308-range-sum-query-2d-mutable.js @@ -0,0 +1,94 @@ +/** + * 308. Range Sum Query 2D - Mutable + * https://leetcode.com/problems/range-sum-query-2d-mutable/ + * Difficulty: Medium + * + * Given a 2D matrix matrix, handle multiple queries of the following types: + * 1. Update the value of a cell in matrix. + * 2. Calculate the sum of the elements of matrix inside the rectangle defined by its upper left + * corner (row1, col1) and lower right corner (row2, col2). + * + * Implement the NumMatrix class: + * - NumMatrix(int[][] matrix) Initializes the object with the integer matrix matrix. + * - void update(int row, int col, int val) Updates the value of matrix[row][col] to be val. + * - int sumRegion(int row1, int col1, int row2, int col2) Returns the sum of the elements of + * matrix inside the rectangle defined by its upper left corner (row1, col1) and lower right + * corner (row2, col2). + */ + +/** + * @param {number[][]} matrix + */ +var NumMatrix = function(matrix) { + this.rows = matrix.length; + this.cols = matrix[0].length; + this.matrix = matrix; + this.tree = new Array(this.rows + 1).fill().map(() => new Array(this.cols + 1).fill(0)); + + for (let i = 0; i < this.rows; i++) { + for (let j = 0; j < this.cols; j++) { + this.updateTree(i + 1, j + 1, matrix[i][j]); + } + } +}; + +/** + * @param {number} row + * @param {number} col + * @param {number} val + * @return {void} + */ +NumMatrix.prototype.updateTree = function(row, col, val) { + while (row <= this.rows) { + let c = col; + while (c <= this.cols) { + this.tree[row][c] += val; + c += c & (-c); + } + row += row & (-row); + } +}; + +/** + * @param {number} row + * @param {number} col + * @return {number} + */ +NumMatrix.prototype.getSum = function(row, col) { + let sum = 0; + while (row > 0) { + let c = col; + while (c > 0) { + sum += this.tree[row][c]; + c -= c & (-c); + } + row -= row & (-row); + } + return sum; +}; + +/** + * @param {number} row + * @param {number} col + * @param {number} val + * @return {void} + */ +NumMatrix.prototype.update = function(row, col, val) { + const diff = val - this.matrix[row][col]; + this.matrix[row][col] = val; + this.updateTree(row + 1, col + 1, diff); +}; + +/** + * @param {number} row1 + * @param {number} col1 + * @param {number} row2 + * @param {number} col2 + * @return {number} + */ +NumMatrix.prototype.sumRegion = function(row1, col1, row2, col2) { + return this.getSum(row2 + 1, col2 + 1) + - this.getSum(row2 + 1, col1) + - this.getSum(row1, col2 + 1) + + this.getSum(row1, col1); +}; diff --git a/solutions/0311-sparse-matrix-multiplication.js b/solutions/0311-sparse-matrix-multiplication.js new file mode 100644 index 00000000..7a69dca2 --- /dev/null +++ b/solutions/0311-sparse-matrix-multiplication.js @@ -0,0 +1,34 @@ +/** + * 311. Sparse Matrix Multiplication + * https://leetcode.com/problems/sparse-matrix-multiplication/ + * Difficulty: Medium + * + * Given two sparse matrices mat1 of size m x k and mat2 of size k x n, return the result of + * mat1 x mat2. You may assume that multiplication is always possible. + */ + +/** + * @param {number[][]} mat1 + * @param {number[][]} mat2 + * @return {number[][]} + */ +var multiply = function(mat1, mat2) { + const m = mat1.length; + const k = mat1[0].length; + const n = mat2[0].length; + const result = new Array(m).fill().map(() => new Array(n).fill(0)); + + for (let i = 0; i < m; i++) { + for (let j = 0; j < k; j++) { + if (mat1[i][j] !== 0) { + for (let l = 0; l < n; l++) { + if (mat2[j][l] !== 0) { + result[i][l] += mat1[i][j] * mat2[j][l]; + } + } + } + } + } + + return result; +}; diff --git a/solutions/0314-binary-tree-vertical-order-traversal.js b/solutions/0314-binary-tree-vertical-order-traversal.js new file mode 100644 index 00000000..e93b1b43 --- /dev/null +++ b/solutions/0314-binary-tree-vertical-order-traversal.js @@ -0,0 +1,53 @@ +/** + * 314. Binary Tree Vertical Order Traversal + * https://leetcode.com/problems/binary-tree-vertical-order-traversal/ + * Difficulty: Medium + * + * Given the root of a binary tree, return the vertical order traversal of its nodes' values. + * (i.e., 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. + */ + +/** + * 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[][]} + */ +var verticalOrder = function(root) { + if (!root) return []; + + const columns = new Map(); + const queue = [[root, 0]]; + let minCol = 0; + let maxCol = 0; + + while (queue.length) { + const [node, col] = queue.shift(); + if (!columns.has(col)) columns.set(col, []); + columns.get(col).push(node.val); + + if (node.left) { + queue.push([node.left, col - 1]); + minCol = Math.min(minCol, col - 1); + } + if (node.right) { + queue.push([node.right, col + 1]); + maxCol = Math.max(maxCol, col + 1); + } + } + + const result = []; + for (let col = minCol; col <= maxCol; col++) { + if (columns.has(col)) result.push(columns.get(col)); + } + + return result; +}; diff --git a/solutions/0317-shortest-distance-from-all-buildings.js b/solutions/0317-shortest-distance-from-all-buildings.js new file mode 100644 index 00000000..f699b1b0 --- /dev/null +++ b/solutions/0317-shortest-distance-from-all-buildings.js @@ -0,0 +1,80 @@ +/** + * 317. Shortest Distance from All Buildings + * https://leetcode.com/problems/shortest-distance-from-all-buildings/ + * Difficulty: Hard + * + * You are given an m x n grid grid of values 0, 1, or 2, where: + * - each 0 marks an empty land that you can pass by freely, + * - each 1 marks a building that you cannot pass through, and + * - each 2 marks an obstacle that you cannot pass through. + * + * You want to build a house on an empty land that reaches all buildings in the shortest total + * travel distance. You can only move up, down, left, and right. + * + * Return the shortest travel distance for such a house. If it is not possible to build such + * a house according to the above rules, return -1. + * + * The total travel distance is the sum of the distances between the houses of the friends and + * the meeting point. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var shortestDistance = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const distances = new Array(rows).fill().map(() => new Array(cols).fill(0)); + const reachCounts = new Array(rows).fill().map(() => new Array(cols).fill(0)); + let buildingCount = 0; + + function bfs(startRow, startCol) { + const queue = [[startRow, startCol]]; + const visited = new Array(rows).fill().map(() => new Array(cols).fill(false)); + visited[startRow][startCol] = true; + let distance = 0; + + const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]; + + while (queue.length) { + const size = queue.length; + distance++; + for (let i = 0; i < size; i++) { + const [row, col] = queue.shift(); + for (const [dr, dc] of directions) { + const newRow = row + dr; + const newCol = col + dc; + if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols + && !visited[newRow][newCol] && grid[newRow][newCol] !== 1 + && grid[newRow][newCol] !== 2) { + queue.push([newRow, newCol]); + visited[newRow][newCol] = true; + distances[newRow][newCol] += distance; + reachCounts[newRow][newCol]++; + } + } + } + } + } + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (grid[i][j] === 1) { + buildingCount++; + bfs(i, j); + } + } + } + + let minDistance = Infinity; + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (grid[i][j] === 0 && reachCounts[i][j] === buildingCount) { + minDistance = Math.min(minDistance, distances[i][j]); + } + } + } + + return minDistance === Infinity ? -1 : minDistance; +}; diff --git a/solutions/0320-generalized-abbreviation.js b/solutions/0320-generalized-abbreviation.js new file mode 100644 index 00000000..96ab102d --- /dev/null +++ b/solutions/0320-generalized-abbreviation.js @@ -0,0 +1,41 @@ +/** + * 320. Generalized Abbreviation + * https://leetcode.com/problems/generalized-abbreviation/ + * Difficulty: Medium + * + * A word's generalized abbreviation can be constructed by taking any number of non-overlapping + * and non-adjacent substrings and replacing them with their respective lengths. + * - For example, "abcde" can be abbreviated into: + * - "a3e" ("bcd" turned into "3") + * - "1bcd1" ("a" and "e" both turned into "1") + * - "5" ("abcde" turned into "5") + * - "abcde" (no substrings replaced) + * - However, these abbreviations are invalid: + * - "23" ("ab" turned into "2" and "cde" turned into "3") is invalid as the substrings + * chosen are adjacent. + * - "22de" ("ab" turned into "2" and "bc" turned into "2") is invalid as the substring + * chosen overlap. + * + * Given a string word, return a list of all the possible generalized abbreviations of word. + * Return the answer in any order. + */ + +/** + * @param {string} word + * @return {string[]} + */ +var generateAbbreviations = function(word) { + const result = []; + backtrack('', 0, 0); + return result; + + function backtrack(current, pos, count) { + if (pos === word.length) { + result.push(current + (count > 0 ? count : '')); + return; + } + + backtrack(current + (count > 0 ? count : '') + word[pos], pos + 1, 0); + backtrack(current, pos + 1, count + 1); + } +}; diff --git a/solutions/0323-number-of-connected-components-in-an-undirected-graph.js b/solutions/0323-number-of-connected-components-in-an-undirected-graph.js new file mode 100644 index 00000000..ba679b5f --- /dev/null +++ b/solutions/0323-number-of-connected-components-in-an-undirected-graph.js @@ -0,0 +1,42 @@ +/** + * 323. Number of Connected Components in an Undirected Graph + * https://leetcode.com/problems/number-of-connected-components-in-an-undirected-graph/ + * Difficulty: Medium + * + * You have a graph of n nodes. You are given an integer n and an array edges where + * edges[i] = [ai, bi] indicates that there is an edge between ai and bi in the graph. + * + * Return the number of connected components in the graph. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @return {number} + */ +var countComponents = function(n, edges) { + const parent = new Array(n).fill().map((_, i) => i); + let components = n; + + for (const [node1, node2] of edges) { + union(node1, node2); + } + + return components; + + function find(node) { + if (parent[node] !== node) { + parent[node] = find(parent[node]); + } + return parent[node]; + } + + function union(node1, node2) { + const root1 = find(node1); + const root2 = find(node2); + if (root1 !== root2) { + parent[root1] = root2; + components--; + } + } +}; diff --git a/solutions/0325-maximum-size-subarray-sum-equals-k.js b/solutions/0325-maximum-size-subarray-sum-equals-k.js new file mode 100644 index 00000000..697c3a73 --- /dev/null +++ b/solutions/0325-maximum-size-subarray-sum-equals-k.js @@ -0,0 +1,31 @@ +/** + * 325. Maximum Size Subarray Sum Equals k + * https://leetcode.com/problems/maximum-size-subarray-sum-equals-k/ + * Difficulty: Medium + * + * Given an integer array nums and an integer k, return the maximum length of a subarray that + * sums to k. If there is not one, return 0 instead. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var maxSubArrayLen = function(nums, k) { + const sumIndex = new Map([[0, -1]]); + let currentSum = 0; + let result = 0; + + for (let i = 0; i < nums.length; i++) { + currentSum += nums[i]; + if (sumIndex.has(currentSum - k)) { + result = Math.max(result, i - sumIndex.get(currentSum - k)); + } + if (!sumIndex.has(currentSum)) { + sumIndex.set(currentSum, i); + } + } + + return result; +}; diff --git a/solutions/0333-largest-bst-subtree.js b/solutions/0333-largest-bst-subtree.js new file mode 100644 index 00000000..30c83e84 --- /dev/null +++ b/solutions/0333-largest-bst-subtree.js @@ -0,0 +1,52 @@ +/** + * 333. Largest BST Subtree + * https://leetcode.com/problems/largest-bst-subtree/ + * Difficulty: Medium + * + * Given the root of a binary tree, find the largest subtree, which is also a Binary Search + * Tree (BST), where the largest means subtree has the largest number of nodes. + * + * A Binary Search Tree (BST) is a tree in which all the nodes follow the below-mentioned + * properties: + * - The left subtree values are less than the value of their parent (root) node's value. + * - The right subtree values are greater than the value of their parent (root) node's value. + * + * Note: A subtree must include all of its descendants. + */ + +/** + * 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} + */ +var largestBSTSubtree = function(root) { + let maxSize = 0; + traverse(root); + return maxSize; + + function traverse(node) { + if (!node) return { isBST: true, size: 0, min: Infinity, max: -Infinity }; + + const left = traverse(node.left); + const right = traverse(node.right); + if (left.isBST && right.isBST && node.val > left.max && node.val < right.min) { + const size = left.size + right.size + 1; + maxSize = Math.max(maxSize, size); + return { + isBST: true, + size, + min: Math.min(left.min, node.val), + max: Math.max(right.max, node.val) + }; + } + + return { isBST: false, size: 0, min: 0, max: 0 }; + } +}; diff --git a/solutions/0339-nested-list-weight-sum.js b/solutions/0339-nested-list-weight-sum.js new file mode 100644 index 00000000..2ca1b16b --- /dev/null +++ b/solutions/0339-nested-list-weight-sum.js @@ -0,0 +1,33 @@ +/** + * 339. Nested List Weight Sum + * https://leetcode.com/problems/nested-list-weight-sum/ + * Difficulty: Medium + * + * You are given a nested list of integers nestedList. Each element is either an integer or + * a list whose elements may also be integers or other lists. + * + * The depth of an integer is the number of lists that it is inside of. For example, the nested + * list [1,[2,2],[[3],2],1] has each integer's value set to its depth. + * + * Return the sum of each integer in nestedList multiplied by its depth. + */ + +/** + * @param {NestedInteger[]} nestedList + * @return {number} + */ +var depthSum = function(nestedList) { + return calculateDepth(nestedList, 1); + + function calculateDepth(list, depth) { + let total = 0; + for (const element of list) { + if (element.isInteger()) { + total += element.getInteger() * depth; + } else { + total += calculateDepth(element.getList(), depth + 1); + } + } + return total; + } +}; diff --git a/solutions/0340-longest-substring-with-at-most-k-distinct-characters.js b/solutions/0340-longest-substring-with-at-most-k-distinct-characters.js new file mode 100644 index 00000000..dfd6a5c3 --- /dev/null +++ b/solutions/0340-longest-substring-with-at-most-k-distinct-characters.js @@ -0,0 +1,35 @@ +/** + * 340. Longest Substring with At Most K Distinct Characters + * https://leetcode.com/problems/longest-substring-with-at-most-k-distinct-characters/ + * Difficulty: Medium + * + * Given a string s and an integer k, return the length of the longest substring of s that + * contains at most k distinct characters. + */ + +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +var lengthOfLongestSubstringKDistinct = function(s, k) { + const map = new Map(); + let result = 0; + let left = 0; + + for (let right = 0; right < s.length; right++) { + map.set(s[right], (map.get(s[right]) || 0) + 1); + + while (map.size > k) { + map.set(s[left], map.get(s[left]) - 1); + if (map.get(s[left]) === 0) { + map.delete(s[left]); + } + left++; + } + + result = Math.max(result, right - left + 1); + } + + return result; +}; diff --git a/solutions/0346-moving-average-from-data-stream.js b/solutions/0346-moving-average-from-data-stream.js new file mode 100644 index 00000000..6c2981a8 --- /dev/null +++ b/solutions/0346-moving-average-from-data-stream.js @@ -0,0 +1,36 @@ +/** + * 346. Moving Average from Data Stream + * https://leetcode.com/problems/moving-average-from-data-stream/ + * Difficulty: Easy + * + * Given a stream of integers and a window size, calculate the moving average of all integers + * in the sliding window. + * + * Implement the MovingAverage class: + * - MovingAverage(int size) Initializes the object with the size of the window size. + * - double next(int val) Returns the moving average of the last size values of the stream. + */ + +/** + * @param {number} size + */ +var MovingAverage = function(size) { + this.window = []; + this.maxSize = size; + this.sum = 0; +}; + +/** + * @param {number} val + * @return {number} + */ +MovingAverage.prototype.next = function(val) { + this.window.push(val); + this.sum += val; + + if (this.window.length > this.maxSize) { + this.sum -= this.window.shift(); + } + + return this.sum / this.window.length; +}; diff --git a/solutions/0348-design-tic-tac-toe.js b/solutions/0348-design-tic-tac-toe.js new file mode 100644 index 00000000..9b517913 --- /dev/null +++ b/solutions/0348-design-tic-tac-toe.js @@ -0,0 +1,59 @@ +/** + * 348. Design Tic-Tac-Toe + * https://leetcode.com/problems/design-tic-tac-toe/ + * Difficulty: Medium + * + * Assume the following rules are for the tic-tac-toe game on an n x n board between two players: + * 1. A move is guaranteed to be valid and is placed on an empty block. + * 2. Once a winning condition is reached, no more moves are allowed. + * 3. A player who succeeds in placing n of their marks in a horizontal, vertical, or diagonal + * row wins the game. + * + * Implement the TicTacToe class: + * - TicTacToe(int n) Initializes the object the size of the board n. + * - int move(int row, int col, int player) Indicates that the player with id player plays at the + * cell (row, col) of the board. The move is guaranteed to be a valid move, and the two players + * alternate in making moves. Return + * - 0 if there is no winner after the move, + * - 1 if player 1 is the winner after the move, or + * - 2 if player 2 is the winner after the move. + */ + +/** + * @param {number} n + */ +var TicTacToe = function(n) { + this.size = n; + this.rows = new Array(n).fill(0); + this.cols = new Array(n).fill(0); + this.diagonal = 0; + this.antiDiagonal = 0; +}; + +/** + * @param {number} row + * @param {number} col + * @param {number} player + * @return {number} + */ +TicTacToe.prototype.move = function(row, col, player) { + const value = player === 1 ? 1 : -1; + + this.rows[row] += value; + this.cols[col] += value; + + if (row === col) { + this.diagonal += value; + } + + if (row + col === this.size - 1) { + this.antiDiagonal += value; + } + + if (Math.abs(this.rows[row]) === this.size || Math.abs(this.cols[col]) === this.size + || Math.abs(this.diagonal) === this.size || Math.abs(this.antiDiagonal) === this.size) { + return player; + } + + return 0; +}; diff --git a/solutions/0351-android-unlock-patterns.js b/solutions/0351-android-unlock-patterns.js new file mode 100644 index 00000000..ef71439d --- /dev/null +++ b/solutions/0351-android-unlock-patterns.js @@ -0,0 +1,68 @@ +/** + * 351. Android Unlock Patterns + * https://leetcode.com/problems/android-unlock-patterns/ + * Difficulty: Medium + * + * Android devices have a special lock screen with a 3 x 3 grid of dots. Users can set an + * "unlock pattern" by connecting the dots in a specific sequence, forming a series of joined + * line segments where each segment's endpoints are two consecutive dots in the sequence. + * A sequence of k dots is a valid unlock pattern if both of the following are true: + * - All the dots in the sequence are distinct. + * - If the line segment connecting two consecutive dots in the sequence passes through the + * center of any other dot, the other dot must have previously appeared in the sequence. + * No jumps through the center non-selected dots are allowed. + * - For example, connecting dots 2 and 9 without dots 5 or 6 appearing beforehand is valid + * because the line from dot 2 to dot 9 does not pass through the center of either dot 5 or 6. + * - However, connecting dots 1 and 3 without dot 2 appearing beforehand is invalid because + * the line from dot 1 to dot 3 passes through the center of dot 2. + * + * Here are some example valid and invalid unlock patterns: + */ + +/** + * @param {number} m + * @param {number} n + * @return {number} + */ +var numberOfPatterns = function(m, n) { + const jumps = new Array(10).fill().map(() => new Array(10).fill(0)); + jumps[1][3] = jumps[3][1] = 2; + jumps[1][7] = jumps[7][1] = 4; + jumps[3][9] = jumps[9][3] = 6; + jumps[7][9] = jumps[9][7] = 8; + jumps[1][9] = jumps[9][1] = jumps[2][8] = jumps[8][2] = jumps[3][7] + = jumps[7][3] = jumps[4][6] = jumps[6][4] = 5; + + function backtrack(current, visited, length) { + if (length > n) return 0; + let count = length >= m ? 1 : 0; + if (length === n) return count; + + for (let next = 1; next <= 9; next++) { + if (!visited.has(next)) { + const jump = jumps[current][next]; + if (jump === 0 || visited.has(jump)) { + visited.add(next); + count += backtrack(next, visited, length + 1); + visited.delete(next); + } + } + } + return count; + } + + let total = 0; + const visited = new Set(); + visited.add(1); + total += backtrack(1, visited, 1) * 4; + visited.delete(1); + + visited.add(2); + total += backtrack(2, visited, 1) * 4; + visited.delete(2); + + visited.add(5); + total += backtrack(5, visited, 1); + + return total; +}; diff --git a/solutions/0353-design-snake-game.js b/solutions/0353-design-snake-game.js new file mode 100644 index 00000000..4f615906 --- /dev/null +++ b/solutions/0353-design-snake-game.js @@ -0,0 +1,82 @@ +/** + * 353. Design Snake Game + * https://leetcode.com/problems/design-snake-game/ + * Difficulty: Medium + * + * Design a Snake game that is played on a device with screen size height x width. Play the + * game online if you are not familiar with the game. + * + * The snake is initially positioned at the top left corner (0, 0) with a length of 1 unit. + * + * You are given an array food where food[i] = (ri, ci) is the row and column position of a + * piece of food that the snake can eat. When a snake eats a piece of food, its length and + * the game's score both increase by 1. + * + * Each piece of food appears one by one on the screen, meaning the second piece of food will + * not appear until the snake eats the first piece of food. + * + * When a piece of food appears on the screen, it is guaranteed that it will not appear on a + * block occupied by the snake. + * + * The game is over if the snake goes out of bounds (hits a wall) or if its head occupies a + * space that its body occupies after moving (i.e. a snake of length 4 cannot run into itself). + * + * Implement the SnakeGame class: + * - SnakeGame(int width, int height, int[][] food) Initializes the object with a screen of size + * height x width and the positions of the food. + * - int move(String direction) Returns the score of the game after applying one direction move + * by the snake. If the game is over, return -1. + */ + +/** + * @param {number} width + * @param {number} height + * @param {number[][]} food + */ +var SnakeGame = function(width, height, food) { + this.width = width; + this.height = height; + this.food = food; + this.foodIndex = 0; + this.score = 0; + this.snake = [[0, 0]]; + this.bodySet = new Set(['0,0']); +}; + +/** + * @param {string} direction + * @return {number} + */ +SnakeGame.prototype.move = function(direction) { + const head = [...this.snake[0]]; + + if (direction === 'U') head[0]--; + else if (direction === 'D') head[0]++; + else if (direction === 'L') head[1]--; + else if (direction === 'R') head[1]++; + + if (head[0] < 0 || head[0] >= this.height || head[1] < 0 || head[1] >= this.width) { + return -1; + } + + const tail = this.snake.pop(); + this.bodySet.delete(`${tail[0]},${tail[1]}`); + + const headKey = `${head[0]},${head[1]}`; + if (this.bodySet.has(headKey)) { + return -1; + } + + this.snake.unshift(head); + this.bodySet.add(headKey); + + if (this.foodIndex < this.food.length && head[0] === this.food[this.foodIndex][0] + && head[1] === this.food[this.foodIndex][1]) { + this.snake.push(tail); + this.bodySet.add(`${tail[0]},${tail[1]}`); + this.foodIndex++; + this.score++; + } + + return this.score; +}; diff --git a/solutions/0356-line-reflection.js b/solutions/0356-line-reflection.js new file mode 100644 index 00000000..76722159 --- /dev/null +++ b/solutions/0356-line-reflection.js @@ -0,0 +1,37 @@ +/** + * 356. Line Reflection + * https://leetcode.com/problems/line-reflection/ + * Difficulty: Medium + * + * Given n points on a 2D plane, find if there is such a line parallel to the y-axis that reflects + * the given points symmetrically. + * + * In other words, answer whether or not if there exists a line that after reflecting all points + * over the given line, the original points' set is the same as the reflected ones. + * + * Note that there can be repeated points. + */ + +/** + * @param {number[][]} points + * @return {boolean} + */ +var isReflected = function(points) { + const pointSet = new Set(points.map(([x, y]) => `${x},${y}`)); + let minX = Infinity; + let maxX = -Infinity; + + for (const [x] of points) { + minX = Math.min(minX, x); + maxX = Math.max(maxX, x); + } + + const sum = minX + maxX; + for (const [x, y] of points) { + if (!pointSet.has(`${sum - x},${y}`)) { + return false; + } + } + + return true; +}; diff --git a/solutions/0358-rearrange-string-k-distance-apart.js b/solutions/0358-rearrange-string-k-distance-apart.js new file mode 100644 index 00000000..9d498ae4 --- /dev/null +++ b/solutions/0358-rearrange-string-k-distance-apart.js @@ -0,0 +1,65 @@ +/** + * 358. Rearrange String k Distance Apart + * https://leetcode.com/problems/rearrange-string-k-distance-apart/ + * Difficulty: Hard + * + * Given a string s and an integer k, rearrange s such that the same characters are at least + * distance k from each other. If it is not possible to rearrange the string, return an empty + * string "". + */ + +/** + * @param {string} s + * @param {number} k + * @return {string} + */ +var rearrangeString = function(s, k) { + if (k <= 1) return s; + + const charCount = new Array(26).fill(0); + for (const char of s) { + charCount[char.charCodeAt(0) - 97]++; + } + + const maxHeap = []; + for (let i = 0; i < 26; i++) { + if (charCount[i] > 0) { + maxHeap.push([charCount[i], String.fromCharCode(i + 97)]); + } + } + maxHeap.sort((a, b) => b[0] - a[0]); + + const maxFreq = maxHeap[0] ? maxHeap[0][0] : 0; + if (maxFreq > Math.ceil(s.length / k)) return ''; + + const result = new Array(s.length).fill(''); + let index = 0; + + while (maxHeap.length) { + const temp = []; + for (let i = 0; i < k && maxHeap.length; i++) { + const [count, char] = maxHeap.shift(); + while (index < s.length && result[index] !== '') { + index++; + } + if (index >= s.length) index = 0; + result[index] = char; + index++; + if (count > 1) temp.push([count - 1, char]); + } + + temp.sort((a, b) => b[0] - a[0]); + maxHeap.push(...temp); + maxHeap.sort((a, b) => b[0] - a[0]); + } + + for (let i = 0; i <= s.length - k; i++) { + const seen = new Set(); + for (let j = i; j < i + k; j++) { + if (seen.has(result[j])) return ''; + seen.add(result[j]); + } + } + + return result.join(''); +}; diff --git a/solutions/0359-logger-rate-limiter.js b/solutions/0359-logger-rate-limiter.js new file mode 100644 index 00000000..9dacbd78 --- /dev/null +++ b/solutions/0359-logger-rate-limiter.js @@ -0,0 +1,35 @@ +/** + * 359. Logger Rate Limiter + * https://leetcode.com/problems/logger-rate-limiter/ + * Difficulty: Easy + * + * Design a logger system that receives a stream of messages along with their timestamps. + * Each unique message should only be printed at most every 10 seconds (i.e. a message + * printed at timestamp t will prevent other identical messages from being printed until + * timestamp t + 10). + * + * All messages will come in chronological order. Several messages may arrive at the same timestamp. + * + * Implement the Logger class: + * - Logger() Initializes the logger object. + * - bool shouldPrintMessage(int timestamp, string message) Returns true if the message should + * be printed in the given timestamp, otherwise returns false. + */ + +var Logger = function() { + this.messageTimestamps = new Map(); +}; + +/** + * @param {number} timestamp + * @param {string} message + * @return {boolean} + */ +Logger.prototype.shouldPrintMessage = function(timestamp, message) { + const nextAllowed = this.messageTimestamps.get(message) || 0; + if (timestamp >= nextAllowed) { + this.messageTimestamps.set(message, timestamp + 10); + return true; + } + return false; +}; diff --git a/solutions/0360-sort-transformed-array.js b/solutions/0360-sort-transformed-array.js new file mode 100644 index 00000000..30badca3 --- /dev/null +++ b/solutions/0360-sort-transformed-array.js @@ -0,0 +1,52 @@ +/** + * 360. Sort Transformed Array + * https://leetcode.com/problems/sort-transformed-array/ + * Difficulty: Medium + * + * Given a sorted integer array nums and three integers a, b and c, apply a quadratic function + * of the form f(x) = ax2 + bx + c to each element nums[i] in the array, and return the array + * in a sorted order. + */ + +/** + * @param {number[]} nums + * @param {number} a + * @param {number} b + * @param {number} c + * @return {number[]} + */ +var sortTransformedArray = function(nums, a, b, c) { + const result = new Array(nums.length); + let left = 0; + let right = nums.length - 1; + let index = a >= 0 ? nums.length - 1 : 0; + + while (left <= right) { + const leftVal = transform(nums[left]); + const rightVal = transform(nums[right]); + + if (a >= 0) { + if (leftVal > rightVal) { + result[index--] = leftVal; + left++; + } else { + result[index--] = rightVal; + right--; + } + } else { + if (leftVal < rightVal) { + result[index++] = leftVal; + left++; + } else { + result[index++] = rightVal; + right--; + } + } + } + + return result; + + function transform(x) { + return a * x * x + b * x + c; + } +}; diff --git a/solutions/0361-bomb-enemy.js b/solutions/0361-bomb-enemy.js new file mode 100644 index 00000000..ffa279e8 --- /dev/null +++ b/solutions/0361-bomb-enemy.js @@ -0,0 +1,46 @@ +/** + * 361. Bomb Enemy + * https://leetcode.com/problems/bomb-enemy/ + * Difficulty: Medium + * + * Given an m x n matrix grid where each cell is either a wall 'W', an enemy 'E' or empty '0', + * return the maximum enemies you can kill using one bomb. You can only place the bomb in an + * empty cell. + * + * The bomb kills all the enemies in the same row and column from the planted point until it + * hits the wall since it is too strong to be destroyed. + */ + +/** + * @param {character[][]} grid + * @return {number} + */ +var maxKilledEnemies = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const colHits = new Array(cols).fill(0); + let rowHits = 0; + let result = 0; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (j === 0 || grid[i][j-1] === 'W') { + rowHits = 0; + for (let k = j; k < cols && grid[i][k] !== 'W'; k++) { + if (grid[i][k] === 'E') rowHits++; + } + } + if (i === 0 || grid[i-1][j] === 'W') { + colHits[j] = 0; + for (let k = i; k < rows && grid[k][j] !== 'W'; k++) { + if (grid[k][j] === 'E') colHits[j]++; + } + } + if (grid[i][j] === '0') { + result = Math.max(result, rowHits + colHits[j]); + } + } + } + + return result; +}; diff --git a/solutions/0362-design-hit-counter.js b/solutions/0362-design-hit-counter.js new file mode 100644 index 00000000..ebe1aeef --- /dev/null +++ b/solutions/0362-design-hit-counter.js @@ -0,0 +1,43 @@ +/** + * 362. Design Hit Counter + * https://leetcode.com/problems/design-hit-counter/ + * Difficulty: Medium + * + * Design a hit counter which counts the number of hits received in the past 5 minutes + * (i.e., the past 300 seconds). + * + * Your system should accept a timestamp parameter (in seconds granularity), and you may + * assume that calls are being made to the system in chronological order (i.e., timestamp + * is monotonically increasing). Several hits may arrive roughly at the same time. + * + * Implement the HitCounter class: + * - HitCounter() Initializes the object of the hit counter system. + * - void hit(int timestamp) Records a hit that happened at timestamp (in seconds). Several + * hits may happen at the same timestamp. + * - int getHits(int timestamp) Returns the number of hits in the past 5 minutes from timestamp + * (i.e., the past 300 seconds). + */ + +var HitCounter = function() { + this.hits = []; +}; + +/** + * @param {number} timestamp + * @return {void} + */ +HitCounter.prototype.hit = function(timestamp) { + this.hits.push(timestamp); +}; + +/** + * @param {number} timestamp + * @return {number} + */ +HitCounter.prototype.getHits = function(timestamp) { + const threshold = timestamp - 300; + while (this.hits.length && this.hits[0] <= threshold) { + this.hits.shift(); + } + return this.hits.length; +}; diff --git a/solutions/0364-nested-list-weight-sum-ii.js b/solutions/0364-nested-list-weight-sum-ii.js new file mode 100644 index 00000000..dea3ecd0 --- /dev/null +++ b/solutions/0364-nested-list-weight-sum-ii.js @@ -0,0 +1,47 @@ +/** + * 364. Nested List Weight Sum II + * https://leetcode.com/problems/nested-list-weight-sum-ii/ + * Difficulty: Medium + * + * You are given a nested list of integers nestedList. Each element is either an integer or + * a list whose elements may also be integers or other lists. + * + * The depth of an integer is the number of lists that it is inside of. For example, the + * nested list [1,[2,2],[[3],2],1] has each integer's value set to its depth. Let maxDepth + * be the maximum depth of any integer. + * + * The weight of an integer is maxDepth - (the depth of the integer) + 1. + * + * Return the sum of each integer in nestedList multiplied by its weight. + */ + +/** + * @param {NestedInteger[]} nestedList + * @return {number} + */ +var depthSumInverse = function(nestedList) { + const maxDepth = findMaxDepth(nestedList, 1); + return calculateSum(nestedList, 1, maxDepth); + + function findMaxDepth(list, depth) { + let maxDepth = depth; + for (const element of list) { + if (!element.isInteger()) { + maxDepth = Math.max(maxDepth, findMaxDepth(element.getList(), depth + 1)); + } + } + return maxDepth; + } + + function calculateSum(list, depth, maxDepth) { + let total = 0; + for (const element of list) { + if (element.isInteger()) { + total += element.getInteger() * (maxDepth - depth + 1); + } else { + total += calculateSum(element.getList(), depth + 1, maxDepth); + } + } + return total; + } +}; diff --git a/solutions/0366-find-leaves-of-binary-tree.js b/solutions/0366-find-leaves-of-binary-tree.js new file mode 100644 index 00000000..45159fed --- /dev/null +++ b/solutions/0366-find-leaves-of-binary-tree.js @@ -0,0 +1,43 @@ +/** + * 366. Find Leaves of Binary Tree + * https://leetcode.com/problems/find-leaves-of-binary-tree/ + * Difficulty: Medium + * + * Given the root of a binary tree, collect a tree's nodes as if you were doing this: + * - Collect all the leaf nodes. + * - Remove all the leaf nodes. + * - Repeat until the tree is empty. + */ + +/** + * 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[][]} + */ +var findLeaves = function(root) { + const levels = []; + getHeight(root); + return levels; + + function getHeight(node) { + if (!node) return -1; + + const leftHeight = getHeight(node.left); + const rightHeight = getHeight(node.right); + const height = Math.max(leftHeight, rightHeight) + 1; + + if (levels.length <= height) { + levels.push([]); + } + levels[height].push(node.val); + + return height; + } +}; diff --git a/solutions/0369-plus-one-linked-list.js b/solutions/0369-plus-one-linked-list.js new file mode 100644 index 00000000..0dbb048d --- /dev/null +++ b/solutions/0369-plus-one-linked-list.js @@ -0,0 +1,40 @@ +/** + * 369. Plus One Linked List + * https://leetcode.com/problems/plus-one-linked-list/ + * Difficulty: Medium + * + * Given a non-negative integer represented as a linked list of digits, plus one to the integer. + * + * The digits are stored such that the most significant digit is at the head of the list. + */ + +/** + * 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} + */ +var plusOne = function(head) { + const list = new ListNode(0, head); + let notNine = list; + + while (head) { + if (head.val !== 9) notNine = head; + head = head.next; + } + + notNine.val++; + notNine = notNine.next; + + while (notNine) { + notNine.val = 0; + notNine = notNine.next; + } + + return list.val === 0 ? list.next : list; +}; diff --git a/solutions/0370-range-addition.js b/solutions/0370-range-addition.js new file mode 100644 index 00000000..b10a3991 --- /dev/null +++ b/solutions/0370-range-addition.js @@ -0,0 +1,34 @@ +/** + * 370. Range Addition + * https://leetcode.com/problems/range-addition/ + * Difficulty: Medium + * + * You are given an integer length and an array updates where + * updates[i] = [startIdxi, endIdxi, inci]. + * + * You have an array arr of length length with all zeros, and you have some operation + * to apply on arr. In the ith operation, you should increment all the elements + * arr[startIdxi], arr[startIdxi + 1], ..., arr[endIdxi] by inci. + * + * Return arr after applying all the updates. + */ + +/** + * @param {number} length + * @param {number[][]} updates + * @return {number[]} + */ +var getModifiedArray = function(length, updates) { + const result = new Array(length).fill(0); + + for (const [start, end, inc] of updates) { + result[start] += inc; + if (end + 1 < length) result[end + 1] -= inc; + } + + for (let i = 1; i < length; i++) { + result[i] += result[i - 1]; + } + + return result; +}; diff --git a/solutions/0373-find-k-pairs-with-smallest-sums.js b/solutions/0373-find-k-pairs-with-smallest-sums.js index 59ab2d80..bc0ca7d5 100644 --- a/solutions/0373-find-k-pairs-with-smallest-sums.js +++ b/solutions/0373-find-k-pairs-with-smallest-sums.js @@ -18,20 +18,26 @@ * @return {number[][]} */ var kSmallestPairs = function(nums1, nums2, k) { - const heap = new MinPriorityQueue({ compare: (a, b) => a[0] - b[0] }); + const minHeap = new PriorityQueue((a, b) => a[0] - b[0]); const result = []; + const visited = new Set(); - for (let i = 0; i < nums1.length; i++) { - heap.enqueue([nums1[i] + nums2[0], 0]); - } + minHeap.enqueue([nums1[0] + nums2[0], 0, 0]); + visited.add('0,0'); + + for (let count = 0; count < k && !minHeap.isEmpty(); count++) { + const [currentSum, index1, index2] = minHeap.dequeue(); + result.push([nums1[index1], nums2[index2]]); + + if (index1 + 1 < nums1.length && !visited.has(`${index1 + 1},${index2}`)) { + minHeap.enqueue([nums1[index1 + 1] + nums2[index2], index1 + 1, index2]); + visited.add(`${index1 + 1},${index2}`); + } - while (k > 0 && !heap.isEmpty()) { - const [n, index] = heap.dequeue(); - result.push([n - nums2[index], nums2[index]]); - if (index + 1 < nums2.length) { - heap.enqueue([n - nums2[index] + nums2[index + 1], index + 1]); + if (index2 + 1 < nums2.length && !visited.has(`${index1},${index2 + 1}`)) { + minHeap.enqueue([nums1[index1] + nums2[index2 + 1], index1, index2 + 1]); + visited.add(`${index1},${index2 + 1}`); } - k--; } return result; diff --git a/solutions/0379-design-phone-directory.js b/solutions/0379-design-phone-directory.js new file mode 100644 index 00000000..4973efa9 --- /dev/null +++ b/solutions/0379-design-phone-directory.js @@ -0,0 +1,64 @@ +/** + * 379. Design Phone Directory + * https://leetcode.com/problems/design-phone-directory/ + * Difficulty: Medium + * + * Design a phone directory that initially has maxNumbers empty slots that can store numbers. + * The directory should store numbers, check if a certain slot is empty or not, and empty a + * given slot. + * + * Implement the PhoneDirectory class: + * - PhoneDirectory(int maxNumbers) Initializes the phone directory with the number of + * available slots maxNumbers. + * - int get() Provides a number that is not assigned to anyone. Returns -1 if no number + * is available. + * - bool check(int number) Returns true if the slot number is available and false otherwise. + * - void release(int number) Recycles or releases the slot number. + */ + +/** + * @param {number} maxNumbers + */ +var PhoneDirectory = function(maxNumbers) { + this.available = new Set(); + this.released = []; + this.max = maxNumbers; + for (let i = 0; i < maxNumbers; i++) { + this.available.add(i); + } +}; + +/** + * @return {number} + */ +PhoneDirectory.prototype.get = function() { + if (this.available.size === 0 && this.released.length === 0) return -1; + let number; + if (this.released.length > 0) { + number = this.released.pop(); + } else { + number = this.available.values().next().value; + this.available.delete(number); + } + return number; +}; + +/** + * @param {number} number + * @return {boolean} + */ +PhoneDirectory.prototype.check = function(number) { + return number >= 0 && number < this.max + && (this.available.has(number) || this.released.includes(number)); +}; + +/** + * @param {number} number + * @return {void} + */ +PhoneDirectory.prototype.release = function(number) { + if (number >= 0 && number < this.max + && !this.available.has(number) && !this.released.includes(number)) { + this.released.push(number); + } +}; diff --git a/solutions/0408-valid-word-abbreviation.js b/solutions/0408-valid-word-abbreviation.js new file mode 100644 index 00000000..9dde3f72 --- /dev/null +++ b/solutions/0408-valid-word-abbreviation.js @@ -0,0 +1,55 @@ +/** + * 408. Valid Word Abbreviation + * https://leetcode.com/problems/valid-word-abbreviation/ + * Difficulty: Easy + * + * A string can be abbreviated by replacing any number of non-adjacent, non-empty substrings + * with their lengths. The lengths should not have leading zeros. + * + * For example, a string such as "substitution" could be abbreviated as (but not limited to): + * - "s10n" ("s ubstitutio n") + * - "sub4u4" ("sub stit u tion") + * - "12" ("substitution") + * - "su3i1u2on" ("su bst i t u ti on") + * - "substitution" (no substrings replaced) + * + * The following are not valid abbreviations: + * - "s55n" ("s ubsti tutio n", the replaced substrings are adjacent) + * - "s010n" (has leading zeros) + * - "s0ubstitution" (replaces an empty substring) + * + * Given a string word and an abbreviation abbr, return whether the string matches the given + * abbreviation. + * + * A substring is a contiguous non-empty sequence of characters within a string. + */ + +/** + * @param {string} word + * @param {string} abbr + * @return {boolean} + */ +var validWordAbbreviation = function(word, abbr) { + let wordIndex = 0; + let abbrIndex = 0; + + while (wordIndex < word.length && abbrIndex < abbr.length) { + if (word[wordIndex] === abbr[abbrIndex]) { + wordIndex++; + abbrIndex++; + continue; + } + + if (abbr[abbrIndex] < '0' || abbr[abbrIndex] > '9') return false; + if (abbr[abbrIndex] === '0') return false; + + let num = 0; + while (abbrIndex < abbr.length && /[0-9]/.test(abbr[abbrIndex])) { + num = num * 10 + Number(abbr[abbrIndex]); + abbrIndex++; + } + wordIndex += num; + } + + return wordIndex === word.length && abbrIndex === abbr.length; +}; diff --git a/solutions/0411-minimum-unique-word-abbreviation.js b/solutions/0411-minimum-unique-word-abbreviation.js new file mode 100644 index 00000000..f595afd4 --- /dev/null +++ b/solutions/0411-minimum-unique-word-abbreviation.js @@ -0,0 +1,97 @@ +/** + * 411. Minimum Unique Word Abbreviation + * https://leetcode.com/problems/minimum-unique-word-abbreviation/ + * Difficulty: Hard + * + * A string can be abbreviated by replacing any number of non-adjacent substrings with their + * lengths. For example, a string such as "substitution" could be abbreviated as (but not + * limited to): + * - "s10n" ("s ubstitutio n") + * - "sub4u4" ("sub stit u tion") + * - "12" ("substitution") + * - "su3i1u2on" ("su bst i t u ti on") + * - "substitution" (no substrings replaced) + * + * Note that "s55n" ("s ubsti tutio n") is not a valid abbreviation of "substitution" because + * the replaced substrings are adjacent. + * + * The length of an abbreviation is the number of letters that were not replaced plus the + * number of substrings that were replaced. For example, the abbreviation "s10n" has a length + * of 3 (2 letters + 1 substring) and "su3i1u2on" has a length of 9 (6 letters + 3 substrings). + * + * Given a target string target and an array of strings dictionary, return an abbreviation + * of target with the shortest possible length such that it is not an abbreviation of any + * string in dictionary. If there are multiple shortest abbreviations, return any of them. + */ + +/** + * @param {string} target + * @param {string[]} dictionary + * @return {string} + */ +var minAbbreviation = function(target, dictionary) { + let minLength = target.length; + let result = target; + const validDict = dictionary.filter(word => word.length === target.length); + + for (let mask = 0; mask < (1 << target.length); mask++) { + const abbr = getAbbr(target, mask); + if (abbr.length <= minLength) { + let isValid = true; + for (const word of validDict) { + if (conflicts(abbr, word)) { + isValid = false; + break; + } + } + if (isValid) { + if (abbr.length < minLength) { + minLength = abbr.length; + result = abbr; + } else if (abbr.length === minLength && abbr < result) { + result = abbr; + } + } + } + } + + return result; + + function getAbbr(str, mask) { + let abbr = ''; + let count = 0; + for (let i = 0; i < str.length; i++) { + if (mask & (1 << i)) { + if (count) { + abbr += count; + count = 0; + } + abbr += str[i]; + } else { + count++; + } + } + if (count) abbr += count; + return abbr; + } + + function conflicts(abbr, word) { + let i = 0; + let j = 0; + while (i < abbr.length && j < word.length) { + if (i < abbr.length && j < word.length && abbr[i] === word[j]) { + i++; + j++; + } else if (i < abbr.length && /\d/.test(abbr[i])) { + let num = 0; + while (i < abbr.length && /\d/.test(abbr[i])) { + num = num * 10 + Number(abbr[i++]); + } + j += num; + } else { + return false; + } + } + return i === abbr.length && j === word.length; + } +}; diff --git a/solutions/0418-sentence-screen-fitting.js b/solutions/0418-sentence-screen-fitting.js new file mode 100644 index 00000000..68a6a992 --- /dev/null +++ b/solutions/0418-sentence-screen-fitting.js @@ -0,0 +1,42 @@ +/** + * 418. Sentence Screen Fitting + * https://leetcode.com/problems/sentence-screen-fitting/ + * Difficulty: Medium + * + * Given a rows x cols screen and a sentence represented as a list of strings, return the number + * of times the given sentence can be fitted on the screen. + * + * The order of words in the sentence must remain unchanged, and a word cannot be split into two + * lines. A single space must separate two consecutive words in a line. + */ + +/** + * @param {string[]} sentence + * @param {number} rows + * @param {number} cols + * @return {number} + */ +var wordsTyping = function(sentence, rows, cols) { + const sentenceLength = sentence.length; + const wordLengths = sentence.map(word => word.length + 1); + let rowIndex = 0; + let colIndex = 0; + let wordIndex = 0; + let result = 0; + + while (rowIndex < rows) { + if (colIndex + wordLengths[wordIndex] - 1 <= cols) { + colIndex += wordLengths[wordIndex]; + wordIndex++; + if (wordIndex === sentenceLength) { + result++; + wordIndex = 0; + } + } else { + rowIndex++; + colIndex = 0; + } + } + + return result; +}; diff --git a/solutions/0422-valid-word-square.js b/solutions/0422-valid-word-square.js new file mode 100644 index 00000000..36f46305 --- /dev/null +++ b/solutions/0422-valid-word-square.js @@ -0,0 +1,30 @@ +/** + * 422. Valid Word Square + * https://leetcode.com/problems/valid-word-square/ + * Difficulty: Easy + * + * Given an array of strings words, return true if it forms a valid word square. + * + * A sequence of strings forms a valid word square if the kth row and column read the same + * string, where 0 <= k < max(numRows, numColumns). + */ + +/** + * @param {string[]} words + * @return {boolean} + */ +var validWordSquare = function(words) { + const rowCount = words.length; + + for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) { + const row = words[rowIndex]; + for (let colIndex = 0; colIndex < row.length; colIndex++) { + if (colIndex >= rowCount || rowIndex >= words[colIndex].length + || row[colIndex] !== words[colIndex][rowIndex]) { + return false; + } + } + } + + return true; +}; diff --git a/solutions/0425-word-squares.js b/solutions/0425-word-squares.js new file mode 100644 index 00000000..4a124ea3 --- /dev/null +++ b/solutions/0425-word-squares.js @@ -0,0 +1,59 @@ +/** + * 425. Word Squares + * https://leetcode.com/problems/word-squares/ + * Difficulty: Hard + * + * Given an array of unique strings words, return all the word squares you can build from + * words. The same word from words can be used multiple times. You can return the answer + * in any order. + * + * A sequence of strings forms a valid word square if the kth row and column read the same + * string, where 0 <= k < max(numRows, numColumns). + * + * - For example, the word sequence ["ball","area","lead","lady"] forms a word square because + * each word reads the same both horizontally and vertically. + */ + +/** + * @param {string[]} words + * @return {string[][]} + */ +var wordSquares = function(words) { + const result = []; + const prefixMap = new Map(); + const wordLength = words[0].length; + + for (const word of words) { + for (let i = 0; i < word.length; i++) { + const prefix = word.slice(0, i); + if (!prefixMap.has(prefix)) { + prefixMap.set(prefix, []); + } + prefixMap.get(prefix).push(word); + } + } + + function buildSquare(currentSquare) { + if (currentSquare.length === wordLength) { + result.push([...currentSquare]); + return; + } + + const prefix = currentSquare + .map(word => word[currentSquare.length]) + .join(''); + + const candidates = prefixMap.get(prefix) || []; + for (const candidate of candidates) { + currentSquare.push(candidate); + buildSquare(currentSquare); + currentSquare.pop(); + } + } + + for (const word of words) { + buildSquare([word]); + } + + return result; +}; diff --git a/solutions/0426-convert-binary-search-tree-to-sorted-doubly-linked-list.js b/solutions/0426-convert-binary-search-tree-to-sorted-doubly-linked-list.js new file mode 100644 index 00000000..77ba2440 --- /dev/null +++ b/solutions/0426-convert-binary-search-tree-to-sorted-doubly-linked-list.js @@ -0,0 +1,58 @@ +/** + * 426. Convert Binary Search Tree to Sorted Doubly Linked List + * https://leetcode.com/problems/convert-binary-search-tree-to-sorted-doubly-linked-list/ + * Difficulty: Medium + * + * Convert a Binary Search Tree to a sorted Circular Doubly-Linked List in place. + * + * You can think of the left and right pointers as synonymous to the predecessor and successor + * pointers in a doubly-linked list. For a circular doubly linked list, the predecessor of the + * first element is the last element, and the successor of the last element is the first element. + * + * We want to do the transformation in place. After the transformation, the left pointer of the + * tree node should point to its predecessor, and the right pointer should point to its successor. + * You should return the pointer to the smallest element of the linked list. + */ + +/** + * // Definition for a _Node. + * function _Node(val, left, right) { + * this.val = val; + * this.left = left; + * this.right = right; + * }; + */ + +/** + * @param {_Node} root + * @return {_Node} + */ +var treeToDoublyList = function(root) { + if (!root) return null; + + let first = null; + let last = null; + + inorder(root); + + last.right = first; + first.left = last; + + return first; + + function inorder(node) { + if (!node) return; + + inorder(node.left); + + if (last) { + last.right = node; + node.left = last; + } else { + first = node; + } + last = node; + + inorder(node.right); + } +}; diff --git a/solutions/0428-serialize-and-deserialize-n-ary-tree.js b/solutions/0428-serialize-and-deserialize-n-ary-tree.js new file mode 100644 index 00000000..8128bde1 --- /dev/null +++ b/solutions/0428-serialize-and-deserialize-n-ary-tree.js @@ -0,0 +1,74 @@ +/** + * 428. Serialize and Deserialize N-ary Tree + * https://leetcode.com/problems/serialize-and-deserialize-n-ary-tree/ + * Difficulty: Hard + * + * Serialization is the process of converting a data structure or object into a sequence of + * bits so that it can be stored in a file or memory buffer, or transmitted across a network + * connection link to be reconstructed later in the same or another computer environment. + * + * Design an algorithm to serialize and deserialize an N-ary tree. An N-ary tree is a rooted + * tree in which each node has no more than N children. There is no restriction on how your + * serialization/deserialization algorithm should work. You just need to ensure that an N-ary + * tree can be serialized to a string and this string can be deserialized to the original + * tree structure. + * + * For example, you may serialize the following 3-ary tree as [1 [3[5 6] 2 4]]. Note that + * this is just an example, you do not necessarily need to follow this format. + * + * Or you can follow LeetCode's level order traversal serialization format, where each + * group of children is separated by the null value. + * + * For example, the above tree may be serialized as + * [1,null,2,3,4,5,null,null,6,7,null,8,null,9,10,null,null,11,null,12,null,13,null,null,14]. + * + * You do not necessarily need to follow the above-suggested formats, there are many more + * different formats that work so please be creative and come up with different approaches + * yourself. + */ + +/** + * // Definition for a _Node. + * function _Node(val,children) { + * this.val = val; + * this.children = children; + * }; + */ + +class Codec { + constructor() {} + + serialize = function(root) { + if (!root) return ''; + const result = []; + + function serializeNode(node) { + result.push(node.val); + result.push(node.children.length); + for (const child of node.children) { + serializeNode(child); + } + } + + serializeNode(root); + return result.join(','); + }; + + deserialize = function(data) { + if (!data) return null; + const values = data.split(',').map(Number); + let index = 0; + + function deserializeNode() { + const val = values[index++]; + const childCount = values[index++]; + const children = []; + for (let i = 0; i < childCount; i++) { + children.push(deserializeNode()); + } + return new _Node(val, children); + } + + return deserializeNode(); + }; +} diff --git a/solutions/0431-encode-n-ary-tree-to-binary-tree.js b/solutions/0431-encode-n-ary-tree-to-binary-tree.js new file mode 100644 index 00000000..6a7cf758 --- /dev/null +++ b/solutions/0431-encode-n-ary-tree-to-binary-tree.js @@ -0,0 +1,74 @@ +/** + * 431. Encode N-ary Tree to Binary Tree + * https://leetcode.com/problems/encode-n-ary-tree-to-binary-tree/ + * Difficulty: Hard + * + * Design an algorithm to encode an N-ary tree into a binary tree and decode the binary tree + * to get the original N-ary tree. An N-ary tree is a rooted tree in which each node has no + * more than N children. Similarly, a binary tree is a rooted tree in which each node has no + * more than 2 children. There is no restriction on how your encode/decode algorithm should + * work. You just need to ensure that an N-ary tree can be encoded to a binary tree and this + * binary tree can be decoded to the original N-nary tree structure. + * + * Nary-Tree input serialization is represented in their level order traversal, each group + * of children is separated by the null value (See following example). + * + * For example, you may encode the following 3-ary tree to a binary tree in this way: + * - Input: root = [1,null,3,2,4,null,5,6] + * + * Note that the above is just an example which might or might not work. You do not necessarily + * need to follow this format, so please be creative and come up with different approaches yourself. + */ + +/** + * // Definition for a _Node. + * function _Node(val,children) { + * this.val = val; + * this.children = children; + * }; + */ + +/** + * Definition for a binary tree node. + * function TreeNode(val) { + * this.val = val; + * this.left = this.right = null; + * } + */ + +class Codec { + constructor() {} + + encode = function(root) { + if (!root) return null; + + const binaryRoot = new TreeNode(root.val); + + if (root.children.length > 0) { + binaryRoot.left = this.encode(root.children[0]); + } + + let sibling = binaryRoot.left; + for (let i = 1; i < root.children.length; i++) { + if (sibling) { + sibling.right = this.encode(root.children[i]); + sibling = sibling.right; + } + } + + return binaryRoot; + }; + + decode = function(root) { + if (!root) return null; + + const updated = new _Node(root.val, []); + let sibling = root.left; + while (sibling) { + updated.children.push(this.decode(sibling)); + sibling = sibling.right; + } + + return updated; + }; +} diff --git a/solutions/0439-ternary-expression-parser.js b/solutions/0439-ternary-expression-parser.js new file mode 100644 index 00000000..586a3b73 --- /dev/null +++ b/solutions/0439-ternary-expression-parser.js @@ -0,0 +1,38 @@ +/** + * 439. Ternary Expression Parser + * https://leetcode.com/problems/ternary-expression-parser/ + * Difficulty: Medium + * + * Given a string expression representing arbitrarily nested ternary expressions, + * evaluate the expression, and return the result of it. + * + * You can always assume that the given expression is valid and only contains digits, + * '?', ':', 'T', and 'F' where 'T' is true and 'F' is false. All the numbers in the + * expression are one-digit numbers (i.e., in the range [0, 9]). + * + * The conditional expressions group right-to-left (as usual in most languages), and + * the result of the expression will always evaluate to either a digit, 'T' or 'F'. + */ + +/** + * @param {string} expression + * @return {string} + */ +var parseTernary = function(expression) { + const stack = []; + + for (let i = expression.length - 1; i >= 0; i--) { + const char = expression[i]; + if (char !== ':' && char !== '?') { + stack.push(char); + } else if (char === '?') { + const condition = expression[i - 1]; + const trueValue = stack.pop(); + const falseValue = stack.pop(); + stack.push(condition === 'T' ? trueValue : falseValue); + i--; + } + } + + return stack[0]; +}; diff --git a/solutions/0444-sequence-reconstruction.js b/solutions/0444-sequence-reconstruction.js new file mode 100644 index 00000000..a972a0ca --- /dev/null +++ b/solutions/0444-sequence-reconstruction.js @@ -0,0 +1,70 @@ +/** + * 444. Sequence Reconstruction + * https://leetcode.com/problems/sequence-reconstruction/ + * Difficulty: Medium + * + * You are given an integer array nums of length n where nums is a permutation of the + * integers in the range [1, n]. You are also given a 2D integer array sequences where + * sequences[i] is a subsequence of nums. + * + * Check if nums is the shortest possible and the only supersequence. The shortest + * supersequence is a sequence with the shortest length and has all sequences[i] as + * subsequences. There could be multiple valid supersequences for the given array sequences. + * - For example, for sequences = [[1,2],[1,3]], there are two shortest supersequences, + * [1,2,3] and [1,3,2]. + * - While for sequences = [[1,2],[1,3],[1,2,3]], the only shortest supersequence possible + * is [1,2,3]. [1,2,3,4] is a possible supersequence but not the shortest. + * + * Return true if nums is the only shortest supersequence for sequences, or false otherwise. + * + * A subsequence is a sequence that can be derived from another sequence by deleting some or + * no elements without changing the order of the remaining elements. + */ + +/** + * @param {number[]} nums + * @param {number[][]} sequences + * @return {boolean} + */ +var sequenceReconstruction = function(nums, sequences) { + const n = nums.length; + const graph = new Map(); + const inDegree = new Array(n + 1).fill(0); + + for (let i = 1; i <= n; i++) { + graph.set(i, []); + } + + for (const seq of sequences) { + for (let i = 1; i < seq.length; i++) { + graph.get(seq[i - 1]).push(seq[i]); + inDegree[seq[i]]++; + } + } + + const queue = []; + for (let i = 1; i <= n; i++) { + if (inDegree[i] === 0) { + queue.push(i); + } + } + + if (queue.length !== 1) return false; + + const result = []; + while (queue.length) { + if (queue.length > 1) return false; + const curr = queue.shift(); + result.push(curr); + + const nextNodes = graph.get(curr); + for (const next of nextNodes) { + inDegree[next]--; + if (inDegree[next] === 0) { + queue.push(next); + } + } + } + + return result.length === n && result.every((val, i) => val === nums[i]); +}; diff --git a/solutions/0465-optimal-account-balancing.js b/solutions/0465-optimal-account-balancing.js new file mode 100644 index 00000000..14b6f3f5 --- /dev/null +++ b/solutions/0465-optimal-account-balancing.js @@ -0,0 +1,46 @@ +/** + * 465. Optimal Account Balancing + * https://leetcode.com/problems/optimal-account-balancing/ + * Difficulty: Hard + * + * You are given an array of transactions transactions where + * transactions[i] = [fromi, toi, amounti] indicates that the person with ID = fromi + * gave amounti $ to the person with ID = toi. + * + * Return the minimum number of transactions required to settle the debt. + */ + +/** + * @param {number[][]} transactions + * @return {number} + */ +var minTransfers = function(transactions) { + const balances = new Array(12).fill(0); + + for (const [from, to, amount] of transactions) { + balances[from] -= amount; + balances[to] += amount; + } + + const debts = balances.filter(balance => balance !== 0); + return helper(0, 0); + + function helper(index, count) { + if (index === debts.length) return count; + + if (debts[index] === 0) return helper(index + 1, count); + + let minTransactions = Infinity; + const currentDebt = debts[index]; + + for (let i = index + 1; i < debts.length; i++) { + if (debts[i] * currentDebt < 0) { + debts[i] += currentDebt; + minTransactions = Math.min(minTransactions, helper(index + 1, count + 1)); + debts[i] -= currentDebt; + } + } + + return minTransactions; + } +}; diff --git a/solutions/0469-convex-polygon.js b/solutions/0469-convex-polygon.js new file mode 100644 index 00000000..d61e33e4 --- /dev/null +++ b/solutions/0469-convex-polygon.js @@ -0,0 +1,44 @@ +/** + * 469. Convex Polygon + * https://leetcode.com/problems/convex-polygon/ + * Difficulty: Medium + * + * You are given an array of points on the X-Y plane points where points[i] = [xi, yi]. + * The points form a polygon when joined sequentially. + * + * Return true if this polygon is convex and false otherwise. + * + * You may assume the polygon formed by given points is always a simple polygon. In other + * words, we ensure that exactly two edges intersect at each vertex and that edges otherwise + * don't intersect each other. + */ + +/** + * @param {number[][]} points + * @return {boolean} + */ +var isConvex = function(points) { + const n = points.length; + let prevSign = 0; + + for (let i = 0; i < n; i++) { + const p1 = points[i]; + const p2 = points[(i + 1) % n]; + const p3 = points[(i + 2) % n]; + const dx1 = p2[0] - p1[0]; + const dy1 = p2[1] - p1[1]; + const dx2 = p3[0] - p2[0]; + const dy2 = p3[1] - p2[1]; + const crossProduct = dx1 * dy2 - dy1 * dx2; + const currentSign = Math.sign(crossProduct); + + if (currentSign !== 0) { + if (prevSign !== 0 && currentSign !== prevSign) { + return false; + } + prevSign = currentSign; + } + } + + return true; +}; diff --git a/solutions/0471-encode-string-with-shortest-length.js b/solutions/0471-encode-string-with-shortest-length.js new file mode 100644 index 00000000..70a96646 --- /dev/null +++ b/solutions/0471-encode-string-with-shortest-length.js @@ -0,0 +1,65 @@ +/** + * 471. Encode String with Shortest Length + * https://leetcode.com/problems/encode-string-with-shortest-length/ + * Difficulty: Hard + * + * Given a string s, encode the string such that its encoded length is the shortest. + * + * The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets + * is being repeated exactly k times. k should be a positive integer. + * + * If an encoding process does not make the string shorter, then do not encode it. If there are + * several solutions, return any of them. + */ + +/** + * @param {string} s + * @return {string} + */ +var encode = function(s) { + const n = s.length; + const dp = Array.from({ length: n }, () => new Array(n).fill('')); + + for (let len = 1; len <= n; len++) { + for (let start = 0; start + len <= n; start++) { + const end = start + len - 1; + const substr = s.slice(start, end + 1); + + dp[start][end] = substr; + + for (let k = 1; k < len; k++) { + const left = dp[start][start + k - 1]; + const right = dp[start + k][end]; + const combined = left + right; + if (combined.length < dp[start][end].length) { + dp[start][end] = combined; + } + } + + let repeat = 1; + const patternLen = len; + while (repeat * patternLen <= n && s.slice(start, start + patternLen).repeat(repeat) + === s.slice(start, start + repeat * patternLen)) { + const encoded = `${repeat}[${dp[start][start + patternLen - 1]}]`; + if (encoded.length < dp[start][end].length) { + dp[start][end] = encoded; + } + repeat++; + } + + for (let k = 1; k < len; k++) { + if (len % k === 0) { + const pattern = s.slice(start, start + k); + if (pattern.repeat(len / k) === substr) { + const encoded = `${len / k}[${dp[start][start + k - 1]}]`; + if (encoded.length < dp[start][end].length) { + dp[start][end] = encoded; + } + } + } + } + } + } + + return dp[0][n - 1]; +}; diff --git a/solutions/0484-find-permutation.js b/solutions/0484-find-permutation.js new file mode 100644 index 00000000..62bbfabf --- /dev/null +++ b/solutions/0484-find-permutation.js @@ -0,0 +1,39 @@ +/** + * 484. Find Permutation + * https://leetcode.com/problems/find-permutation/ + * Difficulty: Medium + * + * A permutation perm of n integers of all the integers in the range [1, n] can be + * represented as a string s of length n - 1 where: + * - s[i] == 'I' if perm[i] < perm[i + 1], and + * - s[i] == 'D' if perm[i] > perm[i + 1]. + * + * Given a string s, reconstruct the lexicographically smallest permutation perm and return it. + */ + +/** + * @param {string} s + * @return {number[]} + */ +var findPermutation = function(s) { + const n = s.length + 1; + const result = new Array(n).fill(0).map((_, i) => i + 1); + + for (let i = 0; i < s.length; i++) { + if (s[i] === 'D') { + let start = i; + while (i < s.length && s[i] === 'D') { + i++; + } + let end = i; + while (start < end) { + [result[start], result[end]] = [result[end], result[start]]; + start++; + end--; + } + i--; + } + } + + return result; +}; diff --git a/solutions/0487-max-consecutive-ones-ii.js b/solutions/0487-max-consecutive-ones-ii.js new file mode 100644 index 00000000..d96259b6 --- /dev/null +++ b/solutions/0487-max-consecutive-ones-ii.js @@ -0,0 +1,38 @@ +/** + * 487. Max Consecutive Ones II + * https://leetcode.com/problems/max-consecutive-ones-ii/ + * Difficulty: Medium + * + * Given a binary array nums, return the maximum number of consecutive 1's in the array + * if you can flip at most one 0. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var findMaxConsecutiveOnes = function(nums) { + let result = 0; + let currentConsecutive = 0; + let zeroCount = 0; + let left = 0; + + for (let right = 0; right < nums.length; right++) { + if (nums[right] === 0) { + zeroCount++; + } + + while (zeroCount > 1) { + if (nums[left] === 0) { + zeroCount--; + } + currentConsecutive--; + left++; + } + + currentConsecutive++; + result = Math.max(result, currentConsecutive); + } + + return result; +}; diff --git a/solutions/0489-robot-room-cleaner.js b/solutions/0489-robot-room-cleaner.js new file mode 100644 index 00000000..2eea307d --- /dev/null +++ b/solutions/0489-robot-room-cleaner.js @@ -0,0 +1,78 @@ +/** + * 489. Robot Room Cleaner + * https://leetcode.com/problems/robot-room-cleaner/ + * Difficulty: Hard + * + * You are controlling a robot that is located somewhere in a room. The room is modeled as an m x n + * binary grid where 0 represents a wall and 1 represents an empty slot. + * + * The robot starts at an unknown location in the room that is guaranteed to be empty, and you do + * not have access to the grid, but you can move the robot using the given API Robot. + * + * You are tasked to use the robot to clean the entire room (i.e., clean every empty cell in the + * room). The robot with the four given APIs can move forward, turn left, or turn right. Each turn + * is 90 degrees. + * + * When the robot tries to move into a wall cell, its bumper sensor detects the obstacle, and it + * stays on the current cell. + * + * Design an algorithm to clean the entire room using the following APIs: + * + * interface Robot { + * // returns true if next cell is open and robot moves into the cell. + * // returns false if next cell is obstacle and robot stays on the current cell. + * boolean move(); + * + * // Robot will stay on the same cell after calling turnLeft/turnRight. + * // Each turn will be 90 degrees. + * void turnLeft(); + * void turnRight(); + * + * // Clean the current cell. + * void clean(); + * } + * + * Note that the initial direction of the robot will be facing up. You can assume all four edges of + * the grid are all surrounded by a wall. + * + * Custom testing: + * The input is only given to initialize the room and the robot's position internally. You must + * solve this problem "blindfolded". In other words, you must control the robot using only the + * four mentioned APIs without knowing the room layout and the initial robot's position. + */ + +/** + * @param {Robot} robot + * @return {void} + */ +var cleanRoom = function(robot) { + const visited = new Set(); + const directions = [[-1, 0], [0, 1], [1, 0], [0, -1]]; + + backtrack(0, 0, 0); + + function backtrack(row, col, dir) { + const key = `${row},${col}`; + if (visited.has(key)) return; + + visited.add(key); + robot.clean(); + + for (let i = 0; i < 4; i++) { + const newDir = (dir + i) % 4; + const [dx, dy] = directions[newDir]; + const newRow = row + dx; + const newCol = col + dy; + + if (robot.move()) { + backtrack(newRow, newCol, newDir); + robot.turnRight(); + robot.turnRight(); + robot.move(); + robot.turnLeft(); + robot.turnLeft(); + } + robot.turnRight(); + } + } +}; diff --git a/solutions/0490-the-maze.js b/solutions/0490-the-maze.js new file mode 100644 index 00000000..cca94171 --- /dev/null +++ b/solutions/0490-the-maze.js @@ -0,0 +1,52 @@ +/** + * 490. The Maze + * https://leetcode.com/problems/the-maze/ + * Difficulty: Medium + * + * There is a ball in a maze with empty spaces (represented as 0) and walls (represented as 1). + * The ball can go through the 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 m x n maze, the ball's start position and the destination, where + * start = [startrow, startcol] and destination = [destinationrow, destinationcol], + * return true if the ball can stop at the destination, otherwise return false. + * + * You may assume that the borders of the maze are all walls (see examples). + */ + +/** + * @param {number[][]} maze + * @param {number[]} start + * @param {number[]} destination + * @return {boolean} + */ +var hasPath = function(maze, start, destination) { + const rows = maze.length; + const cols = maze[0].length; + const visited = new Set(); + const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]; + + return helper(start[0], start[1]); + + function helper(row, col) { + if (visited.has(`${row},${col}`)) return false; + visited.add(`${row},${col}`); + + if (row === destination[0] && col === destination[1]) return true; + + for (const [dr, dc] of directions) { + let newRow = row; + let newCol = col; + + while (newRow + dr >= 0 && newRow + dr < rows && newCol + dc >= 0 && newCol + dc < cols + && maze[newRow + dr][newCol + dc] === 0) { + newRow += dr; + newCol += dc; + } + + if (helper(newRow, newCol)) return true; + } + + return false; + } +}; diff --git a/solutions/0499-the-maze-iii.js b/solutions/0499-the-maze-iii.js new file mode 100644 index 00000000..22079773 --- /dev/null +++ b/solutions/0499-the-maze-iii.js @@ -0,0 +1,80 @@ +/** + * 499. The Maze III + * https://leetcode.com/problems/the-maze-iii/ + * Difficulty: Hard + * + * There is a ball in a maze with empty spaces (represented as 0) and walls (represented as 1). + * The ball can go through the 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. + * There is also a hole in this maze. The ball will drop into the hole if it rolls onto the hole. + * + * Given the m x n maze, the ball's position ball and the hole's position hole, where + * ball = [ballrow, ballcol] and hole = [holerow, holecol], return a string instructions of + * all the instructions that the ball should follow to drop in the hole with the shortest + * distance possible. If there are multiple valid instructions, return the lexicographically + * minimum one. If the ball can't drop in the hole, return "impossible". + * + * If there is a way for the ball to drop in the hole, the answer instructions should contain + * the characters 'u' (i.e., up), 'd' (i.e., down), 'l' (i.e., left), and 'r' (i.e., right). + * + * The distance is the number of empty spaces traveled by the ball from the start position + * (excluded) to the destination (included). + * + * You may assume that the borders of the maze are all walls (see examples). + */ + +var findShortestWay = function(maze, ball, hole) { + const rows = maze.length; + const cols = maze[0].length; + const directions = [[-1, 0, 'u'], [1, 0, 'd'], [0, -1, 'l'], [0, 1, 'r']]; + const distances = new Array(rows).fill().map(() => new Array(cols).fill(Infinity)); + const paths = new Array(rows).fill().map(() => new Array(cols).fill('')); + + const pq = [[0, ball[0], ball[1], '']]; + distances[ball[0]][ball[1]] = 0; + + while (pq.length > 0) { + pq.sort((a, b) => a[0] - b[0] || a[3].localeCompare(b[3])); + const [currentDist, row, col, path] = pq.shift(); + + if (row === hole[0] && col === hole[1]) { + return path; + } + + if (currentDist > distances[row][col] + || (currentDist === distances[row][col] && path > paths[row][col])) { + continue; + } + + for (const [dr, dc, dir] of directions) { + let newRow = row; + let newCol = col; + let steps = 0; + + while (newRow + dr >= 0 && newRow + dr < rows && newCol + dc >= 0 && newCol + dc < cols + && maze[newRow + dr][newCol + dc] === 0) { + newRow += dr; + newCol += dc; + steps++; + + if (newRow === hole[0] && newCol === hole[1]) { + break; + } + } + + if (steps > 0) { + const newDist = currentDist + steps; + const newPath = path + dir; + + if (newDist < distances[newRow][newCol] + || (newDist === distances[newRow][newCol] && newPath < paths[newRow][newCol])) { + distances[newRow][newCol] = newDist; + paths[newRow][newCol] = newPath; + pq.push([newDist, newRow, newCol, newPath]); + } + } + } + } + + return 'impossible'; +}; diff --git a/solutions/0505-the-maze-ii.js b/solutions/0505-the-maze-ii.js new file mode 100644 index 00000000..3d84611e --- /dev/null +++ b/solutions/0505-the-maze-ii.js @@ -0,0 +1,62 @@ +/** + * 505. The Maze II + * https://leetcode.com/problems/the-maze-ii/ + * Difficulty: Medium + * + * There is a ball in a maze with empty spaces (represented as 0) and walls (represented as 1). + * The ball can go through the 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 m x n maze, the ball's start position and the destination, where + * start = [startrow, startcol] and destination = [destinationrow, destinationcol], return + * the shortest distance for the ball to stop at the destination. If the ball cannot stop + * at destination, return -1. + * + * The distance is the number of empty spaces traveled by the ball from the start position + * (excluded) to the destination (included). + * + * You may assume that the borders of the maze are all walls (see examples). + */ + +/** + * @param {number[][]} maze + * @param {number[]} start + * @param {number[]} destination + * @return {number} + */ +var shortestDistance = function(maze, start, destination) { + const rows = maze.length; + const cols = maze[0].length; + const distances = new Array(rows).fill().map(() => new Array(cols).fill(Infinity)); + const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]; + const queue = [[start[0], start[1], 0]]; + distances[start[0]][start[1]] = 0; + + while (queue.length) { + const [row, col, distance] = queue.shift(); + if (distance > distances[row][col]) continue; + + for (const [dx, dy] of directions) { + let nextRow = row; + let nextCol = col; + let steps = 0; + + while (nextRow + dx >= 0 && nextRow + dx < rows && nextCol + dy >= 0 + && nextCol + dy < cols && maze[nextRow + dx][nextCol + dy] === 0 + ) { + nextRow += dx; + nextCol += dy; + steps++; + } + + const newDistance = distance + steps; + if (newDistance < distances[nextRow][nextCol]) { + distances[nextRow][nextCol] = newDistance; + queue.push([nextRow, nextCol, newDistance]); + } + } + } + + const result = distances[destination[0]][destination[1]]; + return result === Infinity ? -1 : result; +}; diff --git a/solutions/0510-inorder-successor-in-bst-ii.js b/solutions/0510-inorder-successor-in-bst-ii.js new file mode 100644 index 00000000..db87a419 --- /dev/null +++ b/solutions/0510-inorder-successor-in-bst-ii.js @@ -0,0 +1,50 @@ +/** + * 510. Inorder Successor in BST II + * https://leetcode.com/problems/inorder-successor-in-bst-ii/ + * Difficulty: Medium + * + * Given a node in a binary search tree, return the in-order successor of that node in the BST. + * If that node has no in-order successor, return null. + * + * The successor of a node is the node with the smallest key greater than node.val. + * + * You will have direct access to the node but not to the root of the tree. Each node will have + * a reference to its parent node. Below is the definition for Node: + * + * class Node { + * public int val; + * public Node left; + * public Node right; + * public Node parent; + * } + */ + +/** + * // Definition for a _Node. + * function _Node(val) { + * this.val = val; + * this.left = null; + * this.right = null; + * this.parent = null; + * }; + */ + +/** + * @param {_Node} node + * @return {_Node} + */ +var inorderSuccessor = function(node) { + if (node.right) { + let successor = node.right; + while (successor.left) { + successor = successor.left; + } + return successor; + } + + let current = node; + while (current.parent && current.parent.right === current) { + current = current.parent; + } + return current.parent; +}; diff --git a/solutions/0527-word-abbreviation.js b/solutions/0527-word-abbreviation.js new file mode 100644 index 00000000..59447b55 --- /dev/null +++ b/solutions/0527-word-abbreviation.js @@ -0,0 +1,80 @@ +/** + * 527. Word Abbreviation + * https://leetcode.com/problems/word-abbreviation/ + * Difficulty: Hard + * + * Given an array of distinct strings words, return the minimal possible abbreviations for + * every word. + * + * The following are the rules for a string abbreviation: + * 1. The initial abbreviation for each word is: the first character, then the number of + * characters in between, followed by the last character. + * 2. If more than one word shares the same abbreviation, then perform the following operation: + * - Increase the prefix (characters in the first part) of each of their abbreviations by 1. + * - For example, say you start with the words ["abcdef","abndef"] both initially abbreviated + * as "a4f". Then, a sequence of operations would be + * ["a4f","a4f"] -> ["ab3f","ab3f"] -> ["abc2f","abn2f"]. + * - This operation is repeated until every abbreviation is unique. + * 3. At the end, if an abbreviation did not make a word shorter, then keep it as the original word. + */ + +/** + * @param {string[]} words + * @return {string[]} + */ +var wordsAbbreviation = function(words) { + const n = words.length; + const result = new Array(n).fill(''); + const groups = new Map(); + + function getAbbreviation(word, prefixLen) { + const len = word.length; + if (len <= prefixLen + 2) return word; + return word.slice(0, prefixLen) + (len - prefixLen - 1) + word[len - 1]; + } + + for (let i = 0; i < n; i++) { + const word = words[i]; + const prefixLen = 1; + const abbr = getAbbreviation(word, prefixLen); + + if (!groups.has(abbr)) { + groups.set(abbr, []); + } + groups.get(abbr).push([i, prefixLen]); + } + + while (true) { + let resolved = true; + const newGroups = new Map(); + + for (const [abbr, indices] of groups) { + if (indices.length === 1) { + const [index, prefixLen] = indices[0]; + const word = words[index]; + const finalAbbr = getAbbreviation(word, prefixLen); + result[index] = finalAbbr.length < word.length ? finalAbbr : word; + continue; + } + + resolved = false; + for (const [index, prefixLen] of indices) { + const word = words[index]; + const newAbbr = getAbbreviation(word, prefixLen + 1); + + if (!newGroups.has(newAbbr)) { + newGroups.set(newAbbr, []); + } + newGroups.get(newAbbr).push([index, prefixLen + 1]); + } + } + + if (resolved) break; + groups.clear(); + for (const [abbr, indices] of newGroups) { + groups.set(abbr, indices); + } + } + + return result; +}; diff --git a/solutions/0531-lonely-pixel-i.js b/solutions/0531-lonely-pixel-i.js new file mode 100644 index 00000000..41a2f956 --- /dev/null +++ b/solutions/0531-lonely-pixel-i.js @@ -0,0 +1,42 @@ +/** + * 531. Lonely Pixel I + * https://leetcode.com/problems/lonely-pixel-i/ + * Difficulty: Medium + * + * Given an m x n picture consisting of black 'B' and white 'W' pixels, return the number of + * black lonely pixels. + * + * A black lonely pixel is a character 'B' that located at a specific position where the same + * row and same column don't have any other black pixels. + */ + +/** + * @param {character[][]} picture + * @return {number} + */ +var findLonelyPixel = function(picture) { + const rows = picture.length; + const cols = picture[0].length; + const rowCounts = new Array(rows).fill(0); + const colCounts = new Array(cols).fill(0); + let result = 0; + + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + if (picture[row][col] === 'B') { + rowCounts[row]++; + colCounts[col]++; + } + } + } + + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + if (picture[row][col] === 'B' && rowCounts[row] === 1 && colCounts[col] === 1) { + result++; + } + } + } + + return result; +}; diff --git a/solutions/0533-lonely-pixel-ii.js b/solutions/0533-lonely-pixel-ii.js new file mode 100644 index 00000000..c615bb36 --- /dev/null +++ b/solutions/0533-lonely-pixel-ii.js @@ -0,0 +1,57 @@ +/** + * 533. Lonely Pixel II + * https://leetcode.com/problems/lonely-pixel-ii/ + * Difficulty: Medium + * + * Given an m x n picture consisting of black 'B' and white 'W' pixels and an integer target, + * return the number of black lonely pixels. + * + * A black lonely pixel is a character 'B' that located at a specific position (r, c) where: + * - Row r and column c both contain exactly target black pixels. + * - For all rows that have a black pixel at column c, they should be exactly the same as row r. + */ + +/** + * @param {character[][]} picture + * @param {number} target + * @return {number} + */ +var findBlackPixel = function(picture, target) { + const rows = picture.length; + const cols = picture[0].length; + const rowCounts = new Array(rows).fill(0); + const colCounts = new Array(cols).fill(0); + const rowPatterns = new Map(); + + for (let row = 0; row < rows; row++) { + let blackCount = 0; + for (let col = 0; col < cols; col++) { + if (picture[row][col] === 'B') { + blackCount++; + colCounts[col]++; + } + } + rowCounts[row] = blackCount; + if (blackCount === target) { + const pattern = picture[row].join(''); + rowPatterns.set(pattern, (rowPatterns.get(pattern) || 0) + 1); + } + } + + let result = 0; + for (let col = 0; col < cols; col++) { + if (colCounts[col] === target) { + for (let row = 0; row < rows; row++) { + if (picture[row][col] === 'B' && rowCounts[row] === target) { + const pattern = picture[row].join(''); + if (rowPatterns.get(pattern) === target) { + result += target; + break; + } + } + } + } + } + + return result; +}; diff --git a/solutions/0536-construct-binary-tree-from-string.js b/solutions/0536-construct-binary-tree-from-string.js new file mode 100644 index 00000000..a6a9cb1a --- /dev/null +++ b/solutions/0536-construct-binary-tree-from-string.js @@ -0,0 +1,64 @@ +/** + * 536. Construct Binary Tree from String + * https://leetcode.com/problems/construct-binary-tree-from-string/ + * Difficulty: Medium + * + * You need to construct a binary tree from a string consisting of parenthesis and integers. + * + * The whole input represents a binary tree. It contains an integer followed by zero, one or + * two pairs of parenthesis. The integer represents the root's value and a pair of parenthesis + * contains a child binary tree with the same structure. + * + * You always start to construct the left child node of the parent first if it exists. + */ + +/** + * 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 {string} s + * @return {TreeNode} + */ +var str2tree = function(s) { + if (!s) return null; + let index = 0; + return constructTree(); + + function parseNumber() { + const isNegative = s[index] === '-'; + if (isNegative) index++; + + let num = 0; + while (index < s.length && /[0-9]/.test(s[index])) { + num = num * 10 + parseInt(s[index]); + index++; + } + + return isNegative ? -num : num; + } + + function constructTree() { + if (index >= s.length) return null; + + const value = parseNumber(); + const node = new TreeNode(value); + if (index < s.length && s[index] === '(') { + index++; + node.left = constructTree(); + index++; + } + + if (index < s.length && s[index] === '(') { + index++; + node.right = constructTree(); + index++; + } + + return node; + } +}; diff --git a/solutions/0544-output-contest-matches.js b/solutions/0544-output-contest-matches.js new file mode 100644 index 00000000..e1392dd0 --- /dev/null +++ b/solutions/0544-output-contest-matches.js @@ -0,0 +1,39 @@ +/** + * 544. Output Contest Matches + * https://leetcode.com/problems/output-contest-matches/ + * Difficulty: Medium + * + * During the NBA playoffs, we always set the rather strong team to play with the rather weak + * team, like making the rank 1 team play with the rank nth team, which is a good strategy to + * make the contest more interesting. + * + * Given n teams, return their final contest matches in the form of a string. + * + * The n teams are labeled from 1 to n, which represents their initial rank (i.e., Rank 1 is + * the strongest team and Rank n is the weakest team). + * + * We will use parentheses '(', and ')' and commas ',' to represent the contest team pairing. + * We use the parentheses for pairing and the 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. + */ + +/** + * @param {number} n + * @return {string} + */ +var findContestMatch = function(n) { + const teams = Array.from({ length: n }, (_, i) => (i + 1).toString()); + return pairTeams(teams); + + function pairTeams(arr) { + if (arr.length === 1) return arr[0]; + + const nextRound = []; + for (let i = 0; i < arr.length / 2; i++) { + nextRound.push(`(${arr[i]},${arr[arr.length - 1 - i]})`); + } + + return pairTeams(nextRound); + } +}; diff --git a/solutions/0545-boundary-of-binary-tree.js b/solutions/0545-boundary-of-binary-tree.js new file mode 100644 index 00000000..eabf126a --- /dev/null +++ b/solutions/0545-boundary-of-binary-tree.js @@ -0,0 +1,84 @@ +/** + * 545. Boundary of Binary Tree + * https://leetcode.com/problems/boundary-of-binary-tree/ + * Difficulty: Medium + * + * The boundary of a binary tree is the concatenation of the root, the left boundary, the leaves + * ordered from left-to-right, and the reverse order of the right boundary. + * + * The left boundary is the set of nodes defined by the following: + * - The root node's left child is in the left boundary. If the root does not have a left child, + * then the left boundary is empty. + * - If a node in the left boundary and has a left child, then the left child is in the left + * boundary. + * - If a node is in the left boundary, has no left child, but has a right child, then the right + * child is in the left boundary. + * - The leftmost leaf is not in the left boundary. + * + * The right boundary is similar to the left boundary, except it is the right side of the root's + * right subtree. Again, the leaf is not part of the right boundary, and the right boundary is + * empty if the root does not have a right child. + * + * The leaves are nodes that do not have any children. For this problem, the root is not a leaf. + * + * Given the root of a binary tree, return the values of its boundary. + */ + +/** + * 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[]} + */ +var boundaryOfBinaryTree = function(root) { + if (!root) return []; + if (!root.left && !root.right) return [root.val]; + + const result = [root.val]; + + collectLeftBoundary(root.left); + collectLeaves(root); + collectRightBoundary(root.right); + + return result; + + function isLeaf(node) { + return node && !node.left && !node.right; + } + + function collectLeftBoundary(node) { + if (!node || isLeaf(node)) return; + result.push(node.val); + if (node.left) { + collectLeftBoundary(node.left); + } else { + collectLeftBoundary(node.right); + } + } + + function collectLeaves(node) { + if (!node) return; + if (isLeaf(node)) { + result.push(node.val); + return; + } + collectLeaves(node.left); + collectLeaves(node.right); + } + + function collectRightBoundary(node) { + if (!node || isLeaf(node)) return; + if (node.right) { + collectRightBoundary(node.right); + } else { + collectRightBoundary(node.left); + } + result.push(node.val); + } +}; diff --git a/solutions/0548-split-array-with-equal-sum.js b/solutions/0548-split-array-with-equal-sum.js new file mode 100644 index 00000000..672843be --- /dev/null +++ b/solutions/0548-split-array-with-equal-sum.js @@ -0,0 +1,48 @@ +/** + * 548. Split Array with Equal Sum + * https://leetcode.com/problems/split-array-with-equal-sum/ + * Difficulty: Hard + * + * Given an integer array nums of length n, return true if there is a triplet (i, j, k) which + * satisfies the following conditions: + * - 0 < i, i + 1 < j, j + 1 < k < n - 1 + * - The sum of subarrays (0, i - 1), (i + 1, j - 1), (j + 1, k - 1) and (k + 1, n - 1) is equal. + * + * A subarray (l, r) represents a slice of the original array starting from the element + * indexed l to the element indexed r. + */ + +/** + * @param {number[]} nums + * @return {boolean} + */ +var splitArray = function(nums) { + const length = nums.length; + if (length < 7) return false; + + const prefixSums = new Array(length + 1).fill(0); + for (let i = 0; i < length; i++) { + prefixSums[i + 1] = prefixSums[i] + nums[i]; + } + + const getSum = (start, end) => prefixSums[end + 1] - prefixSums[start]; + + for (let j = 3; j < length - 3; j++) { + const seenSums = new Set(); + for (let i = 1; i < j - 1; i++) { + const firstSum = getSum(0, i - 1); + const secondSum = getSum(i + 1, j - 1); + if (firstSum === secondSum) { + seenSums.add(firstSum); + } + } + for (let k = j + 2; k < length - 1; k++) { + const thirdSum = getSum(j + 1, k - 1); + const fourthSum = getSum(k + 1, length - 1); + if (thirdSum === fourthSum && seenSums.has(thirdSum)) { + return true; + } + } + } + return false; +}; diff --git a/solutions/0549-binary-tree-longest-consecutive-sequence-ii.js b/solutions/0549-binary-tree-longest-consecutive-sequence-ii.js new file mode 100644 index 00000000..158a829e --- /dev/null +++ b/solutions/0549-binary-tree-longest-consecutive-sequence-ii.js @@ -0,0 +1,61 @@ +/** + * 549. Binary Tree Longest Consecutive Sequence II + * https://leetcode.com/problems/binary-tree-longest-consecutive-sequence-ii/ + * Difficulty: Medium + * + * Given the root of a binary tree, return the length of the longest consecutive path in the tree. + * + * A consecutive path is a path where the values of the consecutive nodes in the path differ by one. + * This path can be either increasing or decreasing. + * - For example, [1,2,3,4] and [4,3,2,1] are both considered valid, but the path [1,2,4,3] is + * not valid. + * + * On the other hand, the path can be in the child-Parent-child order, where not necessarily be + * parent-child order. + */ + +/** + * 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} + */ +var longestConsecutive = function(root) { + let maxLength = 0; + traverse(root); + return maxLength; + + function traverse(node) { + if (!node) return [0, 0]; + + let inc = 1; + let dec = 1; + + if (node.left) { + const [leftInc, leftDec] = traverse(node.left); + if (node.val === node.left.val + 1) { + dec = Math.max(dec, leftDec + 1); + } else if (node.val === node.left.val - 1) { + inc = Math.max(inc, leftInc + 1); + } + } + + if (node.right) { + const [rightInc, rightDec] = traverse(node.right); + if (node.val === node.right.val + 1) { + dec = Math.max(dec, rightDec + 1); + } else if (node.val === node.right.val - 1) { + inc = Math.max(inc, rightInc + 1); + } + } + + maxLength = Math.max(maxLength, inc + dec - 1); + return [inc, dec]; + } +}; diff --git a/solutions/0555-split-concatenated-strings.js b/solutions/0555-split-concatenated-strings.js new file mode 100644 index 00000000..9f353e18 --- /dev/null +++ b/solutions/0555-split-concatenated-strings.js @@ -0,0 +1,50 @@ +/** + * 555. Split Concatenated Strings + * https://leetcode.com/problems/split-concatenated-strings/ + * Difficulty: Medium + * + * You are given an array of strings strs. You could concatenate these strings together into a + * loop, where for each string, you could choose to reverse it or not. Among all the possible loops + * + * Return the lexicographically largest string after cutting the loop, which will make the looped + * string into a regular one. + * + * + * Specifically, to find the lexicographically largest string, you need to experience two phases: + * 1. Concatenate all the strings into a loop, where you can reverse some strings or not and connect + * them in the same order as given. + * 2. Cut and make one breakpoint in any place of the loop, which will make the looped string into + * a regular one starting from the character at the cutpoint. + * + * And your job is to find the lexicographically largest one among all the possible regular strings. + */ + +/** + * @param {string[]} strs + * @return {string} + */ +var splitLoopedString = function(strs) { + const normalized = strs.map(str => { + const reversed = str.split('').reverse().join(''); + return str > reversed ? str : reversed; + }); + + let result = ''; + for (let i = 0; i < normalized.length; i++) { + const current = normalized[i]; + const prefix = normalized.slice(i + 1).join('') + normalized.slice(0, i).join(''); + const original = current; + const reversed = current.split('').reverse().join(''); + + for (const str of [original, reversed]) { + for (let j = 0; j <= str.length; j++) { + const candidate = str.slice(j) + prefix + str.slice(0, j); + if (candidate > result) { + result = candidate; + } + } + } + } + + return result; +}; diff --git a/solutions/0562-longest-line-of-consecutive-one-in-matrix.js b/solutions/0562-longest-line-of-consecutive-one-in-matrix.js new file mode 100644 index 00000000..601f0203 --- /dev/null +++ b/solutions/0562-longest-line-of-consecutive-one-in-matrix.js @@ -0,0 +1,35 @@ +/** + * 562. Longest Line of Consecutive One in Matrix + * https://leetcode.com/problems/longest-line-of-consecutive-one-in-matrix/ + * Difficulty: Medium + * + * Given an m x n binary matrix mat, return the length of the longest line of consecutive one + * in the matrix. + * + * The line could be horizontal, vertical, diagonal, or anti-diagonal. + */ + +/** + * @param {number[][]} mat + * @return {number} + */ +var longestLine = function(mat) { + const rows = mat.length; + const cols = mat[0].length; + const dp = new Array(rows).fill().map(() => new Array(cols).fill().map(() => [0, 0, 0, 0])); + let maxLength = 0; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (mat[i][j] === 1) { + dp[i][j][0] = j > 0 ? dp[i][j - 1][0] + 1 : 1; + dp[i][j][1] = i > 0 ? dp[i - 1][j][1] + 1 : 1; + dp[i][j][2] = (i > 0 && j > 0) ? dp[i - 1][j - 1][2] + 1 : 1; + dp[i][j][3] = (i > 0 && j < cols - 1) ? dp[i - 1][j + 1][3] + 1 : 1; + maxLength = Math.max(maxLength, ...dp[i][j]); + } + } + } + + return maxLength; +}; diff --git a/solutions/0568-maximum-vacation-days.js b/solutions/0568-maximum-vacation-days.js new file mode 100644 index 00000000..3ad9a277 --- /dev/null +++ b/solutions/0568-maximum-vacation-days.js @@ -0,0 +1,61 @@ +/** + * 568. Maximum Vacation Days + * https://leetcode.com/problems/maximum-vacation-days/ + * Difficulty: Hard + * + * LeetCode wants to give one of its best employees the option to travel among n cities to collect + * algorithm problems. But all work and no play makes Jack a dull boy, you could take vacations in + * some particular cities and weeks. Your job is to schedule the traveling to maximize the number + * of vacation days you could take, but there are certain rules and restrictions you need to follow. + * + * Rules and restrictions: + * 1. You can only travel among n cities, represented by indexes from 0 to n - 1. Initially, you + * are in the city indexed 0 on Monday. + * 2. The cities are connected by flights. The flights are represented as an n x n matrix (not + * necessarily symmetrical), called flights representing the airline status from the city i to + * the city j. If there is no flight from the city i to the city j, flights[i][j] == 0; + * Otherwise, flights[i][j] == 1. Also, flights[i][i] == 0 for all i. + * 3. You totally have k weeks (each week has seven days) to travel. You can only take flights at + * most once per day and can only take flights on each week's Monday morning. Since flight time + * is so short, we do not consider the impact of flight time. + * 4. For each city, you can only have restricted vacation days in different weeks, given an n x k + * matrix called days representing this relationship. For the value of days[i][j], it represents + * the maximum days you could take a vacation in the city i in the week j. + * 5. You could stay in a city beyond the number of vacation days, but you should work on the extra + * days, which will not be counted as vacation days. + * 6. If you fly from city A to city B and take the vacation on that day, the deduction towards + * vacation days will count towards the vacation days of city B in that week. + * 7. We do not consider the impact of flight hours on the calculation of vacation days. + * + * Given the two matrices flights and days, return the maximum vacation days you could take during + * k weeks. + */ + +/** + * @param {number[][]} flights + * @param {number[][]} days + * @return {number} + */ +var maxVacationDays = function(flights, days) { + const cities = flights.length; + const weeks = days[0].length; + const dp = new Array(weeks + 1).fill().map(() => new Array(cities).fill(-Infinity)); + + dp[0][0] = 0; + + for (let week = 1; week <= weeks; week++) { + for (let currCity = 0; currCity < cities; currCity++) { + for (let prevCity = 0; prevCity < cities; prevCity++) { + if (dp[week - 1][prevCity] !== -Infinity + && (flights[prevCity][currCity] || prevCity === currCity)) { + dp[week][currCity] = Math.max( + dp[week][currCity], + dp[week - 1][prevCity] + days[currCity][week - 1] + ); + } + } + } + } + + return Math.max(0, ...dp[weeks]); +}; diff --git a/solutions/0573-squirrel-simulation.js b/solutions/0573-squirrel-simulation.js new file mode 100644 index 00000000..0e6c74c9 --- /dev/null +++ b/solutions/0573-squirrel-simulation.js @@ -0,0 +1,44 @@ +/** + * 573. Squirrel Simulation + * https://leetcode.com/problems/squirrel-simulation/ + * Difficulty: Medium + * + * You are given two integers height and width representing a garden of size height x width. + * You are also given: + * - an array tree where tree = [treer, treec] is the position of the tree in the garden, + * - an array squirrel where squirrel = [squirrelr, squirrelc] is the position of the squirrel + * in the garden, + * - and an array nuts where nuts[i] = [nutir, nutic] is the position of the ith nut in the garden. + * + * The squirrel can only take at most one nut at one time and can move in four directions: up, down, + * left, and right, to the adjacent cell. + * + * Return the minimal distance for the squirrel to collect all the nuts and put them under the tree + * one by one. + * + * The distance is the number of moves. + */ + +/** + * @param {number} height + * @param {number} width + * @param {number[]} tree + * @param {number[]} squirrel + * @param {number[][]} nuts + * @return {number} + */ +var minDistance = function(height, width, tree, squirrel, nuts) { + const helper = (p1, p2) => Math.abs(p1[0] - p2[0]) + Math.abs(p1[1] - p2[1]); + + let totalDistance = 0; + let maxSaving = -Infinity; + + for (const nut of nuts) { + const nutToTree = helper(nut, tree); + totalDistance += 2 * nutToTree; + const squirrelToNut = helper(squirrel, nut); + maxSaving = Math.max(maxSaving, nutToTree - squirrelToNut); + } + + return totalDistance - maxSaving; +}; diff --git a/solutions/0582-kill-process.js b/solutions/0582-kill-process.js new file mode 100644 index 00000000..bc550c4f --- /dev/null +++ b/solutions/0582-kill-process.js @@ -0,0 +1,46 @@ +/** + * 582. Kill Process + * https://leetcode.com/problems/kill-process/ + * Difficulty: Medium + * + * You have n processes forming a rooted tree structure. You are given two integer arrays pid + * and ppid, where pid[i] is the ID of the ith process and ppid[i] is the ID of the ith process's + * parent process. + * + * Each process has only one parent process but may have multiple children processes. Only one + * process has ppid[i] = 0, which means this process has no parent process (the root of the tree). + * + * When a process is killed, all of its children processes will also be killed. + * + * Given an integer kill representing the ID of a process you want to kill, return a list of the + * IDs of the processes that will be killed. You may return the answer in any order. + */ + +/** + * @param {number[]} pid + * @param {number[]} ppid + * @param {number} kill + * @return {number[]} + */ +var killProcess = function(pid, ppid, kill) { + const map = new Map(); + for (let i = 0; i < ppid.length; i++) { + if (!map.has(ppid[i])) { + map.set(ppid[i], []); + } + map.get(ppid[i]).push(pid[i]); + } + + const result = []; + traverse(kill); + return result; + + function traverse(process) { + result.push(process); + if (map.has(process)) { + for (const child of map.get(process)) { + traverse(child); + } + } + } +}; diff --git a/solutions/0588-design-in-memory-file-system.js b/solutions/0588-design-in-memory-file-system.js new file mode 100644 index 00000000..a3e2e20a --- /dev/null +++ b/solutions/0588-design-in-memory-file-system.js @@ -0,0 +1,97 @@ +/** + * 588. Design In-Memory File System + * https://leetcode.com/problems/design-in-memory-file-system/ + * Difficulty: Hard + * + * Design a data structure that simulates an in-memory file system. + * + * Implement the FileSystem class: + * - FileSystem() Initializes the object of the system. + * - List ls(String path) + * - If path is a file path, returns a list that only contains this file's name. + * - If path is a directory path, returns the list of file and directory names in this directory. + * - The answer should in lexicographic order. + * - void mkdir(String path) Makes a new directory according to the given path. The given directory + * path does not exist. If the middle directories in the path do not exist, you should create + * them as well. + * - void addContentToFile(String filePath, String content) + * - If filePath does not exist, creates that file containing given content. + * - If filePath already exists, appends the given content to original content. + * - String readContentFromFile(String filePath) Returns the content in the file at filePath. + */ + +var FileSystem = function() { + this.root = new Map(); +}; + +/** + * @param {string} path + * @return {string[]} + */ +FileSystem.prototype.ls = function(path) { + const parts = path === '/' ? [] : path.split('/').slice(1); + let current = this.root; + + for (const part of parts) { + current = current.get(part); + } + + if (typeof current === 'string') { + return [parts[parts.length - 1]]; + } + + return Array.from(current.keys()).sort(); +}; + +/** + * @param {string} path + * @return {void} + */ +FileSystem.prototype.mkdir = function(path) { + const parts = path.split('/').slice(1); + let current = this.root; + + for (const part of parts) { + if (!current.has(part)) { + current.set(part, new Map()); + } + current = current.get(part); + } +}; + +/** + * @param {string} filePath + * @param {string} content + * @return {void} + */ +FileSystem.prototype.addContentToFile = function(filePath, content) { + const parts = filePath.split('/').slice(1); + const fileName = parts.pop(); + let current = this.root; + + for (const part of parts) { + if (!current.has(part)) { + current.set(part, new Map()); + } + current = current.get(part); + } + + const existingContent = current.get(fileName) || ''; + current.set(fileName, existingContent + content); +}; + +/** + * @param {string} filePath + * @return {string} + */ +FileSystem.prototype.readContentFromFile = function(filePath) { + const parts = filePath.split('/').slice(1); + const fileName = parts.pop(); + let current = this.root; + + for (const part of parts) { + current = current.get(part); + } + + return current.get(fileName); +}; diff --git a/solutions/0604-design-compressed-string-iterator.js b/solutions/0604-design-compressed-string-iterator.js new file mode 100644 index 00000000..e79f8beb --- /dev/null +++ b/solutions/0604-design-compressed-string-iterator.js @@ -0,0 +1,65 @@ +/** + * 604. Design Compressed String Iterator + * https://leetcode.com/problems/design-compressed-string-iterator/ + * Difficulty: Easy + * + * Design and implement a data structure for a compressed string iterator. The given compressed + * string will be in the form of each letter followed by a positive integer representing the + * number of this letter existing in the original uncompressed string. + * + * Implement the StringIterator class: + * - next() Returns the next character if the original string still has uncompressed characters, + * otherwise returns a white space. + * - hasNext() Returns true if there is any letter needs to be uncompressed in the original string, + * otherwise returns false. + */ + +/** + * @param {string} compressedString + */ +var StringIterator = function(compressedString) { + this.segments = []; + this.currentIndex = 0; + this.currentCount = 0; + + let i = 0; + while (i < compressedString.length) { + const character = compressedString[i]; + i++; + let count = ''; + while (i < compressedString.length && /\d/.test(compressedString[i])) { + count += compressedString[i]; + i++; + } + this.segments.push([character, parseInt(count)]); + } +}; + +/** + * @return {character} + */ +StringIterator.prototype.next = function() { + if (!this.hasNext()) { + return ' '; + } + + if (this.currentCount === 0) { + this.currentCount = this.segments[this.currentIndex][1]; + } + + const character = this.segments[this.currentIndex][0]; + this.currentCount--; + + if (this.currentCount === 0) { + this.currentIndex++; + } + + return character; +}; + +/** + * @return {boolean} + */ +StringIterator.prototype.hasNext = function() { + return this.currentIndex < this.segments.length; +}; diff --git a/solutions/0616-add-bold-tag-in-string.js b/solutions/0616-add-bold-tag-in-string.js new file mode 100644 index 00000000..563c80c5 --- /dev/null +++ b/solutions/0616-add-bold-tag-in-string.js @@ -0,0 +1,61 @@ +/** + * 616. Add Bold Tag in String + * https://leetcode.com/problems/add-bold-tag-in-string/ + * Difficulty: Medium + * + * You are given a string s and an array of strings words. + * + * You should add a closed pair of bold tag and to wrap the substrings in s that + * exist in words. + * - If two such substrings overlap, you should wrap them together with only one pair of + * closed bold-tag. + * - If two substrings wrapped by bold tags are consecutive, you should combine them. + * + * Return s after adding the bold tags. + */ + +/** + * @param {string} s + * @param {string[]} words + * @return {string} + */ +var addBoldTag = function(s, words) { + const boldIntervals = []; + + for (const word of words) { + let start = s.indexOf(word); + while (start !== -1) { + boldIntervals.push([start, start + word.length]); + start = s.indexOf(word, start + 1); + } + } + + if (!boldIntervals.length) return s; + + boldIntervals.sort((a, b) => a[0] - b[0] || a[1] - b[1]); + + const mergedIntervals = []; + let [currentStart, currentEnd] = boldIntervals[0]; + + for (let i = 1; i < boldIntervals.length; i++) { + const [nextStart, nextEnd] = boldIntervals[i]; + if (nextStart <= currentEnd) { + currentEnd = Math.max(currentEnd, nextEnd); + } else { + mergedIntervals.push([currentStart, currentEnd]); + [currentStart, currentEnd] = [nextStart, nextEnd]; + } + } + mergedIntervals.push([currentStart, currentEnd]); + + let result = ''; + let lastEnd = 0; + for (const [start, end] of mergedIntervals) { + result += s.slice(lastEnd, start) + '' + s.slice(start, end) + ''; + lastEnd = end; + } + + result += s.slice(lastEnd); + + return result; +}; diff --git a/solutions/0625-minimum-factorization.js b/solutions/0625-minimum-factorization.js new file mode 100644 index 00000000..80019298 --- /dev/null +++ b/solutions/0625-minimum-factorization.js @@ -0,0 +1,35 @@ +/** + * 625. Minimum Factorization + * https://leetcode.com/problems/minimum-factorization/ + * Difficulty: Medium + * + * Given a positive integer num, return the smallest positive integer x whose multiplication + * of each digit equals num. If there is no answer or the answer is not fit in 32-bit signed + * integer, return 0. + */ + +/** + * @param {number} num + * @return {number} + */ +var smallestFactorization = function(num) { + if (num < 2) return num; + + const digits = []; + for (let divisor = 9; divisor > 1; divisor--) { + while (num % divisor === 0) { + digits.push(divisor); + num /= divisor; + } + } + + if (num > 1) return 0; + + let result = 0; + for (const digit of digits.reverse()) { + result = result * 10 + digit; + if (result > 2**31 - 1) return 0; + } + + return result; +}; diff --git a/solutions/0631-design-excel-sum-formula.js b/solutions/0631-design-excel-sum-formula.js new file mode 100644 index 00000000..83af1528 --- /dev/null +++ b/solutions/0631-design-excel-sum-formula.js @@ -0,0 +1,141 @@ +/** + * 631. Design Excel Sum Formula + * https://leetcode.com/problems/design-excel-sum-formula/ + * Difficulty: Hard + * + * Design the basic function of Excel and implement the function of the sum formula. + * + * Implement the Excel class: + * - Excel(int height, char width) Initializes the object with the height and the width + * of the sheet. The sheet is an integer matrix mat of size height x width with the row + * index in the range [1, height] and the column index in the range ['A', width]. All the + * values should be zero initially. + * - void set(int row, char column, int val) Changes the value at mat[row][column] to be val. + * - int get(int row, char column) Returns the value at mat[row][column]. + * - int sum(int row, char column, List numbers) Sets the value at mat[row][column] to + * be the sum of cells represented by numbers and returns the value at mat[row][column]. + * This sum formula should exist until this cell is overlapped by another value or another + * sum formula. numbers[i] could be on the format: + * - "ColRow" that represents a single cell. + * - For example, "F7" represents the cell mat[7]['F']. + * - "ColRow1:ColRow2" that represents a range of cells. The range will always be a rectangle + * where "ColRow1" represent the position of the top-left cell, and "ColRow2" represents the + * position of the bottom-right cell. + * - For example, "B3:F7" represents the cells mat[i][j] for 3 <= i <= 7 and 'B' <= j <= 'F'. + * + * Note: You could assume that there will not be any circular sum reference. + * + * For example, mat[1]['A'] == sum(1, "B") and mat[1]['B'] == sum(1, "A"). + */ + +/** + * @param {number} height + * @param {character} width + */ +var Excel = function(height, width) { + this.height = height; + this.width = width.charCodeAt(0) - 64; + this.matrix = new Array(height).fill().map(() => new Array(this.width).fill(0)); + this.formulas = new Map(); + this.dependencies = new Map(); +}; + +/** + * @param {number} row + * @param {character} column + * @param {number} val + * @return {void} + */ +Excel.prototype.set = function(row, column, val) { + const col = column.charCodeAt(0) - 65; + const key = `${row}:${column}`; + this.matrix[row - 1][col] = val; + if (this.formulas.has(key)) { + this.formulas.delete(key); + this.dependencies.get(key)?.delete(key); + } + this.updateDependents(row, column); +}; + +/** + * @param {number} row + * @param {character} column + * @return {number} + */ +Excel.prototype.get = function(row, column) { + const col = column.charCodeAt(0) - 65; + return this.matrix[row - 1][col]; +}; + +/** + * @param {number} row + * @param {character} column + * @param {string[]} numbers + * @return {number} + */ +Excel.prototype.sum = function(row, column, numbers) { + const col = column.charCodeAt(0) - 65; + const cellKey = `${row}:${column}`; + const cells = []; + + for (const num of numbers) { + if (num.includes(':')) { + const [start, end] = num.split(':'); + const startCol = start[0].charCodeAt(0) - 65; + const startRow = parseInt(start.slice(1)) - 1; + const endCol = end[0].charCodeAt(0) - 65; + const endRow = parseInt(end.slice(1)) - 1; + + for (let r = startRow; r <= endRow; r++) { + for (let c = startCol; c <= endCol; c++) { + cells.push([r, c]); + } + } + } else { + const c = num[0].charCodeAt(0) - 65; + const r = parseInt(num.slice(1)) - 1; + cells.push([r, c]); + } + } + + if (this.formulas.has(cellKey)) { + for (const [r, c] of this.formulas.get(cellKey)) { + const depKey = `${r + 1}:${String.fromCharCode(c + 65)}`; + this.dependencies.get(depKey)?.delete(cellKey); + } + } + + this.formulas.set(cellKey, cells); + for (const [r, c] of cells) { + const depKey = `${r + 1}:${String.fromCharCode(c + 65)}`; + if (!this.dependencies.has(depKey)) { + this.dependencies.set(depKey, new Set()); + } + this.dependencies.get(depKey).add(cellKey); + } + + const total = this.calculateSum(cells); + this.matrix[row - 1][col] = total; + this.updateDependents(row, column); + return total; +}; + +Excel.prototype.calculateSum = function(cells) { + return cells.reduce((sum, [r, c]) => sum + this.matrix[r][c], 0); +}; + +Excel.prototype.updateDependents = function(row, column) { + const key = `${row}:${column}`; + if (!this.dependencies.has(key)) return; + + for (const depKey of this.dependencies.get(key)) { + const [depRow, depCol] = depKey.split(':'); + const col = depCol.charCodeAt(0) - 65; + const cells = this.formulas.get(depKey); + if (cells) { + const newSum = this.calculateSum(cells); + this.matrix[parseInt(depRow) - 1][col] = newSum; + this.updateDependents(parseInt(depRow), depCol); + } + } +}; diff --git a/solutions/0634-find-the-derangement-of-an-array.js b/solutions/0634-find-the-derangement-of-an-array.js new file mode 100644 index 00000000..7efca728 --- /dev/null +++ b/solutions/0634-find-the-derangement-of-an-array.js @@ -0,0 +1,32 @@ +/** + * 634. Find the Derangement of An Array + * https://leetcode.com/problems/find-the-derangement-of-an-array/ + * Difficulty: Medium + * + * In combinatorial mathematics, a derangement is a permutation of the elements of a set, + * such that no element appears in its original position. + * + * You are given an integer n. There is originally an array consisting of n integers from + * 1 to n in ascending order, return the number of derangements it can generate. Since the + * answer may be huge, return it modulo 109 + 7. + */ + +/** + * @param {number} n + * @return {number} + */ +var findDerangement = function(n) { + const MOD = 1e9 + 7; + if (n === 1) return 0; + if (n === 2) return 1; + + let prev2 = 0; + let prev1 = 1; + for (let i = 3; i <= n; i++) { + const current = ((i - 1) * (prev1 + prev2)) % MOD; + prev2 = prev1; + prev1 = current; + } + + return prev1; +}; diff --git a/solutions/0635-design-log-storage-system.js b/solutions/0635-design-log-storage-system.js new file mode 100644 index 00000000..50a8b303 --- /dev/null +++ b/solutions/0635-design-log-storage-system.js @@ -0,0 +1,63 @@ +/** + * 635. Design Log Storage System + * https://leetcode.com/problems/design-log-storage-system/ + * Difficulty: Medium + * + * You are given several logs, where each log contains a unique ID and timestamp. Timestamp is a + * string that has the following format: Year:Month:Day:Hour:Minute:Second, for example, + * 2017:01:01:23:59:59. All domains are zero-padded decimal numbers. + * + * Implement the LogSystem class: + * - LogSystem() Initializes the LogSystem object. + * - void put(int id, string timestamp) Stores the given log (id, timestamp) in your storage system. + * - int[] retrieve(string start, string end, string granularity) Returns the IDs of the logs whose + * timestamps are within the range from start to end inclusive. start and end all have the same + * format as timestamp, and granularity means how precise the range should be (i.e. to the exact + * Day, Minute, etc.). For example, start = "2017:01:01:23:59:59", end = "2017:01:02:23:59:59", + * and granularity = "Day" means that we need to find the logs within the inclusive range from + * Jan. 1st 2017 to Jan. 2nd 2017, and the Hour, Minute, and Second for each log entry can be + * ignored. + */ + +var LogSystem = function() { + this.logs = []; + this.granularities = { + Year: 4, + Month: 7, + Day: 10, + Hour: 13, + Minute: 16, + Second: 19 + }; +}; + +/** + * @param {number} id + * @param {string} timestamp + * @return {void} + */ +LogSystem.prototype.put = function(id, timestamp) { + this.logs.push([timestamp, id]); +}; + +/** + * @param {string} start + * @param {string} end + * @param {string} granularity + * @return {number[]} + */ +LogSystem.prototype.retrieve = function(start, end, granularity) { + const precision = this.granularities[granularity]; + const startKey = start.slice(0, precision).padEnd(19, '0'); + const endKey = end.slice(0, precision).padEnd(19, '9'); + + const result = []; + for (const [timestamp, id] of this.logs) { + const key = timestamp.slice(0, precision).padEnd(19, '0'); + if (key >= startKey && key <= endKey) { + result.push(id); + } + } + + return result.sort((a, b) => a - b); +}; diff --git a/solutions/0642-design-search-autocomplete-system.js b/solutions/0642-design-search-autocomplete-system.js new file mode 100644 index 00000000..d6e63851 --- /dev/null +++ b/solutions/0642-design-search-autocomplete-system.js @@ -0,0 +1,97 @@ +/** + * 642. Design Search Autocomplete System + * https://leetcode.com/problems/design-search-autocomplete-system/ + * Difficulty: Hard + * + * Design a search autocomplete system for a search engine. Users may input a sentence (at + * least one word and end with a special character '#'). + * + * You are given a string array sentences and an integer array times both of length n where + * sentences[i] is a previously typed sentence and times[i] is the corresponding number of + * times the sentence was typed. For each input character except '#', return the top 3 + * historical hot sentences that have the same prefix as the part of the sentence already typed. + * + * Here are the specific rules: + * - The hot degree for a sentence is defined as the number of times a user typed the exactly + * same sentence before. + * - The returned top 3 hot sentences should be sorted by hot degree (The first is the hottest + * one). If several sentences have the same hot degree, use ASCII-code order (smaller one + * appears first). + * - If less than 3 hot sentences exist, return as many as you can. + * - When the input is a special character, it means the sentence ends, and in this case, you + * need to return an empty list. + * + * Implement the AutocompleteSystem class: + * - AutocompleteSystem(String[] sentences, int[] times) Initializes the object with the + * sentences and times arrays. + * - List input(char c) This indicates that the user typed the character c. + * - Returns an empty array [] if c == '#' and stores the inputted sentence in the system. + * - Returns the top 3 historical hot sentences that have the same prefix as the part of the + * sentence already typed. If there are fewer than 3 matches, return them all. + */ + +/** + * @param {string[]} sentences + * @param {number[]} times + */ +var AutocompleteSystem = function(sentences, times) { + this.trie = {}; + this.current = ''; + this.root = this.trie; + + for (let i = 0; i < sentences.length; i++) { + this.insert(sentences[i], times[i]); + } +}; + +/** + * @param {character} c + * @return {string[]} + */ +AutocompleteSystem.prototype.input = function(c) { + if (c === '#') { + this.insert(this.current, 1); + this.current = ''; + this.root = this.trie; + return []; + } + + this.current += c; + if (!this.root[c]) { + this.root[c] = {}; + this.root = this.root[c]; + return []; + } + + this.root = this.root[c]; + const candidates = []; + this.search(this.root, this.current, candidates); + + candidates.sort((a, b) => { + if (a.count !== b.count) return b.count - a.count; + return a.sentence < b.sentence ? -1 : 1; + }); + + return candidates.slice(0, 3).map(item => item.sentence); +}; + +AutocompleteSystem.prototype.insert = function(sentence, count) { + let node = this.trie; + for (const char of sentence) { + if (!node[char]) node[char] = {}; + node = node[char]; + } + node.isEnd = (node.isEnd || 0) + count; +}; + +AutocompleteSystem.prototype.search = function(node, prefix, candidates) { + if (node.isEnd) { + candidates.push({ sentence: prefix, count: node.isEnd }); + } + + for (const char in node) { + if (char !== 'isEnd') { + this.search(node[char], prefix + char, candidates); + } + } +}; diff --git a/solutions/0644-maximum-average-subarray-ii.js b/solutions/0644-maximum-average-subarray-ii.js new file mode 100644 index 00000000..b2f7549a --- /dev/null +++ b/solutions/0644-maximum-average-subarray-ii.js @@ -0,0 +1,54 @@ +/** + * 644. Maximum Average Subarray II + * https://leetcode.com/problems/maximum-average-subarray-ii/ + * Difficulty: Hard + * + * You are given an integer array nums consisting of n elements, and an integer k. + * + * Find a contiguous subarray whose length is greater than or equal to k that has the maximum + * average value and return this value. Any answer with a calculation error less than 10-5 will + * be accepted. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var findMaxAverage = function(nums, k) { + const n = nums.length; + let minVal = Math.min(...nums); + let maxVal = Math.max(...nums); + + while (maxVal - minVal > 1e-5) { + const mid = (minVal + maxVal) / 2; + if (canFindLargerAverage(nums, k, mid)) { + minVal = mid; + } else { + maxVal = mid; + } + } + + return minVal; +}; + +function canFindLargerAverage(nums, k, target) { + let sum = 0; + let prevSum = 0; + let minPrevSum = 0; + + for (let i = 0; i < k; i++) { + sum += nums[i] - target; + } + + if (sum >= 0) return true; + + for (let i = k; i < nums.length; i++) { + sum += nums[i] - target; + prevSum += nums[i - k] - target; + minPrevSum = Math.min(minPrevSum, prevSum); + if (sum - minPrevSum >= 0) return true; + } + + return false; +} diff --git a/solutions/0651-4-keys-keyboard.js b/solutions/0651-4-keys-keyboard.js new file mode 100644 index 00000000..5420a8c9 --- /dev/null +++ b/solutions/0651-4-keys-keyboard.js @@ -0,0 +1,31 @@ +/** + * 651. 4 Keys Keyboard + * https://leetcode.com/problems/4-keys-keyboard/ + * Difficulty: Medium + * + * Imagine you have a special keyboard with the following keys: + * - A: Print one 'A' on the screen. + * - Ctrl-A: Select the whole screen. + * - Ctrl-C: Copy selection to buffer. + * - Ctrl-V: Print buffer on screen appending it after what has already been printed. + * + * Given an integer n, return the maximum number of 'A' you can print on the screen with at + * most n presses on the keys. + */ + +/** + * @param {number} n + * @return {number} + */ +var maxA = function(n) { + const dp = new Array(n + 1).fill(0); + + for (let i = 1; i <= n; i++) { + dp[i] = dp[i - 1] + 1; + for (let j = 2; j < i; j++) { + dp[i] = Math.max(dp[i], dp[j - 2] * (i - j + 1)); + } + } + + return dp[n]; +}; diff --git a/solutions/0656-coin-path.js b/solutions/0656-coin-path.js new file mode 100644 index 00000000..f5c3e9ee --- /dev/null +++ b/solutions/0656-coin-path.js @@ -0,0 +1,88 @@ +/** + * 656. Coin Path + * https://leetcode.com/problems/coin-path/ + * Difficulty: Hard + * + * You are given an integer array coins (1-indexed) of length n and an integer maxJump. You can + * jump to any index i of the array coins if coins[i] != -1 and you have to pay coins[i] when you + * visit index i. In addition to that, if you are currently at index i, you can only jump to any + * index i + k where i + k <= n and k is a value in the range [1, maxJump]. + * + * You are initially positioned at index 1 (coins[1] is not -1). You want to find the path that + * reaches index n with the minimum cost. + * + * Return an integer array of the indices that you will visit in order so that you can reach + * index n with the minimum cost. If there are multiple paths with the same cost, return the + * lexicographically smallest such path. If it is not possible to reach index n, return an + * empty array. + * + * A path p1 = [Pa1, Pa2, ..., Pax] of length x is lexicographically smaller than + * p2 = [Pb1, Pb2, ..., Pbx] of length y, if and only if at the first j where Paj and Pbj + * differ, Paj < Pbj; when no such j exists, then x < y. + */ + +/** + * @param {number[]} coins + * @param {number} maxJump + * @return {number[]} + */ +var cheapestJump = function(coins, maxJump) { + const n = coins.length; + const minCost = new Array(n + 1).fill(Infinity); + const parent = new Array(n + 1).fill(-1); + + minCost[1] = coins[0]; + + for (let i = 1; i <= n; i++) { + if (coins[i - 1] === -1 || minCost[i] === Infinity) continue; + + for (let j = i + 1; j <= Math.min(i + maxJump, n); j++) { + if (coins[j - 1] === -1) continue; + + const newCost = minCost[i] + coins[j - 1]; + if (newCost < minCost[j]) { + minCost[j] = newCost; + parent[j] = i; + } else if (newCost === minCost[j] && parent[j] !== -1) { + const currentPath = buildPath(parent, j); + const newPath = buildPath(parent, j, i); + if (compare(newPath, currentPath)) { + parent[j] = i; + } + } + } + } + + if (minCost[n] === Infinity) return []; + + const result = []; + let current = n; + while (current !== -1) { + result.unshift(current); + current = parent[current]; + } + + return result; +}; + +function buildPath(parent, end, newParent = null) { + const path = []; + let current = end; + if (newParent !== null) { + path.unshift(current); + current = newParent; + } + while (current !== -1) { + path.unshift(current); + current = parent[current]; + } + return path; +} + +function compare(path1, path2) { + for (let i = 0; i < Math.min(path1.length, path2.length); i++) { + if (path1[i] < path2[i]) return true; + if (path1[i] > path2[i]) return false; + } + return path1.length < path2.length; +} diff --git a/solutions/0660-remove-9.js b/solutions/0660-remove-9.js new file mode 100644 index 00000000..02b239a0 --- /dev/null +++ b/solutions/0660-remove-9.js @@ -0,0 +1,28 @@ +/** + * 660. Remove 9 + * https://leetcode.com/problems/remove-9/ + * Difficulty: Hard + * + * Start from integer 1, remove any integer that contains 9 such as 9, 19, 29... + * + * Now, you will have a new integer sequence [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, ...]. + * + * Given an integer n, return the nth (1-indexed) integer in the new sequence. + */ + +/** + * @param {number} n + * @return {number} + */ +var newInteger = function(n) { + let result = 0; + let base = 1; + + while (n > 0) { + result += (n % 9) * base; + n = Math.floor(n / 9); + base *= 10; + } + + return result; +}; diff --git a/solutions/0663-equal-tree-partition.js b/solutions/0663-equal-tree-partition.js new file mode 100644 index 00000000..7c93c6e1 --- /dev/null +++ b/solutions/0663-equal-tree-partition.js @@ -0,0 +1,41 @@ +/** + * 663. Equal Tree Partition + * https://leetcode.com/problems/equal-tree-partition/ + * Difficulty: Medium + * + * Given the root of a binary tree, return true if you can partition the tree into two trees + * with equal sums of values after removing exactly one edge on the original tree. + */ + +/** + * 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 {boolean} + */ +var checkEqualTree = function(root) { + const subtreeSums = new Set(); + const totalSum = calculateSum(root); + + return totalSum % 2 === 0 && subtreeSums.has(totalSum / 2); + + function calculateSum(node) { + if (!node) return 0; + + const leftSum = calculateSum(node.left); + const rightSum = calculateSum(node.right); + const currentSum = node.val + leftSum + rightSum; + + if (node !== root) { + subtreeSums.add(currentSum); + } + + return currentSum; + } +}; diff --git a/solutions/0666-path-sum-iv.js b/solutions/0666-path-sum-iv.js new file mode 100644 index 00000000..b3f637a5 --- /dev/null +++ b/solutions/0666-path-sum-iv.js @@ -0,0 +1,52 @@ +/** + * 666. Path Sum IV + * https://leetcode.com/problems/path-sum-iv/ + * Difficulty: Medium + * + * If the depth of a tree is smaller than 5, then this tree can be represented by an array + * of three-digit integers. You are given an ascending array nums consisting of three-digit + * integers representing a binary tree with a depth smaller than 5, where for each integer: + * - The hundreds digit represents the depth d of this node, where 1 <= d <= 4. + * - The tens digit represents the position p of this node within its level, where 1 <= p <= 8, + * corresponding to its position in a full binary tree. + * - The units digit represents the value v of this node, where 0 <= v <= 9. + * + * Return the sum of all paths from the root towards the leaves. + * + * It is guaranteed that the given array represents a valid connected binary tree. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var pathSum = function(nums) { + const nodeMap = new Map(); + + for (const num of nums) { + const depth = Math.floor(num / 100); + const position = Math.floor((num % 100) / 10); + const value = num % 10; + nodeMap.set(`${depth}-${position}`, value); + } + + return dfs(1, 1, 0); + + function dfs(depth, position, currentSum) { + const key = `${depth}-${position}`; + if (!nodeMap.has(key)) return 0; + + const nodeValue = nodeMap.get(key); + const pathSum = currentSum + nodeValue; + + const leftChild = `${depth + 1}-${position * 2 - 1}`; + const rightChild = `${depth + 1}-${position * 2}`; + + if (!nodeMap.has(leftChild) && !nodeMap.has(rightChild)) { + return pathSum; + } + + return dfs(depth + 1, position * 2 - 1, pathSum) + + dfs(depth + 1, position * 2, pathSum); + } +}; diff --git a/solutions/0681-next-closest-time.js b/solutions/0681-next-closest-time.js new file mode 100644 index 00000000..78d06313 --- /dev/null +++ b/solutions/0681-next-closest-time.js @@ -0,0 +1,50 @@ +/** + * 681. Next Closest Time + * https://leetcode.com/problems/next-closest-time/ + * Difficulty: Medium + * + * Given a time represented in the format "HH:MM", form the next closest time by reusing the + * current digits. There is no limit on how many times a digit can be reused. + * + * You may assume the given input string is always valid. For example, "01:34", "12:09" are + * all valid. "1:34", "12:9" are all invalid. + */ + +/** + * @param {string} time + * @return {string} + */ +var nextClosestTime = function(time) { + const digits = new Set(time.replace(':', '')); + const sortedDigits = [...digits].sort(); + + return generateNextTime(time); + + function isValidTime(h, m) { + return h < 24 && m < 60; + } + + function generateNextTime(timeStr) { + const [hours, minutes] = timeStr.split(':'); + + for (let i = 3; i >= 0; i--) { + const pos = i < 2 ? i : i + 1; + const currentDigit = timeStr[pos]; + + for (const digit of sortedDigits) { + if (digit > currentDigit) { + const newTime = timeStr.substring(0, pos) + digit + timeStr.substring(pos + 1); + const [h, m] = newTime.split(':').map(Number); + if (isValidTime(h, m)) { + return newTime; + } + } + } + + const newTime = timeStr.substring(0, pos) + sortedDigits[0] + timeStr.substring(pos + 1); + timeStr = newTime; + } + + return sortedDigits[0].repeat(2) + ':' + sortedDigits[0].repeat(2); + } +}; diff --git a/solutions/0683-k-empty-slots.js b/solutions/0683-k-empty-slots.js new file mode 100644 index 00000000..f3b23181 --- /dev/null +++ b/solutions/0683-k-empty-slots.js @@ -0,0 +1,55 @@ +/** + * 683. K Empty Slots + * https://leetcode.com/problems/k-empty-slots/ + * Difficulty: Hard + * + * You have n bulbs in a row numbered from 1 to n. Initially, all the bulbs are turned off. + * We turn on exactly one bulb every day until all bulbs are on after n days. + * + * You are given an array bulbs of length n where bulbs[i] = x means that on the (i+1)th day, + * we will turn on the bulb at position x where i is 0-indexed and x is 1-indexed. + * + * Given an integer k, return the minimum day number such that there exists two turned on + * bulbs that have exactly k bulbs between them that are all turned off. If there isn't + * such day, return -1. + */ + +/** + * @param {number[]} bulbs + * @param {number} k + * @return {number} + */ +var kEmptySlots = function(bulbs, k) { + const days = new Array(bulbs.length + 1); + + for (let i = 0; i < bulbs.length; i++) { + days[bulbs[i]] = i + 1; + } + + let left = 1; + let right = k + 2; + let minDay = Infinity; + + while (right <= bulbs.length) { + let mid = left + 1; + let isValid = true; + + while (mid < right) { + if (days[mid] < Math.max(days[left], days[right])) { + isValid = false; + left = mid; + right = mid + k + 1; + break; + } + mid++; + } + + if (isValid) { + minDay = Math.min(minDay, Math.max(days[left], days[right])); + left++; + right++; + } + } + + return minDay === Infinity ? -1 : minDay; +}; diff --git a/solutions/0694-number-of-distinct-islands.js b/solutions/0694-number-of-distinct-islands.js new file mode 100644 index 00000000..cd7baca6 --- /dev/null +++ b/solutions/0694-number-of-distinct-islands.js @@ -0,0 +1,52 @@ +/** + * 694. Number of Distinct Islands + * https://leetcode.com/problems/number-of-distinct-islands/ + * Difficulty: Medium + * + * You are given an m x n binary matrix grid. 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. + * + * 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. + * + * Return the number of distinct islands. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var numDistinctIslands = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const visited = Array.from({ length: rows }, () => new Array(cols).fill(false)); + const islandShapes = new Set(); + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (grid[i][j] === 1 && !visited[i][j]) { + const shape = []; + dfs(i, j, i, j, shape); + islandShapes.add(shape.join('|')); + } + } + } + + return islandShapes.size; + + function dfs(row, col, baseRow, baseCol, shape) { + if (row < 0 || row >= rows || col < 0 || col >= cols + || visited[row][col] || grid[row][col] === 0) { + return; + } + + visited[row][col] = true; + shape.push(`${row - baseRow},${col - baseCol}`); + + dfs(row + 1, col, baseRow, baseCol, shape); + dfs(row - 1, col, baseRow, baseCol, shape); + dfs(row, col + 1, baseRow, baseCol, shape); + dfs(row, col - 1, baseRow, baseCol, shape); + } +}; diff --git a/solutions/0702-search-in-a-sorted-array-of-unknown-size.js b/solutions/0702-search-in-a-sorted-array-of-unknown-size.js new file mode 100644 index 00000000..865bda15 --- /dev/null +++ b/solutions/0702-search-in-a-sorted-array-of-unknown-size.js @@ -0,0 +1,49 @@ +/** + * 702. Search in a Sorted Array of Unknown Size + * https://leetcode.com/problems/search-in-a-sorted-array-of-unknown-size/ + * Difficulty: Medium + * + * This is an interactive problem. + * + * You have a sorted array of unique elements and an unknown size. You do not have an access + * to the array but you can use the ArrayReader interface to access it. You can call + * ArrayReader.get(i) that: + * - returns the value at the ith index (0-indexed) of the secret array (i.e., secret[i]), or + * - returns 231 - 1 if the i is out of the boundary of the array. + * + * You are also given an integer target. + * + * Return the index k of the hidden array where secret[k] == target or return -1 otherwise. + * + * You must write an algorithm with O(log n) runtime complexity. + */ + +/** + * @param {ArrayReader} reader + * @param {number} target + * @return {number} + */ +var search = function(reader, target) { + let left = 0; + let right = 1; + + while (reader.get(right) < target) { + left = right; + right *= 2; + } + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + const value = reader.get(mid); + + if (value === target) { + return mid; + } else if (value < target) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return -1; +}; diff --git a/solutions/0708-insert-into-a-sorted-circular-linked-list.js b/solutions/0708-insert-into-a-sorted-circular-linked-list.js new file mode 100644 index 00000000..ff17f2de --- /dev/null +++ b/solutions/0708-insert-into-a-sorted-circular-linked-list.js @@ -0,0 +1,53 @@ +/** + * 708. Insert into a Sorted Circular Linked List + * https://leetcode.com/problems/insert-into-a-sorted-circular-linked-list/ + * Difficulty: Medium + * + * Given a Circular Linked List node, which is sorted in non-descending order, write a + * function to insert a value insertVal into the list such that it remains a sorted + * circular list. The given node can be a reference to any single node in the list and + * may not necessarily be the smallest value in the circular list. + * + * If there are multiple suitable places for insertion, you may choose any place to + * insert the new value. After the insertion, the circular list should remain sorted. + * + * If the list is empty (i.e., the given node is null), you should create a new single + * circular list and return the reference to that single node. Otherwise, you should + * return the originally given node. + */ + +/** + * @param {_Node} head + * @param {number} insertVal + * @return {_Node} + */ +var insert = function(head, insertVal) { + const newNode = new _Node(insertVal, null); + + if (!head) { + newNode.next = newNode; + return newNode; + } + + if (head.next === head) { + newNode.next = head; + head.next = newNode; + return head; + } + + let prev = head; + let curr = head.next; + do { + if ((prev.val <= insertVal && insertVal <= curr.val) + || (prev.val > curr.val && (insertVal >= prev.val || insertVal <= curr.val))) { + break; + } + prev = curr; + curr = curr.next; + } while (prev !== head); + + prev.next = newNode; + newNode.next = curr; + + return head; +}; diff --git a/solutions/0711-number-of-distinct-islands-ii.js b/solutions/0711-number-of-distinct-islands-ii.js new file mode 100644 index 00000000..309f9d51 --- /dev/null +++ b/solutions/0711-number-of-distinct-islands-ii.js @@ -0,0 +1,82 @@ +/** + * 711. Number of Distinct Islands II + * https://leetcode.com/problems/number-of-distinct-islands-ii/ + * Difficulty: Hard + * + * You are given an m x n binary matrix grid. 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. + * + * An island is considered to be the same as another if they have the same shape, or have + * the same shape after rotation (90, 180, or 270 degrees only) or reflection (left/right + * direction or up/down direction). + * + * Return the number of distinct islands. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var numDistinctIslands2 = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const visited = Array.from({ length: rows }, () => new Array(cols).fill(false)); + const uniqueShapes = new Set(); + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (grid[i][j] === 1 && !visited[i][j]) { + const cells = []; + dfs(i, j, cells); + const canonical = normalize(cells); + uniqueShapes.add(canonical); + } + } + } + + return uniqueShapes.size; + + function dfs(row, col, cells) { + if (row < 0 || row >= rows || col < 0 || col >= cols + || visited[row][col] || grid[row][col] === 0) { + return; + } + + visited[row][col] = true; + cells.push([row, col]); + + dfs(row + 1, col, cells); + dfs(row - 1, col, cells); + dfs(row, col + 1, cells); + dfs(row, col - 1, cells); + } + + function normalize(cells) { + const transformations = [ + (r, c) => [r, c], + (r, c) => [r, -c], + (r, c) => [-r, c], + (r, c) => [-r, -c], + (r, c) => [c, r], + (r, c) => [c, -r], + (r, c) => [-c, r], + (r, c) => [-c, -r] + ]; + + const shapes = []; + + for (const transform of transformations) { + const transformed = cells.map(([r, c]) => transform(r, c)); + transformed.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]); + + const minR = transformed[0][0]; + const minC = transformed[0][1]; + const normalized = transformed.map(([r, c]) => [r - minR, c - minC]); + + shapes.push(normalized.map(([r, c]) => `${r},${c}`).join('|')); + } + + return shapes.sort()[0]; + } +}; diff --git a/solutions/0716-max-stack.js b/solutions/0716-max-stack.js new file mode 100644 index 00000000..f12bdc59 --- /dev/null +++ b/solutions/0716-max-stack.js @@ -0,0 +1,92 @@ +/** + * 716. Max Stack + * https://leetcode.com/problems/max-stack/ + * Difficulty: Hard + * + * Design a max stack data structure that supports the stack operations and supports finding + * the stack's maximum element. + * + * Implement the MaxStack class: + * - MaxStack() Initializes the stack object. + * - void push(int x) Pushes element x onto the stack. + * - int pop() Removes the element on top of the stack and returns it. + * - int top() Gets the element on the top of the stack without removing it. + * - int peekMax() Retrieves the maximum element in the stack without removing it. + * - int popMax() Retrieves the maximum element in the stack and removes it. If there is more + * than one maximum element, only remove the top-most one. + * + * You must come up with a solution that supports O(1) for each top call and O(logn) for each + * other call. + */ + +var MaxStack = function() { + this.stack = []; + this.maxHeap = new PriorityQueue((a, b) => a.val === b.val ? b.id - a.id : b.val - a.val); + this.nodeId = 0; + this.deleted = new Set(); +}; + +/** +* @param {number} x +* @return {void} +*/ +MaxStack.prototype.push = function(x) { + const id = this.nodeId++; + const node = { val: x, id }; + this.stack.push(node); + this.maxHeap.enqueue(node); +}; + +/** +* @return {number} +*/ +MaxStack.prototype.pop = function() { + this.cleanStack(); + const node = this.stack.pop(); + this.deleted.add(node.id); + return node.val; +}; + +/** +* @return {number} +*/ +MaxStack.prototype.top = function() { + this.cleanStack(); + return this.stack[this.stack.length - 1].val; +}; + +/** +* @return {number} +*/ +MaxStack.prototype.peekMax = function() { + this.cleanMaxHeap(); + return this.maxHeap.front().val; +}; + +/** +* @return {number} +*/ +MaxStack.prototype.popMax = function() { + this.cleanMaxHeap(); + const maxNode = this.maxHeap.dequeue(); + this.deleted.add(maxNode.id); + return maxNode.val; +}; + +/** +* @return {void} +*/ +MaxStack.prototype.cleanStack = function() { + while (this.stack.length && this.deleted.has(this.stack[this.stack.length - 1].id)) { + this.stack.pop(); + } +}; + +/** +* @return {void} +*/ +MaxStack.prototype.cleanMaxHeap = function() { + while (this.maxHeap.size() && this.deleted.has(this.maxHeap.front().id)) { + this.maxHeap.dequeue(); + } +}; diff --git a/solutions/0723-candy-crush.js b/solutions/0723-candy-crush.js new file mode 100644 index 00000000..39cd84ec --- /dev/null +++ b/solutions/0723-candy-crush.js @@ -0,0 +1,88 @@ +/** + * 723. Candy Crush + * https://leetcode.com/problems/candy-crush/ + * Difficulty: Medium + * + * This question is about implementing a basic elimination algorithm for Candy Crush. + * + * Given an m x n integer array board representing the grid of candy where board[i][j] represents + * the type of candy. A value of board[i][j] == 0 represents that the cell is empty. + * + * The given board represents the state of the game following the player's move. Now, you need to + * restore the board to a stable state by crushing candies according to the following rules: + * - If three or more candies of the same type are adjacent vertically or horizontally, crush them + * all at the same time - these positions become empty. + * - After crushing all candies simultaneously, if an empty space on the board has candies on top + * of itself, then these candies will drop until they hit a candy or bottom at the same time. + * No new candies will drop outside the top boundary. + * - After the above steps, there may exist more candies that can be crushed. If so, you need to + * repeat the above steps. + * - If there does not exist more candies that can be crushed (i.e., the board is stable), then + * return the current board. + * + * You need to perform the above rules until the board becomes stable, then return the stable board. + */ + +/** + * @param {number[][]} board + * @return {number[][]} + */ +var candyCrush = function(board) { + const rows = board.length; + const cols = board[0].length; + + while (markCrushables()) { + dropCandies(); + } + + return board; + + function markCrushables() { + let hasCrushables = false; + + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols - 2; col++) { + const candy = Math.abs(board[row][col]); + if (candy !== 0 && candy === Math.abs(board[row][col + 1]) + && candy === Math.abs(board[row][col + 2])) { + hasCrushables = true; + board[row][col] = -candy; + board[row][col + 1] = -candy; + board[row][col + 2] = -candy; + } + } + } + + for (let col = 0; col < cols; col++) { + for (let row = 0; row < rows - 2; row++) { + const candy = Math.abs(board[row][col]); + if (candy !== 0 && candy === Math.abs(board[row + 1][col]) + && candy === Math.abs(board[row + 2][col])) { + hasCrushables = true; + board[row][col] = -candy; + board[row + 1][col] = -candy; + board[row + 2][col] = -candy; + } + } + } + + return hasCrushables; + } + + function dropCandies() { + for (let col = 0; col < cols; col++) { + let bottom = rows - 1; + for (let row = rows - 1; row >= 0; row--) { + if (board[row][col] > 0) { + board[bottom][col] = board[row][col]; + if (bottom !== row) { + board[row][col] = 0; + } + bottom--; + } else if (board[row][col] < 0) { + board[row][col] = 0; + } + } + } + } +}; diff --git a/solutions/0727-minimum-window-subsequence.js b/solutions/0727-minimum-window-subsequence.js new file mode 100644 index 00000000..ddc0e2d4 --- /dev/null +++ b/solutions/0727-minimum-window-subsequence.js @@ -0,0 +1,46 @@ +/** + * 727. Minimum Window Subsequence + * https://leetcode.com/problems/minimum-window-subsequence/ + * Difficulty: Hard + * + * Given strings s1 and s2, return the minimum contiguous substring part of s1, so that + * s2 is a subsequence of the part. + * + * If there is no such window in s1 that covers all characters in s2, return the empty + * string "". If there are multiple such minimum-length windows, return the one with the + * left-most starting index. + */ + +/** + * @param {string} s1 + * @param {string} s2 + * @return {string} + */ +var minWindow = function(s1, s2) { + const n = s1.length; + const m = s2.length; + const dp = new Array(m + 1).fill().map(() => new Array(n + 1).fill(Infinity)); + dp[0][0] = 0; + + for (let j = 1; j <= n; j++) { + dp[0][j] = 0; + for (let i = 1; i <= m; i++) { + if (s1[j - 1] === s2[i - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + } else { + dp[i][j] = dp[i][j - 1] !== Infinity ? dp[i][j - 1] + 1 : Infinity; + } + } + } + + let minLength = Infinity; + let endIndex = -1; + for (let j = 1; j <= n; j++) { + if (dp[m][j] < minLength) { + minLength = dp[m][j]; + endIndex = j; + } + } + + return minLength === Infinity ? '' : s1.slice(endIndex - minLength, endIndex); +}; diff --git a/solutions/0734-sentence-similarity.js b/solutions/0734-sentence-similarity.js new file mode 100644 index 00000000..2beae535 --- /dev/null +++ b/solutions/0734-sentence-similarity.js @@ -0,0 +1,50 @@ +/** + * 734. Sentence Similarity + * https://leetcode.com/problems/sentence-similarity/ + * Difficulty: Easy + * + * We can represent a sentence as an array of words, for example, the sentence + * "I am happy with leetcode" can be represented as arr = ["I","am",happy","with","leetcode"]. + * + * Given two sentences sentence1 and sentence2 each represented as a string array and given an + * array of string pairs similarPairs where similarPairs[i] = [xi, yi] indicates that the two + * words xi and yi are similar. + * + * Return true if sentence1 and sentence2 are similar, or false if they are not similar. + * + * Two sentences are similar if: + * - They have the same length (i.e., the same number of words) + * - sentence1[i] and sentence2[i] are similar. + * + * Notice that a word is always similar to itself, also notice that the similarity relation is + * not transitive. For example, if the words a and b are similar, and the words b and c are + * similar, a and c are not necessarily similar. + */ + +/** + * @param {string[]} sentence1 + * @param {string[]} sentence2 + * @param {string[][]} similarPairs + * @return {boolean} + */ +var areSentencesSimilar = function(sentence1, sentence2, similarPairs) { + if (sentence1.length !== sentence2.length) { + return false; + } + + const similarWords = new Set(); + for (const [word1, word2] of similarPairs) { + similarWords.add(`${word1}:${word2}`); + similarWords.add(`${word2}:${word1}`); + } + + for (let i = 0; i < sentence1.length; i++) { + const word1 = sentence1[i]; + const word2 = sentence2[i]; + if (word1 !== word2 && !similarWords.has(`${word1}:${word2}`)) { + return false; + } + } + + return true; +}; diff --git a/solutions/0737-sentence-similarity-ii.js b/solutions/0737-sentence-similarity-ii.js new file mode 100644 index 00000000..cc370b6f --- /dev/null +++ b/solutions/0737-sentence-similarity-ii.js @@ -0,0 +1,69 @@ +/** + * 737. Sentence Similarity II + * https://leetcode.com/problems/sentence-similarity-ii/ + * Difficulty: Medium + * + * We can represent a sentence as an array of words, for example, the sentence + * "I am happy with leetcode" can be represented as arr = ["I","am",happy","with","leetcode"]. + * + * Given two sentences sentence1 and sentence2 each represented as a string array and given an + * array of string pairs similarPairs where similarPairs[i] = [xi, yi] indicates that the two + * words xi and yi are similar. + * + * Return true if sentence1 and sentence2 are similar, or false if they are not similar. + * + * Two sentences are similar if: + * - They have the same length (i.e., the same number of words) + * - sentence1[i] and sentence2[i] are similar. + * + * Notice that a word is always similar to itself, also notice that the similarity relation is + * transitive. For example, if the words a and b are similar, and the words b and c are similar, + * then a and c are similar. + */ + +/** + * @param {string[]} sentence1 + * @param {string[]} sentence2 + * @param {string[][]} similarPairs + * @return {boolean} + */ +var areSentencesSimilarTwo = function(sentence1, sentence2, similarPairs) { + if (sentence1.length !== sentence2.length) { + return false; + } + + const graph = new Map(); + for (const [word1, word2] of similarPairs) { + if (!graph.has(word1)) graph.set(word1, new Set()); + if (!graph.has(word2)) graph.set(word2, new Set()); + graph.get(word1).add(word2); + graph.get(word2).add(word1); + } + + for (let i = 0; i < sentence1.length; i++) { + if (!areSimilar(sentence1[i], sentence2[i])) { + return false; + } + } + + return true; + + function areSimilar(start, target) { + if (start === target) return true; + const visited = new Set(); + const queue = [start]; + visited.add(start); + + while (queue.length) { + const word = queue.shift(); + for (const neighbor of graph.get(word) || []) { + if (neighbor === target) return true; + if (!visited.has(neighbor)) { + visited.add(neighbor); + queue.push(neighbor); + } + } + } + return false; + } +}; diff --git a/solutions/0742-closest-leaf-in-a-binary-tree.js b/solutions/0742-closest-leaf-in-a-binary-tree.js new file mode 100644 index 00000000..8367bf08 --- /dev/null +++ b/solutions/0742-closest-leaf-in-a-binary-tree.js @@ -0,0 +1,61 @@ +/** + * 742. Closest Leaf in a Binary Tree + * https://leetcode.com/problems/closest-leaf-in-a-binary-tree/ + * Difficulty: Medium + * + * Given the root of a binary tree where every node has a unique value and a target integer k, + * return the value of the nearest leaf node to the target k in the tree. + * + * Nearest to a leaf means the least number of edges traveled on the binary tree to reach any + * leaf of the tree. Also, a node is called a leaf if it has no children. + */ + +/** + * 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} k + * @return {number} + */ +var findClosestLeaf = function(root, k) { + const graph = new Map(); + const leaves = new Set(); + + buildGraph(root, null); + + const queue = [k]; + const visited = new Set([k]); + + while (queue.length) { + const current = queue.shift(); + if (leaves.has(current)) return current; + + for (const neighbor of graph.get(current) || []) { + if (!visited.has(neighbor)) { + visited.add(neighbor); + queue.push(neighbor); + } + } + } + + return -1; + + function buildGraph(node, parent) { + if (!node) return; + if (!node.left && !node.right) leaves.add(node.val); + if (parent) { + if (!graph.has(node.val)) graph.set(node.val, new Set()); + if (!graph.has(parent.val)) graph.set(parent.val, new Set()); + graph.get(node.val).add(parent.val); + graph.get(parent.val).add(node.val); + } + buildGraph(node.left, node); + buildGraph(node.right, node); + } +}; diff --git a/solutions/0750-number-of-corner-rectangles.js b/solutions/0750-number-of-corner-rectangles.js new file mode 100644 index 00000000..815559fa --- /dev/null +++ b/solutions/0750-number-of-corner-rectangles.js @@ -0,0 +1,35 @@ +/** + * 750. Number Of Corner Rectangles + * https://leetcode.com/problems/number-of-corner-rectangles/ + * Difficulty: Medium + * + * Given an m x n integer matrix grid where each entry is only 0 or 1, return the number of + * corner rectangles. + * + * A corner rectangle is four distinct 1's on the grid that forms an axis-aligned rectangle. + * Note that only the corners need to have the value 1. Also, all four 1's used must be distinct. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var countCornerRectangles = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + let result = 0; + + for (let row1 = 0; row1 < rows; row1++) { + for (let row2 = row1 + 1; row2 < rows; row2++) { + let sharedOnes = 0; + for (let col = 0; col < cols; col++) { + if (grid[row1][col] === 1 && grid[row2][col] === 1) { + sharedOnes++; + } + } + result += sharedOnes * (sharedOnes - 1) / 2; + } + } + + return result; +}; diff --git a/solutions/0751-ip-to-cidr.js b/solutions/0751-ip-to-cidr.js new file mode 100644 index 00000000..b9bf5540 --- /dev/null +++ b/solutions/0751-ip-to-cidr.js @@ -0,0 +1,74 @@ +/** + * 751. IP to CIDR + * https://leetcode.com/problems/ip-to-cidr/ + * Difficulty: Medium + * + * An IP address is a formatted 32-bit unsigned integer where each group of 8 bits is printed as + * a decimal number and the dot character '.' splits the groups. + * - For example, the binary number 00001111 10001000 11111111 01101011 (spaces added for clarity) + * formatted as an IP address would be "15.136.255.107". + * + * A CIDR block is a format used to denote a specific set of IP addresses. It is a string consisting + * of a base IP address, followed by a slash, followed by a prefix length k. The addresses it covers + * are all the IPs whose first k bits are the same as the base IP address. + * - For example, "123.45.67.89/20" is a CIDR block with a prefix length of 20. Any IP address whose + * binary representation matches 01111011 00101101 0100xxxx xxxxxxxx, where x can be either 0 or + * 1, is in the set covered by the CIDR block. + * + * You are given a start IP address ip and the number of IP addresses we need to cover n. Your goal + * is to use as few CIDR blocks as possible to cover all the IP addresses in the inclusive + * range [ip, ip + n - 1] exactly. No other IP addresses outside of the range should be covered. + * + * Return the shortest list of CIDR blocks that covers the range of IP addresses. If there are + * multiple answers, return any of them. + */ + +/** + * @param {string} ip + * @param {number} n + * @return {string[]} + */ +var ipToCIDR = function(ip, n) { + let start = ipToNumber(ip); + const result = []; + + while (n > 0) { + let rightmostOneBit = start & (-start); + if (rightmostOneBit === 0) rightmostOneBit = 4294967296; + + let blockSize = Math.min(rightmostOneBit, n); + let temp = blockSize; + while ((temp & (temp - 1)) !== 0) { + temp = temp & (temp - 1); + } + blockSize = temp; + + let prefixLength = 32; + let mask = blockSize; + while (mask > 1) { + mask >>>= 1; + prefixLength--; + } + + result.push(`${numberToIp(start)}/${prefixLength}`); + + start += blockSize; + n -= blockSize; + } + + return result; + + function ipToNumber(ip) { + const parts = ip.split('.').map(Number); + return (parts[0] << 24) + (parts[1] << 16) + (parts[2] << 8) + parts[3]; + } + + function numberToIp(num) { + return [ + (num >>> 24) & 255, + (num >>> 16) & 255, + (num >>> 8) & 255, + num & 255 + ].join('.'); + } +}; diff --git a/solutions/0755-pour-water.js b/solutions/0755-pour-water.js new file mode 100644 index 00000000..f5e3ae88 --- /dev/null +++ b/solutions/0755-pour-water.js @@ -0,0 +1,95 @@ +/** + * 755. Pour Water + * https://leetcode.com/problems/pour-water/ + * Difficulty: Medium + * + * You are given an elevation map represents as an integer array heights where heights[i] + * representing the height of the terrain at index i. The width at each index is 1. You + * are also given two integers volume and k. volume units of water will fall at index k. + * + * Water first drops at the index k and rests on top of the highest terrain or water at + * that index. Then, it flows according to the following rules: + * - If the droplet would eventually fall by moving left, then move left. + * - Otherwise, if the droplet would eventually fall by moving right, then move right. + * - Otherwise, rise to its current position. + * + * Here, "eventually fall" means that the droplet will eventually be at a lower level if + * it moves in that direction. Also, level means the height of the terrain plus any water + * in that column. + * + * We can assume there is infinitely high terrain on the two sides out of bounds of the + * array. Also, there could not be partial water being spread out evenly on more than one + * grid block, and each unit of water has to be in exactly one block. + */ + +/** + * @param {number[]} heights + * @param {number} volume + * @param {number} k + * @return {number[]} + */ +var pourWater = function(heights, volume, k) { + const water = new Array(heights.length).fill(0); + + for (let drop = 0; drop < volume; drop++) { + if (canFallLeft(k)) { + water[findLeftPosition(k)]++; + } else if (canFallRight(k)) { + water[findRightPosition(k)]++; + } else { + water[k]++; + } + } + + return heights.map((h, i) => h + water[i]); + + function canFallLeft(index) { + let currentLevel = heights[index] + water[index]; + for (let i = index - 1; i >= 0; i--) { + const level = heights[i] + water[i]; + if (level < currentLevel) return true; + if (level > currentLevel) return false; + currentLevel = level; + } + return false; + } + + function canFallRight(index) { + let currentLevel = heights[index] + water[index]; + for (let i = index + 1; i < heights.length; i++) { + const level = heights[i] + water[i]; + if (level < currentLevel) return true; + if (level > currentLevel) return false; + currentLevel = level; + } + return false; + } + + function findLeftPosition(index) { + let minHeight = heights[index] + water[index]; + let position = index; + for (let i = index - 1; i >= 0; i--) { + const level = heights[i] + water[i]; + if (level > minHeight) break; + if (level < minHeight) { + minHeight = level; + position = i; + } + } + return position; + } + + function findRightPosition(index) { + let minHeight = heights[index] + water[index]; + let position = index; + for (let i = index + 1; i < heights.length; i++) { + const level = heights[i] + water[i]; + if (level > minHeight) break; + if (level < minHeight) { + minHeight = level; + position = i; + } + } + return position; + } +}; diff --git a/solutions/0758-bold-words-in-string.js b/solutions/0758-bold-words-in-string.js new file mode 100644 index 00000000..5187a17d --- /dev/null +++ b/solutions/0758-bold-words-in-string.js @@ -0,0 +1,57 @@ +/** + * 758. Bold Words in String + * https://leetcode.com/problems/bold-words-in-string/ + * Difficulty: Medium + * + * Given an array of keywords words and a string s, make all appearances of all keywords words[i] + * in s bold. Any letters between and tags become bold. + * + * Return s after adding the bold tags. The returned string should use the least number of tags + * possible, and the tags should form a valid combination. + */ + +/** + * @param {string[]} words + * @param {string} s + * @return {string} + */ +var boldWords = function(words, s) { + const boldIntervals = []; + + for (const word of words) { + let start = s.indexOf(word); + while (start !== -1) { + boldIntervals.push([start, start + word.length]); + start = s.indexOf(word, start + 1); + } + } + + if (!boldIntervals.length) return s; + + boldIntervals.sort((a, b) => a[0] - b[0] || a[1] - b[1]); + + const mergedIntervals = []; + let [currentStart, currentEnd] = boldIntervals[0]; + + for (let i = 1; i < boldIntervals.length; i++) { + const [nextStart, nextEnd] = boldIntervals[i]; + if (nextStart <= currentEnd) { + currentEnd = Math.max(currentEnd, nextEnd); + } else { + mergedIntervals.push([currentStart, currentEnd]); + [currentStart, currentEnd] = [nextStart, nextEnd]; + } + } + mergedIntervals.push([currentStart, currentEnd]); + + let result = ''; + let lastEnd = 0; + for (const [start, end] of mergedIntervals) { + result += s.slice(lastEnd, start) + '' + s.slice(start, end) + ''; + lastEnd = end; + } + + result += s.slice(lastEnd); + + return result; +}; diff --git a/solutions/0759-employee-free-time.js b/solutions/0759-employee-free-time.js new file mode 100644 index 00000000..5b29cb37 --- /dev/null +++ b/solutions/0759-employee-free-time.js @@ -0,0 +1,51 @@ +/** + * 759. Employee Free Time + * https://leetcode.com/problems/employee-free-time/ + * Difficulty: Hard + * + * 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. + */ + +/** + * @param {Interval[][]} schedule + * @return {Interval[]} + */ +var employeeFreeTime = function(schedule) { + const allIntervals = []; + + for (const employee of schedule) { + for (const interval of employee) { + allIntervals.push(interval); + } + } + + allIntervals.sort((a, b) => a.start - b.start); + + const merged = []; + for (const interval of allIntervals) { + if (merged.length === 0 || merged[merged.length - 1].end < interval.start) { + merged.push(interval); + } else { + merged[merged.length - 1].end = Math.max(merged[merged.length - 1].end, interval.end); + } + } + + const result = []; + for (let i = 0; i < merged.length - 1; i++) { + if (merged[i].end < merged[i + 1].start) { + result.push(new Interval(merged[i].end, merged[i + 1].start)); + } + } + + return result; +}; diff --git a/solutions/0760-find-anagram-mappings.js b/solutions/0760-find-anagram-mappings.js new file mode 100644 index 00000000..f6bc9fa6 --- /dev/null +++ b/solutions/0760-find-anagram-mappings.js @@ -0,0 +1,38 @@ +/** + * 760. Find Anagram Mappings + * https://leetcode.com/problems/find-anagram-mappings/ + * Difficulty: Easy + * + * You are given two integer arrays nums1 and nums2 where nums2 is an anagram of nums1. Both + * arrays may contain duplicates. + * + * Return an index mapping array mapping from nums1 to nums2 where mapping[i] = j means the + * ith element in nums1 appears in nums2 at index j. If there are multiple answers, return + * any of them. + * + * An array a is an anagram of an array b means b is made by randomizing the order of the + * elements in a. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number[]} + */ +var anagramMappings = function(nums1, nums2) { + const map = new Map(); + + for (let i = 0; i < nums2.length; i++) { + if (!map.has(nums2[i])) { + map.set(nums2[i], []); + } + map.get(nums2[i]).push(i); + } + + const result = []; + for (const num of nums1) { + result.push(map.get(num).pop()); + } + + return result; +}; diff --git a/solutions/0772-basic-calculator-iii.js b/solutions/0772-basic-calculator-iii.js new file mode 100644 index 00000000..4520c1cc --- /dev/null +++ b/solutions/0772-basic-calculator-iii.js @@ -0,0 +1,77 @@ +/** + * 772. Basic Calculator III + * https://leetcode.com/problems/basic-calculator-iii/ + * Difficulty: Hard + * + * Implement a basic calculator to evaluate a simple expression string. + * + * The expression string contains only non-negative integers, '+', '-', '*', '/' operators, and + * open '(' and closing parentheses ')'. The integer division should truncate toward zero. + * + * You may assume that the given expression is always valid. All intermediate results will be + * in the range of [-231, 231 - 1]. + * + * Note: You are not allowed to use any built-in function which evaluates strings as mathematical + * expressions, such as eval(). + */ + +/** + * @param {string} s + * @return {number} + */ +var calculate = function(s) { + let index = 0; + return parseExpression(); + + function parseExpression() { + let result = parseTerm(); + + while (index < s.length && (s[index] === '+' || s[index] === '-')) { + const operator = s[index++]; + const term = parseTerm(); + result = operator === '+' ? result + term : result - term; + } + + return result; + } + + function parseTerm() { + let result = parseFactor(); + + while (index < s.length && (s[index] === '*' || s[index] === '/')) { + const operator = s[index++]; + const factor = parseFactor(); + if (operator === '*') { + result *= factor; + } else { + result = Math.trunc(result / factor); + } + } + + return result; + } + + function parseFactor() { + skipSpaces(); + + if (s[index] === '(') { + index++; + const result = parseExpression(); + index++; + return result; + } + + let result = 0; + while (index < s.length && s[index] >= '0' && s[index] <= '9') { + result = result * 10 + parseInt(s[index++]); + } + + return result; + } + + function skipSpaces() { + while (index < s.length && s[index] === ' ') { + index++; + } + } +}; diff --git a/solutions/0774-minimize-max-distance-to-gas-station.js b/solutions/0774-minimize-max-distance-to-gas-station.js new file mode 100644 index 00000000..27930e3b --- /dev/null +++ b/solutions/0774-minimize-max-distance-to-gas-station.js @@ -0,0 +1,49 @@ +/** + * 774. Minimize Max Distance to Gas Station + * https://leetcode.com/problems/minimize-max-distance-to-gas-station/ + * Difficulty: Hard + * + * You are given an integer array stations that represents the positions of the gas stations + * on the x-axis. You are also given an integer k. + * + * You should add k new gas stations. You can add the stations anywhere on the x-axis, and + * not necessarily on an integer position. + * + * Let penalty() be the maximum distance between adjacent gas stations after adding the k + * new stations. + * + * Return the smallest possible value of penalty(). Answers within 10-6 of the actual answer + * will be accepted. + */ + +/** + * @param {number[]} stations + * @param {number} k + * @return {number} + */ +var minmaxGasDist = function(stations, k) { + const gaps = []; + for (let i = 1; i < stations.length; i++) { + gaps.push(stations[i] - stations[i - 1]); + } + + let left = 0; + let right = Math.max(...gaps); + + while (right - left > 1e-6) { + const mid = (left + right) / 2; + + let stationsNeeded = 0; + for (const gap of gaps) { + stationsNeeded += Math.floor(gap / mid); + } + + if (stationsNeeded <= k) { + right = mid; + } else { + left = mid; + } + } + + return right; +}; diff --git a/solutions/0776-split-bst.js b/solutions/0776-split-bst.js new file mode 100644 index 00000000..2b4dbd05 --- /dev/null +++ b/solutions/0776-split-bst.js @@ -0,0 +1,43 @@ +/** + * 776. Split BST + * https://leetcode.com/problems/split-bst/ + * Difficulty: Medium + * + * Given the root of a binary search tree (BST) and an integer target, split the tree into + * two subtrees where the first subtree has nodes that are all smaller or equal to the + * target value, while the second subtree has all nodes that are greater than the target + * value. It is not necessarily the case that the tree contains a node with the value target. + * + * Additionally, most of the structure of the original tree should remain. Formally, for + * any child c with parent p in the original tree, if they are both in the same subtree + * after the split, then node c should still have the parent p. + * + * Return an array of the two roots of the two subtrees in order. + */ + +/** + * 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[]} + */ +var splitBST = function(root, target) { + if (!root) return [null, null]; + + if (root.val <= target) { + const [smaller, larger] = splitBST(root.right, target); + root.right = smaller; + return [root, larger]; + } else { + const [smaller, larger] = splitBST(root.left, target); + root.left = larger; + return [smaller, root]; + } +}; diff --git a/solutions/0800-similar-rgb-color.js b/solutions/0800-similar-rgb-color.js new file mode 100644 index 00000000..5e545dbf --- /dev/null +++ b/solutions/0800-similar-rgb-color.js @@ -0,0 +1,51 @@ +/** + * 800. Similar RGB Color + * https://leetcode.com/problems/similar-rgb-color/ + * Difficulty: Easy + * + * The red-green-blue color "#AABBCC" can be written as "#ABC" in shorthand. + * - For example, "#15c" is shorthand for the color "#1155cc". + * + * The similarity between the two colors "#ABCDEF" and "#UVWXYZ" + * is -(AB - UV)2 - (CD - WX)2 - (EF - YZ)2. + * + * Given a string color that follows the format "#ABCDEF", return a string represents + * the color that is most similar to the given color and has a shorthand (i.e., it can + * be represented as some "#XYZ"). + * + * Any answer which has the same highest similarity as the best answer will be accepted. + */ + +/** + * @param {string} color + * @return {string} + */ +var similarRGB = function(color) { + const shorthandValues = [ + '00', '11', '22', '33', '44', '55', '66', '77', + '88', '99', 'aa', 'bb', 'cc', 'dd', 'ee', 'ff' + ]; + + const red = helper(color.slice(1, 3)); + const green = helper(color.slice(3, 5)); + const blue = helper(color.slice(5, 7)); + + return `#${red}${green}${blue}`; + + function helper(hex) { + const value = parseInt(hex, 16); + let minDiff = Infinity; + let closest = ''; + + for (const shorthand of shorthandValues) { + const shorthandValue = parseInt(shorthand, 16); + const diff = Math.abs(value - shorthandValue); + if (diff < minDiff) { + minDiff = diff; + closest = shorthand; + } + } + + return closest; + } +}; diff --git a/solutions/1055-shortest-way-to-form-string.js b/solutions/1055-shortest-way-to-form-string.js new file mode 100644 index 00000000..57957f92 --- /dev/null +++ b/solutions/1055-shortest-way-to-form-string.js @@ -0,0 +1,50 @@ +/** + * 1055. Shortest Way to Form String + * https://leetcode.com/problems/shortest-way-to-form-string/ + * Difficulty: Medium + * + * A subsequence of a string is a new string that is formed from the original string by deleting + * some (can be none) of the characters without disturbing the relative positions of the remaining + * characters. (i.e., "ace" is a subsequence of "abcde" while "aec" is not). + * + * Given two strings source and target, return the minimum number of subsequences of source such + * that their concatenation equals target. If the task is impossible, return -1. + */ + +/** + * @param {string} source + * @param {string} target + * @return {number} + */ +var shortestWay = function(source, target) { + const sourceSet = new Set(source); + + for (const char of target) { + if (!sourceSet.has(char)) { + return -1; + } + } + + let subsequences = 0; + let targetIndex = 0; + + while (targetIndex < target.length) { + let sourceIndex = 0; + const startTargetIndex = targetIndex; + + while (sourceIndex < source.length && targetIndex < target.length) { + if (source[sourceIndex] === target[targetIndex]) { + targetIndex++; + } + sourceIndex++; + } + + if (targetIndex === startTargetIndex) { + return -1; + } + + subsequences++; + } + + return subsequences; +}; diff --git a/solutions/1056-confusing-number.js b/solutions/1056-confusing-number.js new file mode 100644 index 00000000..da6ef82d --- /dev/null +++ b/solutions/1056-confusing-number.js @@ -0,0 +1,36 @@ +/** + * 1056. Confusing Number + * https://leetcode.com/problems/confusing-number/ + * Difficulty: Easy + * + * A confusing number is a number that when rotated 180 degrees becomes a different number with + * each digit valid. + * + * We can rotate digits of a number by 180 degrees to form new digits. + * - When 0, 1, 6, 8, and 9 are rotated 180 degrees, they become 0, 1, 9, 8, and 6 respectively. + * - When 2, 3, 4, 5, and 7 are rotated 180 degrees, they become invalid. + * + * Note that after rotating a number, we can ignore leading zeros. + * - For example, after rotating 8000, we have 0008 which is considered as just 8. + * + * Given an integer n, return true if it is a confusing number, or false otherwise. + */ + +/** + * @param {number} n + * @return {boolean} + */ +var confusingNumber = function(n) { + const rotationMap = { '0': '0', '1': '1', '6': '9', '8': '8', '9': '6' }; + const digits = n.toString(); + + let rotated = ''; + for (let i = digits.length - 1; i >= 0; i--) { + if (!(digits[i] in rotationMap)) { + return false; + } + rotated += rotationMap[digits[i]]; + } + + return parseInt(rotated, 10) !== n; +}; diff --git a/solutions/1057-campus-bikes.js b/solutions/1057-campus-bikes.js new file mode 100644 index 00000000..65811be2 --- /dev/null +++ b/solutions/1057-campus-bikes.js @@ -0,0 +1,64 @@ +/** + * 1057. Campus Bikes + * https://leetcode.com/problems/campus-bikes/ + * Difficulty: Medium + * + * On a campus represented on the X-Y plane, there are n workers and m bikes, with n <= m. + * + * You are given an array workers of length n where workers[i] = [xi, yi] is the position of + * the ith worker. You are also given an array bikes of length m where bikes[j] = [xj, yj] + * is the position of the jth bike. All the given positions are unique. + * + * Assign a bike to each worker. Among the available bikes and workers, we choose the + * (workeri, bikej) pair with the shortest Manhattan distance between each other and assign + * the bike to that worker. + * + * If there are multiple (workeri, bikej) pairs with the same shortest Manhattan distance, + * we choose the pair with the smallest worker index. If there are multiple ways to do that, + * we choose the pair with the smallest bike index. Repeat this process until there are no + * available workers. + * + * Return an array answer of length n, where answer[i] is the index (0-indexed) of the bike + * that the ith worker is assigned to. + * + * The Manhattan distance between two points p1 and p2 is + * Manhattan(p1, p2) = |p1.x - p2.x| + |p1.y - p2.y|. + */ + +/** + * @param {number[][]} workers + * @param {number[][]} bikes + * @return {number[]} + */ +var assignBikes = function(workers, bikes) { + const distances = []; + + for (let i = 0; i < workers.length; i++) { + for (let j = 0; j < bikes.length; j++) { + const distance = Math.abs( + workers[i][0] - bikes[j][0]) + Math.abs(workers[i][1] - bikes[j][1] + ); + distances.push([distance, i, j]); + } + } + + distances.sort((a, b) => { + if (a[0] !== b[0]) return a[0] - b[0]; + if (a[1] !== b[1]) return a[1] - b[1]; + return a[2] - b[2]; + }); + + const result = new Array(workers.length); + const usedBikes = new Set(); + const assignedWorkers = new Set(); + + for (const [distance, workerIndex, bikeIndex] of distances) { + if (!assignedWorkers.has(workerIndex) && !usedBikes.has(bikeIndex)) { + result[workerIndex] = bikeIndex; + assignedWorkers.add(workerIndex); + usedBikes.add(bikeIndex); + } + } + + return result; +}; diff --git a/solutions/1058-minimize-rounding-error-to-meet-target.js b/solutions/1058-minimize-rounding-error-to-meet-target.js new file mode 100644 index 00000000..6ddd5138 --- /dev/null +++ b/solutions/1058-minimize-rounding-error-to-meet-target.js @@ -0,0 +1,53 @@ +/** + * 1058. Minimize Rounding Error to Meet Target + * https://leetcode.com/problems/minimize-rounding-error-to-meet-target/ + * Difficulty: Medium + * + * Given an array of prices [p1,p2...,pn] and a target, round each price pi to Roundi(pi) so + * that the rounded array [Round1(p1),Round2(p2)...,Roundn(pn)] sums to the given target. + * Each operation Roundi(pi) could be either Floor(pi) or Ceil(pi). + * + * Return the string "-1" if the rounded array is impossible to sum to target. Otherwise, + * return the smallest rounding error, which is defined as Σ |Roundi(pi) - (pi)| for i from + * 1 to n, as a string with three places after the decimal. + */ + +/** + * @param {string[]} prices + * @param {number} target + * @return {string} + */ +var minimizeError = function(prices, target) { + const nums = prices.map(p => parseFloat(p)); + const floors = nums.map(n => Math.floor(n)); + const ceils = nums.map(n => Math.ceil(n)); + + const minSum = floors.reduce((sum, f) => sum + f, 0); + const maxSum = ceils.reduce((sum, c) => sum + c, 0); + + if (target < minSum || target > maxSum) { + return '-1'; + } + + const ceilsNeeded = target - minSum; + + const items = nums.map((n, i) => ({ + floorError: n - floors[i], + ceilError: ceils[i] - n, + diff: (ceils[i] - n) - (n - floors[i]) + })); + + items.sort((a, b) => a.diff - b.diff); + + let totalError = 0; + + for (let i = 0; i < nums.length; i++) { + if (i < ceilsNeeded) { + totalError += items[i].ceilError; + } else { + totalError += items[i].floorError; + } + } + + return totalError.toFixed(3); +}; diff --git a/solutions/1059-all-paths-from-source-lead-to-destination.js b/solutions/1059-all-paths-from-source-lead-to-destination.js new file mode 100644 index 00000000..b6862441 --- /dev/null +++ b/solutions/1059-all-paths-from-source-lead-to-destination.js @@ -0,0 +1,57 @@ +/** + * 1059. All Paths from Source Lead to Destination + * https://leetcode.com/problems/all-paths-from-source-lead-to-destination/ + * Difficulty: Medium + * + * Given the edges of a directed graph where edges[i] = [ai, bi] indicates there is an edge + * between nodes ai and bi, and two nodes source and destination of this graph, determine + * whether or not all paths starting from source eventually, end at destination, that is: + * - At least one path exists from the source node to the destination node + * - If a path exists from the source node to a node with no outgoing edges, then that node + * is equal to destination. + * - The number of possible paths from source to destination is a finite number. + * + * Return true if and only if all roads from source lead to destination. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number} source + * @param {number} destination + * @return {boolean} + */ +var leadsToDestination = function(n, edges, source, destination) { + const graph = new Map(); + const states = new Array(n).fill(0); + + for (const [from, to] of edges) { + if (!graph.has(from)) { + graph.set(from, []); + } + graph.get(from).push(to); + } + + return dfs(source); + + function dfs(node) { + if (states[node] === 1) return false; + if (states[node] === 2) return true; + + states[node] = 1; + + if (!graph.has(node)) { + states[node] = 2; + return node === destination; + } + + for (const neighbor of graph.get(node)) { + if (!dfs(neighbor)) { + return false; + } + } + + states[node] = 2; + return true; + } +}; diff --git a/solutions/1060-missing-element-in-sorted-array.js b/solutions/1060-missing-element-in-sorted-array.js new file mode 100644 index 00000000..2a168e83 --- /dev/null +++ b/solutions/1060-missing-element-in-sorted-array.js @@ -0,0 +1,41 @@ +/** + * 1060. Missing Element in Sorted Array + * https://leetcode.com/problems/missing-element-in-sorted-array/ + * Difficulty: Medium + * + * Given an integer array nums which is sorted in ascending order and all of its elements are + * unique and given also an integer k, return the kth missing number starting from the leftmost + * number of the array. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var missingElement = function(nums, k) { + const n = nums.length; + + if (k > getMissingCount(n - 1)) { + return nums[n - 1] + k - getMissingCount(n - 1); + } + + let left = 0; + let right = n - 1; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + + if (getMissingCount(mid) < k) { + left = mid + 1; + } else { + right = mid; + } + } + + return nums[left - 1] + k - getMissingCount(left - 1); + + function getMissingCount(index) { + return nums[index] - nums[0] - index; + } +}; diff --git a/solutions/1062-longest-repeating-substring.js b/solutions/1062-longest-repeating-substring.js new file mode 100644 index 00000000..68c7232c --- /dev/null +++ b/solutions/1062-longest-repeating-substring.js @@ -0,0 +1,29 @@ +/** + * 1062. Longest Repeating Substring + * https://leetcode.com/problems/longest-repeating-substring/ + * Difficulty: Medium + * + * Given a string s, return the length of the longest repeating substrings. If no repeating + * substring exists, return 0. + */ + +/** + * @param {string} s + * @return {number} + */ +var longestRepeatingSubstring = function(s) { + const n = s.length; + const dp = new Array(n + 1).fill(null).map(() => new Array(n + 1).fill(0)); + let result = 0; + + for (let i = 1; i <= n; i++) { + for (let j = 1; j <= n; j++) { + if (i !== j && s[i - 1] === s[j - 1]) { + dp[i][j] = dp[i - 1][j - 1] + 1; + result = Math.max(result, dp[i][j]); + } + } + } + + return result; +}; diff --git a/solutions/1063-number-of-valid-subarrays.js b/solutions/1063-number-of-valid-subarrays.js new file mode 100644 index 00000000..075c69b5 --- /dev/null +++ b/solutions/1063-number-of-valid-subarrays.js @@ -0,0 +1,35 @@ +/** + * 1063. Number of Valid Subarrays + * https://leetcode.com/problems/number-of-valid-subarrays/ + * Difficulty: Hard + * + * Given an integer array nums, return the number of non-empty subarrays with the leftmost + * element of the subarray not larger than other elements in the subarray. + * + * A subarray is a contiguous part of an array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var validSubarrays = function(nums) { + const n = nums.length; + const stack = []; + let result = 0; + + for (let i = 0; i < n; i++) { + while (stack.length && nums[stack[stack.length - 1]] > nums[i]) { + const index = stack.pop(); + result += i - index; + } + stack.push(i); + } + + while (stack.length) { + const index = stack.pop(); + result += n - index; + } + + return result; +}; diff --git a/solutions/1064-fixed-point.js b/solutions/1064-fixed-point.js new file mode 100644 index 00000000..216af9a6 --- /dev/null +++ b/solutions/1064-fixed-point.js @@ -0,0 +1,33 @@ +/** + * 1064. Fixed Point + * https://leetcode.com/problems/fixed-point/ + * Difficulty: Easy + * + * Given an array of distinct integers arr, where arr is sorted in ascending order, return + * the smallest index i that satisfies arr[i] == i. If there is no such index, return -1. + */ + +/** + * @param {number[]} arr + * @return {number} + */ +var fixedPoint = function(arr) { + let left = 0; + let right = arr.length - 1; + let result = -1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + + if (arr[mid] === mid) { + result = mid; + right = mid - 1; + } else if (arr[mid] < mid) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return result; +}; diff --git a/solutions/1065-index-pairs-of-a-string.js b/solutions/1065-index-pairs-of-a-string.js new file mode 100644 index 00000000..35aa0a54 --- /dev/null +++ b/solutions/1065-index-pairs-of-a-string.js @@ -0,0 +1,32 @@ +/** + * 1065. Index Pairs of a String + * https://leetcode.com/problems/index-pairs-of-a-string/ + * Difficulty: Easy + * + * Given a string text and an array of strings words, return an array of all index + * pairs [i, j] so that the substring text[i...j] is in words. + * + * Return the pairs [i, j] in sorted order (i.e., sort them by their first coordinate, + * and in case of ties sort them by their second coordinate). + */ + +/** + * @param {string} text + * @param {string[]} words + * @return {number[][]} + */ +var indexPairs = function(text, words) { + const result = []; + const wordSet = new Set(words); + + for (let i = 0; i < text.length; i++) { + for (let j = i; j < text.length; j++) { + const substring = text.slice(i, j + 1); + if (wordSet.has(substring)) { + result.push([i, j]); + } + } + } + + return result; +}; diff --git a/solutions/1066-campus-bikes-ii.js b/solutions/1066-campus-bikes-ii.js new file mode 100644 index 00000000..8d2e0f74 --- /dev/null +++ b/solutions/1066-campus-bikes-ii.js @@ -0,0 +1,55 @@ +/** + * 1066. Campus Bikes II + * https://leetcode.com/problems/campus-bikes-ii/ + * Difficulty: Medium + * + * On a campus represented as a 2D grid, there are n workers and m bikes, with n <= m. + * Each worker and bike is a 2D coordinate on this grid. + * + * We assign one unique bike to each worker so that the sum of the Manhattan distances + * between each worker and their assigned bike is minimized. + * + * Return the minimum possible sum of Manhattan distances between each worker and their + * assigned bike. + * + * The Manhattan distance between two points p1 and p2 is + * Manhattan(p1, p2) = |p1.x - p2.x| + |p1.y - p2.y|. + */ + +/** + * @param {number[][]} workers + * @param {number[][]} bikes + * @return {number} + */ +var assignBikes = function(workers, bikes) { + const n = workers.length; + const m = bikes.length; + const memo = new Map(); + + return dfs(0, 0); + + function getDistance(worker, bike) { + return Math.abs(workers[worker][0] - bikes[bike][0]) + + Math.abs(workers[worker][1] - bikes[bike][1]); + } + + function dfs(workerIndex, usedBikes) { + if (workerIndex === n) return 0; + + const key = `${workerIndex}-${usedBikes}`; + if (memo.has(key)) return memo.get(key); + + let minDistance = Infinity; + + for (let bikeIndex = 0; bikeIndex < m; bikeIndex++) { + if ((usedBikes & (1 << bikeIndex)) === 0) { + const distance = getDistance(workerIndex, bikeIndex) + + dfs(workerIndex + 1, usedBikes | (1 << bikeIndex)); + minDistance = Math.min(minDistance, distance); + } + } + + memo.set(key, minDistance); + return minDistance; + } +}; diff --git a/solutions/1067-digit-count-in-range.js b/solutions/1067-digit-count-in-range.js new file mode 100644 index 00000000..63ffbb94 --- /dev/null +++ b/solutions/1067-digit-count-in-range.js @@ -0,0 +1,60 @@ +/** + * 1067. Digit Count in Range + * https://leetcode.com/problems/digit-count-in-range/ + * Difficulty: Hard + * + * Given a single-digit integer d and two integers low and high, return the number of times + * that d occurs as a digit in all integers in the inclusive range [low, high]. + */ + +/** + * @param {number} d + * @param {number} low + * @param {number} high + * @return {number} + */ +var digitsCount = function(d, low, high) { + return countDigits(high) - countDigits(low - 1); + + function countDigits(num) { + if (num < 0) return 0; + + const str = num.toString(); + const n = str.length; + let count = 0; + + for (let pos = 0; pos < n; pos++) { + const left = pos > 0 ? parseInt(str.substring(0, pos)) : 0; + const current = parseInt(str[pos]); + const right = pos < n - 1 ? parseInt(str.substring(pos + 1)) : 0; + const rightLength = n - pos - 1; + const rightPower = Math.pow(10, rightLength); + + if (d === 0) { + if (pos === 0) { + continue; + } + + if (current > d) { + count += (left - 1) * rightPower + rightPower; + } else if (current === d) { + count += (left - 1) * rightPower + right + 1; + } else { + if (left > 0) { + count += (left - 1) * rightPower + rightPower; + } + } + } else { + if (current > d) { + count += (left + 1) * rightPower; + } else if (current === d) { + count += left * rightPower + right + 1; + } else { + count += left * rightPower; + } + } + } + + return count; + } +}; diff --git a/solutions/1085-sum-of-digits-in-the-minimum-number.js b/solutions/1085-sum-of-digits-in-the-minimum-number.js new file mode 100644 index 00000000..69d8735a --- /dev/null +++ b/solutions/1085-sum-of-digits-in-the-minimum-number.js @@ -0,0 +1,21 @@ +/** + * 1085. Sum of Digits in the Minimum Number + * https://leetcode.com/problems/sum-of-digits-in-the-minimum-number/ + * Difficulty: Easy + * + * Given an integer array nums, return 0 if the sum of the digits of the minimum + * integer in nums is odd, or 1 otherwise. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var sumOfDigits = function(nums) { + const digitSum = Math.min(...nums) + .toString() + .split('') + .reduce((sum, digit) => sum + parseInt(digit), 0); + + return digitSum % 2 === 0 ? 1 : 0; +}; diff --git a/solutions/1086-high-five.js b/solutions/1086-high-five.js new file mode 100644 index 00000000..e7f379ba --- /dev/null +++ b/solutions/1086-high-five.js @@ -0,0 +1,42 @@ +/** + * 1086. High Five + * https://leetcode.com/problems/high-five/ + * Difficulty: Easy + * + * Given a list of the scores of different students, items, where items[i] = [IDi, scorei] + * represents one score from a student with IDi, calculate each student's top five average. + * + * Return the answer as an array of pairs result, where result[j] = [IDj, topFiveAveragej] + * represents the student with IDj and their top five average. Sort result by IDj in + * increasing order. + * + * A student's top five average is calculated by taking the sum of their top five scores + * and dividing it by 5 using integer division. + */ + +/** + * @param {number[][]} items + * @return {number[][]} + */ +var highFive = function(items) { + const studentScores = new Map(); + + for (const [id, score] of items) { + if (!studentScores.has(id)) { + studentScores.set(id, []); + } + studentScores.get(id).push(score); + } + + const result = []; + for (const [id, scores] of studentScores) { + scores.sort((a, b) => b - a); + const topFiveSum = scores.slice(0, 5).reduce((sum, score) => sum + score, 0); + const average = Math.floor(topFiveSum / 5); + result.push([id, average]); + } + + result.sort((a, b) => a[0] - b[0]); + + return result; +}; diff --git a/solutions/1087-brace-expansion.js b/solutions/1087-brace-expansion.js new file mode 100644 index 00000000..95571310 --- /dev/null +++ b/solutions/1087-brace-expansion.js @@ -0,0 +1,55 @@ +/** + * 1087. Brace Expansion + * https://leetcode.com/problems/brace-expansion/ + * Difficulty: Medium + * + * You are given a string s representing a list of words. Each letter in the word has + * one or more options. + * - If there is one option, the letter is represented as is. + * - If there is more than one option, then curly braces delimit the options. + * For example, "{a,b,c}" represents options ["a", "b", "c"]. + * + * For example, if s = "a{b,c}", the first character is always 'a', but the second + * character can be 'b' or 'c'. The original list is ["ab", "ac"]. + * + * Return all words that can be formed in this manner, sorted in lexicographical order. + */ + +/** + * @param {string} s + * @return {string[]} + */ +var expand = function(s) { + const groups = []; + let i = 0; + + while (i < s.length) { + if (s[i] === '{') { + const start = i + 1; + while (s[i] !== '}') i++; + const options = s.substring(start, i).split(','); + groups.push(options); + i++; + } else { + groups.push([s[i]]); + i++; + } + } + + const result = []; + + backtrack(0, ''); + + return result.sort(); + + function backtrack(index, current) { + if (index === groups.length) { + result.push(current); + return; + } + + for (const option of groups[index]) { + backtrack(index + 1, current + option); + } + } +}; diff --git a/solutions/1088-confusing-number-ii.js b/solutions/1088-confusing-number-ii.js new file mode 100644 index 00000000..dc5c8f51 --- /dev/null +++ b/solutions/1088-confusing-number-ii.js @@ -0,0 +1,64 @@ +/** + * 1088. Confusing Number II + * https://leetcode.com/problems/confusing-number-ii/ + * Difficulty: Hard + * + * A confusing number is a number that when rotated 180 degrees becomes a different number + * with each digit valid. + * + * We can rotate digits of a number by 180 degrees to form new digits. + * - When 0, 1, 6, 8, and 9 are rotated 180 degrees, they become 0, 1, 9, 8, and 6 respectively. + * - When 2, 3, 4, 5, and 7 are rotated 180 degrees, they become invalid. + * + * Note that after rotating a number, we can ignore leading zeros. + * - For example, after rotating 8000, we have 0008 which is considered as just 8. + * + * Given an integer n, return the number of confusing numbers in the inclusive range [1, n]. + */ + +/** + * @param {number} n + * @return {number} + */ +var confusingNumberII = function(n) { + const validDigits = [0, 1, 6, 8, 9]; + const rotationMap = { 0: 0, 1: 1, 6: 9, 8: 8, 9: 6 }; + let count = 0; + + const maxLength = n.toString().length; + + for (let len = 1; len <= maxLength; len++) { + dfs(0, 0, len); + } + + return count; + + function isConfusing(num) { + const original = num; + let rotated = 0; + + while (num > 0) { + const digit = num % 10; + rotated = rotated * 10 + rotationMap[digit]; + num = Math.floor(num / 10); + } + + return original !== rotated; + } + + function dfs(current, length, targetLength) { + if (length === targetLength) { + if (current <= n && current > 0 && isConfusing(current)) { + count++; + } + return; + } + + for (const digit of validDigits) { + if (current === 0 && digit === 0) continue; + const next = current * 10 + digit; + if (next > n) break; + dfs(next, length + 1, targetLength); + } + } +}; diff --git a/solutions/1099-two-sum-less-than-k.js b/solutions/1099-two-sum-less-than-k.js new file mode 100644 index 00000000..9041f0c2 --- /dev/null +++ b/solutions/1099-two-sum-less-than-k.js @@ -0,0 +1,34 @@ +/** + * 1099. Two Sum Less Than K + * https://leetcode.com/problems/two-sum-less-than-k/ + * Difficulty: Easy + * + * Given an array nums of integers and integer k, return the maximum sum such that there + * exists i < j with nums[i] + nums[j] = sum and sum < k. If no i, j exist satisfying + * this equation, return -1. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var twoSumLessThanK = function(nums, k) { + nums.sort((a, b) => a - b); + let left = 0; + let right = nums.length - 1; + let result = -1; + + while (left < right) { + const sum = nums[left] + nums[right]; + + if (sum < k) { + result = Math.max(result, sum); + left++; + } else { + right--; + } + } + + return result; +}; diff --git a/solutions/1100-find-k-length-substrings-with-no-repeated-characters.js b/solutions/1100-find-k-length-substrings-with-no-repeated-characters.js new file mode 100644 index 00000000..bcbd2814 --- /dev/null +++ b/solutions/1100-find-k-length-substrings-with-no-repeated-characters.js @@ -0,0 +1,42 @@ +/** + * 1100. Find K-Length Substrings With No Repeated Characters + * https://leetcode.com/problems/find-k-length-substrings-with-no-repeated-characters/ + * Difficulty: Medium + * + * Given a string s and an integer k, return the number of substrings in s of length k + * with no repeated characters. + */ + +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +var numKLenSubstrNoRepeats = function(s, k) { + if (k > s.length) return 0; + + const charCount = new Map(); + let count = 0; + + for (let i = 0; i < k; i++) { + charCount.set(s[i], (charCount.get(s[i]) || 0) + 1); + } + + if (charCount.size === k) count++; + + for (let i = k; i < s.length; i++) { + const leftChar = s[i - k]; + const rightChar = s[i]; + + charCount.set(leftChar, charCount.get(leftChar) - 1); + if (charCount.get(leftChar) === 0) { + charCount.delete(leftChar); + } + + charCount.set(rightChar, (charCount.get(rightChar) || 0) + 1); + + if (charCount.size === k) count++; + } + + return count; +}; diff --git a/solutions/1101-the-earliest-moment-when-everyone-become-friends.js b/solutions/1101-the-earliest-moment-when-everyone-become-friends.js new file mode 100644 index 00000000..cc6cf1a9 --- /dev/null +++ b/solutions/1101-the-earliest-moment-when-everyone-become-friends.js @@ -0,0 +1,62 @@ +/** + * 1101. The Earliest Moment When Everyone Become Friends + * https://leetcode.com/problems/the-earliest-moment-when-everyone-become-friends/ + * Difficulty: Medium + * + * There are n people in a social group labeled from 0 to n - 1. You are given an array logs + * where logs[i] = [timestampi, xi, yi] indicates that xi and yi will be friends at the time + * timestampi. + * + * Friendship is symmetric. That means if a is friends with b, then b is friends with a. + * Also, person a is acquainted with a person b if a is friends with b, or a is a friend + * of someone acquainted with b. + * + * Return the earliest time for which every person became acquainted with every other person. + * If there is no such earliest time, return -1. + */ + +/** + * @param {number[][]} logs + * @param {number} n + * @return {number} + */ +var earliestAcq = function(logs, n) { + logs.sort((a, b) => a[0] - b[0]); + + const parent = Array.from({ length: n }, (_, i) => i); + const rank = new Array(n).fill(0); + let components = n; + for (const [timestamp, x, y] of logs) { + if (union(x, y) && components === 1) { + return timestamp; + } + } + + return -1; + + function find(x) { + if (parent[x] !== x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + function union(x, y) { + const rootX = find(x); + const rootY = find(y); + + if (rootX === rootY) return false; + + if (rank[rootX] < rank[rootY]) { + parent[rootX] = rootY; + } else if (rank[rootX] > rank[rootY]) { + parent[rootY] = rootX; + } else { + parent[rootY] = rootX; + rank[rootX]++; + } + + components--; + return true; + } +}; diff --git a/solutions/1102-path-with-maximum-minimum-value.js b/solutions/1102-path-with-maximum-minimum-value.js new file mode 100644 index 00000000..37536848 --- /dev/null +++ b/solutions/1102-path-with-maximum-minimum-value.js @@ -0,0 +1,47 @@ +/** + * 1102. Path With Maximum Minimum Value + * https://leetcode.com/problems/path-with-maximum-minimum-value/ + * Difficulty: Medium + * + * Given an m x n integer matrix grid, return the maximum score of a path starting + * at (0, 0) and ending at (m - 1, n - 1) moving in the 4 cardinal directions. + * + * The score of a path is the minimum value in that path. + * - For example, the score of the path 8 → 4 → 5 → 9 is 4. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var maximumMinimumPath = function(grid) { + const m = grid.length; + const n = grid[0].length; + const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]; + const visited = new Array(m).fill(null).map(() => new Array(n).fill(false)); + + const maxHeap = new PriorityQueue((a, b) => b[0] - a[0]); + maxHeap.enqueue([grid[0][0], 0, 0]); + visited[0][0] = true; + + while (!maxHeap.isEmpty()) { + const [currentScore, row, col] = maxHeap.dequeue(); + + if (row === m - 1 && col === n - 1) { + return currentScore; + } + + for (const [dr, dc] of directions) { + const newRow = row + dr; + const newCol = col + dc; + + if (newRow >= 0 && newRow < m && newCol >= 0 && newCol < n && !visited[newRow][newCol]) { + visited[newRow][newCol] = true; + const newScore = Math.min(currentScore, grid[newRow][newCol]); + maxHeap.enqueue([newScore, newRow, newCol]); + } + } + } + + return -1; +}; diff --git a/solutions/1118-number-of-days-in-a-month.js b/solutions/1118-number-of-days-in-a-month.js new file mode 100644 index 00000000..d201f255 --- /dev/null +++ b/solutions/1118-number-of-days-in-a-month.js @@ -0,0 +1,16 @@ +/** + * 1118. Number of Days in a Month + * https://leetcode.com/problems/number-of-days-in-a-month/ + * Difficulty: Easy + * + * Given a year year and a month month, return the number of days of that month. + */ + +/** + * @param {number} year + * @param {number} month + * @return {number} + */ +var numberOfDays = function(year, month) { + return new Date(year, month, 0).getDate(); +}; diff --git a/solutions/1119-remove-vowels-from-a-string.js b/solutions/1119-remove-vowels-from-a-string.js new file mode 100644 index 00000000..df679c98 --- /dev/null +++ b/solutions/1119-remove-vowels-from-a-string.js @@ -0,0 +1,16 @@ +/** + * 1119. Remove Vowels from a String + * https://leetcode.com/problems/remove-vowels-from-a-string/ + * Difficulty: Easy + * + * Given a string s, remove the vowels 'a', 'e', 'i', 'o', and 'u' from it, and + * return the new string. + */ + +/** + * @param {string} s + * @return {string} + */ +var removeVowels = function(s) { + return s.replace(/[aeiou]/g, ''); +}; diff --git a/solutions/1120-maximum-average-subtree.js b/solutions/1120-maximum-average-subtree.js new file mode 100644 index 00000000..2052a8f2 --- /dev/null +++ b/solutions/1120-maximum-average-subtree.js @@ -0,0 +1,44 @@ +/** + * 1120. Maximum Average Subtree + * https://leetcode.com/problems/maximum-average-subtree/ + * Difficulty: Medium + * + * Given the root of a binary tree, return the maximum average value of a subtree of that tree. + * Answers within 10-5 of the actual answer will be accepted. + * + * A subtree of a tree is any node of that tree plus all its descendants. + * + * The average value of a tree is the sum of its values, divided by the number of nodes. + */ + +/** + * 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} + */ +var maximumAverageSubtree = function(root) { + let maxAverage = 0; + calculateSubtree(root); + return maxAverage; + + function calculateSubtree(node) { + if (!node) return [0, 0]; + + const [leftSum, leftCount] = calculateSubtree(node.left); + const [rightSum, rightCount] = calculateSubtree(node.right); + const totalSum = leftSum + rightSum + node.val; + const totalCount = leftCount + rightCount + 1; + const currentAverage = totalSum / totalCount; + + maxAverage = Math.max(maxAverage, currentAverage); + + return [totalSum, totalCount]; + } +}; diff --git a/solutions/1121-divide-array-into-increasing-sequences.js b/solutions/1121-divide-array-into-increasing-sequences.js new file mode 100644 index 00000000..e36de1ad --- /dev/null +++ b/solutions/1121-divide-array-into-increasing-sequences.js @@ -0,0 +1,26 @@ +/** + * 1121. Divide Array Into Increasing Sequences + * https://leetcode.com/problems/divide-array-into-increasing-sequences/ + * Difficulty: Hard + * + * Given an integer array nums sorted in non-decreasing order and an integer k, return true + * if this array can be divided into one or more disjoint increasing subsequences of length + * at least k, or false otherwise. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {boolean} + */ +var canDivideIntoSubsequences = function(nums, k) { + let maxFrequency = 0; + let currentFrequency = 1; + + for (let i = 1; i < nums.length; i++) { + currentFrequency = nums[i] === nums[i - 1] ? currentFrequency + 1 : 1; + maxFrequency = Math.max(maxFrequency, currentFrequency); + } + + return k * maxFrequency <= nums.length; +}; diff --git a/solutions/1133-largest-unique-number.js b/solutions/1133-largest-unique-number.js new file mode 100644 index 00000000..7e731d63 --- /dev/null +++ b/solutions/1133-largest-unique-number.js @@ -0,0 +1,29 @@ +/** + * 1133. Largest Unique Number + * https://leetcode.com/problems/largest-unique-number/ + * Difficulty: Easy + * + * Given an integer array nums, return the largest integer that only occurs once. + * If no integer occurs once, return -1. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var largestUniqueNumber = function(nums) { + const map = new Map(); + + for (const num of nums) { + map.set(num, (map.get(num) || 0) + 1); + } + + let result = -1; + for (const [num, frequency] of map) { + if (frequency === 1) { + result = Math.max(result, num); + } + } + + return result; +}; diff --git a/solutions/1134-armstrong-number.js b/solutions/1134-armstrong-number.js new file mode 100644 index 00000000..cd4f9e33 --- /dev/null +++ b/solutions/1134-armstrong-number.js @@ -0,0 +1,23 @@ +/** + * 1134. Armstrong Number + * https://leetcode.com/problems/armstrong-number/ + * Difficulty: Easy + * + * Given an integer n, return true if and only if it is an Armstrong number. + * + * The k-digit number n is an Armstrong number if and only if the kth power of each digit sums to n. + */ + +/** + * @param {number} n + * @return {boolean} + */ +var isArmstrong = function(n) { + const digits = n.toString(); + const digitCount = digits.length; + const digitSum = digits + .split('') + .reduce((sum, digit) => sum + Math.pow(parseInt(digit, 10), digitCount), 0); + + return digitSum === n; +}; diff --git a/solutions/1135-connecting-cities-with-minimum-cost.js b/solutions/1135-connecting-cities-with-minimum-cost.js new file mode 100644 index 00000000..94f9062d --- /dev/null +++ b/solutions/1135-connecting-cities-with-minimum-cost.js @@ -0,0 +1,59 @@ +/** + * 1135. Connecting Cities With Minimum Cost + * https://leetcode.com/problems/connecting-cities-with-minimum-cost/ + * Difficulty: Medium + * + * There are n cities labeled from 1 to n. You are given the integer n and an array + * connections where connections[i] = [xi, yi, costi] indicates that the cost of connecting + * city xi and city yi (bidirectional connection) is costi. + * + * Return the minimum cost to connect all the n cities such that there is at least one path + * between each pair of cities. If it is impossible to connect all the n cities, return -1, + * + * The cost is the sum of the connections' costs used. + */ + +/** + * @param {number} n + * @param {number[][]} connections + * @return {number} + */ +var minimumCost = function(n, connections) { + const parent = Array.from({ length: n + 1 }, (_, i) => i); + + connections.sort((a, b) => a[2] - b[2]); + + let totalCost = 0; + let edgesUsed = 0; + + for (const [city1, city2, cost] of connections) { + if (union(city1, city2)) { + totalCost += cost; + edgesUsed++; + + if (edgesUsed === n - 1) { + return totalCost; + } + } + } + + return -1; + + function findParent(x) { + if (parent[x] !== x) { + parent[x] = findParent(parent[x]); + } + return parent[x]; + } + + function union(x, y) { + const rootX = findParent(x); + const rootY = findParent(y); + + if (rootX !== rootY) { + parent[rootX] = rootY; + return true; + } + return false; + } +}; diff --git a/solutions/1136-parallel-courses.js b/solutions/1136-parallel-courses.js new file mode 100644 index 00000000..121eaf3f --- /dev/null +++ b/solutions/1136-parallel-courses.js @@ -0,0 +1,64 @@ +/** + * 1136. Parallel Courses + * https://leetcode.com/problems/parallel-courses/ + * Difficulty: Medium + * + * You are given an integer n, which indicates that there are n courses labeled from 1 to n. + * You are also given an array relations where relations[i] = [prevCoursei, nextCoursei], + * representing a prerequisite relationship between course prevCoursei and course + * nextCoursei: course prevCoursei has to be taken before course nextCoursei. + * + * In one semester, you can take any number of courses as long as you have taken all the + * prerequisites in the previous semester for the courses you are taking. + * + * Return the minimum number of semesters needed to take all courses. If there is no way to + * take all the courses, return -1. + */ + +/** + * @param {number} n + * @param {number[][]} relations + * @return {number} + */ +var minimumSemesters = function(n, relations) { + const graph = new Map(); + const indegree = new Array(n + 1).fill(0); + + for (let i = 1; i <= n; i++) { + graph.set(i, []); + } + + for (const [prev, next] of relations) { + graph.get(prev).push(next); + indegree[next]++; + } + + const queue = []; + for (let i = 1; i <= n; i++) { + if (indegree[i] === 0) { + queue.push(i); + } + } + + let semesters = 0; + let coursesCompleted = 0; + + while (queue.length > 0) { + const currentSemesterSize = queue.length; + semesters++; + + for (let i = 0; i < currentSemesterSize; i++) { + const course = queue.shift(); + coursesCompleted++; + + for (const nextCourse of graph.get(course)) { + indegree[nextCourse]--; + if (indegree[nextCourse] === 0) { + queue.push(nextCourse); + } + } + } + } + + return coursesCompleted === n ? semesters : -1; +}; diff --git a/solutions/1150-check-if-a-number-is-majority-element-in-a-sorted-array.js b/solutions/1150-check-if-a-number-is-majority-element-in-a-sorted-array.js new file mode 100644 index 00000000..87414163 --- /dev/null +++ b/solutions/1150-check-if-a-number-is-majority-element-in-a-sorted-array.js @@ -0,0 +1,56 @@ +/** + * 1150. Check If a Number Is Majority Element in a Sorted Array + * https://leetcode.com/problems/check-if-a-number-is-majority-element-in-a-sorted-array/ + * Difficulty: Easy + * + * Given an integer array nums sorted in non-decreasing order and an integer target, return true + * if target is a majority element, or false otherwise. + * + * A majority element in an array nums is an element that appears more than nums.length / 2 times + * in the array. + */ + +/** + * @param {number[]} nums + * @param {number} target + * @return {boolean} + */ +var isMajorityElement = function(nums, target) { + const firstIndex = findFirstIndex(target); + if (firstIndex >= nums.length || nums[firstIndex] !== target) { + return false; + } + + const lastIndex = findLastIndex(target); + const frequency = lastIndex - firstIndex + 1; + + return frequency > nums.length / 2; + + function findFirstIndex(target) { + let left = 0; + let right = nums.length; + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (nums[mid] < target) { + left = mid + 1; + } else { + right = mid; + } + } + return left; + } + + function findLastIndex(target) { + let left = 0; + let right = nums.length; + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (nums[mid] <= target) { + left = mid + 1; + } else { + right = mid; + } + } + return left - 1; + } +}; diff --git a/solutions/1151-minimum-swaps-to-group-all-1s-together.js b/solutions/1151-minimum-swaps-to-group-all-1s-together.js new file mode 100644 index 00000000..5e923a94 --- /dev/null +++ b/solutions/1151-minimum-swaps-to-group-all-1s-together.js @@ -0,0 +1,32 @@ +/** + * 1151. Minimum Swaps to Group All 1's Together + * https://leetcode.com/problems/minimum-swaps-to-group-all-1s-together/ + * Difficulty: Medium + * + * Given a binary array data, return the minimum number of swaps required to group all + * 1’s present in the array together in any place in the array. + */ + +/** + * @param {number[]} data + * @return {number} + */ +var minSwaps = function(data) { + const totalOnes = data.reduce((sum, val) => sum + val, 0); + + if (totalOnes <= 1) return 0; + + let currentOnes = 0; + for (let i = 0; i < totalOnes; i++) { + currentOnes += data[i]; + } + + let maxOnes = currentOnes; + + for (let i = totalOnes; i < data.length; i++) { + currentOnes = currentOnes - data[i - totalOnes] + data[i]; + maxOnes = Math.max(maxOnes, currentOnes); + } + + return totalOnes - maxOnes; +}; diff --git a/solutions/1152-analyze-user-website-visit-pattern.js b/solutions/1152-analyze-user-website-visit-pattern.js new file mode 100644 index 00000000..fae12ef7 --- /dev/null +++ b/solutions/1152-analyze-user-website-visit-pattern.js @@ -0,0 +1,88 @@ +/** + * 1152. Analyze User Website Visit Pattern + * https://leetcode.com/problems/analyze-user-website-visit-pattern/ + * Difficulty: Medium + * + * You are given two string arrays username and website and an integer array timestamp. + * All the given arrays are of the same length and the tuple [username[i], website[i], + * timestamp[i]] indicates that the user username[i] visited the website website[i] at + * time timestamp[i]. + * + * A pattern is a list of three websites (not necessarily distinct). + * - For example, ["home", "away", "love"], ["leetcode", "love", "leetcode"], + * and ["luffy", "luffy", "luffy"] are all patterns. + * + * The score of a pattern is the number of users that visited all the websites in the + * pattern in the same order they appeared in the pattern. + * - For example, if the pattern is ["home", "away", "love"], the score is the number of + * users x such that x visited "home" then visited "away" and visited "love" after that. + * - Similarly, if the pattern is ["leetcode", "love", "leetcode"], the score is the number + * of users x such that x visited "leetcode" then visited "love" and visited "leetcode" + * one more time after that. + * - Also, if the pattern is ["luffy", "luffy", "luffy"], the score is the number of users + * x such that x visited "luffy" three different times at different timestamps. + * + * Return the pattern with the largest score. If there is more than one pattern with the + * same largest score, return the lexicographically smallest such pattern. + * + * Note that the websites in a pattern do not need to be visited contiguously, they only + * need to be visited in the order they appeared in the pattern. + */ + +/** + * @param {string[]} username + * @param {number[]} timestamp + * @param {string[]} website + * @return {string[]} + */ +var mostVisitedPattern = function(username, timestamp, website) { + const visitData = username.map((user, i) => ({ + user, + time: timestamp[i], + site: website[i] + })); + + visitData.sort((a, b) => a.time - b.time); + + const userVisits = new Map(); + + for (const visit of visitData) { + if (!userVisits.has(visit.user)) { + userVisits.set(visit.user, []); + } + userVisits.get(visit.user).push(visit.site); + } + + const patternCounts = new Map(); + + for (const [user, sites] of userVisits) { + if (sites.length < 3) continue; + + const userPatterns = new Set(); + + for (let i = 0; i < sites.length - 2; i++) { + for (let j = i + 1; j < sites.length - 1; j++) { + for (let k = j + 1; k < sites.length; k++) { + const pattern = [sites[i], sites[j], sites[k]].join(','); + userPatterns.add(pattern); + } + } + } + + for (const pattern of userPatterns) { + patternCounts.set(pattern, (patternCounts.get(pattern) || 0) + 1); + } + } + + let maxCount = 0; + let bestPattern = ''; + + for (const [pattern, count] of patternCounts) { + if (count > maxCount || (count === maxCount && pattern < bestPattern)) { + maxCount = count; + bestPattern = pattern; + } + } + + return bestPattern.split(','); +}; diff --git a/solutions/1153-string-transforms-into-another-string.js b/solutions/1153-string-transforms-into-another-string.js new file mode 100644 index 00000000..e677e77e --- /dev/null +++ b/solutions/1153-string-transforms-into-another-string.js @@ -0,0 +1,41 @@ +/** + * 1153. String Transforms Into Another String + * https://leetcode.com/problems/string-transforms-into-another-string/ + * Difficulty: Hard + * + * Given two strings str1 and str2 of the same length, determine whether you can transform + * str1 into str2 by doing zero or more conversions. + * + * In one conversion you can convert all occurrences of one character in str1 to any other + * lowercase English character. + * + * Return true if and only if you can transform str1 into str2. + */ + +/** + * @param {string} str1 + * @param {string} str2 + * @return {boolean} + */ +var canConvert = function(str1, str2) { + if (str1 === str2) return true; + + const mapping = new Map(); + const uniqueCharsInStr2 = new Set(); + for (let i = 0; i < str1.length; i++) { + const char1 = str1[i]; + const char2 = str2[i]; + + if (mapping.has(char1)) { + if (mapping.get(char1) !== char2) { + return false; + } + } else { + mapping.set(char1, char2); + } + + uniqueCharsInStr2.add(char2); + } + + return uniqueCharsInStr2.size < 26; +}; diff --git a/solutions/1165-single-row-keyboard.js b/solutions/1165-single-row-keyboard.js new file mode 100644 index 00000000..58c34abc --- /dev/null +++ b/solutions/1165-single-row-keyboard.js @@ -0,0 +1,39 @@ +/** + * 1165. Single-Row Keyboard + * https://leetcode.com/problems/single-row-keyboard/ + * Difficulty: Easy + * + * There is a special keyboard with all keys in a single row. + * + * Given a string keyboard of length 26 indicating the layout of the keyboard (indexed + * from 0 to 25). Initially, your finger is at index 0. To type a character, you have + * to move your finger to the index of the desired character. The time taken to move + * your finger from index i to index j is |i - j|. + * + * You want to type a string word. Write a function to calculate how much time it takes + * to type it with one finger. + */ + +/** + * @param {string} keyboard + * @param {string} word + * @return {number} + */ +var calculateTime = function(keyboard, word) { + const map = new Map(); + + for (let i = 0; i < keyboard.length; i++) { + map.set(keyboard[i], i); + } + + let currentPosition = 0; + let result = 0; + + for (const char of word) { + const targetPosition = map.get(char); + result += Math.abs(currentPosition - targetPosition); + currentPosition = targetPosition; + } + + return result; +}; diff --git a/solutions/1166-design-file-system.js b/solutions/1166-design-file-system.js new file mode 100644 index 00000000..71af7964 --- /dev/null +++ b/solutions/1166-design-file-system.js @@ -0,0 +1,52 @@ +/** + * 1166. Design File System + * https://leetcode.com/problems/design-file-system/ + * Difficulty: Medium + * + * You are asked to design a file system that allows you to create new paths and associate + * them with different values. + * + * The format of a path is one or more concatenated strings of the form: / followed by one + * or more lowercase English letters. For example, "/leetcode" and "/leetcode/problems" are + * valid paths while an empty string "" and "/" are not. + * + * Implement the FileSystem class: + * - bool createPath(string path, int value) Creates a new path and associates a value to it + * if possible and returns true. Returns false if the path already exists or its parent path + * doesn't exist. + * - int get(string path) Returns the value associated with path or returns -1 if the path + * doesn't exist. + */ + +var FileSystem = function() { + this.pathMap = new Map(); +}; + +/** + * @param {string} path + * @param {number} value + * @return {boolean} + */ +FileSystem.prototype.createPath = function(path, value) { + if (this.pathMap.has(path)) { + return false; + } + + const lastSlashIndex = path.lastIndexOf('/'); + const parentPath = path.substring(0, lastSlashIndex); + + if (parentPath.length > 0 && !this.pathMap.has(parentPath)) { + return false; + } + + this.pathMap.set(path, value); + return true; +}; + +/** + * @param {string} path + * @return {number} + */ +FileSystem.prototype.get = function(path) { + return this.pathMap.get(path) ?? -1; +}; diff --git a/solutions/1167-minimum-cost-to-connect-sticks.js b/solutions/1167-minimum-cost-to-connect-sticks.js new file mode 100644 index 00000000..db2ee2b4 --- /dev/null +++ b/solutions/1167-minimum-cost-to-connect-sticks.js @@ -0,0 +1,38 @@ +/** + * 1167. Minimum Cost to Connect Sticks + * https://leetcode.com/problems/minimum-cost-to-connect-sticks/ + * Difficulty: Medium + * + * You have some number of sticks with positive integer lengths. These lengths are given as + * an array sticks, where sticks[i] is the length of the ith stick. + * + * You can connect any two sticks of lengths x and y into one stick by paying a cost of x + y. + * You must connect all the sticks until there is only one stick remaining. + * + * Return the minimum cost of connecting all the given sticks into one stick in this way. + */ + +/** + * @param {number[]} sticks + * @return {number} + */ +var connectSticks = function(sticks) { + const minHeap = [...sticks].sort((a, b) => a - b); + let result = 0; + + while (minHeap.length > 1) { + const first = minHeap.shift(); + const second = minHeap.shift(); + const combinedCost = first + second; + + result += combinedCost; + + let insertIndex = 0; + while (insertIndex < minHeap.length && minHeap[insertIndex] < combinedCost) { + insertIndex++; + } + minHeap.splice(insertIndex, 0, combinedCost); + } + + return result; +}; diff --git a/solutions/1168-optimize-water-distribution-in-a-village.js b/solutions/1168-optimize-water-distribution-in-a-village.js new file mode 100644 index 00000000..74be1b50 --- /dev/null +++ b/solutions/1168-optimize-water-distribution-in-a-village.js @@ -0,0 +1,68 @@ +/** + * 1168. Optimize Water Distribution in a Village + * https://leetcode.com/problems/optimize-water-distribution-in-a-village/ + * Difficulty: Hard + * + * There are n houses in a village. We want to supply water for all the houses by building + * wells and laying pipes. + * + * For each house i, we can either build a well inside it directly with cost wells[i - 1] + * (note the -1 due to 0-indexing), or pipe in water from another well to it. The costs + * to lay pipes between houses are given by the array pipes where each + * pipes[j] = [house1j, house2j, costj] represents the cost to connect house1j and house2j + * together using a pipe. Connections are bidirectional, and there could be multiple valid + * connections between the same two houses with different costs. + * + * Return the minimum total cost to supply water to all houses. + */ + +/** + * @param {number} n + * @param {number[]} wells + * @param {number[][]} pipes + * @return {number} + */ +var minCostToSupplyWater = function(n, wells, pipes) { + const edges = []; + + for (let i = 0; i < n; i++) { + edges.push([0, i + 1, wells[i]]); + } + + for (const [house1, house2, cost] of pipes) { + edges.push([house1, house2, cost]); + } + + edges.sort((a, b) => a[2] - b[2]); + + const parent = Array.from({ length: n + 1 }, (_, i) => i); + let result = 0; + let edgesUsed = 0; + + for (const [from, to, cost] of edges) { + if (union(from, to)) { + result += cost; + edgesUsed++; + if (edgesUsed === n) break; + } + } + + return result; + + function find(x) { + if (parent[x] !== x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + function union(x, y) { + const rootX = find(x); + const rootY = find(y); + if (rootX !== rootY) { + parent[rootX] = rootY; + return true; + } + return false; + } +}; diff --git a/solutions/1176-diet-plan-performance.js b/solutions/1176-diet-plan-performance.js new file mode 100644 index 00000000..4bb18c83 --- /dev/null +++ b/solutions/1176-diet-plan-performance.js @@ -0,0 +1,48 @@ +/** + * 1176. Diet Plan Performance + * https://leetcode.com/problems/diet-plan-performance/ + * Difficulty: Easy + * + * A dieter consumes calories[i] calories on the i-th day. + * + * Given an integer k, for every consecutive sequence of k days + * (calories[i], calories[i+1], ..., calories[i+k-1] for all 0 <= i <= n-k), + * they look at T, the total calories consumed during that sequence of k days + * (calories[i] + calories[i+1] + ... + calories[i+k-1]): + * - If T < lower, they performed poorly on their diet and lose 1 point; + * - If T > upper, they performed well on their diet and gain 1 point; + * - Otherwise, they performed normally and there is no change in points. + * + * Initially, the dieter has zero points. Return the total number of points the dieter + * has after dieting for calories.length days. + * + * Note that the total points can be negative. + */ + +/** + * @param {number[]} calories + * @param {number} k + * @param {number} lower + * @param {number} upper + * @return {number} + */ +var dietPlanPerformance = function(calories, k, lower, upper) { + let windowSum = 0; + let points = 0; + + for (let i = 0; i < k; i++) { + windowSum += calories[i]; + } + + if (windowSum < lower) points--; + else if (windowSum > upper) points++; + + for (let i = k; i < calories.length; i++) { + windowSum = windowSum - calories[i - k] + calories[i]; + + if (windowSum < lower) points--; + else if (windowSum > upper) points++; + } + + return points; +}; diff --git a/solutions/1180-count-substrings-with-only-one-distinct-letter.js b/solutions/1180-count-substrings-with-only-one-distinct-letter.js new file mode 100644 index 00000000..4d61be97 --- /dev/null +++ b/solutions/1180-count-substrings-with-only-one-distinct-letter.js @@ -0,0 +1,29 @@ +/** + * 1180. Count Substrings with Only One Distinct Letter + * https://leetcode.com/problems/count-substrings-with-only-one-distinct-letter/ + * Difficulty: Easy + * + * Given a string s, return the number of substrings that have only one distinct letter. + */ + +/** + * @param {string} s + * @return {number} + */ +var countLetters = function(s) { + let result = 0; + let consecutiveCount = 1; + + for (let i = 1; i < s.length; i++) { + if (s[i] === s[i - 1]) { + consecutiveCount++; + } else { + result += (consecutiveCount * (consecutiveCount + 1)) / 2; + consecutiveCount = 1; + } + } + + result += (consecutiveCount * (consecutiveCount + 1)) / 2; + + return result; +}; diff --git a/solutions/1181-before-and-after-puzzle.js b/solutions/1181-before-and-after-puzzle.js new file mode 100644 index 00000000..9aa544b9 --- /dev/null +++ b/solutions/1181-before-and-after-puzzle.js @@ -0,0 +1,46 @@ +/** + * 1181. Before and After Puzzle + * https://leetcode.com/problems/before-and-after-puzzle/ + * Difficulty: Medium + * + * Given a list of phrases, generate a list of Before and After puzzles. + * + * A phrase is a string that consists of lowercase English letters and spaces only. No + * space appears in the start or the end of a phrase. There are no consecutive spaces + * in a phrase. + * + * Before and After puzzles are phrases that are formed by merging two phrases where the + * last word of the first phrase is the same as the first word of the second phrase. + * + * Return the Before and After puzzles that can be formed by every two phrases phrases[i] + * and phrases[j] where i != j. Note that the order of matching two phrases matters, we + * want to consider both orders. + * + * You should return a list of distinct strings sorted lexicographically. + */ + +/** + * @param {string[]} phrases + * @return {string[]} + */ +var beforeAndAfterPuzzles = function(phrases) { + const set = new Set(); + + for (let i = 0; i < phrases.length; i++) { + for (let j = 0; j < phrases.length; j++) { + if (i !== j) { + const firstWords = phrases[i].split(' '); + const secondWords = phrases[j].split(' '); + + const lastWordFirst = firstWords[firstWords.length - 1]; + const firstWordSecond = secondWords[0]; + if (lastWordFirst === firstWordSecond) { + const merged = firstWords.concat(secondWords.slice(1)).join(' '); + set.add(merged); + } + } + } + } + + return Array.from(set).sort(); +}; diff --git a/solutions/1182-shortest-distance-to-target-color.js b/solutions/1182-shortest-distance-to-target-color.js new file mode 100644 index 00000000..469c8aab --- /dev/null +++ b/solutions/1182-shortest-distance-to-target-color.js @@ -0,0 +1,50 @@ +/** + * 1182. Shortest Distance to Target Color + * https://leetcode.com/problems/shortest-distance-to-target-color/ + * Difficulty: Medium + * + * You are given an array colors, in which there are three colors: 1, 2 and 3. + * + * You are also given some queries. Each query consists of two integers i and c, + * return the shortest distance between the given index i and the target color c. + * If there is no solution return -1. + */ + +/** + * @param {number[]} colors + * @param {number[][]} queries + * @return {number[]} + */ +var shortestDistanceColor = function(colors, queries) { + const colorIndices = { 1: [], 2: [], 3: [] }; + + for (let i = 0; i < colors.length; i++) { + colorIndices[colors[i]].push(i); + } + + return queries.map(([index, color]) => + findClosestDistance(index, colorIndices[color]) + ); + + function findClosestDistance(targetIndex, colorArray) { + if (colorArray.length === 0) return -1; + + let left = 0; + let right = colorArray.length - 1; + let closestDistance = Infinity; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + const distance = Math.abs(colorArray[mid] - targetIndex); + closestDistance = Math.min(closestDistance, distance); + + if (colorArray[mid] < targetIndex) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return closestDistance; + } +}; diff --git a/solutions/1183-maximum-number-of-ones.js b/solutions/1183-maximum-number-of-ones.js new file mode 100644 index 00000000..1e50b44b --- /dev/null +++ b/solutions/1183-maximum-number-of-ones.js @@ -0,0 +1,38 @@ +/** + * 1183. Maximum Number of Ones + * https://leetcode.com/problems/maximum-number-of-ones/ + * Difficulty: Hard + * + * Consider a matrix M with dimensions width * height, such that every cell has value 0 or 1, + * and any square sub-matrix of M of size sideLength * sideLength has at most maxOnes ones. + * + * Return the maximum possible number of ones that the matrix M can have. + */ + +/** + * @param {number} width + * @param {number} height + * @param {number} sideLength + * @param {number} maxOnes + * @return {number} + */ +var maximumNumberOfOnes = function(width, height, sideLength, maxOnes) { + const frequencies = []; + + for (let i = 0; i < sideLength; i++) { + for (let j = 0; j < sideLength; j++) { + const rowCount = Math.ceil((height - i) / sideLength); + const colCount = Math.ceil((width - j) / sideLength); + frequencies.push(rowCount * colCount); + } + } + + frequencies.sort((a, b) => b - a); + + let result = 0; + for (let i = 0; i < maxOnes; i++) { + result += frequencies[i]; + } + + return result; +}; diff --git a/solutions/1196-how-many-apples-can-you-put-into-the-basket.js b/solutions/1196-how-many-apples-can-you-put-into-the-basket.js new file mode 100644 index 00000000..8d7a4531 --- /dev/null +++ b/solutions/1196-how-many-apples-can-you-put-into-the-basket.js @@ -0,0 +1,32 @@ +/** + * 1196. How Many Apples Can You Put into the Basket + * https://leetcode.com/problems/how-many-apples-can-you-put-into-the-basket/ + * Difficulty: Easy + * + * You have some apples and a basket that can carry up to 5000 units of weight. + * + * Given an integer array weight where weight[i] is the weight of the ith apple, + * return the maximum number of apples you can put in the basket. + */ + +/** + * @param {number[]} weight + * @return {number} + */ +var maxNumberOfApples = function(weight) { + weight.sort((a, b) => a - b); + + let totalWeight = 0; + let result = 0; + + for (const appleWeight of weight) { + if (totalWeight + appleWeight <= 5000) { + totalWeight += appleWeight; + result++; + } else { + break; + } + } + + return result; +}; diff --git a/solutions/1197-minimum-knight-moves.js b/solutions/1197-minimum-knight-moves.js new file mode 100644 index 00000000..7c1b59e7 --- /dev/null +++ b/solutions/1197-minimum-knight-moves.js @@ -0,0 +1,43 @@ +/** + * 1197. Minimum Knight Moves + * https://leetcode.com/problems/minimum-knight-moves/ + * Difficulty: Medium + * + * In an infinite chess board with coordinates from -infinity to +infinity, you have + * a knight at square [0, 0]. + * + * A knight has 8 possible moves it can make, as illustrated below. Each move is two + * squares in a cardinal direction, then one square in an orthogonal direction. + * + * Return the minimum number of steps needed to move the knight to the square [x, y]. + * It is guaranteed the answer exists. + */ + +/** + * @param {number} x + * @param {number} y + * @return {number} + */ +var minKnightMoves = function(x, y) { + x = Math.abs(x); + y = Math.abs(y); + + const memo = new Map(); + return dfs(x, y); + + function dfs(currX, currY) { + if (currX + currY === 0) return 0; + if (currX + currY === 2) return 2; + + const key = `${currX},${currY}`; + if (memo.has(key)) return memo.get(key); + + const result = Math.min( + dfs(Math.abs(currX - 1), Math.abs(currY - 2)), + dfs(Math.abs(currX - 2), Math.abs(currY - 1)) + ) + 1; + + memo.set(key, result); + return result; + } +}; diff --git a/solutions/1198-find-smallest-common-element-in-all-rows.js b/solutions/1198-find-smallest-common-element-in-all-rows.js new file mode 100644 index 00000000..9f777b33 --- /dev/null +++ b/solutions/1198-find-smallest-common-element-in-all-rows.js @@ -0,0 +1,31 @@ +/** + * 1198. Find Smallest Common Element in All Rows + * https://leetcode.com/problems/find-smallest-common-element-in-all-rows/ + * Difficulty: Medium + * + * Given an m x n matrix mat where every row is sorted in strictly increasing order, + * return the smallest common element in all rows. + * + * If there is no common element, return -1. + */ + +/** + * @param {number[][]} mat + * @return {number} + */ +var smallestCommonElement = function(mat) { + const map = new Map(); + const rows = mat.length; + + for (let i = 0; i < rows; i++) { + for (const element of mat[i]) { + map.set(element, (map.get(element) || 0) + 1); + + if (map.get(element) === rows) { + return element; + } + } + } + + return -1; +}; diff --git a/solutions/1199-minimum-time-to-build-blocks.js b/solutions/1199-minimum-time-to-build-blocks.js new file mode 100644 index 00000000..76cd4a45 --- /dev/null +++ b/solutions/1199-minimum-time-to-build-blocks.js @@ -0,0 +1,42 @@ +/** + * 1199. Minimum Time to Build Blocks + * https://leetcode.com/problems/minimum-time-to-build-blocks/ + * Difficulty: Hard + * + * You are given a list of blocks, where blocks[i] = t means that the i-th block needs + * t units of time to be built. A block can only be built by exactly one worker. + * + * A worker can either split into two workers (number of workers increases by one) or + * build a block then go home. Both decisions cost some time. + * + * The time cost of spliting one worker into two workers is given as an integer split. + * Note that if two workers split at the same time, they split in parallel so the cost + * would be split. + * + * Output the minimum time needed to build all blocks. + * + * Initially, there is only one worker. + */ + +/** + * @param {number[]} blocks + * @param {number} split + * @return {number} + */ +var minBuildTime = function(blocks, split) { + const minHeap = new PriorityQueue((a, b) => a - b); + + for (const block of blocks) { + minHeap.enqueue(block); + } + + while (minHeap.size() > 1) { + const first = minHeap.dequeue(); + const second = minHeap.dequeue(); + + const mergedTime = split + Math.max(first, second); + minHeap.enqueue(mergedTime); + } + + return minHeap.dequeue(); +}; diff --git a/solutions/1213-intersection-of-three-sorted-arrays.js b/solutions/1213-intersection-of-three-sorted-arrays.js new file mode 100644 index 00000000..86bddea1 --- /dev/null +++ b/solutions/1213-intersection-of-three-sorted-arrays.js @@ -0,0 +1,37 @@ +/** + * 1213. Intersection of Three Sorted Arrays + * https://leetcode.com/problems/intersection-of-three-sorted-arrays/ + * Difficulty: Easy + * + * Given three integer arrays arr1, arr2 and arr3 sorted in strictly increasing order, + * return a sorted array of only the integers that appeared in all three arrays. + */ + +/** + * @param {number[]} arr1 + * @param {number[]} arr2 + * @param {number[]} arr3 + * @return {number[]} + */ +var arraysIntersection = function(arr1, arr2, arr3) { + let i = 0; + let j = 0; + let k = 0; + const result = []; + + while (i < arr1.length && j < arr2.length && k < arr3.length) { + if (arr1[i] === arr2[j] && arr2[j] === arr3[k]) { + result.push(arr1[i]); + i++; + j++; + k++; + } else { + const minValue = Math.min(arr1[i], arr2[j], arr3[k]); + if (arr1[i] === minValue) i++; + if (arr2[j] === minValue) j++; + if (arr3[k] === minValue) k++; + } + } + + return result; +}; diff --git a/solutions/1214-two-sum-bsts.js b/solutions/1214-two-sum-bsts.js new file mode 100644 index 00000000..c8452c8d --- /dev/null +++ b/solutions/1214-two-sum-bsts.js @@ -0,0 +1,45 @@ +/** + * 1214. Two Sum BSTs + * https://leetcode.com/problems/two-sum-bsts/ + * Difficulty: Medium + * + * Given the roots of two binary search trees, root1 and root2, return true if and only if + * there is a node in the first tree and a node in the second tree whose values sum up to + * a given integer target. + */ + +/** + * 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} root1 + * @param {TreeNode} root2 + * @param {number} target + * @return {boolean} + */ +var twoSumBSTs = function(root1, root2, target) { + const valuesSet = new Set(); + collectValues(root1); + return searchForComplement(root2); + + function collectValues(node) { + if (!node) return; + valuesSet.add(node.val); + collectValues(node.left); + collectValues(node.right); + } + + function searchForComplement(node) { + if (!node) return false; + + const complement = target - node.val; + if (valuesSet.has(complement)) return true; + + return searchForComplement(node.left) || searchForComplement(node.right); + } +}; diff --git a/solutions/1215-stepping-numbers.js b/solutions/1215-stepping-numbers.js new file mode 100644 index 00000000..3051bc98 --- /dev/null +++ b/solutions/1215-stepping-numbers.js @@ -0,0 +1,53 @@ +/** + * 1215. Stepping Numbers + * https://leetcode.com/problems/stepping-numbers/ + * Difficulty: Medium + * + * A stepping number is an integer such that all of its adjacent digits have an absolute + * difference of exactly 1. + * - For example, 321 is a stepping number while 421 is not. + * + * Given two integers low and high, return a sorted list of all the stepping numbers in the + * inclusive range [low, high]. + */ + +/** + * @param {number} low + * @param {number} high + * @return {number[]} + */ +var countSteppingNumbers = function(low, high) { + const result = []; + + if (low === 0) result.push(0); + + const minLength = low.toString().length; + const maxLength = high.toString().length; + + for (let length = minLength; length <= maxLength; length++) { + for (let start = 1; start <= 9; start++) { + dfs(start.toString(), length); + } + } + + return result.sort((a, b) => a - b); + + function dfs(current, targetLength) { + if (current.length === targetLength) { + const num = parseInt(current); + if (num >= low && num <= high) { + result.push(num); + } + return; + } + + const lastDigit = parseInt(current[current.length - 1]); + + if (lastDigit > 0) { + dfs(current + (lastDigit - 1), targetLength); + } + if (lastDigit < 9) { + dfs(current + (lastDigit + 1), targetLength); + } + } +}; diff --git a/solutions/1216-valid-palindrome-iii.js b/solutions/1216-valid-palindrome-iii.js new file mode 100644 index 00000000..2371169f --- /dev/null +++ b/solutions/1216-valid-palindrome-iii.js @@ -0,0 +1,42 @@ +/** + * 1216. Valid Palindrome III + * https://leetcode.com/problems/valid-palindrome-iii/ + * Difficulty: Hard + * + * Given a string s and an integer k, return true if s is a k-palindrome. + * + * A string is k-palindrome if it can be transformed into a palindrome by removing + * at most k characters from it. + */ + +/** + * @param {string} s + * @param {number} k + * @return {boolean} + */ +var isValidPalindrome = function(s, k) { + const n = s.length; + const memo = new Array(n).fill().map(() => new Array(n).fill(-1)); + const longestPalindrome = longestPalindromeSubseq(0, n - 1); + const deletions = n - longestPalindrome; + + return deletions <= k; + + function longestPalindromeSubseq(left, right) { + if (left > right) return 0; + if (left === right) return 1; + + if (memo[left][right] !== -1) return memo[left][right]; + + if (s[left] === s[right]) { + memo[left][right] = 2 + longestPalindromeSubseq(left + 1, right - 1); + } else { + memo[left][right] = Math.max( + longestPalindromeSubseq(left + 1, right), + longestPalindromeSubseq(left, right - 1) + ); + } + + return memo[left][right]; + } +}; diff --git a/solutions/1228-missing-number-in-arithmetic-progression.js b/solutions/1228-missing-number-in-arithmetic-progression.js new file mode 100644 index 00000000..67fff03e --- /dev/null +++ b/solutions/1228-missing-number-in-arithmetic-progression.js @@ -0,0 +1,30 @@ +/** + * 1228. Missing Number In Arithmetic Progression + * https://leetcode.com/problems/missing-number-in-arithmetic-progression/ + * Difficulty: Easy + * + * In some array arr, the values were in arithmetic progression: the values + * arr[i + 1] - arr[i] are all equal for every 0 <= i < arr.length - 1. + * + * A value from arr was removed that was not the first or last value in the array. + * + * Given arr, return the removed value. + */ + +/** + * @param {number[]} arr + * @return {number} + */ +var missingNumber = function(arr) { + const n = arr.length; + const totalDiff = arr[n - 1] - arr[0]; + const expectedDiff = totalDiff / n; + + for (let i = 1; i < n; i++) { + if (arr[i] - arr[i - 1] !== expectedDiff) { + return arr[i - 1] + expectedDiff; + } + } + + return arr[0] + expectedDiff; +}; diff --git a/solutions/1229-meeting-scheduler.js b/solutions/1229-meeting-scheduler.js new file mode 100644 index 00000000..c0f8f772 --- /dev/null +++ b/solutions/1229-meeting-scheduler.js @@ -0,0 +1,49 @@ +/** + * 1229. Meeting Scheduler + * https://leetcode.com/problems/meeting-scheduler/ + * Difficulty: Medium + * + * Given the availability time slots arrays slots1 and slots2 of two people and a meeting + * duration duration, return the earliest time slot that works for both of them and is of + * duration duration. + * + * If there is no common time slot that satisfies the requirements, return an empty array. + * + * The format of a time slot is an array of two elements [start, end] representing an + * inclusive time range from start to end. + * + * It is guaranteed that no two availability slots of the same person intersect with each + * other. That is, for any two time slots [start1, end1] and [start2, end2] of the same + * person, either start1 > end2 or start2 > end1. + */ + +/** + * @param {number[][]} slots1 + * @param {number[][]} slots2 + * @param {number} duration + * @return {number[]} + */ +var minAvailableDuration = function(slots1, slots2, duration) { + slots1.sort((a, b) => a[0] - b[0]); + slots2.sort((a, b) => a[0] - b[0]); + + let i = 0; + let j = 0; + + while (i < slots1.length && j < slots2.length) { + const overlapStart = Math.max(slots1[i][0], slots2[j][0]); + const overlapEnd = Math.min(slots1[i][1], slots2[j][1]); + + if (overlapEnd - overlapStart >= duration) { + return [overlapStart, overlapStart + duration]; + } + + if (slots1[i][1] < slots2[j][1]) { + i++; + } else { + j++; + } + } + + return []; +}; diff --git a/solutions/1230-toss-strange-coins.js b/solutions/1230-toss-strange-coins.js new file mode 100644 index 00000000..b78575e7 --- /dev/null +++ b/solutions/1230-toss-strange-coins.js @@ -0,0 +1,30 @@ +/** + * 1230. Toss Strange Coins + * https://leetcode.com/problems/toss-strange-coins/ + * Difficulty: Medium + * + * You have some coins. The i-th coin has a probability prob[i] of facing heads when tossed. + * + * Return the probability that the number of coins facing heads equals target if you toss every + * coin exactly once. + */ + +/** + * @param {number[]} prob + * @param {number} target + * @return {number} + */ +var probabilityOfHeads = function(prob, target) { + const n = prob.length; + const dp = new Array(target + 1).fill(0); + dp[0] = 1; + + for (let i = 0; i < n; i++) { + for (let j = Math.min(i + 1, target); j >= 1; j--) { + dp[j] = dp[j] * (1 - prob[i]) + dp[j - 1] * prob[i]; + } + dp[0] *= (1 - prob[i]); + } + + return dp[target]; +}; diff --git a/solutions/1231-divide-chocolate.js b/solutions/1231-divide-chocolate.js new file mode 100644 index 00000000..cbb25425 --- /dev/null +++ b/solutions/1231-divide-chocolate.js @@ -0,0 +1,55 @@ +/** + * 1231. Divide Chocolate + * https://leetcode.com/problems/divide-chocolate/ + * Difficulty: Hard + * + * You have one chocolate bar that consists of some chunks. Each chunk has its own sweetness + * given by the array sweetness. + * + * You want to share the chocolate with your k friends so you start cutting the chocolate bar + * into k + 1 pieces using k cuts, each piece consists of some consecutive chunks. + * + * Being generous, you will eat the piece with the minimum total sweetness and give the other + * pieces to your friends. + * + * Find the maximum total sweetness of the piece you can get by cutting the chocolate bar optimally. + */ + +/** + * @param {number[]} sweetness + * @param {number} k + * @return {number} + */ +var maximizeSweetness = function(sweetness, k) { + let left = Math.min(...sweetness); + let right = sweetness.reduce((sum, val) => sum + val, 0); + let result = left; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + + if (canDivide(mid)) { + result = mid; + left = mid + 1; + } else { + right = mid - 1; + } + } + + return result; + + function canDivide(minSweetness) { + let pieces = 0; + let currentSum = 0; + + for (const chunk of sweetness) { + currentSum += chunk; + if (currentSum >= minSweetness) { + pieces++; + currentSum = 0; + } + } + + return pieces >= k + 1; + } +}; diff --git a/solutions/1236-web-crawler.js b/solutions/1236-web-crawler.js new file mode 100644 index 00000000..b5d4a40c --- /dev/null +++ b/solutions/1236-web-crawler.js @@ -0,0 +1,69 @@ +/** + * 1236. Web Crawler + * https://leetcode.com/problems/web-crawler/ + * Difficulty: Medium + * + * Given a url startUrl and an interface HtmlParser, implement a web crawler to crawl all + * links that are under the same hostname as startUrl. + * + * Return all urls obtained by your web crawler in any order. + * + * Your crawler should: + * - Start from the page: startUrl + * - Call HtmlParser.getUrls(url) to get all urls from a webpage of given url. + * - Do not crawl the same link twice. + * - Explore only the links that are under the same hostname as startUrl. + * + * As shown in the example url above, the hostname is example.org. For simplicity sake, you may + * assume all urls use http protocol without any port specified. For example, the urls + * http://leetcode.com/problems and http://leetcode.com/contest are under the same hostname, + * while urls http://example.org/test and http://example.com/abc are not under the same hostname. + * + * The HtmlParser interface is defined as such: + * interface HtmlParser { + * // Return a list of all urls from a webpage of given url. + * public List getUrls(String url); + * } + * + * Below are two examples explaining the functionality of the problem, for custom testing purposes + * you'll have three variables urls, edges and startUrl. Notice that you will only have access to + * startUrl in your code, while urls and edges are not directly accessible to you in code. + * + * Note: Consider the same URL with the trailing slash "/" as a different URL. For example, + * "http://news.yahoo.com", and "http://news.yahoo.com/" are different urls. + */ + +/** + * @param {string} startUrl + * @param {HtmlParser} htmlParser + * @return {string[]} +*/ +var crawl = function(startUrl, htmlParser) { + const targetHostname = getHostname(startUrl); + const visited = new Set(); + const queue = [startUrl]; + const result = []; + + while (queue.length > 0) { + const currentUrl = queue.shift(); + + if (visited.has(currentUrl)) continue; + + visited.add(currentUrl); + result.push(currentUrl); + + const urls = htmlParser.getUrls(currentUrl); + + for (const url of urls) { + if (!visited.has(url) && getHostname(url) === targetHostname) { + queue.push(url); + } + } + } + + return result; + + function getHostname(url) { + return url.split('/')[2]; + } +}; diff --git a/solutions/1243-array-transformation.js b/solutions/1243-array-transformation.js new file mode 100644 index 00000000..43bd2c30 --- /dev/null +++ b/solutions/1243-array-transformation.js @@ -0,0 +1,47 @@ +/** + * 1243. Array Transformation + * https://leetcode.com/problems/array-transformation/ + * Difficulty: Easy + * + * Given an initial array arr, every day you produce a new array using the array of the + * previous day. + * + * On the i-th day, you do the following operations on the array of day i-1 to produce + * the array of day i: + * - If an element is smaller than both its left neighbor and its right neighbor, then this + * element is incremented. + * - If an element is bigger than both its left neighbor and its right neighbor, then this + * element is decremented. + * + * The first and last elements never change. + * + * After some days, the array does not change. Return that final array. + */ + +/** + * @param {number[]} arr + * @return {number[]} + */ +var transformArray = function(arr) { + let current = [...arr]; + + while (true) { + const next = [...current]; + let changed = false; + + for (let i = 1; i < current.length - 1; i++) { + if (current[i] < current[i - 1] && current[i] < current[i + 1]) { + next[i]++; + changed = true; + } else if (current[i] > current[i - 1] && current[i] > current[i + 1]) { + next[i]--; + changed = true; + } + } + + if (!changed) break; + current = next; + } + + return current; +}; diff --git a/solutions/1244-design-a-leaderboard.js b/solutions/1244-design-a-leaderboard.js new file mode 100644 index 00000000..0b1fe9f7 --- /dev/null +++ b/solutions/1244-design-a-leaderboard.js @@ -0,0 +1,47 @@ +/** + * 1244. Design A Leaderboard + * https://leetcode.com/problems/design-a-leaderboard/ + * Difficulty: Medium + * + * Design a Leaderboard class, which has 3 functions: + * - addScore(playerId, score): Update the leaderboard by adding score to the given player's + * score. If there is no player with such id in the leaderboard, add him to the leaderboard + * with the given score. + * - top(K): Return the score sum of the top K players. + * - reset(playerId): Reset the score of the player with the given id to 0 (in other words + * erase it from the leaderboard). It is guaranteed that the player was added to the leaderboard + * before calling this function. + * + * Initially, the leaderboard is empty. + */ + + +var Leaderboard = function() { + this.scores = new Map(); +}; + +/** + * @param {number} playerId + * @param {number} score + * @return {void} + */ +Leaderboard.prototype.addScore = function(playerId, score) { + this.scores.set(playerId, (this.scores.get(playerId) || 0) + score); +}; + +/** + * @param {number} K + * @return {number} + */ +Leaderboard.prototype.top = function(K) { + const sortedScores = Array.from(this.scores.values()).sort((a, b) => b - a); + return sortedScores.slice(0, K).reduce((sum, score) => sum + score, 0); +}; + +/** + * @param {number} playerId + * @return {void} + */ +Leaderboard.prototype.reset = function(playerId) { + this.scores.delete(playerId); +}; diff --git a/solutions/1245-tree-diameter.js b/solutions/1245-tree-diameter.js new file mode 100644 index 00000000..b086c2b5 --- /dev/null +++ b/solutions/1245-tree-diameter.js @@ -0,0 +1,60 @@ +/** + * 1245. Tree Diameter + * https://leetcode.com/problems/tree-diameter/ + * Difficulty: Medium + * + * The diameter of a tree is the number of edges in the longest path in that tree. + * + * There is an undirected tree of n nodes labeled from 0 to n - 1. You are given a 2D array + * edges where edges.length == n - 1 and edges[i] = [ai, bi] indicates that there is an + * undirected edge between nodes ai and bi in the tree. + * + * Return the diameter of the tree. + */ + +/** + * @param {number[][]} edges + * @return {number} + */ +var treeDiameter = function(edges) { + if (edges.length === 0) return 0; + + const graph = new Map(); + for (const [a, b] of edges) { + if (!graph.has(a)) graph.set(a, []); + if (!graph.has(b)) graph.set(b, []); + graph.get(a).push(b); + graph.get(b).push(a); + } + + const [farthestFromStart] = bfs(0); + const [, diameter] = bfs(farthestFromStart); + + return diameter; + + function bfs(start) { + const visited = new Set(); + const queue = [[start, 0]]; + visited.add(start); + let farthestNode = start; + let maxDistance = 0; + + while (queue.length > 0) { + const [node, distance] = queue.shift(); + + if (distance > maxDistance) { + maxDistance = distance; + farthestNode = node; + } + + for (const neighbor of graph.get(node) || []) { + if (!visited.has(neighbor)) { + visited.add(neighbor); + queue.push([neighbor, distance + 1]); + } + } + } + + return [farthestNode, maxDistance]; + } +}; diff --git a/solutions/1246-palindrome-removal.js b/solutions/1246-palindrome-removal.js new file mode 100644 index 00000000..32810863 --- /dev/null +++ b/solutions/1246-palindrome-removal.js @@ -0,0 +1,47 @@ +/** + * 1246. Palindrome Removal + * https://leetcode.com/problems/palindrome-removal/ + * Difficulty: Hard + * + * You are given an integer array arr. + * + * In one move, you can select a palindromic subarray arr[i], arr[i + 1], ..., arr[j] + * where i <= j, and remove that subarray from the given array. Note that after removing + * a subarray, the elements on the left and on the right of that subarray move to fill + * the gap left by the removal. + * + * Return the minimum number of moves needed to remove all numbers from the array. + */ + +/** + * @param {number[]} arr + * @return {number} + */ +var minimumMoves = function(arr) { + const n = arr.length; + const dp = new Array(n).fill().map(() => new Array(n).fill(Infinity)); + + for (let i = 0; i < n; i++) { + dp[i][i] = 1; + } + + for (let length = 2; length <= n; length++) { + for (let i = 0; i <= n - length; i++) { + const j = i + length - 1; + + if (arr[i] === arr[j]) { + if (length === 2) { + dp[i][j] = 1; + } else { + dp[i][j] = dp[i + 1][j - 1]; + } + } + + for (let k = i; k < j; k++) { + dp[i][j] = Math.min(dp[i][j], dp[i][k] + dp[k + 1][j]); + } + } + } + + return dp[0][n - 1]; +}; diff --git a/solutions/1256-encode-number.js b/solutions/1256-encode-number.js new file mode 100644 index 00000000..0b334dfc --- /dev/null +++ b/solutions/1256-encode-number.js @@ -0,0 +1,18 @@ +/** + * 1256. Encode Number + * https://leetcode.com/problems/encode-number/ + * Difficulty: Medium + * + * Given a non-negative integer num, Return its encoding string. + * + * The encoding is done by converting the integer to a string using a secret function that + * you should deduce from the following table: + */ + +/** + * @param {number} num + * @return {string} + */ +var encode = function(num) { + return (num + 1).toString(2).slice(1); +}; diff --git a/solutions/1257-smallest-common-region.js b/solutions/1257-smallest-common-region.js new file mode 100644 index 00000000..c40af77a --- /dev/null +++ b/solutions/1257-smallest-common-region.js @@ -0,0 +1,56 @@ +/** + * 1257. Smallest Common Region + * https://leetcode.com/problems/smallest-common-region/ + * Difficulty: Medium + * + * You are given some lists of regions where the first region of each list directly contains + * all other regions in that list. + * + * If a region x contains a region y directly, and region y contains region z directly, then + * region x is said to contain region z indirectly. Note that region x also indirectly contains + * all regions indirectly containd in y. + * + * Naturally, if a region x contains (either directly or indirectly) another region y, then x + * is bigger than or equal to y in size. Also, by definition, a region x contains itself. + * + * Given two regions: region1 and region2, return the smallest region that contains both of them. + * + * It is guaranteed the smallest region exists. + */ + +/** + * @param {string[][]} regions + * @param {string} region1 + * @param {string} region2 + * @return {string} + */ +var findSmallestRegion = function(regions, region1, region2) { + const map = new Map(); + + for (const region of regions) { + const parent = region[0]; + for (let i = 1; i < region.length; i++) { + map.set(region[i], parent); + } + } + + const path1 = getPath(region1); + const path2 = getPath(region2); + const set = new Set(path1); + + for (const ancestor of path2) { + if (set.has(ancestor)) { + return ancestor; + } + } + + function getPath(region) { + const path = []; + let current = region; + while (current) { + path.push(current); + current = map.get(current); + } + return path; + } +}; diff --git a/solutions/1258-synonymous-sentences.js b/solutions/1258-synonymous-sentences.js new file mode 100644 index 00000000..125d1bf9 --- /dev/null +++ b/solutions/1258-synonymous-sentences.js @@ -0,0 +1,69 @@ +/** + * 1258. Synonymous Sentences + * https://leetcode.com/problems/synonymous-sentences/ + * Difficulty: Medium + * + * You are given a list of equivalent string pairs synonyms where synonyms[i] = [si, ti] + * indicates that si and ti are equivalent strings. You are also given a sentence text. + * + * Return all possible synonymous sentences sorted lexicographically. + */ + +/** + * @param {string[][]} synonyms + * @param {string} text + * @return {string[]} + */ +var generateSentences = function(synonyms, text) { + const graph = new Map(); + + for (const [word1, word2] of synonyms) { + if (!graph.has(word1)) graph.set(word1, []); + if (!graph.has(word2)) graph.set(word2, []); + graph.get(word1).push(word2); + graph.get(word2).push(word1); + } + + const words = text.split(' '); + const allCombinations = []; + backtrack(0, []); + return allCombinations.sort(); + + function findSynonyms(word) { + if (!graph.has(word)) return [word]; + + const visited = new Set(); + const queue = [word]; + const synonymGroup = []; + + while (queue.length > 0) { + const current = queue.shift(); + if (visited.has(current)) continue; + + visited.add(current); + synonymGroup.push(current); + + for (const neighbor of graph.get(current)) { + if (!visited.has(neighbor)) { + queue.push(neighbor); + } + } + } + + return synonymGroup.sort(); + } + + function backtrack(index, currentSentence) { + if (index === words.length) { + allCombinations.push(currentSentence.join(' ')); + return; + } + + const synonyms = findSynonyms(words[index]); + for (const synonym of synonyms) { + currentSentence.push(synonym); + backtrack(index + 1, currentSentence); + currentSentence.pop(); + } + } +}; diff --git a/solutions/1259-handshakes-that-dont-cross.js b/solutions/1259-handshakes-that-dont-cross.js new file mode 100644 index 00000000..28006d83 --- /dev/null +++ b/solutions/1259-handshakes-that-dont-cross.js @@ -0,0 +1,31 @@ +/** + * 1259. Handshakes That Don't Cross + * https://leetcode.com/problems/handshakes-that-dont-cross/ + * Difficulty: Hard + * + * You are given an even number of people numPeople that stand around a circle and each + * person shakes hands with someone else so that there are numPeople / 2 handshakes total. + * + * Return the number of ways these handshakes could occur such that none of the handshakes cross. + * + * Since the answer could be very large, return it modulo 109 + 7. + */ + +/** + * @param {number} numPeople + * @return {number} + */ +var numberOfWays = function(numPeople) { + const MOD = 1e9 + 7; + const n = numPeople / 2; + const dp = new Array(n + 1).fill(0n); + dp[0] = 1n; + + for (let i = 1; i <= n; i++) { + for (let j = 0; j < i; j++) { + dp[i] = (dp[i] + dp[j] * dp[i - 1 - j]) % BigInt(MOD); + } + } + + return Number(dp[n]); +}; diff --git a/solutions/1265-print-immutable-linked-list-in-reverse.js b/solutions/1265-print-immutable-linked-list-in-reverse.js new file mode 100644 index 00000000..6435844d --- /dev/null +++ b/solutions/1265-print-immutable-linked-list-in-reverse.js @@ -0,0 +1,28 @@ +/** + * 1265. Print Immutable Linked List in Reverse + * https://leetcode.com/problems/print-immutable-linked-list-in-reverse/ + * Difficulty: Medium + * + * You are given an immutable linked list, print out all values of each node in reverse + * with the help of the following interface: + * - ImmutableListNode: An interface of immutable linked list, you are given the head of the list. + * + * You need to use the following functions to access the linked list (you can't access the + * ImmutableListNode directly): + * - ImmutableListNode.printValue(): Print value of the current node. + * - ImmutableListNode.getNext(): Return the next node. + * + * The input is only given to initialize the linked list internally. You must solve this problem + * without modifying the linked list. In other words, you must operate the linked list using + * only the mentioned APIs. + */ + +/** + * @param {ImmutableListNode} head + * @return {void} + */ +var printLinkedListInReverse = function(head) { + if (!head) return; + printLinkedListInReverse(head.getNext()); + head.printValue(); +}; diff --git a/solutions/1271-hexspeak.js b/solutions/1271-hexspeak.js new file mode 100644 index 00000000..4a5714f3 --- /dev/null +++ b/solutions/1271-hexspeak.js @@ -0,0 +1,30 @@ +/** + * 1271. Hexspeak + * https://leetcode.com/problems/hexspeak/ + * Difficulty: Easy + * + * A decimal number can be converted to its Hexspeak representation by first converting it to + * an uppercase hexadecimal string, then replacing all occurrences of the digit '0' with the + * letter 'O', and the digit '1' with the letter 'I'. Such a representation is valid if and + * only if it consists only of the letters in the set {'A', 'B', 'C', 'D', 'E', 'F', 'I', 'O'}. + * + * Given a string num representing a decimal integer n, return the Hexspeak representation of + * n if it is valid, otherwise return "ERROR". + */ + +/** + * @param {string} num + * @return {string} + */ +var toHexspeak = function(num) { + const hex = BigInt(num).toString(16).toUpperCase(); + const validChars = new Set(['0', '1', 'A', 'B', 'C', 'D', 'E', 'F']); + + for (const char of hex) { + if (!validChars.has(char)) { + return 'ERROR'; + } + } + + return hex.replace(/0/g, 'O').replace(/1/g, 'I'); +}; diff --git a/solutions/1272-remove-interval.js b/solutions/1272-remove-interval.js new file mode 100644 index 00000000..ef3b2157 --- /dev/null +++ b/solutions/1272-remove-interval.js @@ -0,0 +1,43 @@ +/** + * 1272. Remove Interval + * https://leetcode.com/problems/remove-interval/ + * Difficulty: Medium + * + * A set of real numbers can be represented as the union of several disjoint intervals, + * where each interval is in the form [a, b). A real number x is in the set if one of + * its intervals [a, b) contains x (i.e. a <= x < b). + * + * You are given a sorted list of disjoint intervals intervals representing a set of + * real numbers as described above, where intervals[i] = [ai, bi] represents the interval + * [ai, bi). You are also given another interval toBeRemoved. + * + * Return the set of real numbers with the interval toBeRemoved removed from intervals. + * In other words, return the set of real numbers such that every x in the set is in + * intervals but not in toBeRemoved. Your answer should be a sorted list of disjoint + * intervals as described above. + */ + +/** + * @param {number[][]} intervals + * @param {number[]} toBeRemoved + * @return {number[][]} + */ +var removeInterval = function(intervals, toBeRemoved) { + const result = []; + const [removeStart, removeEnd] = toBeRemoved; + + for (const [start, end] of intervals) { + if (end <= removeStart || start >= removeEnd) { + result.push([start, end]); + } else { + if (start < removeStart) { + result.push([start, removeStart]); + } + if (end > removeEnd) { + result.push([removeEnd, end]); + } + } + } + + return result; +}; diff --git a/solutions/1273-delete-tree-nodes.js b/solutions/1273-delete-tree-nodes.js new file mode 100644 index 00000000..5b9d250c --- /dev/null +++ b/solutions/1273-delete-tree-nodes.js @@ -0,0 +1,47 @@ +/** + * 1273. Delete Tree Nodes + * https://leetcode.com/problems/delete-tree-nodes/ + * Difficulty: Medium + * + * A tree rooted at node 0 is given as follows: + * - The number of nodes is nodes; + * - The value of the ith node is value[i]; + * - The parent of the ith node is parent[i]. + * + * Remove every subtree whose sum of values of nodes is zero. + * + * Return the number of the remaining nodes in the tree. + */ + +/** + * @param {number} nodes + * @param {number[]} parent + * @param {number[]} value + * @return {number} + */ +var deleteTreeNodes = function(nodes, parent, value) { + const children = new Array(nodes).fill().map(() => []); + + for (let i = 1; i < nodes; i++) { + children[parent[i]].push(i); + } + + return dfs(0)[1]; + + function dfs(node) { + let subtreeSum = value[node]; + let subtreeCount = 1; + + for (const child of children[node]) { + const [childSum, childCount] = dfs(child); + subtreeSum += childSum; + subtreeCount += childCount; + } + + if (subtreeSum === 0) { + return [0, 0]; + } + + return [subtreeSum, subtreeCount]; + } +}; diff --git a/solutions/1274-number-of-ships-in-a-rectangle.js b/solutions/1274-number-of-ships-in-a-rectangle.js new file mode 100644 index 00000000..2093511a --- /dev/null +++ b/solutions/1274-number-of-ships-in-a-rectangle.js @@ -0,0 +1,46 @@ +/** + * 1274. Number of Ships in a Rectangle + * https://leetcode.com/problems/number-of-ships-in-a-rectangle/ + * Difficulty: Hard + * + * Each ship is located at an integer point on the sea represented by a cartesian plane, and + * each integer point may contain at most 1 ship. + * + * You have a function Sea.hasShips(topRight, bottomLeft) which takes two points as arguments + * and returns true If there is at least one ship in the rectangle represented by the two + * points, including on the boundary. + * + * Given two points: the top right and bottom left corners of a rectangle, return the number + * of ships present in that rectangle. It is guaranteed that there are at most 10 ships in + * that rectangle. + * + * Submissions making more than 400 calls to hasShips will be judged Wrong Answer. Also, any + * solutions that attempt to circumvent the judge will result in disqualification. + */ + +/** + * @param {Sea} sea + * @param {integer[]} topRight + * @param {integer[]} bottomLeft + * @return {integer} + */ +var countShips = function(sea, topRight, bottomLeft) { + const [x2, y2] = topRight; + const [x1, y1] = bottomLeft; + + if (x1 > x2 || y1 > y2 || !sea.hasShips(topRight, bottomLeft)) { + return 0; + } + + if (x1 === x2 && y1 === y2) { + return 1; + } + + const midX = Math.floor((x1 + x2) / 2); + const midY = Math.floor((y1 + y2) / 2); + + return countShips(sea, [midX, midY], [x1, y1]) + + countShips(sea, [x2, midY], [midX + 1, y1]) + + countShips(sea, [midX, y2], [x1, midY + 1]) + + countShips(sea, [x2, y2], [midX + 1, midY + 1]); +}; diff --git a/solutions/1426-counting-elements.js b/solutions/1426-counting-elements.js new file mode 100644 index 00000000..1784bdef --- /dev/null +++ b/solutions/1426-counting-elements.js @@ -0,0 +1,17 @@ +/** + * 1426. Counting Elements + * https://leetcode.com/problems/counting-elements/ + * Difficulty: Easy + * + * Given an integer array arr, count how many elements x there are, such that x + 1 is also + * in arr. If there are duplicates in arr, count them separately. + */ + +/** + * @param {number[]} arr + * @return {number} + */ +var countElements = function(arr) { + const set = new Set(arr); + return arr.filter(num => set.has(num + 1)).length; +}; diff --git a/solutions/1427-perform-string-shifts.js b/solutions/1427-perform-string-shifts.js new file mode 100644 index 00000000..751826e5 --- /dev/null +++ b/solutions/1427-perform-string-shifts.js @@ -0,0 +1,32 @@ +/** + * 1427. Perform String Shifts + * https://leetcode.com/problems/perform-string-shifts/ + * Difficulty: Easy + * + * You are given a string s containing lowercase English letters, and a matrix shift, + * where shift[i] = [directioni, amounti]: + * - directioni can be 0 (for left shift) or 1 (for right shift). + * - amounti is the amount by which string s is to be shifted. + * - A left shift by 1 means remove the first character of s and append it to the end. + * - Similarly, a right shift by 1 means remove the last character of s and add it to the beginning. + * + * Return the final string after all operations. + */ + +/** + * @param {string} s + * @param {number[][]} shift + * @return {string} + */ +var stringShift = function(s, shift) { + let netShift = 0; + + for (const [direction, amount] of shift) { + netShift += direction === 0 ? -amount : amount; + } + + const n = s.length; + netShift = ((netShift % n) + n) % n; + + return s.slice(-netShift) + s.slice(0, -netShift); +}; diff --git a/solutions/1428-leftmost-column-with-at-least-a-one.js b/solutions/1428-leftmost-column-with-at-least-a-one.js new file mode 100644 index 00000000..004ae054 --- /dev/null +++ b/solutions/1428-leftmost-column-with-at-least-a-one.js @@ -0,0 +1,45 @@ +/** + * 1428. Leftmost Column with at Least a One + * https://leetcode.com/problems/leftmost-column-with-at-least-a-one/ + * Difficulty: Medium + * + * A row-sorted binary matrix means that all elements are 0 or 1 and each row of the matrix + * is sorted in non-decreasing order. + * + * Given a row-sorted binary matrix binaryMatrix, return the index (0-indexed) of the leftmost + * column with a 1 in it. If such an index does not exist, return -1. + * + * You can't access the Binary Matrix directly. You may only access the matrix using a + * BinaryMatrix interface: + * - BinaryMatrix.get(row, col) returns the element of the matrix at index (row, col) (0-indexed). + * - BinaryMatrix.dimensions() returns the dimensions of the matrix as a list of 2 + * elements [rows, cols], which means the matrix is rows x cols. + * + * Submissions making more than 1000 calls to BinaryMatrix.get will be judged Wrong Answer. + * Also, any solutions that attempt to circumvent the judge will result in disqualification. + * + * For custom testing purposes, the input will be the entire binary matrix mat. You will not + * have access to the binary matrix directly. + */ + +/** + * @param {BinaryMatrix} binaryMatrix + * @return {number} + */ +var leftMostColumnWithOne = function(binaryMatrix) { + const [rows, cols] = binaryMatrix.dimensions(); + let result = -1; + let row = 0; + let col = cols - 1; + + while (row < rows && col >= 0) { + if (binaryMatrix.get(row, col) === 1) { + result = col; + col--; + } else { + row++; + } + } + + return result; +}; diff --git a/solutions/1429-first-unique-number.js b/solutions/1429-first-unique-number.js new file mode 100644 index 00000000..de330ddf --- /dev/null +++ b/solutions/1429-first-unique-number.js @@ -0,0 +1,52 @@ +/** + * 1429. First Unique Number + * https://leetcode.com/problems/first-unique-number/ + * Difficulty: Medium + * + * You have a queue of integers, you need to retrieve the first unique integer in the queue. + * + * Implement the FirstUnique class: + * - FirstUnique(int[] nums) Initializes the object with the numbers in the queue. + * - int showFirstUnique() returns the value of the first unique integer of the queue, and + * returns -1 if there is no such integer. + * - void add(int value) insert value to the queue. + */ + +/** +* @param {number[]} nums +*/ +var FirstUnique = function(nums) { + this.queue = []; + this.counts = new Map(); + this.uniqueSet = new Set(); + + for (const num of nums) { + this.add(num); + } +}; + +/** +* @return {number} +*/ +FirstUnique.prototype.showFirstUnique = function() { + while (this.queue.length > 0 && !this.uniqueSet.has(this.queue[0])) { + this.queue.shift(); + } + return this.queue.length > 0 ? this.queue[0] : -1; +}; + +/** +* @param {number} value +* @return {void} +*/ +FirstUnique.prototype.add = function(value) { + const count = this.counts.get(value) || 0; + this.counts.set(value, count + 1); + + if (count === 0) { + this.queue.push(value); + this.uniqueSet.add(value); + } else if (count === 1) { + this.uniqueSet.delete(value); + } +}; diff --git a/solutions/1430-check-if-a-string-is-a-valid-sequence-from-root-to-leaves-path-in-a-binary-tree.js b/solutions/1430-check-if-a-string-is-a-valid-sequence-from-root-to-leaves-path-in-a-binary-tree.js new file mode 100644 index 00000000..7fcc855b --- /dev/null +++ b/solutions/1430-check-if-a-string-is-a-valid-sequence-from-root-to-leaves-path-in-a-binary-tree.js @@ -0,0 +1,41 @@ +/** + * 1430. Check If a String Is a Valid Sequence from Root to Leaves Path in a Binary Tree + * https://leetcode.com/problems/check-if-a-string-is-a-valid-sequence-from-root-to-leaves-path-in-a-binary-tree/ + * Difficulty: Medium + * + * Given a binary tree where each path going from the root to any leaf form a valid + * sequence, check if a given string is a valid sequence in such binary tree. + * + * We get the given string from the concatenation of an array of integers arr and the + * concatenation of all values of the nodes along a path results in a sequence in the + * given binary tree. + */ + +/** + * 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[]} arr + * @return {boolean} + */ +var isValidSequence = function(root, arr) { + return dfs(root, 0); + + function dfs(node, index) { + if (!node || index >= arr.length || node.val !== arr[index]) { + return false; + } + + if (index === arr.length - 1) { + return !node.left && !node.right; + } + + return dfs(node.left, index + 1) || dfs(node.right, index + 1); + } +}; diff --git a/solutions/1469-find-all-the-lonely-nodes.js b/solutions/1469-find-all-the-lonely-nodes.js new file mode 100644 index 00000000..91aa1167 --- /dev/null +++ b/solutions/1469-find-all-the-lonely-nodes.js @@ -0,0 +1,44 @@ +/** + * 1469. Find All The Lonely Nodes + * https://leetcode.com/problems/find-all-the-lonely-nodes/ + * Difficulty: Easy + * + * In a binary tree, a lonely node is a node that is the only child of its parent node. + * The root of the tree is not lonely because it does not have a parent node. + * + * Given the root of a binary tree, return an array containing the values of all lonely + * nodes in the tree. Return the list in any order. + */ + +/** + * 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[]} + */ +var getLonelyNodes = function(root) { + const result = []; + dfs(root); + return result; + + function dfs(node) { + if (!node) return; + + if (node.left && !node.right) { + result.push(node.left.val); + } + + if (!node.left && node.right) { + result.push(node.right.val); + } + + dfs(node.left); + dfs(node.right); + } +}; diff --git a/solutions/1474-delete-n-nodes-after-m-nodes-of-a-linked-list.js b/solutions/1474-delete-n-nodes-after-m-nodes-of-a-linked-list.js new file mode 100644 index 00000000..8fd296ca --- /dev/null +++ b/solutions/1474-delete-n-nodes-after-m-nodes-of-a-linked-list.js @@ -0,0 +1,50 @@ +/** + * 1474. Delete N Nodes After M Nodes of a Linked List + * https://leetcode.com/problems/delete-n-nodes-after-m-nodes-of-a-linked-list/ + * Difficulty: Easy + * + * You are given the head of a linked list and two integers m and n. + * + * Traverse the linked list and remove some nodes in the following way: + * - Start with the head as the current node. + * - Keep the first m nodes starting with the current node. + * - Remove the next n nodes + * - Keep repeating steps 2 and 3 until you reach the end of the list. + * + * Return the head of the modified list after removing the mentioned nodes. + */ + +/** + * 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} + */ +var deleteNodes = function(head, m, n) { + let current = head; + + while (current) { + for (let i = 1; i < m && current; i++) { + current = current.next; + } + + if (!current) break; + + let nodeToDelete = current.next; + for (let i = 0; i < n && nodeToDelete; i++) { + nodeToDelete = nodeToDelete.next; + } + + current.next = nodeToDelete; + current = nodeToDelete; + } + + return head; +}; diff --git a/solutions/1485-clone-binary-tree-with-random-pointer.js b/solutions/1485-clone-binary-tree-with-random-pointer.js new file mode 100644 index 00000000..36dab6d7 --- /dev/null +++ b/solutions/1485-clone-binary-tree-with-random-pointer.js @@ -0,0 +1,53 @@ +/** + * 1485. Clone Binary Tree With Random Pointer + * https://leetcode.com/problems/clone-binary-tree-with-random-pointer/ + * Difficulty: Medium + * + * A binary tree is given such that each node contains an additional random pointer which + * could point to any node in the tree or null. + * + * Return a deep copy of the tree. + * + * The tree is represented in the same input/output way as normal binary trees where each + * node is represented as a pair of [val, random_index] where: + * - val: an integer representing Node.val + * - random_index: the index of the node (in the input) where the random pointer points to, + * or null if it does not point to any node. + * + * You will be given the tree in class Node and you should return the cloned tree in class + * NodeCopy. NodeCopy class is just a clone of Node class with the same attributes and constructors. + */ + +/** + * // Definition for a _Node. + * function _Node(val, left, right, random) { + * this.val = val === undefined ? null : val; + * this.left = left === undefined ? null : left; + * this.right = right === undefined ? null : right; + * this.random = random === undefined ? null : random; + * }; + */ + +/** + * @param {_Node} root + * @return {NodeCopy} + */ +var copyRandomBinaryTree = function(root) { + if (!root) return null; + const nodeMap = new Map(); + return createCopy(root); + + function createCopy(node) { + if (!node) return null; + if (nodeMap.has(node)) return nodeMap.get(node); + + const copy = new NodeCopy(node.val); + nodeMap.set(node, copy); + + copy.left = createCopy(node.left); + copy.right = createCopy(node.right); + copy.random = createCopy(node.random); + + return copy; + } +}; diff --git a/solutions/1490-clone-n-ary-tree.js b/solutions/1490-clone-n-ary-tree.js new file mode 100644 index 00000000..46d589f0 --- /dev/null +++ b/solutions/1490-clone-n-ary-tree.js @@ -0,0 +1,38 @@ +/** + * 1490. Clone N-ary Tree + * https://leetcode.com/problems/clone-n-ary-tree/ + * Difficulty: Medium + * + * Given a root of an N-ary tree, return a deep copy (clone) of the tree. + * + * Each node in the n-ary tree contains a val (int) and a list (List[Node]) of its children. + * + * class Node { + * public int val; + * public List children; + * } + * + * Nary-Tree input serialization is represented in their level order traversal, each group + * of children is separated by the null value (See examples). + */ + +/** + * // Definition for a _Node. + * function _Node(val, children) { + * this.val = val === undefined ? 0 : val; + * this.children = children === undefined ? [] : children; + * }; + */ + +/** + * @param {_Node|null} node + * @return {_Node|null} + */ +var cloneTree = function(root) { + if (!root) return null; + + const clonedNode = new _Node(root.val); + clonedNode.children = root.children.map(child => cloneTree(child)); + + return clonedNode; +}; diff --git a/solutions/1500-design-a-file-sharing-system.js b/solutions/1500-design-a-file-sharing-system.js new file mode 100644 index 00000000..f32f210a --- /dev/null +++ b/solutions/1500-design-a-file-sharing-system.js @@ -0,0 +1,89 @@ +/** + * 1500. Design a File Sharing System + * https://leetcode.com/problems/design-a-file-sharing-system/ + * Difficulty: Medium + * + * We will use a file-sharing system to share a very large file which consists of m small + * chunks with IDs from 1 to m. + * + * When users join the system, the system should assign a unique ID to them. The unique ID + * should be used once for each user, but when a user leaves the system, the ID can be reused again. + * + * Users can request a certain chunk of the file, the system should return a list of IDs of + * all the users who own this chunk. If the user receives a non-empty list of IDs, they receive + * the requested chunk successfully. + * + * Implement the FileSharing class: + * - FileSharing(int m) Initializes the object with a file of m chunks. + * - int join(int[] ownedChunks): A new user joined the system owning some chunks of the file, + * the system should assign an id to the user which is the smallest positive integer not + * taken by any other user. Return the assigned id. + * - void leave(int userID): The user with userID will leave the system, you cannot take file + * chunks from them anymore. + * - int[] request(int userID, int chunkID): The user userID requested the file chunk with chunkID. + * Return a list of the IDs of all users that own this chunk sorted in ascending order. + */ + +/** +* @param {number} m +*/ +var FileSharing = function(m) { + this.chunkToUsers = new Array(m + 1).fill().map(() => new Set()); + this.userToChunks = new Map(); + this.availableIds = []; + this.nextId = 1; +}; + +/** +* @param {number[]} ownedChunks +* @return {number} +*/ +FileSharing.prototype.join = function(ownedChunks) { + let userId; + + if (this.availableIds.length > 0) { + userId = this.availableIds.sort((a, b) => a - b).shift(); + } else { + userId = this.nextId++; + } + + this.userToChunks.set(userId, new Set(ownedChunks)); + + for (const chunk of ownedChunks) { + this.chunkToUsers[chunk].add(userId); + } + + return userId; +}; + +/** +* @param {number} userID +* @return {void} +*/ +FileSharing.prototype.leave = function(userID) { + const userChunks = this.userToChunks.get(userID); + + if (userChunks) { + for (const chunk of userChunks) { + this.chunkToUsers[chunk].delete(userID); + } + this.userToChunks.delete(userID); + this.availableIds.push(userID); + } +}; + +/** +* @param {number} userID +* @param {number} chunkID +* @return {number[]} +*/ +FileSharing.prototype.request = function(userID, chunkID) { + const usersWithChunk = Array.from(this.chunkToUsers[chunkID]).sort((a, b) => a - b); + + if (usersWithChunk.length > 0) { + this.userToChunks.get(userID).add(chunkID); + this.chunkToUsers[chunkID].add(userID); + } + + return usersWithChunk; +}; diff --git a/solutions/1506-find-root-of-n-ary-tree.js b/solutions/1506-find-root-of-n-ary-tree.js new file mode 100644 index 00000000..22e1105b --- /dev/null +++ b/solutions/1506-find-root-of-n-ary-tree.js @@ -0,0 +1,42 @@ +/** + * 1506. Find Root of N-Ary Tree + * https://leetcode.com/problems/find-root-of-n-ary-tree/ + * Difficulty: Medium + * + * You are given all the nodes of an N-ary tree as an array of Node objects, where each + * node has a unique value. + * + * Return the root of the N-ary tree. + * + * Custom testing: + * - An N-ary tree can be serialized as represented in its level order traversal where each + * group of children is separated by the null value (see examples). + */ + +/** + * // Definition for a _Node. + * function _Node(val, children) { + * this.val = val === undefined ? 0 : val; + * this.children = children === undefined ? [] : children; + * }; + */ + +/** + * @param {_Node[]} tree + * @return {_Node} + */ +var findRoot = function(tree) { + const set = new Set(); + + for (const node of tree) { + for (const child of node.children) { + set.add(child.val); + } + } + + for (const node of tree) { + if (!set.has(node.val)) { + return node; + } + } +}; diff --git a/solutions/1516-move-sub-tree-of-n-ary-tree.js b/solutions/1516-move-sub-tree-of-n-ary-tree.js new file mode 100644 index 00000000..09b8cade --- /dev/null +++ b/solutions/1516-move-sub-tree-of-n-ary-tree.js @@ -0,0 +1,76 @@ +/** + * 1516. Move Sub-Tree of N-Ary Tree + * https://leetcode.com/problems/move-sub-tree-of-n-ary-tree/ + * Difficulty: Hard + * + * Given the root of an N-ary tree of unique values, and two nodes of the tree p and q. + * + * You should move the subtree of the node p to become a direct child of node q. If p is + * already a direct child of q, do not change anything. Node p must be the last child in + * the children list of node q. + * + * Return the root of the tree after adjusting it. + * + * There are 3 cases for nodes p and q: + * 1. Node q is in the sub-tree of node p. + * 2. Node p is in the sub-tree of node q. + * 3. Neither node p is in the sub-tree of node q nor node q is in the sub-tree of node p. + * + * In cases 2 and 3, you just need to move p (with its sub-tree) to be a child of q, but in + * case 1 the tree may be disconnected, thus you need to reconnect the tree again. Please + * read the examples carefully before solving this problem. + * + * Nary-Tree input serialization is represented in their level order traversal, each group + * of children is separated by the null value (See examples). + */ + +/** + * // Definition for a Node. + * function Node(val, children) { + * this.val = val === undefined ? 0 : val; + * this.children = children === undefined ? [] : children; + * }; + */ + +/** + * @param {Node} root + * @param {Node} p + * @param {Node} q + * @return {Node} + */ +var moveSubTree = function(root, p, q) { + if (q.children.includes(p)) return root; + + const pParent = findParent(root, p); + const qParent = findParent(root, q); + + if (isDescendant(q, p)) { + qParent.children = qParent.children.filter(child => child !== q); + q.children.push(p); + + if (!pParent) return q; + + pParent.children[pParent.children.indexOf(p)] = q; + } else { + q.children.push(p); + pParent.children = pParent.children.filter(child => child !== p); + } + + return root; + + function findParent(node, target) { + if (!node) return null; + for (const child of node.children) { + if (child === target) return node; + const parent = findParent(child, target); + if (parent) return parent; + } + return null; + } + + function isDescendant(target, node) { + if (!node) return false; + if (node === target) return true; + return node.children.some(child => isDescendant(target, child)); + } +}; diff --git a/solutions/1522-diameter-of-n-ary-tree.js b/solutions/1522-diameter-of-n-ary-tree.js new file mode 100644 index 00000000..d953888d --- /dev/null +++ b/solutions/1522-diameter-of-n-ary-tree.js @@ -0,0 +1,42 @@ +/** + * 1522. Diameter of N-Ary Tree + * https://leetcode.com/problems/diameter-of-n-ary-tree/ + * Difficulty: Medium + * + * Given a root of an N-ary tree, you need to compute the length of the diameter of the tree. + * + * The diameter of an N-ary tree is the length of the longest path between any two nodes in + * the tree. This path may or may not pass through the root. + * + * (Nary-Tree input serialization is represented in their level order traversal, each group + * of children is separated by the null value.) + */ + +/** + * // Definition for a _Node. + * function _Node(val, children) { + * this.val = val === undefined ? 0 : val; + * this.children = children === undefined ? [] : children; + * }; + */ + +/** + * @param {_Node} root + * @return {number} + */ +var diameter = function(root) { + let maxDiameter = 0; + dfs(root); + return maxDiameter; + + function dfs(node) { + if (!node) return 0; + + const depths = node.children.map(child => dfs(child)).sort((a, b) => b - a); + + const currentDiameter = depths.length >= 2 ? depths[0] + depths[1] : depths[0] || 0; + maxDiameter = Math.max(maxDiameter, currentDiameter); + + return (depths[0] || 0) + 1; + } +}; diff --git a/solutions/1533-find-the-index-of-the-large-integer.js b/solutions/1533-find-the-index-of-the-large-integer.js new file mode 100644 index 00000000..74decece --- /dev/null +++ b/solutions/1533-find-the-index-of-the-large-integer.js @@ -0,0 +1,56 @@ +/** + * 1533. Find the Index of the Large Integer + * https://leetcode.com/problems/find-the-index-of-the-large-integer/ + * Difficulty: Medium + * + * We have an integer array arr, where all the integers in arr are equal except for one integer + * which is larger than the rest of the integers. You will not be given direct access to the + * array, instead, you will have an API ArrayReader which have the following functions: + * - int compareSub(int l, int r, int x, int y): where 0 <= l, r, x, y < ArrayReader.length(), + * l <= r and x <= y. The function compares the sum of sub-array arr[l..r] with the sum of + * the sub-array arr[x..y] and returns: + * - 1 if arr[l]+arr[l+1]+...+arr[r] > arr[x]+arr[x+1]+...+arr[y]. + * - 0 if arr[l]+arr[l+1]+...+arr[r] == arr[x]+arr[x+1]+...+arr[y]. + * - -1 if arr[l]+arr[l+1]+...+arr[r] < arr[x]+arr[x+1]+...+arr[y]. + * - int length(): Returns the size of the array. + * + * You are allowed to call compareSub() 20 times at most. You can assume both functions work + * in O(1) time. + * + * Return the index of the array arr which has the largest integer. + */ + +/** + * @param {ArrayReader} reader + * @return {number} + */ +var getIndex = function(reader) { + const n = reader.length(); + let left = 0; + let right = n - 1; + + while (left < right) { + const length = right - left + 1; + const mid = Math.floor((left + right) / 2); + + if (length % 2 === 1) { + const comparison = reader.compareSub(left, mid - 1, mid + 1, right); + if (comparison === 0) { + return mid; + } else if (comparison === 1) { + right = mid - 1; + } else { + left = mid + 1; + } + } else { + const comparison = reader.compareSub(left, mid, mid + 1, right); + if (comparison === 1) { + right = mid; + } else { + left = mid + 1; + } + } + } + + return left; +}; diff --git a/solutions/1538-guess-the-majority-in-a-hidden-array.js b/solutions/1538-guess-the-majority-in-a-hidden-array.js new file mode 100644 index 00000000..d1f1dbc6 --- /dev/null +++ b/solutions/1538-guess-the-majority-in-a-hidden-array.js @@ -0,0 +1,86 @@ +/** + * 1538. Guess the Majority in a Hidden Array + * https://leetcode.com/problems/guess-the-majority-in-a-hidden-array/ + * Difficulty: Medium + * + * We have an integer array nums, where all the integers in nums are 0 or 1. You will not + * be given direct access to the array, instead, you will have an API ArrayReader which + * have the following functions: + * - int query(int a, int b, int c, int d): where 0 <= a < b < c < d < ArrayReader.length(). + * The function returns the distribution of the value of the 4 elements and returns: + * - 4 : if the values of the 4 elements are the same (0 or 1). + * - 2 : if three elements have a value equal to 0 and one element has value equal to 1 or + * vice versa. + * - 0 : if two element have a value equal to 0 and two elements have a value equal to 1. + * - int length(): Returns the size of the array. + * + * You are allowed to call query() 2 * n times at most where n is equal to ArrayReader.length(). + * + * Return any index of the most frequent value in nums, in case of tie, return -1. + */ + +/** + * // This is the ArrayReader's API interface. + * // You should not implement it, or speculate about its implementation + * function ArrayReader() { + * // Compares 4 different elements in the array + * // return 4 if the values of the 4 elements are the same (0 or 1). + * // return 2 if three elements have a value equal to 0 and one element has value equal + * // to 1 or vice versa. + * // return 0 : if two element have a value equal to 0 and two elements have a value + * // equal to 1. + * @param {number} a, b, c, d + * @return {number} + * this.query = function(a, b, c, d) { + * ... + * }; + * + * // Returns the length of the array + * @return {number} + * this.length = function() { + * ... + * }; + * }; + */ + +/** + * @param {ArrayReader} reader + * @return {number} + */ +var guessMajority = function(reader) { + const baseQuery = reader.query(0, 1, 2, 3); + const n = reader.length(); + let sameAsZeroCount = 1; + let differentIndex = -1; + + for (let i = 4; i < n; i++) { + const currentQuery = reader.query(1, 2, 3, i); + if (baseQuery === currentQuery) { + sameAsZeroCount++; + } else { + differentIndex = i; + } + } + + const referenceQuery = reader.query(1, 2, 3, 4); + checkElement([0, 2, 3, 4], 1); + checkElement([0, 1, 3, 4], 2); + checkElement([0, 1, 2, 4], 3); + + const differentCount = n - sameAsZeroCount; + if (sameAsZeroCount > differentCount) { + return 0; + } else if (sameAsZeroCount === differentCount) { + return -1; + } else { + return differentIndex; + } + + function checkElement(indices, elementIndex) { + if (referenceQuery === reader.query(...indices)) { + sameAsZeroCount++; + } else { + differentIndex = elementIndex; + } + } +}; diff --git a/solutions/1548-the-most-similar-path-in-a-graph.js b/solutions/1548-the-most-similar-path-in-a-graph.js new file mode 100644 index 00000000..6de39220 --- /dev/null +++ b/solutions/1548-the-most-similar-path-in-a-graph.js @@ -0,0 +1,71 @@ +/** + * 1548. The Most Similar Path in a Graph + * https://leetcode.com/problems/the-most-similar-path-in-a-graph/ + * Difficulty: Hard + * + * We have n cities and m bi-directional roads where roads[i] = [ai, bi] connects city ai + * with city bi. Each city has a name consisting of exactly three upper-case English letters + * given in the string array names. Starting at any city x, you can reach any city y where + * y != x (i.e., the cities and the roads are forming an undirected connected graph). + * + * You will be given a string array targetPath. You should find a path in the graph of the + * same length and with the minimum edit distance to targetPath. + * + * You need to return the order of the nodes in the path with the minimum edit distance. + * The path should be of the same length of targetPath and should be valid (i.e., there + * should be a direct road between ans[i] and ans[i + 1]). If there are multiple answers + * return any one of them. + */ + +/** + * @param {number} n + * @param {number[][]} roads + * @param {string[]} names + * @param {string[]} targetPath + * @return {number[]} + */ +var mostSimilar = function(n, roads, names, targetPath) { + const graph = new Array(n).fill().map(() => []); + for (const [a, b] of roads) { + graph[a].push(b); + graph[b].push(a); + } + + const m = targetPath.length; + const dp = new Array(m).fill().map(() => new Array(n).fill(Infinity)); + const parent = new Array(m).fill().map(() => new Array(n).fill(-1)); + + for (let city = 0; city < n; city++) { + dp[0][city] = names[city] === targetPath[0] ? 0 : 1; + } + + for (let step = 1; step < m; step++) { + for (let city = 0; city < n; city++) { + for (const neighbor of graph[city]) { + const cost = dp[step - 1][neighbor] + (names[city] === targetPath[step] ? 0 : 1); + if (cost < dp[step][city]) { + dp[step][city] = cost; + parent[step][city] = neighbor; + } + } + } + } + + let minCost = Infinity; + let lastCity = -1; + for (let city = 0; city < n; city++) { + if (dp[m - 1][city] < minCost) { + minCost = dp[m - 1][city]; + lastCity = city; + } + } + + const result = []; + let currentCity = lastCity; + for (let step = m - 1; step >= 0; step--) { + result.unshift(currentCity); + currentCity = parent[step][currentCity]; + } + + return result; +}; diff --git a/solutions/1554-strings-differ-by-one-character.js b/solutions/1554-strings-differ-by-one-character.js new file mode 100644 index 00000000..52fb2b70 --- /dev/null +++ b/solutions/1554-strings-differ-by-one-character.js @@ -0,0 +1,34 @@ +/** + * 1554. Strings Differ by One Character + * https://leetcode.com/problems/strings-differ-by-one-character/ + * Difficulty: Medium + * + * Given a list of strings dict where all the strings are of the same length. + * + * Return true if there are 2 strings that only differ by 1 character in the same index, + * otherwise return false. + */ + +/** + * @param {string[]} dict + * @return {boolean} + */ +var differByOne = function(dict) { + const m = dict[0].length; + + for (let pos = 0; pos < m; pos++) { + const patterns = new Set(); + + for (const word of dict) { + const pattern = word.slice(0, pos) + '*' + word.slice(pos + 1); + + if (patterns.has(pattern)) { + return true; + } + + patterns.add(pattern); + } + } + + return false; +}; diff --git a/solutions/1564-put-boxes-into-the-warehouse-i.js b/solutions/1564-put-boxes-into-the-warehouse-i.js new file mode 100644 index 00000000..dbd787e4 --- /dev/null +++ b/solutions/1564-put-boxes-into-the-warehouse-i.js @@ -0,0 +1,46 @@ +/** + * 1564. Put Boxes Into the Warehouse I + * https://leetcode.com/problems/put-boxes-into-the-warehouse-i/ + * Difficulty: Medium + * + * You are given two arrays of positive integers, boxes and warehouse, representing the + * heights of some boxes of unit width and the heights of n rooms in a warehouse respectively. + * The warehouse's rooms are labelled from 0 to n - 1 from left to right where warehouse[i] + * (0-indexed) is the height of the ith room. + * + * Boxes are put into the warehouse by the following rules: + * - Boxes cannot be stacked. + * - You can rearrange the insertion order of the boxes. + * - Boxes can only be pushed into the warehouse from left to right only. + * - If the height of some room in the warehouse is less than the height of a box, then that + * box and all other boxes behind it will be stopped before that room. + * + * Return the maximum number of boxes you can put into the warehouse. + */ + +/** + * @param {number[]} boxes + * @param {number[]} warehouse + * @return {number} + */ +var maxBoxesInWarehouse = function(boxes, warehouse) { + const effectiveHeights = new Array(warehouse.length); + effectiveHeights[0] = warehouse[0]; + + for (let i = 1; i < warehouse.length; i++) { + effectiveHeights[i] = Math.min(effectiveHeights[i - 1], warehouse[i]); + } + + boxes.sort((a, b) => a - b); + + let boxIndex = 0; + let count = 0; + for (let i = effectiveHeights.length - 1; i >= 0; i--) { + if (boxIndex < boxes.length && boxes[boxIndex] <= effectiveHeights[i]) { + count++; + boxIndex++; + } + } + + return count; +}; diff --git a/solutions/1570-dot-product-of-two-sparse-vectors.js b/solutions/1570-dot-product-of-two-sparse-vectors.js new file mode 100644 index 00000000..3fa6bb2b --- /dev/null +++ b/solutions/1570-dot-product-of-two-sparse-vectors.js @@ -0,0 +1,45 @@ +/** + * 1570. Dot Product of Two Sparse Vectors + * https://leetcode.com/problems/dot-product-of-two-sparse-vectors/ + * Difficulty: Medium + * + * Given two sparse vectors, compute their dot product. + * + * Implement class SparseVector: + * - SparseVector(nums) Initializes the object with the vector nums + * - dotProduct(vec) Compute the dot product between the instance of SparseVector and vec + * + * A sparse vector is a vector that has mostly zero values, you should store the sparse vector + * efficiently and compute the dot product between two SparseVector. + * + * Follow up: What if only one of the vectors is sparse? + */ + +/** + * @param {number[]} nums + * @return {SparseVector} + */ +var SparseVector = function(nums) { + this.nonZeroElements = new Map(); + for (let i = 0; i < nums.length; i++) { + if (nums[i] !== 0) { + this.nonZeroElements.set(i, nums[i]); + } + } +}; + +/** + * @param {SparseVector} vec + * @return {number} + */ +SparseVector.prototype.dotProduct = function(vec) { + let result = 0; + + for (const [index, value] of this.nonZeroElements) { + if (vec.nonZeroElements.has(index)) { + result += value * vec.nonZeroElements.get(index); + } + } + + return result; +}; diff --git a/solutions/1580-put-boxes-into-the-warehouse-ii.js b/solutions/1580-put-boxes-into-the-warehouse-ii.js new file mode 100644 index 00000000..66c86ba8 --- /dev/null +++ b/solutions/1580-put-boxes-into-the-warehouse-ii.js @@ -0,0 +1,66 @@ +/** + * 1580. Put Boxes Into the Warehouse II + * https://leetcode.com/problems/put-boxes-into-the-warehouse-ii/ + * Difficulty: Medium + * + * You are given two arrays of positive integers, boxes and warehouse, representing the heights + * of some boxes of unit width and the heights of n rooms in a warehouse respectively. The + * warehouse's rooms are labeled from 0 to n - 1 from left to right where warehouse[i] (0-indexed) + * is the height of the ith room. + * + * Boxes are put into the warehouse by the following rules: + * - Boxes cannot be stacked. + * - You can rearrange the insertion order of the boxes. + * - Boxes can be pushed into the warehouse from either side (left or right) + * - If the height of some room in the warehouse is less than the height of a box, then that box + * and all other boxes behind it will be stopped before that room. + * + * Return the maximum number of boxes you can put into the warehouse. + */ + +/** + * @param {number[]} boxes + * @param {number[]} warehouse + * @return {number} + */ +var maxBoxesInWarehouse = function(boxes, warehouse) { + boxes.sort((a, b) => a - b); + + let leftPointer = 0; + let rightPointer = warehouse.length - 1; + let leftMaxHeight = warehouse[0]; + let rightMaxHeight = warehouse[warehouse.length - 1]; + let result = 0; + + while (result < warehouse.length && leftPointer <= rightPointer && boxes.length > 0) { + while (boxes.length > 0 && boxes[boxes.length - 1] > leftMaxHeight + && boxes[boxes.length - 1] > rightMaxHeight) { + boxes.pop(); + } + + if (boxes.length === 0) break; + + const canFitLeft = boxes[boxes.length - 1] <= leftMaxHeight; + const canFitRight = boxes[boxes.length - 1] <= rightMaxHeight; + + if (canFitLeft && (!canFitRight || leftMaxHeight <= rightMaxHeight)) { + boxes.pop(); + leftPointer++; + result++; + if (leftPointer < warehouse.length) { + leftMaxHeight = Math.min(warehouse[leftPointer], leftMaxHeight); + } + } else if (canFitRight) { + boxes.pop(); + rightPointer--; + result++; + if (rightPointer >= 0) { + rightMaxHeight = Math.min(warehouse[rightPointer], rightMaxHeight); + } + } else { + break; + } + } + + return result; +}; diff --git a/solutions/1586-binary-search-tree-iterator-ii.js b/solutions/1586-binary-search-tree-iterator-ii.js new file mode 100644 index 00000000..b343697a --- /dev/null +++ b/solutions/1586-binary-search-tree-iterator-ii.js @@ -0,0 +1,72 @@ +/** + * 1586. Binary Search Tree Iterator II + * https://leetcode.com/problems/binary-search-tree-iterator-ii/ + * Difficulty: Medium + * + * Implement the BSTIterator class that represents an iterator over the in-order traversal + * of a binary search tree (BST): + * - BSTIterator(TreeNode root) Initializes an object of the BSTIterator class. The root of the + * BST is given as part of the constructor. The pointer should be initialized to a non-existent + * number smaller than any element in the BST. + * - boolean hasNext() Returns true if there exists a number in the traversal to the right of the + * pointer, otherwise returns false. + * - int next() Moves the pointer to the right, then returns the number at the pointer. + * - boolean hasPrev() Returns true if there exists a number in the traversal to the left of the + * pointer, otherwise returns false. + * - int prev() Moves the pointer to the left, then returns the number at the pointer. + * + * Notice that by initializing the pointer to a non-existent smallest number, the first call to + * next() will return the smallest element in the BST. + * + * You may assume that next() and prev() calls will always be valid. That is, there will be at + * least a next/previous number in the in-order traversal when next()/prev() is called. + */ + +/** + * @param {TreeNode} root + */ +var BSTIterator = function(root) { + this.inorderValues = []; + this.currentIndex = -1; + this.inorderTraversal(root); +}; + +/** + * @param {TreeNode} node + */ +BSTIterator.prototype.inorderTraversal = function(node) { + if (!node) return; + this.inorderTraversal(node.left); + this.inorderValues.push(node.val); + this.inorderTraversal(node.right); +}; + +/** + * @return {boolean} + */ +BSTIterator.prototype.hasNext = function() { + return this.currentIndex + 1 < this.inorderValues.length; +}; + +/** + * @return {number} + */ +BSTIterator.prototype.next = function() { + this.currentIndex++; + return this.inorderValues[this.currentIndex]; +}; + +/** + * @return {boolean} + */ +BSTIterator.prototype.hasPrev = function() { + return this.currentIndex > 0; +}; + +/** + * @return {number} + */ +BSTIterator.prototype.prev = function() { + this.currentIndex--; + return this.inorderValues[this.currentIndex]; +}; diff --git a/solutions/1597-build-binary-expression-tree-from-infix-expression.js b/solutions/1597-build-binary-expression-tree-from-infix-expression.js new file mode 100644 index 00000000..50fbd593 --- /dev/null +++ b/solutions/1597-build-binary-expression-tree-from-infix-expression.js @@ -0,0 +1,85 @@ +/** + * 1597. Build Binary Expression Tree From Infix Expression + * https://leetcode.com/problems/build-binary-expression-tree-from-infix-expression/ + * Difficulty: Hard + * + * A binary expression tree is a kind of binary tree used to represent arithmetic expressions. + * Each node of a binary expression tree has either zero or two children. Leaf nodes (nodes + * with 0 children) correspond to operands (numbers), and internal nodes (nodes with 2 children) + * correspond to the operators '+' (addition), '-' (subtraction), '*' (multiplication), and + * '/' (division). + * + * For each internal node with operator o, the infix expression it represents is (A o B), + * where A is the expression the left subtree represents and B is the expression the right + * subtree represents. + * + * You are given a string s, an infix expression containing operands, the operators described + * above, and parentheses '(' and ')'. + * + * Return any valid binary expression tree, whose in-order traversal reproduces s after omitting + * the parenthesis from it. + * + * Please note that order of operations applies in s. That is, expressions in parentheses are + * evaluated first, and multiplication and division happen before addition and subtraction. + * + * Operands must also appear in the same order in both s and the in-order traversal of the tree. + */ + +/** + * 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} + */ +var expTree = function(s) { + const operators = new Map([['+', 1], ['-', 1], ['*', 2], ['/', 2]]); + const operatorStack = []; + const operandStack = []; + + for (let i = 0; i < s.length; i++) { + const char = s[i]; + + if (char >= '0' && char <= '9') { + operandStack.push(createNode(char)); + } else if (char === '(') { + operatorStack.push(char); + } else if (char === ')') { + while (operatorStack.length > 0 && operatorStack[operatorStack.length - 1] !== '(') { + processOperator(); + } + operatorStack.pop(); + } else if (operators.has(char)) { + while (operatorStack.length > 0 && operatorStack[operatorStack.length - 1] !== '(' + && operators.get(operatorStack[operatorStack.length - 1]) >= operators.get(char)) { + processOperator(); + } + operatorStack.push(char); + } + } + + while (operatorStack.length > 0) { + processOperator(); + } + + return operandStack[0]; + + function processOperator() { + const operator = operatorStack.pop(); + const right = operandStack.pop(); + const left = operandStack.pop(); + const node = createNode(operator); + node.left = left; + node.right = right; + operandStack.push(node); + } + + function createNode(val) { + return new Node(val); + } +}; diff --git a/solutions/1602-find-nearest-right-node-in-binary-tree.js b/solutions/1602-find-nearest-right-node-in-binary-tree.js new file mode 100644 index 00000000..626f0a0b --- /dev/null +++ b/solutions/1602-find-nearest-right-node-in-binary-tree.js @@ -0,0 +1,42 @@ +/** + * 1602. Find Nearest Right Node in Binary Tree + * https://leetcode.com/problems/find-nearest-right-node-in-binary-tree/ + * Difficulty: Medium + * + * Given the root of a binary tree and a node u in the tree, return the nearest node on the + * same level that is to the right of u, or return null if u is the rightmost node in its level. + */ + +/** + * 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 {TreeNode} u + * @return {TreeNode} + */ +var findNearestRightNode = function(root, u) { + const queue = [root]; + + while (queue.length > 0) { + const levelSize = queue.length; + + for (let i = 0; i < levelSize; i++) { + const currentNode = queue.shift(); + + if (currentNode === u) { + return i === levelSize - 1 ? null : queue.shift(); + } + + if (currentNode.left) queue.push(currentNode.left); + if (currentNode.right) queue.push(currentNode.right); + } + } + + return null; +}; diff --git a/solutions/1612-check-if-two-expression-trees-are-equivalent.js b/solutions/1612-check-if-two-expression-trees-are-equivalent.js new file mode 100644 index 00000000..a0c1970f --- /dev/null +++ b/solutions/1612-check-if-two-expression-trees-are-equivalent.js @@ -0,0 +1,64 @@ +/** + * 1612. Check If Two Expression Trees are Equivalent + * https://leetcode.com/problems/check-if-two-expression-trees-are-equivalent/ + * Difficulty: Medium + * + * A binary expression tree is a kind of binary tree used to represent arithmetic expressions. + * Each node of a binary expression tree has either zero or two children. Leaf nodes (nodes + * with 0 children) correspond to operands (variables), and internal nodes (nodes with two + * children) correspond to the operators. In this problem, we only consider the '+' operator + * (i.e. addition). + * + * You are given the roots of two binary expression trees, root1 and root2. Return true if + * the two binary expression trees are equivalent. Otherwise, return false. + * + * Two binary expression trees are equivalent if they evaluate to the same value regardless + * of what the variables are set to. + */ + +/** + * 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 {Node} root1 + * @param {Node} root2 + * @return {boolean} + */ +var checkEquivalence = function(root1, root2) { + const count1 = getVariableCount(root1); + const count2 = getVariableCount(root2); + const variables1 = Object.keys(count1); + const variables2 = Object.keys(count2); + + if (variables1.length !== variables2.length) return false; + + for (const variable of variables1) { + if (count1[variable] !== count2[variable]) return false; + } + + return true; + + function getVariableCount(node) { + if (!node) return {}; + + if (node.val !== '+') { + return { [node.val]: 1 }; + } + + const leftCount = getVariableCount(node.left); + const rightCount = getVariableCount(node.right); + const mergedCount = { ...leftCount }; + for (const variable in rightCount) { + if (rightCount.hasOwnProperty(variable)) { + mergedCount[variable] = (mergedCount[variable] || 0) + rightCount[variable]; + } + } + + return mergedCount; + } +}; diff --git a/solutions/1618-maximum-font-to-fit-a-sentence-in-a-screen.js b/solutions/1618-maximum-font-to-fit-a-sentence-in-a-screen.js new file mode 100644 index 00000000..2300f043 --- /dev/null +++ b/solutions/1618-maximum-font-to-fit-a-sentence-in-a-screen.js @@ -0,0 +1,96 @@ +/** + * 1618. Maximum Font to Fit a Sentence in a Screen + * https://leetcode.com/problems/maximum-font-to-fit-a-sentence-in-a-screen/ + * Difficulty: Medium + * + * You are given a string text. We want to display text on a screen of width w and height h. + * You can choose any font size from array fonts, which contains the available font sizes in + * ascending order. + * + * You can use the FontInfo interface to get the width and height of any character at any + * available font size. + * + * The FontInfo interface is defined as such: + * interface FontInfo { + * // Returns the width of character ch on the screen using font size fontSize. + * // O(1) per call + * public int getWidth(int fontSize, char ch); + * + * // Returns the height of any character on the screen using font size fontSize. + * // O(1) per call + * public int getHeight(int fontSize); + * } + * + * The calculated width of text for some fontSize is the sum of every + * getWidth(fontSize, text[i]) call for each 0 <= i < text.length (0-indexed). + * The calculated height of text for some fontSize is getHeight(fontSize). Note + * that text is displayed on a single line. + * + * It is guaranteed that FontInfo will return the same value if you call getHeight + * or getWidth with the same parameters. + * + * It is also guaranteed that for any font size fontSize and any character ch: + * - getHeight(fontSize) <= getHeight(fontSize+1) + * - getWidth(fontSize, ch) <= getWidth(fontSize+1, ch) + * + * Return the maximum font size you can use to display text on the screen. If text cannot + * fit on the display with any font size, return -1. + */ + +/** + * // This is the FontInfo's API interface. + * // You should not implement it, or speculate about its implementation + * function FontInfo() { + * + * @param {number} fontSize + * @param {char} ch + * @return {number} + * this.getWidth = function(fontSize, ch) { + * ... + * }; + * + * @param {number} fontSize + * @return {number} + * this.getHeight = function(fontSize) { + * ... + * }; + * }; + */ +/** + * @param {string} text + * @param {number} w + * @param {number} h + * @param {number[]} fonts + * @param {FontInfo} fontInfo + * @return {number} + */ +var maxFont = function(text, w, h, fonts, fontInfo) { + let left = 0; + let right = fonts.length - 1; + let maxFontSize = -1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + const fontSize = fonts[mid]; + + if (canFit(fontSize)) { + maxFontSize = fontSize; + left = mid + 1; + } else { + right = mid - 1; + } + } + + return maxFontSize; + + function canFit(fontSize) { + if (fontInfo.getHeight(fontSize) > h) return false; + + let totalWidth = 0; + for (const char of text) { + totalWidth += fontInfo.getWidth(fontSize, char); + if (totalWidth > w) return false; + } + return true; + } +}; diff --git a/solutions/1628-design-an-expression-tree-with-evaluate-function.js b/solutions/1628-design-an-expression-tree-with-evaluate-function.js new file mode 100644 index 00000000..649aab3a --- /dev/null +++ b/solutions/1628-design-an-expression-tree-with-evaluate-function.js @@ -0,0 +1,106 @@ +/** + * 1628. Design an Expression Tree With Evaluate Function + * https://leetcode.com/problems/design-an-expression-tree-with-evaluate-function/ + * Difficulty: Medium + * + * Given the postfix tokens of an arithmetic expression, build and return the binary expression + * tree that represents this expression. + * + * Postfix notation is a notation for writing arithmetic expressions in which the operands + * (numbers) appear before their operators. For example, the postfix tokens of the expression + * 4*(5-(7+2)) are represented in the array postfix = ["4","5","7","2","+","-","*"]. + * + * The class Node is an interface you should use to implement the binary expression tree. + * The returned tree will be tested using the evaluate function, which is supposed to evaluate + * the tree's value. You should not remove the Node class; however, you can modify it as you + * wish, and you can define other classes to implement it if needed. + * + * A binary expression tree is a kind of binary tree used to represent arithmetic expressions. + * Each node of a binary expression tree has either zero or two children. Leaf nodes (nodes + * with 0 children) correspond to operands (numbers), and internal nodes (nodes with two + * children) correspond to the operators '+' (addition), '-' (subtraction), '*' + * (multiplication), and '/' (division). + * + * It's guaranteed that no subtree will yield a value that exceeds 109 in absolute value, + * and all the operations are valid (i.e., no division by zero). + * + * Follow up: Could you design the expression tree such that it is more modular? For example, + * is your design able to support additional operators without making changes to your existing + * evaluate implementation? + */ + +/** + * This is the interface for the expression tree Node. + * You should not remove it, and you can define some classes to implement it. + */ +var Node = function() { + if (this.constructor === Node) { + throw new Error('Cannot instanciate abstract class'); + } +}; + +Node.prototype.evaluate = function() { + throw new Error('Cannot call abstract method'); +}; + +class NumberNode extends Node { + constructor(value) { + super(); + this.value = parseInt(value); + } + + evaluate() { + return this.value; + } +} + +class OperatorNode extends Node { + constructor(operator, left, right) { + super(); + this.operator = operator; + this.left = left; + this.right = right; + } + + evaluate() { + const leftValue = this.left.evaluate(); + const rightValue = this.right.evaluate(); + + switch (this.operator) { + case '+': + return leftValue + rightValue; + case '-': + return leftValue - rightValue; + case '*': + return leftValue * rightValue; + case '/': + return Math.floor(leftValue / rightValue); + default: + throw new Error('Unknown operator'); + } + } +} + +/** + * This is the TreeBuilder class. + * You can treat it as the driver code that takes the postinfix input + * and returns the expression tree representing it as a Node. + */ +class TreeBuilder { + buildTree(postfix) { + const stack = []; + const operators = new Set(['+', '-', '*', '/']); + + for (const token of postfix) { + if (operators.has(token)) { + const right = stack.pop(); + const left = stack.pop(); + stack.push(new OperatorNode(token, left, right)); + } else { + stack.push(new NumberNode(token)); + } + } + + return stack[0]; + } +} diff --git a/solutions/1634-add-two-polynomials-represented-as-linked-lists.js b/solutions/1634-add-two-polynomials-represented-as-linked-lists.js new file mode 100644 index 00000000..d8bc467f --- /dev/null +++ b/solutions/1634-add-two-polynomials-represented-as-linked-lists.js @@ -0,0 +1,84 @@ +/** + * 1634. Add Two Polynomials Represented as Linked Lists + * https://leetcode.com/problems/add-two-polynomials-represented-as-linked-lists/ + * Difficulty: Medium + * + * A polynomial linked list is a special type of linked list where every node represents a + * term in a polynomial expression. + * + * Each node has three attributes: + * - coefficient: an integer representing the number multiplier of the term. The coefficient + * of the term 9x4 is 9. + * - power: an integer representing the exponent. The power of the term 9x4 is 4. + * - next: a pointer to the next node in the list, or null if it is the last node of the list. + * + * For example, the polynomial 5x3 + 4x - 7 is represented by the polynomial linked list + * illustrated below: + * + * The polynomial linked list must be in its standard form: the polynomial must be in strictly + * descending order by its power value. Also, terms with a coefficient of 0 are omitted. + * + * Given two polynomial linked list heads, poly1 and poly2, add the polynomials together + * and return the head of the sum of the polynomials. + * + * PolyNode format: + * The input/output format is as a list of n nodes, where each node is represented as + * its [coefficient, power]. For example, the polynomial 5x3 + 4x - 7 would be represented + * as: [[5,3],[4,1],[-7,0]]. + */ + +/** + * Definition for polynomial singly-linked list. + * function PolyNode(x=0, y=0, next=null) { + * this.coefficient = x; + * this.power = y; + * this.next = next; + * } + */ + +/** + * @param {PolyNode} poly1 + * @param {PolyNode} poly2 + * @return {PolyNode} + */ +var addPoly = function(poly1, poly2) { + const dummyHead = new PolyNode(); + let current = dummyHead; + let pointer1 = poly1; + let pointer2 = poly2; + + while (pointer1 || pointer2) { + let coefficient = 0; + let power = 0; + + if (!pointer1) { + coefficient = pointer2.coefficient; + power = pointer2.power; + pointer2 = pointer2.next; + } else if (!pointer2) { + coefficient = pointer1.coefficient; + power = pointer1.power; + pointer1 = pointer1.next; + } else if (pointer1.power > pointer2.power) { + coefficient = pointer1.coefficient; + power = pointer1.power; + pointer1 = pointer1.next; + } else if (pointer2.power > pointer1.power) { + coefficient = pointer2.coefficient; + power = pointer2.power; + pointer2 = pointer2.next; + } else { + coefficient = pointer1.coefficient + pointer2.coefficient; + power = pointer1.power; + pointer1 = pointer1.next; + pointer2 = pointer2.next; + } + + if (coefficient !== 0) { + current.next = new PolyNode(coefficient, power); + current = current.next; + } + } + + return dummyHead.next; +}; diff --git a/solutions/1644-lowest-common-ancestor-of-a-binary-tree-ii.js b/solutions/1644-lowest-common-ancestor-of-a-binary-tree-ii.js new file mode 100644 index 00000000..07762f25 --- /dev/null +++ b/solutions/1644-lowest-common-ancestor-of-a-binary-tree-ii.js @@ -0,0 +1,63 @@ +/** + * 1644. Lowest Common Ancestor of a Binary Tree II + * https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree-ii/ + * Difficulty: Medium + * + * Given the root of a binary tree, return the lowest common ancestor (LCA) of two given + * nodes, p and q. If either node p or q does not exist in the tree, return null. All + * values of the nodes in the tree are unique. + * + * According to the definition of LCA on Wikipedia: "The lowest common ancestor of two + * nodes p and q in a binary tree T is the lowest node that has both p and q as descendants + * (where we allow a node to be a descendant of itself)". A descendant of a node x is a + * node y that is on the path from node x to some leaf node. + */ + +/** + * 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} + */ +var lowestCommonAncestor = function(root, p, q) { + let foundP = false; + let foundQ = false; + + const lca = findLCA(root); + return foundP && foundQ ? lca : null; + + function findLCA(node) { + if (!node) return null; + + const leftResult = findLCA(node.left); + const rightResult = findLCA(node.right); + + let currentMatch = false; + if (node === p) { + foundP = true; + currentMatch = true; + } + + if (node === q) { + foundQ = true; + currentMatch = true; + } + + if (leftResult && rightResult) { + return node; + } + + if (currentMatch && (leftResult || rightResult)) { + return node; + } + + return leftResult || rightResult || (currentMatch ? node : null); + } +}; diff --git a/solutions/1650-lowest-common-ancestor-of-a-binary-tree-iii.js b/solutions/1650-lowest-common-ancestor-of-a-binary-tree-iii.js new file mode 100644 index 00000000..78a6cc1e --- /dev/null +++ b/solutions/1650-lowest-common-ancestor-of-a-binary-tree-iii.js @@ -0,0 +1,54 @@ +/** + * 1650. Lowest Common Ancestor of a Binary Tree III + * https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree-iii/ + * Difficulty: Medium + * + * Given two nodes of a binary tree p and q, return their lowest common ancestor (LCA). + * + * Each node will have a reference to its parent node. The definition for Node is below: + * class Node { + * public int val; + * public Node left; + * public Node right; + * public Node parent; + * } + * + * According to the definition of LCA on Wikipedia: "The lowest common ancestor of two + * nodes p and q in a tree T is the lowest node that has both p and q as descendants + * (where we allow a node to be a descendant of itself)." + */ + +/** + * // Definition for a _Node. + * function _Node(val) { + * this.val = val; + * this.left = null; + * this.right = null; + * this.parent = null; + * }; + */ + +/** + * @param {_Node} p + * @param {_Node} q + * @return {_Node} + */ +var lowestCommonAncestor = function(p, q) { + const set = new Set(); + + let current = p; + while (current) { + set.add(current); + current = current.parent; + } + + current = q; + while (current) { + if (set.has(current)) { + return current; + } + current = current.parent; + } + + return null; +}; diff --git a/solutions/1660-correct-a-binary-tree.js b/solutions/1660-correct-a-binary-tree.js new file mode 100644 index 00000000..c5ab98cd --- /dev/null +++ b/solutions/1660-correct-a-binary-tree.js @@ -0,0 +1,63 @@ +/** + * 1660. Correct a Binary Tree + * https://leetcode.com/problems/correct-a-binary-tree/ + * Difficulty: Medium + * + * You have a binary tree with a small defect. There is exactly one invalid node where its right + * child incorrectly points to another node at the same depth but to the invalid node's right. + * + * Given the root of the binary tree with this defect, root, return the root of the binary tree + * after removing this invalid node and every node underneath it (minus the node it incorrectly + * points to). + * + * Custom testing: + * The test input is read as 3 lines: + * - TreeNode root + * - int fromNode (not available to correctBinaryTree) + * - int toNode (not available to correctBinaryTree) + * + * After the binary tree rooted at root is parsed, the TreeNode with value of fromNode will have + * its right child pointer pointing to the TreeNode with a value of toNode. Then, root is passed + * to correctBinaryTree. + */ + +/** + * 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} + */ +var correctBinaryTree = function(root) { + const set = new Set(); + return traverse(root, null, false); + + function traverse(node, parent, isLeft) { + if (!node) return null; + + if (node.right && set.has(node.right)) { + if (parent) { + if (isLeft) { + parent.left = null; + } else { + parent.right = null; + } + } + return null; + } + + set.add(node); + + node.right = traverse(node.right, node, false); + node.left = traverse(node.left, node, true); + + return node; + } +}; diff --git a/solutions/1666-change-the-root-of-a-binary-tree.js b/solutions/1666-change-the-root-of-a-binary-tree.js new file mode 100644 index 00000000..b27b8773 --- /dev/null +++ b/solutions/1666-change-the-root-of-a-binary-tree.js @@ -0,0 +1,55 @@ +/** + * 1666. Change the Root of a Binary Tree + * https://leetcode.com/problems/change-the-root-of-a-binary-tree/ + * Difficulty: Medium + * + * Given the root of a binary tree and a leaf node, reroot the tree so that the leaf is the + * new root. + * + * You can reroot the tree with the following steps for each node cur on the path starting + * from the leaf up to the root excluding the root: + * 1. If cur has a left child, then that child becomes cur's right child. + * 2. cur's original parent becomes cur's left child. Note that in this process the original + * parent's pointer to cur becomes null, making it have at most one child. + * + * Return the new root of the rerooted tree. + * + * Note: Ensure that your solution sets the Node.parent pointers correctly after rerooting or + * you will receive "Wrong Answer". + */ + +/** + * // Definition for a Node. + * function Node(val) { + * this.val = val; + * this.left = null; + * this.right = null; + * this.parent = null; + * }; + */ + +/** + * @param {Node} node + * @return {Node} + */ +var flipBinaryTree = function(root, leaf) { + helper(leaf, null); + return leaf; + + function helper(node, newParent) { + const originalParent = node.parent; + node.parent = newParent; + if (!originalParent) return; + + if (node.left) node.right = node.left; + node.left = originalParent; + + if (originalParent.left === node) { + originalParent.left = null; + } else { + originalParent.right = null; + } + + helper(originalParent, node); + } +}; diff --git a/solutions/1676-lowest-common-ancestor-of-a-binary-tree-iv.js b/solutions/1676-lowest-common-ancestor-of-a-binary-tree-iv.js new file mode 100644 index 00000000..f9690335 --- /dev/null +++ b/solutions/1676-lowest-common-ancestor-of-a-binary-tree-iv.js @@ -0,0 +1,44 @@ +/** + * 1676. Lowest Common Ancestor of a Binary Tree IV + * https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree-iv/ + * Difficulty: Medium + * + * Given the root of a binary tree and an array of TreeNode objects nodes, return the lowest common + * ancestor (LCA) of all the nodes in nodes. All the nodes will exist in the tree, and all values + * of the tree's nodes are unique. + * + * Extending the definition of LCA on Wikipedia: "The lowest common ancestor of n nodes p1, + * p2, ..., pn in a binary tree T is the lowest node that has every pi as a descendant (where we + * allow a node to be a descendant of itself) for every valid i". A descendant of a node x is a + * node y that is on the path from node x to some leaf node. + */ + +/** + * 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} + */ +var lowestCommonAncestor = function(root, nodes) { + const targetSet = new Set(nodes); + return helper(root); + + function helper(node) { + if (!node) return null; + + if (targetSet.has(node)) return node; + + const leftResult = helper(node.left); + const rightResult = helper(node.right); + + if (leftResult && rightResult) return node; + + return leftResult || rightResult; + } +}; diff --git a/solutions/1682-longest-palindromic-subsequence-ii.js b/solutions/1682-longest-palindromic-subsequence-ii.js new file mode 100644 index 00000000..2a10e561 --- /dev/null +++ b/solutions/1682-longest-palindromic-subsequence-ii.js @@ -0,0 +1,60 @@ +/** + * 1682. Longest Palindromic Subsequence II + * https://leetcode.com/problems/longest-palindromic-subsequence-ii/ + * Difficulty: Medium + * + * A subsequence of a string s is considered a good palindromic subsequence if: + * - It is a subsequence of s. + * - It is a palindrome (has the same value if reversed). + * - It has an even length. + * - No two consecutive characters are equal, except the two middle ones. + * + * For example, if s = "abcabcabb", then "abba" is considered a good palindromic subsequence, + * while "bcb" (not even length) and "bbbb" (has equal consecutive characters) are not. + * + * Given a string s, return the length of the longest good palindromic subsequence in s. + */ + +/** + * @param {string} s + * @return {number} + */ +var longestPalindromeSubseq = function(s) { + const stringLength = s.length; + const alphabetSize = 26; + const baseCharCode = 97; + + const memoTable = new Array(alphabetSize + 1); + for (let i = 0; i <= alphabetSize; i++) { + const matrix = memoTable[i] = new Array(stringLength); + for (let j = 0; j < stringLength; j++) { + matrix[j] = new Array(stringLength); + } + } + + return findLongestPalindrome(alphabetSize, 0, stringLength - 1); + + function findLongestPalindrome(previousChar, leftIndex, rightIndex) { + if (leftIndex >= rightIndex) return 0; + + const cachedResult = memoTable[previousChar][leftIndex][rightIndex]; + if (cachedResult !== undefined) return cachedResult; + + let maxLength = 0; + const leftChar = s.charCodeAt(leftIndex) - baseCharCode; + const rightChar = s.charCodeAt(rightIndex) - baseCharCode; + + if (leftChar === rightChar) { + if (leftChar !== previousChar) { + maxLength += 2; + } + maxLength += findLongestPalindrome(leftChar, leftIndex + 1, rightIndex - 1); + } else { + const skipLeftResult = findLongestPalindrome(previousChar, leftIndex + 1, rightIndex); + const skipRightResult = findLongestPalindrome(previousChar, leftIndex, rightIndex - 1); + maxLength += Math.max(skipLeftResult, skipRightResult); + } + + return memoTable[previousChar][leftIndex][rightIndex] = maxLength; + } +}; diff --git a/solutions/1692-count-ways-to-distribute-candies.js b/solutions/1692-count-ways-to-distribute-candies.js new file mode 100644 index 00000000..3288cbd6 --- /dev/null +++ b/solutions/1692-count-ways-to-distribute-candies.js @@ -0,0 +1,42 @@ +/** + * 1692. Count Ways to Distribute Candies + * https://leetcode.com/problems/count-ways-to-distribute-candies/ + * Difficulty: Hard + * + * There are n unique candies (labeled 1 through n) and k bags. You are asked to distribute all + * the candies into the bags such that every bag has at least one candy. + * + * There can be multiple ways to distribute the candies. Two ways are considered different if + * the candies in one bag in the first way are not all in the same bag in the second way. The + * order of the bags and the order of the candies within each bag do not matter. + * + * For example, (1), (2,3) and (2), (1,3) are considered different because candies 2 and 3 in + * the bag (2,3) in the first way are not in the same bag in the second way (they are split + * between the bags (2) and (1,3)). However, (1), (2,3) and (3,2), (1) are considered the same + * because the candies in each bag are all in the same bags in both ways. + * + * Given two integers, n and k, return the number of different ways to distribute the candies. + * As the answer may be too large, return it modulo 109 + 7. + */ + +/** + * @param {number} n + * @param {number} k + * @return {number} + */ +var waysToDistribute = function(n, k) { + const MOD = 1e9 + 7; + const dp = new Array(n + 1).fill(0).map(() => new Array(k + 1).fill(0)); + + for (let i = 1; i <= n; i++) { + dp[i][1] = 1; + } + + for (let candies = 2; candies <= n; candies++) { + for (let bags = 2; bags <= Math.min(candies, k); bags++) { + dp[candies][bags] = (dp[candies - 1][bags - 1] + (bags * dp[candies - 1][bags]) % MOD) % MOD; + } + } + + return dp[n][k]; +}; diff --git a/solutions/1698-number-of-distinct-substrings-in-a-string.js b/solutions/1698-number-of-distinct-substrings-in-a-string.js new file mode 100644 index 00000000..d7700654 --- /dev/null +++ b/solutions/1698-number-of-distinct-substrings-in-a-string.js @@ -0,0 +1,27 @@ +/** + * 1698. Number of Distinct Substrings in a String + * https://leetcode.com/problems/number-of-distinct-substrings-in-a-string/ + * Difficulty: Medium + * + * Given a string s, return the number of distinct substrings of s. + * + * A substring of a string is obtained by deleting any number of characters (possibly zero) + * from the front of the string and any number (possibly zero) from the back of the string. + */ + +/** + * @param {string} s + * @return {number} + */ +var countDistinct = function(s) { + const set = new Set(); + const length = s.length; + + for (let start = 0; start < length; start++) { + for (let end = start; end < length; end++) { + set.add(s.substring(start, end + 1)); + } + } + + return set.size; +}; diff --git a/solutions/1708-largest-subarray-length-k.js b/solutions/1708-largest-subarray-length-k.js new file mode 100644 index 00000000..bf6490d1 --- /dev/null +++ b/solutions/1708-largest-subarray-length-k.js @@ -0,0 +1,33 @@ +/** + * 1708. Largest Subarray Length K + * https://leetcode.com/problems/largest-subarray-length-k/ + * Difficulty: Easy + * + * An array A is larger than some array B if for the first index i where A[i] != B[i], A[i] > B[i]. + * + * For example, consider 0-indexing: + * - [1,3,2,4] > [1,2,2,4], since at index 1, 3 > 2. + * - [1,4,4,4] < [2,1,1,1], since at index 0, 1 < 2. + * + * A subarray is a contiguous subsequence of the array. + * + * Given an integer array nums of distinct integers, return the largest subarray of nums of + * length k. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number[]} + */ +var largestSubarray = function(nums, k) { + let maxStartIndex = 0; + + for (let i = 1; i <= nums.length - k; i++) { + if (nums[i] > nums[maxStartIndex]) { + maxStartIndex = i; + } + } + + return nums.slice(maxStartIndex, maxStartIndex + k); +}; diff --git a/solutions/1714-sum-of-special-evenly-spaced-elements-in-array.js b/solutions/1714-sum-of-special-evenly-spaced-elements-in-array.js new file mode 100644 index 00000000..de256870 --- /dev/null +++ b/solutions/1714-sum-of-special-evenly-spaced-elements-in-array.js @@ -0,0 +1,53 @@ +/** + * 1714. Sum Of Special Evenly-Spaced Elements In Array + * https://leetcode.com/problems/sum-of-special-evenly-spaced-elements-in-array/ + * Difficulty: Hard + * + * You are given a 0-indexed integer array nums consisting of n non-negative integers. + * + * You are also given an array queries, where queries[i] = [xi, yi]. The answer to the ith + * query is the sum of all nums[j] where xi <= j < n and (j - xi) is divisible by yi. + * + * Return an array answer where answer.length == queries.length and answer[i] is the answer + * to the ith query modulo 109 + 7. + */ + +/** + * @param {number[]} nums + * @param {number[][]} queries + * @return {number[]} + */ +var solve = function(nums, queries) { + const MOD = 1e9 + 7; + const n = nums.length; + const threshold = Math.sqrt(n); + const precomputed = new Map(); + + for (let step = 1; step <= threshold; step++) { + const suffixSums = new Array(n).fill(0); + for (let start = n - 1; start >= 0; start--) { + if (start + step < n) { + suffixSums[start] = (nums[start] + suffixSums[start + step]) % MOD; + } else { + suffixSums[start] = nums[start]; + } + } + precomputed.set(step, suffixSums); + } + + const result = []; + + for (const [startIndex, step] of queries) { + if (step <= threshold) { + result.push(precomputed.get(step)[startIndex] || 0); + } else { + let sum = 0; + for (let i = startIndex; i < n; i += step) { + sum = (sum + nums[i]) % MOD; + } + result.push(sum); + } + } + + return result; +}; diff --git a/solutions/1724-checking-existence-of-edge-length-limited-paths-ii.js b/solutions/1724-checking-existence-of-edge-length-limited-paths-ii.js new file mode 100644 index 00000000..401bcc62 --- /dev/null +++ b/solutions/1724-checking-existence-of-edge-length-limited-paths-ii.js @@ -0,0 +1,83 @@ +/** + * 1724. Checking Existence of Edge Length Limited Paths II + * https://leetcode.com/problems/checking-existence-of-edge-length-limited-paths-ii/ + * Difficulty: Hard + * + * An undirected graph of n nodes is defined by edgeList, where edgeList[i] = [ui, vi, disi] + * denotes an edge between nodes ui and vi with distance disi. Note that there may be multiple + * edges between two nodes, and the graph may not be connected. + * + * Implement the DistanceLimitedPathsExist class: + * - DistanceLimitedPathsExist(int n, int[][] edgeList) Initializes the class with an + * undirected graph. + * - boolean query(int p, int q, int limit) Returns true if there exists a path from p to q + * such that each edge on the path has a distance strictly less than limit, and otherwise + * false. + */ + +/** + * @param {number} n + * @param {number[][]} edgeList + */ +var DistanceLimitedPathsExist = function(n, edgeList) { + this.nodeCount = n; + this.sortedEdges = edgeList.slice().sort((a, b) => a[2] - b[2]); + this.unionFindByLimit = new Map(); + this.processedLimits = new Set(); +}; + +/** + * @param {number} p + * @param {number} q + * @param {number} limit + * @return {boolean} + */ +DistanceLimitedPathsExist.prototype.query = function(p, q, limit) { + if (!this.processedLimits.has(limit)) { + const unionFind = new UnionFind(this.nodeCount); + + for (const [u, v, weight] of this.sortedEdges) { + if (weight >= limit) break; + unionFind.union(u, v); + } + + this.unionFindByLimit.set(limit, unionFind); + this.processedLimits.add(limit); + } + + return this.unionFindByLimit.get(limit).connected(p, q); +}; + +class UnionFind { + constructor(n) { + this.parent = Array.from({ length: n }, (_, i) => i); + this.rank = new Array(n).fill(0); + } + + find(x) { + if (this.parent[x] !== 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) { + if (this.rank[rootX] < this.rank[rootY]) { + this.parent[rootX] = rootY; + } else if (this.rank[rootX] > this.rank[rootY]) { + this.parent[rootY] = rootX; + } else { + this.parent[rootY] = rootX; + this.rank[rootX]++; + } + } + } + + connected(x, y) { + return this.find(x) === this.find(y); + } +} diff --git a/solutions/1730-shortest-path-to-get-food.js b/solutions/1730-shortest-path-to-get-food.js new file mode 100644 index 00000000..beb22796 --- /dev/null +++ b/solutions/1730-shortest-path-to-get-food.js @@ -0,0 +1,68 @@ +/** + * 1730. Shortest Path to Get Food + * https://leetcode.com/problems/shortest-path-to-get-food/ + * Difficulty: Medium + * + * You are starving and you want to eat food as quickly as possible. You want to find the + * shortest path to arrive at any food cell. + * + * You are given an m x n character matrix, grid, of these different types of cells: + * - '*' is your location. There is exactly one '*' cell. + * - '#' is a food cell. There may be multiple food cells. + * - 'O' is free space, and you can travel through these cells. + * - 'X' is an obstacle, and you cannot travel through these cells. + * + * You can travel to any adjacent cell north, east, south, or west of your current location + * if there is not an obstacle. + * + * Return the length of the shortest path for you to reach any food cell. If there is no + * path for you to reach food, return -1. + */ + +/** + * @param {character[][]} grid + * @return {number} + */ +var getFood = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]; + let startRow = 0; + let startCol = 0; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (grid[i][j] === '*') { + startRow = i; + startCol = j; + break; + } + } + } + + const queue = [[startRow, startCol, 0]]; + const visited = new Set(); + visited.add(`${startRow},${startCol}`); + + while (queue.length > 0) { + const [currentRow, currentCol, steps] = queue.shift(); + + if (grid[currentRow][currentCol] === '#') { + return steps; + } + + for (const [deltaRow, deltaCol] of directions) { + const newRow = currentRow + deltaRow; + const newCol = currentCol + deltaCol; + const key = `${newRow},${newCol}`; + + if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols && !visited.has(key) + && grid[newRow][newCol] !== 'X') { + visited.add(key); + queue.push([newRow, newCol, steps + 1]); + } + } + } + + return -1; +}; diff --git a/solutions/1740-find-distance-in-a-binary-tree.js b/solutions/1740-find-distance-in-a-binary-tree.js new file mode 100644 index 00000000..e4bcff0a --- /dev/null +++ b/solutions/1740-find-distance-in-a-binary-tree.js @@ -0,0 +1,54 @@ +/** + * 1740. Find Distance in a Binary Tree + * https://leetcode.com/problems/find-distance-in-a-binary-tree/ + * Difficulty: Medium + * + * Given the root of a binary tree and two integers p and q, return the distance between the + * nodes of value p and value q in the tree. + * + * The distance between two nodes is the number of edges on the path from one to the other. + */ + +/** + * 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} + */ +var findDistance = function(root, p, q) { + if (p === q) return 0; + + const lca = findLCA(root); + const depthP = findDepth(lca, p, 0); + const depthQ = findDepth(lca, q, 0); + + return depthP + depthQ; + + function findLCA(node) { + if (!node || node.val === p || node.val === q) return node; + + const leftResult = findLCA(node.left); + const rightResult = findLCA(node.right); + + if (leftResult && rightResult) return node; + return leftResult || rightResult; + } + + function findDepth(node, target, depth) { + if (!node) return -1; + if (node.val === target) return depth; + + const leftDepth = findDepth(node.left, target, depth + 1); + if (leftDepth !== -1) return leftDepth; + + return findDepth(node.right, target, depth + 1); + } +}; diff --git a/solutions/1746-maximum-subarray-sum-after-one-operation.js b/solutions/1746-maximum-subarray-sum-after-one-operation.js new file mode 100644 index 00000000..57f9dd8c --- /dev/null +++ b/solutions/1746-maximum-subarray-sum-after-one-operation.js @@ -0,0 +1,44 @@ +/** + * 1746. Maximum Subarray Sum After One Operation + * https://leetcode.com/problems/maximum-subarray-sum-after-one-operation/ + * Difficulty: Medium + * + * You are given an integer array nums. You must perform exactly one operation where you can + * replace one element nums[i] with nums[i] * nums[i]. + * + * Return the maximum possible subarray sum after exactly one operation. The subarray must + * be non-empty. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxSumAfterOperation = function(nums) { + const n = nums.length; + let maxWithoutSquare = nums[0]; + let maxWithSquare = nums[0] * nums[0]; + let result = maxWithSquare; + + for (let i = 1; i < n; i++) { + const currentValue = nums[i]; + const squaredValue = currentValue * currentValue; + + const newMaxWithSquare = Math.max( + squaredValue, + maxWithoutSquare + squaredValue, + maxWithSquare + currentValue + ); + + const newMaxWithoutSquare = Math.max( + currentValue, + maxWithoutSquare + currentValue + ); + + maxWithSquare = newMaxWithSquare; + maxWithoutSquare = newMaxWithoutSquare; + result = Math.max(result, maxWithSquare); + } + + return result; +}; diff --git a/solutions/1756-design-most-recently-used-queue.js b/solutions/1756-design-most-recently-used-queue.js new file mode 100644 index 00000000..91ac1bb2 --- /dev/null +++ b/solutions/1756-design-most-recently-used-queue.js @@ -0,0 +1,30 @@ +/** + * 1756. Design Most Recently Used Queue + * https://leetcode.com/problems/design-most-recently-used-queue/ + * Difficulty: Medium + * + * Design a queue-like data structure that moves the most recently used element to the end + * of the queue. + * + * Implement the MRUQueue class: + * - MRUQueue(int n) constructs the MRUQueue with n elements: [1,2,3,...,n]. + * - int fetch(int k) moves the kth element (1-indexed) to the end of the queue and returns it. + */ + +/** + * @param {number} n + */ +var MRUQueue = function(n) { + this.elements = Array.from({ length: n }, (_, i) => i + 1); +}; + +/** + * @param {number} k + * @return {number} + */ +MRUQueue.prototype.fetch = function(k) { + const element = this.elements[k - 1]; + this.elements.splice(k - 1, 1); + this.elements.push(element); + return element; +}; diff --git a/solutions/1762-buildings-with-an-ocean-view.js b/solutions/1762-buildings-with-an-ocean-view.js new file mode 100644 index 00000000..34de9c3b --- /dev/null +++ b/solutions/1762-buildings-with-an-ocean-view.js @@ -0,0 +1,33 @@ +/** + * 1762. Buildings With an Ocean View + * https://leetcode.com/problems/buildings-with-an-ocean-view/ + * Difficulty: Medium + * + * There are n buildings in a line. You are given an integer array heights of size n that + * represents the heights of the buildings in the line. + * + * The ocean is to the right of the buildings. A building has an ocean view if the building + * can see the ocean without obstructions. Formally, a building has an ocean view if all the + * buildings to its right have a smaller height. + * + * Return a list of indices (0-indexed) of buildings that have an ocean view, sorted in + * increasing order. + */ + +/** + * @param {number[]} heights + * @return {number[]} + */ +var findBuildings = function(heights) { + const result = []; + let maxHeightFromRight = 0; + + for (let i = heights.length - 1; i >= 0; i--) { + if (heights[i] > maxHeightFromRight) { + result.push(i); + maxHeightFromRight = heights[i]; + } + } + + return result.reverse(); +}; diff --git a/solutions/1772-sort-features-by-popularity.js b/solutions/1772-sort-features-by-popularity.js new file mode 100644 index 00000000..66067e06 --- /dev/null +++ b/solutions/1772-sort-features-by-popularity.js @@ -0,0 +1,50 @@ +/** + * 1772. Sort Features by Popularity + * https://leetcode.com/problems/sort-features-by-popularity/ + * Difficulty: Medium + * + * You are given a string array features where features[i] is a single word that represents + * the name of a feature of the latest product you are working on. You have made a survey + * where users have reported which features they like. You are given a string array responses, + * where each responses[i] is a string containing space-separated words. + * + * The popularity of a feature is the number of responses[i] that contain the feature. You + * want to sort the features in non-increasing order by their popularity. If two features + * have the same popularity, order them by their original index in features. Notice that + * one response could contain the same feature multiple times; this feature is only counted + * once in its popularity. + * + * Return the features in sorted order. + */ + +/** + * @param {string[]} features + * @param {string[]} responses + * @return {string[]} + */ +var sortFeatures = function(features, responses) { + const map = new Map(); + + for (const feature of features) { + map.set(feature, 0); + } + + for (const response of responses) { + const uniqueWords = new Set(response.split(' ')); + for (const word of uniqueWords) { + if (map.has(word)) { + map.set(word, map.get(word) + 1); + } + } + } + + return features + .map((feature, index) => ({ feature, popularity: map.get(feature), index })) + .sort((a, b) => { + if (a.popularity !== b.popularity) { + return b.popularity - a.popularity; + } + return a.index - b.index; + }) + .map(item => item.feature); +}; diff --git a/solutions/1778-shortest-path-in-a-hidden-grid.js b/solutions/1778-shortest-path-in-a-hidden-grid.js new file mode 100644 index 00000000..a205d21b --- /dev/null +++ b/solutions/1778-shortest-path-in-a-hidden-grid.js @@ -0,0 +1,127 @@ +/** + * 1778. Shortest Path in a Hidden Grid + * https://leetcode.com/problems/shortest-path-in-a-hidden-grid/ + * Difficulty: Medium + * + * This is an interactive problem. + * + * There is a robot in a hidden grid, and you are trying to get it from its starting cell to the + * target cell in this grid. The grid is of size m x n, and each cell in the grid is either empty + * or blocked. It is guaranteed that the starting cell and the target cell are different, and + * neither of them is blocked. + * + * You want to find the minimum distance to the target cell. However, you do not know the grid's + * dimensions, the starting cell, nor the target cell. You are only allowed to ask queries to the + * GridMaster object. + * + * The GridMaster class has the following functions: + * - boolean canMove(char direction) Returns true if the robot can move in that direction. + * Otherwise, it returns false. + * - void move(char direction) Moves the robot in that direction. If this move would move the + * robot to a blocked cell or off the grid, the move will be ignored, and the robot will + * remain in the same position. + * - boolean isTarget() Returns true if the robot is currently on the target cell. Otherwise, + * it returns false. + * + * Note that direction in the above functions should be a character from {'U','D','L','R'}, + * representing the directions up, down, left, and right, respectively. + * + * Return the minimum distance between the robot's initial starting cell and the target cell. + * If there is no valid path between the cells, return -1. + * + * Custom testing: + * + * The test input is read as a 2D matrix grid of size m x n where: + * - grid[i][j] == -1 indicates that the robot is in cell (i, j) (the starting cell). + * - grid[i][j] == 0 indicates that the cell (i, j) is blocked. + * - grid[i][j] == 1 indicates that the cell (i, j) is empty. + * - grid[i][j] == 2 indicates that the cell (i, j) is the target cell. + * + * There is exactly one -1 and 2 in grid. Remember that you will not have this information + * in your code. + */ + +/** + * // This is the GridMaster's API interface. + * // You should not implement it, or speculate about its implementation + * function GridMaster() { + * + * @param {character} direction + * @return {boolean} + * this.canMove = function(direction) { + * ... + * }; + * @param {character} direction + * @return {void} + * this.move = function(direction) { + * ... + * }; + * @return {boolean} + * this.isTarget = function() { + * ... + * }; + * }; + */ + +/** + * @param {GridMaster} master + * @return {integer} + */ +var findShortestPath = function(master) { + const directions = [ + ['U', 'D', 0, -1], + ['D', 'U', 0, 1], + ['L', 'R', -1, 0], + ['R', 'L', 1, 0] + ]; + + const visited = new Set(); + let targetPosition = null; + + dfs(0, 0); + + if (!targetPosition) return -1; + + const queue = [[0, 0, 0]]; + const bfsVisited = new Set(['0,0']); + + while (queue.length > 0) { + const [x, y, distance] = queue.shift(); + + if (x === targetPosition[0] && y === targetPosition[1]) { + return distance; + } + + for (const [, , dx, dy] of directions) { + const newX = x + dx; + const newY = y + dy; + const key = `${newX},${newY}`; + + if (!bfsVisited.has(key) && visited.has(key)) { + bfsVisited.add(key); + queue.push([newX, newY, distance + 1]); + } + } + } + + return -1; + + function dfs(x, y) { + const key = `${x},${y}`; + if (visited.has(key)) return; + visited.add(key); + + if (master.isTarget()) { + targetPosition = [x, y]; + return; + } + + for (const [moveDir, backDir, dx, dy] of directions) { + if (master.canMove(moveDir)) { + master.move(moveDir); + dfs(x + dx, y + dy); + master.move(backDir); + } + } + } +}; diff --git a/solutions/1788-maximize-the-beauty-of-the-garden.js b/solutions/1788-maximize-the-beauty-of-the-garden.js new file mode 100644 index 00000000..bac04646 --- /dev/null +++ b/solutions/1788-maximize-the-beauty-of-the-garden.js @@ -0,0 +1,54 @@ +/** + * 1788. Maximize the Beauty of the Garden + * https://leetcode.com/problems/maximize-the-beauty-of-the-garden/ + * Difficulty: Hard + * + * There is a garden of n flowers, and each flower has an integer beauty value. The flowers + * are arranged in a line. You are given an integer array flowers of size n and each flowers[i] + * represents the beauty of the ith flower. + * + * A garden is valid if it meets these conditions: + * - The garden has at least two flowers. + * - The first and the last flower of the garden have the same beauty value. + * + * As the appointed gardener, you have the ability to remove any (possibly none) flowers from + * the garden. You want to remove flowers in a way that makes the remaining garden valid. The + * beauty of the garden is the sum of the beauty of all the remaining flowers. + * + * Return the maximum possible beauty of some valid garden after you have removed any (possibly + * none) flowers. + */ + +/** + * @param {number[]} flowers + * @return {number} + */ +var maximumBeauty = function(flowers) { + const map = new Map(); + + for (let i = 0; i < flowers.length; i++) { + if (!map.has(flowers[i])) { + map.set(flowers[i], []); + } + map.get(flowers[i]).push(i); + } + + const prefixSum = new Array(flowers.length + 1).fill(0); + for (let i = 0; i < flowers.length; i++) { + prefixSum[i + 1] = prefixSum[i] + Math.max(0, flowers[i]); + } + + let result = -Infinity; + + for (const [value, indices] of map) { + if (indices.length >= 2) { + const firstIndex = indices[0]; + const lastIndex = indices[indices.length - 1]; + const positiveSum = prefixSum[lastIndex] - prefixSum[firstIndex + 1]; + const beauty = 2 * value + positiveSum; + result = Math.max(result, beauty); + } + } + + return result; +}; diff --git a/solutions/1794-count-pairs-of-equal-substrings-with-minimum-difference.js b/solutions/1794-count-pairs-of-equal-substrings-with-minimum-difference.js new file mode 100644 index 00000000..082f9188 --- /dev/null +++ b/solutions/1794-count-pairs-of-equal-substrings-with-minimum-difference.js @@ -0,0 +1,52 @@ +/** + * 1794. Count Pairs of Equal Substrings With Minimum Difference + * https://leetcode.com/problems/count-pairs-of-equal-substrings-with-minimum-difference/ + * Difficulty: Medium + * + * You are given two strings firstString and secondString that are 0-indexed and consist only + * of lowercase English letters. Count the number of index quadruples (i,j,a,b) that satisfy + * the following conditions: + * - 0 <= i <= j < firstString.length + * - 0 <= a <= b < secondString.length + * - The substring of firstString that starts at the ith character and ends at the jth character + * (inclusive) is equal to the substring of secondString that starts at the ath character and + * ends at the bth character (inclusive). + * - j - a is the minimum possible value among all quadruples that satisfy the previous conditions. + * + * Return the number of such quadruples. + */ + +/** + * @param {string} firstString + * @param {string} secondString + * @return {number} + */ +var countQuadruples = function(firstString, secondString) { + const firstPositions = new Array(26).fill(0); + const secondPositions = new Array(26).fill(0); + let minDifference = Infinity; + let quadrupleCount = 0; + + for (let j = firstString.length - 1; j >= 0; j--) { + firstPositions[firstString[j].charCodeAt(0) - 97] = j + 1; + } + + for (let a = 0; a < secondString.length; a++) { + secondPositions[secondString[a].charCodeAt(0) - 97] = a + 1; + } + + for (let i = 0; i < 26; i++) { + if (firstPositions[i] && secondPositions[i]) { + const difference = firstPositions[i] - secondPositions[i]; + if (difference < minDifference) { + minDifference = difference; + quadrupleCount = 0; + } + if (difference === minDifference) { + quadrupleCount++; + } + } + } + + return quadrupleCount; +}; diff --git a/solutions/1804-implement-trie-ii-prefix-tree.js b/solutions/1804-implement-trie-ii-prefix-tree.js new file mode 100644 index 00000000..235af683 --- /dev/null +++ b/solutions/1804-implement-trie-ii-prefix-tree.js @@ -0,0 +1,81 @@ +/** + * 1804. Implement Trie II (Prefix Tree) + * https://leetcode.com/problems/implement-trie-ii-prefix-tree/ + * Difficulty: Medium + * + * A trie (pronounced as "try") or prefix tree is a tree data structure used to efficiently store + * and retrieve keys in a dataset of strings. There are various applications of this data structure, + * such as autocomplete and spellchecker. + * + * Implement the Trie class: + * - Trie() Initializes the trie object. + * - void insert(String word) Inserts the string word into the trie. + * - int countWordsEqualTo(String word) Returns the number of instances of the string word in the + * trie. + * - int countWordsStartingWith(String prefix) Returns the number of strings in the trie that have + * the string prefix as a prefix. + * - void erase(String word) Erases the string word from the trie. + */ + +var Trie = function() { + this.root = { children: {}, wordCount: 0, prefixCount: 0 }; +}; + +/** + * @param {string} word + * @return {void} + */ +Trie.prototype.insert = function(word) { + let currentNode = this.root; + for (const char of word) { + if (!currentNode.children[char]) { + currentNode.children[char] = { children: {}, wordCount: 0, prefixCount: 0 }; + } + currentNode = currentNode.children[char]; + currentNode.prefixCount++; + } + currentNode.wordCount++; +}; + +/** + * @param {string} word + * @return {number} + */ +Trie.prototype.countWordsEqualTo = function(word) { + let currentNode = this.root; + for (const char of word) { + if (!currentNode.children[char]) { + return 0; + } + currentNode = currentNode.children[char]; + } + return currentNode.wordCount; +}; + +/** + * @param {string} prefix + * @return {number} + */ +Trie.prototype.countWordsStartingWith = function(prefix) { + let currentNode = this.root; + for (const char of prefix) { + if (!currentNode.children[char]) { + return 0; + } + currentNode = currentNode.children[char]; + } + return currentNode.prefixCount; +}; + +/** + * @param {string} word + * @return {void} + */ +Trie.prototype.erase = function(word) { + let currentNode = this.root; + for (const char of word) { + currentNode = currentNode.children[char]; + currentNode.prefixCount--; + } + currentNode.wordCount--; +}; diff --git a/solutions/1810-minimum-path-cost-in-a-hidden-grid.js b/solutions/1810-minimum-path-cost-in-a-hidden-grid.js new file mode 100644 index 00000000..979de666 --- /dev/null +++ b/solutions/1810-minimum-path-cost-in-a-hidden-grid.js @@ -0,0 +1,147 @@ +/** + * 1810. Minimum Path Cost in a Hidden Grid + * https://leetcode.com/problems/minimum-path-cost-in-a-hidden-grid/ + * Difficulty: Medium + * + * This is an interactive problem. + * + * There is a robot in a hidden grid, and you are trying to get it from its starting cell to the + * target cell in this grid. The grid is of size m x n, and each cell in the grid is either empty + * or blocked. It is guaranteed that the starting cell and the target cell are different, and + * neither of them is blocked. + * + * Each cell has a cost that you need to pay each time you move to the cell. The starting cell's + * cost is not applied before the robot moves. + * + * You want to find the minimum total cost to move the robot to the target cell. However, you do + * not know the grid's dimensions, the starting cell, nor the target cell. You are only allowed + * to ask queries to the GridMaster object. + * + * The GridMaster class has the following functions: + * - boolean canMove(char direction) Returns true if the robot can move in that direction. + * Otherwise, it returns false. + * - int move(char direction) Moves the robot in that direction and returns the cost of moving + * to that cell. If this move would move the robot to a blocked cell or off the grid, the move + * will be ignored, the robot will remain in the same position, and the function will return -1. + * - boolean isTarget() Returns true if the robot is currently on the target cell. Otherwise, it + * returns false. + * + * Note that direction in the above functions should be a character from {'U','D','L','R'}, + * representing the directions up, down, left, and right, respectively. + * + * Return the minimum total cost to get the robot from its initial starting cell to the target + * cell. If there is no valid path between the cells, return -1. + * + * Custom testing: + * + * The test input is read as a 2D matrix grid of size m x n and four integers r1, c1, r2, and + * c2 where: + * - grid[i][j] == 0 indicates that the cell (i, j) is blocked. + * - grid[i][j] >= 1 indicates that the cell (i, j) is empty and grid[i][j] is the cost to move + * to that cell. + * - (r1, c1) is the starting cell of the robot. + * - (r2, c2) is the target cell of the robot. + * + * Remember that you will not have this information in your code. + */ + +/** + * // This is the GridMaster's API interface. + * // You should not implement it, or speculate about its implementation + * function GridMaster() { + * + * @param {character} direction + * @return {boolean} + * this.canMove = function(direction) { + * ... + * }; + * @param {character} direction + * @return {integer} + * this.move = function(direction) { + * ... + * }; + * @return {boolean} + * this.isTarget = function() { + * ... + * }; + * }; + */ + +/** + * @param {GridMaster} master + * @return {integer} + */ +var findShortestPath = function(master) { + const directions = ['U', 'D', 'L', 'R']; + const opposites = { 'U': 'D', 'D': 'U', 'L': 'R', 'R': 'L' }; + const deltas = { 'U': [-1, 0], 'D': [1, 0], 'L': [0, -1], 'R': [0, 1] }; + const visited = new Set(); + const cellCosts = new Map(); + let targetPosition = null; + + cellCosts.set('0,0', 0); + dfs(0, 0); + + if (!targetPosition) return -1; + + const dijkstraVisited = new Set(); + const priorityQueue = new PriorityQueue((a, b) => a[2] - b[2]); + priorityQueue.enqueue([0, 0, 0]); + + while (!priorityQueue.isEmpty()) { + const [currentRow, currentCol, currentCost] = priorityQueue.dequeue(); + const currentKey = `${currentRow},${currentCol}`; + + if (dijkstraVisited.has(currentKey)) continue; + dijkstraVisited.add(currentKey); + + if (currentRow === targetPosition[0] && currentCol === targetPosition[1]) { + return currentCost; + } + + for (const direction of directions) { + const [deltaRow, deltaCol] = deltas[direction]; + const nextRow = currentRow + deltaRow; + const nextCol = currentCol + deltaCol; + const nextKey = `${nextRow},${nextCol}`; + + if (cellCosts.has(nextKey) && !dijkstraVisited.has(nextKey)) { + const nextCost = currentCost + cellCosts.get(nextKey); + priorityQueue.enqueue([nextRow, nextCol, nextCost]); + } + } + } + + return -1; + + function dfs(row, col) { + const key = `${row},${col}`; + if (visited.has(key)) return; + + visited.add(key); + + if (master.isTarget()) { + targetPosition = [row, col]; + } + + for (const direction of directions) { + if (master.canMove(direction)) { + const cost = master.move(direction); + if (cost !== -1) { + const [deltaRow, deltaCol] = deltas[direction]; + const newRow = row + deltaRow; + const newCol = col + deltaCol; + const newKey = `${newRow},${newCol}`; + + if (!cellCosts.has(newKey)) { + cellCosts.set(newKey, cost); + } + + dfs(newRow, newCol); + + master.move(opposites[direction]); + } + } + } + } +}; diff --git a/solutions/1820-maximum-number-of-accepted-invitations.js b/solutions/1820-maximum-number-of-accepted-invitations.js new file mode 100644 index 00000000..5c6f1c11 --- /dev/null +++ b/solutions/1820-maximum-number-of-accepted-invitations.js @@ -0,0 +1,48 @@ +/** + * 1820. Maximum Number of Accepted Invitations + * https://leetcode.com/problems/maximum-number-of-accepted-invitations/ + * Difficulty: Medium + * + * There are m boys and n girls in a class attending an upcoming party. + * + * You are given an m x n integer matrix grid, where grid[i][j] equals 0 or 1. If grid[i][j] == 1, + * then that means the ith boy can invite the jth girl to the party. A boy can invite at most one + * girl, and a girl can accept at most one invitation from a boy. + * + * Return the maximum possible number of accepted invitations. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var maximumInvitations = function(grid) { + const boyCount = grid.length; + const girlCount = grid[0].length; + const girlMatched = new Array(girlCount).fill(-1); + + let result = 0; + + for (let boy = 0; boy < boyCount; boy++) { + const visited = new Array(girlCount).fill(false); + if (findMatch(boy, visited)) { + result++; + } + } + + return result; + + function findMatch(boy, visited) { + for (let girl = 0; girl < girlCount; girl++) { + if (grid[boy][girl] && !visited[girl]) { + visited[girl] = true; + + if (girlMatched[girl] === -1 || findMatch(girlMatched[girl], visited)) { + girlMatched[girl] = boy; + return true; + } + } + } + return false; + } +}; diff --git a/solutions/1826-faulty-sensor.js b/solutions/1826-faulty-sensor.js new file mode 100644 index 00000000..6271adf4 --- /dev/null +++ b/solutions/1826-faulty-sensor.js @@ -0,0 +1,69 @@ +/** + * 1826. Faulty Sensor + * https://leetcode.com/problems/faulty-sensor/ + * Difficulty: Easy + * + * An experiment is being conducted in a lab. To ensure accuracy, there are two sensors + * collecting data simultaneously. You are given two arrays sensor1 and sensor2, where + * sensor1[i] and sensor2[i] are the ith data points collected by the two sensors. + * + * However, this type of sensor has a chance of being defective, which causes exactly one data + * point to be dropped. After the data is dropped, all the data points to the right of the + * dropped data are shifted one place to the left, and the last data point is replaced with + * some random value. It is guaranteed that this random value will not be equal to the dropped + * value. + * - For example, if the correct data is [1,2,3,4,5] and 3 is dropped, the sensor could + * return [1,2,4,5,7] (the last position can be any value, not just 7). + * + * We know that there is a defect in at most one of the sensors. Return the sensor number + * (1 or 2) with the defect. If there is no defect in either sensor or if it is impossible + * to determine the defective sensor, return -1. + */ + +/** + * @param {number[]} sensor1 + * @param {number[]} sensor2 + * @return {number} + */ +var badSensor = function(sensor1, sensor2) { + const length = sensor1.length; + let firstDifference = -1; + + for (let i = 0; i < length; i++) { + if (sensor1[i] !== sensor2[i]) { + firstDifference = i; + break; + } + } + + if (firstDifference === -1) { + return -1; + } + + let sensor1Defective = true; + let sensor2Defective = true; + + for (let i = firstDifference; i < length - 1; i++) { + if (sensor1[i] !== sensor2[i + 1]) { + sensor1Defective = false; + break; + } + } + + for (let i = firstDifference; i < length - 1; i++) { + if (sensor2[i] !== sensor1[i + 1]) { + sensor2Defective = false; + break; + } + } + + if (sensor1Defective && !sensor2Defective) { + return 1; + } + + if (sensor2Defective && !sensor1Defective) { + return 2; + } + + return -1; +}; diff --git a/solutions/1836-remove-duplicates-from-an-unsorted-linked-list.js b/solutions/1836-remove-duplicates-from-an-unsorted-linked-list.js new file mode 100644 index 00000000..58e17b49 --- /dev/null +++ b/solutions/1836-remove-duplicates-from-an-unsorted-linked-list.js @@ -0,0 +1,47 @@ +/** + * 1836. Remove Duplicates From an Unsorted Linked List + * https://leetcode.com/problems/remove-duplicates-from-an-unsorted-linked-list/ + * Difficulty: Medium + * + * Given the head of a linked list, find all the values that appear more than once in the list + * and delete the nodes that have any of those values. + * + * Return the linked list after the deletions. + */ + +/** + * 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} + */ +var deleteDuplicatesUnsorted = function(head) { + const map = new Map(); + let current = head; + + while (current) { + map.set(current.val, (map.get(current.val) || 0) + 1); + current = current.next; + } + + const dummy = new ListNode(0); + dummy.next = head; + let previous = dummy; + current = head; + + while (current) { + if (map.get(current.val) > 1) { + previous.next = current.next; + } else { + previous = current; + } + current = current.next; + } + + return dummy.next; +}; diff --git a/solutions/1842-next-palindrome-using-same-digits.js b/solutions/1842-next-palindrome-using-same-digits.js new file mode 100644 index 00000000..906c3d29 --- /dev/null +++ b/solutions/1842-next-palindrome-using-same-digits.js @@ -0,0 +1,60 @@ +/** + * 1842. Next Palindrome Using Same Digits + * https://leetcode.com/problems/next-palindrome-using-same-digits/ + * Difficulty: Hard + * + * You are given a numeric string num, representing a very large palindrome. + * + * Return the smallest palindrome larger than num that can be created by rearranging its + * digits. If no such palindrome exists, return an empty string "". + * + * A palindrome is a number that reads the same backward as forward. + */ + +/** + * @param {string} num + * @return {string} + */ +var nextPalindrome = function(num) { + const length = num.length; + const halfLength = Math.floor(length / 2); + const leftHalf = num.slice(0, halfLength).split(''); + + if (!nextPermutation(leftHalf)) { + return ''; + } + + const rightHalf = leftHalf.slice().reverse(); + const result = leftHalf.join('') + (length % 2 === 1 ? num[halfLength] : '') + rightHalf.join(''); + + return result; + + function nextPermutation(digits) { + let pivot = -1; + + for (let i = digits.length - 2; i >= 0; i--) { + if (digits[i] < digits[i + 1]) { + pivot = i; + break; + } + } + + if (pivot === -1) return false; + + for (let i = digits.length - 1; i > pivot; i--) { + if (digits[i] > digits[pivot]) { + [digits[pivot], digits[i]] = [digits[i], digits[pivot]]; + break; + } + } + + const leftPart = digits.slice(0, pivot + 1); + const rightPart = digits.slice(pivot + 1).reverse(); + + for (let i = 0; i < digits.length; i++) { + digits[i] = i < leftPart.length ? leftPart[i] : rightPart[i - leftPart.length]; + } + + return true; + } +}; diff --git a/solutions/1852-distinct-numbers-in-each-subarray.js b/solutions/1852-distinct-numbers-in-each-subarray.js new file mode 100644 index 00000000..25cf47f2 --- /dev/null +++ b/solutions/1852-distinct-numbers-in-each-subarray.js @@ -0,0 +1,43 @@ +/** + * 1852. Distinct Numbers in Each Subarray + * https://leetcode.com/problems/distinct-numbers-in-each-subarray/ + * Difficulty: Medium + * + * You are given an integer array nums of length n and an integer k. Your task is to find + * the number of distinct elements in every subarray of size k within nums. + * + * Return an array ans such that ans[i] is the count of distinct elements in + * nums[i..(i + k - 1)] for each index 0 <= i < n - k. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number[]} + */ +var distinctNumbers = function(nums, k) { + const result = []; + const map = new Map(); + + for (let i = 0; i < k; i++) { + map.set(nums[i], (map.get(nums[i]) || 0) + 1); + } + + result.push(map.size); + + for (let i = k; i < nums.length; i++) { + const leftElement = nums[i - k]; + const rightElement = nums[i]; + + map.set(leftElement, map.get(leftElement) - 1); + if (map.get(leftElement) === 0) { + map.delete(leftElement); + } + + map.set(rightElement, (map.get(rightElement) || 0) + 1); + + result.push(map.size); + } + + return result; +}; diff --git a/solutions/1858-longest-word-with-all-prefixes.js b/solutions/1858-longest-word-with-all-prefixes.js new file mode 100644 index 00000000..18f1c4f7 --- /dev/null +++ b/solutions/1858-longest-word-with-all-prefixes.js @@ -0,0 +1,41 @@ +/** + * 1858. Longest Word With All Prefixes + * https://leetcode.com/problems/longest-word-with-all-prefixes/ + * Difficulty: Medium + * + * Given an array of strings words, find the longest string in words such that every + * prefix of it is also in words. + * - For example, let words = ["a", "app", "ap"]. The string "app" has prefixes "ap" and "a", + * all of which are in words. + * + * Return the string described above. If there is more than one string with the same length, + * return the lexicographically smallest one, and if no string exists, return "". + */ + +/** + * @param {string[]} words + * @return {string} + */ +var longestWord = function(words) { + const set = new Set(words); + let result = ''; + + for (const word of words) { + let hasAllPrefixes = true; + + for (let i = 1; i < word.length; i++) { + if (!set.has(word.slice(0, i))) { + hasAllPrefixes = false; + break; + } + } + + if (hasAllPrefixes) { + if (word.length > result.length || (word.length === result.length && word < result)) { + result = word; + } + } + } + + return result; +}; diff --git a/solutions/1868-product-of-two-run-length-encoded-arrays.js b/solutions/1868-product-of-two-run-length-encoded-arrays.js new file mode 100644 index 00000000..4a8d9ff6 --- /dev/null +++ b/solutions/1868-product-of-two-run-length-encoded-arrays.js @@ -0,0 +1,66 @@ +/** + * 1868. Product of Two Run-Length Encoded Arrays + * https://leetcode.com/problems/product-of-two-run-length-encoded-arrays/ + * Difficulty: Medium + * + * Run-length encoding is a compression algorithm that allows for an integer array nums with + * many segments of consecutive repeated numbers to be represented by a (generally smaller) + * 2D array encoded. Each encoded[i] = [vali, freqi] describes the ith segment of repeated + * numbers in nums where vali is the value that is repeated freqi times. + * - For example, nums = [1,1,1,2,2,2,2,2] is represented by the run-length encoded array + * encoded = [[1,3],[2,5]]. Another way to read this is "three 1's followed by five 2's". + * + * The product of two run-length encoded arrays encoded1 and encoded2 can be calculated using + * the following steps: + * 1. Expand both encoded1 and encoded2 into the full arrays nums1 and nums2 respectively. + * 2. Create a new array prodNums of length nums1.length and set prodNums[i] = nums1[i] * nums2[i]. + * 3. Compress prodNums into a run-length encoded array and return it. + * + * You are given two run-length encoded arrays encoded1 and encoded2 representing full arrays + * nums1 and nums2 respectively. Both nums1 and nums2 have the same length. Each + * encoded1[i] = [vali, freqi] describes the ith segment of nums1, and each + * encoded2[j] = [valj, freqj] describes the jth segment of nums2. + * + * Return the product of encoded1 and encoded2. + * + * Note: Compression should be done such that the run-length encoded array has the minimum + * possible length. + */ + +/** + * @param {number[][]} encoded1 + * @param {number[][]} encoded2 + * @return {number[][]} + */ +var findRLEArray = function(encoded1, encoded2) { + const result = []; + let i = 0; + let j = 0; + let freq1 = 0; + let freq2 = 0; + + while (i < encoded1.length && j < encoded2.length) { + if (freq1 === 0) { + freq1 = encoded1[i][1]; + } + if (freq2 === 0) { + freq2 = encoded2[j][1]; + } + + const product = encoded1[i][0] * encoded2[j][0]; + const minFreq = Math.min(freq1, freq2); + if (result.length > 0 && result[result.length - 1][0] === product) { + result[result.length - 1][1] += minFreq; + } else { + result.push([product, minFreq]); + } + + freq1 -= minFreq; + freq2 -= minFreq; + + if (freq1 === 0) i++; + if (freq2 === 0) j++; + } + + return result; +}; diff --git a/solutions/1874-minimize-product-sum-of-two-arrays.js b/solutions/1874-minimize-product-sum-of-two-arrays.js new file mode 100644 index 00000000..b02400ea --- /dev/null +++ b/solutions/1874-minimize-product-sum-of-two-arrays.js @@ -0,0 +1,25 @@ +/** + * 1874. Minimize Product Sum of Two Arrays + * https://leetcode.com/problems/minimize-product-sum-of-two-arrays/ + * Difficulty: Medium + * + * The product sum of two equal-length arrays a and b is equal to the sum of a[i] * b[i] + * for all 0 <= i < a.length (0-indexed). + * - For example, if a = [1,2,3,4] and b = [5,2,3,1], the product sum would be + * 1*5 + 2*2 + 3*3 + 4*1 = 22. + * + * Given two arrays nums1 and nums2 of length n, return the minimum product sum if you are + * allowed to rearrange the order of the elements in nums1. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var minProductSum = function(nums1, nums2) { + nums1.sort((a, b) => a - b); + nums2.sort((a, b) => b - a); + + return nums1.reduce((sum, val, i) => sum + val * nums2[i], 0); +}; diff --git a/solutions/1885-count-pairs-in-two-arrays.js b/solutions/1885-count-pairs-in-two-arrays.js new file mode 100644 index 00000000..f6445029 --- /dev/null +++ b/solutions/1885-count-pairs-in-two-arrays.js @@ -0,0 +1,35 @@ +/** + * 1885. Count Pairs in Two Arrays + * https://leetcode.com/problems/count-pairs-in-two-arrays/ + * Difficulty: Medium + * + * Given two integer arrays nums1 and nums2 of length n, count the pairs of indices (i, j) + * such that i < j and nums1[i] + nums1[j] > nums2[i] + nums2[j]. + * + * Return the number of pairs satisfying the condition. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var countPairs = function(nums1, nums2) { + const differences = nums1.map((val, i) => val - nums2[i]); + differences.sort((a, b) => a - b); + + let count = 0; + let left = 0; + let right = differences.length - 1; + + while (left < right) { + if (differences[left] + differences[right] > 0) { + count += right - left; + right--; + } else { + left++; + } + } + + return count; +}; diff --git a/solutions/1891-cutting-ribbons.js b/solutions/1891-cutting-ribbons.js new file mode 100644 index 00000000..08abe052 --- /dev/null +++ b/solutions/1891-cutting-ribbons.js @@ -0,0 +1,53 @@ +/** + * 1891. Cutting Ribbons + * https://leetcode.com/problems/cutting-ribbons/ + * Difficulty: Medium + * + * You are given an integer array ribbons, where ribbons[i] represents the length of the ith + * ribbon, and an integer k. You may cut any of the ribbons into any number of segments of + * positive integer lengths, or perform no cuts at all. + * + * - For example, if you have a ribbon of length 4, you can: + * - Keep the ribbon of length 4, + * - Cut it into one ribbon of length 3 and one ribbon of length 1, + * - Cut it into two ribbons of length 2, + * - Cut it into one ribbon of length 2 and two ribbons of length 1, or + * - Cut it into four ribbons of length 1. + * + * Your task is to determine the maximum length of ribbon, x, that allows you to cut at least + * k ribbons, each of length x. You can discard any leftover ribbon from the cuts. If it is + * impossible to cut k ribbons of the same length, return 0. + */ + +/** + * @param {number[]} ribbons + * @param {number} k + * @return {number} + */ +var maxLength = function(ribbons, k) { + let left = 1; + let right = Math.max(...ribbons); + let result = 0; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + + if (helper(mid)) { + result = mid; + left = mid + 1; + } else { + right = mid - 1; + } + } + + return result; + + function helper(length) { + let count = 0; + for (const ribbon of ribbons) { + count += Math.floor(ribbon / length); + if (count >= k) return true; + } + return false; + } +}; diff --git a/solutions/1902-depth-of-bst-given-insertion-order.js b/solutions/1902-depth-of-bst-given-insertion-order.js new file mode 100644 index 00000000..9f568400 --- /dev/null +++ b/solutions/1902-depth-of-bst-given-insertion-order.js @@ -0,0 +1,63 @@ +/** + * 1902. Depth of BST Given Insertion Order + * https://leetcode.com/problems/depth-of-bst-given-insertion-order/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array order of length n, a permutation of integers + * from 1 to n representing the order of insertion into a binary search tree. + * + * A binary search tree is defined as follows: + * - The left subtree of a node contains only nodes with keys less than the node's key. + * - The right subtree of a node contains only nodes with keys greater than the node's key. + * - Both the left and right subtrees must also be binary search trees. + * + * The binary search tree is constructed as follows: + * - order[0] will be the root of the binary search tree. + * - All subsequent elements are inserted as the child of any existing node such that the + * binary search tree properties hold. + * + * Return the depth of the binary search tree. + * + * A binary tree's depth is the number of nodes along the longest path from the root node + * down to the farthest leaf node. + */ + +/** + * @param {number[]} order + * @return {number} + */ +var maxDepthBST = function(order) { + const n = order.length; + const parents = new Array(n + 1).fill(0); + const insertOrders = new Array(n + 1).fill(0); + + for (let i = 0; i < n; i++) { + insertOrders[order[i]] = i + 1; + } + + const stack = []; + + for (let node = 0; node <= n; node++) { + const insertOrder = insertOrders[node]; + + while (stack.length > 0 && insertOrders[stack[stack.length - 1]] > insertOrder) { + const prevNode = stack.pop(); + if (insertOrders[parents[prevNode]] < insertOrder) { + parents[prevNode] = node; + } + } + + if (stack.length > 0) { + parents[node] = stack[stack.length - 1]; + } + + stack.push(node); + } + + const depths = new Array(n + 1).fill(0); + for (const num of order) { + depths[num] = depths[parents[num]] + 1; + } + + return Math.max(...depths); +}; diff --git a/solutions/1908-game-of-nim.js b/solutions/1908-game-of-nim.js new file mode 100644 index 00000000..831932d9 --- /dev/null +++ b/solutions/1908-game-of-nim.js @@ -0,0 +1,50 @@ +/** + * 1908. Game of Nim + * https://leetcode.com/problems/game-of-nim/ + * Difficulty: Medium + * + * Alice and Bob take turns playing a game with Alice starting first. + * + * In this game, there are n piles of stones. On each player's turn, the player should remove + * any positive number of stones from a non-empty pile of his or her choice. The first player + * who cannot make a move loses, and the other player wins. + * + * Given an integer array piles, where piles[i] is the number of stones in the ith pile, return + * true if Alice wins, or false if Bob wins. + * + * Both Alice and Bob play optimally. + */ + +/** + * @param {number[]} piles + * @return {boolean} + */ +var nimGame = function(piles) { + const map = new Map(); + return helper(piles); + + function helper(currentPiles) { + const key = currentPiles.join(','); + if (map.has(key)) return map.get(key); + + if (currentPiles.every(pile => pile === 0)) { + map.set(key, false); + return false; + } + + for (let i = 0; i < currentPiles.length; i++) { + for (let take = 1; take <= currentPiles[i]; take++) { + const nextPiles = [...currentPiles]; + nextPiles[i] -= take; + + if (!helper(nextPiles)) { + map.set(key, true); + return true; + } + } + } + + map.set(key, false); + return false; + } +}; diff --git a/solutions/1918-kth-smallest-subarray-sum.js b/solutions/1918-kth-smallest-subarray-sum.js new file mode 100644 index 00000000..7d241827 --- /dev/null +++ b/solutions/1918-kth-smallest-subarray-sum.js @@ -0,0 +1,51 @@ +/** + * 1918. Kth Smallest Subarray Sum + * https://leetcode.com/problems/kth-smallest-subarray-sum/ + * Difficulty: Medium + * + * Given an integer array nums of length n and an integer k, return the kth smallest subarray sum. + * + * A subarray is defined as a non-empty contiguous sequence of elements in an array. A subarray + * sum is the sum of all elements in the subarray. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var kthSmallestSubarraySum = function(nums, k) { + let result = Math.min(...nums); + let maxSum = nums.reduce((sum, num) => sum + num, 0); + + while (result < maxSum) { + const midSum = Math.floor((result + maxSum) / 2); + + if (countSubarraysWithSumLessOrEqual(midSum) < k) { + result = midSum + 1; + } else { + maxSum = midSum; + } + } + + return result; + + function countSubarraysWithSumLessOrEqual(target) { + let count = 0; + let left = 0; + let currentSum = 0; + + for (let right = 0; right < nums.length; right++) { + currentSum += nums[right]; + + while (currentSum > target) { + currentSum -= nums[left]; + left++; + } + + count += right - left + 1; + } + + return count; + } +}; diff --git a/solutions/1924-erect-the-fence-ii.js b/solutions/1924-erect-the-fence-ii.js new file mode 100644 index 00000000..ba04f009 --- /dev/null +++ b/solutions/1924-erect-the-fence-ii.js @@ -0,0 +1,91 @@ +/** + * 1924. Erect the Fence II + * https://leetcode.com/problems/erect-the-fence-ii/ + * Difficulty: Hard + * + * You are given a 2D integer array trees where trees[i] = [xi, yi] represents the location + * of the ith tree in the garden. + * + * You are asked to fence the entire garden using the minimum length of rope possible. The garden + * is well-fenced only if all the trees are enclosed and the rope used forms a perfect circle. + * A tree is considered enclosed if it is inside or on the border of the circle. + * + * More formally, you must form a circle using the rope with a center (x, y) and radius r where + * all trees lie inside or on the circle and r is minimum. + * + * Return the center and radius of the circle as a length 3 array [x, y, r]. Answers within 10-5 + * of the actual answer will be accepted. + */ + +/** + * @param {number[][]} trees + * @return {number[]} + */ +var outerTrees = function(trees) { + const n = trees.length; + + if (n === 1) { + return [trees[0][0], trees[0][1], 0]; + } + + const shuffled = [...trees]; + for (let i = shuffled.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; + } + + return getMinimumEnclosingCircle(shuffled, []); + + function distance(p1, p2) { + return Math.sqrt((p1[0] - p2[0]) ** 2 + (p1[1] - p2[1]) ** 2); + } + + function getCircleFromTwoPoints(p1, p2) { + const x = (p1[0] + p2[0]) / 2; + const y = (p1[1] + p2[1]) / 2; + const r = distance(p1, p2) / 2; + return [x, y, r]; + } + + function getCircleFromThreePoints(p1, p2, p3) { + const [x1, y1] = p1; + const [x2, y2] = p2; + const [x3, y3] = p3; + + const d = 2 * (x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2)); + + if (Math.abs(d) < 1e-10) { + return null; + } + + const ux = ((x1 ** 2 + y1 ** 2) * (y2 - y3) + (x2 ** 2 + y2 ** 2) * (y3 - y1) + + (x3 ** 2 + y3 ** 2) * (y1 - y2)) / d; + const uy = ((x1 ** 2 + y1 ** 2) * (x3 - x2) + (x2 ** 2 + y2 ** 2) * (x1 - x3) + + (x3 ** 2 + y3 ** 2) * (x2 - x1)) / d; + const r = distance([ux, uy], p1); + + return [ux, uy, r]; + } + + function isInsideCircle(point, circle) { + const [x, y, r] = circle; + return distance(point, [x, y]) <= r + 1e-7; + } + + function getMinimumEnclosingCircle(points, boundary) { + if (boundary.length === 3 || points.length === 0) { + if (boundary.length === 0) return [0, 0, 0]; + if (boundary.length === 1) return [boundary[0][0], boundary[0][1], 0]; + if (boundary.length === 2) return getCircleFromTwoPoints(boundary[0], boundary[1]); + return getCircleFromThreePoints(boundary[0], boundary[1], boundary[2]); + } + + const point = points[0]; + const circle = getMinimumEnclosingCircle(points.slice(1), boundary); + if (isInsideCircle(point, circle)) { + return circle; + } + + return getMinimumEnclosingCircle(points.slice(1), boundary.concat([point])); + } +}; diff --git a/solutions/1933-check-if-string-is-decomposable-into-value-equal-substrings.js b/solutions/1933-check-if-string-is-decomposable-into-value-equal-substrings.js new file mode 100644 index 00000000..1267aa06 --- /dev/null +++ b/solutions/1933-check-if-string-is-decomposable-into-value-equal-substrings.js @@ -0,0 +1,50 @@ +/** + * 1933. Check if String Is Decomposable Into Value-Equal Substrings + * https://leetcode.com/problems/check-if-string-is-decomposable-into-value-equal-substrings/ + * Difficulty: Easy + * + * A value-equal string is a string where all characters are the same. + * - For example, "1111" and "33" are value-equal strings. + * - In contrast, "123" is not a value-equal string. + * + * Given a digit string s, decompose the string into some number of consecutive value-equal + * substrings where exactly one substring has a length of 2 and the remaining substrings + * have a length of 3. + * + * Return true if you can decompose s according to the above rules. Otherwise, return false. + * + * A substring is a contiguous sequence of characters in a string. + */ + +/** + * @param {string} s + * @return {boolean} + */ +var isDecomposable = function(s) { + const groups = []; + let i = 0; + + while (i < s.length) { + let j = i; + while (j < s.length && s[j] === s[i]) { + j++; + } + groups.push(j - i); + i = j; + } + + let result = false; + + for (const length of groups) { + if (length % 3 === 1) { + return false; + } else if (length % 3 === 2) { + if (result) { + return false; + } + result = true; + } + } + + return result; +}; diff --git a/solutions/1940-longest-common-subsequence-between-sorted-arrays.js b/solutions/1940-longest-common-subsequence-between-sorted-arrays.js new file mode 100644 index 00000000..a77ae4c1 --- /dev/null +++ b/solutions/1940-longest-common-subsequence-between-sorted-arrays.js @@ -0,0 +1,35 @@ +/** + * 1940. Longest Common Subsequence Between Sorted Arrays + * https://leetcode.com/problems/longest-common-subsequence-between-sorted-arrays/ + * Difficulty: Medium + * + * Given an array of integer arrays arrays where each arrays[i] is sorted in strictly increasing + * order, return an integer array representing the longest common subsequence among all the arrays. + * + * A subsequence is a sequence that can be derived from another sequence by deleting some elements + * (possibly none) without changing the order of the remaining elements. + */ + +/** + * @param {number[][]} arrays + * @return {number[]} + */ +var longestCommonSubsequence = function(arrays) { + const map = new Map(); + const totalArrays = arrays.length; + + for (const array of arrays) { + for (const num of array) { + map.set(num, (map.get(num) || 0) + 1); + } + } + + const result = []; + for (const [num, count] of map) { + if (count === totalArrays) { + result.push(num); + } + } + + return result.sort((a, b) => a - b); +}; diff --git a/solutions/1942-the-number-of-the-smallest-unoccupied-chair.js b/solutions/1942-the-number-of-the-smallest-unoccupied-chair.js new file mode 100644 index 00000000..bac12d08 --- /dev/null +++ b/solutions/1942-the-number-of-the-smallest-unoccupied-chair.js @@ -0,0 +1,62 @@ +/** + * 1942. The Number of the Smallest Unoccupied Chair + * https://leetcode.com/problems/the-number-of-the-smallest-unoccupied-chair/ + * Difficulty: Medium + * + * There is a party where n friends numbered from 0 to n - 1 are attending. There is an infinite + * number of chairs in this party that are numbered from 0 to infinity. When a friend arrives at + * the party, they sit on the unoccupied chair with the smallest number. + * - For example, if chairs 0, 1, and 5 are occupied when a friend comes, they will sit on chair + * number 2. + * + * When a friend leaves the party, their chair becomes unoccupied at the moment they leave. + * If another friend arrives at that same moment, they can sit in that chair. + * + * You are given a 0-indexed 2D integer array times where times[i] = [arrivali, leavingi], + * indicating the arrival and leaving times of the ith friend respectively, and an integer + * targetFriend. All arrival times are distinct. + * + * Return the chair number that the friend numbered targetFriend will sit on. + */ + +/** + * @param {number[][]} times + * @param {number} targetFriend + * @return {number} + */ +var smallestChair = function(times, targetFriend) { + const events = []; + + for (let i = 0; i < times.length; i++) { + events.push([times[i][0], 'arrive', i]); + events.push([times[i][1], 'leave', i]); + } + + events.sort((a, b) => a[0] - b[0] || (a[1] === 'leave' ? -1 : 1)); + + const availableChairs = []; + const occupiedChairs = new Map(); + let nextChair = 0; + + for (const [time, eventType, friendId] of events) { + if (eventType === 'leave') { + const chairNumber = occupiedChairs.get(friendId); + occupiedChairs.delete(friendId); + availableChairs.push(chairNumber); + availableChairs.sort((a, b) => a - b); + } else { + let assignedChair; + if (availableChairs.length > 0) { + assignedChair = availableChairs.shift(); + } else { + assignedChair = nextChair++; + } + + occupiedChairs.set(friendId, assignedChair); + + if (friendId === targetFriend) { + return assignedChair; + } + } + } +}; diff --git a/solutions/1950-maximum-of-minimum-values-in-all-subarrays.js b/solutions/1950-maximum-of-minimum-values-in-all-subarrays.js new file mode 100644 index 00000000..ab95408f --- /dev/null +++ b/solutions/1950-maximum-of-minimum-values-in-all-subarrays.js @@ -0,0 +1,59 @@ +/** + * 1950. Maximum of Minimum Values in All Subarrays + * https://leetcode.com/problems/maximum-of-minimum-values-in-all-subarrays/ + * Difficulty: Medium + * + * You are given an integer array nums of size n. You are asked to solve n queries for each + * integer i in the range 0 <= i < n. + * + * To solve the ith query: + * 1. Find the minimum value in each possible subarray of size i + 1 of the array nums. + * 2. Find the maximum of those minimum values. This maximum is the answer to the query. + * + * Return a 0-indexed integer array ans of size n such that ans[i] is the answer to the ith query. + * + * A subarray is a contiguous sequence of elements in an array. + */ + +/** + * @param {number[]} nums + * @return {number[]} + */ +var findMaximums = function(nums) { + const n = nums.length; + const result = new Array(n); + const leftBound = new Array(n); + const rightBound = new Array(n); + const stack = []; + + for (let i = 0; i < n; i++) { + while (stack.length > 0 && nums[stack[stack.length - 1]] >= nums[i]) { + stack.pop(); + } + leftBound[i] = stack.length > 0 ? stack[stack.length - 1] : -1; + stack.push(i); + } + + stack.length = 0; + + for (let i = n - 1; i >= 0; i--) { + while (stack.length > 0 && nums[stack[stack.length - 1]] >= nums[i]) { + stack.pop(); + } + rightBound[i] = stack.length > 0 ? stack[stack.length - 1] : n; + stack.push(i); + } + + result.fill(0); + + for (let i = 0; i < n; i++) { + const maxSubarrayLength = rightBound[i] - leftBound[i] - 1; + result[maxSubarrayLength - 1] = Math.max(result[maxSubarrayLength - 1], nums[i]); + } + + for (let i = n - 2; i >= 0; i--) { + result[i] = Math.max(result[i], result[i + 1]); + } + + return result; +}; diff --git a/solutions/1956-minimum-time-for-k-virus-variants-to-spread.js b/solutions/1956-minimum-time-for-k-virus-variants-to-spread.js new file mode 100644 index 00000000..a1f469c7 --- /dev/null +++ b/solutions/1956-minimum-time-for-k-virus-variants-to-spread.js @@ -0,0 +1,55 @@ +/** + * 1956. Minimum Time For K Virus Variants to Spread + * https://leetcode.com/problems/minimum-time-for-k-virus-variants-to-spread/ + * Difficulty: Hard + * + * There are n unique virus variants in an infinite 2D grid. You are given a 2D array points, + * where points[i] = [xi, yi] represents a virus originating at (xi, yi) on day 0. Note that + * it is possible for multiple virus variants to originate at the same point. + * + * Every day, each cell infected with a virus variant will spread the virus to all neighboring + * points in the four cardinal directions (i.e. up, down, left, and right). If a cell has multiple + * variants, all the variants will spread without interfering with each other. + * + * Given an integer k, return the minimum integer number of days for any point to contain at least + * k of the unique virus variants. + */ + +/** + * @param {number[][]} points + * @param {number} k + * @return {number} + */ +var minDayskVariants = function(points, k) { + let left = 0; + let right = 200; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + + if (check(mid)) { + right = mid; + } else { + left = mid + 1; + } + } + + return left; + + function check(day) { + for (let x = 1; x <= 100; x++) { + for (let y = 1; y <= 100; y++) { + let count = 0; + for (const [px, py] of points) { + if (Math.abs(x - px) + Math.abs(y - py) <= day) { + count++; + } + } + if (count >= k) { + return true; + } + } + } + return false; + } +}; diff --git a/solutions/1962-remove-stones-to-minimize-the-total.js b/solutions/1962-remove-stones-to-minimize-the-total.js new file mode 100644 index 00000000..40535ad8 --- /dev/null +++ b/solutions/1962-remove-stones-to-minimize-the-total.js @@ -0,0 +1,39 @@ +/** + * 1962. Remove Stones to Minimize the Total + * https://leetcode.com/problems/remove-stones-to-minimize-the-total/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array piles, where piles[i] represents the number + * of stones in the ith pile, and an integer k. You should apply the following operation + * exactly k times: + * - Choose any piles[i] and remove ceil(piles[i] / 2) stones from it. + * + * Notice that you can apply the operation on the same pile more than once. + * + * Return the minimum possible total number of stones remaining after applying the k operations. + * + * ceil(x) is the smallest integer that is greater than or equal to x (i.e., rounds x up). + */ + +/** + * @param {number[]} piles + * @param {number} k + * @return {number} + */ +var minStoneSum = function(piles, k) { + const maxHeap = new PriorityQueue((a, b) => b - a); + let result = 0; + + for (const pile of piles) { + maxHeap.enqueue(pile); + result += pile; + } + + while (k-- > 0) { + const largest = maxHeap.dequeue(); + maxHeap.enqueue(largest - Math.floor(largest / 2)); + result -= Math.floor(largest / 2); + } + + return result; +}; diff --git a/solutions/1966-binary-searchable-numbers-in-an-unsorted-array.js b/solutions/1966-binary-searchable-numbers-in-an-unsorted-array.js new file mode 100644 index 00000000..e29fb494 --- /dev/null +++ b/solutions/1966-binary-searchable-numbers-in-an-unsorted-array.js @@ -0,0 +1,60 @@ +/** + * 1966. Binary Searchable Numbers in an Unsorted Array + * https://leetcode.com/problems/binary-searchable-numbers-in-an-unsorted-array/ + * Difficulty: Medium + * + * Consider a function that implements an algorithm similar to Binary Search. The function has + * two input parameters: sequence is a sequence of integers, and target is an integer value. + * The purpose of the function is to find if the target exists in the sequence. + * + * The pseudocode of the function is as follows: + * + * func(sequence, target) + * while sequence is not empty + * randomly choose an element from sequence as the pivot + * if pivot = target, return true + * else if pivot < target, remove pivot and all elements to its left from the sequence + * else, remove pivot and all elements to its right from the sequence + * end while + * return false + * + * When the sequence is sorted, the function works correctly for all values. When the sequence + * is not sorted, the function does not work for all values, but may still work for some values. + * + * Given an integer array nums, representing the sequence, that contains unique numbers and may + * or may not be sorted, return the number of values that are guaranteed to be found using the + * function, for every possible pivot selection. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var binarySearchableNumbers = function(nums) { + const n = nums.length; + const leftMax = new Array(n); + const rightMin = new Array(n); + + leftMax[0] = nums[0]; + for (let i = 1; i < n; i++) { + leftMax[i] = Math.max(leftMax[i - 1], nums[i]); + } + + rightMin[n - 1] = nums[n - 1]; + for (let i = n - 2; i >= 0; i--) { + rightMin[i] = Math.min(rightMin[i + 1], nums[i]); + } + + let count = 0; + + for (let i = 0; i < n; i++) { + const leftMaxVal = i > 0 ? leftMax[i - 1] : -Infinity; + const rightMinVal = i < n - 1 ? rightMin[i + 1] : Infinity; + + if (leftMaxVal < nums[i] && nums[i] < rightMinVal) { + count++; + } + } + + return count; +}; diff --git a/solutions/1973-count-nodes-equal-to-sum-of-descendants.js b/solutions/1973-count-nodes-equal-to-sum-of-descendants.js new file mode 100644 index 00000000..20203c1d --- /dev/null +++ b/solutions/1973-count-nodes-equal-to-sum-of-descendants.js @@ -0,0 +1,43 @@ +/** + * 1973. Count Nodes Equal to Sum of Descendants + * https://leetcode.com/problems/count-nodes-equal-to-sum-of-descendants/ + * Difficulty: Medium + * + * Given the root of a binary tree, return the number of nodes where the value of the node is + * equal to the sum of the values of its descendants. + * + * A descendant of a node x is any node that is on the path from node x to some leaf node. The + * sum is considered to be 0 if the node has no descendants. + */ + +/** + * 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} + */ +var equalToDescendants = function(root) { + let count = 0; + dfs(root); + return count; + + function dfs(node) { + if (!node) return 0; + + const leftSum = dfs(node.left); + const rightSum = dfs(node.right); + const descendantSum = leftSum + rightSum; + + if (node.val === descendantSum) { + count++; + } + + return node.val + descendantSum; + } +}; diff --git a/solutions/1983-widest-pair-of-indices-with-equal-range-sum.js b/solutions/1983-widest-pair-of-indices-with-equal-range-sum.js new file mode 100644 index 00000000..c121129b --- /dev/null +++ b/solutions/1983-widest-pair-of-indices-with-equal-range-sum.js @@ -0,0 +1,42 @@ +/** + * 1983. Widest Pair of Indices With Equal Range Sum + * https://leetcode.com/problems/widest-pair-of-indices-with-equal-range-sum/ + * Difficulty: Medium + * + * You are given two 0-indexed binary arrays nums1 and nums2. Find the widest pair of indices (i, j) + * such that i <= j and nums1[i] + nums1[i+1] + ... + nums1[j] == nums2[i] + nums2[i+1] + ... + + * nums2[j]. + * + * The widest pair of indices is the pair with the largest distance between i and j. The distance + * between a pair of indices is defined as j - i + 1. + * + * Return the distance of the widest pair of indices. If no pair of indices meets the conditions, + * return 0. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var widestPairOfIndices = function(nums1, nums2) { + const n = nums1.length; + const map = new Map(); + map.set(0, -1); + + let prefixDiff = 0; + let result = 0; + + for (let i = 0; i < n; i++) { + prefixDiff += nums1[i] - nums2[i]; + + if (map.has(prefixDiff)) { + const distance = i - map.get(prefixDiff); + result = Math.max(result, distance); + } else { + map.set(prefixDiff, i); + } + } + + return result; +}; diff --git a/solutions/1989-maximum-number-of-people-that-can-be-caught-in-tag.js b/solutions/1989-maximum-number-of-people-that-can-be-caught-in-tag.js new file mode 100644 index 00000000..badcb590 --- /dev/null +++ b/solutions/1989-maximum-number-of-people-that-can-be-caught-in-tag.js @@ -0,0 +1,49 @@ +/** + * 1989. Maximum Number of People That Can Be Caught in Tag + * https://leetcode.com/problems/maximum-number-of-people-that-can-be-caught-in-tag/ + * Difficulty: Medium + * + * You are playing a game of tag with your friends. In tag, people are divided into two + * teams: people who are "it", and people who are not "it". The people who are "it" want + * to catch as many people as possible who are not "it". + * + * You are given a 0-indexed integer array team containing only zeros (denoting people who + * are not "it") and ones (denoting people who are "it"), and an integer dist. A person who + * is "it" at index i can catch any one person whose index is in the range [i - dist, i + dist] + * (inclusive) and is not "it". + * + * Return the maximum number of people that the people who are "it" can catch. + */ + +/** + * @param {number[]} team + * @param {number} dist + * @return {number} + */ +var catchMaximumAmountofPeople = function(team, dist) { + const catchers = []; + const targets = []; + + for (let i = 0; i < team.length; i++) { + if (team[i] === 1) { + catchers.push(i); + } else { + targets.push(i); + } + } + + let result = 0; + let targetIndex = 0; + for (const catcherPos of catchers) { + while (targetIndex < targets.length && targets[targetIndex] < catcherPos - dist) { + targetIndex++; + } + + if (targetIndex < targets.length && targets[targetIndex] <= catcherPos + dist) { + result++; + targetIndex++; + } + } + + return result; +}; diff --git a/solutions/1999-smallest-greater-multiple-made-of-two-digits.js b/solutions/1999-smallest-greater-multiple-made-of-two-digits.js new file mode 100644 index 00000000..4e4f8ce2 --- /dev/null +++ b/solutions/1999-smallest-greater-multiple-made-of-two-digits.js @@ -0,0 +1,44 @@ +/** + * 1999. Smallest Greater Multiple Made of Two Digits + * https://leetcode.com/problems/smallest-greater-multiple-made-of-two-digits/ + * Difficulty: Medium + * + * Given three integers, k, digit1, and digit2, you want to find the smallest integer that is: + * - Larger than k, + * - A multiple of k, and + * - Comprised of only the digits digit1 and/or digit2. + * + * Return the smallest such integer. If no such integer exists or the integer exceeds the limit + * of a signed 32-bit integer (231 - 1), return -1. + */ + +/** + * @param {number} k + * @param {number} digit1 + * @param {number} digit2 + * @return {number} + */ +var findInteger = function(k, digit1, digit2) { + const minDigit = Math.min(digit1, digit2); + const maxDigit = Math.max(digit1, digit2); + const queue = minDigit !== maxDigit ? [minDigit, maxDigit] : [minDigit]; + + while (queue.length > 0) { + const current = queue.shift(); + + if (current === 0 || current > 2147483647) { + continue; + } + + if (current > k && current % k === 0) { + return current; + } + + queue.push(current * 10 + minDigit); + if (minDigit !== maxDigit) { + queue.push(current * 10 + maxDigit); + } + } + + return -1; +}; diff --git a/solutions/2005-subtree-removal-game-with-fibonacci-tree.js b/solutions/2005-subtree-removal-game-with-fibonacci-tree.js new file mode 100644 index 00000000..30e974e4 --- /dev/null +++ b/solutions/2005-subtree-removal-game-with-fibonacci-tree.js @@ -0,0 +1,29 @@ +/** + * 2005. Subtree Removal Game with Fibonacci Tree + * https://leetcode.com/problems/subtree-removal-game-with-fibonacci-tree/ + * Difficulty: Hard + * + * A Fibonacci tree is a binary tree created using the order function order(n): + * - order(0) is the empty tree. + * - order(1) is a binary tree with only one node. + * - order(n) is a binary tree that consists of a root node with the left subtree as order(n - 2) + * and the right subtree as order(n - 1). + * + * Alice and Bob are playing a game with a Fibonacci tree with Alice staring first. On each turn, + * a player selects a node and removes that node and its subtree. The player that is forced to + * delete root loses. + * + * Given the integer n, return true if Alice wins the game or false if Bob wins, assuming both + * players play optimally. + * + * A subtree of a binary tree tree is a tree that consists of a node in tree and all of this + * node's descendants. The tree tree could also be considered as a subtree of itself. + */ + +/** + * @param {number} n + * @return {boolean} + */ +var findGameWinner = function(n) { + return n % 6 !== 1; +}; diff --git a/solutions/2015-average-height-of-buildings-in-each-segment.js b/solutions/2015-average-height-of-buildings-in-each-segment.js new file mode 100644 index 00000000..d1ec62c8 --- /dev/null +++ b/solutions/2015-average-height-of-buildings-in-each-segment.js @@ -0,0 +1,69 @@ +/** + * 2015. Average Height of Buildings in Each Segment + * https://leetcode.com/problems/average-height-of-buildings-in-each-segment/ + * Difficulty: Medium + * + * A perfectly straight street is represented by a number line. The street has building(s) on + * it and is represented by a 2D integer array buildings, where buildings[i] = [starti, endi, + * heighti]. This means that there is a building with heighti in the half-closed + * segment [starti, endi). + * + * You want to describe the heights of the buildings on the street with the minimum number of + * non-overlapping segments. The street can be represented by the 2D integer array street + * where street[j] = [leftj, rightj, averagej] describes a half-closed segment [leftj, rightj) + * of the road where the average heights of the buildings in the segment is averagej. + * + * - For example, if buildings = [[1,5,2],[3,10,4]], the street could be represented by + * street = [[1,3,2],[3,5,3],[5,10,4]] because: + * - From 1 to 3, there is only the first building with an average height of 2 / 1 = 2. + * - From 3 to 5, both the first and the second building are there with an average height + * of (2+4) / 2 = 3. + * - From 5 to 10, there is only the second building with an average height of 4 / 1 = 4. + * + * Given buildings, return the 2D integer array street as described above (excluding any areas + * of the street where there are no buldings). You may return the array in any order. + * + * The average of n elements is the sum of the n elements divided (integer division) by n. + * + * A half-closed segment [a, b) is the section of the number line between points a and b including + * point a and not including point b. + */ + +/** + * @param {number[][]} buildings + * @return {number[][]} + */ +var averageHeightOfBuildings = function(buildings) { + const events = []; + + for (const [start, end, height] of buildings) { + events.push([start, height, 1]); + events.push([end, -height, -1]); + } + + events.sort((a, b) => a[0] - b[0] || a[2] - b[2]); + + const result = []; + let currentSum = 0; + let currentCount = 0; + let prevPos = -1; + + for (const [pos, height, delta] of events) { + if (currentCount > 0 && pos > prevPos) { + const avgHeight = Math.floor(currentSum / currentCount); + + if (result.length > 0 && result[result.length - 1][1] === prevPos + && result[result.length - 1][2] === avgHeight) { + result[result.length - 1][1] = pos; + } else { + result.push([prevPos, pos, avgHeight]); + } + } + + currentSum += height; + currentCount += delta; + prevPos = pos; + } + + return result; +}; diff --git a/solutions/2021-brightest-position-on-street.js b/solutions/2021-brightest-position-on-street.js new file mode 100644 index 00000000..1475effb --- /dev/null +++ b/solutions/2021-brightest-position-on-street.js @@ -0,0 +1,46 @@ +/** + * 2021. Brightest Position on Street + * https://leetcode.com/problems/brightest-position-on-street/ + * Difficulty: Medium + * + * A perfectly straight street is represented by a number line. The street has street lamp(s) + * on it and is represented by a 2D integer array lights. Each lights[i] = [positioni, rangei] + * indicates that there is a street lamp at position positioni that lights up the area from + * [positioni - rangei, positioni + rangei] (inclusive). + * + * The brightness of a position p is defined as the number of street lamp that light up the + * position p. + * + * Given lights, return the brightest position on the street. If there are multiple brightest + * positions, return the smallest one. + */ + +/** + * @param {number[][]} lights + * @return {number} + */ +var brightestPosition = function(lights) { + const events = []; + + for (const [position, range] of lights) { + events.push([position - range, 1]); + events.push([position + range + 1, -1]); + } + + events.sort((a, b) => a[0] - b[0] || a[1] - b[1]); + + let maxBrightness = 0; + let result = 0; + let currentBrightness = 0; + + for (const [position, delta] of events) { + currentBrightness += delta; + + if (currentBrightness > maxBrightness) { + maxBrightness = currentBrightness; + result = position; + } + } + + return result; +}; diff --git a/solutions/2031-count-subarrays-with-more-ones-than-zeros.js b/solutions/2031-count-subarrays-with-more-ones-than-zeros.js new file mode 100644 index 00000000..3e6ea1ab --- /dev/null +++ b/solutions/2031-count-subarrays-with-more-ones-than-zeros.js @@ -0,0 +1,48 @@ +/** + * 2031. Count Subarrays With More Ones Than Zeros + * https://leetcode.com/problems/count-subarrays-with-more-ones-than-zeros/ + * Difficulty: Medium + * + * You are given a binary array nums containing only the integers 0 and 1. Return the number + * of subarrays in nums that have more 1's than 0's. Since the answer may be very large, + * return it modulo 109 + 7. + * + * A subarray is a contiguous sequence of elements within an array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var subarraysWithMoreZerosThanOnes = function(nums) { + const MOD = 1e9 + 7; + const dp = [0, 0]; + const mp = new Map(); + let sum = 0; + let answer = 0; + + mp.set(0, 1); + + for (const num of nums) { + const dpPrev = [...dp]; + + if (num === 1) { + sum++; + } else { + sum--; + } + + dp[0] = mp.get(sum) || 0; + + if (num === 1) { + dp[1] = (dpPrev[0] + dpPrev[1] + 1) % MOD; + } else { + dp[1] = (dpPrev[1] - dp[0] + MOD) % MOD; + } + + mp.set(sum, (mp.get(sum) || 0) + 1); + answer = (answer + dp[1]) % MOD; + } + + return answer; +}; diff --git a/solutions/2034-stock-price-fluctuation.js b/solutions/2034-stock-price-fluctuation.js new file mode 100644 index 00000000..ad4050da --- /dev/null +++ b/solutions/2034-stock-price-fluctuation.js @@ -0,0 +1,82 @@ +/** + * 2034. Stock Price Fluctuation + * https://leetcode.com/problems/stock-price-fluctuation/ + * Difficulty: Medium + * + * You are given a stream of records about a particular stock. Each record contains a timestamp + * and the corresponding price of the stock at that timestamp. + * + * Unfortunately due to the volatile nature of the stock market, the records do not come in order. + * Even worse, some records may be incorrect. Another record with the same timestamp may appear + * later in the stream correcting the price of the previous wrong record. + * + * Design an algorithm that: + * - Updates the price of the stock at a particular timestamp, correcting the price from any + * previous records at the timestamp. + * - Finds the latest price of the stock based on the current records. The latest price is the + * price at the latest timestamp recorded. + * - Finds the maximum price the stock has been based on the current records. + * - Finds the minimum price the stock has been based on the current records. + * + * Implement the StockPrice class: + * - StockPrice() Initializes the object with no price records. + * - void update(int timestamp, int price) Updates the price of the stock at the given timestamp. + * - int current() Returns the latest price of the stock. + * - int maximum() Returns the maximum price of the stock. + * - int minimum() Returns the minimum price of the stock. + */ + +var StockPrice = function() { + this.timestamps = new Map(); + this.highestTimestamp = 0; + this.minHeap = new PriorityQueue((a, b) => a[0] - b[0]); + this.maxHeap = new PriorityQueue((a, b) => b[0] - a[0]); +}; + +/** + * @param {number} timestamp + * @param {number} price + * @return {void} + */ +StockPrice.prototype.update = function(timestamp, price) { + this.timestamps.set(timestamp, price); + this.highestTimestamp = Math.max(this.highestTimestamp, timestamp); + + this.minHeap.enqueue([price, timestamp]); + this.maxHeap.enqueue([price, timestamp]); +}; + +/** + * @return {number} + */ +StockPrice.prototype.current = function() { + return this.timestamps.get(this.highestTimestamp); +}; + +/** + * @return {number} + */ +StockPrice.prototype.maximum = function() { + let [currPrice, timestamp] = this.maxHeap.dequeue(); + + while (currPrice !== this.timestamps.get(timestamp)) { + [currPrice, timestamp] = this.maxHeap.dequeue(); + } + + this.maxHeap.enqueue([currPrice, timestamp]); + return currPrice; +}; + +/** + * @return {number} + */ +StockPrice.prototype.minimum = function() { + let [currPrice, timestamp] = this.minHeap.dequeue(); + + while (currPrice !== this.timestamps.get(timestamp)) { + [currPrice, timestamp] = this.minHeap.dequeue(); + } + + this.minHeap.enqueue([currPrice, timestamp]); + return currPrice; +}; diff --git a/solutions/2036-maximum-alternating-subarray-sum.js b/solutions/2036-maximum-alternating-subarray-sum.js new file mode 100644 index 00000000..9d502e5d --- /dev/null +++ b/solutions/2036-maximum-alternating-subarray-sum.js @@ -0,0 +1,35 @@ +/** + * 2036. Maximum Alternating Subarray Sum + * https://leetcode.com/problems/maximum-alternating-subarray-sum/ + * Difficulty: Medium + * + * A subarray of a 0-indexed integer array is a contiguous non-empty sequence of elements + * within an array. + * + * The alternating subarray sum of a subarray that ranges from index i to j (inclusive, + * 0 <= i <= j < nums.length) is nums[i] - nums[i+1] + nums[i+2] - ... +/- nums[j]. + * + * Given a 0-indexed integer array nums, return the maximum alternating subarray sum of + * any subarray of nums. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maximumAlternatingSubarraySum = function(nums) { + let result = -Infinity; + let positive = -Infinity; + let negative = -Infinity; + + for (const num of nums) { + const newPositive = Math.max(negative + num, num); + const newNegative = positive - num; + + positive = newPositive; + negative = newNegative; + result = Math.max(result, positive, negative); + } + + return result; +}; diff --git a/solutions/2046-sort-linked-list-already-sorted-using-absolute-values.js b/solutions/2046-sort-linked-list-already-sorted-using-absolute-values.js new file mode 100644 index 00000000..a27e2779 --- /dev/null +++ b/solutions/2046-sort-linked-list-already-sorted-using-absolute-values.js @@ -0,0 +1,42 @@ +/** + * 2046. Sort Linked List Already Sorted Using Absolute Values + * https://leetcode.com/problems/sort-linked-list-already-sorted-using-absolute-values/ + * Difficulty: Medium + * + * Given the head of a singly linked list that is sorted in non-decreasing order using the + * absolute values of its nodes, return the list sorted in non-decreasing order using the + * actual values of its nodes. + */ + +/** + * 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} + */ +var sortLinkedList = function(head) { + if (!head || !head.next) return head; + + let current = head.next; + let prev = head; + + while (current) { + if (current.val < 0) { + const next = current.next; + prev.next = next; + current.next = head; + head = current; + current = next; + } else { + prev = current; + current = current.next; + } + } + + return head; +}; diff --git a/solutions/2052-minimum-cost-to-separate-sentence-into-rows.js b/solutions/2052-minimum-cost-to-separate-sentence-into-rows.js new file mode 100644 index 00000000..492f72e0 --- /dev/null +++ b/solutions/2052-minimum-cost-to-separate-sentence-into-rows.js @@ -0,0 +1,61 @@ +/** + * 2052. Minimum Cost to Separate Sentence Into Rows + * https://leetcode.com/problems/minimum-cost-to-separate-sentence-into-rows/ + * Difficulty: Medium + * + * You are given a string sentence containing words separated by spaces, and an integer k. + * Your task is to separate sentence into rows where the number of characters in each row + * is at most k. You may assume that sentence does not begin or end with a space, and the + * words in sentence are separated by a single space. + * + * You can split sentence into rows by inserting line breaks between words in sentence. + * A word cannot be split between two rows. Each word must be used exactly once, and the + * word order cannot be rearranged. Adjacent words in a row should be separated by a single + * space, and rows should not begin or end with spaces. + * + * The cost of a row with length n is (k - n)2, and the total cost is the sum of the costs + * for all rows except the last one. + * - For example if sentence = "i love leetcode" and k = 12: + * - Separating sentence into "i", "love", and "leetcode" has a cost + * of (12 - 1)2 + (12 - 4)2 = 185. + * - Separating sentence into "i love", and "leetcode" has a cost of (12 - 6)2 = 36. + * - Separating sentence into "i", and "love leetcode" is not possible because the + * length of "love leetcode" is greater than k. + * + * Return the minimum possible total cost of separating sentence into rows. + */ + +/** + * @param {string} sentence + * @param {number} k + * @return {number} + */ +var minimumCost = function(sentence, k) { + const words = sentence.split(' '); + const n = words.length; + const map = new Map(); + + return dp(0); + + function dp(wordIndex) { + if (wordIndex === n) return 0; + if (map.has(wordIndex)) return map.get(wordIndex); + + let currentLength = 0; + let minCost = Infinity; + + for (let i = wordIndex; i < n; i++) { + if (i > wordIndex) currentLength += 1; + currentLength += words[i].length; + + if (currentLength > k) break; + + const remainingCost = dp(i + 1); + const currentCost = i === n - 1 ? 0 : (k - currentLength) ** 2; + minCost = Math.min(minCost, currentCost + remainingCost); + } + + map.set(wordIndex, minCost); + return minCost; + } +}; diff --git a/solutions/2054-two-best-non-overlapping-events.js b/solutions/2054-two-best-non-overlapping-events.js new file mode 100644 index 00000000..7cc0083d --- /dev/null +++ b/solutions/2054-two-best-non-overlapping-events.js @@ -0,0 +1,58 @@ +/** + * 2054. Two Best Non-Overlapping Events + * https://leetcode.com/problems/two-best-non-overlapping-events/ + * Difficulty: Medium + * + * You are given a 0-indexed 2D integer array of events where + * events[i] = [startTimei, endTimei, valuei]. The ith event starts at + * startTimei and ends at endTimei, and if you attend this event, you will + * receive a value of valuei. You can choose at most two non-overlapping + * events to attend such that the sum of their values is maximized. + * + * Return this maximum sum. + * + * Note that the start time and end time is inclusive: that is, you cannot + * attend two events where one of them starts and the other ends at the + * same time. More specifically, if you attend an event with end time t, + * the next event must start at or after t + 1. + */ + +/** + * @param {number[][]} events + * @return {number} + */ +var maxTwoEvents = function(events) { + events.sort((a, b) => a[1] - b[1]); + + const maxValueUpTo = new Array(events.length); + maxValueUpTo[0] = events[0][2]; + + for (let i = 1; i < events.length; i++) { + maxValueUpTo[i] = Math.max(maxValueUpTo[i - 1], events[i][2]); + } + + let result = 0; + for (let i = 0; i < events.length; i++) { + const [start, end, value] = events[i]; + result = Math.max(result, value); + + let left = 0; + let right = i - 1; + let bestIndex = -1; + while (left <= right) { + const mid = Math.floor((left + right) / 2); + if (events[mid][1] < start) { + bestIndex = mid; + left = mid + 1; + } else { + right = mid - 1; + } + } + + if (bestIndex !== -1) { + result = Math.max(result, value + maxValueUpTo[bestIndex]); + } + } + + return result; +}; diff --git a/solutions/2061-number-of-spaces-cleaning-robot-cleaned.js b/solutions/2061-number-of-spaces-cleaning-robot-cleaned.js new file mode 100644 index 00000000..5a4871b3 --- /dev/null +++ b/solutions/2061-number-of-spaces-cleaning-robot-cleaned.js @@ -0,0 +1,52 @@ +/** + * 2061. Number of Spaces Cleaning Robot Cleaned + * https://leetcode.com/problems/number-of-spaces-cleaning-robot-cleaned/ + * Difficulty: Medium + * + * A room is represented by a 0-indexed 2D binary matrix room where a 0 represents an empty + * space and a 1 represents a space with an object. The top left corner of the room will be + * empty in all test cases. + * + * A cleaning robot starts at the top left corner of the room and is facing right. The robot + * will continue heading straight until it reaches the edge of the room or it hits an object, + * after which it will turn 90 degrees clockwise and repeat this process. The starting space + * and all spaces that the robot visits are cleaned by it. + * + * Return the number of clean spaces in the room if the robot runs indefinitely. + */ + +/** + * @param {number[][]} room + * @return {number} + */ +var numberOfCleanRooms = function(room) { + const rows = room.length; + const cols = room[0].length; + const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]; + const visited = new Set(); + const states = new Set(); + let row = 0; + let col = 0; + let direction = 0; + + while (true) { + const state = `${row},${col},${direction}`; + if (states.has(state)) break; + + states.add(state); + visited.add(`${row},${col}`); + + const nextRow = row + directions[direction][0]; + const nextCol = col + directions[direction][1]; + + if (nextRow < 0 || nextRow >= rows || nextCol < 0 + || nextCol >= cols || room[nextRow][nextCol] === 1) { + direction = (direction + 1) % 4; + } else { + row = nextRow; + col = nextCol; + } + } + + return visited.size; +}; diff --git a/solutions/2067-number-of-equal-count-substrings.js b/solutions/2067-number-of-equal-count-substrings.js new file mode 100644 index 00000000..6a55478c --- /dev/null +++ b/solutions/2067-number-of-equal-count-substrings.js @@ -0,0 +1,63 @@ +/** + * 2067. Number of Equal Count Substrings + * https://leetcode.com/problems/number-of-equal-count-substrings/ + * Difficulty: Medium + * + * You are given a 0-indexed string s consisting of only lowercase English letters, and an + * integer count. A substring of s is said to be an equal count substring if, for each + * unique letter in the substring, it appears exactly count times in the substring. + * + * Return the number of equal count substrings in s. + * + * A substring is a contiguous non-empty sequence of characters within a string. + */ + +/** + * @param {string} s + * @param {number} count + * @return {number} + */ +var equalCountSubstrings = function(s, count) { + const n = s.length; + let result = 0; + + for (let uniqueChars = 1; uniqueChars <= 26; uniqueChars++) { + const targetLength = uniqueChars * count; + if (targetLength > n) break; + + const charCount = new Map(); + let validChars = 0; + + for (let right = 0; right < n; right++) { + const rightChar = s[right]; + charCount.set(rightChar, (charCount.get(rightChar) || 0) + 1); + + if (charCount.get(rightChar) === count) { + validChars++; + } else if (charCount.get(rightChar) === count + 1) { + validChars--; + } + + if (right >= targetLength) { + const leftChar = s[right - targetLength]; + if (charCount.get(leftChar) === count) { + validChars--; + } else if (charCount.get(leftChar) === count + 1) { + validChars++; + } + + charCount.set(leftChar, charCount.get(leftChar) - 1); + if (charCount.get(leftChar) === 0) { + charCount.delete(leftChar); + } + } + + if (right >= targetLength - 1 && validChars === uniqueChars + && charCount.size === uniqueChars) { + result++; + } + } + } + + return result; +}; diff --git a/solutions/2073-time-needed-to-buy-tickets.js b/solutions/2073-time-needed-to-buy-tickets.js new file mode 100644 index 00000000..5feb01ff --- /dev/null +++ b/solutions/2073-time-needed-to-buy-tickets.js @@ -0,0 +1,39 @@ +/** + * 2073. Time Needed to Buy Tickets + * https://leetcode.com/problems/time-needed-to-buy-tickets/ + * Difficulty: Easy + * + * There are n people in a line queuing to buy tickets, where the 0th person is at the front + * of the line and the (n - 1)th person is at the back of the line. + * + * You are given a 0-indexed integer array tickets of length n where the number of tickets + * that the ith person would like to buy is tickets[i]. + * + * Each person takes exactly 1 second to buy a ticket. A person can only buy 1 ticket at a + * time and has to go back to the end of the line (which happens instantaneously) in order + * to buy more tickets. If a person does not have any tickets left to buy, the person will + * leave the line. + * + * Return the time taken for the person initially at position k (0-indexed) to finish buying + * tickets. + */ + +/** + * @param {number[]} tickets + * @param {number} k + * @return {number} + */ +var timeRequiredToBuy = function(tickets, k) { + const target = tickets[k]; + let result = 0; + + for (let i = 0; i < tickets.length; i++) { + if (i <= k) { + result += Math.min(tickets[i], target); + } else { + result += Math.min(tickets[i], target - 1); + } + } + + return result; +}; diff --git a/solutions/2077-paths-in-maze-that-lead-to-same-room.js b/solutions/2077-paths-in-maze-that-lead-to-same-room.js new file mode 100644 index 00000000..a4d069d2 --- /dev/null +++ b/solutions/2077-paths-in-maze-that-lead-to-same-room.js @@ -0,0 +1,53 @@ +/** + * 2077. Paths in Maze That Lead to Same Room + * https://leetcode.com/problems/paths-in-maze-that-lead-to-same-room/ + * Difficulty: Medium + * + * A maze consists of n rooms numbered from 1 to n, and some rooms are connected by corridors. + * You are given a 2D integer array corridors where corridors[i] = [room1i, room2i] indicates + * that there is a corridor connecting room1i and room2i, allowing a person in the maze to go + * from room1i to room2i and vice versa. + * + * The designer of the maze wants to know how confusing the maze is. The confusion score of + * the maze is the number of different cycles of length 3. + * - For example, 1 → 2 → 3 → 1 is a cycle of length 3, but 1 → 2 → 3 → 4 and + * 1 → 2 → 3 → 2 → 1 are not. + * + * Two cycles are considered to be different if one or more of the rooms visited in the first + * cycle is not in the second cycle. + * + * Return the confusion score of the maze. + */ + +/** + * @param {number} n + * @param {number[][]} corridors + * @return {number} + */ +var numberOfPaths = function(n, corridors) { + const graph = Array.from({ length: n + 1 }, () => new Set()); + + for (const [room1, room2] of corridors) { + graph[room1].add(room2); + graph[room2].add(room1); + } + + let cycles = 0; + + for (let i = 1; i <= n; i++) { + const neighbors = Array.from(graph[i]); + + for (let j = 0; j < neighbors.length; j++) { + for (let k = j + 1; k < neighbors.length; k++) { + const neighbor1 = neighbors[j]; + const neighbor2 = neighbors[k]; + + if (neighbor1 > i && neighbor2 > i && graph[neighbor1].has(neighbor2)) { + cycles++; + } + } + } + } + + return cycles; +}; diff --git a/solutions/2083-substrings-that-begin-and-end-with-the-same-letter.js b/solutions/2083-substrings-that-begin-and-end-with-the-same-letter.js new file mode 100644 index 00000000..1a80d8ba --- /dev/null +++ b/solutions/2083-substrings-that-begin-and-end-with-the-same-letter.js @@ -0,0 +1,30 @@ +/** + * 2083. Substrings That Begin and End With the Same Letter + * https://leetcode.com/problems/substrings-that-begin-and-end-with-the-same-letter/ + * Difficulty: Medium + * + * You are given a 0-indexed string s consisting of only lowercase English letters. + * Return the number of substrings in s that begin and end with the same character. + * + * A substring is a contiguous non-empty sequence of characters within a string. + */ + +/** + * @param {string} s + * @return {number} + */ +var numberOfSubstrings = function(s) { + const map = new Map(); + + for (const char of s) { + map.set(char, (map.get(char) || 0) + 1); + } + + let result = 0; + + for (const count of map.values()) { + result += (count * (count + 1)) / 2; + } + + return result; +}; diff --git a/solutions/2093-minimum-cost-to-reach-city-with-discounts.js b/solutions/2093-minimum-cost-to-reach-city-with-discounts.js new file mode 100644 index 00000000..79047563 --- /dev/null +++ b/solutions/2093-minimum-cost-to-reach-city-with-discounts.js @@ -0,0 +1,59 @@ +/** + * 2093. Minimum Cost to Reach City With Discounts + * https://leetcode.com/problems/minimum-cost-to-reach-city-with-discounts/ + * Difficulty: Medium + * + * A series of highways connect n cities numbered from 0 to n - 1. You are given a 2D + * integer array highways where highways[i] = [city1i, city2i, tolli] indicates that + * there is a highway that connects city1i and city2i, allowing a car to go from city1i + * to city2i and vice versa for a cost of tolli. + * + * You are also given an integer discounts which represents the number of discounts you have. + * You can use a discount to travel across the ith highway for a cost of tolli / 2 (integer + * division). Each discount may only be used once, and you can only use at most one discount + * per highway. + * + * Return the minimum total cost to go from city 0 to city n - 1, or -1 if it is not possible + * to go from city 0 to city n - 1. + */ + +/** + * @param {number} n + * @param {number[][]} highways + * @param {number} discounts + * @return {number} + */ +var minimumCost = function(n, highways, discounts) { + const graph = Array.from({ length: n }, () => []); + + for (const [a, b, c] of highways) { + graph[a].push([b, c]); + graph[b].push([a, c]); + } + + const pq = new PriorityQueue((a, b) => a[0] - b[0]); + pq.enqueue([0, 0, 0]); + const visited = Array.from({ length: n }, () => new Array(discounts + 1).fill(Infinity)); + visited[0][0] = 0; + + while (!pq.isEmpty()) { + const [cost, city, discountUsed] = pq.dequeue(); + + if (city === n - 1) return cost; + + for (const [nextCity, weight] of graph[city]) { + if (cost + weight < visited[nextCity][discountUsed]) { + pq.enqueue([cost + weight, nextCity, discountUsed]); + visited[nextCity][discountUsed] = cost + weight; + } + + if (discountUsed < discounts + && cost + Math.floor(weight / 2) < visited[nextCity][discountUsed + 1]) { + pq.enqueue([cost + Math.floor(weight / 2), nextCity, discountUsed + 1]); + visited[nextCity][discountUsed + 1] = cost + Math.floor(weight / 2); + } + } + } + + return -1; +}; diff --git a/solutions/2098-subsequence-of-size-k-with-the-largest-even-sum.js b/solutions/2098-subsequence-of-size-k-with-the-largest-even-sum.js new file mode 100644 index 00000000..ce24852f --- /dev/null +++ b/solutions/2098-subsequence-of-size-k-with-the-largest-even-sum.js @@ -0,0 +1,39 @@ +/** + * 2098. Subsequence of Size K With the Largest Even Sum + * https://leetcode.com/problems/subsequence-of-size-k-with-the-largest-even-sum/ + * Difficulty: Medium + * + * You are given an integer array nums and an integer k. Find the largest even sum of any + * subsequence of nums that has a length of k. + * + * Return this sum, or -1 if such a sum does not exist. + * + * A subsequence is an array that can be derived from another array by deleting some or no + * elements without changing the order of the remaining elements. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var largestEvenSum = function(nums, k) { + const evenNums = nums.filter(num => num % 2 === 0).sort((a, b) => b - a); + const oddNums = nums.filter(num => num % 2 === 1).sort((a, b) => b - a); + let result = -1; + + for (let evenCount = 0; evenCount <= Math.min(k, evenNums.length); evenCount++) { + const oddCount = k - evenCount; + if (oddCount > oddNums.length || oddCount % 2 === 1) continue; + let currentSum = 0; + for (let i = 0; i < evenCount; i++) { + currentSum += evenNums[i]; + } + for (let i = 0; i < oddCount; i++) { + currentSum += oddNums[i]; + } + result = Math.max(result, currentSum); + } + + return result; +}; diff --git a/solutions/2102-sequentially-ordinal-rank-tracker.js b/solutions/2102-sequentially-ordinal-rank-tracker.js new file mode 100644 index 00000000..3f83c39c --- /dev/null +++ b/solutions/2102-sequentially-ordinal-rank-tracker.js @@ -0,0 +1,53 @@ +/** + * 2102. Sequentially Ordinal Rank Tracker + * https://leetcode.com/problems/sequentially-ordinal-rank-tracker/ + * Difficulty: Hard + * + * A scenic location is represented by its name and attractiveness score, where name is a unique + * string among all locations and score is an integer. Locations can be ranked from the best to + * the worst. The higher the score, the better the location. If the scores of two locations are + * equal, then the location with the lexicographically smaller name is better. + * + * You are building a system that tracks the ranking of locations with the system initially + * starting with no locations. It supports: + * - Adding scenic locations, one at a time. + * - Querying the ith best location of all locations already added, where i is the number of + * times the system has been queried (including the current query). + * - For example, when the system is queried for the 4th time, it returns the 4th best location + * of all locations already added. + * + * Note that the test data are generated so that at any time, the number of queries does not + * exceed the number of locations added to the system. + * + * Implement the SORTracker class: + * - SORTracker() Initializes the tracker system. + * - void add(string name, int score) Adds a scenic location with name and score to the system. + * - string get() Queries and returns the ith best location, where i is the number of times this + * method has been invoked (including this invocation). + */ + +var SORTracker = function() { + this.count = 0; + this.minHeap = new PriorityQueue((a, b) => a[0] - b[0] || b[1].localeCompare(a[1])); + this.maxHeap = new PriorityQueue((a, b) => b[0] - a[0] || a[1].localeCompare(b[1])); +}; + +/** + * @param {string} name + * @param {number} score + * @return {void} + */ +SORTracker.prototype.add = function(name, score) { + this.minHeap.enqueue([score, name]); + this.maxHeap.enqueue(this.minHeap.dequeue()); +}; + +/** + * @return {string} + */ +SORTracker.prototype.get = function() { + const maxElement = this.maxHeap.dequeue(); + this.minHeap.enqueue(maxElement); + + return maxElement[1]; +}; diff --git a/solutions/2107-number-of-unique-flavors-after-sharing-k-candies.js b/solutions/2107-number-of-unique-flavors-after-sharing-k-candies.js new file mode 100644 index 00000000..d7bd172f --- /dev/null +++ b/solutions/2107-number-of-unique-flavors-after-sharing-k-candies.js @@ -0,0 +1,62 @@ +/** + * 2107. Number of Unique Flavors After Sharing K Candies + * https://leetcode.com/problems/number-of-unique-flavors-after-sharing-k-candies/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array candies, where candies[i] represents the flavor + * of the ith candy. Your mom wants you to share these candies with your little sister by + * giving her k consecutive candies, but you want to keep as many flavors of candies as possible. + * + * Return the maximum number of unique flavors of candy you can keep after sharing with your sister. + */ + +/** + * @param {number[]} candies + * @param {number} k + * @return {number} + */ +var shareCandies = function(candies, k) { + if (k === 0) return new Set(candies).size; + if (k === candies.length) return 0; + + const totalFlavorCount = new Map(); + for (const candy of candies) { + totalFlavorCount.set(candy, (totalFlavorCount.get(candy) || 0) + 1); + } + + const windowFlavorCount = new Map(); + let uniqueRemainingFlavors = totalFlavorCount.size; + + for (let i = 0; i < k; i++) { + const candy = candies[i]; + const prevWindowCount = windowFlavorCount.get(candy) || 0; + windowFlavorCount.set(candy, prevWindowCount + 1); + + if (prevWindowCount + 1 === totalFlavorCount.get(candy)) { + uniqueRemainingFlavors--; + } + } + + let result = uniqueRemainingFlavors; + + for (let i = k; i < candies.length; i++) { + const addCandy = candies[i]; + const removeCandy = candies[i - k]; + + const prevAddCount = windowFlavorCount.get(addCandy) || 0; + windowFlavorCount.set(addCandy, prevAddCount + 1); + if (prevAddCount + 1 === totalFlavorCount.get(addCandy)) { + uniqueRemainingFlavors--; + } + + const prevRemoveCount = windowFlavorCount.get(removeCandy); + windowFlavorCount.set(removeCandy, prevRemoveCount - 1); + if (prevRemoveCount === totalFlavorCount.get(removeCandy)) { + uniqueRemainingFlavors++; + } + + result = Math.max(result, uniqueRemainingFlavors); + } + + return result; +}; diff --git a/solutions/2113-elements-in-array-after-removing-and-replacing-elements.js b/solutions/2113-elements-in-array-after-removing-and-replacing-elements.js new file mode 100644 index 00000000..6994fd4a --- /dev/null +++ b/solutions/2113-elements-in-array-after-removing-and-replacing-elements.js @@ -0,0 +1,41 @@ +/** + * 2113. Elements in Array After Removing and Replacing Elements + * https://leetcode.com/problems/elements-in-array-after-removing-and-replacing-elements/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums. Initially on minute 0, the array is unchanged. + * Every minute, the leftmost element in nums is removed until no elements remain. Then, every + * minute, one element is appended to the end of nums, in the order they were removed in, until + * the original array is restored. This process repeats indefinitely. + * - For example, the array [0,1,2] would change as follows: [0,1,2] → [1,2] → [2] → [] → [0] → + * [0,1] → [0,1,2] → [1,2] → [2] → [] → [0] → [0,1] → [0,1,2] → ... + * + * You are also given a 2D integer array queries of size n where queries[j] = [timej, indexj]. + * The answer to the jth query is: + * - nums[indexj] if indexj < nums.length at minute timej + * - -1 if indexj >= nums.length at minute timej + * + * Return an integer array ans of size n where ans[j] is the answer to the jth query. + */ + +/** + * @param {number[]} nums + * @param {number[][]} queries + * @return {number[]} + */ +var elementInNums = function(nums, queries) { + const n = nums.length; + const cycleLength = 2 * n; + + return queries.map(([time, index]) => { + const position = time % cycleLength; + + if (position < n) { + const currentLength = n - position; + return index < currentLength ? nums[position + index] : -1; + } else { + const currentLength = position - n; + return index < currentLength ? nums[index] : -1; + } + }); +}; diff --git a/solutions/2123-minimum-operations-to-remove-adjacent-ones-in-matrix.js b/solutions/2123-minimum-operations-to-remove-adjacent-ones-in-matrix.js new file mode 100644 index 00000000..2c72d6b0 --- /dev/null +++ b/solutions/2123-minimum-operations-to-remove-adjacent-ones-in-matrix.js @@ -0,0 +1,53 @@ +/** + * 2123. Minimum Operations to Remove Adjacent Ones in Matrix + * https://leetcode.com/problems/minimum-operations-to-remove-adjacent-ones-in-matrix/ + * Difficulty: Hard + * + * You are given a 0-indexed binary matrix grid. In one operation, you can flip any 1 in + * grid to be 0. + * + * A binary matrix is well-isolated if there is no 1 in the matrix that is 4-directionally + * connected (i.e., horizontal and vertical) to another 1. + * + * Return the minimum number of operations to make grid well-isolated. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var minimumOperations = function(grid) { + const m = grid.length; + const n = grid[0].length; + let count = 0; + const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]; + const match = Array.from({ length: m }, () => new Array(n).fill(-1)); + const visited = Array.from({ length: m }, () => new Array(n).fill(-1)); + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (grid[i][j] && match[i][j] === -1) { + visited[i][j] = i * n + j; + count += dfs(i, j, visited[i][j]); + } + } + } + + return count; + + function dfs(i, j, v) { + for (const [di, dj] of directions) { + const x = i + di; + const y = j + dj; + if (x >= 0 && x < m && y >= 0 && y < n && grid[x][y] && visited[x][y] !== v) { + visited[x][y] = v; + if (match[x][y] === -1 || dfs(Math.floor(match[x][y] / n), match[x][y] % n, v)) { + match[x][y] = i * n + j; + match[i][j] = x * n + y; + return 1; + } + } + } + return 0; + } +}; diff --git a/solutions/2128-remove-all-ones-with-row-and-column-flips.js b/solutions/2128-remove-all-ones-with-row-and-column-flips.js new file mode 100644 index 00000000..198ecbd2 --- /dev/null +++ b/solutions/2128-remove-all-ones-with-row-and-column-flips.js @@ -0,0 +1,43 @@ +/** + * 2128. Remove All Ones With Row and Column Flips + * https://leetcode.com/problems/remove-all-ones-with-row-and-column-flips/ + * Difficulty: Medium + * + * You are given an m x n binary matrix grid. + * + * In one operation, you can choose any row or column and flip each value in that row or + * column (i.e., changing all 0's to 1's, and all 1's to 0's). + * + * Return true if it is possible to remove all 1's from grid using any number of operations + * or false otherwise. + */ + +/** + * @param {number[][]} grid + * @return {boolean} + */ +var removeOnes = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const firstRow = grid[0]; + + for (let i = 1; i < rows; i++) { + let sameAsFirst = true; + let oppositeToFirst = true; + + for (let j = 0; j < cols; j++) { + if (grid[i][j] !== firstRow[j]) { + sameAsFirst = false; + } + if (grid[i][j] === firstRow[j]) { + oppositeToFirst = false; + } + } + + if (!sameAsFirst && !oppositeToFirst) { + return false; + } + } + + return true; +}; diff --git a/solutions/2137-pour-water-between-buckets-to-make-water-levels-equal.js b/solutions/2137-pour-water-between-buckets-to-make-water-levels-equal.js new file mode 100644 index 00000000..d75d4718 --- /dev/null +++ b/solutions/2137-pour-water-between-buckets-to-make-water-levels-equal.js @@ -0,0 +1,57 @@ +/** + * 2137. Pour Water Between Buckets to Make Water Levels Equal + * https://leetcode.com/problems/pour-water-between-buckets-to-make-water-levels-equal/ + * Difficulty: Medium + * + * You have n buckets each containing some gallons of water in it, represented by a 0-indexed + * integer array buckets, where the ith bucket contains buckets[i] gallons of water. You are + * also given an integer loss. + * + * You want to make the amount of water in each bucket equal. You can pour any amount of water + * from one bucket to another bucket (not necessarily an integer). However, every time you + * pour k gallons of water, you spill loss percent of k. + * + * Return the maximum amount of water in each bucket after making the amount of water equal. + * Answers within 10-5 of the actual answer will be accepted. + */ + +/** + * @param {number[]} buckets + * @param {number} loss + * @return {number} + */ +var equalizeWater = function(buckets, loss) { + const n = buckets.length; + const totalWater = buckets.reduce((sum, water) => sum + water, 0); + const retentionRate = (100 - loss) / 100; + + let left = 0; + let right = Math.max(...buckets); + + while (right - left > 1e-7) { + const mid = (left + right) / 2; + + if (canAchieveLevel(mid)) { + left = mid; + } else { + right = mid; + } + } + + return left; + + function canAchieveLevel(targetLevel) { + let surplus = 0; + let deficit = 0; + + for (const water of buckets) { + if (water > targetLevel) { + surplus += water - targetLevel; + } else { + deficit += targetLevel - water; + } + } + + return surplus * retentionRate >= deficit; + } +}; diff --git a/solutions/2143-choose-numbers-from-two-arrays-in-range.js b/solutions/2143-choose-numbers-from-two-arrays-in-range.js new file mode 100644 index 00000000..a56de83e --- /dev/null +++ b/solutions/2143-choose-numbers-from-two-arrays-in-range.js @@ -0,0 +1,57 @@ +/** + * 2143. Choose Numbers From Two Arrays in Range + * https://leetcode.com/problems/choose-numbers-from-two-arrays-in-range/ + * Difficulty: Hard + * + * You are given two 0-indexed integer arrays nums1 and nums2 of length n. + * + * A range [l, r] (inclusive) where 0 <= l <= r < n is balanced if: + * - For every i in the range [l, r], you pick either nums1[i] or nums2[i]. + * - The sum of the numbers you pick from nums1 equals to the sum of the numbers you pick from + * nums2 (the sum is considered to be 0 if you pick no numbers from an array). + * + * Two balanced ranges from [l1, r1] and [l2, r2] are considered to be different if at least + * one of the following is true: + * - l1 != l2 + * - r1 != r2 + * - nums1[i] is picked in the first range, and nums2[i] is picked in the second range or vice + * versa for at least one i. + * + * Return the number of different ranges that are balanced. Since the answer may be very large, + * return it modulo 109 + 7. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var countSubranges = function(nums1, nums2) { + const MOD = 1e9 + 7; + const n = nums1.length; + let dp = new Map(); + let result = 0; + + for (let i = 0; i < n; i++) { + const n1 = nums1[i]; + const n2 = nums2[i]; + const newDp = new Map(); + + newDp.set(n1, (newDp.get(n1) || 0) + 1); + newDp.set(-n2, (newDp.get(-n2) || 0) + 1); + + for (const [key, value] of dp) { + newDp.set(key + n1, (newDp.get(key + n1) || 0) + value); + newDp.set(key - n2, (newDp.get(key - n2) || 0) + value); + } + + for (const [key, value] of newDp) { + newDp.set(key, value % MOD); + } + + result = (result + (newDp.get(0) || 0)) % MOD; + dp = newDp; + } + + return result; +}; diff --git a/solutions/2146-k-highest-ranked-items-within-a-price-range.js b/solutions/2146-k-highest-ranked-items-within-a-price-range.js new file mode 100644 index 00000000..b0e9db12 --- /dev/null +++ b/solutions/2146-k-highest-ranked-items-within-a-price-range.js @@ -0,0 +1,79 @@ +/** + * 2146. K Highest Ranked Items Within a Price Range + * https://leetcode.com/problems/k-highest-ranked-items-within-a-price-range/ + * Difficulty: Medium + * + * You are given a 0-indexed 2D integer array grid of size m x n that represents a map of the + * items in a shop. The integers in the grid represent the following: + * - 0 represents a wall that you cannot pass through. + * - 1 represents an empty cell that you can freely move to and from. + * + * All other positive integers represent the price of an item in that cell. You may also freely + * move to and from these item cells. + * + * It takes 1 step to travel between adjacent grid cells. + * + * You are also given integer arrays pricing and start where pricing = [low, high] and + * start = [row, col] indicates that you start at the position (row, col) and are interested + * only in items with a price in the range of [low, high] (inclusive). You are further given + * an integer k. + * + * You are interested in the positions of the k highest-ranked items whose prices are within + * the given price range. The rank is determined by the first of these criteria that is different: + * 1. Distance, defined as the length of the shortest path from the start (shorter distance has + * a higher rank). + * 2. Price (lower price has a higher rank, but it must be in the price range). + * 3. The row number (smaller row number has a higher rank). + * 4. The column number (smaller column number has a higher rank). + * + * Return the k highest-ranked items within the price range sorted by their rank (highest to + * lowest). If there are fewer than k reachable items within the price range, return all of them. + */ + +/** + * @param {number[][]} grid + * @param {number[]} pricing + * @param {number[]} start + * @param {number} k + * @return {number[][]} + */ +var highestRankedKItems = function(grid, pricing, start, k) { + const [rows, cols] = [grid.length, grid[0].length]; + const [low, high] = pricing; + const [startRow, startCol] = start; + const directions = [[0, 1], [0, -1], [1, 0], [-1, 0]]; + const queue = [[startRow, startCol, 0]]; + const visited = new Set(); + visited.add(`${startRow},${startCol}`); + const validItems = []; + + while (queue.length > 0) { + const [row, col, distance] = queue.shift(); + const price = grid[row][col]; + + if (price >= low && price <= high) { + validItems.push([distance, price, row, col]); + } + + for (const [dr, dc] of directions) { + const newRow = row + dr; + const newCol = col + dc; + const key = `${newRow},${newCol}`; + + if (newRow >= 0 && newRow < rows && newCol >= 0 && newCol < cols + && grid[newRow][newCol] > 0 && !visited.has(key)) { + visited.add(key); + queue.push([newRow, newCol, distance + 1]); + } + } + } + + validItems.sort((a, b) => { + if (a[0] !== b[0]) return a[0] - b[0]; + if (a[1] !== b[1]) return a[1] - b[1]; + if (a[2] !== b[2]) return a[2] - b[2]; + return a[3] - b[3]; + }); + + return validItems.slice(0, k).map(item => [item[2], item[3]]); +}; diff --git a/solutions/2152-minimum-number-of-lines-to-cover-points.js b/solutions/2152-minimum-number-of-lines-to-cover-points.js new file mode 100644 index 00000000..a6d56b58 --- /dev/null +++ b/solutions/2152-minimum-number-of-lines-to-cover-points.js @@ -0,0 +1,77 @@ +/** + * 2152. Minimum Number of Lines to Cover Points + * https://leetcode.com/problems/minimum-number-of-lines-to-cover-points/ + * Difficulty: Medium + * + * You are given an array points where points[i] = [xi, yi] represents a point on an X-Y plane. + * + * Straight lines are going to be added to the X-Y plane, such that every point is covered by at + * least one line. + * + * Return the minimum number of straight lines needed to cover all the points. + */ + +/** + * @param {number[][]} points + * @return {number} + */ +var minimumLines = function(points) { + const n = points.length; + const linePoints = new Map(); + + for (let i = 0; i < n; i++) { + const [x1, y1] = points[i]; + for (let j = i + 1; j < n; j++) { + const [x2, y2] = points[j]; + let a; + let b; + + if (x1 === x2) { + a = x1; + b = Number.MAX_SAFE_INTEGER; + } else { + a = (y2 - y1) / (x2 - x1); + b = y1 - a * x1; + } + + const key = `${a},${b}`; + if (!linePoints.has(key)) { + linePoints.set(key, new Set()); + } + linePoints.get(key).add(`${x1},${y1}`); + linePoints.get(key).add(`${x2},${y2}`); + } + } + + const lines = []; + for (const [line, pointSet] of linePoints) { + if (pointSet.size > 2) { + lines.push(line); + } + } + + let answer = Math.ceil(n / 2); + const m = lines.length; + + for (let mask = 1; mask < (1 << m); mask++) { + let j = 0; + const lineCount = mask.toString(2).split('1').length - 1; + const currentPoints = new Set(); + let tempMask = mask; + + while (tempMask > 0) { + if (tempMask % 2) { + const line = lines[m - 1 - j]; + for (const point of linePoints.get(line)) { + currentPoints.add(point); + } + } + tempMask >>= 1; + j++; + } + + answer = Math.min(answer, lineCount + Math.ceil((n - currentPoints.size) / 2)); + } + + return answer; +}; diff --git a/solutions/2158-amount-of-new-area-painted-each-day.js b/solutions/2158-amount-of-new-area-painted-each-day.js new file mode 100644 index 00000000..056baa10 --- /dev/null +++ b/solutions/2158-amount-of-new-area-painted-each-day.js @@ -0,0 +1,65 @@ +/** + * 2158. Amount of New Area Painted Each Day + * https://leetcode.com/problems/amount-of-new-area-painted-each-day/ + * Difficulty: Hard + * + * There is a long and thin painting that can be represented by a number line. You are given + * a 0-indexed 2D integer array paint of length n, where paint[i] = [starti, endi]. This means + * that on the ith day you need to paint the area between starti and endi. + * + * Painting the same area multiple times will create an uneven painting so you only want to + * paint each area of the painting at most once. + * + * Return an integer array worklog of length n, where worklog[i] is the amount of new area that + * you painted on the ith day. + */ + +/** + * @param {number[][]} paint + * @return {number[]} + */ +var amountPainted = function(paint) { + const intervals = new Map(); + const result = []; + + for (const [start, end] of paint) { + let left = start; + let right = end; + let paintAmount = right - left; + + const keys = Array.from(intervals.keys()).sort((a, b) => a - b); + const toRemove = []; + let merged = false; + + for (const key of keys) { + const value = intervals.get(key); + + if (key > right || value < left) continue; + + if (!merged && key <= left && value >= left) { + left = Math.min(left, key); + right = Math.max(right, value); + paintAmount = Math.max(0, end - Math.max(start, value)); + toRemove.push(key); + merged = true; + } else if (key >= left && key < right) { + paintAmount -= Math.min(right, value) - key; + right = Math.max(right, value); + toRemove.push(key); + } else if (value > left && value <= right) { + paintAmount -= value - Math.max(left, key); + left = Math.min(left, key); + toRemove.push(key); + } + } + + for (const key of toRemove) { + intervals.delete(key); + } + + intervals.set(left, right); + result.push(Math.max(0, paintAmount)); + } + + return result; +}; diff --git a/solutions/2163-minimum-difference-in-sums-after-removal-of-elements.js b/solutions/2163-minimum-difference-in-sums-after-removal-of-elements.js new file mode 100644 index 00000000..82544302 --- /dev/null +++ b/solutions/2163-minimum-difference-in-sums-after-removal-of-elements.js @@ -0,0 +1,70 @@ +/** + * 2163. Minimum Difference in Sums After Removal of Elements + * https://leetcode.com/problems/minimum-difference-in-sums-after-removal-of-elements/ + * Difficulty: Hard + * + * You are given a 0-indexed integer array nums consisting of 3 * n elements. + * + * You are allowed to remove any subsequence of elements of size exactly n from nums. + * The remaining 2 * n elements will be divided into two equal parts: + * - The first n elements belonging to the first part and their sum is sumfirst. + * - The next n elements belonging to the second part and their sum is sumsecond. + * + * The difference in sums of the two parts is denoted as sumfirst - sumsecond. + * - For example, if sumfirst = 3 and sumsecond = 2, their difference is 1. + * - Similarly, if sumfirst = 2 and sumsecond = 3, their difference is -1. + * + * Return the minimum difference possible between the sums of the two parts after the removal + * of n elements. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumDifference = function(nums) { + const n = nums.length / 3; + const minFirstPart = new Array(nums.length).fill(0); + const maxSecondPart = new Array(nums.length).fill(0); + const maxHeap = new PriorityQueue((a, b) => b - a); + const minHeap = new PriorityQueue((a, b) => a - b); + + let currentSum = 0; + for (let i = 0; i < n; i++) { + maxHeap.enqueue(nums[i]); + currentSum += nums[i]; + } + minFirstPart[n - 1] = currentSum; + + for (let i = n; i < 2 * n; i++) { + maxHeap.enqueue(nums[i]); + currentSum += nums[i]; + const removed = maxHeap.dequeue(); + currentSum -= removed; + minFirstPart[i] = currentSum; + } + + currentSum = 0; + minHeap.clear(); + for (let i = 2 * n; i < 3 * n; i++) { + minHeap.enqueue(nums[i]); + currentSum += nums[i]; + } + maxSecondPart[2 * n] = currentSum; + + for (let i = 2 * n - 1; i >= n; i--) { + minHeap.enqueue(nums[i]); + currentSum += nums[i]; + const removed = minHeap.dequeue(); + currentSum -= removed; + maxSecondPart[i] = currentSum; + } + + let result = Infinity; + for (let i = n - 1; i < 2 * n; i++) { + const difference = minFirstPart[i] - maxSecondPart[i + 1]; + result = Math.min(result, difference); + } + + return result; +}; diff --git a/solutions/2168-unique-substrings-with-equal-digit-frequency.js b/solutions/2168-unique-substrings-with-equal-digit-frequency.js new file mode 100644 index 00000000..3a9dfe8a --- /dev/null +++ b/solutions/2168-unique-substrings-with-equal-digit-frequency.js @@ -0,0 +1,37 @@ +/** + * 2168. Unique Substrings With Equal Digit Frequency + * https://leetcode.com/problems/unique-substrings-with-equal-digit-frequency/ + * Difficulty: Medium + * + * Given a digit string s, return the number of unique substrings of s where every digit appears + * the same number of times. + */ + +/** + * @param {string} s + * @return {number} + */ +var equalDigitFrequency = function(s) { + const uniqueSubstrings = new Set(); + const n = s.length; + + for (let i = 0; i < n; i++) { + const digitCount = new Map(); + + for (let j = i; j < n; j++) { + const digit = s[j]; + digitCount.set(digit, (digitCount.get(digit) || 0) + 1); + + if (hasEqualFrequency(digitCount)) { + uniqueSubstrings.add(s.substring(i, j + 1)); + } + } + } + + return uniqueSubstrings.size; + + function hasEqualFrequency(counts) { + const frequencies = Array.from(counts.values()); + return frequencies.every(freq => freq === frequencies[0]); + } +}; diff --git a/solutions/2174-remove-all-ones-with-row-and-column-flips-ii.js b/solutions/2174-remove-all-ones-with-row-and-column-flips-ii.js new file mode 100644 index 00000000..0d2bdb69 --- /dev/null +++ b/solutions/2174-remove-all-ones-with-row-and-column-flips-ii.js @@ -0,0 +1,67 @@ +/** + * 2174. Remove All Ones With Row and Column Flips II + * https://leetcode.com/problems/remove-all-ones-with-row-and-column-flips-ii/ + * Difficulty: Medium + * + * You are given a 0-indexed m x n binary matrix grid. + * + * In one operation, you can choose any i and j that meet the following conditions: + * - 0 <= i < m + * - 0 <= j < n + * - grid[i][j] == 1 + * + * and change the values of all cells in row i and column j to zero. + * + * Return the minimum number of operations needed to remove all 1's from grid. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var removeOnes = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const map = new Map(); + + return solve(grid); + + function solve(currentGrid) { + const key = currentGrid.map(row => row.join('')).join('|'); + if (map.has(key)) return map.get(key); + + if (hasNoOnes(currentGrid)) return 0; + + let minOps = Infinity; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (currentGrid[i][j] === 1) { + const newGrid = performOperation(currentGrid, i, j); + minOps = Math.min(minOps, 1 + solve(newGrid)); + } + } + } + + map.set(key, minOps); + return minOps; + } + + function hasNoOnes(grid) { + return grid.every(row => row.every(cell => cell === 0)); + } + + function performOperation(grid, targetRow, targetCol) { + const newGrid = grid.map(row => [...row]); + + for (let j = 0; j < cols; j++) { + newGrid[targetRow][j] = 0; + } + + for (let i = 0; i < rows; i++) { + newGrid[i][targetCol] = 0; + } + + return newGrid; + } +}; diff --git a/solutions/2182-construct-string-with-repeat-limit.js b/solutions/2182-construct-string-with-repeat-limit.js new file mode 100644 index 00000000..15896132 --- /dev/null +++ b/solutions/2182-construct-string-with-repeat-limit.js @@ -0,0 +1,60 @@ +/** + * 2182. Construct String With Repeat Limit + * https://leetcode.com/problems/construct-string-with-repeat-limit/ + * Difficulty: Medium + * + * You are given a string s and an integer repeatLimit. Construct a new string + * repeatLimitedString using the characters of s such that no letter appears more than + * repeatLimit times in a row. You do not have to use all characters from s. + * + * Return the lexicographically largest repeatLimitedString possible. + * + * A string a is lexicographically larger than a string b if in the first position where + * a and b differ, string a has a letter that appears later in the alphabet than the + * corresponding letter in b. If the first min(a.length, b.length) characters do not differ, + * then the longer string is the lexicographically larger one. + */ + +/** + * @param {string} s + * @param {number} repeatLimit + * @return {string} + */ +var repeatLimitedString = function(s, repeatLimit) { + const frequency = new Array(26).fill(0); + for (const char of s) { + frequency[char.charCodeAt(0) - 97]++; + } + + const result = []; + let currentChar = 25; + + while (currentChar >= 0) { + if (frequency[currentChar] === 0) { + currentChar--; + continue; + } + + const useCount = Math.min(frequency[currentChar], repeatLimit); + for (let i = 0; i < useCount; i++) { + result.push(String.fromCharCode(currentChar + 97)); + } + frequency[currentChar] -= useCount; + + if (frequency[currentChar] > 0) { + let nextChar = currentChar - 1; + while (nextChar >= 0 && frequency[nextChar] === 0) { + nextChar--; + } + + if (nextChar < 0) break; + + result.push(String.fromCharCode(nextChar + 97)); + frequency[nextChar]--; + } else { + currentChar--; + } + } + + return result.join(''); +}; diff --git a/solutions/2184-number-of-ways-to-build-sturdy-brick-wall.js b/solutions/2184-number-of-ways-to-build-sturdy-brick-wall.js new file mode 100644 index 00000000..3551159b --- /dev/null +++ b/solutions/2184-number-of-ways-to-build-sturdy-brick-wall.js @@ -0,0 +1,99 @@ +/** + * 2184. Number of Ways to Build Sturdy Brick Wall + * https://leetcode.com/problems/number-of-ways-to-build-sturdy-brick-wall/ + * Difficulty: Medium + * + * You are given integers height and width which specify the dimensions of a brick wall you are + * building. You are also given a 0-indexed array of unique integers bricks, where the ith brick + * has a height of 1 and a width of bricks[i]. You have an infinite supply of each type of brick + * and bricks may not be rotated. + * + * Each row in the wall must be exactly width units long. For the wall to be sturdy, adjacent rows + * in the wall should not join bricks at the same location, except at the ends of the wall. + * + * Return the number of ways to build a sturdy wall. Since the answer may be very large, return + * it modulo 109 + 7. + */ + +/** + * @param {number} height + * @param {number} width + * @param {number[]} bricks + * @return {number} + */ +var buildWall = function(height, width, bricks) { + const MOD = 1e9 + 7; + const patterns = []; + + generatePatterns(0, []); + + if (patterns.length === 0) return 0; + + const graph = buildCompatibilityGraph(); + let dp = new Array(patterns.length).fill(1); + for (let row = 1; row < height; row++) { + const newDp = new Array(patterns.length).fill(0); + + for (let i = 0; i < patterns.length; i++) { + for (const j of graph[i]) { + newDp[i] = (newDp[i] + dp[j]) % MOD; + } + } + + dp = newDp; + } + + return dp.reduce((sum, count) => (sum + count) % MOD, 0); + + function generatePatterns(currentWidth, currentPattern) { + if (currentWidth === width) { + patterns.push([...currentPattern]); + return; + } + + for (const brick of bricks) { + if (currentWidth + brick <= width) { + currentPattern.push(brick); + generatePatterns(currentWidth + brick, currentPattern); + currentPattern.pop(); + } + } + } + + function buildCompatibilityGraph() { + const graph = Array.from({ length: patterns.length }, () => []); + + for (let i = 0; i < patterns.length; i++) { + for (let j = 0; j < patterns.length; j++) { + if (areCompatible(patterns[i], patterns[j])) { + graph[i].push(j); + } + } + } + + return graph; + } + + function areCompatible(pattern1, pattern2) { + const cuts1 = new Set(); + const cuts2 = new Set(); + + let pos = 0; + for (const brick of pattern1) { + pos += brick; + if (pos < width) cuts1.add(pos); + } + + pos = 0; + for (const brick of pattern2) { + pos += brick; + if (pos < width) cuts2.add(pos); + } + + for (const cut of cuts1) { + if (cuts2.has(cut)) return false; + } + + return true; + } +}; diff --git a/solutions/2189-number-of-ways-to-build-house-of-cards.js b/solutions/2189-number-of-ways-to-build-house-of-cards.js new file mode 100644 index 00000000..80b2f197 --- /dev/null +++ b/solutions/2189-number-of-ways-to-build-house-of-cards.js @@ -0,0 +1,35 @@ +/** + * 2189. Number of Ways to Build House of Cards + * https://leetcode.com/problems/number-of-ways-to-build-house-of-cards/ + * Difficulty: Medium + * + * You are given an integer n representing the number of playing cards you have. A house of + * cards meets the following conditions: + * - A house of cards consists of one or more rows of triangles and horizontal cards. + * - Triangles are created by leaning two cards against each other. + * - One card must be placed horizontally between all adjacent triangles in a row. + * - Any triangle on a row higher than the first must be placed on a horizontal card from the + * previous row. + * - Each triangle is placed in the leftmost available spot in the row. + * + * Return the number of distinct house of cards you can build using all n cards. Two houses of + * cards are considered distinct if there exists a row where the two houses contain a different + * number of cards. + */ + +/** + * @param {number} n + * @return {number} + */ +var houseOfCards = function(n) { + const dp = new Array(n + 1).fill(0); + dp[0] = 1; + + for (let i = 2; i <= n; i += 3) { + for (let j = n; j >= i; j--) { + dp[j] += dp[j - i]; + } + } + + return dp[n]; +}; diff --git a/solutions/2198-number-of-single-divisor-triplets.js b/solutions/2198-number-of-single-divisor-triplets.js new file mode 100644 index 00000000..b3513233 --- /dev/null +++ b/solutions/2198-number-of-single-divisor-triplets.js @@ -0,0 +1,50 @@ +/** + * 2198. Number of Single Divisor Triplets + * https://leetcode.com/problems/number-of-single-divisor-triplets/ + * Difficulty: Medium + * + * You are given a 0-indexed array of positive integers nums. A triplet of three distinct + * indices (i, j, k) is called a single divisor triplet of nums if nums[i] + nums[j] + nums[k] + * is divisible by exactly one of nums[i], nums[j], or nums[k]. + * + * Return the number of single divisor triplets of nums. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var singleDivisorTriplet = function(nums) { + let result = 0; + const count = new Array(101).fill(0); + + for (const num of nums) { + count[num]++; + } + + for (let i = 1; i <= 100; i++) { + if (!count[i]) continue; + for (let j = i; j <= 100; j++) { + if (!count[j]) continue; + for (let k = j + (i === j ? 1 : 0); k <= 100; k++) { + if (!count[k]) continue; + + const sum = i + j + k; + const divisors = (sum % i === 0 ? 1 : 0) + + (sum % j === 0 ? 1 : 0) + (sum % k === 0 ? 1 : 0); + + if (divisors === 1) { + if (i === j) { + result += count[i] * (count[i] - 1) / 2 * count[k]; + } else if (j === k) { + result += count[i] * count[j] * (count[j] - 1) / 2; + } else { + result += count[i] * count[j] * count[k]; + } + } + } + } + } + + return result * 6; +}; diff --git a/solutions/2204-distance-to-a-cycle-in-undirected-graph.js b/solutions/2204-distance-to-a-cycle-in-undirected-graph.js new file mode 100644 index 00000000..42a48b77 --- /dev/null +++ b/solutions/2204-distance-to-a-cycle-in-undirected-graph.js @@ -0,0 +1,71 @@ +/** + * 2204. Distance to a Cycle in Undirected Graph + * https://leetcode.com/problems/distance-to-a-cycle-in-undirected-graph/ + * Difficulty: Hard + * + * You are given a positive integer n representing the number of nodes in a connected undirected + * graph containing exactly one cycle. The nodes are numbered from 0 to n - 1 (inclusive). + * + * You are also given a 2D integer array edges, where edges[i] = [node1i, node2i] denotes that + * there is a bidirectional edge connecting node1i and node2i in the graph. + * + * The distance between two nodes a and b is defined to be the minimum number of edges that are + * needed to go from a to b. + * + * Return an integer array answer of size n, where answer[i] is the minimum distance between the + * ith node and any node in the cycle. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @return {number[]} + */ +var distanceToCycle = function(n, edges) { + const graph = Array.from({ length: n }, () => []); + const result = new Array(n).fill(0); + const degree = new Array(n).fill(0); + const queue = []; + + for (const [u, v] of edges) { + graph[u].push(v); + graph[v].push(u); + } + + for (let i = 0; i < n; i++) { + degree[i] = graph[i].length; + if (degree[i] === 1) { + queue.push(i); + } + } + + while (queue.length > 0) { + const node = queue.shift(); + result[node] = Infinity; + + for (const neighbor of graph[node]) { + if (degree[neighbor] > 1 && --degree[neighbor] === 1) { + queue.push(neighbor); + } + } + } + + for (let i = 0; i < n; i++) { + if (degree[i] > 1) { + queue.push(i); + } + } + + while (queue.length > 0) { + const node = queue.shift(); + + for (const neighbor of graph[node]) { + if (result[neighbor] > result[node] + 1) { + result[neighbor] = result[node] + 1; + queue.push(neighbor); + } + } + } + + return result; +}; diff --git a/solutions/2208-minimum-operations-to-halve-array-sum.js b/solutions/2208-minimum-operations-to-halve-array-sum.js new file mode 100644 index 00000000..dffd4cd0 --- /dev/null +++ b/solutions/2208-minimum-operations-to-halve-array-sum.js @@ -0,0 +1,39 @@ +/** + * 2208. Minimum Operations to Halve Array Sum + * https://leetcode.com/problems/minimum-operations-to-halve-array-sum/ + * Difficulty: Medium + * + * You are given an array nums of positive integers. In one operation, you can choose any + * number from nums and reduce it to exactly half the number. (Note that you may choose + * this reduced number in future operations.) + * + * Return the minimum number of operations to reduce the sum of nums by at least half. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var halveArray = function(nums) { + const pq = new PriorityQueue((a, b) => b - a); + let totalSum = 0; + + for (const num of nums) { + pq.enqueue(num); + totalSum += num; + } + + const target = totalSum / 2; + let reducedSum = 0; + let result = 0; + + while (reducedSum < target) { + const largest = pq.dequeue(); + const halved = largest / 2; + reducedSum += halved; + pq.enqueue(halved); + result++; + } + + return result; +}; diff --git a/solutions/2214-minimum-health-to-beat-game.js b/solutions/2214-minimum-health-to-beat-game.js new file mode 100644 index 00000000..48daf2f2 --- /dev/null +++ b/solutions/2214-minimum-health-to-beat-game.js @@ -0,0 +1,30 @@ +/** + * 2214. Minimum Health to Beat Game + * https://leetcode.com/problems/minimum-health-to-beat-game/ + * Difficulty: Medium + * + * You are playing a game that has n levels numbered from 0 to n - 1. You are given a 0-indexed + * integer array damage where damage[i] is the amount of health you will lose to complete the + * ith level. + * + * You are also given an integer armor. You may use your armor ability at most once during the + * game on any level which will protect you from at most armor damage. + * + * You must complete the levels in order and your health must be greater than 0 at all times to + * beat the game. + * + * Return the minimum health you need to start with to beat the game. + */ + +/** + * @param {number[]} damage + * @param {number} armor + * @return {number} + */ +var minimumHealth = function(damage, armor) { + const totalDamage = damage.reduce((sum, dmg) => sum + dmg, 0); + const maxDamage = Math.max(...damage); + const armorReduction = Math.min(armor, maxDamage); + + return totalDamage - armorReduction + 1; +}; diff --git a/solutions/2219-maximum-sum-score-of-array.js b/solutions/2219-maximum-sum-score-of-array.js new file mode 100644 index 00000000..4377053e --- /dev/null +++ b/solutions/2219-maximum-sum-score-of-array.js @@ -0,0 +1,33 @@ +/** + * 2219. Maximum Sum Score of Array + * https://leetcode.com/problems/maximum-sum-score-of-array/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums of length n. + * + * The sum score of nums at an index i where 0 <= i < n is the maximum of: + * - The sum of the first i + 1 elements of nums. + * - The sum of the last n - i elements of nums. + * + * Return the maximum sum score of nums at any index. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maximumSumScore = function(nums) { + const n = nums.length; + const totalSum = nums.reduce((sum, num) => sum + num, 0); + let prefixSum = 0; + let maxScore = -Infinity; + + for (let i = 0; i < n; i++) { + prefixSum += nums[i]; + const suffixSum = totalSum - prefixSum + nums[i]; + const score = Math.max(prefixSum, suffixSum); + maxScore = Math.max(maxScore, score); + } + + return maxScore; +}; diff --git a/solutions/2229-check-if-an-array-is-consecutive.js b/solutions/2229-check-if-an-array-is-consecutive.js new file mode 100644 index 00000000..6e03f23a --- /dev/null +++ b/solutions/2229-check-if-an-array-is-consecutive.js @@ -0,0 +1,28 @@ +/** + * 2229. Check if an Array Is Consecutive + * https://leetcode.com/problems/check-if-an-array-is-consecutive/ + * Difficulty: Easy + * + * Given an integer array nums, return true if nums is consecutive, otherwise return false. + * + * An array is consecutive if it contains every number in the range [x, x + n - 1] (inclusive), + * where x is the minimum number in the array and n is the length of the array. + */ + +/** + * @param {number[]} nums + * @return {boolean} + */ +var isConsecutive = function(nums) { + const set = new Set(nums); + if (set.size !== nums.length) return false; + + const minNum = Math.min(...nums); + for (let i = 0; i < nums.length; i++) { + if (!set.has(minNum + i)) { + return false; + } + } + + return true; +}; diff --git a/solutions/2231-largest-number-after-digit-swaps-by-parity.js b/solutions/2231-largest-number-after-digit-swaps-by-parity.js new file mode 100644 index 00000000..c7b43b77 --- /dev/null +++ b/solutions/2231-largest-number-after-digit-swaps-by-parity.js @@ -0,0 +1,45 @@ +/** + * 2231. Largest Number After Digit Swaps by Parity + * https://leetcode.com/problems/largest-number-after-digit-swaps-by-parity/ + * Difficulty: Easy + * + * You are given a positive integer num. You may swap any two digits of num that have the + * same parity (i.e. both odd digits or both even digits). + * + * Return the largest possible value of num after any number of swaps. + */ + +/** + * @param {number} num + * @return {number} + */ +var largestInteger = function(num) { + const digits = num.toString().split('').map(Number); + const evenDigits = []; + const oddDigits = []; + + for (const digit of digits) { + if (digit % 2 === 0) { + evenDigits.push(digit); + } else { + oddDigits.push(digit); + } + } + + evenDigits.sort((a, b) => b - a); + oddDigits.sort((a, b) => b - a); + + let evenIndex = 0; + let oddIndex = 0; + const result = []; + + for (const digit of digits) { + if (digit % 2 === 0) { + result.push(evenDigits[evenIndex++]); + } else { + result.push(oddDigits[oddIndex++]); + } + } + + return parseInt(result.join(''), 10); +}; diff --git a/solutions/2233-maximum-product-after-k-increments.js b/solutions/2233-maximum-product-after-k-increments.js new file mode 100644 index 00000000..2b1b61b0 --- /dev/null +++ b/solutions/2233-maximum-product-after-k-increments.js @@ -0,0 +1,38 @@ +/** + * 2233. Maximum Product After K Increments + * https://leetcode.com/problems/maximum-product-after-k-increments/ + * Difficulty: Medium + * + * You are given an array of non-negative integers nums and an integer k. In one operation, + * you may choose any element from nums and increment it by 1. + * + * Return the maximum product of nums after at most k operations. Since the answer may be + * very large, return it modulo 109 + 7. Note that you should maximize the product before + * taking the modulo. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var maximumProduct = function(nums, k) { + const MOD = 1e9 + 7; + const minHeap = new PriorityQueue((a, b) => a - b); + + for (const num of nums) { + minHeap.enqueue(num); + } + + for (let i = 0; i < k; i++) { + const smallest = minHeap.dequeue(); + minHeap.enqueue(smallest + 1); + } + + let result = 1; + while (!minHeap.isEmpty()) { + result = (result * minHeap.dequeue()) % MOD; + } + + return result; +}; diff --git a/solutions/2237-count-positions-on-street-with-required-brightness.js b/solutions/2237-count-positions-on-street-with-required-brightness.js new file mode 100644 index 00000000..32653575 --- /dev/null +++ b/solutions/2237-count-positions-on-street-with-required-brightness.js @@ -0,0 +1,48 @@ +/** + * 2237. Count Positions on Street With Required Brightness + * https://leetcode.com/problems/count-positions-on-street-with-required-brightness/ + * Difficulty: Medium + * + * You are given an integer n. A perfectly straight street is represented by a number line + * ranging from 0 to n - 1. You are given a 2D integer array lights representing the street + * lamp(s) on the street. Each lights[i] = [positioni, rangei] indicates that there is a + * street lamp at position positioni that lights up the area from + * [max(0, positioni - rangei), min(n - 1, positioni + rangei)] (inclusive). + * + * The brightness of a position p is defined as the number of street lamps that light up the + * position p. You are given a 0-indexed integer array requirement of size n where + * requirement[i] is the minimum brightness of the ith position on the street. + * + * Return the number of positions i on the street between 0 and n - 1 that have a brightness + * of at least requirement[i]. + */ + +/** + * @param {number} n + * @param {number[][]} lights + * @param {number[]} requirement + * @return {number} + */ +var meetRequirement = function(n, lights, requirement) { + const brightness = new Array(n).fill(0); + for (const [position, range] of lights) { + const start = Math.max(0, position - range); + const end = Math.min(n - 1, position + range); + + brightness[start]++; + if (end + 1 < n) { + brightness[end + 1]--; + } + } + + let currentBrightness = 0; + let result = 0; + for (let i = 0; i < n; i++) { + currentBrightness += brightness[i]; + if (currentBrightness >= requirement[i]) { + result++; + } + } + + return result; +}; diff --git a/solutions/2247-maximum-cost-of-trip-with-k-highways.js b/solutions/2247-maximum-cost-of-trip-with-k-highways.js new file mode 100644 index 00000000..1852369a --- /dev/null +++ b/solutions/2247-maximum-cost-of-trip-with-k-highways.js @@ -0,0 +1,61 @@ +/** + * 2247. Maximum Cost of Trip With K Highways + * https://leetcode.com/problems/maximum-cost-of-trip-with-k-highways/ + * Difficulty: Hard + * + * A series of highways connect n cities numbered from 0 to n - 1. You are given a 2D integer array + * highways where highways[i] = [city1i, city2i, tolli] indicates that there is a highway that + * connects city1i and city2i, allowing a car to go from city1i to city2i and vice versa for a cost + * of tolli. + * + * You are also given an integer k. You are going on a trip that crosses exactly k highways. You + * may start at any city, but you may only visit each city at most once during your trip. + * + * Return the maximum cost of your trip. If there is no trip that meets the requirements, return -1. + */ + +/** + * @param {number} n + * @param {number[][]} highways + * @param {number} k + * @return {number} + */ +var maximumCost = function(n, highways, k) { + if (k + 1 > n) return -1; + + const graph = Array(n).fill().map(() => []); + for (const [cityA, cityB, cost] of highways) { + graph[cityA].push([cityB, cost]); + graph[cityB].push([cityA, cost]); + } + + const memo = new Map(); + let result = -1; + + for (let city = 0; city < n; city++) { + result = Math.max(result, dp(city, 1 << city)); + } + + return result; + + function dp(city, bitmask) { + const citiesVisited = bitmask.toString(2).split('1').length - 1; + if (citiesVisited === k + 1) return 0; + + const key = `${city}_${bitmask}`; + if (memo.has(key)) return memo.get(key); + + let answer = -1; + for (const [neighborCity, highwayCost] of graph[city]) { + if (!((bitmask >> neighborCity) & 1)) { + const neighborAnswer = dp(neighborCity, bitmask | (1 << neighborCity)); + if (neighborAnswer !== -1) { + answer = Math.max(answer, highwayCost + neighborAnswer); + } + } + } + + memo.set(key, answer); + return answer; + } +}; diff --git a/solutions/2254-design-video-sharing-platform.js b/solutions/2254-design-video-sharing-platform.js new file mode 100644 index 00000000..c3e6e9fa --- /dev/null +++ b/solutions/2254-design-video-sharing-platform.js @@ -0,0 +1,138 @@ +/** + * 2254. Design Video Sharing Platform + * https://leetcode.com/problems/design-video-sharing-platform/ + * Difficulty: Hard + * + * You have a video sharing platform where users can upload and delete videos. Each video is a + * string of digits, where the ith digit of the string represents the content of the video at + * minute i. For example, the first digit represents the content at minute 0 in the video, the + * second digit represents the content at minute 1 in the video, and so on. Viewers of videos + * can also like and dislike videos. Internally, the platform keeps track of the number of views, + * likes, and dislikes on each video. + * + * When a video is uploaded, it is associated with the smallest available integer videoId starting + * from 0. Once a video is deleted, the videoId associated with that video can be reused for + * another video. + * + * Implement the VideoSharingPlatform class: + * - VideoSharingPlatform() Initializes the object. + * - int upload(String video) The user uploads a video. Return the videoId associated with + * the video. + * - void remove(int videoId) If there is a video associated with videoId, remove the video. + * - String watch(int videoId, int startMinute, int endMinute) If there is a video associated with + * videoId, increase the number of views on the video by 1 and return the substring of the video + * string starting at startMinute and ending at min(endMinute, video.length - 1) (inclusive). + * Otherwise, return "-1". + * - void like(int videoId) Increases the number of likes on the video associated with videoId by 1 + * if there is a video associated with videoId. + * - void dislike(int videoId) Increases the number of dislikes on the video associated with videoId + * by 1 if there is a video associated with videoId. + * - int[] getLikesAndDislikes(int videoId) Return a 0-indexed integer array values of length 2 + * where values[0] is the number of likes and values[1] is the number of dislikes on the video + * associated with videoId. If there is no video associated with videoId, return [-1]. + * - int getViews(int videoId) Return the number of views on the video associated with videoId, if + * there is no video associated with videoId, return -1. + */ + +var VideoSharingPlatform = function() { + this.videos = new Map(); + this.availableIds = []; + this.nextId = 0; +}; + +/** + * @param {string} video + * @return {number} + */ +VideoSharingPlatform.prototype.upload = function(video) { + let videoId; + if (this.availableIds.length > 0) { + videoId = this.availableIds.shift(); + } else { + videoId = this.nextId++; + } + + this.videos.set(videoId, { + content: video, + views: 0, + likes: 0, + dislikes: 0 + }); + + return videoId; +}; + +/** + * @param {number} videoId + * @return {void} + */ +VideoSharingPlatform.prototype.remove = function(videoId) { + if (this.videos.has(videoId)) { + this.videos.delete(videoId); + this.availableIds.push(videoId); + this.availableIds.sort((a, b) => a - b); + } +}; + +/** + * @param {number} videoId + * @param {number} startMinute + * @param {number} endMinute + * @return {string} + */ +VideoSharingPlatform.prototype.watch = function(videoId, startMinute, endMinute) { + if (!this.videos.has(videoId)) { + return '-1'; + } + + const videoData = this.videos.get(videoId); + videoData.views++; + + const actualEndMinute = Math.min(endMinute, videoData.content.length - 1); + return videoData.content.substring(startMinute, actualEndMinute + 1); +}; + +/** + * @param {number} videoId + * @return {void} + */ +VideoSharingPlatform.prototype.like = function(videoId) { + if (this.videos.has(videoId)) { + this.videos.get(videoId).likes++; + } +}; + +/** + * @param {number} videoId + * @return {void} + */ +VideoSharingPlatform.prototype.dislike = function(videoId) { + if (this.videos.has(videoId)) { + this.videos.get(videoId).dislikes++; + } +}; + +/** + * @param {number} videoId + * @return {number[]} + */ +VideoSharingPlatform.prototype.getLikesAndDislikes = function(videoId) { + if (!this.videos.has(videoId)) { + return [-1]; + } + + const videoData = this.videos.get(videoId); + return [videoData.likes, videoData.dislikes]; +}; + +/** + * @param {number} videoId + * @return {number} + */ +VideoSharingPlatform.prototype.getViews = function(videoId) { + if (!this.videos.has(videoId)) { + return -1; + } + + return this.videos.get(videoId).views; +}; diff --git a/solutions/2263-make-array-non-decreasing-or-non-increasing.js b/solutions/2263-make-array-non-decreasing-or-non-increasing.js new file mode 100644 index 00000000..68cf2296 --- /dev/null +++ b/solutions/2263-make-array-non-decreasing-or-non-increasing.js @@ -0,0 +1,45 @@ +/** + * 2263. Make Array Non-decreasing or Non-increasing + * https://leetcode.com/problems/make-array-non-decreasing-or-non-increasing/ + * Difficulty: Hard + * + * You are given a 0-indexed integer array nums. In one operation, you can: + * - Choose an index i in the range 0 <= i < nums.length + * - Set nums[i] to nums[i] + 1 or nums[i] - 1 + * + * Return the minimum number of operations to make nums non-decreasing or non-increasing. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var convertArray = function(nums) { + const levels = [...new Set(nums)].sort((a, b) => a - b); + const reversedNums = [...nums].reverse(); + + return Math.min(helper(nums, levels), helper(reversedNums, levels)); + + function helper(arr, levels) { + const dp = new Map(); + for (const level of levels) { + dp.set(level, 0); + } + + for (const num of arr) { + let currentResult = Infinity; + const newDp = new Map(); + + for (const level of levels) { + currentResult = Math.min(currentResult, dp.get(level) + Math.abs(num - level)); + newDp.set(level, currentResult); + } + + for (const [level, value] of newDp) { + dp.set(level, value); + } + } + + return dp.get(Math.max(...levels)); + } +}; diff --git a/solutions/2268-minimum-number-of-keypresses.js b/solutions/2268-minimum-number-of-keypresses.js new file mode 100644 index 00000000..51145e7e --- /dev/null +++ b/solutions/2268-minimum-number-of-keypresses.js @@ -0,0 +1,40 @@ +/** + * 2268. Minimum Number of Keypresses + * https://leetcode.com/problems/minimum-number-of-keypresses/ + * Difficulty: Medium + * + * You have a keypad with 9 buttons, numbered from 1 to 9, each mapped to lowercase English + * letters. You can choose which characters each button is matched to as long as: + * - All 26 lowercase English letters are mapped to. + * - Each character is mapped to by exactly 1 button. + * - Each button maps to at most 3 characters. + * + * To type the first character matched to a button, you press the button once. To type the + * second character, you press the button twice, and so on. + * + * Given a string s, return the minimum number of keypresses needed to type s using your keypad. + * + * Note that the characters mapped to by each button, and the order they are mapped in cannot + * be changed. + */ + +/** + * @param {string} s + * @return {number} + */ +var minimumKeypresses = function(s) { + const frequency = new Map(); + for (const char of s) { + frequency.set(char, (frequency.get(char) || 0) + 1); + } + + const frequencies = Array.from(frequency.values()).sort((a, b) => b - a); + + let keypresses = 0; + for (let i = 0; i < frequencies.length; i++) { + const pressesPerChar = Math.floor(i / 9) + 1; + keypresses += frequencies[i] * pressesPerChar; + } + + return keypresses; +}; diff --git a/solutions/2276-count-integers-in-intervals.js b/solutions/2276-count-integers-in-intervals.js new file mode 100644 index 00000000..1db3160b --- /dev/null +++ b/solutions/2276-count-integers-in-intervals.js @@ -0,0 +1,80 @@ +/** + * 2276. Count Integers in Intervals + * https://leetcode.com/problems/count-integers-in-intervals/ + * Difficulty: Hard + * + * Given an empty set of intervals, implement a data structure that can: + * - Add an interval to the set of intervals. + * - Count the number of integers that are present in at least one interval. + * + * Implement the CountIntervals class: + * - CountIntervals() Initializes the object with an empty set of intervals. + * - void add(int left, int right) Adds the interval [left, right] to the set of intervals. + * - int count() Returns the number of integers that are present in at least one interval. + * + * Note that an interval [left, right] denotes all the integers x where left <= x <= right. + */ + +var CountIntervals = function() { + this.coverage = 0; + this.intervals = [[-Infinity, -Infinity], [Infinity, Infinity]]; +}; + +/** + * @param {number} left + * @param {number} right + * @return {void} + */ +CountIntervals.prototype.add = function(left, right) { + function bisectLeft(arr, target) { + let low = 0; + let high = arr.length; + while (low < high) { + const mid = Math.floor((low + high) / 2); + if (arr[mid][0] < target) { + low = mid + 1; + } else { + high = mid; + } + } + return low; + } + + function bisectRight(arr, target) { + let low = 0; + let high = arr.length; + while (low < high) { + const mid = Math.floor((low + high) / 2); + if (arr[mid][0] <= target) { + low = mid + 1; + } else { + high = mid; + } + } + return low; + } + + let li = bisectLeft(this.intervals, left - 1); + if (this.intervals[li - 1][1] >= left - 1) { + li -= 1; + } + + const lval = Math.min(this.intervals[li][0], left); + const ri = bisectRight(this.intervals, right + 1); + const rval = Math.max(this.intervals[ri - 1][1], right); + + let toDelete = 0; + for (let i = li; i < ri; i++) { + toDelete += this.intervals[i][1] - this.intervals[i][0] + 1; + } + + this.coverage += rval - lval + 1 - toDelete; + this.intervals.splice(li, ri - li, [lval, rval]); +}; + +/** + * @return {number} + */ +CountIntervals.prototype.count = function() { + return this.coverage; +}; diff --git a/solutions/2277-closest-node-to-path-in-tree.js b/solutions/2277-closest-node-to-path-in-tree.js new file mode 100644 index 00000000..642b68e6 --- /dev/null +++ b/solutions/2277-closest-node-to-path-in-tree.js @@ -0,0 +1,79 @@ +/** + * 2277. Closest Node to Path in Tree + * https://leetcode.com/problems/closest-node-to-path-in-tree/ + * Difficulty: Hard + * + * You are given a positive integer n representing the number of nodes in a tree, numbered + * from 0 to n - 1 (inclusive). You are also given a 2D integer array edges of length n - 1, + * where edges[i] = [node1i, node2i] denotes that there is a bidirectional edge connecting + * node1i and node2i in the tree. + * + * You are given a 0-indexed integer array query of length m where query[i] = [starti, endi, nodei] + * means that for the ith query, you are tasked with finding the node on the path from starti to + * endi that is closest to nodei. + * + * Return an integer array answer of length m, where answer[i] is the answer to the ith query. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number[][]} query + * @return {number[]} + */ +var closestNode = function(n, edges, query) { + const graph = new Array(n).fill().map(() => []); + for (const [a, b] of edges) { + graph[a].push(b); + graph[b].push(a); + } + + const depths = new Array(n).fill(0); + const binaryParents = new Array(n).fill().map(() => new Array(16).fill(0)); + + dfs(0, [], 0); + + return query.map(([a, b, q]) => { + const candidates = [lca(a, b), lca(a, q), lca(b, q)]; + return candidates.reduce((deepest, current) => + depths[current] > depths[deepest] ? current : deepest + ); + }); + + function dfs(node, parents, depth) { + depths[node] = depth; + for (let bit = 0; bit < 16; bit++) { + if ((1 << bit) <= parents.length) { + binaryParents[node][bit] = parents[parents.length - (1 << bit)]; + } + } + parents.push(node); + for (const next of graph[node]) { + if (parents.length >= 2 && next === parents[parents.length - 2]) { + continue; + } + dfs(next, parents, depth + 1); + } + parents.pop(); + } + + function getKthParent(node, k) { + if (!k) return node; + let bit = 0; + while ((1 << (bit + 1)) <= k) bit++; + return getKthParent(binaryParents[node][bit], k & (~(1 << bit))); + } + + function lca(a, b) { + if (depths[a] > depths[b]) return lca(b, a); + b = getKthParent(b, depths[b] - depths[a]); + if (a === b) return a; + for (let i = binaryParents[a].length - 1; i >= 0; i--) { + if (binaryParents[a][i] !== binaryParents[b][i]) { + a = binaryParents[a][i]; + b = binaryParents[b][i]; + } + } + return binaryParents[a][0]; + } +}; diff --git a/solutions/2281-sum-of-total-strength-of-wizards.js b/solutions/2281-sum-of-total-strength-of-wizards.js new file mode 100644 index 00000000..8d477c20 --- /dev/null +++ b/solutions/2281-sum-of-total-strength-of-wizards.js @@ -0,0 +1,82 @@ +/** + * 2281. Sum of Total Strength of Wizards + * https://leetcode.com/problems/sum-of-total-strength-of-wizards/ + * Difficulty: Hard + * + * As the ruler of a kingdom, you have an army of wizards at your command. + * + * You are given a 0-indexed integer array strength, where strength[i] denotes the strength + * of the ith wizard. For a contiguous group of wizards (i.e. the wizards' strengths form + * a subarray of strength), the total strength is defined as the product of the following + * two values: + * - The strength of the weakest wizard in the group. + * - The total of all the individual strengths of the wizards in the group. + * + * Return the sum of the total strengths of all contiguous groups of wizards. Since the answer + * may be very large, return it modulo 109 + 7. + * + * A subarray is a contiguous non-empty sequence of elements within an array. + */ + +/** + * @param {number[]} strength + * @return {number} + */ +var totalStrength = function(strength) { + const n = strength.length; + const mod = BigInt(1e9 + 7); + const left = new Array(n).fill(-1); + const right = new Array(n).fill(n); + + const stack = []; + + for (let i = 0; i < n; ++i) { + while (stack.length > 0 && strength[stack[stack.length - 1]] >= strength[i]) { + stack.pop(); + } + if (stack.length > 0) { + left[i] = stack[stack.length - 1]; + } + stack.push(i); + } + + stack.length = 0; + + for (let i = n - 1; i >= 0; --i) { + while (stack.length > 0 && strength[stack[stack.length - 1]] > strength[i]) { + stack.pop(); + } + if (stack.length > 0) { + right[i] = stack[stack.length - 1]; + } + stack.push(i); + } + + const prefixSum = new Array(n + 1).fill(0n); + for (let i = 0; i < n; ++i) { + prefixSum[i + 1] = (prefixSum[i] + BigInt(strength[i])) % mod; + } + + const prefixSumOfPrefixSum = new Array(n + 2).fill(0n); + for (let i = 0; i < n + 1; ++i) { + prefixSumOfPrefixSum[i + 1] = (prefixSumOfPrefixSum[i] + prefixSum[i]) % mod; + } + + let result = 0n; + for (let i = 0; i < n; ++i) { + const value = BigInt(strength[i]); + const l = left[i] + 1; + const r = right[i] - 1; + const leftSum = (prefixSumOfPrefixSum[i + 1] - prefixSumOfPrefixSum[l] + mod) % mod; + const rightSum = (prefixSumOfPrefixSum[r + 2] - prefixSumOfPrefixSum[i + 1] + mod) % mod; + const leftCount = BigInt(i - l + 1); + const rightCount = BigInt(r - i + 1); + const leftPart = (rightSum * leftCount) % mod; + const rightPart = (leftSum * rightCount) % mod; + const contribution = (value * ((leftPart - rightPart + mod) % mod)) % mod; + + result = (result + contribution) % mod; + } + + return Number(result); +}; diff --git a/solutions/2282-number-of-people-that-can-be-seen-in-a-grid.js b/solutions/2282-number-of-people-that-can-be-seen-in-a-grid.js new file mode 100644 index 00000000..561f87be --- /dev/null +++ b/solutions/2282-number-of-people-that-can-be-seen-in-a-grid.js @@ -0,0 +1,64 @@ +/** + * 2282. Number of People That Can Be Seen in a Grid + * https://leetcode.com/problems/number-of-people-that-can-be-seen-in-a-grid/ + * Difficulty: Medium + * + * You are given an m x n 0-indexed 2D array of positive integers heights where heights[i][j] + * is the height of the person standing at position (i, j). + * + * A person standing at position (row1, col1) can see a person standing at position (row2, col2) if: + * - The person at (row2, col2) is to the right or below the person at (row1, col1). More formally, + * this means that either row1 == row2 and col1 < col2 or row1 < row2 and col1 == col2. + * - Everyone in between them is shorter than both of them. + * + * Return an m x n 2D array of integers answer where answer[i][j] is the number of people that the + * person at position (i, j) can see. + */ + +/** + * @param {number[][]} heights + * @return {number[][]} + */ +var seePeople = function(heights) { + const rows = heights.length; + const cols = heights[0].length; + const result = new Array(rows).fill().map(() => new Array(cols).fill(0)); + + for (let i = 0; i < rows; i++) { + const stack = []; + for (let j = cols - 1; j >= 0; j--) { + let equal = false; + while (stack.length > 0 && stack[stack.length - 1] <= heights[i][j]) { + if (stack[stack.length - 1] === heights[i][j]) { + equal = true; + } + stack.pop(); + result[i][j]++; + } + if (stack.length > 0 && !equal) { + result[i][j]++; + } + stack.push(heights[i][j]); + } + } + + for (let j = 0; j < cols; j++) { + const stack = []; + for (let i = rows - 1; i >= 0; i--) { + let equal = false; + while (stack.length > 0 && stack[stack.length - 1] <= heights[i][j]) { + if (stack[stack.length - 1] === heights[i][j]) { + equal = true; + } + stack.pop(); + result[i][j]++; + } + if (stack.length > 0 && !equal) { + result[i][j]++; + } + stack.push(heights[i][j]); + } + } + + return result; +}; diff --git a/solutions/2285-maximum-total-importance-of-roads.js b/solutions/2285-maximum-total-importance-of-roads.js new file mode 100644 index 00000000..47964c64 --- /dev/null +++ b/solutions/2285-maximum-total-importance-of-roads.js @@ -0,0 +1,42 @@ +/** + * 2285. Maximum Total Importance of Roads + * https://leetcode.com/problems/maximum-total-importance-of-roads/ + * Difficulty: Medium + * + * You are given an integer n denoting the number of cities in a country. The cities are + * numbered from 0 to n - 1. + * + * You are also given a 2D integer array roads where roads[i] = [ai, bi] denotes that there + * exists a bidirectional road connecting cities ai and bi. + * + * You need to assign each city with an integer value from 1 to n, where each value can + * only be used once. The importance of a road is then defined as the sum of the values + * of the two cities it connects. + * + * Return the maximum total importance of all roads possible after assigning the values + * optimally. + */ + +/** + * @param {number} n + * @param {number[][]} roads + * @return {number} + */ +var maximumImportance = function(n, roads) { + const degrees = new Array(n).fill(0); + + for (const [a, b] of roads) { + degrees[a]++; + degrees[b]++; + } + + const cities = Array.from({ length: n }, (_, i) => i); + cities.sort((a, b) => degrees[b] - degrees[a]); + + let result = 0; + for (let i = 0; i < n; i++) { + result += degrees[cities[i]] * (n - i); + } + + return result; +}; diff --git a/solutions/2286-booking-concert-tickets-in-groups.js b/solutions/2286-booking-concert-tickets-in-groups.js new file mode 100644 index 00000000..4e85bb43 --- /dev/null +++ b/solutions/2286-booking-concert-tickets-in-groups.js @@ -0,0 +1,184 @@ +/** + * 2286. Booking Concert Tickets in Groups + * https://leetcode.com/problems/booking-concert-tickets-in-groups/ + * Difficulty: Hard + * + * A concert hall has n rows numbered from 0 to n - 1, each with m seats, numbered from + * 0 to m - 1. You need to design a ticketing system that can allocate seats in the following cases: + * - If a group of k spectators can sit together in a row. + * - If every member of a group of k spectators can get a seat. They may or may not sit together. + * + * Note that the spectators are very picky. Hence: + * - They will book seats only if each member of their group can get a seat with row number less + * than or equal to maxRow. maxRow can vary from group to group. + * - In case there are multiple rows to choose from, the row with the smallest number is chosen. + * If there are multiple seats to choose in the same row, the seat with the smallest number is + * chosen. + * + * Implement the BookMyShow class: + * - BookMyShow(int n, int m) Initializes the object with n as number of rows and m as number of + * seats per row. + * - int[] gather(int k, int maxRow) Returns an array of length 2 denoting the row and seat number + * (respectively) of the first seat being allocated to the k members of the group, who must sit + * together. In other words, it returns the smallest possible r and c such that all [c, c + k - 1] + * seats are valid and empty in row r, and r <= maxRow. Returns [] in case it is not possible to + * allocate seats to the group. + * - boolean scatter(int k, int maxRow) Returns true if all k members of the group can be allocated + * seats in rows 0 to maxRow, who may or may not sit together. If the seats can be allocated, it + * allocates k seats to the group with the smallest row numbers, and the smallest possible seat + * numbers in each row. Otherwise, returns false. + */ + +/** + * @param {number} n + * @param {number} m + */ +var BookMyShow = function(n, m) { + this.n = n; + this.m = m; + + let size = 1; + while (size < n * 2) { + size <<= 1; + } + this.segmentTree = new Array(size).fill(0).map(() => [0, 0]); + + this.build(0, 0, n - 1); +}; + +/** + * @param {number} k + * @param {number} maxRow + * @return {number[]} + */ +BookMyShow.prototype.gather = function(k, maxRow) { + const result = this.queryMax(0, 0, this.n - 1, k, maxRow); + if (result.length) { + this.updateMax(0, 0, this.n - 1, result[0], k); + } + return result; +}; + +/** + * @param {number} k + * @param {number} maxRow + * @return {boolean} + */ +BookMyShow.prototype.scatter = function(k, maxRow) { + const totalAvailable = this.querySum(0, 0, this.n - 1, maxRow); + const canScatter = totalAvailable >= k; + if (canScatter) { + this.updateSum(0, 0, this.n - 1, k, maxRow); + } + return canScatter; +}; + +/** + * @param {number} index + * @param {number} left + * @param {number} right + */ +BookMyShow.prototype.build = function(index, left, right) { + if (left === right) { + this.segmentTree[index] = [this.m, this.m]; + return; + } + const mid = Math.floor((left + right) / 2); + this.segmentTree[index] = [this.m, (right - left + 1) * this.m]; + this.build(2 * index + 1, left, mid); + this.build(2 * index + 2, mid + 1, right); +}; + +/** + * @param {number} index + * @param {number} left + * @param {number} right + * @param {number} k + * @param {number} maxRow + * @return {number[]} + */ +BookMyShow.prototype.queryMax = function(index, left, right, k, maxRow) { + if (left > maxRow) return []; + if (this.segmentTree[index][0] < k) return []; + if (left === right) { + return [left, this.m - this.segmentTree[index][0]]; + } + + const mid = Math.floor((left + right) / 2); + const leftResult = this.queryMax(2 * index + 1, left, mid, k, maxRow); + if (leftResult.length) return leftResult; + return this.queryMax(2 * index + 2, mid + 1, right, k, maxRow); +}; + +/** + * @param {number} index + * @param {number} left + * @param {number} right + * @param {number} row + * @param {number} k + */ +BookMyShow.prototype.updateMax = function(index, left, right, row, k) { + if (left > row || right < row) return; + if (left === right) { + this.segmentTree[index][0] -= k; + this.segmentTree[index][1] -= k; + return; + } + + const mid = Math.floor((left + right) / 2); + this.segmentTree[index][1] -= k; + this.updateMax(2 * index + 1, left, mid, row, k); + this.updateMax(2 * index + 2, mid + 1, right, row, k); + this.segmentTree[index][0] = Math.max( + this.segmentTree[2 * index + 1][0], + this.segmentTree[2 * index + 2][0] + ); +}; + +/** + * @param {number} index + * @param {number} left + * @param {number} right + * @param {number} maxRow + * @return {number} + */ +BookMyShow.prototype.querySum = function(index, left, right, maxRow) { + if (left > maxRow) return 0; + if (right <= maxRow) return this.segmentTree[index][1]; + + const mid = Math.floor((left + right) / 2); + return this.querySum(2 * index + 1, left, mid, maxRow) + + this.querySum(2 * index + 2, mid + 1, right, maxRow); +}; + +/** + * @param {number} index + * @param {number} left + * @param {number} right + * @param {number} k + * @param {number} maxRow + */ +BookMyShow.prototype.updateSum = function(index, left, right, k, maxRow) { + if (left > maxRow) return; + if (left === right) { + this.segmentTree[index][0] -= k; + this.segmentTree[index][1] -= k; + return; + } + + const mid = Math.floor((left + right) / 2); + this.segmentTree[index][1] -= k; + + if (mid + 1 > maxRow || this.segmentTree[2 * index + 1][1] >= k) { + this.updateSum(2 * index + 1, left, mid, k, maxRow); + } else { + const leftSum = this.segmentTree[2 * index + 1][1]; + this.updateSum(2 * index + 1, left, mid, leftSum, maxRow); + this.updateSum(2 * index + 2, mid + 1, right, k - leftSum, maxRow); + } + + this.segmentTree[index][0] = Math.max( + this.segmentTree[2 * index + 1][0], + this.segmentTree[2 * index + 2][0] + ); +}; diff --git a/solutions/2289-steps-to-make-array-non-decreasing.js b/solutions/2289-steps-to-make-array-non-decreasing.js new file mode 100644 index 00000000..8556f9a2 --- /dev/null +++ b/solutions/2289-steps-to-make-array-non-decreasing.js @@ -0,0 +1,32 @@ +/** + * 2289. Steps to Make Array Non-decreasing + * https://leetcode.com/problems/steps-to-make-array-non-decreasing/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums. In one step, remove all elements nums[i] + * where nums[i - 1] > nums[i] for all 0 < i < nums.length. + * + * Return the number of steps performed until nums becomes a non-decreasing array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var totalSteps = function(nums) { + const n = nums.length; + const stack = []; + const steps = new Array(n).fill(0); + let result = 0; + + for (let i = n - 1; i >= 0; i--) { + while (stack.length && nums[i] > nums[stack[stack.length - 1]]) { + const j = stack.pop(); + steps[i] = Math.max(steps[i] + 1, steps[j]); + } + result = Math.max(result, steps[i]); + stack.push(i); + } + + return result; +}; diff --git a/solutions/2290-minimum-obstacle-removal-to-reach-corner.js b/solutions/2290-minimum-obstacle-removal-to-reach-corner.js new file mode 100644 index 00000000..c1559b8d --- /dev/null +++ b/solutions/2290-minimum-obstacle-removal-to-reach-corner.js @@ -0,0 +1,60 @@ +/** + * 2290. Minimum Obstacle Removal to Reach Corner + * https://leetcode.com/problems/minimum-obstacle-removal-to-reach-corner/ + * Difficulty: Hard + * + * You are given a 0-indexed 2D integer array grid of size m x n. Each cell has one of two values: + * - 0 represents an empty cell, + * - 1 represents an obstacle that may be removed. + * + * You can move up, down, left, or right from and to an empty cell. + * + * Return the minimum number of obstacles to remove so you can move from the upper left corner + * (0, 0) to the lower right corner (m - 1, n - 1). + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var minimumObstacles = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const directions = [[0, 1], [0, -1], [1, 0], [-1, 0]]; + const dp = new Array(rows).fill().map(() => new Array(cols).fill(Number.MAX_SAFE_INTEGER)); + const queue = [[0, 0, 0]]; + let result = rows * cols + 1; + + while (queue.length > 0) { + const levelSize = queue.length; + for (let l = 0; l < levelSize; l++) { + const [i, j, cost] = queue.shift(); + + if (i === rows - 1 && j === cols - 1) { + result = Math.min(result, cost); + continue; + } + + if (cost > dp[i][j]) { + continue; + } + + for (const [dx, dy] of directions) { + const newI = i + dx; + const newJ = j + dy; + + if (isValid(newI, newJ, cost)) { + queue.push([newI, newJ, dp[newI][newJ]]); + } + } + } + } + + return result; + + function isValid(i, j, cost) { + const valid = i >= 0 && j >= 0 && i < rows && j < cols && dp[i][j] > cost + grid[i][j]; + if (valid) dp[i][j] = cost + grid[i][j]; + return valid; + } +}; diff --git a/solutions/2291-maximum-profit-from-trading-stocks.js b/solutions/2291-maximum-profit-from-trading-stocks.js new file mode 100644 index 00000000..5104bb18 --- /dev/null +++ b/solutions/2291-maximum-profit-from-trading-stocks.js @@ -0,0 +1,35 @@ +/** + * 2291. Maximum Profit From Trading Stocks + * https://leetcode.com/problems/maximum-profit-from-trading-stocks/ + * Difficulty: Medium + * + * You are given two 0-indexed integer arrays of the same length present and future where + * present[i] is the current price of the ith stock and future[i] is the price of the ith + * stock a year in the future. You may buy each stock at most once. You are also given an + * integer budget representing the amount of money you currently have. + * + * Return the maximum amount of profit you can make. + */ + +/** + * @param {number[]} present + * @param {number[]} future + * @param {number} budget + * @return {number} + */ +var maximumProfit = function(present, future, budget) { + const stocks = present.map((price, i) => ({ + cost: price, + profit: future[i] - price + })).filter(stock => stock.profit > 0) + .sort((a, b) => b.profit - a.profit); + + const dp = new Array(budget + 1).fill(0); + for (const stock of stocks) { + for (let money = budget; money >= stock.cost; money--) { + dp[money] = Math.max(dp[money], dp[money - stock.cost] + stock.profit); + } + } + + return dp[budget]; +}; diff --git a/solutions/2297-jump-game-viii.js b/solutions/2297-jump-game-viii.js new file mode 100644 index 00000000..954e9614 --- /dev/null +++ b/solutions/2297-jump-game-viii.js @@ -0,0 +1,47 @@ +/** + * 2297. Jump Game VIII + * https://leetcode.com/problems/jump-game-viii/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums of length n. You are initially standing at index 0. + * You can jump from index i to index j where i < j if: + * - nums[i] <= nums[j] and nums[k] < nums[i] for all indexes k in the range i < k < j, or + * - nums[i] > nums[j] and nums[k] >= nums[i] for all indexes k in the range i < k < j. + * + * You are also given an integer array costs of length n where costs[i] denotes the cost of jumping + * to index i. + * + * Return the minimum cost to jump to the index n - 1. + */ + +/** + * @param {number[]} nums + * @param {number[]} costs + * @return {number} + */ +var minCost = function(nums, costs) { + const n = nums.length; + const dp = new Array(n).fill(Infinity); + dp[0] = 0; + + const increasingStack = []; + const decreasingStack = []; + for (let i = 0; i < n; i++) { + while (increasingStack.length > 0 + && nums[increasingStack[increasingStack.length - 1]] > nums[i]) { + const j = increasingStack.pop(); + dp[i] = Math.min(dp[i], dp[j] + costs[i]); + } + + while (decreasingStack.length > 0 + && nums[decreasingStack[decreasingStack.length - 1]] <= nums[i]) { + const j = decreasingStack.pop(); + dp[i] = Math.min(dp[i], dp[j] + costs[i]); + } + + increasingStack.push(i); + decreasingStack.push(i); + } + + return dp[n - 1]; +}; diff --git a/solutions/2307-check-for-contradictions-in-equations.js b/solutions/2307-check-for-contradictions-in-equations.js new file mode 100644 index 00000000..56509a5c --- /dev/null +++ b/solutions/2307-check-for-contradictions-in-equations.js @@ -0,0 +1,62 @@ +/** + * 2307. Check for Contradictions in Equations + * https://leetcode.com/problems/check-for-contradictions-in-equations/ + * Difficulty: Hard + * + * You are given a 2D array of strings equations and an array of real numbers values, where + * equations[i] = [Ai, Bi] and values[i] means that Ai / Bi = values[i]. + * + * Determine if there exists a contradiction in the equations. Return true if there is a + * contradiction, or false otherwise. + * + * Note: + * - When checking if two numbers are equal, check that their absolute difference is less than 10-5. + * - The testcases are generated such that there are no cases targeting precision, i.e. using double + * is enough to solve the problem. + */ + +/** + * @param {string[][]} equations + * @param {number[]} values + * @return {boolean} + */ +var checkContradictions = function(equations, values) { + const graph = new Map(); + + for (let i = 0; i < equations.length; i++) { + const [a, b] = equations[i]; + const value = values[i]; + + const existingValue = dfs(a, b, new Set(), 1); + + if (existingValue !== null && Math.abs(existingValue - value) >= 1e-5) { + return true; + } + + addEdge(a, b, value); + } + + return false; + + function addEdge(a, b, value) { + if (!graph.has(a)) graph.set(a, []); + if (!graph.has(b)) graph.set(b, []); + graph.get(a).push([b, value]); + graph.get(b).push([a, 1 / value]); + } + + function dfs(start, target, visited, currentValue) { + if (start === target) return currentValue; + if (visited.has(start)) return null; + + visited.add(start); + + for (const [neighbor, value] of graph.get(start) || []) { + const result = dfs(neighbor, target, visited, currentValue * value); + if (result !== null) return result; + } + + visited.delete(start); + return null; + } +}; diff --git a/solutions/2310-sum-of-numbers-with-units-digit-k.js b/solutions/2310-sum-of-numbers-with-units-digit-k.js new file mode 100644 index 00000000..edf6abeb --- /dev/null +++ b/solutions/2310-sum-of-numbers-with-units-digit-k.js @@ -0,0 +1,33 @@ +/** + * 2310. Sum of Numbers With Units Digit K + * https://leetcode.com/problems/sum-of-numbers-with-units-digit-k/ + * Difficulty: Medium + * + * Given two integers num and k, consider a set of positive integers with the following properties: + * - The units digit of each integer is k. + * - The sum of the integers is num. + * + * Return the minimum possible size of such a set, or -1 if no such set exists. + * + * Note: + * - The set can contain multiple instances of the same integer, and the sum of an empty set is + * considered 0. + * - The units digit of a number is the rightmost digit of the number. + */ + +/** + * @param {number} num + * @param {number} k + * @return {number} + */ +var minimumNumbers = function(num, k) { + if (num === 0) return 0; + + for (let count = 1; count <= 10; count++) { + if ((count * k) % 10 === num % 10 && count * k <= num) { + return count; + } + } + + return -1; +}; diff --git a/solutions/2311-longest-binary-subsequence-less-than-or-equal-to-k.js b/solutions/2311-longest-binary-subsequence-less-than-or-equal-to-k.js new file mode 100644 index 00000000..b9a6e646 --- /dev/null +++ b/solutions/2311-longest-binary-subsequence-less-than-or-equal-to-k.js @@ -0,0 +1,44 @@ +/** + * 2311. Longest Binary Subsequence Less Than or Equal to K + * https://leetcode.com/problems/longest-binary-subsequence-less-than-or-equal-to-k/ + * Difficulty: Medium + * + * You are given a binary string s and a positive integer k. + * + * Return the length of the longest subsequence of s that makes up a binary number less than + * or equal to k. + * + * Note: + * - The subsequence can contain leading zeroes. + * - The empty string is considered to be equal to 0. + * - A subsequence is a string that can be derived from another string by deleting some or no + * characters without changing the order of the remaining characters. + */ + +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +var longestSubsequence = function(s, k) { + let zeros = 0; + let ones = 0; + let value = 0; + let power = 1; + + for (let i = s.length - 1; i >= 0; i--) { + if (s[i] === '0') { + zeros++; + } else { + if (power <= k && value + power <= k) { + value += power; + ones++; + } + } + if (power <= k) { + power *= 2; + } + } + + return zeros + ones; +}; diff --git a/solutions/2313-minimum-flips-in-binary-tree-to-get-result.js b/solutions/2313-minimum-flips-in-binary-tree-to-get-result.js new file mode 100644 index 00000000..fc759975 --- /dev/null +++ b/solutions/2313-minimum-flips-in-binary-tree-to-get-result.js @@ -0,0 +1,85 @@ +/** + * 2313. Minimum Flips in Binary Tree to Get Result + * https://leetcode.com/problems/minimum-flips-in-binary-tree-to-get-result/ + * Difficulty: Hard + * + * You are given the root of a binary tree with the following properties: + * - Leaf nodes have either the value 0 or 1, representing false and true respectively. + * - Non-leaf nodes have either the value 2, 3, 4, or 5, representing the boolean operations + * OR, AND, XOR, and NOT, respectively. + * + * You are also given a boolean result, which is the desired result of the evaluation of the + * root node. + * + * The evaluation of a node is as follows: + * - If the node is a leaf node, the evaluation is the value of the node, i.e. true or false. + * - Otherwise, evaluate the node's children and apply the boolean operation of its value with + * the children's evaluations. + * + * In one operation, you can flip a leaf node, which causes a false node to become true, and + * a true node to become false. + * + * Return the minimum number of operations that need to be performed such that the evaluation + * of root yields result. It can be shown that there is always a way to achieve result. + * + * A leaf node is a node that has zero children. + * + * Note: NOT nodes have either a left child or a right child, but other non-leaf nodes have both + * a left child and a right child. + */ + +/** + * 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 {boolean} result + * @return {number} + */ +var minimumFlips = function(root, result) { + const [trueFlips, falseFlips] = dfs(root); + return result ? trueFlips : falseFlips; + + function dfs(node) { + if (node.val === 0) { + return [1, 0]; + } + if (node.val === 1) { + return [0, 1]; + } + + if (node.val === 5) { + const [t, f] = dfs(node.left || node.right); + return [f, t]; + } + + const [leftTrue, leftFalse] = dfs(node.left); + const [rightTrue, rightFalse] = dfs(node.right); + + if (node.val === 2) { + return [ + Math.min(leftTrue + rightTrue, leftFalse + rightTrue, leftTrue + rightFalse), + leftFalse + rightFalse + ]; + } + + if (node.val === 3) { + return [ + leftTrue + rightTrue, + Math.min(leftTrue + rightFalse, leftFalse + rightTrue, leftFalse + rightFalse) + ]; + } + + if (node.val === 4) { + return [ + Math.min(leftFalse + rightTrue, leftTrue + rightFalse), + Math.min(leftTrue + rightTrue, leftFalse + rightFalse) + ]; + } + } +}; diff --git a/solutions/2323-find-minimum-time-to-finish-all-jobs-ii.js b/solutions/2323-find-minimum-time-to-finish-all-jobs-ii.js new file mode 100644 index 00000000..b9b17bac --- /dev/null +++ b/solutions/2323-find-minimum-time-to-finish-all-jobs-ii.js @@ -0,0 +1,32 @@ +/** + * 2323. Find Minimum Time to Finish All Jobs II + * https://leetcode.com/problems/find-minimum-time-to-finish-all-jobs-ii/ + * Difficulty: Medium + * + * You are given two 0-indexed integer arrays jobs and workers of equal length, where jobs[i] + * is the amount of time needed to complete the ith job, and workers[j] is the amount of time + * the jth worker can work each day. + * + * Each job should be assigned to exactly one worker, such that each worker completes exactly + * one job. + * + * Return the minimum number of days needed to complete all the jobs after assignment. + */ + +/** + * @param {number[]} jobs + * @param {number[]} workers + * @return {number} + */ +var minimumTime = function(jobs, workers) { + jobs.sort((a, b) => b - a); + workers.sort((a, b) => b - a); + + let result = 0; + for (let i = 0; i < jobs.length; i++) { + const daysNeeded = Math.ceil(jobs[i] / workers[i]); + result = Math.max(result, daysNeeded); + } + + return result; +}; diff --git a/solutions/2327-number-of-people-aware-of-a-secret.js b/solutions/2327-number-of-people-aware-of-a-secret.js new file mode 100644 index 00000000..513c9eaf --- /dev/null +++ b/solutions/2327-number-of-people-aware-of-a-secret.js @@ -0,0 +1,43 @@ +/** + * 2327. Number of People Aware of a Secret + * https://leetcode.com/problems/number-of-people-aware-of-a-secret/ + * Difficulty: Medium + * + * On day 1, one person discovers a secret. + * + * You are given an integer delay, which means that each person will share the secret with a new + * person every day, starting from delay days after discovering the secret. You are also given + * an integer forget, which means that each person will forget the secret forget days after + * discovering it. A person cannot share the secret on the same day they forgot it, or on any + * day afterwards. + * + * Given an integer n, return the number of people who know the secret at the end of day n. + * Since the answer may be very large, return it modulo 109 + 7. + */ + +/** + * @param {number} n + * @param {number} delay + * @param {number} forget + * @return {number} + */ +var peopleAwareOfSecret = function(n, delay, forget) { + const MOD = 1e9 + 7; + const dp = new Array(n + 1).fill(0); + dp[1] = 1; + + for (let day = 1; day <= n; day++) { + if (dp[day] === 0) continue; + + for (let shareDay = day + delay; shareDay < day + forget && shareDay <= n; shareDay++) { + dp[shareDay] = (dp[shareDay] + dp[day]) % MOD; + } + } + + let result = 0; + for (let day = Math.max(1, n - forget + 1); day <= n; day++) { + result = (result + dp[day]) % MOD; + } + + return result; +}; diff --git a/solutions/2330-valid-palindrome-iv.js b/solutions/2330-valid-palindrome-iv.js new file mode 100644 index 00000000..bce33766 --- /dev/null +++ b/solutions/2330-valid-palindrome-iv.js @@ -0,0 +1,28 @@ +/** + * 2330. Valid Palindrome IV + * https://leetcode.com/problems/valid-palindrome-iv/ + * Difficulty: Medium + * + * You are given a 0-indexed string s consisting of only lowercase English letters. + * In one operation, you can change any character of s to any other character. + * + * Return true if you can make s a palindrome after performing exactly one or two + * operations, or return false otherwise. + */ + +/** + * @param {string} s + * @return {boolean} + */ +var makePalindrome = function(s) { + const n = s.length; + let mismatches = 0; + + for (let i = 0; i < Math.floor(n / 2); i++) { + if (s[i] !== s[n - 1 - i]) { + mismatches++; + } + } + + return mismatches <= 2; +}; diff --git a/solutions/2332-the-latest-time-to-catch-a-bus.js b/solutions/2332-the-latest-time-to-catch-a-bus.js new file mode 100644 index 00000000..2354e722 --- /dev/null +++ b/solutions/2332-the-latest-time-to-catch-a-bus.js @@ -0,0 +1,64 @@ +/** + * 2332. The Latest Time to Catch a Bus + * https://leetcode.com/problems/the-latest-time-to-catch-a-bus/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array buses of length n, where buses[i] represents the + * departure time of the ith bus. You are also given a 0-indexed integer array passengers of + * length m, where passengers[j] represents the arrival time of the jth passenger. All bus + * departure times are unique. All passenger arrival times are unique. + * + * You are given an integer capacity, which represents the maximum number of passengers that + * can get on each bus. + * + * When a passenger arrives, they will wait in line for the next available bus. You can get + * on a bus that departs at x minutes if you arrive at y minutes where y <= x, and the bus + * is not full. Passengers with the earliest arrival times get on the bus first. + * + * More formally when a bus arrives, either: + * - If capacity or fewer passengers are waiting for a bus, they will all get on the bus, or + * - The capacity passengers with the earliest arrival times will get on the bus. + * + * Return the latest time you may arrive at the bus station to catch a bus. You cannot arrive + * at the same time as another passenger. + * + * Note: The arrays buses and passengers are not necessarily sorted. + */ + +/** + * @param {number[]} buses + * @param {number[]} passengers + * @param {number} capacity + * @return {number} + */ +var latestTimeCatchTheBus = function(buses, passengers, capacity) { + buses.sort((a, b) => a - b); + passengers.sort((a, b) => a - b); + + let passengerIndex = 0; + let lastBusPassengers = []; + for (const busTime of buses) { + const currentBusPassengers = []; + + while (passengerIndex < passengers.length && passengers[passengerIndex] <= busTime + && currentBusPassengers.length < capacity) { + currentBusPassengers.push(passengers[passengerIndex]); + passengerIndex++; + } + + lastBusPassengers = currentBusPassengers; + } + + const lastBusTime = buses[buses.length - 1]; + let latestTime = lastBusTime; + if (lastBusPassengers.length === capacity) { + latestTime = lastBusPassengers[lastBusPassengers.length - 1] - 1; + } + + const passengerSet = new Set(passengers); + while (passengerSet.has(latestTime)) { + latestTime--; + } + + return latestTime; +}; diff --git a/solutions/2333-minimum-sum-of-squared-difference.js b/solutions/2333-minimum-sum-of-squared-difference.js new file mode 100644 index 00000000..4616d586 --- /dev/null +++ b/solutions/2333-minimum-sum-of-squared-difference.js @@ -0,0 +1,84 @@ +/** + * 2333. Minimum Sum of Squared Difference + * https://leetcode.com/problems/minimum-sum-of-squared-difference/ + * Difficulty: Medium + * + * You are given two positive 0-indexed integer arrays nums1 and nums2, both of length n. + * + * The sum of squared difference of arrays nums1 and nums2 is defined as the sum of + * (nums1[i] - nums2[i])2 for each 0 <= i < n. + * + * You are also given two positive integers k1 and k2. You can modify any of the elements + * of nums1 by +1 or -1 at most k1 times. Similarly, you can modify any of the elements + * of nums2 by +1 or -1 at most k2 times. + * + * Return the minimum sum of squared difference after modifying array nums1 at most k1 + * times and modifying array nums2 at most k2 times. + * + * Note: You are allowed to modify the array elements to become negative integers. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @param {number} k1 + * @param {number} k2 + * @return {number} + */ +var minSumSquareDiff = function(nums1, nums2, k1, k2) { + const n = nums1.length; + const frequencyMap = new Map(); + + for (let i = 0; i < n; i++) { + const diff = Math.abs(nums1[i] - nums2[i]); + frequencyMap.set(diff, (frequencyMap.get(diff) || 0) + 1); + } + + let totalMoves = k1 + k2; + const maxHeap = new PriorityQueue((a, b) => b[0] - a[0]); + + for (const [value, count] of frequencyMap) { + if (value === 0) continue; + maxHeap.enqueue([value, count]); + } + + while (!maxHeap.isEmpty() && totalMoves > 0) { + const [value, count] = maxHeap.dequeue(); + + if (maxHeap.isEmpty()) { + const moves = Math.min(totalMoves, count); + totalMoves -= moves; + const remainingCount = count - moves; + + if (value - 1 > 0) { + maxHeap.enqueue([value - 1, moves]); + } + if (remainingCount > 0) { + maxHeap.enqueue([value, remainingCount]); + } + } else { + const moves = Math.min(totalMoves, count); + totalMoves -= moves; + const remainingCount = count - moves; + + if (remainingCount > 0) { + maxHeap.enqueue([value, remainingCount]); + } + + if (!maxHeap.isEmpty() && maxHeap.front()[0] === value - 1) { + const [nextValue, nextCount] = maxHeap.dequeue(); + maxHeap.enqueue([nextValue, nextCount + moves]); + } else if (value - 1 > 0) { + maxHeap.enqueue([value - 1, moves]); + } + } + } + + let result = 0; + while (!maxHeap.isEmpty()) { + const [value, count] = maxHeap.dequeue(); + result += value * value * count; + } + + return result; +}; diff --git a/solutions/2335-minimum-amount-of-time-to-fill-cups.js b/solutions/2335-minimum-amount-of-time-to-fill-cups.js new file mode 100644 index 00000000..e808dd25 --- /dev/null +++ b/solutions/2335-minimum-amount-of-time-to-fill-cups.js @@ -0,0 +1,21 @@ +/** + * 2335. Minimum Amount of Time to Fill Cups + * https://leetcode.com/problems/minimum-amount-of-time-to-fill-cups/ + * Difficulty: Easy + * + * You have a water dispenser that can dispense cold, warm, and hot water. Every second, you + * can either fill up 2 cups with different types of water, or 1 cup of any type of water. + * + * You are given a 0-indexed integer array amount of length 3 where amount[0], amount[1], and + * amount[2] denote the number of cold, warm, and hot water cups you need to fill respectively. + * Return the minimum number of seconds needed to fill up all the cups. + */ + +/** + * @param {number[]} amount + * @return {number} + */ +var fillCups = function(amount) { + const [a, b, c] = amount.sort((x, y) => y - x); + return Math.max(a, Math.ceil((a + b + c) / 2)); +}; diff --git a/solutions/2340-minimum-adjacent-swaps-to-make-a-valid-array.js b/solutions/2340-minimum-adjacent-swaps-to-make-a-valid-array.js new file mode 100644 index 00000000..99f4bf4a --- /dev/null +++ b/solutions/2340-minimum-adjacent-swaps-to-make-a-valid-array.js @@ -0,0 +1,38 @@ +/** + * 2340. Minimum Adjacent Swaps to Make a Valid Array + * https://leetcode.com/problems/minimum-adjacent-swaps-to-make-a-valid-array/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums. + * + * Swaps of adjacent elements are able to be performed on nums. + * + * A valid array meets the following conditions: + * - The largest element (any of the largest elements if there are multiple) is at the rightmost + * position in the array. + * - The smallest element (any of the smallest elements if there are multiple) is at the leftmost + * position in the array. + * + * Return the minimum swaps required to make nums a valid array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumSwaps = function(nums) { + const n = nums.length; + if (n === 1) return 0; + + const minValue = Math.min(...nums); + const maxValue = Math.max(...nums); + const minIndex = nums.indexOf(minValue); + const maxIndex = nums.lastIndexOf(maxValue); + let result = minIndex + (n - 1 - maxIndex); + + if (minIndex > maxIndex) { + result -= 1; + } + + return result; +}; diff --git a/solutions/2343-query-kth-smallest-trimmed-number.js b/solutions/2343-query-kth-smallest-trimmed-number.js new file mode 100644 index 00000000..1af6705b --- /dev/null +++ b/solutions/2343-query-kth-smallest-trimmed-number.js @@ -0,0 +1,61 @@ +/** + * 2343. Query Kth Smallest Trimmed Number + * https://leetcode.com/problems/query-kth-smallest-trimmed-number/ + * Difficulty: Medium + * + * You are given a 0-indexed array of strings nums, where each string is of equal length + * and consists of only digits. + * + * You are also given a 0-indexed 2D integer array queries where queries[i] = [ki, trimi]. + * For each queries[i], you need to: + * - Trim each number in nums to its rightmost trimi digits. + * - Determine the index of the kith smallest trimmed number in nums. If two trimmed numbers + * are equal, the number with the lower index is considered to be smaller. + * - Reset each number in nums to its original length. + * + * Return an array answer of the same length as queries, where answer[i] is the answer to + * the ith query. + * + * Note: + * - To trim to the rightmost x digits means to keep removing the leftmost digit, until only + * x digits remain. + * - Strings in nums may contain leading zeros. + */ + +/** + * @param {string[]} nums + * @param {number[][]} queries + * @return {number[]} + */ +var smallestTrimmedNumbers = function(nums, queries) { + if (nums.length === 0) return []; + + const result = []; + const stringLength = nums[0].length; + let startIndex = 0; + + const maxHeap = new PriorityQueue((a, b) => { + for (let i = startIndex; i < stringLength; i++) { + if (nums[a].charAt(i) !== nums[b].charAt(i)) { + return nums[b].charAt(i).charCodeAt(0) - nums[a].charAt(i).charCodeAt(0); + } + } + return b - a; + }); + + for (let i = 0; i < queries.length; i++) { + startIndex = stringLength - queries[i][1]; + maxHeap.clear(); + + for (let j = 0; j < nums.length; j++) { + maxHeap.enqueue(j); + if (maxHeap.size() > queries[i][0]) { + maxHeap.dequeue(); + } + } + + result[i] = maxHeap.dequeue(); + } + + return result; +}; diff --git a/solutions/2344-minimum-deletions-to-make-array-divisible.js b/solutions/2344-minimum-deletions-to-make-array-divisible.js new file mode 100644 index 00000000..1d5ab870 --- /dev/null +++ b/solutions/2344-minimum-deletions-to-make-array-divisible.js @@ -0,0 +1,35 @@ +/** + * 2344. Minimum Deletions to Make Array Divisible + * https://leetcode.com/problems/minimum-deletions-to-make-array-divisible/ + * Difficulty: Hard + * + * You are given two positive integer arrays nums and numsDivide. You can delete any number + * of elements from nums. + * + * Return the minimum number of deletions such that the smallest element in nums divides + * all the elements of numsDivide. If this is not possible, return -1. + * + * Note that an integer x divides y if y % x == 0. + */ + +/** + * @param {number[]} nums + * @param {number[]} numsDivide + * @return {number} + */ +var minOperations = function(nums, numsDivide) { + const targetGcd = numsDivide.reduce(gcd); + nums.sort((a, b) => a - b); + + for (let i = 0; i < nums.length; i++) { + if (targetGcd % nums[i] === 0) { + return i; + } + } + + return -1; + + function gcd(a, b) { + return b === 0 ? a : gcd(b, a % b); + } +}; diff --git a/solutions/2345-finding-the-number-of-visible-mountains.js b/solutions/2345-finding-the-number-of-visible-mountains.js new file mode 100644 index 00000000..a382483f --- /dev/null +++ b/solutions/2345-finding-the-number-of-visible-mountains.js @@ -0,0 +1,50 @@ +/** + * 2345. Finding the Number of Visible Mountains + * https://leetcode.com/problems/finding-the-number-of-visible-mountains/ + * Difficulty: Medium + * + * You are given a 0-indexed 2D integer array peaks where peaks[i] = [xi, yi] states that mountain + * i has a peak at coordinates (xi, yi). A mountain can be described as a right-angled isosceles + * triangle, with its base along the x-axis and a right angle at its peak. More formally, the + * gradients of ascending and descending the mountain are 1 and -1 respectively. + * + * A mountain is considered visible if its peak does not lie within another mountain (including + * the border of other mountains). + * + * Return the number of visible mountains. + */ + +/** + * @param {number[][]} peaks + * @return {number} + */ +var visibleMountains = function(peaks) { + const n = peaks.length; + + peaks.sort((a, b) => { + const leftA = a[0] - a[1]; + const leftB = b[0] - b[1]; + if (leftA === leftB) { + return (b[0] + b[1]) - (a[0] + a[1]); + } + return leftA - leftB; + }); + + let result = 0; + let maxEnd = -Infinity; + + for (let i = 0; i < n; i++) { + const [x, y] = peaks[i]; + const rightIntercept = x + y; + + if (rightIntercept > maxEnd) { + maxEnd = rightIntercept; + if (i < n - 1 && peaks[i][0] === peaks[i + 1][0] && peaks[i][1] === peaks[i + 1][1]) { + continue; + } + result++; + } + } + + return result; +}; diff --git a/solutions/2353-design-a-food-rating-system.js b/solutions/2353-design-a-food-rating-system.js new file mode 100644 index 00000000..e2e03f94 --- /dev/null +++ b/solutions/2353-design-a-food-rating-system.js @@ -0,0 +1,82 @@ +/** + * 2353. Design a Food Rating System + * https://leetcode.com/problems/design-a-food-rating-system/ + * Difficulty: Medium + * + * Design a food rating system that can do the following: + * - Modify the rating of a food item listed in the system. + * - Return the highest-rated food item for a type of cuisine in the system. + * + * Implement the FoodRatings class: + * - FoodRatings(String[] foods, String[] cuisines, int[] ratings) Initializes the system. + * The food items are described by foods, cuisines and ratings, all of which have a length + * of n. + * - foods[i] is the name of the ith food, + * - cuisines[i] is the type of cuisine of the ith food, and + * - ratings[i] is the initial rating of the ith food. + * - void changeRating(String food, int newRating) Changes the rating of the food item with + * the name food. + * - String highestRated(String cuisine) Returns the name of the food item that has the + * highest rating for the given type of cuisine. If there is a tie, return the item with + * the lexicographically smaller name. + * + * Note that a string x is lexicographically smaller than string y if x comes before y in + * dictionary order, that is, either x is a prefix of y, or if i is the first position such + * that x[i] != y[i], then x[i] comes before y[i] in alphabetic order. + */ + +/** + * @param {string[]} foods + * @param {string[]} cuisines + * @param {number[]} ratings + */ +var FoodRatings = function(foods, cuisines, ratings) { + this.foodToCuisine = new Map(); + this.foodToRating = new Map(); + this.cuisineToFoods = new Map(); + + for (let i = 0; i < foods.length; i++) { + const food = foods[i]; + const cuisine = cuisines[i]; + const rating = ratings[i]; + + this.foodToCuisine.set(food, cuisine); + this.foodToRating.set(food, rating); + + if (!this.cuisineToFoods.has(cuisine)) { + this.cuisineToFoods.set(cuisine, new PriorityQueue((a, b) => { + if (a.rating !== b.rating) return b.rating - a.rating; + return a.food.localeCompare(b.food); + })); + } + + this.cuisineToFoods.get(cuisine).enqueue({ food, rating }); + } +}; + +/** + * @param {string} food + * @param {number} newRating + * @return {void} + */ +FoodRatings.prototype.changeRating = function(food, newRating) { + const cuisine = this.foodToCuisine.get(food); + this.foodToRating.set(food, newRating); + this.cuisineToFoods.get(cuisine).enqueue({ food, rating: newRating }); +}; + +/** + * @param {string} cuisine + * @return {string} + */ +FoodRatings.prototype.highestRated = function(cuisine) { + const heap = this.cuisineToFoods.get(cuisine); + + while (!heap.isEmpty()) { + const top = heap.front(); + if (this.foodToRating.get(top.food) === top.rating) { + return top.food; + } + heap.dequeue(); + } +}; diff --git a/solutions/2355-maximum-number-of-books-you-can-take.js b/solutions/2355-maximum-number-of-books-you-can-take.js new file mode 100644 index 00000000..f9e58b8a --- /dev/null +++ b/solutions/2355-maximum-number-of-books-you-can-take.js @@ -0,0 +1,44 @@ +/** + * 2355. Maximum Number of Books You Can Take + * https://leetcode.com/problems/maximum-number-of-books-you-can-take/ + * Difficulty: Hard + * + * You are given a 0-indexed integer array books of length n where books[i] denotes the number of + * books on the ith shelf of a bookshelf. + * + * You are going to take books from a contiguous section of the bookshelf spanning from l to r + * where 0 <= l <= r < n. For each index i in the range l <= i < r, you must take strictly fewer + * books from shelf i than shelf i + 1. + * + * Return the maximum number of books you can take from the bookshelf. + */ + +/** + * @param {number[]} books + * @return {number} + */ +var maximumBooks = function(books) { + const n = books.length; + const dp = new Array(n).fill(0); + const stack = []; + + for (let i = 0; i < n; i++) { + while (stack.length > 0 + && books[stack[stack.length - 1]] >= books[i] - (i - stack[stack.length - 1])) { + stack.pop(); + } + + if (stack.length === 0) { + const length = Math.min(i + 1, books[i]); + dp[i] = (length * (2 * books[i] - length + 1)) / 2; + } else { + const prevIndex = stack[stack.length - 1]; + const length = i - prevIndex; + dp[i] = dp[prevIndex] + (length * (2 * books[i] - length + 1)) / 2; + } + + stack.push(i); + } + + return Math.max(...dp); +}; diff --git a/solutions/2357-make-array-zero-by-subtracting-equal-amounts.js b/solutions/2357-make-array-zero-by-subtracting-equal-amounts.js new file mode 100644 index 00000000..63e08177 --- /dev/null +++ b/solutions/2357-make-array-zero-by-subtracting-equal-amounts.js @@ -0,0 +1,20 @@ +/** + * 2357. Make Array Zero by Subtracting Equal Amounts + * https://leetcode.com/problems/make-array-zero-by-subtracting-equal-amounts/ + * Difficulty: Easy + * + * You are given a non-negative integer array nums. In one operation, you must: + * - Choose a positive integer x such that x is less than or equal to the smallest + * non-zero element in nums. + * - Subtract x from every positive element in nums. + * + * Return the minimum number of operations to make every element in nums equal to 0. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumOperations = function(nums) { + return new Set(nums.filter(num => num > 0)).size; +}; diff --git a/solutions/2361-minimum-costs-using-the-train-line.js b/solutions/2361-minimum-costs-using-the-train-line.js new file mode 100644 index 00000000..9d4e569f --- /dev/null +++ b/solutions/2361-minimum-costs-using-the-train-line.js @@ -0,0 +1,51 @@ +/** + * 2361. Minimum Costs Using the Train Line + * https://leetcode.com/problems/minimum-costs-using-the-train-line/ + * Difficulty: Hard + * + * A train line going through a city has two routes, the regular route and the express route. + * Both routes go through the same n + 1 stops labeled from 0 to n. Initially, you start on + * the regular route at stop 0. + * + * You are given two 1-indexed integer arrays regular and express, both of length n. + * regular[i] describes the cost it takes to go from stop i - 1 to stop i using the regular + * route, and express[i] describes the cost it takes to go from stop i - 1 to stop i using + * the express route. + * + * You are also given an integer expressCost which represents the cost to transfer from the + * regular route to the express route. + * + * Note that: + * - There is no cost to transfer from the express route back to the regular route. + * - You pay expressCost every time you transfer from the regular route to the express route. + * - There is no extra cost to stay on the express route. + * + * Return a 1-indexed array costs of length n, where costs[i] is the minimum cost to reach + * stop i from stop 0. + * + * Note that a stop can be counted as reached from either route. + */ + +/** + * @param {number[]} regular + * @param {number[]} express + * @param {number} expressCost + * @return {number[]} + */ +var minimumCosts = function(regular, express, expressCost) { + const n = regular.length; + const result = new Array(n); + let regularDp = 0; + let expressDp = expressCost; + + for (let i = 1; i <= n; i++) { + const newRegularDp = Math.min(regularDp, expressDp) + regular[i - 1]; + const newExpressDp = Math.min(regularDp + expressCost, expressDp) + express[i - 1]; + + regularDp = newRegularDp; + expressDp = newExpressDp; + result[i - 1] = Math.min(regularDp, expressDp); + } + + return result; +}; diff --git a/solutions/2371-minimize-maximum-value-in-a-grid.js b/solutions/2371-minimize-maximum-value-in-a-grid.js new file mode 100644 index 00000000..832eafff --- /dev/null +++ b/solutions/2371-minimize-maximum-value-in-a-grid.js @@ -0,0 +1,52 @@ +/** + * 2371. Minimize Maximum Value in a Grid + * https://leetcode.com/problems/minimize-maximum-value-in-a-grid/ + * Difficulty: Hard + * + * You are given an m x n integer matrix grid containing distinct positive integers. + * + * You have to replace each integer in the matrix with a positive integer satisfying the + * following conditions: + * - The relative order of every two elements that are in the same row or column should stay + * the same after the replacements. + * - The maximum number in the matrix after the replacements should be as small as possible. + * + * The relative order stays the same if for all pairs of elements in the original matrix such + * that grid[r1][c1] > grid[r2][c2] where either r1 == r2 or c1 == c2, then it must be true + * that grid[r1][c1] > grid[r2][c2] after the replacements. + * + * For example, if grid = [[2, 4, 5], [7, 3, 9]] then a good replacement could be either + * grid = [[1, 2, 3], [2, 1, 4]] or grid = [[1, 2, 3], [3, 1, 4]]. + * + * Return the resulting matrix. If there are multiple answers, return any of them. + */ + +/** + * @param {number[][]} grid + * @return {number[][]} + */ +var minScore = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + + const positions = []; + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + positions.push([grid[i][j], i, j]); + } + } + + positions.sort((a, b) => a[0] - b[0]); + + const result = new Array(rows).fill().map(() => new Array(cols).fill(0)); + const rowMax = new Array(rows).fill(0); + const colMax = new Array(cols).fill(0); + for (const [value, row, col] of positions) { + const newValue = Math.max(rowMax[row], colMax[col]) + 1; + result[row][col] = newValue; + rowMax[row] = newValue; + colMax[col] = newValue; + } + + return result; +}; diff --git a/solutions/2376-count-special-integers.js b/solutions/2376-count-special-integers.js new file mode 100644 index 00000000..977b5730 --- /dev/null +++ b/solutions/2376-count-special-integers.js @@ -0,0 +1,47 @@ +/** + * 2376. Count Special Integers + * https://leetcode.com/problems/count-special-integers/ + * Difficulty: Hard + * + * We call a positive integer special if all of its digits are distinct. + * + * Given a positive integer n, return the number of special integers that belong to the + * interval [1, n]. + */ + +/** + * @param {number} n + * @return {number} + */ +var countSpecialNumbers = function(n) { + const digits = String(n).split('').map(Number); + const len = digits.length; + let total = 0; + + for (let i = 1; i < len; i++) { + let count = 9; + for (let j = 0; j < i - 1; j++) { + count *= (10 - j - 1); + } + total += count; + } + + const used = new Set(); + for (let i = 0; i < len; i++) { + for (let d = (i === 0 ? 1 : 0); d < digits[i]; d++) { + if (!used.has(d)) { + let count = 1; + for (let j = i + 1; j < len; j++) { + count *= (10 - used.size - (j - i)); + } + total += count; + } + } + if (used.has(digits[i]) || digits[i] === 0 && i === 0) break; + used.add(digits[i]); + } + + if (used.size === len) total++; + + return total; +}; diff --git a/solutions/2378-choose-edges-to-maximize-score-in-a-tree.js b/solutions/2378-choose-edges-to-maximize-score-in-a-tree.js new file mode 100644 index 00000000..a3fb4fde --- /dev/null +++ b/solutions/2378-choose-edges-to-maximize-score-in-a-tree.js @@ -0,0 +1,57 @@ +/** + * 2378. Choose Edges to Maximize Score in a Tree + * https://leetcode.com/problems/choose-edges-to-maximize-score-in-a-tree/ + * Difficulty: Medium + * + * You are given a weighted tree consisting of n nodes numbered from 0 to n - 1. + * + * The tree is rooted at node 0 and represented with a 2D array edges of size n where + * edges[i] = [pari, weighti] indicates that node pari is the parent of node i, and the + * edge between them has a weight equal to weighti. Since the root does not have a parent, + * you have edges[0] = [-1, -1]. + * + * Choose some edges from the tree such that no two chosen edges are adjacent and the sum + * of the weights of the chosen edges is maximized. + * + * Return the maximum sum of the chosen edges. + * + * Note: + * - You are allowed to not choose any edges in the tree, the sum of weights in this case will be 0. + * - Two edges Edge1 and Edge2 in the tree are adjacent if they have a common node. + * - In other words, they are adjacent if Edge1 connects nodes a and b and Edge2 connects nodes + * b and c. + */ + +/** + * @param {number[][]} edges + * @return {number} + */ +var maxScore = function(edges) { + const n = edges.length; + const children = new Array(n).fill().map(() => []); + let root = 0; + + for (let i = 0; i < n; i++) { + if (edges[i][0] >= 0) { + children[edges[i][0]].push([i, edges[i][1]]); + } else { + root = i; + } + } + + const [skipRoot, takeRoot] = dfs(root); + return Math.max(skipRoot, takeRoot); + + function dfs(node) { + let skip = 0; + let take = 0; + + for (const [child, weight] of children[node]) { + const [childSkip, childTake] = dfs(child); + skip += childTake; + take = Math.max(take, childSkip - childTake + weight); + } + + return [skip, take + skip]; + } +}; diff --git a/solutions/2384-largest-palindromic-number.js b/solutions/2384-largest-palindromic-number.js new file mode 100644 index 00000000..a06b86dc --- /dev/null +++ b/solutions/2384-largest-palindromic-number.js @@ -0,0 +1,50 @@ +/** + * 2384. Largest Palindromic Number + * https://leetcode.com/problems/largest-palindromic-number/ + * Difficulty: Medium + * + * You are given a string num consisting of digits only. + * + * Return the largest palindromic integer (in the form of a string) that can be formed + * using digits taken from num. It should not contain leading zeroes. + * + * Notes: + * - You do not need to use all the digits of num, but you must use at least one digit. + * - The digits can be reordered. + */ + +/** + * @param {string} num + * @return {string} + */ +var largestPalindromic = function(num) { + const digitCount = new Array(10).fill(0); + + for (const digit of num) { + digitCount[parseInt(digit, 10)]++; + } + + let leftHalf = ''; + let middle = ''; + for (let digit = 9; digit >= 0; digit--) { + const count = digitCount[digit]; + const pairs = Math.floor(count / 2); + + if (digit === 0 && leftHalf === '') { + continue; + } + + leftHalf += digit.toString().repeat(pairs); + + if (count % 2 === 1 && middle === '') { + middle = digit.toString(); + } + } + + if (leftHalf === '' && middle === '') { + return '0'; + } + + const rightHalf = leftHalf.split('').reverse().join(''); + return leftHalf + middle + rightHalf; +}; diff --git a/solutions/2386-find-the-k-sum-of-an-array.js b/solutions/2386-find-the-k-sum-of-an-array.js new file mode 100644 index 00000000..c3f49e46 --- /dev/null +++ b/solutions/2386-find-the-k-sum-of-an-array.js @@ -0,0 +1,42 @@ +/** + * 2386. Find the K-Sum of an Array + * https://leetcode.com/problems/find-the-k-sum-of-an-array/ + * Difficulty: Hard + * + * You are given an integer array nums and a positive integer k. You can choose any subsequence + * of the array and sum all of its elements together. + * + * We define the K-Sum of the array as the kth largest subsequence sum that can be obtained + * (not necessarily distinct). + * + * Return the K-Sum of the array. + * + * A subsequence is an array that can be derived from another array by deleting some or no elements + * without changing the order of the remaining elements. + * + * Note that the empty subsequence is considered to have a sum of 0. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var kSum = function(nums, k) { + const maxSum = nums.reduce((sum, num) => sum + Math.max(0, num), 0); + const absoluteNums = nums.map(num => Math.abs(num)).sort((a, b) => a - b); + const maxHeap = new PriorityQueue((a, b) => a[0] - b[0]); + maxHeap.enqueue([-maxSum + absoluteNums[0], 0]); + let nextSum = -maxSum; + + for (let iteration = 0; iteration < k - 1; iteration++) { + [nextSum, i] = maxHeap.dequeue(); + + if (i + 1 < absoluteNums.length) { + maxHeap.enqueue([nextSum - absoluteNums[i] + absoluteNums[i + 1], i + 1]); + maxHeap.enqueue([nextSum + absoluteNums[i + 1], i + 1]); + } + } + + return -nextSum; +}; diff --git a/solutions/2387-median-of-a-row-wise-sorted-matrix.js b/solutions/2387-median-of-a-row-wise-sorted-matrix.js new file mode 100644 index 00000000..485ba53b --- /dev/null +++ b/solutions/2387-median-of-a-row-wise-sorted-matrix.js @@ -0,0 +1,52 @@ +/** + * 2387. Median of a Row Wise Sorted Matrix + * https://leetcode.com/problems/median-of-a-row-wise-sorted-matrix/ + * Difficulty: Medium + * + * Given an m x n matrix grid containing an odd number of integers where each row is sorted + * in non-decreasing order, return the median of the matrix. + * + * You must solve the problem in less than O(m * n) time complexity. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var matrixMedian = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const totalElements = rows * cols; + const targetPosition = Math.floor(totalElements / 2) + 1; + let low = 0; + let high = 1000001; + + while (low < high) { + const mid = low + Math.floor((high - low) / 2); + if (helper(mid)) { + high = mid; + } else { + low = mid + 1; + } + } + + return high; + + function helper(target) { + let count = 0; + for (const row of grid) { + let left = 0; + let right = cols; + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (row[mid] <= target) { + left = mid + 1; + } else { + right = mid; + } + } + count += left; + } + return count >= targetPosition; + } +}; diff --git a/solutions/2393-count-strictly-increasing-subarrays.js b/solutions/2393-count-strictly-increasing-subarrays.js new file mode 100644 index 00000000..12f7bbe3 --- /dev/null +++ b/solutions/2393-count-strictly-increasing-subarrays.js @@ -0,0 +1,33 @@ +/** + * 2393. Count Strictly Increasing Subarrays + * https://leetcode.com/problems/count-strictly-increasing-subarrays/ + * Difficulty: Medium + * + * You are given an array nums consisting of positive integers. + * + * Return the number of subarrays of nums that are in strictly increasing order. + * + * A subarray is a contiguous part of an array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var countSubarrays = function(nums) { + let result = 0; + let currentLength = 1; + + for (let i = 1; i < nums.length; i++) { + if (nums[i] > nums[i - 1]) { + currentLength++; + } else { + result += (currentLength * (currentLength + 1)) / 2; + currentLength = 1; + } + } + + result += (currentLength * (currentLength + 1)) / 2; + + return result; +}; diff --git a/solutions/2398-maximum-number-of-robots-within-budget.js b/solutions/2398-maximum-number-of-robots-within-budget.js new file mode 100644 index 00000000..cdf88590 --- /dev/null +++ b/solutions/2398-maximum-number-of-robots-within-budget.js @@ -0,0 +1,57 @@ +/** + * 2398. Maximum Number of Robots Within Budget + * https://leetcode.com/problems/maximum-number-of-robots-within-budget/ + * Difficulty: Hard + * + * You have n robots. You are given two 0-indexed integer arrays, chargeTimes and runningCosts, + * both of length n. The ith robot costs chargeTimes[i] units to charge and costs runningCosts[i] + * units to run. You are also given an integer budget. + * + * The total cost of running k chosen robots is equal to max(chargeTimes) + k * sum(runningCosts), + * where max(chargeTimes) is the largest charge cost among the k robots and sum(runningCosts) is + * the sum of running costs among the k robots. + * + * Return the maximum number of consecutive robots you can run such that the total cost does not + * exceed budget. + */ + +/** + * @param {number[]} chargeTimes + * @param {number[]} runningCosts + * @param {number} budget + * @return {number} + */ +var maximumRobots = function(chargeTimes, runningCosts, budget) { + const n = chargeTimes.length; + let left = 0; + let result = 0; + let runningSum = 0; + const queue = []; + + for (let right = 0; right < n; right++) { + runningSum += runningCosts[right]; + + while (queue.length > 0 && chargeTimes[queue[queue.length - 1]] <= chargeTimes[right]) { + queue.pop(); + } + queue.push(right); + + while (left <= right) { + const maxCharge = chargeTimes[queue[0]]; + const totalCost = maxCharge + (right - left + 1) * runningSum; + + if (totalCost <= budget) { + result = Math.max(result, right - left + 1); + break; + } + + if (queue[0] === left) { + queue.shift(); + } + runningSum -= runningCosts[left]; + left++; + } + } + + return result; +}; diff --git a/solutions/2400-number-of-ways-to-reach-a-position-after-exactly-k-steps.js b/solutions/2400-number-of-ways-to-reach-a-position-after-exactly-k-steps.js new file mode 100644 index 00000000..fa0c7186 --- /dev/null +++ b/solutions/2400-number-of-ways-to-reach-a-position-after-exactly-k-steps.js @@ -0,0 +1,49 @@ +/** + * 2400. Number of Ways to Reach a Position After Exactly k Steps + * https://leetcode.com/problems/number-of-ways-to-reach-a-position-after-exactly-k-steps/ + * Difficulty: Medium + * + * You are given two positive integers startPos and endPos. Initially, you are standing at + * position startPos on an infinite number line. With one step, you can move either one position + * to the left, or one position to the right. + * + * Given a positive integer k, return the number of different ways to reach the position endPos + * starting from startPos, such that you perform exactly k steps. Since the answer may be very + * large, return it modulo 109 + 7. + * + * Two ways are considered different if the order of the steps made is not exactly the same. + * + * Note that the number line includes negative integers. + */ + +/** + * @param {number} startPos + * @param {number} endPos + * @param {number} k + * @return {number} + */ +var numberOfWays = function(startPos, endPos, k) { + const MOD = 1e9 + 7; + const dp = new Array(3000).fill().map(() => new Array(k + 1).fill(-1)); + + return helper(startPos, endPos, k); + + function helper(currentPos, targetPos, remainingSteps) { + if (currentPos === targetPos && remainingSteps === 0) { + return 1; + } + if (remainingSteps === 0) { + return 0; + } + + const dpIndex = currentPos + 1000; + if (dp[dpIndex][remainingSteps] !== -1) { + return dp[dpIndex][remainingSteps]; + } + const leftMove = helper(currentPos - 1, targetPos, remainingSteps - 1); + const rightMove = helper(currentPos + 1, targetPos, remainingSteps - 1); + + dp[dpIndex][remainingSteps] = (leftMove + rightMove) % MOD; + return dp[dpIndex][remainingSteps]; + } +}; diff --git a/solutions/2402-meeting-rooms-iii.js b/solutions/2402-meeting-rooms-iii.js new file mode 100644 index 00000000..1be391aa --- /dev/null +++ b/solutions/2402-meeting-rooms-iii.js @@ -0,0 +1,66 @@ +/** + * 2402. Meeting Rooms III + * https://leetcode.com/problems/meeting-rooms-iii/ + * Difficulty: Hard + * + * You are given an integer n. There are n rooms numbered from 0 to n - 1. + * + * You are given a 2D integer array meetings where meetings[i] = [starti, endi] means that + * a meeting will be held during the half-closed time interval [starti, endi). All the values + * of starti are unique. + * + * Meetings are allocated to rooms in the following manner: + * 1. Each meeting will take place in the unused room with the lowest number. + * 2. If there are no available rooms, the meeting will be delayed until a room becomes free. + * The delayed meeting should have the same duration as the original meeting. + * 3. When a room becomes unused, meetings that have an earlier original start time should be + * given the room. + * + * Return the number of the room that held the most meetings. If there are multiple rooms, + * return the room with the lowest number. + * + * A half-closed interval [a, b) is the interval between a and b including a and not including b. + */ + +/** + * @param {number} n + * @param {number[][]} meetings + * @return {number} + */ +var mostBooked = function(n, meetings) { + meetings.sort((a, b) => a[0] - b[0]); + + const roomCount = new Array(n).fill(0); + const availableRooms = []; + const occupiedRooms = []; + for (let i = 0; i < n; i++) { + availableRooms.push(i); + } + + for (const [start, end] of meetings) { + while (occupiedRooms.length > 0 && occupiedRooms[0][0] <= start) { + const [endTime, roomNumber] = occupiedRooms.shift(); + availableRooms.push(roomNumber); + availableRooms.sort((a, b) => a - b); + } + + let assignedRoom; + let meetingEnd; + + if (availableRooms.length > 0) { + assignedRoom = availableRooms.shift(); + meetingEnd = end; + } else { + const [earliestEndTime, roomNumber] = occupiedRooms.shift(); + assignedRoom = roomNumber; + meetingEnd = earliestEndTime + (end - start); + } + + roomCount[assignedRoom]++; + occupiedRooms.push([meetingEnd, assignedRoom]); + occupiedRooms.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]); + } + + const maxMeetings = Math.max(...roomCount); + return roomCount.indexOf(maxMeetings); +}; diff --git a/solutions/2403-minimum-time-to-kill-all-monsters.js b/solutions/2403-minimum-time-to-kill-all-monsters.js new file mode 100644 index 00000000..2f4a0644 --- /dev/null +++ b/solutions/2403-minimum-time-to-kill-all-monsters.js @@ -0,0 +1,48 @@ +/** + * 2403. Minimum Time to Kill All Monsters + * https://leetcode.com/problems/minimum-time-to-kill-all-monsters/ + * Difficulty: Hard + * + * You are given an integer array power where power[i] is the power of the ith monster. + * + * You start with 0 mana points, and each day you increase your mana points by gain where gain + * initially is equal to 1. + * + * Each day, after gaining gain mana, you can defeat a monster if your mana points are greater + * than or equal to the power of that monster. When you defeat a monster: + * - your mana points will be reset to 0, and + * - the value of gain increases by 1. + * + * Return the minimum number of days needed to defeat all the monsters. + */ + +/** + * @param {number[]} power + * @return {number} + */ +var minimumTime = function(power) { + const n = power.length; + const map = new Map(); + + return dp(0, 1); + + function dp(mask, gain) { + if (mask === (1 << n) - 1) return 0; + + const key = `${mask}_${gain}`; + if (map.has(key)) return map.get(key); + + let minDays = Infinity; + + for (let i = 0; i < n; i++) { + if (!(mask & (1 << i))) { + const daysNeeded = Math.ceil(power[i] / gain); + const totalDays = daysNeeded + dp(mask | (1 << i), gain + 1); + minDays = Math.min(minDays, totalDays); + } + } + + map.set(key, minDays); + return minDays; + } +}; diff --git a/solutions/2406-divide-intervals-into-minimum-number-of-groups.js b/solutions/2406-divide-intervals-into-minimum-number-of-groups.js new file mode 100644 index 00000000..60b50fb3 --- /dev/null +++ b/solutions/2406-divide-intervals-into-minimum-number-of-groups.js @@ -0,0 +1,39 @@ +/** + * 2406. Divide Intervals Into Minimum Number of Groups + * https://leetcode.com/problems/divide-intervals-into-minimum-number-of-groups/ + * Difficulty: Medium + * + * You are given a 2D integer array intervals where intervals[i] = [lefti, righti] represents + * the inclusive interval [lefti, righti]. + * + * You have to divide the intervals into one or more groups such that each interval is in + * exactly one group, and no two intervals that are in the same group intersect each other. + * + * Return the minimum number of groups you need to make. + * + * Two intervals intersect if there is at least one common number between them. For example, + * the intervals [1, 5] and [5, 8] intersect. + */ + +/** + * @param {number[][]} intervals + * @return {number} + */ +var minGroups = function(intervals) { + const events = []; + for (const [start, end] of intervals) { + events.push([start, 1]); + events.push([end + 1, -1]); + } + + events.sort((a, b) => a[0] === b[0] ? a[1] - b[1] : a[0] - b[0]); + + let activeIntervals = 0; + let result = 0; + for (const [time, change] of events) { + activeIntervals += change; + result = Math.max(result, activeIntervals); + } + + return result; +}; diff --git a/solutions/2407-longest-increasing-subsequence-ii.js b/solutions/2407-longest-increasing-subsequence-ii.js new file mode 100644 index 00000000..d30f3ae8 --- /dev/null +++ b/solutions/2407-longest-increasing-subsequence-ii.js @@ -0,0 +1,65 @@ +/** + * 2407. Longest Increasing Subsequence II + * https://leetcode.com/problems/longest-increasing-subsequence-ii/ + * Difficulty: Hard + * + * You are given an integer array nums and an integer k. + * + * Find the longest subsequence of nums that meets the following requirements: + * - The subsequence is strictly increasing and + * - The difference between adjacent elements in the subsequence is at most k. + * + * Return the length of the longest subsequence that meets the requirements. + * + * A subsequence is an array that can be derived from another array by deleting some or + * no elements without changing the order of the remaining elements. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var lengthOfLIS = function(nums, k) { + const maxValue = Math.max(...nums); + const tree = new Array(4 * maxValue).fill(0); + + for (const currentNum of nums) { + const rangeStart = Math.max(1, currentNum - k); + const rangeEnd = currentNum - 1; + + const bestPreviousLength = rangeEnd >= rangeStart + ? queryRange(1, 1, maxValue, rangeStart, rangeEnd) : 0; + updatePosition(1, 1, maxValue, currentNum, bestPreviousLength + 1); + } + + return queryRange(1, 1, maxValue, 1, maxValue); + + function updatePosition(nodeIndex, treeStart, treeEnd, position, newLength) { + if (treeStart === treeEnd) { + tree[nodeIndex] = Math.max(tree[nodeIndex], newLength); + } else { + const treeMid = Math.floor((treeStart + treeEnd) / 2); + if (position <= treeMid) { + updatePosition(2 * nodeIndex, treeStart, treeMid, position, newLength); + } else { + updatePosition(2 * nodeIndex + 1, treeMid + 1, treeEnd, position, newLength); + } + tree[nodeIndex] = Math.max(tree[2 * nodeIndex], tree[2 * nodeIndex + 1]); + } + } + + function queryRange(nodeIndex, treeStart, treeEnd, queryStart, queryEnd) { + if (queryEnd < treeStart || treeEnd < queryStart) { + return 0; + } + if (queryStart <= treeStart && treeEnd <= queryEnd) { + return tree[nodeIndex]; + } + const mid = Math.floor((treeStart + treeEnd) / 2); + return Math.max( + queryRange(2 * nodeIndex, treeStart, mid, queryStart, queryEnd), + queryRange(2 * nodeIndex + 1, mid + 1, treeEnd, queryStart, queryEnd) + ); + } +}; diff --git a/solutions/2408-design-sql.js b/solutions/2408-design-sql.js new file mode 100644 index 00000000..371e1b87 --- /dev/null +++ b/solutions/2408-design-sql.js @@ -0,0 +1,116 @@ +/** + * 2408. Design SQL + * https://leetcode.com/problems/design-sql/ + * Difficulty: Medium + * + * You are given two string arrays, names and columns, both of size n. The ith table is represented + * by the name names[i] and contains columns[i] number of columns. + * + * You need to implement a class that supports the following operations: + * - Insert a row in a specific table with an id assigned using an auto-increment method, where the + * id of the first inserted row is 1, and the id of each new row inserted into the same table is + * one greater than the id of the last inserted row, even if the last row was removed. + * - Remove a row from a specific table. Removing a row does not affect the id of the next inserted + * row. + * - Select a specific cell from any table and return its value. + * - Export all rows from any table in csv format. + * + * Implement the SQL class: + * - SQL(String[] names, int[] columns) + * - Creates the n tables. + * - bool ins(String name, String[] row) + * - Inserts row into the table name and returns true. + * - If row.length does not match the expected number of columns, or name is not a valid table, + * returns false without any insertion. + * - void rmv(String name, int rowId) + * - Removes the row rowId from the table name. + * - If name is not a valid table or there is no row with id rowId, no removal is performed. + * - String sel(String name, int rowId, int columnId) + * - Returns the value of the cell at the specified rowId and columnId in the table name. + * - If name is not a valid table, or the cell (rowId, columnId) is invalid, returns "". + * - String[] exp(String name) + * - Returns the rows present in the table name. + * - If name is not a valid table, returns an empty array. Each row is represented as a string, + * with each cell value (including the row's id) separated by a ",". + */ + +/** + * @param {string[]} names + * @param {number[]} columns + */ +var SQL = function(names, columns) { + this.tables = new Map(); + this.nextRowIds = new Map(); + + for (let i = 0; i < names.length; i++) { + this.tables.set(names[i], { + columns: columns[i], + rows: new Map() + }); + this.nextRowIds.set(names[i], 1); + } +}; + +/** + * @param {string} name + * @param {string[]} row + * @return {boolean} + */ +SQL.prototype.ins = function(name, row) { + if (!this.tables.has(name)) return false; + + const table = this.tables.get(name); + if (row.length !== table.columns) return false; + + const rowId = this.nextRowIds.get(name); + table.rows.set(rowId, row); + this.nextRowIds.set(name, rowId + 1); + + return true; +}; + +/** + * @param {string} name + * @param {number} rowId + * @return {void} + */ +SQL.prototype.rmv = function(name, rowId) { + if (!this.tables.has(name)) return; + + const table = this.tables.get(name); + table.rows.delete(rowId); +}; + +/** + * @param {string} name + * @param {number} rowId + * @param {number} columnId + * @return {string} + */ +SQL.prototype.sel = function(name, rowId, columnId) { + if (!this.tables.has(name)) return ''; + + const table = this.tables.get(name); + if (!table.rows.has(rowId) || columnId < 1 || columnId > table.columns) { + return ''; + } + + return table.rows.get(rowId)[columnId - 1]; +}; + +/** + * @param {string} name + * @return {string[]} + */ +SQL.prototype.exp = function(name) { + if (!this.tables.has(name)) return []; + + const table = this.tables.get(name); + const result = []; + + for (const [rowId, row] of table.rows) { + result.push(`${rowId},${row.join(',')}`); + } + + return result; +}; diff --git a/solutions/2417-closest-fair-integer.js b/solutions/2417-closest-fair-integer.js new file mode 100644 index 00000000..d478b184 --- /dev/null +++ b/solutions/2417-closest-fair-integer.js @@ -0,0 +1,45 @@ +/** + * 2417. Closest Fair Integer + * https://leetcode.com/problems/closest-fair-integer/ + * Difficulty: Medium + * + * You are given a positive integer n. + * + * We call an integer k fair if the number of even digits in k is equal to the number of + * odd digits in it. + * + * Return the smallest fair integer that is greater than or equal to n. + */ + +/** + * @param {number} n + * @return {number} + */ +var closestFair = function(n) { + const digitCount = n.toString().length; + if (digitCount % 2 === 1) { + return smallestFairNumberWithLength(digitCount + 1); + } + + return hasEqualEvenOddDigits(n) ? n : closestFair(n + 1); + + function hasEqualEvenOddDigits(num) { + const counts = [0, 0]; + while (num > 0) { + counts[(num % 10) % 2]++; + num = Math.floor(num / 10); + } + return counts[0] === counts[1]; + } + + function smallestFairNumberWithLength(length) { + let result = '1'; + for (let i = 1; i <= length / 2; i++) { + result += '0'; + } + for (let i = length / 2 + 1; i < length; i++) { + result += '1'; + } + return parseInt(result); + } +}; diff --git a/solutions/2420-find-all-good-indices.js b/solutions/2420-find-all-good-indices.js new file mode 100644 index 00000000..e3216e6e --- /dev/null +++ b/solutions/2420-find-all-good-indices.js @@ -0,0 +1,42 @@ +/** + * 2420. Find All Good Indices + * https://leetcode.com/problems/find-all-good-indices/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums of size n and a positive integer k. + * + * We call an index i in the range k <= i < n - k good if the following conditions are satisfied: + * - The k elements that are just before the index i are in non-increasing order. + * - The k elements that are just after the index i are in non-decreasing order. + * + * Return an array of all good indices sorted in increasing order. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number[]} + */ +var goodIndices = function(nums, k) { + const n = nums.length; + const nonIncreasing = new Array(n).fill(1); + const nonDecreasing = new Array(n).fill(1); + const result = []; + + for (let i = 1; i < n; i++) { + if (nums[i - 1] >= nums[i]) { + nonIncreasing[i] = nonIncreasing[i - 1] + 1; + } + if (nums[n - i] >= nums[n - i - 1]) { + nonDecreasing[n - i - 1] = nonDecreasing[n - i] + 1; + } + } + + for (let i = k; i < n - k; i++) { + if (nonIncreasing[i - 1] >= k && nonDecreasing[i + 1] >= k) { + result.push(i); + } + } + + return result; +}; diff --git a/solutions/2422-merge-operations-to-turn-array-into-a-palindrome.js b/solutions/2422-merge-operations-to-turn-array-into-a-palindrome.js new file mode 100644 index 00000000..ea3946c6 --- /dev/null +++ b/solutions/2422-merge-operations-to-turn-array-into-a-palindrome.js @@ -0,0 +1,46 @@ +/** + * 2422. Merge Operations to Turn Array Into a Palindrome + * https://leetcode.com/problems/merge-operations-to-turn-array-into-a-palindrome/ + * Difficulty: Medium + * + * You are given an array nums consisting of positive integers. + * + * You can perform the following operation on the array any number of times: + * - Choose any two adjacent elements and replace them with their sum. + * - For example, if nums = [1,2,3,1], you can apply one operation to make it [1,5,1]. + * + * Return the minimum number of operations needed to turn the array into a palindrome. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumOperations = function(nums) { + let left = 0; + let right = nums.length - 1; + let leftSum = nums[left]; + let rightSum = nums[right]; + let result = 0; + + while (left < right) { + if (leftSum === rightSum) { + left++; + right--; + if (left <= right) { + leftSum = nums[left]; + rightSum = nums[right]; + } + } else if (leftSum < rightSum) { + left++; + leftSum += nums[left]; + result++; + } else { + right--; + rightSum += nums[right]; + result++; + } + } + + return result; +}; diff --git a/solutions/2431-maximize-total-tastiness-of-purchased-fruits.js b/solutions/2431-maximize-total-tastiness-of-purchased-fruits.js new file mode 100644 index 00000000..5dab31aa --- /dev/null +++ b/solutions/2431-maximize-total-tastiness-of-purchased-fruits.js @@ -0,0 +1,67 @@ +/** + * 2431. Maximize Total Tastiness of Purchased Fruits + * https://leetcode.com/problems/maximize-total-tastiness-of-purchased-fruits/ + * Difficulty: Medium + * + * You are given two non-negative integer arrays price and tastiness, both arrays have the same + * length n. You are also given two non-negative integers maxAmount and maxCoupons. + * + * For every integer i in range [0, n - 1]: + * - price[i] describes the price of ith fruit. + * - tastiness[i] describes the tastiness of ith fruit. + * + * You want to purchase some fruits such that total tastiness is maximized and the total price + * does not exceed maxAmount. + * + * Additionally, you can use a coupon to purchase fruit for half of its price (rounded down to + * the closest integer). You can use at most maxCoupons of such coupons. + * + * Return the maximum total tastiness that can be purchased. + * + * Note that: + * - You can purchase each fruit at most once. + * - You can use coupons on some fruit at most once. + */ + +/** + * @param {number[]} price + * @param {number[]} tastiness + * @param {number} maxAmount + * @param {number} maxCoupons + * @return {number} + */ +var maxTastiness = function(price, tastiness, maxAmount, maxCoupons) { + const n = price.length; + const map = new Map(); + + return dp(0, maxAmount, maxCoupons); + + function dp(index, remainingAmount, remainingCoupons) { + if (index === n) return 0; + + const key = `${index}_${remainingAmount}_${remainingCoupons}`; + if (map.has(key)) return map.get(key); + + let maxValue = dp(index + 1, remainingAmount, remainingCoupons); + + if (price[index] <= remainingAmount) { + maxValue = Math.max( + maxValue, + tastiness[index] + dp(index + 1, remainingAmount - price[index], remainingCoupons) + ); + } + + if (remainingCoupons > 0) { + const discountedPrice = Math.floor(price[index] / 2); + if (discountedPrice <= remainingAmount) { + maxValue = Math.max( + maxValue, + tastiness[index] + dp(index + 1, remainingAmount - discountedPrice, remainingCoupons - 1) + ); + } + } + + map.set(key, maxValue); + return maxValue; + } +}; diff --git a/solutions/2436-minimum-split-into-subarrays-with-gcd-greater-than-one.js b/solutions/2436-minimum-split-into-subarrays-with-gcd-greater-than-one.js new file mode 100644 index 00000000..c0410d87 --- /dev/null +++ b/solutions/2436-minimum-split-into-subarrays-with-gcd-greater-than-one.js @@ -0,0 +1,49 @@ +/** + * 2436. Minimum Split Into Subarrays With GCD Greater Than One + * https://leetcode.com/problems/minimum-split-into-subarrays-with-gcd-greater-than-one/ + * Difficulty: Medium + * + * You are given an array nums consisting of positive integers. + * + * Split the array into one or more disjoint subarrays such that: + * - Each element of the array belongs to exactly one subarray, and + * - The GCD of the elements of each subarray is strictly greater than 1. + * + * Return the minimum number of subarrays that can be obtained after the split. + * + * Note that: + * - The GCD of a subarray is the largest positive integer that evenly divides all the elements + * of the subarray. + * - A subarray is a contiguous part of the array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumSplits = function(nums) { + const n = nums.length; + let result = 1; + let currentGcd = nums[0]; + + for (let i = 1; i < n; i++) { + const newGcd = gcd(currentGcd, nums[i]); + if (newGcd === 1) { + result++; + currentGcd = nums[i]; + } else { + currentGcd = newGcd; + } + } + + return result; + + function gcd(a, b) { + while (b !== 0) { + const temp = b; + b = a % b; + a = temp; + } + return a; + } +}; diff --git a/solutions/2445-number-of-nodes-with-value-one.js b/solutions/2445-number-of-nodes-with-value-one.js new file mode 100644 index 00000000..115d7dea --- /dev/null +++ b/solutions/2445-number-of-nodes-with-value-one.js @@ -0,0 +1,53 @@ +/** + * 2445. Number of Nodes With Value One + * https://leetcode.com/problems/number-of-nodes-with-value-one/ + * Difficulty: Medium + * + * There is an undirected connected tree with n nodes labeled from 1 to n and n - 1 edges. + * You are given the integer n. The parent node of a node with a label v is the node with + * the label floor (v / 2). The root of the tree is the node with the label 1. + * + * - For example, if n = 7, then the node with the label 3 has the node with the label + * floor(3 / 2) = 1 as its parent, and the node with the label 7 has the node with the + * label floor(7 / 2) = 3 as its parent. + * + * You are also given an integer array queries. Initially, every node has a value 0 on it. + * For each query queries[i], you should flip all values in the subtree of the node with + * the label queries[i]. + * + * Return the total number of nodes with the value 1 after processing all the queries. + * + * Note that: + * - Flipping the value of a node means that the node with the value 0 becomes 1 and vice versa. + * - floor(x) is equivalent to rounding x down to the nearest integer. + */ + +/** + * @param {number} n + * @param {number[]} queries + * @return {number} + */ +var numberOfNodes = function(n, queries) { + const flipCount = new Array(n + 1).fill(0); + + for (const query of queries) { + flipCount[query]++; + } + + let result = 0; + for (let i = 1; i <= n; i++) { + let totalFlips = 0; + let current = i; + + while (current >= 1) { + totalFlips += flipCount[current]; + current = Math.floor(current / 2); + } + + if (totalFlips % 2 === 1) { + result++; + } + } + + return result; +}; diff --git a/solutions/2450-number-of-distinct-binary-strings-after-applying-operations.js b/solutions/2450-number-of-distinct-binary-strings-after-applying-operations.js new file mode 100644 index 00000000..7db5d4be --- /dev/null +++ b/solutions/2450-number-of-distinct-binary-strings-after-applying-operations.js @@ -0,0 +1,39 @@ +/** + * 2450. Number of Distinct Binary Strings After Applying Operations + * https://leetcode.com/problems/number-of-distinct-binary-strings-after-applying-operations/ + * Difficulty: Medium + * + * You are given a binary string s and a positive integer k. + * + * You can apply the following operation on the string any number of times: + * - Choose any substring of size k from s and flip all its characters, that is, turn all 1's + * into 0's, and all 0's into 1's. + * - Return the number of distinct strings you can obtain. Since the answer may be too large, + * return it modulo 109 + 7. + * + * Note that: + * - A binary string is a string that consists only of the characters 0 and 1. + * - A substring is a contiguous part of a string. + */ + +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +var countDistinctStrings = function(s, k) { + if (s.length <= 0) { + return -1; + } + + const MOD = 1e9 + 7; + let n = s.length - k + 1; + let result = 1; + + while (n > 0) { + result = (result << 1) % MOD; + n--; + } + + return result; +}; diff --git a/solutions/2456-most-popular-video-creator.js b/solutions/2456-most-popular-video-creator.js new file mode 100644 index 00000000..e41632d8 --- /dev/null +++ b/solutions/2456-most-popular-video-creator.js @@ -0,0 +1,67 @@ +/** + * 2456. Most Popular Video Creator + * https://leetcode.com/problems/most-popular-video-creator/ + * Difficulty: Medium + * + * You are given two string arrays creators and ids, and an integer array views, all of length n. + * The ith video on a platform was created by creators[i], has an id of ids[i], and has views[i] + * views. + * + * The popularity of a creator is the sum of the number of views on all of the creator's videos. + * Find the creator with the highest popularity and the id of their most viewed video. + * - If multiple creators have the highest popularity, find all of them. + * - If multiple videos have the highest view count for a creator, find the lexicographically + * smallest id. + * + * Note: It is possible for different videos to have the same id, meaning that ids do not uniquely + * identify a video. For example, two videos with the same ID are considered as distinct videos + * with their own viewcount. + * + * Return a 2D array of strings answer where answer[i] = [creatorsi, idi] means that creatorsi + * has the highest popularity and idi is the id of their most popular video. The answer can be + * returned in any order. + */ + +/** + * @param {string[]} creators + * @param {string[]} ids + * @param {number[]} views + * @return {string[][]} + */ +var mostPopularCreator = function(creators, ids, views) { + const map = new Map(); + + for (let i = 0; i < creators.length; i++) { + const creator = creators[i]; + const videoId = ids[i]; + const videoViews = views[i]; + + if (!map.has(creator)) { + map.set(creator, { + totalViews: 0, + mostViewedCount: -1, + mostViewedId: '' + }); + } + + const stats = map.get(creator); + stats.totalViews += videoViews; + + if (videoViews > stats.mostViewedCount || (videoViews === stats.mostViewedCount + && videoId < stats.mostViewedId)) { + stats.mostViewedCount = videoViews; + stats.mostViewedId = videoId; + } + } + + const maxViews = Math.max(...Array.from(map.values()).map(s => s.totalViews)); + + const result = []; + for (const [creator, stats] of map) { + if (stats.totalViews === maxViews) { + result.push([creator, stats.mostViewedId]); + } + } + + return result; +}; diff --git a/solutions/2459-sort-array-by-moving-items-to-empty-space.js b/solutions/2459-sort-array-by-moving-items-to-empty-space.js new file mode 100644 index 00000000..ee27aa25 --- /dev/null +++ b/solutions/2459-sort-array-by-moving-items-to-empty-space.js @@ -0,0 +1,61 @@ +/** + * 2459. Sort Array by Moving Items to Empty Space + * https://leetcode.com/problems/sort-array-by-moving-items-to-empty-space/ + * Difficulty: Hard + * + * You are given an integer array nums of size n containing each element from 0 to n - 1 + * (inclusive). Each of the elements from 1 to n - 1 represents an item, and the element + * 0 represents an empty space. + * + * In one operation, you can move any item to the empty space. nums is considered to be sorted + * if the numbers of all the items are in ascending order and the empty space is either at the + * beginning or at the end of the array. + * + * For example, if n = 4, nums is sorted if: + * - nums = [0,1,2,3] or + * - nums = [1,2,3,0] + * + * ...and considered to be unsorted otherwise. + * + * Return the minimum number of operations needed to sort nums. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var sortArray = function(nums) { + const n = nums.length; + const positions = new Array(n); + + for (let i = 0; i < n; i++) { + positions[nums[i]] = i; + } + + return Math.min( + permute([...positions], 0), + permute([...positions], 1) + ); + + function permute(pos, shift) { + let count = 0; + let next = 1; + + while (next < n) { + if (pos[0] === shift * (n - 1)) { + while (pos[next] === next - shift) { + next++; + if (next === n) return count; + } + var targetIndex = next; + } else { + var targetIndex = pos[0] + shift; + } + + [pos[0], pos[targetIndex]] = [pos[targetIndex], pos[0]]; + count++; + } + + return count; + } +}; diff --git a/solutions/2464-minimum-subarrays-in-a-valid-split.js b/solutions/2464-minimum-subarrays-in-a-valid-split.js new file mode 100644 index 00000000..fa16bd70 --- /dev/null +++ b/solutions/2464-minimum-subarrays-in-a-valid-split.js @@ -0,0 +1,51 @@ +/** + * 2464. Minimum Subarrays in a Valid Split + * https://leetcode.com/problems/minimum-subarrays-in-a-valid-split/ + * Difficulty: Medium + * + * You are given an integer array nums. + * + * Splitting of an integer array nums into subarrays is valid if: + * - the greatest common divisor of the first and last elements of each subarray is + * greater than 1, and + * - each element of nums belongs to exactly one subarray. + * + * Return the minimum number of subarrays in a valid subarray splitting of nums. + * If a valid subarray splitting is not possible, return -1. + * + * Note that: + * - The greatest common divisor of two numbers is the largest positive integer that + * evenly divides both numbers. + * - A subarray is a contiguous non-empty part of an array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var validSubarraySplit = function(nums) { + const n = nums.length; + const dp = new Array(n + 1).fill(Infinity); + dp[0] = 0; + + for (let i = 0; i < n; i++) { + if (dp[i] === Infinity) continue; + + for (let j = i; j < n; j++) { + if (gcd(nums[i], nums[j]) > 1) { + dp[j + 1] = Math.min(dp[j + 1], dp[i] + 1); + } + } + } + + return dp[n] === Infinity ? -1 : dp[n]; + + function gcd(a, b) { + while (b !== 0) { + const temp = b; + b = a % b; + a = temp; + } + return a; + } +}; diff --git a/solutions/2470-number-of-subarrays-with-lcm-equal-to-k.js b/solutions/2470-number-of-subarrays-with-lcm-equal-to-k.js new file mode 100644 index 00000000..41edda1d --- /dev/null +++ b/solutions/2470-number-of-subarrays-with-lcm-equal-to-k.js @@ -0,0 +1,45 @@ +/** + * 2470. Number of Subarrays With LCM Equal to K + * https://leetcode.com/problems/number-of-subarrays-with-lcm-equal-to-k/ + * Difficulty: Medium + * + * Given an integer array nums and an integer k, return the number of subarrays of nums + * where the least common multiple of the subarray's elements is k. + * + * A subarray is a contiguous non-empty sequence of elements within an array. + * + * The least common multiple of an array is the smallest positive integer that is divisible + * by all the array elements. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var subarrayLCM = function(nums, k) { + let count = 0; + + for (let start = 0; start < nums.length; start++) { + let currentLCM = nums[start]; + for (let end = start; end < nums.length; end++) { + currentLCM = lcm(currentLCM, nums[end]); + if (currentLCM > k) break; + if (currentLCM === k) count++; + } + } + + return count; + + function gcd(a, b) { + while (b) { + a %= b; + [a, b] = [b, a]; + } + return a; + } + + function lcm(a, b) { + return (a * b) / gcd(a, b); + } +}; diff --git a/solutions/2473-minimum-cost-to-buy-apples.js b/solutions/2473-minimum-cost-to-buy-apples.js new file mode 100644 index 00000000..ce8700b3 --- /dev/null +++ b/solutions/2473-minimum-cost-to-buy-apples.js @@ -0,0 +1,67 @@ +/** + * 2473. Minimum Cost to Buy Apples + * https://leetcode.com/problems/minimum-cost-to-buy-apples/ + * Difficulty: Medium + * + * You are given a positive integer n representing n cities numbered from 1 to n. You are also + * given a 2D array roads, where roads[i] = [ai, bi, costi] indicates that there is a bidirectional + * road between cities ai and bi with a cost of traveling equal to costi. + * + * You can buy apples in any city you want, but some cities have different costs to buy apples. + * You are given the 1-based array appleCost where appleCost[i] is the cost of buying one apple + * from city i. + * + * You start at some city, traverse through various roads, and eventually buy exactly one apple + * from any city. After you buy that apple, you have to return back to the city you started at, + * but now the cost of all the roads will be multiplied by a given factor k. + * + * Given the integer k, return a 1-based array answer of size n where answer[i] is the minimum + * total cost to buy an apple if you start at city i. + */ + +/** + * @param {number} n + * @param {number[][]} roads + * @param {number[]} appleCost + * @param {number} k + * @return {number[]} + */ +var minCost = function(n, roads, appleCost, k) { + const graph = new Array(n).fill().map(() => []); + for (const [cityA, cityB, cost] of roads) { + graph[cityA - 1].push([cityB - 1, cost]); + graph[cityB - 1].push([cityA - 1, cost]); + } + + const result = new Array(n); + for (let startCity = 0; startCity < n; startCity++) { + result[startCity] = appleCost[startCity]; + } + + const heap = []; + for (let startCity = 0; startCity < n; startCity++) { + heap.push([appleCost[startCity], startCity]); + } + heap.sort((a, b) => a[0] - b[0]); + + while (heap.length > 0) { + const [totalCost, currCity] = heap.shift(); + + if (result[currCity] < totalCost) continue; + + for (const [neighbor, cost] of graph[currCity]) { + const newCost = result[currCity] + (k + 1) * cost; + if (result[neighbor] > newCost) { + result[neighbor] = newCost; + + let insertIndex = 0; + while (insertIndex < heap.length && heap[insertIndex][0] <= newCost) { + insertIndex++; + } + heap.splice(insertIndex, 0, [newCost, neighbor]); + } + } + } + + return result; +}; diff --git a/solutions/2479-maximum-xor-of-two-non-overlapping-subtrees.js b/solutions/2479-maximum-xor-of-two-non-overlapping-subtrees.js new file mode 100644 index 00000000..0d856990 --- /dev/null +++ b/solutions/2479-maximum-xor-of-two-non-overlapping-subtrees.js @@ -0,0 +1,112 @@ +/** + * 2479. Maximum XOR of Two Non-Overlapping Subtrees + * https://leetcode.com/problems/maximum-xor-of-two-non-overlapping-subtrees/ + * Difficulty: Hard + * + * There is an undirected tree with n nodes labeled from 0 to n - 1. You are given the integer + * n and a 2D integer array edges of length n - 1, where edges[i] = [ai, bi] indicates that + * there is an edge between nodes ai and bi in the tree. The root of the tree is the node labeled 0. + * + * Each node has an associated value. You are given an array values of length n, where values[i] + * is the value of the ith node. + * + * Select any two non-overlapping subtrees. Your score is the bitwise XOR of the sum of the + * values within those subtrees. + * + * Return the maximum possible score you can achieve. If it is impossible to find two + * nonoverlapping subtrees, return 0. + * + * Note that: + * - The subtree of a node is the tree consisting of that node and all of its descendants. + * - Two subtrees are non-overlapping if they do not share any common node. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number[]} values + * @return {number} + */ +var maxXor = function(n, edges, values) { + class TrieNode { + constructor() { + this.children = [null, null]; + } + } + + const graph = Array(n).fill().map(() => []); + for (const [u, v] of edges) { + graph[u].push(v); + graph[v].push(u); + } + + const subtreeSums = new Array(n); + + calculateSubtreeSum(0, -1); + const root = new TrieNode(); + + return Number(findMaxXor(0, -1, root)); + + function calculateSubtreeSum(node, parent) { + subtreeSums[node] = BigInt(values[node]); + for (const child of graph[node]) { + if (child !== parent) { + subtreeSums[node] += calculateSubtreeSum(child, node); + } + } + return subtreeSums[node]; + } + + function insert(root, value) { + let current = root; + for (let bit = 44; bit >= 0; bit--) { + const bitValue = (value >> BigInt(bit)) & 1n; + const index = Number(bitValue); + if (!current.children[index]) { + current.children[index] = new TrieNode(); + } + current = current.children[index]; + } + } + + function getMaxValue(root, currentValue) { + if (!root.children[0] && !root.children[1]) { + return 0n; + } + + let result = 0n; + let current = root; + + for (let bit = 44; bit >= 0; bit--) { + const currentBit = (currentValue >> BigInt(bit)) & 1n; + const wantedBit = 1n - currentBit; + const wantedIndex = Number(wantedBit); + const currentIndex = Number(currentBit); + + if (current.children[wantedIndex]) { + result += 1n << BigInt(bit); + current = current.children[wantedIndex]; + } else { + current = current.children[currentIndex]; + } + } + + return result; + } + + function findMaxXor(node, parent, root) { + let result = getMaxValue(root, subtreeSums[node]); + + for (const child of graph[node]) { + if (child !== parent) { + const childResult = findMaxXor(child, node, root); + if (childResult > result) { + result = childResult; + } + } + } + + insert(root, subtreeSums[node]); + return result; + } +}; diff --git a/solutions/2484-count-palindromic-subsequences.js b/solutions/2484-count-palindromic-subsequences.js new file mode 100644 index 00000000..a6c3851c --- /dev/null +++ b/solutions/2484-count-palindromic-subsequences.js @@ -0,0 +1,59 @@ +/** + * 2484. Count Palindromic Subsequences + * https://leetcode.com/problems/count-palindromic-subsequences/ + * Difficulty: Hard + * + * Given a string of digits s, return the number of palindromic subsequences of s having length 5. + * Since the answer may be very large, return it modulo 109 + 7. + * + * Note: + * - A string is palindromic if it reads the same forward and backward. + * - A subsequence is a string that can be derived from another string by deleting some or no + * characters without changing the order of the remaining characters. + */ + +/** + * @param {string} s + * @return {number} + */ +var countPalindromes = function(s) { + const MOD = 1e9 + 7; + const n = s.length; + + const prefixPairs = new Array(n).fill(0).map(() => new Array(100).fill(0)); + const suffixPairs = new Array(n).fill(0).map(() => new Array(100).fill(0)); + + for (let i = 1; i < n; i++) { + for (let pair = 0; pair < 100; pair++) { + prefixPairs[i][pair] = prefixPairs[i - 1][pair]; + } + for (let j = 0; j < i; j++) { + const pair = parseInt(s[j]) * 10 + parseInt(s[i]); + prefixPairs[i][pair]++; + } + } + + for (let i = n - 2; i >= 0; i--) { + for (let pair = 0; pair < 100; pair++) { + suffixPairs[i][pair] = suffixPairs[i + 1][pair]; + } + for (let j = i + 1; j < n; j++) { + const pair = parseInt(s[i]) * 10 + parseInt(s[j]); + suffixPairs[i][pair]++; + } + } + + let result = 0; + for (let i = 2; i < n - 2; i++) { + for (let first = 0; first < 10; first++) { + for (let second = 0; second < 10; second++) { + const leftPair = first * 10 + second; + const rightPair = second * 10 + first; + result = (result + (prefixPairs[i - 1][leftPair] + * suffixPairs[i + 1][rightPair]) % MOD) % MOD; + } + } + } + + return result; +}; diff --git a/solutions/2489-number-of-substrings-with-fixed-ratio.js b/solutions/2489-number-of-substrings-with-fixed-ratio.js new file mode 100644 index 00000000..4a5b9c2e --- /dev/null +++ b/solutions/2489-number-of-substrings-with-fixed-ratio.js @@ -0,0 +1,53 @@ +/** + * 2489. Number of Substrings With Fixed Ratio + * https://leetcode.com/problems/number-of-substrings-with-fixed-ratio/ + * Difficulty: Medium + * + * You are given a binary string s, and two integers num1 and num2. num1 and num2 are + * coprime numbers. + * + * A ratio substring is a substring of s where the ratio between the number of 0's and + * the number of 1's in the substring is exactly num1 : num2. + * - For example, if num1 = 2 and num2 = 3, then "01011" and "1110000111" are ratio substrings, + * while "11000" is not. + * + * Return the number of non-empty ratio substrings of s. + * + * Note that: + * - A substring is a contiguous sequence of characters within a string. + * - Two values x and y are coprime if gcd(x, y) == 1 where gcd(x, y) is the greatest common + * divisor of x and y. + */ + +/** + * @param {string} s + * @param {number} num1 + * @param {number} num2 + * @return {number} + */ +var fixedRatio = function(s, num1, num2) { + const n = s.length; + const map = new Map(); + map.set(0, 1); + + let zeros = 0; + let ones = 0; + let result = 0; + for (let i = 0; i < n; i++) { + if (s[i] === '0') { + zeros++; + } else { + ones++; + } + + const difference = ones * num1 - zeros * num2; + + if (map.has(difference)) { + result += map.get(difference); + } + + map.set(difference, (map.get(difference) || 0) + 1); + } + + return result; +}; diff --git a/solutions/2495-number-of-subarrays-having-even-product.js b/solutions/2495-number-of-subarrays-having-even-product.js new file mode 100644 index 00000000..a94af32b --- /dev/null +++ b/solutions/2495-number-of-subarrays-having-even-product.js @@ -0,0 +1,32 @@ +/** + * 2495. Number of Subarrays Having Even Product + * https://leetcode.com/problems/number-of-subarrays-having-even-product/ + * Difficulty: Medium + * + * Given a 0-indexed integer array nums, return the number of subarrays of nums having an + * even product. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var evenProduct = function(nums) { + const n = nums.length; + const totalSubarrays = (n * (n + 1)) / 2; + let oddProductSubarrays = 0; + let currentOddLength = 0; + + for (let i = 0; i < n; i++) { + if (nums[i] % 2 === 1) { + currentOddLength++; + } else { + oddProductSubarrays += (currentOddLength * (currentOddLength + 1)) / 2; + currentOddLength = 0; + } + } + + oddProductSubarrays += (currentOddLength * (currentOddLength + 1)) / 2; + + return totalSubarrays - oddProductSubarrays; +}; diff --git a/solutions/2500-delete-greatest-value-in-each-row.js b/solutions/2500-delete-greatest-value-in-each-row.js new file mode 100644 index 00000000..68f0164f --- /dev/null +++ b/solutions/2500-delete-greatest-value-in-each-row.js @@ -0,0 +1,38 @@ +/** + * 2500. Delete Greatest Value in Each Row + * https://leetcode.com/problems/delete-greatest-value-in-each-row/ + * Difficulty: Easy + * + * You are given an m x n matrix grid consisting of positive integers. + * + * Perform the following operation until grid becomes empty: + * - Delete the element with the greatest value from each row. If multiple such elements exist, + * delete any of them. + * - Add the maximum of deleted elements to the answer. + * + * Note that the number of columns decreases by one after each operation. + * + * Return the answer after performing the operations described above. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var deleteGreatestValue = function(grid) { + for (const row of grid) { + row.sort((a, b) => a - b); + } + + let result = 0; + const cols = grid[0].length; + for (let col = cols - 1; col >= 0; col--) { + let maxInColumn = 0; + for (let row = 0; row < grid.length; row++) { + maxInColumn = Math.max(maxInColumn, grid[row][col]); + } + result += maxInColumn; + } + + return result; +}; diff --git a/solutions/2505-bitwise-or-of-all-subsequence-sums.js b/solutions/2505-bitwise-or-of-all-subsequence-sums.js new file mode 100644 index 00000000..d7730cfc --- /dev/null +++ b/solutions/2505-bitwise-or-of-all-subsequence-sums.js @@ -0,0 +1,38 @@ +/** + * 2505. Bitwise OR of All Subsequence Sums + * https://leetcode.com/problems/bitwise-or-of-all-subsequence-sums/ + * Difficulty: Medium + * + * Given an integer array nums, return the value of the bitwise OR of the sum of all possible + * subsequences in the array. + * + * A subsequence is a sequence that can be derived from another sequence by removing zero or + * more elements without changing the order of the remaining elements. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var subsequenceSumOr = function(nums) { + const bitCounts = new Array(64).fill(0n); + + for (const num of nums) { + for (let bit = 0; bit < 31; bit++) { + if (num & (1 << bit)) { + bitCounts[bit]++; + } + } + } + + for (let bit = 0; bit < 63; bit++) { + bitCounts[bit + 1] += bitCounts[bit] / 2n; + } + + let result = 0n; + for (let bit = 63; bit >= 0; bit--) { + result = (result << 1n) | (bitCounts[bit] > 0n ? 1n : 0n); + } + + return Number(result); +}; diff --git a/solutions/2510-check-if-there-is-a-path-with-equal-number-of-0s-and-1s.js b/solutions/2510-check-if-there-is-a-path-with-equal-number-of-0s-and-1s.js new file mode 100644 index 00000000..fc05209f --- /dev/null +++ b/solutions/2510-check-if-there-is-a-path-with-equal-number-of-0s-and-1s.js @@ -0,0 +1,56 @@ +/** + * 2510. Check if There is a Path With Equal Number of 0's And 1's + * https://leetcode.com/problems/check-if-there-is-a-path-with-equal-number-of-0s-and-1s/ + * Difficulty: Medium + * + * You are given a 0-indexed m x n binary matrix grid. You can move from a cell (row, col) to + * any of the cells (row + 1, col) or (row, col + 1). + * + * Return true if there is a path from (0, 0) to (m - 1, n - 1) that visits an equal number + * of 0's and 1's. Otherwise return false. + */ + +/** + * @param {number[][]} grid + * @return {boolean} + */ +var isThereAPath = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const pathLength = rows + cols - 1; + + if (pathLength % 2 !== 0) return false; + + const visited = new Set(); + const startBalance = grid[0][0] === 1 ? 1 : -1; + + return dfs(0, 0, startBalance); + + function dfs(row, col, balance) { + if (row === rows - 1 && col === cols - 1) { + return balance === 0; + } + + const key = `${row},${col},${balance}`; + if (visited.has(key)) return false; + visited.add(key); + + if (Math.abs(balance) > (rows - 1 - row) + (cols - 1 - col)) { + return false; + } + + let canReach = false; + + if (row + 1 < rows) { + const nextBalance = balance + (grid[row + 1][col] === 1 ? 1 : -1); + canReach = canReach || dfs(row + 1, col, nextBalance); + } + + if (col + 1 < cols) { + const nextBalance = balance + (grid[row][col + 1] === 1 ? 1 : -1); + canReach = canReach || dfs(row, col + 1, nextBalance); + } + + return canReach; + } +}; diff --git a/solutions/2511-maximum-enemy-forts-that-can-be-captured.js b/solutions/2511-maximum-enemy-forts-that-can-be-captured.js new file mode 100644 index 00000000..7a7b5045 --- /dev/null +++ b/solutions/2511-maximum-enemy-forts-that-can-be-captured.js @@ -0,0 +1,42 @@ +/** + * 2511. Maximum Enemy Forts That Can Be Captured + * https://leetcode.com/problems/maximum-enemy-forts-that-can-be-captured/ + * Difficulty: Easy + * + * You are given a 0-indexed integer array forts of length n representing the positions of + * several forts. forts[i] can be -1, 0, or 1 where: + * - -1 represents there is no fort at the ith position. + * - 0 indicates there is an enemy fort at the ith position. + * - 1 indicates the fort at the ith the position is under your command. + * + * Now you have decided to move your army from one of your forts at position i to an empty + * position j such that: + * - 0 <= i, j <= n - 1 + * - The army travels over enemy forts only. Formally, for all k where min(i,j) < k < max(i,j), + * forts[k] == 0. + * + * While moving the army, all the enemy forts that come in the way are captured. + * + * Return the maximum number of enemy forts that can be captured. In case it is impossible to + * move your army, or you do not have any fort under your command, return 0. + */ + +/** + * @param {number[]} forts + * @return {number} + */ +var captureForts = function(forts) { + let result = 0; + let start = -1; + + for (let i = 0; i < forts.length; i++) { + if (forts[i] === 1 || forts[i] === -1) { + if (start !== -1 && forts[start] !== forts[i]) { + result = Math.max(result, i - start - 1); + } + start = i; + } + } + + return result; +}; diff --git a/solutions/2512-reward-top-k-students.js b/solutions/2512-reward-top-k-students.js new file mode 100644 index 00000000..d5c663f2 --- /dev/null +++ b/solutions/2512-reward-top-k-students.js @@ -0,0 +1,56 @@ +/** + * 2512. Reward Top K Students + * https://leetcode.com/problems/reward-top-k-students/ + * Difficulty: Medium + * + * You are given two string arrays positive_feedback and negative_feedback, containing the words + * denoting positive and negative feedback, respectively. Note that no word is both positive and + * negative. + * + * Initially every student has 0 points. Each positive word in a feedback report increases the + * points of a student by 3, whereas each negative word decreases the points by 1. + * + * You are given n feedback reports, represented by a 0-indexed string array report and a + * 0-indexed integer array student_id, where student_id[i] represents the ID of the student + * who has received the feedback report report[i]. The ID of each student is unique. + * + * Given an integer k, return the top k students after ranking them in non-increasing order + * by their points. In case more than one student has the same points, the one with the lower + * ID ranks higher. + */ + +/** + * @param {string[]} positive_feedback + * @param {string[]} negative_feedback + * @param {string[]} report + * @param {number[]} student_id + * @param {number} k + * @return {number[]} + */ +var topStudents = function(positive_feedback, negative_feedback, report, student_id, k) { + const positiveSet = new Set(positive_feedback); + const negativeSet = new Set(negative_feedback); + const studentScores = []; + + for (let i = 0; i < report.length; i++) { + const words = report[i].split(' '); + let score = 0; + + for (const word of words) { + if (positiveSet.has(word)) { + score += 3; + } else if (negativeSet.has(word)) { + score -= 1; + } + } + + studentScores.push([student_id[i], score]); + } + + studentScores.sort((a, b) => { + if (a[1] !== b[1]) return b[1] - a[1]; + return a[0] - b[0]; + }); + + return studentScores.slice(0, k).map(student => student[0]); +}; diff --git a/solutions/2519-count-the-number-of-k-big-indices.js b/solutions/2519-count-the-number-of-k-big-indices.js new file mode 100644 index 00000000..b77a7cad --- /dev/null +++ b/solutions/2519-count-the-number-of-k-big-indices.js @@ -0,0 +1,48 @@ +/** + * 2519. Count the Number of K-Big Indices + * https://leetcode.com/problems/count-the-number-of-k-big-indices/ + * Difficulty: Hard + * + * You are given a 0-indexed integer array nums and a positive integer k. + * + * We call an index i k-big if the following conditions are satisfied: + * - There exist at least k different indices idx1 such that idx1 < i and nums[idx1] < nums[i]. + * - There exist at least k different indices idx2 such that idx2 > i and nums[idx2] < nums[i]. + * + * Return the number of k-big indices. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var kBigIndices = function(nums, k) { + const n = nums.length; + const hasKSmallerLeft = new Array(n).fill(false); + + const leftMaxHeap = new PriorityQueue((a, b) => b - a); + for (let i = 0; i < n; i++) { + if (leftMaxHeap.size() === k && leftMaxHeap.front() < nums[i]) { + hasKSmallerLeft[i] = true; + } + leftMaxHeap.enqueue(nums[i]); + if (leftMaxHeap.size() > k) { + leftMaxHeap.dequeue(); + } + } + + let result = 0; + const rightMaxHeap = new PriorityQueue((a, b) => b - a); + for (let i = n - 1; i >= 0; i--) { + if (rightMaxHeap.size() === k && rightMaxHeap.front() < nums[i] && hasKSmallerLeft[i]) { + result++; + } + rightMaxHeap.enqueue(nums[i]); + if (rightMaxHeap.size() > k) { + rightMaxHeap.dequeue(); + } + } + + return result; +}; diff --git a/solutions/2524-maximum-frequency-score-of-a-subarray.js b/solutions/2524-maximum-frequency-score-of-a-subarray.js new file mode 100644 index 00000000..9bb7d33a --- /dev/null +++ b/solutions/2524-maximum-frequency-score-of-a-subarray.js @@ -0,0 +1,56 @@ +/** + * 2524. Maximum Frequency Score of a Subarray + * https://leetcode.com/problems/maximum-frequency-score-of-a-subarray/ + * Difficulty: Hard + * + * You are given an integer array nums and a positive integer k. + * + * The frequency score of an array is the sum of the distinct values in the array raised to + * the power of their frequencies, taking the sum modulo 109 + 7. + * - For example, the frequency score of the array [5,4,5,7,4,4] is (43 + 52 + 71) modulo + * (109 + 7) = 96. + * + * Return the maximum frequency score of a subarray of size k in nums. You should maximize + * the value under the modulo and not the actual value. + * + * A subarray is a contiguous part of an array. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var maxFrequencyScore = function(nums, k) { + const MOD = 1e9 + 7; + + let sum = 0; + let result = 0; + const frequency = new Map(); + for (let i = 0; i < nums.length; i++) { + if (!frequency.has(nums[i])) { + frequency.set(nums[i], []); + } + sum = adjustSum(sum, nums[i], frequency.get(nums[i])); + + if (i >= k - 1) { + if (i >= k) { + sum = adjustSum(sum, nums[i - k], frequency.get(nums[i - k]), false); + } + result = Math.max(result, sum); + } + } + + return result; + + function adjustSum(sum, value, powers, add = true) { + sum = (MOD + sum - (powers.length === 0 ? 0 : powers[powers.length - 1])) % MOD; + if (add) { + const newPower = (value * (powers.length === 0 ? 1 : powers[powers.length - 1])) % MOD; + powers.push(newPower); + } else { + powers.pop(); + } + return (sum + (powers.length === 0 ? 0 : powers[powers.length - 1])) % MOD; + } +}; diff --git a/solutions/2533-number-of-good-binary-strings.js b/solutions/2533-number-of-good-binary-strings.js new file mode 100644 index 00000000..5f0a03db --- /dev/null +++ b/solutions/2533-number-of-good-binary-strings.js @@ -0,0 +1,50 @@ +/** + * 2533. Number of Good Binary Strings + * https://leetcode.com/problems/number-of-good-binary-strings/ + * Difficulty: Medium + * + * You are given four integers minLength, maxLength, oneGroup and zeroGroup. + * + * A binary string is good if it satisfies the following conditions: + * - The length of the string is in the range [minLength, maxLength]. + * - The size of each block of consecutive 1's is a multiple of oneGroup. + * - For example in a binary string 00110111100 sizes of each block of consecutive ones + * are [2,4]. + * - The size of each block of consecutive 0's is a multiple of zeroGroup. + * - For example, in a binary string 00110111100 sizes of each block of consecutive zeros + * are [2,1,2]. + * + * Return the number of good binary strings. Since the answer may be too large, return it + * modulo 109 + 7. + * + * Note that 0 is considered a multiple of all the numbers. + */ + +/** + * @param {number} minLength + * @param {number} maxLength + * @param {number} oneGroup + * @param {number} zeroGroup + * @return {number} + */ +var goodBinaryStrings = function(minLength, maxLength, oneGroup, zeroGroup) { + const MOD = 1e9 + 7; + const dp = new Array(maxLength + 1).fill(0); + dp[0] = 1; + + for (let i = 1; i <= maxLength; i++) { + if (oneGroup <= i) { + dp[i] = (dp[i] + dp[i - oneGroup]) % MOD; + } + if (zeroGroup <= i) { + dp[i] = (dp[i] + dp[i - zeroGroup]) % MOD; + } + } + + let result = 0; + for (let i = minLength; i <= maxLength; i++) { + result = (result + dp[i]) % MOD; + } + + return result; +}; diff --git a/solutions/2534-time-taken-to-cross-the-door.js b/solutions/2534-time-taken-to-cross-the-door.js new file mode 100644 index 00000000..07a331a2 --- /dev/null +++ b/solutions/2534-time-taken-to-cross-the-door.js @@ -0,0 +1,79 @@ +/** + * 2534. Time Taken to Cross the Door + * https://leetcode.com/problems/time-taken-to-cross-the-door/ + * Difficulty: Hard + * + * There are n persons numbered from 0 to n - 1 and a door. Each person can enter or exit + * through the door once, taking one second. + * + * You are given a non-decreasing integer array arrival of size n, where arrival[i] is the + * arrival time of the ith person at the door. You are also given an array state of size n, + * where state[i] is 0 if person i wants to enter through the door or 1 if they want to exit + * through the door. + * + * If two or more persons want to use the door at the same time, they follow the following + * rules: + * - If the door was not used in the previous second, then the person who wants to exit + * goes first. + * - If the door was used in the previous second for entering, the person who wants to + * enter goes first. + * - If the door was used in the previous second for exiting, the person who wants to + * exit goes first. + * - If multiple persons want to go in the same direction, the person with the smallest + * index goes first. + * + * Return an array answer of size n where answer[i] is the second at which the ith person + * crosses the door. + * + * Note that: + * - Only one person can cross the door at each second. + * - A person may arrive at the door and wait without entering or exiting to follow the + * mentioned rules. + */ + +/** + * @param {number[]} arrival + * @param {number[]} state + * @return {number[]} + */ +var timeTaken = function(arrival, state) { + const enterPool = []; + const exitPool = []; + let currentTime = 0; + let previousState = 1; + let i = 0; + const result = new Array(arrival.length); + + while (i < arrival.length || enterPool.length > 0 || exitPool.length > 0) { + while (i < arrival.length && arrival[i] <= currentTime) { + if (state[i] === 0) { + enterPool.push(i); + } else { + exitPool.push(i); + } + i++; + } + + if (previousState === 1) { + if (exitPool.length > 0) { + result[exitPool.shift()] = currentTime; + } else if (enterPool.length > 0) { + result[enterPool.shift()] = currentTime; + previousState = 0; + } + } else { + if (enterPool.length > 0) { + result[enterPool.shift()] = currentTime; + } else if (exitPool.length > 0) { + result[exitPool.shift()] = currentTime; + previousState = 1; + } else { + previousState = 1; + } + } + + currentTime++; + } + + return result; +}; diff --git a/solutions/2539-count-the-number-of-good-subsequences.js b/solutions/2539-count-the-number-of-good-subsequences.js new file mode 100644 index 00000000..e6d5819e --- /dev/null +++ b/solutions/2539-count-the-number-of-good-subsequences.js @@ -0,0 +1,80 @@ +/** + * 2539. Count the Number of Good Subsequences + * https://leetcode.com/problems/count-the-number-of-good-subsequences/ + * Difficulty: Medium + * + * A subsequence of a string is good if it is not empty and the frequency of each one of its + * characters is the same. + * + * Given a string s, return the number of good subsequences of s. Since the answer may be too + * large, return it modulo 109 + 7. + * + * A subsequence is a string that can be derived from another string by deleting some or no + * characters without changing the order of the remaining characters. + */ + +/** + * @param {string} s + * @return {number} + */ +var countGoodSubsequences = function(s) { + const MOD = 1e9 + 7; + const n = s.length; + const factorial = new Array(n + 1); + + const frequency = new Array(26).fill(0); + let maxFrequency = 0; + + for (let i = 0; i < n; i++) { + frequency[s.charCodeAt(i) - 97]++; + } + + for (let i = 0; i < 26; i++) { + maxFrequency = Math.max(maxFrequency, frequency[i]); + } + + let result = 0n; + + for (let k = 1; k <= maxFrequency; k++) { + let current = 1n; + for (let i = 0; i < 26; i++) { + if (frequency[i] > 0) { + current = (current * (1n + combination(frequency[i], k))) % BigInt(MOD); + } + } + result = (result + current - 1n + BigInt(MOD)) % BigInt(MOD); + } + + return Number(result); + + function computeFactorial(num) { + if (factorial[num] !== undefined) return factorial[num]; + if (num === 0) { + factorial[num] = 1n; + } else { + factorial[num] = (computeFactorial(num - 1) * BigInt(num)) % BigInt(MOD); + } + return factorial[num]; + } + + function modInverse(a) { + let result = 1n; + let base = a % BigInt(MOD); + let exp = BigInt(MOD - 2); + while (exp > 0n) { + if (exp & 1n) result = (result * base) % BigInt(MOD); + base = (base * base) % BigInt(MOD); + exp >>= 1n; + } + return result; + } + + function combination(n, k) { + if (n < k) return 0n; + if (n === k) return 1n; + let result = computeFactorial(n); + result = (result * modInverse(computeFactorial(k))) % BigInt(MOD); + result = (result * modInverse(computeFactorial(n - k))) % BigInt(MOD); + return result; + } +}; diff --git a/solutions/2548-maximum-price-to-fill-a-bag.js b/solutions/2548-maximum-price-to-fill-a-bag.js new file mode 100644 index 00000000..14d9a33c --- /dev/null +++ b/solutions/2548-maximum-price-to-fill-a-bag.js @@ -0,0 +1,38 @@ +/** + * 2548. Maximum Price to Fill a Bag + * https://leetcode.com/problems/maximum-price-to-fill-a-bag/ + * Difficulty: Medium + * + * You are given a 2D integer array items where items[i] = [pricei, weighti] denotes the + * price and weight of the ith item, respectively. + * + * You are also given a positive integer capacity. + * + * Each item can be divided into two items with ratios part1 and part2, where part1 + part2 == 1. + * - The weight of the first item is weighti * part1 and the price of the first item is + * pricei * part1. + * - Similarly, the weight of the second item is weighti * part2 and the price of the second + * item is pricei * part2. + * + * Return the maximum total price to fill a bag of capacity capacity with given items. If it + * is impossible to fill a bag return -1. Answers within 10-5 of the actual answer will be + * considered accepted. + */ + +/** + * @param {number[][]} items + * @param {number} capacity + * @return {number} + */ +var maxPrice = function(items, capacity) { + const sortedItems = items.sort((a, b) => (b[0] / b[1]) - (a[0] / a[1])); + let score = 0; + + for (const [price, weight] of sortedItems) { + const take = Math.min(weight, capacity); + score += price * take / weight; + capacity -= take; + } + + return capacity === 0 ? score : -1; +}; diff --git a/solutions/2557-maximum-number-of-integers-to-choose-from-a-range-ii.js b/solutions/2557-maximum-number-of-integers-to-choose-from-a-range-ii.js new file mode 100644 index 00000000..22732080 --- /dev/null +++ b/solutions/2557-maximum-number-of-integers-to-choose-from-a-range-ii.js @@ -0,0 +1,47 @@ +/** + * 2557. Maximum Number of Integers to Choose From a Range II + * https://leetcode.com/problems/maximum-number-of-integers-to-choose-from-a-range-ii/ + * Difficulty: Medium + * + * You are given an integer array banned and two integers n and maxSum. You are choosing some + * number of integers following the below rules: + * - The chosen integers have to be in the range [1, n]. + * - Each integer can be chosen at most once. + * - The chosen integers should not be in the array banned. + * - The sum of the chosen integers should not exceed maxSum. + * + * Return the maximum number of integers you can choose following the mentioned rules. + */ + +/** + * @param {number[]} banned + * @param {number} n + * @param {number} maxSum + * @return {number} + */ +var maxCount = function(banned, n, maxSum) { + const initialLimit = Math.min(n, Math.floor((-1 + Math.sqrt(1 + 8 * maxSum)) / 2)); + const bannedNumbers = new Set(banned); + let totalSum = Math.floor(initialLimit * (initialLimit + 1) / 2); + let result = initialLimit; + + for (const bannedNumber of bannedNumbers) { + if (bannedNumber <= initialLimit) { + totalSum -= bannedNumber; + result -= 1; + } + } + + for (let candidate = initialLimit + 1; candidate <= n; candidate++) { + if (totalSum + candidate > maxSum) { + return result; + } + + if (!bannedNumbers.has(candidate)) { + totalSum += candidate; + result += 1; + } + } + + return result; +}; diff --git a/solutions/2561-rearranging-fruits.js b/solutions/2561-rearranging-fruits.js new file mode 100644 index 00000000..34cb159e --- /dev/null +++ b/solutions/2561-rearranging-fruits.js @@ -0,0 +1,72 @@ +/** + * 2561. Rearranging Fruits + * https://leetcode.com/problems/rearranging-fruits/ + * Difficulty: Hard + * + * You have two fruit baskets containing n fruits each. You are given two 0-indexed integer + * arrays basket1 and basket2 representing the cost of fruit in each basket. You want to + * make both baskets equal. To do so, you can use the following operation as many times as you want: + * - Chose two indices i and j, and swap the ith fruit of basket1 with the jth fruit of basket2. + * - The cost of the swap is min(basket1[i],basket2[j]). + * + * Two baskets are considered equal if sorting them according to the fruit cost makes them + * exactly the same baskets. + * + * Return the minimum cost to make both the baskets equal or -1 if impossible. + */ + +/** + * @param {number[]} basket1 + * @param {number[]} basket2 + * @return {number} + */ +var minCost = function(basket1, basket2) { + const count1 = new Map(); + const count2 = new Map(); + + for (const fruit of basket1) { + count1.set(fruit, (count1.get(fruit) || 0) + 1); + } + + for (const fruit of basket2) { + count2.set(fruit, (count2.get(fruit) || 0) + 1); + } + + const allFruits = new Set([...basket1, ...basket2]); + const excess1 = []; + const excess2 = []; + let minCost = Infinity; + + for (const fruit of allFruits) { + const freq1 = count1.get(fruit) || 0; + const freq2 = count2.get(fruit) || 0; + const total = freq1 + freq2; + + if (total % 2 !== 0) return -1; + + minCost = Math.min(minCost, fruit); + const target = total / 2; + + if (freq1 > target) { + for (let i = 0; i < freq1 - target; i++) { + excess1.push(fruit); + } + } else if (freq2 > target) { + for (let i = 0; i < freq2 - target; i++) { + excess2.push(fruit); + } + } + } + + excess1.sort((a, b) => a - b); + excess2.sort((a, b) => b - a); + + let result = 0; + for (let i = 0; i < excess1.length; i++) { + const directSwap = Math.min(excess1[i], excess2[i]); + const doubleSwap = 2 * minCost; + result += Math.min(directSwap, doubleSwap); + } + + return result; +}; diff --git a/solutions/2576-find-the-maximum-number-of-marked-indices.js b/solutions/2576-find-the-maximum-number-of-marked-indices.js new file mode 100644 index 00000000..73f0f859 --- /dev/null +++ b/solutions/2576-find-the-maximum-number-of-marked-indices.js @@ -0,0 +1,38 @@ +/** + * 2576. Find the Maximum Number of Marked Indices + * https://leetcode.com/problems/find-the-maximum-number-of-marked-indices/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums. + * + * Initially, all of the indices are unmarked. You are allowed to make this operation any + * number of times: + * - Pick two different unmarked indices i and j such that 2 * nums[i] <= nums[j], then + * mark i and j. + * + * Return the maximum possible number of marked indices in nums using the above operation + * any number of times. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxNumOfMarkedIndices = function(nums) { + nums.sort((a, b) => a - b); + let result = 0; + let left = 0; + let right = Math.floor(nums.length / 2); + + while (left < Math.floor(nums.length / 2) && right < nums.length) { + if (2 * nums[left] <= nums[right]) { + result += 2; + left++; + right++; + } else { + right++; + } + } + + return result; +}; diff --git a/solutions/2590-design-a-todo-list.js b/solutions/2590-design-a-todo-list.js new file mode 100644 index 00000000..b586ec45 --- /dev/null +++ b/solutions/2590-design-a-todo-list.js @@ -0,0 +1,99 @@ +/** + * 2590. Design a Todo List + * https://leetcode.com/problems/design-a-todo-list/ + * Difficulty: Medium + * + * Design a Todo List Where users can add tasks, mark them as complete, or get a list of pending + * tasks. Users can also add tags to tasks and can filter the tasks by certain tags. + * + * Implement the TodoList class: + * - TodoList() Initializes the object. + * - int addTask(int userId, String taskDescription, int dueDate, List tags) Adds a task for + * the user with the ID userId with a due date equal to dueDate and a list of tags attached to the + * task. The return value is the ID of the task. This ID starts at 1 and is sequentially + * increasing. That is, the first task's id should be 1, the second task's id should be 2, and so + * on. + * - List getAllTasks(int userId) Returns a list of all the tasks not marked as complete for + * the user with ID userId, ordered by the due date. You should return an empty list if the user + * has no uncompleted tasks. + * - List getTasksForTag(int userId, String tag) Returns a list of all the tasks that are + * not marked as complete for the user with the ID userId and have tag as one of their tags, + * ordered by their due date. Return an empty list if no such task exists. + * - void completeTask(int userId, int taskId) Marks the task with the ID taskId as completed only + * if the task exists and the user with the ID userId has this task, and it is uncompleted. + */ + +var TodoList = function() { + this.nextTaskId = 1; + this.userTasks = new Map(); + this.allTasks = new Map(); +}; + +/** + * @param {number} userId + * @param {string} taskDescription + * @param {number} dueDate + * @param {string[]} tags + * @return {number} + */ +TodoList.prototype.addTask = function(userId, taskDescription, dueDate, tags) { + const taskId = this.nextTaskId++; + const task = { + id: taskId, + description: taskDescription, + dueDate: dueDate, + tags: new Set(tags), + completed: false + }; + + if (!this.userTasks.has(userId)) { + this.userTasks.set(userId, []); + } + this.userTasks.get(userId).push(task); + this.allTasks.set(taskId, { userId, task }); + + return taskId; +}; + +/** + * @param {number} userId + * @return {string[]} + */ +TodoList.prototype.getAllTasks = function(userId) { + if (!this.userTasks.has(userId)) { + return []; + } + + return this.userTasks.get(userId) + .filter(task => !task.completed) + .sort((a, b) => a.dueDate - b.dueDate) + .map(task => task.description); +}; + +/** + * @param {number} userId + * @param {string} tag + * @return {string[]} + */ +TodoList.prototype.getTasksForTag = function(userId, tag) { + if (!this.userTasks.has(userId)) { + return []; + } + + return this.userTasks.get(userId) + .filter(task => !task.completed && task.tags.has(tag)) + .sort((a, b) => a.dueDate - b.dueDate) + .map(task => task.description); +}; + +/** + * @param {number} userId + * @param {number} taskId + * @return {void} + */ +TodoList.prototype.completeTask = function(userId, taskId) { + const taskInfo = this.allTasks.get(taskId); + if (taskInfo && taskInfo.userId === userId && !taskInfo.task.completed) { + taskInfo.task.completed = true; + } +}; diff --git a/solutions/2598-smallest-missing-non-negative-integer-after-operations.js b/solutions/2598-smallest-missing-non-negative-integer-after-operations.js new file mode 100644 index 00000000..fe19438b --- /dev/null +++ b/solutions/2598-smallest-missing-non-negative-integer-after-operations.js @@ -0,0 +1,40 @@ +/** + * 2598. Smallest Missing Non-negative Integer After Operations + * https://leetcode.com/problems/smallest-missing-non-negative-integer-after-operations/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums and an integer value. + * + * In one operation, you can add or subtract value from any element of nums. + * - For example, if nums = [1,2,3] and value = 2, you can choose to subtract value from nums[0] + * to make nums = [-1,2,3]. + * + * The MEX (minimum excluded) of an array is the smallest missing non-negative integer in it. + * - For example, the MEX of [-1,2,3] is 0 while the MEX of [1,0,3] is 2. + * + * Return the maximum MEX of nums after applying the mentioned operation any number of times. + */ + +/** + * @param {number[]} nums + * @param {number} value + * @return {number} + */ +var findSmallestInteger = function(nums, value) { + const remainderCount = new Map(); + + for (const num of nums) { + const remainder = ((num % value) + value) % value; + remainderCount.set(remainder, (remainderCount.get(remainder) || 0) + 1); + } + + for (let mex = 0; mex <= nums.length; mex++) { + const remainder = mex % value; + if (!remainderCount.has(remainder) || remainderCount.get(remainder) === 0) { + return mex; + } + remainderCount.set(remainder, remainderCount.get(remainder) - 1); + } + + return nums.length; +}; diff --git a/solutions/2599-make-the-prefix-sum-non-negative.js b/solutions/2599-make-the-prefix-sum-non-negative.js new file mode 100644 index 00000000..787d7286 --- /dev/null +++ b/solutions/2599-make-the-prefix-sum-non-negative.js @@ -0,0 +1,42 @@ +/** + * 2599. Make the Prefix Sum Non-negative + * https://leetcode.com/problems/make-the-prefix-sum-non-negative/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums. You can apply the following operation any + * number of times: + * - Pick any element from nums and put it at the end of nums. + * + * The prefix sum array of nums is an array prefix of the same length as nums such that prefix[i] + * is the sum of all the integers nums[j] where j is in the inclusive range [0, i]. + * + * Return the minimum number of operations such that the prefix sum array does not contain negative + * integers. The test cases are generated such that it is always possible to make the prefix sum + * array non-negative. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var makePrefSumNonNegative = function(nums) { + const minHeap = new PriorityQueue((a, b) => a - b); + let prefixSum = 0; + let result = 0; + + for (const num of nums) { + prefixSum += num; + + if (num < 0) { + minHeap.enqueue(num); + } + + if (prefixSum < 0) { + const minNegative = minHeap.dequeue(); + prefixSum -= minNegative; + result++; + } + } + + return result; +}; diff --git a/solutions/2604-minimum-time-to-eat-all-grains.js b/solutions/2604-minimum-time-to-eat-all-grains.js new file mode 100644 index 00000000..28841317 --- /dev/null +++ b/solutions/2604-minimum-time-to-eat-all-grains.js @@ -0,0 +1,72 @@ +/** + * 2604. Minimum Time to Eat All Grains + * https://leetcode.com/problems/minimum-time-to-eat-all-grains/ + * Difficulty: Hard + * + * There are n hens and m grains on a line. You are given the initial positions of the hens + * and the grains in two integer arrays hens and grains of size n and m respectively. + * + * Any hen can eat a grain if they are on the same position. The time taken for this is + * negligible. One hen can also eat multiple grains. + * + * In 1 second, a hen can move right or left by 1 unit. The hens can move simultaneously + * and independently of each other. + * + * Return the minimum time to eat all grains if the hens act optimally. + */ + +/** + * @param {number[]} hens + * @param {number[]} grains + * @return {number} + */ +var minimumTime = function(hens, grains) { + hens.sort((a, b) => a - b); + grains.sort((a, b) => a - b); + + let minTime = 0; + let maxTime = 2 * (Math.max( + grains[grains.length - 1], + hens[hens.length - 1]) - Math.min(grains[0], hens[0] + )); + + while (minTime < maxTime) { + const midTime = Math.floor((minTime + maxTime) / 2); + if (isTimeReachable(midTime)) { + maxTime = midTime; + } else { + minTime = midTime + 1; + } + } + + return minTime; + + function isTimeReachable(time) { + let currentGrainIndex = 0; + + for (const currentHenPosition of hens) { + let maximumRightReach = time; + + if (grains[currentGrainIndex] < currentHenPosition) { + const costToReachLeftmost = currentHenPosition - grains[currentGrainIndex]; + if (costToReachLeftmost > time) return false; + + maximumRightReach = Math.max( + 0, + time - 2 * costToReachLeftmost, Math.floor((time - costToReachLeftmost) / 2) + ); + } + + if (currentHenPosition + maximumRightReach >= grains[currentGrainIndex]) { + const farthestReachablePosition = currentHenPosition + maximumRightReach; + while (currentGrainIndex < grains.length + && grains[currentGrainIndex] <= farthestReachablePosition) { + currentGrainIndex++; + } + if (currentGrainIndex === grains.length) return true; + } + } + + return false; + } +}; diff --git a/solutions/2613-beautiful-pairs.js b/solutions/2613-beautiful-pairs.js new file mode 100644 index 00000000..b636fea1 --- /dev/null +++ b/solutions/2613-beautiful-pairs.js @@ -0,0 +1,128 @@ +/** + * 2613. Beautiful Pairs + * https://leetcode.com/problems/beautiful-pairs/ + * Difficulty: Hard + * + * You are given two 0-indexed integer arrays nums1 and nums2 of the same length. A pair + * of indices (i,j) is called beautiful if|nums1[i] - nums1[j]| + |nums2[i] - nums2[j]| + * is the smallest amongst all possible indices pairs where i < j. + * + * Return the beautiful pair. In the case that there are multiple beautiful pairs, return + * the lexicographically smallest pair. + * + * Note that + * - |x| denotes the absolute value of x. + * - A pair of indices (i1, j1) is lexicographically smaller than (i2, j2) if i1 < i2 + * or i1 == i2 and j1 < j2. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number[]} + */ +var beautifulPair = function(nums1, nums2) { + const n = nums1.length; + const max = Math.max(...nums1, ...nums2); + const size = max + 1; + + const indices = Array.from({ length: n }, (_, i) => i) + .sort((a, b) => nums1[a] === nums1[b] ? a - b : nums1[a] - nums1[b]); + + nums1.push(-100000001); + nums2.push(100000000); + + const tree1 = new Array(2 * size).fill(-1); + const tree2 = new Array(2 * size).fill(-1); + let best = null; + + update(nums2[indices[0]], indices[0], 1); + update(nums2[indices[0]], indices[0], -1); + + for (let i = 1; i < n; i++) { + const index = indices[i]; + const y = nums2[index]; + + const left = query(0, y, -1); + const right = query(y, max, 1); + + best = select(index, left, right); + + update(y, index, -1); + update(y, index, 1); + } + + return best; + + function compare(i, j, dir) { + if (j === -1) return i; + if (i === -1) return j; + const vi = -nums1[i] + dir * nums2[i]; + const vj = -nums1[j] + dir * nums2[j]; + return vi < vj || (vi === vj && i < j) ? i : j; + } + + function update(position, index, dir) { + position += size; + const tree = dir === 1 ? tree2 : tree1; + + while (position > 0) { + const cur = tree[position]; + const better = compare(index, cur, dir); + if (better !== index) return; + tree[position] = better; + position = Math.floor(position / 2); + } + } + + function query(l, r, dir) { + l += size; + r += size; + const tree = dir === 1 ? tree2 : tree1; + let result = -1; + + while (l <= r) { + if (l & 1) { + result = compare(result, tree[l], dir); + l++; + } + if (!(r & 1)) { + result = compare(result, tree[r], dir); + r--; + } + l = Math.floor(l / 2); + r = Math.floor(r / 2); + } + + return result; + } + + function select(x, y, z) { + const pairs = []; + + if (y !== -1) { + const d = nums1[x] + nums2[x] - nums1[y] - nums2[y]; + pairs.push([d, [Math.min(x, y), Math.max(x, y)]]); + } + + if (z !== -1) { + const d = nums1[x] - nums2[x] - nums1[z] + nums2[z]; + pairs.push([d, [Math.min(x, z), Math.max(x, z)]]); + } + + if (best !== null) { + const d = Math.abs( + nums1[best[0]] - nums1[best[1]]) + Math.abs(nums2[best[0]] - nums2[best[1]] + ); + pairs.push([d, best]); + } else { + pairs.push([Infinity, [-1, -1]]); + } + + return pairs.sort((a, b) => { + if (a[0] !== b[0]) return a[0] - b[0]; + if (a[1][0] !== b[1][0]) return a[1][0] - b[1][0]; + return a[1][1] - b[1][1]; + })[0][1]; + } +}; diff --git a/solutions/2628-json-deep-equal.js b/solutions/2628-json-deep-equal.js new file mode 100644 index 00000000..2f0cf372 --- /dev/null +++ b/solutions/2628-json-deep-equal.js @@ -0,0 +1,43 @@ +/** + * 2628. JSON Deep Equal + * https://leetcode.com/problems/json-deep-equal/ + * Difficulty: Medium + * + * Given two values o1 and o2, return a boolean value indicating whether two values, o1 and o2, + * are deeply equal. + * + * For two values to be deeply equal, the following conditions must be met: + * - If both values are primitive types, they are deeply equal if they pass the === equality check. + * - If both values are arrays, they are deeply equal if they have the same elements in the same + * order, and each element is also deeply equal according to these conditions. + * - If both values are objects, they are deeply equal if they have the same keys, and the + * associated values for each key are also deeply equal according to these conditions. + * + * You may assume both values are the output of JSON.parse. In other words, they are valid JSON. + * + * Please solve it without using lodash's _.isEqual() function + */ + +/** + * @param {null|boolean|number|string|Array|Object} o1 + * @param {null|boolean|number|string|Array|Object} o2 + * @return {boolean} + */ +var areDeeplyEqual = function(o1, o2) { + if (o1 === o2) return true; + if (o1 == null || o2 == null) return false; + if (typeof o1 !== 'object' || typeof o2 !== 'object') return false; + + if (Array.isArray(o1) !== Array.isArray(o2)) return false; + + if (Array.isArray(o1)) { + if (o1.length !== o2.length) return false; + return o1.every((item, index) => areDeeplyEqual(item, o2[index])); + } + + const keys1 = Object.keys(o1); + const keys2 = Object.keys(o2); + if (keys1.length !== keys2.length) return false; + + return keys1.every(key => keys2.includes(key) && areDeeplyEqual(o1[key], o2[key])); +}; diff --git a/solutions/2632-curry.js b/solutions/2632-curry.js new file mode 100644 index 00000000..23b54c9f --- /dev/null +++ b/solutions/2632-curry.js @@ -0,0 +1,28 @@ +/** + * 2632. Curry + * https://leetcode.com/problems/curry/ + * Difficulty: Medium + * + * Given a function fn, return a curried version of that function. + * + * A curried function is a function that accepts fewer or an equal number of parameters as the + * original function and returns either another curried function or the same value the original + * function would have returned. + * + * In practical terms, if you called the original function like sum(1,2,3), you would call the + * curried version like csum(1)(2)(3), csum(1)(2,3), csum(1,2)(3), or csum(1,2,3). All these + * methods of calling the curried function should return the same value as the original. + */ + +/** + * @param {Function} fn + * @return {Function} + */ +var curry = function(fn) { + return function curried(...args) { + if (args.length >= fn.length) { + return fn(...args); + } + return (...nextArgs) => curried(...args, ...nextArgs); + }; +}; diff --git a/solutions/2633-convert-object-to-json-string.js b/solutions/2633-convert-object-to-json-string.js new file mode 100644 index 00000000..90fd0f2e --- /dev/null +++ b/solutions/2633-convert-object-to-json-string.js @@ -0,0 +1,29 @@ +/** + * 2633. Convert Object to JSON String + * https://leetcode.com/problems/convert-object-to-json-string/ + * Difficulty: Medium + * + * Given a value, return a valid JSON string of that value. The value can be a string, number, + * array, object, boolean, or null. The returned string should not include extra spaces. The + * order of keys should be the same as the order returned by Object.keys(). + * + * Please solve it without using the built-in JSON.stringify method. + */ + +/** + * @param {null|boolean|number|string|Array|Object} object + * @return {string} + */ +var jsonStringify = function(object) { + if (object === null) return 'null'; + if (typeof object === 'boolean' || typeof object === 'number') return String(object); + if (typeof object === 'string') return `"${object}"`; + + if (Array.isArray(object)) { + const elements = object.map(item => jsonStringify(item)); + return `[${elements.join(',')}]`; + } + + const pairs = Object.keys(object).map(key => `"${key}":${jsonStringify(object[key])}`); + return `{${pairs.join(',')}}`; +}; diff --git a/solutions/2636-promise-pool.js b/solutions/2636-promise-pool.js new file mode 100644 index 00000000..c2bde850 --- /dev/null +++ b/solutions/2636-promise-pool.js @@ -0,0 +1,32 @@ +/** + * 2636. Promise Pool + * https://leetcode.com/problems/promise-pool/ + * Difficulty: Medium + * + * Given an array of asynchronous functions functions and a pool limit n, return an asynchronous + * function promisePool. It should return a promise that resolves when all the input functions + * resolve. + * + * Pool limit is defined as the maximum number promises that can be pending at once. promisePool + * should begin execution of as many functions as possible and continue executing new functions + * when old promises resolve. promisePool should execute functions[i] then functions[i + 1] then + * functions[i + 2], etc. When the last promise resolves, promisePool should also resolve. + * + * For example, if n = 1, promisePool will execute one function at a time in series. However, + * if n = 2, it first executes two functions. When either of the two functions resolve, a 3rd + * function should be executed (if available), and so on until there are no functions left to + * execute. + * + * You can assume all functions never reject. It is acceptable for promisePool to return a promise + * that resolves any value. + */ + +/** + * @param {Function[]} functions + * @param {number} n + * @return {Promise} + */ +var promisePool = async function(functions, n) { + const next = () => functions[n++]?.().then(next); + return Promise.all(functions.slice(0, n).map(f => f().then(next))); +}; diff --git a/solutions/2638-count-the-number-of-k-free-subsets.js b/solutions/2638-count-the-number-of-k-free-subsets.js new file mode 100644 index 00000000..f02dfd34 --- /dev/null +++ b/solutions/2638-count-the-number-of-k-free-subsets.js @@ -0,0 +1,58 @@ +/** + * 2638. Count the Number of K-Free Subsets + * https://leetcode.com/problems/count-the-number-of-k-free-subsets/ + * Difficulty: Medium + * + * You are given an integer array nums, which contains distinct elements and an integer k. + * + * A subset is called a k-Free subset if it contains no two elements with an absolute + * difference equal to k. Notice that the empty set is a k-Free subset. + * + * Return the number of k-Free subsets of nums. + * + * A subset of an array is a selection of elements (possibly none) of the array. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var countTheNumOfKFreeSubsets = function(nums, k) { + nums.sort((a, b) => a - b); + const visited = new Set(); + let result = 1; + + for (const num of nums) { + if (visited.has(num)) continue; + + const chain = []; + let current = num; + + while (nums.includes(current) && !visited.has(current)) { + chain.push(current); + visited.add(current); + current += k; + } + + result *= calculateChainSubsets(chain.length); + } + + return result; + + function calculateChainSubsets(length) { + if (length === 0) return 1; + if (length === 1) return 2; + + let prev2 = 1; + let prev1 = 2; + + for (let i = 2; i <= length; i++) { + const current = prev1 + prev2; + prev2 = prev1; + prev1 = current; + } + + return prev1; + } +}; diff --git a/solutions/2646-minimize-the-total-price-of-the-trips.js b/solutions/2646-minimize-the-total-price-of-the-trips.js new file mode 100644 index 00000000..08bb9cfd --- /dev/null +++ b/solutions/2646-minimize-the-total-price-of-the-trips.js @@ -0,0 +1,81 @@ +/** + * 2646. Minimize the Total Price of the Trips + * https://leetcode.com/problems/minimize-the-total-price-of-the-trips/ + * Difficulty: Hard + * + * There exists an undirected and unrooted tree with n nodes indexed from 0 to n - 1. You are + * given the integer n and a 2D integer array edges of length n - 1, where edges[i] = [ai, bi] + * indicates that there is an edge between nodes ai and bi in the tree. + * + * Each node has an associated price. You are given an integer array price, where price[i] is + * the price of the ith node. + * + * The price sum of a given path is the sum of the prices of all nodes lying on that path. + * + * Additionally, you are given a 2D integer array trips, where trips[i] = [starti, endi] + * indicates that you start the ith trip from the node starti and travel to the node endi + * by any path you like. + * + * Before performing your first trip, you can choose some non-adjacent nodes and halve the + * prices. + * + * Return the minimum total price sum to perform all the given trips. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number[]} price + * @param {number[][]} trips + * @return {number} + */ +var minimumTotalPrice = function(n, edges, price, trips) { + const graph = Array.from({ length: n }, () => []); + for (const [u, v] of edges) { + graph[u].push(v); + graph[v].push(u); + } + + const count = new Array(n).fill(0); + + for (const [start, end] of trips) { + dfsPath(start, end, -1, []); + } + + return dp(0, -1, true)[1]; + + function dp(node, parent, canHalve) { + const full = count[node] * price[node]; + const half = full / 2; + let childrenFull = 0; + let childrenHalf = 0; + + for (const child of graph[node]) { + if (child !== parent) { + const [childFull, childHalf] = dp(child, node, canHalve && node !== -1); + childrenFull += childFull; + childrenHalf += childHalf; + } + } + + if (canHalve) { + return [full + childrenHalf, Math.min(full + childrenHalf, half + childrenFull)]; + } + return [full + childrenHalf, full + childrenHalf]; + } + + function dfsPath(start, end, parent, path) { + path.push(start); + if (start === end) { + for (const node of path) count[node]++; + return true; + } + for (const next of graph[start]) { + if (next !== parent && dfsPath(next, end, start, path)) { + return true; + } + } + path.pop(); + return false; + } +}; diff --git a/solutions/2647-color-the-triangle-red.js b/solutions/2647-color-the-triangle-red.js new file mode 100644 index 00000000..3c4ab329 --- /dev/null +++ b/solutions/2647-color-the-triangle-red.js @@ -0,0 +1,34 @@ +/** + * 2647. Color the Triangle Red + * https://leetcode.com/problems/color-the-triangle-red/ + * Difficulty: Hard + * + * You are given an integer n. Consider an equilateral triangle of side length n, broken up into n2 + * unit equilateral triangles. The triangle has n 1-indexed rows where the ith row has 2i - 1 unit + * equilateral triangles. + * + * The triangles in the ith row are also 1-indexed with coordinates from (i, 1) to (i, 2i - 1). + * The following image shows a triangle of side length 4 with the indexing of its triangle. + */ + +/** + * @param {number} n + * @return {number[][]} + */ +var colorRed = function(n) { + const result = [[1, 1]]; + const startCycle = [1, 2, 3, 1]; + const shortCycle = [0, 1]; + + for (let i = n; i > 1; i--) { + const start = startCycle[(n - i) % 4]; + const short = shortCycle[(n - i) % 2]; + + for (let j = start; j < i * 2; j += 2) { + result.push([i, j]); + if (short) break; + } + } + + return result; +}; diff --git a/solutions/2655-find-maximal-uncovered-ranges.js b/solutions/2655-find-maximal-uncovered-ranges.js new file mode 100644 index 00000000..56a4c8a0 --- /dev/null +++ b/solutions/2655-find-maximal-uncovered-ranges.js @@ -0,0 +1,68 @@ +/** + * 2655. Find Maximal Uncovered Ranges + * https://leetcode.com/problems/find-maximal-uncovered-ranges/ + * Difficulty: Medium + * + * You are given an integer n which is the length of a 0-indexed array nums, and a 0-indexed + * 2D-array ranges, which is a list of sub-ranges of nums (sub-ranges may overlap). + * + * Each row ranges[i] has exactly 2 cells: + * - ranges[i][0], which shows the start of the ith range (inclusive) + * - ranges[i][1], which shows the end of the ith range (inclusive) + * + * These ranges cover some cells of nums and leave some cells uncovered. Your task is to find + * all of the uncovered ranges with maximal length. + * + * Return a 2D-array answer of the uncovered ranges, sorted by the starting point in ascending + * order. + * + * By all of the uncovered ranges with maximal length, we mean satisfying two conditions: + * - Each uncovered cell should belong to exactly one sub-range + * - There should not exist two ranges (l1, r1) and (l2, r2) such that r1 + 1 = l2 + */ + +/** + * @param {number} n + * @param {number[][]} ranges + * @return {number[][]} + */ +var findMaximalUncoveredRanges = function(n, ranges) { + if (ranges.length === 0) return [[0, n - 1]]; + + ranges.sort((a, b) => a[0] - b[0]); + + const mergedRanges = []; + let currentStart = ranges[0][0]; + let currentEnd = ranges[0][1]; + for (let i = 1; i < ranges.length; i++) { + const [start, end] = ranges[i]; + if (start <= currentEnd + 1) { + currentEnd = Math.max(currentEnd, end); + } else { + mergedRanges.push([currentStart, currentEnd]); + currentStart = start; + currentEnd = end; + } + } + mergedRanges.push([currentStart, currentEnd]); + + const result = []; + + if (mergedRanges[0][0] > 0) { + result.push([0, mergedRanges[0][0] - 1]); + } + + for (let i = 0; i < mergedRanges.length - 1; i++) { + const gapStart = mergedRanges[i][1] + 1; + const gapEnd = mergedRanges[i + 1][0] - 1; + if (gapStart <= gapEnd) { + result.push([gapStart, gapEnd]); + } + } + + if (mergedRanges[mergedRanges.length - 1][1] < n - 1) { + result.push([mergedRanges[mergedRanges.length - 1][1] + 1, n - 1]); + } + + return result; +}; diff --git a/solutions/2664-the-knights-tour.js b/solutions/2664-the-knights-tour.js new file mode 100644 index 00000000..10147ab1 --- /dev/null +++ b/solutions/2664-the-knights-tour.js @@ -0,0 +1,70 @@ +/** + * 2664. The Knight’s Tour + * https://leetcode.com/problems/the-knights-tour/ + * Difficulty: Medium + * + * Given two positive integers m and n which are the height and width of a 0-indexed 2D-array + * board, a pair of positive integers (r, c) which is the starting position of the knight on + * the board. + * + * Your task is to find an order of movements for the knight, in a manner that every cell of + * the board gets visited exactly once (the starting cell is considered visited and you + * shouldn't visit it again). + * + * Return the array board in which the cells' values show the order of visiting the cell + * starting from 0 (the initial place of the knight). + * + * Note that a knight can move from cell (r1, c1) to cell (r2, c2) if 0 <= r2 <= m - 1 and + * 0 <= c2 <= n - 1 and min(abs(r1 - r2), abs(c1 - c2)) = 1 and max(abs(r1 - r2), abs(c1 - c2)) = 2. + */ + +/** + * @param {number} m + * @param {number} n + * @param {number} r + * @param {number} c + * @return {number[][]} + */ +var tourOfKnight = function(m, n, r, c) { + const board = new Array(m).fill().map(() => new Array(n).fill(-1)); + const moves = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]]; + + backtrack(r, c, 0); + return board; + + function isValid(row, col) { + return row >= 0 && row < m && col >= 0 && col < n && board[row][col] === -1; + } + + function getDegree(row, col) { + let count = 0; + for (const [dr, dc] of moves) { + if (isValid(row + dr, col + dc)) count++; + } + return count; + } + + function backtrack(row, col, moveCount) { + board[row][col] = moveCount; + + if (moveCount === m * n - 1) return true; + + const nextMoves = []; + for (const [dr, dc] of moves) { + const newRow = row + dr; + const newCol = col + dc; + if (isValid(newRow, newCol)) { + nextMoves.push([newRow, newCol, getDegree(newRow, newCol)]); + } + } + + nextMoves.sort((a, b) => a[2] - b[2]); + + for (const [newRow, newCol] of nextMoves) { + if (backtrack(newRow, newCol, moveCount + 1)) return true; + } + + board[row][col] = -1; + return false; + } +}; diff --git a/solutions/2674-split-a-circular-linked-list.js b/solutions/2674-split-a-circular-linked-list.js new file mode 100644 index 00000000..34307396 --- /dev/null +++ b/solutions/2674-split-a-circular-linked-list.js @@ -0,0 +1,57 @@ +/** + * 2674. Split a Circular Linked List + * https://leetcode.com/problems/split-a-circular-linked-list/ + * Difficulty: Medium + * + * Given a circular linked list list of positive integers, your task is to split it into 2 circular + * linked lists so that the first one contains the first half of the nodes in list (exactly + * ceil(list.length / 2) nodes) in the same order they appeared in list, and the second one contains + * the rest of the nodes in list in the same order they appeared in list. + * + * Return an array answer of length 2 in which the first element is a circular linked list + * representing the first half and the second element is a circular linked list representing the + * second half. + * + * A circular linked list is a normal linked list with the only difference being that the last + * node's next node, is the first node. + */ + +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} list + * @return {ListNode[]} + */ +var splitCircularLinkedList = function(list) { + let length = 0; + let current = list; + + do { + length++; + current = current.next; + } while (current !== list); + + const firstHalfLength = Math.ceil(length / 2); + + let firstHalfEnd = list; + for (let i = 0; i < firstHalfLength - 1; i++) { + firstHalfEnd = firstHalfEnd.next; + } + + const secondHalfStart = firstHalfEnd.next; + + let secondHalfEnd = secondHalfStart; + for (let i = 0; i < length - firstHalfLength - 1; i++) { + secondHalfEnd = secondHalfEnd.next; + } + + firstHalfEnd.next = list; + secondHalfEnd.next = secondHalfStart; + + return [list, secondHalfStart]; +}; diff --git a/solutions/2675-array-of-objects-to-matrix.js b/solutions/2675-array-of-objects-to-matrix.js new file mode 100644 index 00000000..c5a1c570 --- /dev/null +++ b/solutions/2675-array-of-objects-to-matrix.js @@ -0,0 +1,63 @@ +/** + * 2675. Array of Objects to Matrix + * https://leetcode.com/problems/array-of-objects-to-matrix/ + * Difficulty: Hard + * + * Write a function that converts an array of objects arr into a matrix m. + * + * arr is an array of objects or arrays. Each item in the array can be deeply nested with child + * arrays and child objects. It can also contain numbers, strings, booleans, and null values. + * + * The first row m should be the column names. If there is no nesting, the column names are the + * unique keys within the objects. If there is nesting, the column names are the respective paths + * in the object separated by ".". + * + * Each of the remaining rows corresponds to an object in arr. Each value in the matrix corresponds + * to a value in an object. If a given object doesn't contain a value for a given column, the cell + * should contain an empty string "". + * + * The columns in the matrix should be in lexographically ascending order. + */ + +/** + * @param {Array} arr + * @return {(string | number | boolean | null)[][]} + */ +var jsonToMatrix = function(arr) { + const allKeys = Array.from( + arr.reduce((keySet, item) => { + extractKeys(item).forEach(key => keySet.add(key)); + return keySet; + }, new Set()) + ).sort(); + + return [allKeys, ...arr.map(item => allKeys.map(key => getValue(item, key)))]; + + function isObject(value) { + return value !== null && typeof value === 'object'; + } + + function extractKeys(object) { + if (!isObject(object)) return ['']; + const keys = []; + for (const key of Object.keys(object)) { + const childKeys = extractKeys(object[key]); + for (const childKey of childKeys) { + keys.push(childKey ? `${key}.${childKey}` : key); + } + } + return keys; + } + + function getValue(obj, path) { + const segments = path.split('.'); + let current = obj; + let index = 0; + + while (index < segments.length && isObject(current)) { + current = current[segments[index++]]; + } + + return index < segments.length || isObject(current) || current === undefined ? '' : current; + } +}; diff --git a/solutions/2676-throttle.js b/solutions/2676-throttle.js new file mode 100644 index 00000000..a17f27b2 --- /dev/null +++ b/solutions/2676-throttle.js @@ -0,0 +1,55 @@ +/** + * 2676. Throttle + * https://leetcode.com/problems/throttle/ + * Difficulty: Medium + * + * Given a function fn and a time in milliseconds t, return a throttled version of that + * function. + * + * A throttled function is first called without delay and then, for a time interval of + * t milliseconds, can't be executed but should store the latest function arguments provided + * to call fn with them after the end of the delay. + * + * For instance, t = 50ms, and the function was called at 30ms, 40ms, and 60ms. + * + * At 30ms, without delay, the throttled function fn should be called with the arguments, + * and calling the throttled function fn should be blocked for the following t milliseconds. + * + * At 40ms, the function should just save arguments. + * + * At 60ms, arguments should overwrite currently stored arguments from the second call because + * the second and third calls are made before 80ms. Once the delay has passed, the throttled + * function fn should be called with the latest arguments provided during the delay period, + * and it should also create another delay period of 80ms + t. + */ + +/** + * @param {Function} fn + * @param {number} t + * @return {Function} + */ +var throttle = function(fn, t) { + let isThrottled = false; + let nextArgs = null; + + function invoke() { + if (nextArgs) { + fn(...nextArgs); + nextArgs = null; + setTimeout(invoke, t); + } else { + isThrottled = false; + } + } + + return function(...args) { + if (isThrottled) { + nextArgs = args; + return; + } + + fn(...args); + isThrottled = true; + setTimeout(invoke, t); + }; +}; diff --git a/solutions/2689-extract-kth-character-from-the-rope-tree.js b/solutions/2689-extract-kth-character-from-the-rope-tree.js new file mode 100644 index 00000000..ffe7dd8e --- /dev/null +++ b/solutions/2689-extract-kth-character-from-the-rope-tree.js @@ -0,0 +1,62 @@ +/** + * 2689. Extract Kth Character From The Rope Tree + * https://leetcode.com/problems/extract-kth-character-from-the-rope-tree/ + * Difficulty: Easy + * + * You are given the root of a binary tree and an integer k. Besides the left and right children, + * every node of this tree has two other properties, a string node.val containing only lowercase + * English letters (possibly empty) and a non-negative integer node.len. There are two types of + * nodes in this tree: + * - Leaf: These nodes have no children, node.len = 0, and node.val is some non-empty string. + * - Internal: These nodes have at least one child (also at most two children), node.len > 0, + * and node.val is an empty string. + * + * The tree described above is called a Rope binary tree. Now we define S[node] recursively + * as follows: + * - If node is some leaf node, S[node] = node.val, + * - Otherwise if node is some internal node, S[node] = concat(S[node.left], S[node.right]) + * and S[node].length = node.len. + * + * Return k-th character of the string S[root]. + * + * Note: If s and p are two strings, concat(s, p) is a string obtained by concatenating p to s. + * For example, concat("ab", "zz") = "abzz". + */ + +/** + * Definition for a rope tree node. + * class RopeTreeNode { + * constructor(len, val, left, right) { + * this.len = (len===undefined ? 0 : len); + * this.val = (val===undefined ? "" : val); + * this.left = (left===undefined ? null : left); + * this.right = (right===undefined ? null : right); + * } + * } + */ +/** + * @param {RopeTreeNode} root + * @param {number} k + * @return {character} + */ +var getKthCharacter = function(root, k) { + if (!root.left && !root.right) { + return root.val[k - 1]; + } + + const leftLength = getSubtreeLength(root.left); + + if (k <= leftLength) { + return getKthCharacter(root.left, k); + } else { + return getKthCharacter(root.right, k - leftLength); + } + + function getSubtreeLength(node) { + if (!node) return 0; + if (!node.left && !node.right) { + return node.val.length; + } + return node.len; + } +}; diff --git a/solutions/2690-infinite-method-object.js b/solutions/2690-infinite-method-object.js new file mode 100644 index 00000000..9d61341a --- /dev/null +++ b/solutions/2690-infinite-method-object.js @@ -0,0 +1,23 @@ +/** + * 2690. Infinite Method Object + * https://leetcode.com/problems/infinite-method-object/ + * Difficulty: Easy + * + * Write a function that returns an infinite-method object. + * + * An infinite-method object is defined as an object that allows you to call any method and + * it will always return the name of the method. + * + * For example, if you execute obj.abc123(), it will return "abc123". + */ + +/** + * @return {Object} + */ +var createInfiniteObject = function() { + return new Proxy({}, { + get(target, property) { + return () => property; + } + }); +}; diff --git a/solutions/2691-immutability-helper.js b/solutions/2691-immutability-helper.js new file mode 100644 index 00000000..ea1ffe51 --- /dev/null +++ b/solutions/2691-immutability-helper.js @@ -0,0 +1,82 @@ +/** + * 2691. Immutability Helper + * https://leetcode.com/problems/immutability-helper/ + * Difficulty: Hard + * + * Creating clones of immutable objects with minor alterations can be a tedious process. + * Write a class ImmutableHelper that serves as a tool to help with this requirement. + * The constructor accepts an immutable object obj which will be a JSON object or array. + * + * The class has a single method produce which accepts a function mutator. The function + * returns a new object which is similar to the original except it has those mutations applied. + * + * mutator accepts a proxied version of obj. A user of this function can (appear to) mutate + * this object, but the original object obj should not actually be effected. + * + * For example, a user could write code like this: + * const originalObj = {"x": 5}; + * const helper = new ImmutableHelper(originalObj); + * const newObj = helper.produce((proxy) => { + * proxy.x = proxy.x + 1; + * }); + * console.log(originalObj); // {"x": 5} + * console.log(newObj); // {"x": 6} + * + * Properties of the mutator function: + * - It will always return undefined. + * - It will never access keys that don't exist. + * - It will never delete keys (delete obj.key) + * - It will never call methods on a proxied object (push, shift, etc). + * - It will never set keys to objects (proxy.x = {}) + * + * Note on how the solution will be tested: the solution validator will only analyze differences + * between what was returned and the original obj. Doing a full comparison would be too + * computationally expensive. Also, any mutations to the original object will result in a + * wrong answer. + */ + +var ImmutableHelper = function(obj) { + this.original = obj; +}; + +/** + * @param {Function} mutator + * @return {JSON} clone of obj + */ +ImmutableHelper.prototype.produce = function(mutator) { + const mutated = { _: this.original }; + + mutator(proxify(mutated, { _: this.original }, (field, value) => { + mutated[field] = value; + return mutated; + })._); + + return mutated._; + + function proxify(mutableObj, originalObj, setter) { + return new Proxy(mutableObj, { + set(_, property, value) { + mutableObj = setter(property, value); + }, + + get(_, property) { + let value = mutableObj[property]; + + if (!value || typeof value !== 'object') { + return value; + } else { + return proxify(value, originalObj[property], (field, newValue) => { + if (value === originalObj[property]) { + mutableObj = setter( + property, + value = Array.isArray(value) ? [...value] : { ...value } + ); + } + value[field] = newValue; + return value; + }); + } + } + }); + } +}; diff --git a/solutions/2692-make-object-immutable.js b/solutions/2692-make-object-immutable.js new file mode 100644 index 00000000..00fb33e1 --- /dev/null +++ b/solutions/2692-make-object-immutable.js @@ -0,0 +1,62 @@ +/** + * 2692. Make Object Immutable + * https://leetcode.com/problems/make-object-immutable/ + * Difficulty: Medium + * + * Write a function that takes an object obj and returns a new immutable version of this object. + * + * An immutable object is an object that can't be altered and will throw an error if any attempt + * is made to alter it. + * + * There are three types of error messages that can be produced from this new object. + * - Attempting to modify a key on the object will result in this error message: + * - `Error Modifying: ${key}`. + * - Attempting to modify an index on an array will result in this error message: + * - `Error Modifying Index: ${index}`. + * - Attempting to call a method that mutates an array will result in this error message: + * - `Error Calling Method: ${methodName}`. + * - You may assume the only methods that can mutate an array + * are ['pop', 'push', 'shift', 'unshift', 'splice', 'sort', 'reverse']. + * + * obj is a valid JSON object or array, meaning it is the output of JSON.parse(). + * + * Note that a string literal should be thrown, not an Error. + */ + +/** + * @param {Object|Array} obj + * @return {Object|Array} immutable obj + */ +var makeImmutable = function(obj) { + const mutatingMethods = new Set(['pop', 'push', 'shift', 'unshift', 'splice', 'sort', 'reverse']); + + return new Proxy(obj, { + set(target, key) { + if (Array.isArray(target)) { + throw `Error Modifying Index: ${key}`; + } + throw `Error Modifying: ${key}`; + }, + + get(target, key) { + const value = target[key]; + + if (typeof value === 'object' && value !== null) { + return makeImmutable(value); + } + + if (typeof value === 'function') { + return new Proxy(value, { + apply(...args) { + if (mutatingMethods.has(key)) { + throw `Error Calling Method: ${key}`; + } + return Reflect.apply(...args); + } + }); + } + + return value; + } + }); +}; diff --git a/solutions/2700-differences-between-two-objects.js b/solutions/2700-differences-between-two-objects.js new file mode 100644 index 00000000..a62d9929 --- /dev/null +++ b/solutions/2700-differences-between-two-objects.js @@ -0,0 +1,50 @@ +/** + * 2700. Differences Between Two Objects + * https://leetcode.com/problems/differences-between-two-objects/ + * Difficulty: Medium + * + * Write a function that accepts two deeply nested objects or arrays obj1 and obj2 and returns + * a new object representing their differences. + * + * The function should compare the properties of the two objects and identify any changes. + * The returned object should only contains keys where the value is different from obj1 to obj2. + * + * For each changed key, the value should be represented as an array [obj1 value, obj2 value]. + * Keys that exist in one object but not in the other should not be included in the returned + * object. The end result should be a deeply nested object where each leaf value is a + * difference array. + * + * When comparing two arrays, the indices of the arrays are considered to be their keys. + * + * You may assume that both objects are the output of JSON.parse. + */ + +/** + * @param {Object|Array} obj1 + * @param {Object|Array} obj2 + * @return {Object|Array} + */ +function objDiff(obj1, obj2) { + if (obj1 === obj2) return {}; + + if (obj1 === null || obj2 === null || typeof obj1 !== typeof obj2 + || typeof obj1 !== 'object') { + return [obj1, obj2]; + } + + if (Array.isArray(obj1) !== Array.isArray(obj2)) { + return [obj1, obj2]; + } + + const result = {}; + for (const key in obj1) { + if (key in obj2) { + const difference = objDiff(obj1[key], obj2[key]); + if (Object.keys(difference).length > 0 || Array.isArray(difference)) { + result[key] = difference; + } + } + } + + return result; +} diff --git a/solutions/2702-minimum-operations-to-make-numbers-non-positive.js b/solutions/2702-minimum-operations-to-make-numbers-non-positive.js new file mode 100644 index 00000000..7834aac7 --- /dev/null +++ b/solutions/2702-minimum-operations-to-make-numbers-non-positive.js @@ -0,0 +1,50 @@ +/** + * 2702. Minimum Operations to Make Numbers Non-positive + * https://leetcode.com/problems/minimum-operations-to-make-numbers-non-positive/ + * Difficulty: Hard + * + * You are given a 0-indexed integer array nums and two integers x and y. In one operation, + * you must choose an index i such that 0 <= i < nums.length and perform the following: + * - Decrement nums[i] by x. + * - Decrement values by y at all indices except the ith one. + * + * Return the minimum number of operations to make all the integers in nums less than or equal + * to zero. + */ + +/** + * @param {number[]} nums + * @param {number} x + * @param {number} y + * @return {number} + */ +var minOperations = function(nums, x, y) { + let left = 0; + let right = Math.max(...nums); + + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (canMakeNonPositive(nums, x, y, mid)) { + right = mid; + } else { + left = mid + 1; + } + } + + return left; + + function canMakeNonPositive(nums, x, y, operations) { + const n = nums.length; + const remaining = nums.map(num => num - operations * y); + + let totalExtraNeeded = 0; + for (let i = 0; i < n; i++) { + if (remaining[i] > 0) { + const extraNeeded = Math.ceil(remaining[i] / (x - y)); + totalExtraNeeded += extraNeeded; + } + } + + return totalExtraNeeded <= operations; + } +}; diff --git a/solutions/2709-greatest-common-divisor-traversal.js b/solutions/2709-greatest-common-divisor-traversal.js new file mode 100644 index 00000000..0db68ad2 --- /dev/null +++ b/solutions/2709-greatest-common-divisor-traversal.js @@ -0,0 +1,79 @@ +/** + * 2709. Greatest Common Divisor Traversal + * https://leetcode.com/problems/greatest-common-divisor-traversal/ + * Difficulty: Hard + * + * You are given a 0-indexed integer array nums, and you are allowed to traverse between its + * indices. You can traverse between index i and index j, i != j, if and only if gcd(nums[i], + * nums[j]) > 1, where gcd is the greatest common divisor. + * + * Your task is to determine if for every pair of indices i and j in nums, where i < j, there + * exists a sequence of traversals that can take us from i to j. + * + * Return true if it is possible to traverse between all such pairs of indices, or false otherwise. + */ + +/** + * @param {number[]} nums + * @return {boolean} + */ +var canTraverseAllPairs = function(nums) { + if (nums.length === 1) return true; + const n = nums.length; + const maxNum = Math.max(...nums); + const parent = new Array(maxNum + 1).fill().map((_, i) => i); + const rank = new Array(maxNum + 1).fill(0); + + const primeToIndex = new Map(); + for (let i = 0; i < n; i++) { + if (nums[i] === 1) return false; + const factors = getPrimeFactors(nums[i]); + for (const prime of factors) { + if (primeToIndex.has(prime)) { + union(primeToIndex.get(prime), i); + } else { + primeToIndex.set(prime, i); + } + } + } + + const root = find(0); + for (let i = 1; i < n; i++) { + if (find(i) !== root) return false; + } + + return true; + + function find(x) { + if (parent[x] !== x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + function union(x, y) { + const px = find(x); + const py = find(y); + if (px === py) return; + if (rank[px] < rank[py]) { + parent[px] = py; + } else if (rank[px] > rank[py]) { + parent[py] = px; + } else { + parent[py] = px; + rank[px]++; + } + } + + function getPrimeFactors(num) { + const factors = []; + for (let i = 2; i * i <= num; i++) { + if (num % i === 0) { + factors.push(i); + while (num % i === 0) num /= i; + } + } + if (num > 1) factors.push(num); + return factors; + } +}; diff --git a/solutions/2710-remove-trailing-zeros-from-a-string.js b/solutions/2710-remove-trailing-zeros-from-a-string.js new file mode 100644 index 00000000..217d4552 --- /dev/null +++ b/solutions/2710-remove-trailing-zeros-from-a-string.js @@ -0,0 +1,16 @@ +/** + * 2710. Remove Trailing Zeros From a String + * https://leetcode.com/problems/remove-trailing-zeros-from-a-string/ + * Difficulty: Easy + * + * Given a positive integer num represented as a string, return the integer num without + * trailing zeros as a string. + */ + +/** + * @param {string} num + * @return {string} + */ +var removeTrailingZeros = function(num) { + return num.replace(/0+$/g, ''); +}; diff --git a/solutions/2711-difference-of-number-of-distinct-values-on-diagonals.js b/solutions/2711-difference-of-number-of-distinct-values-on-diagonals.js new file mode 100644 index 00000000..86d12ee8 --- /dev/null +++ b/solutions/2711-difference-of-number-of-distinct-values-on-diagonals.js @@ -0,0 +1,55 @@ +/** + * 2711. Difference of Number of Distinct Values on Diagonals + * https://leetcode.com/problems/difference-of-number-of-distinct-values-on-diagonals/ + * Difficulty: Medium + * + * Given a 2D grid of size m x n, you should find the matrix answer of size m x n. + * + * The cell answer[r][c] is calculated by looking at the diagonal values of the cell grid[r][c]: + * - Let leftAbove[r][c] be the number of distinct values on the diagonal to the left and above + * the cell grid[r][c] not including the cell grid[r][c] itself. + * - Let rightBelow[r][c] be the number of distinct values on the diagonal to the right and below + * the cell grid[r][c], not including the cell grid[r][c] itself. + * - Then answer[r][c] = |leftAbove[r][c] - rightBelow[r][c]|. + * + * A matrix diagonal is a diagonal line of cells starting from some cell in either the topmost + * row or leftmost column and going in the bottom-right direction until the end of the matrix + * is reached. + * + * - For example, in the below diagram the diagonal is highlighted using the cell with indices + * (2, 3) colored gray: + * - Red-colored cells are left and above the cell. + * - Blue-colored cells are right and below the cell. + */ + +/** + * @param {number[][]} grid + * @return {number[][]} + */ +var differenceOfDistinctValues = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const result = Array.from({ length: rows }, () => new Array(cols).fill(0)); + + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + const leftAboveSet = new Set(); + let i = r - 1; + let j = c - 1; + while (i >= 0 && j >= 0) { + leftAboveSet.add(grid[i--][j--]); + } + + const rightBelowSet = new Set(); + i = r + 1; + j = c + 1; + while (i < rows && j < cols) { + rightBelowSet.add(grid[i++][j++]); + } + + result[r][c] = Math.abs(leftAboveSet.size - rightBelowSet.size); + } + } + + return result; +}; diff --git a/solutions/2712-minimum-cost-to-make-all-characters-equal.js b/solutions/2712-minimum-cost-to-make-all-characters-equal.js new file mode 100644 index 00000000..bc70fa86 --- /dev/null +++ b/solutions/2712-minimum-cost-to-make-all-characters-equal.js @@ -0,0 +1,32 @@ +/** + * 2712. Minimum Cost to Make All Characters Equal + * https://leetcode.com/problems/minimum-cost-to-make-all-characters-equal/ + * Difficulty: Medium + * + * You are given a 0-indexed binary string s of length n on which you can apply two types + * of operations: + * - Choose an index i and invert all characters from index 0 to index i (both inclusive), + * with a cost of i + 1 + * - Choose an index i and invert all characters from index i to index n - 1 (both inclusive), + * with a cost of n - i + * + * Return the minimum cost to make all characters of the string equal. + * + * Invert a character means if its value is '0' it becomes '1' and vice-versa. + */ + +/** + * @param {string} s + * @return {number} + */ +var minimumCost = function(s) { + let result = 0; + + for (let i = 1; i < s.length; i++) { + if (s[i] !== s[i - 1]) { + result += Math.min(i, s.length - i); + } + } + + return result; +}; diff --git a/solutions/2714-find-shortest-path-with-k-hops.js b/solutions/2714-find-shortest-path-with-k-hops.js new file mode 100644 index 00000000..015a2aec --- /dev/null +++ b/solutions/2714-find-shortest-path-with-k-hops.js @@ -0,0 +1,62 @@ +/** + * 2714. Find Shortest Path with K Hops + * https://leetcode.com/problems/find-shortest-path-with-k-hops/ + * Difficulty: Hard + * + * You are given a positive integer n which is the number of nodes of a 0-indexed undirected + * weighted connected graph and a 0-indexed 2D array edges where edges[i] = [ui, vi, wi] + * indicates that there is an edge between nodes ui and vi with weight wi. + * + * You are also given two nodes s and d, and a positive integer k, your task is to find the + * shortest path from s to d, but you can hop over at most k edges. In other words, make the + * weight of at most k edges 0 and then find the shortest path from s to d. + * + * Return the length of the shortest path from s to d with the given condition. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number} s + * @param {number} d + * @param {number} k + * @return {number} + */ +var shortestPathWithHops = function(n, edges, s, d, k) { + const graph = new Array(n).fill().map(() => []); + + for (const [u, v, w] of edges) { + graph[u].push([v, w]); + graph[v].push([u, w]); + } + + const dist = new Array(n).fill().map(() => new Array(k + 1).fill(Infinity)); + const visited = new Array(n).fill().map(() => new Array(k + 1).fill(false)); + const pq = new PriorityQueue((a, b) => a[0] - b[0]); + + pq.enqueue([0, k, s]); + + while (!pq.isEmpty()) { + const [currentDist, hopsLeft, node] = pq.dequeue(); + + if (visited[node][hopsLeft]) continue; + visited[node][hopsLeft] = true; + + if (node === d) return currentDist; + + for (const [neighbor, weight] of graph[node]) { + const newDist = currentDist + weight; + if (newDist < dist[neighbor][hopsLeft]) { + dist[neighbor][hopsLeft] = newDist; + pq.enqueue([newDist, hopsLeft, neighbor]); + } + + if (hopsLeft > 0 && currentDist < dist[neighbor][hopsLeft - 1]) { + dist[neighbor][hopsLeft - 1] = currentDist; + pq.enqueue([currentDist, hopsLeft - 1, neighbor]); + } + } + } + + return -1; +}; diff --git a/solutions/2716-minimize-string-length.js b/solutions/2716-minimize-string-length.js new file mode 100644 index 00000000..b16b102b --- /dev/null +++ b/solutions/2716-minimize-string-length.js @@ -0,0 +1,23 @@ +/** + * 2716. Minimize String Length + * https://leetcode.com/problems/minimize-string-length/ + * Difficulty: Easy + * + * Given a string s, you have two types of operation: + * 1. Choose an index i in the string, and let c be the character in position i. Delete the + * closest occurrence of c to the left of i (if exists). + * 2. Choose an index i in the string, and let c be the character in position i. Delete the + * closest occurrence of c to the right of i (if exists). + * + * Your task is to minimize the length of s by performing the above operations zero or more times. + * + * Return an integer denoting the length of the minimized string. + */ + +/** + * @param {string} s + * @return {number} + */ +var minimizedStringLength = function(s) { + return new Set(s).size; +}; diff --git a/solutions/2717-semi-ordered-permutation.js b/solutions/2717-semi-ordered-permutation.js new file mode 100644 index 00000000..b1717e3c --- /dev/null +++ b/solutions/2717-semi-ordered-permutation.js @@ -0,0 +1,33 @@ +/** + * 2717. Semi-Ordered Permutation + * https://leetcode.com/problems/semi-ordered-permutation/ + * Difficulty: Easy + * + * You are given a 0-indexed permutation of n integers nums. + * + * A permutation is called semi-ordered if the first number equals 1 and the last number equals n. + * You can perform the below operation as many times as you want until you make nums a semi-ordered + * permutation: + * - Pick two adjacent elements in nums, then swap them. + * + * Return the minimum number of operations to make nums a semi-ordered permutation. + * + * A permutation is a sequence of integers from 1 to n of length n containing each number exactly + * once. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var semiOrderedPermutation = function(nums) { + let oneIndex = 0; + let nIndex = 0; + + for (let i = 0; i < nums.length; i++) { + if (nums[i] === 1) oneIndex = i; + if (nums[i] === nums.length) nIndex = i; + } + + return oneIndex + (nums.length - 1 - nIndex) - (oneIndex > nIndex ? 1 : 0); +}; diff --git a/solutions/2728-count-houses-in-a-circular-street.js b/solutions/2728-count-houses-in-a-circular-street.js new file mode 100644 index 00000000..936f1699 --- /dev/null +++ b/solutions/2728-count-houses-in-a-circular-street.js @@ -0,0 +1,68 @@ +/** + * 2728. Count Houses in a Circular Street + * https://leetcode.com/problems/count-houses-in-a-circular-street/ + * Difficulty: Easy + * + * You are given an object street of class Street that represents a circular street and a positive + * integer k which represents a maximum bound for the number of houses in that street (in other + * words, the number of houses is less than or equal to k). Houses' doors could be open or closed + * initially. + * + * Initially, you are standing in front of a door to a house on this street. Your task is to count + * the number of houses in the street. + * + * The class Street contains the following functions which may help you: + * - void openDoor(): Open the door of the house you are in front of. + * - void closeDoor(): Close the door of the house you are in front of. + * - boolean isDoorOpen(): Returns true if the door of the current house is open and false + * otherwise. + * - void moveRight(): Move to the right house. + * - void moveLeft(): Move to the left house. + * + * Return ans which represents the number of houses on this street. + */ + +/** + * Definition for a street. + * class Street { + * @param {number[]} doors + * constructor(doors); + * + * @return {void} + * openDoor(); + * + * @return {void} + * closeDoor(); + * + * @return {boolean} + * isDoorOpen(); + * + * @return {void} + * moveRight(); + * + * @return {void} + * moveLeft(); + * } + */ +/** + * @param {Street} street + * @param {number} k + * @return {number} + */ +var houseCount = function(street, k) { + for (let i = 0; i < k; i++) { + street.closeDoor(); + street.moveLeft(); + } + + street.openDoor(); + let count = 1; + + street.moveLeft(); + while (!street.isDoorOpen()) { + street.moveLeft(); + count++; + } + + return count; +}; diff --git a/solutions/2729-check-if-the-number-is-fascinating.js b/solutions/2729-check-if-the-number-is-fascinating.js new file mode 100644 index 00000000..12537342 --- /dev/null +++ b/solutions/2729-check-if-the-number-is-fascinating.js @@ -0,0 +1,26 @@ +/** + * 2729. Check if The Number is Fascinating + * https://leetcode.com/problems/check-if-the-number-is-fascinating/ + * Difficulty: Easy + * + * You are given an integer n that consists of exactly 3 digits. + * + * We call the number n fascinating if, after the following modification, the resulting number + * contains all the digits from 1 to 9 exactly once and does not contain any 0's: + * - Concatenate n with the numbers 2 * n and 3 * n. + * + * Return true if n is fascinating, or false otherwise. + * + * Concatenating two numbers means joining them together. For example, the concatenation of 121 + * and 371 is 121371. + */ + +/** + * @param {number} n + * @return {boolean} + */ +var isFascinating = function(n) { + const concatenated = `${n}${2 * n}${3 * n}`; + const digitSet = new Set(concatenated); + return concatenated.length === 9 && digitSet.size === 9 && !digitSet.has('0'); +}; diff --git a/solutions/2732-find-a-good-subset-of-the-matrix.js b/solutions/2732-find-a-good-subset-of-the-matrix.js new file mode 100644 index 00000000..1e13f830 --- /dev/null +++ b/solutions/2732-find-a-good-subset-of-the-matrix.js @@ -0,0 +1,48 @@ +/** + * 2732. Find a Good Subset of the Matrix + * https://leetcode.com/problems/find-a-good-subset-of-the-matrix/ + * Difficulty: Hard + * + * You are given a 0-indexed m x n binary matrix grid. + * + * Let us call a non-empty subset of rows good if the sum of each column of the subset is at + * most half of the length of the subset. + * + * More formally, if the length of the chosen subset of rows is k, then the sum of each column + * should be at most floor(k / 2). + * + * Return an integer array that contains row indices of a good subset sorted in ascending order. + * + * If there are multiple good subsets, you can return any of them. If there are no good subsets, + * return an empty array. + * + * A subset of rows of the matrix grid is any matrix that can be obtained by deleting some (possibly + * none or all) rows from grid. + */ + +/** + * @param {number[][]} grid + * @return {number[]} + */ +var goodSubsetofBinaryMatrix = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const rowMasks = new Map(); + + for (let i = 0; i < rows; i++) { + let mask = 0; + for (let j = 0; j < cols; j++) { + mask |= grid[i][j] << j; + } + if (mask === 0) return [i]; + rowMasks.set(mask, i); + } + + for (const [mask1, i] of rowMasks) { + for (const [mask2, j] of rowMasks) { + if ((mask1 & mask2) === 0) return [Math.min(i, j), Math.max(i, j)]; + } + } + + return []; +}; diff --git a/solutions/2733-neither-minimum-nor-maximum.js b/solutions/2733-neither-minimum-nor-maximum.js new file mode 100644 index 00000000..4dcc9150 --- /dev/null +++ b/solutions/2733-neither-minimum-nor-maximum.js @@ -0,0 +1,27 @@ +/** + * 2733. Neither Minimum nor Maximum + * https://leetcode.com/problems/neither-minimum-nor-maximum/ + * Difficulty: Easy + * + * Given an integer array nums containing distinct positive integers, find and return any + * number from the array that is neither the minimum nor the maximum value in the array, + * or -1 if there is no such number. + * + * Return the selected integer. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var findNonMinOrMax = function(nums) { + if (nums.length < 3) return -1; + const minVal = Math.min(nums[0], nums[1], nums[2]); + const maxVal = Math.max(nums[0], nums[1], nums[2]); + + for (const num of [nums[0], nums[1], nums[2]]) { + if (num !== minVal && num !== maxVal) return num; + } + + return -1; +}; diff --git a/solutions/2737-find-the-closest-marked-node.js b/solutions/2737-find-the-closest-marked-node.js new file mode 100644 index 00000000..dc8cba75 --- /dev/null +++ b/solutions/2737-find-the-closest-marked-node.js @@ -0,0 +1,56 @@ +/** + * 2737. Find the Closest Marked Node + * https://leetcode.com/problems/find-the-closest-marked-node/ + * Difficulty: Medium + * + * You are given a positive integer n which is the number of nodes of a 0-indexed directed + * weighted graph and a 0-indexed 2D array edges where edges[i] = [ui, vi, wi] indicates + * that there is an edge from node ui to node vi with weight wi. + * + * You are also given a node s and a node array marked; your task is to find the minimum + * distance from s to any of the nodes in marked. + * + * Return an integer denoting the minimum distance from s to any node in marked or -1 if + * there are no paths from s to any of the marked nodes. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number} s + * @param {number[]} marked + * @return {number} + */ +var minimumDistance = function(n, edges, s, marked) { + const graph = new Array(n).fill().map(() => []); + const markedSet = new Set(marked); + + for (const [u, v, w] of edges) { + graph[u].push([v, w]); + } + + const distances = new Array(n).fill(Infinity); + const pq = new PriorityQueue((a, b) => a[0] - b[0]); + distances[s] = 0; + pq.enqueue([0, s]); + + while (!pq.isEmpty()) { + const [currentDist, node] = pq.dequeue(); + + if (currentDist > distances[node]) continue; + + if (markedSet.has(node)) { + return currentDist; + } + + for (const [neighbor, weight] of graph[node]) { + const newDist = currentDist + weight; + if (newDist < distances[neighbor]) { + distances[neighbor] = newDist; + pq.enqueue([newDist, neighbor]); + } + } + } + + return -1; +}; diff --git a/solutions/2739-total-distance-traveled.js b/solutions/2739-total-distance-traveled.js new file mode 100644 index 00000000..2c2d593d --- /dev/null +++ b/solutions/2739-total-distance-traveled.js @@ -0,0 +1,38 @@ +/** + * 2739. Total Distance Traveled + * https://leetcode.com/problems/total-distance-traveled/ + * Difficulty: Easy + * + * A truck has two fuel tanks. You are given two integers, mainTank representing the fuel present + * in the main tank in liters and additionalTank representing the fuel present in the additional + * tank in liters. + * + * The truck has a mileage of 10 km per liter. Whenever 5 liters of fuel get used up in the main + * tank, if the additional tank has at least 1 liters of fuel, 1 liters of fuel will be transferred + * from the additional tank to the main tank. + * + * Return the maximum distance which can be traveled. + * + * Note: Injection from the additional tank is not continuous. It happens suddenly and immediately + * for every 5 liters consumed. + */ + +/** + * @param {number} mainTank + * @param {number} additionalTank + * @return {number} + */ +var distanceTraveled = function(mainTank, additionalTank) { + let distance = 0; + let fuel = mainTank; + + while (fuel >= 5 && additionalTank > 0) { + distance += 50; + fuel -= 5; + fuel += 1; + additionalTank -= 1; + } + + distance += fuel * 10; + return distance; +}; diff --git a/solutions/2740-find-the-value-of-the-partition.js b/solutions/2740-find-the-value-of-the-partition.js new file mode 100644 index 00000000..8c1f661e --- /dev/null +++ b/solutions/2740-find-the-value-of-the-partition.js @@ -0,0 +1,34 @@ +/** + * 2740. Find the Value of the Partition + * https://leetcode.com/problems/find-the-value-of-the-partition/ + * Difficulty: Medium + * + * You are given a positive integer array nums. + * + * Partition nums into two arrays, nums1 and nums2, such that: + * - Each element of the array nums belongs to either the array nums1 or the array nums2. + * - Both arrays are non-empty. + * - The value of the partition is minimized. + * + * The value of the partition is |max(nums1) - min(nums2)|. + * + * Here, max(nums1) denotes the maximum element of the array nums1, and min(nums2) denotes the + * minimum element of the array nums2. + * + * Return the integer denoting the value of such partition. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var findValueOfPartition = function(nums) { + nums.sort((a, b) => a - b); + let result = Infinity; + + for (let i = 1; i < nums.length; i++) { + result = Math.min(result, nums[i] - nums[i - 1]); + } + + return result; +}; diff --git a/solutions/2742-painting-the-walls.js b/solutions/2742-painting-the-walls.js new file mode 100644 index 00000000..42275242 --- /dev/null +++ b/solutions/2742-painting-the-walls.js @@ -0,0 +1,38 @@ +/** + * 2742. Painting the Walls + * https://leetcode.com/problems/painting-the-walls/ + * Difficulty: Hard + * + * You are given two 0-indexed integer arrays, cost and time, of size n representing the costs + * and the time taken to paint n different walls respectively. There are two painters available: + * - A paid painter that paints the ith wall in time[i] units of time and takes cost[i] units of + * money. + * - A free painter that paints any wall in 1 unit of time at a cost of 0. But the free painter + * can only be used if the paid painter is already occupied. + * + * Return the minimum amount of money required to paint the n walls. + */ + +/** + * @param {number[]} cost + * @param {number[]} time + * @return {number} + */ +var paintWalls = function(cost, time) { + const n = cost.length; + const dp = new Array(n + 1).fill().map(() => new Array(n + 1).fill(Infinity)); + dp[0][0] = 0; + + for (let i = 0; i < n; i++) { + for (let j = 0; j <= n; j++) { + if (dp[i][j] === Infinity) continue; + + dp[i + 1][j] = Math.min(dp[i + 1][j], dp[i][j]); + + const walls = Math.min(n, j + time[i] + 1); + dp[i + 1][walls] = Math.min(dp[i + 1][walls], dp[i][j] + cost[i]); + } + } + + return dp[n][n]; +}; diff --git a/solutions/2743-count-substrings-without-repeating-character.js b/solutions/2743-count-substrings-without-repeating-character.js new file mode 100644 index 00000000..37dce1d2 --- /dev/null +++ b/solutions/2743-count-substrings-without-repeating-character.js @@ -0,0 +1,45 @@ +/** + * 2743. Count Substrings Without Repeating Character + * https://leetcode.com/problems/count-substrings-without-repeating-character/ + * Difficulty: Medium + * + * You are given a string s consisting only of lowercase English letters. We call a substring + * special if it contains no character which has occurred at least twice (in other words, it + * does not contain a repeating character). Your task is to count the number of special + * substrings. For example, in the string "pop", the substring "po" is a special substring, + * however, "pop" is not special (since 'p' has occurred twice). + * + * Return the number of special substrings. + * + * A substring is a contiguous sequence of characters within a string. For example, "abc" is + * a substring of "abcd", but "acd" is not. + */ + +/** + * @param {string} s + * @return {number} + */ +var numberOfSpecialSubstrings = function(s) { + const n = s.length; + const map = new Map(); + let result = 0; + let left = 0; + + for (let right = 0; right < n; right++) { + const char = s[right]; + map.set(char, (map.get(char) || 0) + 1); + + while (map.get(char) > 1) { + const leftChar = s[left]; + map.set(leftChar, map.get(leftChar) - 1); + if (map.get(leftChar) === 0) { + map.delete(leftChar); + } + left++; + } + + result += right - left + 1; + } + + return result; +}; diff --git a/solutions/2744-find-maximum-number-of-string-pairs.js b/solutions/2744-find-maximum-number-of-string-pairs.js new file mode 100644 index 00000000..b8e9a4ac --- /dev/null +++ b/solutions/2744-find-maximum-number-of-string-pairs.js @@ -0,0 +1,36 @@ +/** + * 2744. Find Maximum Number of String Pairs + * https://leetcode.com/problems/find-maximum-number-of-string-pairs/ + * Difficulty: Easy + * + * You are given a 0-indexed array words consisting of distinct strings. + * + * The string words[i] can be paired with the string words[j] if: + * - The string words[i] is equal to the reversed string of words[j]. + * - 0 <= i < j < words.length. + * + * Return the maximum number of pairs that can be formed from the array words. + * + * Note that each string can belong in at most one pair. + */ + +/** + * @param {string[]} words + * @return {number} + */ +var maximumNumberOfStringPairs = function(words) { + const set = new Set(); + let result = 0; + + for (const word of words) { + const reversed = word[1] + word[0]; + if (set.has(reversed)) { + result++; + set.delete(reversed); + } else { + set.add(word); + } + } + + return result; +}; diff --git a/solutions/2745-construct-the-longest-new-string.js b/solutions/2745-construct-the-longest-new-string.js new file mode 100644 index 00000000..c5014fa7 --- /dev/null +++ b/solutions/2745-construct-the-longest-new-string.js @@ -0,0 +1,26 @@ +/** + * 2745. Construct the Longest New String + * https://leetcode.com/problems/construct-the-longest-new-string/ + * Difficulty: Medium + * + * You are given three integers x, y, and z. + * + * You have x strings equal to "AA", y strings equal to "BB", and z strings equal to "AB". You + * want to choose some (possibly all or none) of these strings and concatenate them in some order + * to form a new string. This new string must not contain "AAA" or "BBB" as a substring. + * + * Return the maximum possible length of the new string. + * + * A substring is a contiguous non-empty sequence of characters within a string. + */ + +/** + * @param {number} x + * @param {number} y + * @param {number} z + * @return {number} + */ +var longestString = function(x, y, z) { + const minPairs = Math.min(x, y); + return 2 * (minPairs * 2 + (x > minPairs ? 1 : 0) + (y > minPairs ? 1 : 0) + z); +}; diff --git a/solutions/2748-number-of-beautiful-pairs.js b/solutions/2748-number-of-beautiful-pairs.js new file mode 100644 index 00000000..28e7a52f --- /dev/null +++ b/solutions/2748-number-of-beautiful-pairs.js @@ -0,0 +1,53 @@ +/** + * 2748. Number of Beautiful Pairs + * https://leetcode.com/problems/number-of-beautiful-pairs/ + * Difficulty: Easy + * + * You are given a 0-indexed integer array nums. A pair of indices i, j where + * 0 <= i < j < nums.length is called beautiful if the first digit of nums[i] and + * the last digit of nums[j] are coprime. + * + * Return the total number of beautiful pairs in nums. + * + * Two integers x and y are coprime if there is no integer greater than 1 that divides + * both of them. In other words, x and y are coprime if gcd(x, y) == 1, where gcd(x, y) + * is the greatest common divisor of x and y. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var countBeautifulPairs = function(nums) { + let result = 0; + for (let i = 0; i < nums.length - 1; i++) { + for (let j = i + 1; j < nums.length; j++) { + const first = getFirstDigit(nums[i]); + const last = getLastDigit(nums[j]); + if (gcd(first, last) === 1) { + result++; + } + } + } + + return result; + + function gcd(a, b) { + while (b) { + a %= b; + [a, b] = [b, a]; + } + return a; + } + + function getFirstDigit(num) { + while (num >= 10) { + num = Math.floor(num / 10); + } + return num; + } + + function getLastDigit(num) { + return num % 10; + } +}; diff --git a/solutions/2749-minimum-operations-to-make-the-integer-zero.js b/solutions/2749-minimum-operations-to-make-the-integer-zero.js new file mode 100644 index 00000000..c837f351 --- /dev/null +++ b/solutions/2749-minimum-operations-to-make-the-integer-zero.js @@ -0,0 +1,43 @@ +/** + * 2749. Minimum Operations to Make the Integer Zero + * https://leetcode.com/problems/minimum-operations-to-make-the-integer-zero/ + * Difficulty: Medium + * + * You are given two integers num1 and num2. + * + * In one operation, you can choose integer i in the range [0, 60] and subtract 2i + num2 from num1. + * + * Return the integer denoting the minimum number of operations needed to make num1 equal to 0. + * + * If it is impossible to make num1 equal to 0, return -1. + */ + +/** + * @param {number} num1 + * @param {number} num2 + * @return {number} + */ +var makeTheIntegerZero = function(num1, num2) { + for (let operations = 1; operations <= 60; operations++) { + const remaining = num1 - num2 * operations; + + if (remaining < operations) { + return -1; + } + + if (operations >= countBits(remaining)) { + return operations; + } + } + + return -1; + + function countBits(n) { + let count = 0; + while (n > 0) { + count += n & 1; + n = Math.floor(n / 2); + } + return count; + } +}; diff --git a/solutions/2751-robot-collisions.js b/solutions/2751-robot-collisions.js new file mode 100644 index 00000000..53149178 --- /dev/null +++ b/solutions/2751-robot-collisions.js @@ -0,0 +1,76 @@ +/** + * 2751. Robot Collisions + * https://leetcode.com/problems/robot-collisions/ + * Difficulty: Hard + * + * There are n 1-indexed robots, each having a position on a line, health, and movement direction. + * + * You are given 0-indexed integer arrays positions, healths, and a string directions (directions[i] + * is either 'L' for left or 'R' for right). All integers in positions are unique. + * + * All robots start moving on the line simultaneously at the same speed in their given directions. + * If two robots ever share the same position while moving, they will collide. + * + * If two robots collide, the robot with lower health is removed from the line, and the health of + * the other robot decreases by one. The surviving robot continues in the same direction it was + * going. If both robots have the same health, they are both removed from the line. + * + * Your task is to determine the health of the robots that survive the collisions, in the same + * order that the robots were given, i.e. final health of robot 1 (if survived), final health + * of robot 2 (if survived), and so on. If there are no survivors, return an empty array. + * + * Return an array containing the health of the remaining robots (in the order they were given + * in the input), after no further collisions can occur. + * + * Note: The positions may be unsorted. + */ + +/** + * @param {number[]} positions + * @param {number[]} healths + * @param {string} directions + * @return {number[]} + */ +var survivedRobotsHealths = function(positions, healths, directions) { + const n = positions.length; + const robots = Array.from({ length: n }, (_, i) => ({ + index: i, + position: positions[i], + health: healths[i], + direction: directions[i] + })); + + robots.sort((a, b) => a.position - b.position); + + const stack = []; + for (const robot of robots) { + if (robot.direction === 'R') { + stack.push(robot); + continue; + } + + while (stack.length && stack[stack.length - 1].direction === 'R' && robot.health > 0) { + const last = stack[stack.length - 1]; + if (last.health === robot.health) { + stack.pop(); + robot.health = 0; + } else if (last.health > robot.health) { + last.health--; + robot.health = 0; + } else { + stack.pop(); + robot.health--; + } + } + if (robot.health > 0) { + stack.push(robot); + } + } + + const result = new Array(n).fill(0); + for (const robot of stack) { + result[robot.index] = robot.health; + } + + return result.filter(health => health > 0); +}; diff --git a/solutions/2753-count-houses-in-a-circular-street-ii.js b/solutions/2753-count-houses-in-a-circular-street-ii.js new file mode 100644 index 00000000..66f385ab --- /dev/null +++ b/solutions/2753-count-houses-in-a-circular-street-ii.js @@ -0,0 +1,77 @@ +/** + * 2753. Count Houses in a Circular Street II + * https://leetcode.com/problems/count-houses-in-a-circular-street-ii/ + * Difficulty: Hard + * + * You are given an object street of class Street that represents a circular street and a positive + * integer k which represents a maximum bound for the number of houses in that street (in other + * words, the number of houses is less than or equal to k). Houses' doors could be open or closed + * initially (at least one is open). + * + * Initially, you are standing in front of a door to a house on this street. Your task is to count + * the number of houses in the street. + * + * The class Street contains the following functions which may help you: + * - void closeDoor(): Close the door of the house you are in front of. + * - boolean isDoorOpen(): Returns true if the door of the current house is open and false + * otherwise. + * - void moveRight(): Move to the right house. + * + * Note that by circular street, we mean if you number the houses from 1 to n, then the right house + * of housei is housei+1 for i < n, and the right house of housen is house1. + * + * Return ans which represents the number of houses on this street. + */ + +/** + * Definition for a street. + * class Street { + * @param {number[]} doors + * constructor(doors); + * + * @return {void} + * closeDoor(); + * + * @return {boolean} + * isDoorOpen(); + * + * @return {void} + * moveRight(); + * } + */ +/** + * @param {Street} street + * @param {number} k + * @return {number} + */ +var houseCount = function(street, k) { + let result = 0; + + while (true) { + tryMoveToOpen(street, k, true); + const distance = tryMoveToOpen(street, k, false); + + if (distance > k) { + return result; + } + + result = distance; + street.closeDoor(); + } + + function tryMoveToOpen(street, k, considerCurrent) { + if (street.isDoorOpen() && considerCurrent) { + return 0; + } + + let moves = 1; + street.moveRight(); + + while (!street.isDoorOpen() && moves <= k) { + street.moveRight(); + moves++; + } + + return moves; + } +}; diff --git a/solutions/2754-bind-function-to-context.js b/solutions/2754-bind-function-to-context.js new file mode 100644 index 00000000..169a61ba --- /dev/null +++ b/solutions/2754-bind-function-to-context.js @@ -0,0 +1,38 @@ +/** + * 2754. Bind Function to Context + * https://leetcode.com/problems/bind-function-to-context/ + * Difficulty: Medium + * + * Enhance all functions to have the bindPolyfill method. When bindPolyfill is called with + * a passed object obj, that object becomes the this context for the function. + * + * For example, if you had the code: + * function f() { + * console.log('My context is ' + this.ctx); + * } + * f(); + * + * The output would be "My context is undefined". However, if you bound the function: + * function f() { + * console.log('My context is ' + this.ctx); + * } + * const boundFunc = f.boundPolyfill({ "ctx": "My Object" }) + * boundFunc(); + * + * The output should be "My context is My Object". + * + * You may assume that a single non-null object will be passed to the bindPolyfill method. + * + * Please solve it without the built-in Function.bind method. + */ + +/** + * @param {Object} obj + * @return {Function} + */ +Function.prototype.bindPolyfill = function(obj) { + var fn = this; + return function() { + return fn.apply(obj, arguments); + }; +}; diff --git a/solutions/2755-deep-merge-of-two-objects.js b/solutions/2755-deep-merge-of-two-objects.js new file mode 100644 index 00000000..f9775813 --- /dev/null +++ b/solutions/2755-deep-merge-of-two-objects.js @@ -0,0 +1,59 @@ +/** + * 2755. Deep Merge of Two Objects + * https://leetcode.com/problems/deep-merge-of-two-objects/ + * Difficulty: Medium + * + * Given two values obj1 and obj2, return a deepmerged value. + * + * Values should be deepmerged according to these rules: + * - If the two values are objects, the resulting object should have all the keys that exist + * on either object. If a key belongs to both objects, deepmerge the two associated values. + * Otherwise, add the key-value pair to the resulting object. + * - If the two values are arrays, the resulting array should be the same length as the longer + * array. Apply the same logic as you would with objects, but treat the indices as keys. + * - Otherwise the resulting value is obj2. + * + * You can assume obj1 and obj2 are the output of JSON.parse(). + */ + +/** + * @param {null|boolean|number|string|Array|Object} obj1 + * @param {null|boolean|number|string|Array|Object} obj2 + * @return {null|boolean|number|string|Array|Object} + */ +var deepMerge = function(obj1, obj2) { + if (obj2 === null || typeof obj2 !== 'object') { + return obj2; + } + + if (obj1 === null || typeof obj1 !== 'object') { + return obj2; + } + + if (Array.isArray(obj1) !== Array.isArray(obj2)) { + return obj2; + } + + if (Array.isArray(obj1)) { + const maxLength = Math.max(obj1.length, obj2.length); + const result = []; + + for (let i = 0; i < maxLength; i++) { + if (i < obj2.length) { + result[i] = deepMerge(obj1[i], obj2[i]); + } else { + result[i] = obj1[i]; + } + } + + return result; + } + + const result = { ...obj1 }; + + Object.keys(obj2).forEach(key => { + result[key] = deepMerge(obj1[key], obj2[key]); + }); + + return result; +}; diff --git a/solutions/2756-query-batching.js b/solutions/2756-query-batching.js new file mode 100644 index 00000000..56072f39 --- /dev/null +++ b/solutions/2756-query-batching.js @@ -0,0 +1,80 @@ +/** + * 2756. Query Batching + * https://leetcode.com/problems/query-batching/ + * Difficulty: Hard + * + * Batching multiple small queries into a single large query can be a useful optimization. + * Write a class QueryBatcher that implements this functionality. + * + * The constructor should accept two parameters: + * - An asynchronous function queryMultiple which accepts an array of string keys input. It will + * resolve with an array of values that is the same length as the input array. Each index + * corresponds to the value associated with input[i]. You can assume the promise will never + * reject. + * - A throttle time in milliseconds t. + * + * The class has a single method. + * - async getValue(key). Accepts a single string key and resolves with a single string value. + * The keys passed to this function should eventually get passed to the queryMultiple function. + * queryMultiple should never be called consecutively within t milliseconds. The first time + * getValue is called, queryMultiple should immediately be called with that single key. + * If after t milliseconds, getValue had been called again, all the passed keys should be + * passed to queryMultiple and ultimately returned. You can assume every key passed to this + * method is unique. + * + * The following diagram illustrates how the throttling algorithm works. Each rectangle represents + * 100ms. The throttle time is 400ms. + */ + +/** + * @param {Function} queryMultiple + * @param {number} t + * @return {void} + */ +var QueryBatcher = function(queryMultiple, t) { + this.queryMultiple = queryMultiple; + this.throttleTime = t; + this.pendingRequests = []; + this.batchTimer = null; + this.lastExecutionTime = 0; +}; + +/** + * @param {string} key + * @return {Promise} + */ +QueryBatcher.prototype.getValue = function(key) { + return new Promise((resolve) => { + const currentTime = Date.now(); + const timeSinceLastExecution = currentTime - this.lastExecutionTime; + const remainingDelay = Math.max(0, this.throttleTime - timeSinceLastExecution); + + this.lastExecutionTime = currentTime + remainingDelay; + + this.pendingRequests.push({ key, resolve }); + + if (!this.batchTimer) { + clearTimeout(this.batchTimer); + this.batchTimer = setTimeout(() => this.executeBatch(), remainingDelay); + } + }); +}; + +/** + * @return {Promise} + */ +QueryBatcher.prototype.executeBatch = async function() { + const currentBatch = this.pendingRequests.slice(); + this.pendingRequests = []; + this.batchTimer = null; + + const keys = currentBatch.map((request) => request.key); + const resolvers = currentBatch.map((request) => request.resolve); + + this.lastExecutionTime = Date.now(); + const results = await this.queryMultiple(keys); + + for (let i = 0; i < keys.length; i++) { + resolvers[i](results[i]); + } +}; diff --git a/solutions/2757-generate-circular-array-values.js b/solutions/2757-generate-circular-array-values.js new file mode 100644 index 00000000..260384e6 --- /dev/null +++ b/solutions/2757-generate-circular-array-values.js @@ -0,0 +1,34 @@ +/** + * 2757. Generate Circular Array Values + * https://leetcode.com/problems/generate-circular-array-values/ + * Difficulty: Medium + * + * Given a circular array arr and an integer startIndex, return a generator object gen that + * yields values from arr. + * + * The first time gen.next() is called on the generator, it should should yield arr[startIndex]. + * + * Each subsequent time gen.next() is called, an integer jump will be passed into the function + * (Ex: gen.next(-3)). + * - If jump is positive, the index should increase by that value, however if the current index + * is the last index, it should instead jump to the first index. + * - If jump is negative, the index should decrease by the magnitude of that value, however if + * the current index is the first index, it should instead jump to the last index. + */ + +/** + * @param {Array} arr + * @param {number} startIndex + * @yields {number} + */ +var cycleGenerator = function* (arr, startIndex) { + let currentIndex = startIndex; + + while (true) { + const jump = yield arr[currentIndex]; + + if (jump !== undefined) { + currentIndex = ((currentIndex + jump) % arr.length + arr.length) % arr.length; + } + } +}; diff --git a/solutions/2758-next-day.js b/solutions/2758-next-day.js new file mode 100644 index 00000000..9ec99596 --- /dev/null +++ b/solutions/2758-next-day.js @@ -0,0 +1,17 @@ +/** + * 2758. Next Day + * https://leetcode.com/problems/next-day/ + * Difficulty: Easy + * + * Write code that enhances all date objects such that you can call the date.nextDay() method + * on any date object and it will return the next day in the format YYYY-MM-DD as a string. + */ + +/** + * @return {string} + */ +Date.prototype.nextDay = function() { + const nextDate = new Date(this); + nextDate.setDate(nextDate.getDate() + 1); + return nextDate.toISOString().split('T')[0]; +} diff --git a/solutions/2759-convert-json-string-to-object.js b/solutions/2759-convert-json-string-to-object.js new file mode 100644 index 00000000..4157918e --- /dev/null +++ b/solutions/2759-convert-json-string-to-object.js @@ -0,0 +1,82 @@ +/** + * 2759. Convert JSON String to Object + * https://leetcode.com/problems/convert-json-string-to-object/ + * Difficulty: Hard + * + * Given a string str, return parsed JSON parsedStr. You may assume the str is a valid JSON + * string hence it only includes strings, numbers, arrays, objects, booleans, and null. str + * will not include invisible characters and escape characters. + * + * Please solve it without using the built-in JSON.parse method. + */ + +/** + * @param {string} str + * @return {null|boolean|number|string|Array|Object} + */ +var jsonParse = function(str) { + const length = str.length; + const stack = []; + let currentValue = null; + let pendingKey = null; + + for (let index = 0; index < length; index++) { + if (str[index] === ',') continue; + + if (str[index] === '[' || str[index] === '{') { + stack.push(currentValue); + let newContainer = null; + if (str[index] === '[') newContainer = []; + else newContainer = {}; + + if (Array.isArray(currentValue)) currentValue.push(newContainer); + else if (pendingKey !== null) { + currentValue[pendingKey] = newContainer; + pendingKey = null; + } + currentValue = newContainer; + } else if (str[index] === ']' || str[index] === '}') { + const previousValue = stack.pop(); + if (index !== length - 1) currentValue = previousValue; + } else { + let parsedValue = null; + + if (str[index] === '"') { + const startIndex = index + 1; + while (index + 1 < length && str[index + 1] !== '"') index++; + parsedValue = str.substring(startIndex, index + 1); + index++; + } else if (str[index] === '-' || ('0' <= str[index] && str[index] <= '9')) { + const startIndex = index; + while (index + 1 < length && (str[index + 1] === '-' + || ('0' <= str[index + 1] && str[index + 1] <= '9') || str[index + 1] === '.')) { + index++; + } + parsedValue = Number(str.substring(startIndex, index + 1)); + } else { + if (index + 4 <= length && str.substring(index, index + 4) === 'true') { + parsedValue = true; + } else if (index + 5 <= length && str.substring(index, index + 5) === 'false') { + parsedValue = false; + } else { + parsedValue = null; + } + index += parsedValue || parsedValue === null ? 3 : 4; + } + + if (str[index + 1] === ':') { + pendingKey = parsedValue; + index++; + } else if (Array.isArray(currentValue)) { + currentValue.push(parsedValue); + } else if (pendingKey !== null) { + currentValue[pendingKey] = parsedValue; + pendingKey = null; + } else { + currentValue = parsedValue; + } + } + } + + return currentValue; +}; diff --git a/solutions/2763-sum-of-imbalance-numbers-of-all-subarrays.js b/solutions/2763-sum-of-imbalance-numbers-of-all-subarrays.js new file mode 100644 index 00000000..5d7ba4ed --- /dev/null +++ b/solutions/2763-sum-of-imbalance-numbers-of-all-subarrays.js @@ -0,0 +1,51 @@ +/** + * 2763. Sum of Imbalance Numbers of All Subarrays + * https://leetcode.com/problems/sum-of-imbalance-numbers-of-all-subarrays/ + * Difficulty: Hard + * + * The imbalance number of a 0-indexed integer array arr of length n is defined as the number + * of indices in sarr = sorted(arr) such that: + * - 0 <= i < n - 1, and + * - sarr[i+1] - sarr[i] > 1 + * + * Here, sorted(arr) is the function that returns the sorted version of arr. + * + * Given a 0-indexed integer array nums, return the sum of imbalance numbers of all its subarrays. + * + * A subarray is a contiguous non-empty sequence of elements within an array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var sumImbalanceNumbers = function(nums) { + const n = nums.length; + let result = 0; + + for (let i = 0; i < n; i++) { + const seen = new Set(); + let imbalance = 0; + + for (let j = i; j < n; j++) { + const current = nums[j]; + + if (!seen.has(current)) { + const hasNext = seen.has(current + 1); + const hasPrev = seen.has(current - 1); + + if (hasNext && hasPrev) { + imbalance--; + } else if (!hasNext && !hasPrev && seen.size > 0) { + imbalance++; + } + + seen.add(current); + } + + result += imbalance; + } + } + + return result; +}; diff --git a/solutions/2764-is-array-a-preorder-of-some-binary-tree.js b/solutions/2764-is-array-a-preorder-of-some-binary-tree.js new file mode 100644 index 00000000..908d862b --- /dev/null +++ b/solutions/2764-is-array-a-preorder-of-some-binary-tree.js @@ -0,0 +1,64 @@ +/** + * 2764. Is Array a Preorder of Some ‌Binary Tree + * https://leetcode.com/problems/is-array-a-preorder-of-some-binary-tree/ + * Difficulty: Medium + * + * Given a 0-indexed integer 2D array nodes, your task is to determine if the given array represents + * the preorder traversal of some binary tree. + * + * For each index i, nodes[i] = [id, parentId], where id is the id of the node at the index i and + * parentId is the id of its parent in the tree (if the node has no parent, then parentId == -1). + * + * Return true if the given array represents the preorder traversal of some tree, and false + * otherwise. + * + * Note: the preorder traversal of a tree is a recursive way to traverse a tree in which we first + * visit the current node, then we do the preorder traversal for the left child, and finally, we + * do it for the right child. + */ + +/** + * @param {number[][]} nodes + * @return {boolean} + */ +var isPreorder = function(nodes) { + const children = new Map(); + let root = null; + + for (const [id, parentId] of nodes) { + if (parentId === -1) { + root = id; + } else { + if (!children.has(parentId)) { + children.set(parentId, []); + } + children.get(parentId).push(id); + } + } + + const expectedOrder = []; + + traverse(root); + + for (let i = 0; i < nodes.length; i++) { + if (nodes[i][0] !== expectedOrder[i]) { + return false; + } + } + + return true; + + function traverse(nodeId) { + if (nodeId === null) return; + + expectedOrder.push(nodeId); + + const nodeChildren = children.get(nodeId) || []; + if (nodeChildren.length > 0) { + traverse(nodeChildren[0]); + } + if (nodeChildren.length > 1) { + traverse(nodeChildren[1]); + } + } +}; diff --git a/solutions/2766-relocate-marbles.js b/solutions/2766-relocate-marbles.js new file mode 100644 index 00000000..08d51e6f --- /dev/null +++ b/solutions/2766-relocate-marbles.js @@ -0,0 +1,34 @@ +/** + * 2766. Relocate Marbles + * https://leetcode.com/problems/relocate-marbles/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums representing the initial positions of some + * marbles. You are also given two 0-indexed integer arrays moveFrom and moveTo of equal length. + * + * Throughout moveFrom.length steps, you will change the positions of the marbles. On the ith + * step, you will move all marbles at position moveFrom[i] to position moveTo[i]. + * + * After completing all the steps, return the sorted list of occupied positions. + * + * Notes: + * - We call a position occupied if there is at least one marble in that position. + * - There may be multiple marbles in a single position. + */ + +/** + * @param {number[]} nums + * @param {number[]} moveFrom + * @param {number[]} moveTo + * @return {number[]} + */ +var relocateMarbles = function(nums, moveFrom, moveTo) { + const set = new Set(nums); + + for (let i = 0; i < moveFrom.length; i++) { + set.delete(moveFrom[i]); + set.add(moveTo[i]); + } + + return [...set].sort((a, b) => a - b); +}; diff --git a/solutions/2767-partition-string-into-minimum-beautiful-substrings.js b/solutions/2767-partition-string-into-minimum-beautiful-substrings.js new file mode 100644 index 00000000..45e5b024 --- /dev/null +++ b/solutions/2767-partition-string-into-minimum-beautiful-substrings.js @@ -0,0 +1,52 @@ +/** + * 2767. Partition String Into Minimum Beautiful Substrings + * https://leetcode.com/problems/partition-string-into-minimum-beautiful-substrings/ + * Difficulty: Medium + * + * Given a binary string s, partition the string into one or more substrings such that each + * substring is beautiful. + * + * A string is beautiful if: + * - It doesn't contain leading zeros. + * - It's the binary representation of a number that is a power of 5. + * + * Return the minimum number of substrings in such partition. If it is impossible to partition + * the string s into beautiful substrings, return -1. + * + * A substring is a contiguous sequence of characters in a string. + */ + +/** + * @param {string} s + * @return {number} + */ +var minimumBeautifulSubstrings = function(s) { + const n = s.length; + const powersOfFive = new Set(); + let power = 1; + while (power.toString(2).length <= n) { + powersOfFive.add(power.toString(2)); + power *= 5; + } + + const result = findMinPartitions(0); + return result === Infinity ? -1 : result; + + function findMinPartitions(index) { + if (index === n) return 0; + if (s[index] === '0') return Infinity; + + let minPartitions = Infinity; + for (let end = index + 1; end <= n; end++) { + const substring = s.slice(index, end); + if (powersOfFive.has(substring)) { + const next = findMinPartitions(end); + if (next !== Infinity) { + minPartitions = Math.min(minPartitions, 1 + next); + } + } + } + + return minPartitions; + } +}; diff --git a/solutions/2769-find-the-maximum-achievable-number.js b/solutions/2769-find-the-maximum-achievable-number.js new file mode 100644 index 00000000..cfd60aeb --- /dev/null +++ b/solutions/2769-find-the-maximum-achievable-number.js @@ -0,0 +1,20 @@ +/** + * 2769. Find the Maximum Achievable Number + * https://leetcode.com/problems/find-the-maximum-achievable-number/ + * Difficulty: Easy + * + * Given two integers, num and t. A number x is achievable if it can become equal to num + * after applying the following operation at most t times: + * - Increase or decrease x by 1, and simultaneously increase or decrease num by 1. + * + * Return the maximum possible value of x. + */ + +/** + * @param {number} num + * @param {number} t + * @return {number} + */ +var theMaximumAchievableX = function(num, t) { + return num + 2 * t; +}; diff --git a/solutions/2773-height-of-special-binary-tree.js b/solutions/2773-height-of-special-binary-tree.js new file mode 100644 index 00000000..0a28dcdb --- /dev/null +++ b/solutions/2773-height-of-special-binary-tree.js @@ -0,0 +1,39 @@ +/** + * 2773. Height of Special Binary Tree + * https://leetcode.com/problems/height-of-special-binary-tree/ + * Difficulty: Medium + * + * You are given a root, which is the root of a special binary tree with n nodes. The nodes of + * the special binary tree are numbered from 1 to n. Suppose the tree has k leaves in the + * following order: b1 < b2 < ... < bk. + * + * The leaves of this tree have a special property! That is, for every leaf bi, the following + * conditions hold: + * - The right child of bi is bi + 1 if i < k, and b1 otherwise. + * - The left child of bi is bi - 1 if i > 1, and bk otherwise. + * + * Return the height of the given tree. + * + * Note: The height of a binary tree is the length of the longest path from the root to any + * other node. + */ + +/** + * 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} + */ +var heightOfTree = function(root) { + if (!root || (root.left && root.left.right === root)) { + return 0; + } + + return 1 + Math.max(heightOfTree(root.left), heightOfTree(root.right)); +}; diff --git a/solutions/2774-array-upper-bound.js b/solutions/2774-array-upper-bound.js new file mode 100644 index 00000000..4600ca60 --- /dev/null +++ b/solutions/2774-array-upper-bound.js @@ -0,0 +1,35 @@ +/** + * 2774. Array Upper Bound + * https://leetcode.com/problems/array-upper-bound/ + * Difficulty: Easy + * + * Write code that enhances all arrays such that you can call the upperBound() method on any + * array and it will return the last index of a given target number. nums is a sorted ascending + * array of numbers that may contain duplicates. If the target number is not found in the array, + * return -1. + */ + +/** + * @param {number} target + * @return {number} + */ +Array.prototype.upperBound = function(target) { + let left = 0; + let right = this.length - 1; + let result = -1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + + if (this[mid] === target) { + result = mid; + left = mid + 1; + } else if (this[mid] < target) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return result; +}; diff --git a/solutions/2775-undefined-to-null.js b/solutions/2775-undefined-to-null.js new file mode 100644 index 00000000..c2c6ed7b --- /dev/null +++ b/solutions/2775-undefined-to-null.js @@ -0,0 +1,37 @@ +/** + * 2775. Undefined to Null + * https://leetcode.com/problems/undefined-to-null/ + * Difficulty: Medium + * + * Given a deeply nested object or array obj, return the object obj with any undefined + * values replaced by null. + * + * undefined values are handled differently than null values when objects are converted + * to a JSON string using JSON.stringify(). This function helps ensure serialized data + * is free of unexpected errors. + */ + +/** + * @param {Object|Array} obj + * @return {Object|Array} + */ +var undefinedToNull = function(obj) { + if (obj === undefined) { + return null; + } + + if (obj === null || typeof obj !== 'object') { + return obj; + } + + if (Array.isArray(obj)) { + return obj.map(item => undefinedToNull(item)); + } + + const result = {}; + Object.keys(obj).forEach(key => { + result[key] = undefinedToNull(obj[key]); + }); + + return result; +}; diff --git a/solutions/2776-convert-callback-based-function-to-promise-based-function.js b/solutions/2776-convert-callback-based-function-to-promise-based-function.js new file mode 100644 index 00000000..347396ca --- /dev/null +++ b/solutions/2776-convert-callback-based-function-to-promise-based-function.js @@ -0,0 +1,54 @@ +/** + * 2776. Convert Callback Based Function to Promise Based Function + * https://leetcode.com/problems/convert-callback-based-function-to-promise-based-function/ + * Difficulty: Medium + * + * Write a function that accepts another function fn and converts the callback-based function into + * a promise-based function. + * + * The function fn takes a callback as its first argument, along with any additional arguments + * args passed as separate inputs. + * + * The promisify function returns a new function that should return a promise. The promise should + * resolve with the argument passed as the first parameter of the callback when the callback is + * invoked without error, and reject with the error when the callback is called with an error as + * the second argument. + * + * The following is an example of a function that could be passed into promisify. + * function sum(callback, a, b) { + * if (a < 0 || b < 0) { + * const err = Error('a and b must be positive'); + * callback(undefined, err); + * } else { + * callback(a + b); + * } + * } + * + * This is the equivalent code based on promises: + * + * async function sum(a, b) { + * if (a < 0 || b < 0) { + * throw Error('a and b must be positive'); + * } else { + * return a + b; + * } + * } + * */ + +/** + * @param {Function} fn + * @return {Function>} + */ +var promisify = function(fn) { + return async function(...args) { + return new Promise((resolve, reject) => { + fn((result, error) => { + if (error) { + reject(error); + } else { + resolve(result); + } + }, ...args); + }); + }; +}; diff --git a/solutions/2777-date-range-generator.js b/solutions/2777-date-range-generator.js new file mode 100644 index 00000000..f1fb2b4b --- /dev/null +++ b/solutions/2777-date-range-generator.js @@ -0,0 +1,29 @@ +/** + * 2777. Date Range Generator + * https://leetcode.com/problems/date-range-generator/ + * Difficulty: Medium + * + * Given a start date start, an end date end, and a positive integer step, return a generator + * object that yields dates in the range from start to end inclusive. + * + * The value of step indicates the number of days between consecutive yielded values. + * + * All yielded dates must be in the string format YYYY-MM-DD. + */ + +/** + * @param {string} start + * @param {string} end + * @param {number} step + * @yields {string} + */ +var dateRangeGenerator = function* (start, end, step) { + const startDate = new Date(start); + const endDate = new Date(end); + const currentDate = new Date(startDate); + + while (currentDate <= endDate) { + yield currentDate.toISOString().split('T')[0]; + currentDate.setDate(currentDate.getDate() + step); + } +}; diff --git a/solutions/2778-sum-of-squares-of-special-elements.js b/solutions/2778-sum-of-squares-of-special-elements.js new file mode 100644 index 00000000..fbac7766 --- /dev/null +++ b/solutions/2778-sum-of-squares-of-special-elements.js @@ -0,0 +1,28 @@ +/** + * 2778. Sum of Squares of Special Elements + * https://leetcode.com/problems/sum-of-squares-of-special-elements/ + * Difficulty: Easy + * + * You are given a 1-indexed integer array nums of length n. + * + * An element nums[i] of nums is called special if i divides n, i.e. n % i == 0. + * + * Return the sum of the squares of all special elements of nums. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var sumOfSquares = function(nums) { + const n = nums.length; + let total = 0; + + for (let i = 1; i <= n; i++) { + if (n % i === 0) { + total += nums[i - 1] * nums[i - 1]; + } + } + + return total; +}; diff --git a/solutions/2779-maximum-beauty-of-an-array-after-applying-operation.js b/solutions/2779-maximum-beauty-of-an-array-after-applying-operation.js new file mode 100644 index 00000000..1015482b --- /dev/null +++ b/solutions/2779-maximum-beauty-of-an-array-after-applying-operation.js @@ -0,0 +1,41 @@ +/** + * 2779. Maximum Beauty of an Array After Applying Operation + * https://leetcode.com/problems/maximum-beauty-of-an-array-after-applying-operation/ + * Difficulty: Medium + * + * You are given a 0-indexed array nums and a non-negative integer k. + * + * In one operation, you can do the following: + * - Choose an index i that hasn't been chosen before from the range [0, nums.length - 1]. + * - Replace nums[i] with any integer from the range [nums[i] - k, nums[i] + k]. + * + * The beauty of the array is the length of the longest subsequence consisting of equal elements. + * + * Return the maximum possible beauty of the array nums after applying the operation any number + * of times. + * + * Note that you can apply the operation to each index only once. + * + * A subsequence of an array is a new array generated from the original array by deleting some + * elements (possibly none) without changing the order of the remaining elements. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var maximumBeauty = function(nums, k) { + nums.sort((a, b) => a - b); + let result = 0; + let left = 0; + + for (let right = 0; right < nums.length; right++) { + while (nums[right] - nums[left] > 2 * k) { + left++; + } + result = Math.max(result, right - left + 1); + } + + return result; +}; diff --git a/solutions/2782-number-of-unique-categories.js b/solutions/2782-number-of-unique-categories.js new file mode 100644 index 00000000..7ddebf86 --- /dev/null +++ b/solutions/2782-number-of-unique-categories.js @@ -0,0 +1,55 @@ +/** + * 2782. Number of Unique Categories + * https://leetcode.com/problems/number-of-unique-categories/ + * Difficulty: Medium + * + * You are given an integer n and an object categoryHandler of class CategoryHandler. + * + * There are n elements, numbered from 0 to n - 1. Each element has a category, and your task + * is to find the number of unique categories. + * + * The class CategoryHandler contains the following function, which may help you: + * - boolean haveSameCategory(integer a, integer b): Returns true if a and b are in the same + * category and false otherwise. Also, if either a or b is not a valid number (i.e. it's greater + * than or equal to nor less than 0), it returns false. + * + * Return the number of unique categories. + */ + +/** + * Definition for a category handler. + * class CategoryHandler { + * @param {number[]} categories + * constructor(categories); + * + * @param {number} a + * @param {number} b + * @return {boolean} + * haveSameCategory(a, b); + * } + */ +/** + * @param {number} n + * @param {CategoryHandler} categoryHandler + * @return {number} + */ +var numberOfCategories = function(n, categoryHandler) { + let result = 0; + + for (let j = 0; j < n; j++) { + let isNewCategory = true; + + for (let i = 0; i < j; i++) { + if (categoryHandler.haveSameCategory(i, j)) { + isNewCategory = false; + break; + } + } + + if (isNewCategory) { + result++; + } + } + + return result; +}; diff --git a/solutions/2784-check-if-array-is-good.js b/solutions/2784-check-if-array-is-good.js new file mode 100644 index 00000000..289edd0d --- /dev/null +++ b/solutions/2784-check-if-array-is-good.js @@ -0,0 +1,36 @@ +/** + * 2784. Check if Array is Good + * https://leetcode.com/problems/check-if-array-is-good/ + * Difficulty: Easy + * + * You are given an integer array nums. We consider an array good if it is a permutation of + * an array base[n]. + * + * base[n] = [1, 2, ..., n - 1, n, n] (in other words, it is an array of length n + 1 which + * contains 1 to n - 1 exactly once, plus two occurrences of n). For example, base[1] = [1, 1] + * and base[3] = [1, 2, 3, 3]. + * + * Return true if the given array is good, otherwise return false. + * + * Note: A permutation of integers represents an arrangement of these numbers. + */ + +/** + * @param {number[]} nums + * @return {boolean} + */ +var isGood = function(nums) { + const n = Math.max(...nums); + if (nums.length !== n + 1) return false; + + const frequency = new Array(n + 1).fill(0); + for (const num of nums) { + if (num > n) return false; + frequency[num]++; + } + + for (let i = 1; i < n; i++) { + if (frequency[i] !== 1) return false; + } + return frequency[n] === 2; +}; diff --git a/solutions/2785-sort-vowels-in-a-string.js b/solutions/2785-sort-vowels-in-a-string.js new file mode 100644 index 00000000..d4a25c7e --- /dev/null +++ b/solutions/2785-sort-vowels-in-a-string.js @@ -0,0 +1,45 @@ +/** + * 2785. Sort Vowels in a String + * https://leetcode.com/problems/sort-vowels-in-a-string/ + * Difficulty: Medium + * + * Given a 0-indexed string s, permute s to get a new string t such that: + * - All consonants remain in their original places. More formally, if there is an index i + * with 0 <= i < s.length such that s[i] is a consonant, then t[i] = s[i]. + * - The vowels must be sorted in the nondecreasing order of their ASCII values. More formally, + * for pairs of indices i, j with 0 <= i < j < s.length such that s[i] and s[j] are vowels, + * then t[i] must not have a higher ASCII value than t[j]. + * + * Return the resulting string. + * + * The vowels are 'a', 'e', 'i', 'o', and 'u', and they can appear in lowercase or uppercase. + * Consonants comprise all letters that are not vowels. + */ + +/** + * @param {string} s + * @return {string} + */ +var sortVowels = function(s) { + const vowels = new Set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']); + const vowelChars = []; + + for (const char of s) { + if (vowels.has(char)) { + vowelChars.push(char); + } + } + + vowelChars.sort(); + + const result = [...s]; + let vowelIndex = 0; + + for (let i = 0; i < s.length; i++) { + if (vowels.has(s[i])) { + result[i] = vowelChars[vowelIndex++]; + } + } + + return result.join(''); +}; diff --git a/solutions/2787-ways-to-express-an-integer-as-sum-of-powers.js b/solutions/2787-ways-to-express-an-integer-as-sum-of-powers.js new file mode 100644 index 00000000..240f2ec6 --- /dev/null +++ b/solutions/2787-ways-to-express-an-integer-as-sum-of-powers.js @@ -0,0 +1,37 @@ +/** + * 2787. Ways to Express an Integer as Sum of Powers + * https://leetcode.com/problems/ways-to-express-an-integer-as-sum-of-powers/ + * Difficulty: Medium + * + * Given two positive integers n and x. + * + * Return the number of ways n can be expressed as the sum of the xth power of unique positive + * integers, in other words, the number of sets of unique integers [n1, n2, ..., nk] where + * n = n1x + n2x + ... + nkx. + * + * Since the result can be very large, return it modulo 109 + 7. + * + * For example, if n = 160 and x = 3, one way to express n is n = 23 + 33 + 53. + */ + +/** + * @param {number} n + * @param {number} x + * @return {number} + */ +var numberOfWays = function(n, x) { + const MOD = 1e9 + 7; + const dp = new Array(n + 1).fill(0); + dp[0] = 1; + + let power = 1; + while (Math.pow(power, x) <= n) { + const currentPower = Math.pow(power, x); + for (let sum = n; sum >= currentPower; sum--) { + dp[sum] = (dp[sum] + dp[sum - currentPower]) % MOD; + } + power++; + } + + return dp[n]; +}; diff --git a/solutions/2788-split-strings-by-separator.js b/solutions/2788-split-strings-by-separator.js new file mode 100644 index 00000000..6681bef2 --- /dev/null +++ b/solutions/2788-split-strings-by-separator.js @@ -0,0 +1,31 @@ +/** + * 2788. Split Strings by Separator + * https://leetcode.com/problems/split-strings-by-separator/ + * Difficulty: Easy + * + * Given an array of strings words and a character separator, split each string in words by + * separator. + * + * Return an array of strings containing the new strings formed after the splits, excluding + * empty strings. + * + * Notes + * - separator is used to determine where the split should occur, but it is not included as + * part of the resulting strings. + * - A split may result in more than two strings. + * - The resulting strings must maintain the same order as they were initially given. + */ + +/** + * @param {string[]} words + * @param {character} separator + * @return {string[]} + */ +var splitWordsBySeparator = function(words, separator) { + const result = []; + for (const word of words) { + const splitWords = word.split(separator).filter(part => part !== ''); + result.push(...splitWords); + } + return result; +}; diff --git a/solutions/2789-largest-element-in-an-array-after-merge-operations.js b/solutions/2789-largest-element-in-an-array-after-merge-operations.js new file mode 100644 index 00000000..3de874a6 --- /dev/null +++ b/solutions/2789-largest-element-in-an-array-after-merge-operations.js @@ -0,0 +1,34 @@ +/** + * 2789. Largest Element in an Array after Merge Operations + * https://leetcode.com/problems/largest-element-in-an-array-after-merge-operations/ + * Difficulty: Medium + * + * You are given a 0-indexed array nums consisting of positive integers. + * + * You can do the following operation on the array any number of times: + * - Choose an integer i such that 0 <= i < nums.length - 1 and nums[i] <= nums[i + 1]. + * Replace the element nums[i + 1] with nums[i] + nums[i + 1] and delete the element + * nums[i] from the array. + * + * Return the value of the largest element that you can possibly obtain in the final array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxArrayValue = function(nums) { + let result = nums[nums.length - 1]; + let currentSum = result; + + for (let i = nums.length - 2; i >= 0; i--) { + if (nums[i] <= currentSum) { + currentSum += nums[i]; + } else { + currentSum = nums[i]; + } + result = Math.max(result, currentSum); + } + + return result; +}; diff --git a/solutions/2791-count-paths-that-can-form-a-palindrome-in-a-tree.js b/solutions/2791-count-paths-that-can-form-a-palindrome-in-a-tree.js new file mode 100644 index 00000000..195def8e --- /dev/null +++ b/solutions/2791-count-paths-that-can-form-a-palindrome-in-a-tree.js @@ -0,0 +1,49 @@ +/** + * 2791. Count Paths That Can Form a Palindrome in a Tree + * https://leetcode.com/problems/count-paths-that-can-form-a-palindrome-in-a-tree/ + * Difficulty: Hard + * + * You are given a tree (i.e. a connected, undirected graph that has no cycles) rooted at node + * 0 consisting of n nodes numbered from 0 to n - 1. The tree is represented by a 0-indexed + * array parent of size n, where parent[i] is the parent of node i. Since node 0 is the root, + * parent[0] == -1. + * + * You are also given a string s of length n, where s[i] is the character assigned to the edge + * between i and parent[i]. s[0] can be ignored. + * + * Return the number of pairs of nodes (u, v) such that u < v and the characters assigned to edges + * on the path from u to v can be rearranged to form a palindrome. + * + * A string is a palindrome when it reads the same backwards as forwards. + */ + +/** + * @param {number[]} parent + * @param {string} s + * @return {number} + */ +var countPalindromePaths = function(parent, s) { + const n = parent.length; + const graph = Array.from({ length: n }, () => []); + for (let i = 1; i < n; i++) { + graph[parent[i]].push(i); + } + + const freq = new Map([[0, 1]]); + let result = 0; + + dfs(0, 0); + return result; + + function dfs(node, mask) { + for (const child of graph[node]) { + const newMask = mask ^ (1 << (s[child].charCodeAt(0) - 97)); + result += freq.get(newMask) || 0; + for (let i = 0; i < 26; i++) { + result += freq.get(newMask ^ (1 << i)) || 0; + } + freq.set(newMask, (freq.get(newMask) || 0) + 1); + dfs(child, newMask); + } + } +}; diff --git a/solutions/2792-count-nodes-that-are-great-enough.js b/solutions/2792-count-nodes-that-are-great-enough.js new file mode 100644 index 00000000..4c4f4e42 --- /dev/null +++ b/solutions/2792-count-nodes-that-are-great-enough.js @@ -0,0 +1,51 @@ +/** + * 2792. Count Nodes That Are Great Enough + * https://leetcode.com/problems/count-nodes-that-are-great-enough/ + * Difficulty: Hard + * + * You are given a root to a binary tree and an integer k. A node of this tree is called great + * enough if the followings hold: + * - Its subtree has at least k nodes. + * - Its value is greater than the value of at least k nodes in its subtree. + * + * Return the number of nodes in this tree that are great enough. + * + * The node u is in the subtree of the node v, if u == v or v is an ancestor of u. + */ + +/** + * 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} k + * @return {number} + */ +var countGreatEnoughNodes = function(root, k) { + let result = 0; + + dfs(root); + + return result; + + function dfs(node) { + if (!node) return []; + + const leftValues = dfs(node.left); + const rightValues = dfs(node.right); + const combined = [...leftValues, ...rightValues].sort((a, b) => a - b).slice(0, k); + + if (combined.length >= k && combined[k - 1] < node.val) { + result++; + } else { + combined.push(node.val); + } + + return combined; + } +}; diff --git a/solutions/2794-create-object-from-two-arrays.js b/solutions/2794-create-object-from-two-arrays.js new file mode 100644 index 00000000..4fcfd1e7 --- /dev/null +++ b/solutions/2794-create-object-from-two-arrays.js @@ -0,0 +1,31 @@ +/** + * 2794. Create Object from Two Arrays + * https://leetcode.com/problems/create-object-from-two-arrays/ + * Difficulty: Easy + * + * Given two arrays keysArr and valuesArr, return a new object obj. Each key-value pair in obj + * should come from keysArr[i] and valuesArr[i]. + * + * If a duplicate key exists at a previous index, that key-value should be excluded. In other + * words, only the first key should be added to the object. + * + * If the key is not a string, it should be converted into a string by calling String() on it. + */ + +/** + * @param {Array} keysArr + * @param {Array} valuesArr + * @return {Object} + */ +var createObject = function(keysArr, valuesArr) { + const result = {}; + + for (let i = 0; i < keysArr.length; i++) { + const stringKey = String(keysArr[i]); + if (!(stringKey in result)) { + result[stringKey] = valuesArr[i]; + } + } + + return result; +}; diff --git a/solutions/2795-parallel-execution-of-promises-for-individual-results-retrieval.js b/solutions/2795-parallel-execution-of-promises-for-individual-results-retrieval.js new file mode 100644 index 00000000..5638a94b --- /dev/null +++ b/solutions/2795-parallel-execution-of-promises-for-individual-results-retrieval.js @@ -0,0 +1,43 @@ +/** + * 2795. Parallel Execution of Promises for Individual Results Retrieval + * https://leetcode.com/problems/parallel-execution-of-promises-for-individual-results-retrieval/ + * Difficulty: Medium + * + * Given an array functions, return a promise promise. functions is an array of functions that + * return promises fnPromise. Each fnPromise can be resolved or rejected. + * + * If fnPromise is resolved: + * + * obj = { status: "fulfilled", value: resolved value} + * + * If fnPromise is rejected: + * + * obj = { status: "rejected", reason: reason of rejection (catched error message)} + * + * The promise should resolve with an array of these objects obj. Each obj in the array should + * correspond to the promises in the original array function, maintaining the same order. + * + * Try to implement it without using the built-in method Promise.allSettled(). + */ + +/** + * @param {Array} functions + * @return {Promise} + */ +var promiseAllSettled = function(functions) { + return new Promise(resolve => { + const results = new Array(functions.length); + let completedCount = 0; + + functions.forEach((fn, index) => { + fn().then(value => results[index] = { status: 'fulfilled', value }) + .catch(reason => results[index] = { status: 'rejected', reason }) + .finally(() => { + completedCount++; + if (completedCount === functions.length) { + resolve(results); + } + }); + }); + }); +}; diff --git a/solutions/2796-repeat-string.js b/solutions/2796-repeat-string.js new file mode 100644 index 00000000..d22c0cdd --- /dev/null +++ b/solutions/2796-repeat-string.js @@ -0,0 +1,22 @@ +/** + * 2796. Repeat String + * https://leetcode.com/problems/repeat-string/ + * Difficulty: Easy + * + * Write code that enhances all strings such that you can call the string.replicate(x) method + * on any string and it will return repeated string x times. + * + * Try to implement it without using the built-in method string.repeat. + */ + +/** + * @param {number} times + * @return {string} + */ +String.prototype.replicate = function(times) { + let result = ''; + for (let i = 0; i < times; i++) { + result += this; + } + return result; +}; diff --git a/solutions/2797-partial-function-with-placeholders.js b/solutions/2797-partial-function-with-placeholders.js new file mode 100644 index 00000000..9afa8558 --- /dev/null +++ b/solutions/2797-partial-function-with-placeholders.js @@ -0,0 +1,39 @@ +/** + * 2797. Partial Function with Placeholders + * https://leetcode.com/problems/partial-function-with-placeholders/ + * Difficulty: Easy + * + * Given a function fn and an array args, return a function partialFn. + * + * Placeholders "_" in the args should be replaced with values from restArgs starting from + * index 0. Any remaining values in the restArgs should be added at the end of the args. + * + * partialFn should return a result of fn. fn should be called with the elements of the + * modified args passed as separate arguments. + */ + +/** + * @param {Function} fn + * @param {Array} args + * @return {Function} + */ +var partial = function(fn, args) { + return function(...restArgs) { + const finalArgs = [...args]; + let restIndex = 0; + + for (let i = 0; i < finalArgs.length; i++) { + if (finalArgs[i] === '_' && restIndex < restArgs.length) { + finalArgs[i] = restArgs[restIndex]; + restIndex++; + } + } + + while (restIndex < restArgs.length) { + finalArgs.push(restArgs[restIndex]); + restIndex++; + } + + return fn(...finalArgs); + }; +}; diff --git a/solutions/2798-number-of-employees-who-met-the-target.js b/solutions/2798-number-of-employees-who-met-the-target.js new file mode 100644 index 00000000..b3c1f4ac --- /dev/null +++ b/solutions/2798-number-of-employees-who-met-the-target.js @@ -0,0 +1,30 @@ +/** + * 2798. Number of Employees Who Met the Target + * https://leetcode.com/problems/number-of-employees-who-met-the-target/ + * Difficulty: Easy + * + * There are n employees in a company, numbered from 0 to n - 1. Each employee i has worked + * for hours[i] hours in the company. + * + * The company requires each employee to work for at least target hours. + * + * You are given a 0-indexed array of non-negative integers hours of length n and a non-negative + * integer target. + * + * Return the integer denoting the number of employees who worked at least target hours. + */ + +/** + * @param {number[]} hours + * @param {number} target + * @return {number} + */ +var numberOfEmployeesWhoMetTarget = function(hours, target) { + let count = 0; + + for (const hoursWorked of hours) { + if (hoursWorked >= target) count++; + } + + return count; +}; diff --git a/solutions/2802-find-the-k-th-lucky-number.js b/solutions/2802-find-the-k-th-lucky-number.js new file mode 100644 index 00000000..00f11024 --- /dev/null +++ b/solutions/2802-find-the-k-th-lucky-number.js @@ -0,0 +1,29 @@ +/** + * 2802. Find The K-th Lucky Number + * https://leetcode.com/problems/find-the-k-th-lucky-number/ + * Difficulty: Medium + * + * We know that 4 and 7 are lucky digits. Also, a number is called lucky if it contains only + * lucky digits. + * + * You are given an integer k, return the kth lucky number represented as a string. + */ + +/** + * @param {number} k + * @return {string} + */ +var kthLuckyNumber = function(k) { + let length = 1; + let totalNumbers = 0; + + while (totalNumbers + Math.pow(2, length) < k) { + totalNumbers += Math.pow(2, length); + length++; + } + + const position = k - totalNumbers; + const binaryString = (position - 1).toString(2).padStart(length, '0'); + + return binaryString.replace(/0/g, '4').replace(/1/g, '7'); +}; diff --git a/solutions/2803-factorial-generator.js b/solutions/2803-factorial-generator.js new file mode 100644 index 00000000..15dcfbf4 --- /dev/null +++ b/solutions/2803-factorial-generator.js @@ -0,0 +1,29 @@ +/** + * 2803. Factorial Generator + * https://leetcode.com/problems/factorial-generator/ + * Difficulty: Easy + * + * Write a generator function that takes an integer n as an argument and returns a generator + * object which yields the factorial sequence. + * + * The factorial sequence is defined by the relation n! = n * (n-1) * (n-2) * ... * 2 * 1. + * + * The factorial of 0 is defined as 1. + */ + +/** + * @param {number} n + * @yields {number} + */ +function* factorial(n) { + let currentFactorial = 1; + + for (let i = 1; i <= n; i++) { + currentFactorial *= i; + yield currentFactorial; + } + + if (n === 0) { + yield 1; + } +} diff --git a/solutions/2804-array-prototype-foreach.js b/solutions/2804-array-prototype-foreach.js new file mode 100644 index 00000000..c694cbf7 --- /dev/null +++ b/solutions/2804-array-prototype-foreach.js @@ -0,0 +1,33 @@ +/** + * 2804. Array Prototype ForEach + * https://leetcode.com/problems/array-prototype-foreach/ + * Difficulty: Easy + * + * Write your version of method forEach that enhances all arrays such that you can call the + * array.forEach(callback, context) method on any array and it will execute callback on each + * element of the array. Method forEach should not return anything. + * + * callback accepts the following arguments: + * - currentValue - represents the current element being processed in the array. It is the + * value of the element in the current iteration. + * - index - represents the index of the current element being processed in the array. + * - array - represents the array itself, allowing access to the entire array within the + * callback function. + * + * The context is the object that should be passed as the function context parameter to the + * callback function, ensuring that the this keyword within the callback function refers to + * this context object. + * + * Try to implement it without using the built-in array methods. + */ + +/** + * @param {Function} callback + * @param {Object} context + * @return {void} + */ +Array.prototype.forEach = function(callback, context) { + for (let i = 0; i < this.length; i++) { + callback.call(context, this[i], i, this); + } +}; diff --git a/solutions/2805-custom-interval.js b/solutions/2805-custom-interval.js new file mode 100644 index 00000000..9da9d162 --- /dev/null +++ b/solutions/2805-custom-interval.js @@ -0,0 +1,62 @@ +/** + * 2805. Custom Interval + * https://leetcode.com/problems/custom-interval/ + * Difficulty: Medium + * + * Function customInterval + * + * Given a function fn, a number delay and a number period, return a number id. + * + * customInterval is a function that should execute the provided function fn at intervals based + * on a linear pattern defined by the formula delay + period * count. + * + * The count in the formula represents the number of times the interval has been executed + * starting from an initial value of 0. + * + * Function customClearInterval + * + * Given the id. id is the returned value from the function customInterval. + * + * customClearInterval should stop executing provided function fn at intervals. + * + * Note: The setTimeout and setInterval functions in Node.js return an object, not a number. + */ + +const intervalMap = new Map(); +let nextId = 1; + +/** + * @param {Function} fn + * @param {number} delay + * @param {number} period + * @return {number} id + */ +function customInterval(fn, delay, period) { + let count = 0; + const id = nextId++; + + function scheduleNext() { + const nextDelay = delay + period * count; + const timeoutId = setTimeout(() => { + fn(); + count++; + scheduleNext(); + }, nextDelay); + intervalMap.set(id, timeoutId); + } + + scheduleNext(); + return id; +} + +/** + * @param {number} id + * @return {void} + */ +function customClearInterval(id) { + const timeoutId = intervalMap.get(id); + if (timeoutId) { + clearTimeout(timeoutId); + intervalMap.delete(id); + } +} diff --git a/solutions/2806-account-balance-after-rounded-purchase.js b/solutions/2806-account-balance-after-rounded-purchase.js new file mode 100644 index 00000000..0862ed28 --- /dev/null +++ b/solutions/2806-account-balance-after-rounded-purchase.js @@ -0,0 +1,29 @@ +/** + * 2806. Account Balance After Rounded Purchase + * https://leetcode.com/problems/account-balance-after-rounded-purchase/ + * Difficulty: Easy + * + * Initially, you have a bank account balance of 100 dollars. + * + * You are given an integer purchaseAmount representing the amount you will spend on a purchase + * in dollars, in other words, its price. + * + * When making the purchase, first the purchaseAmount is rounded to the nearest multiple of 10. + * Let us call this value roundedAmount. Then, roundedAmount dollars are removed from your bank + * account. + * + * Return an integer denoting your final bank account balance after this purchase. + * + * Notes: + * - 0 is considered to be a multiple of 10 in this problem. + * - When rounding, 5 is rounded upward (5 is rounded to 10, 15 is rounded to 20, 25 to 30, and + * so on). + */ + +/** + * @param {number} purchaseAmount + * @return {number} + */ +var accountBalanceAfterPurchase = function(purchaseAmount) { + return 100 - (Math.round(purchaseAmount / 10) * 10); +}; diff --git a/solutions/2807-insert-greatest-common-divisors-in-linked-list.js b/solutions/2807-insert-greatest-common-divisors-in-linked-list.js new file mode 100644 index 00000000..ee1b2f8e --- /dev/null +++ b/solutions/2807-insert-greatest-common-divisors-in-linked-list.js @@ -0,0 +1,45 @@ +/** + * 2807. Insert Greatest Common Divisors in Linked List + * https://leetcode.com/problems/insert-greatest-common-divisors-in-linked-list/ + * Difficulty: Medium + * + * Given the head of a linked list head, in which each node contains an integer value. + * + * Between every pair of adjacent nodes, insert a new node with a value equal to the greatest + * common divisor of them. + * + * Return the linked list after insertion. + * + * The greatest common divisor of two numbers is the largest positive integer that evenly + * divides both numbers. + */ + +/** + * 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} + */ +var insertGreatestCommonDivisors = function(head) { + let current = head; + while (current && current.next) { + const nextNode = current.next; + const divisor = gcd(current.val, nextNode.val); + current.next = new ListNode(divisor, nextNode); + current = nextNode; + } + return head; + + function gcd(a, b) { + while (b) { + a %= b; + [a, b] = [b, a]; + } + return a; + } +}; diff --git a/solutions/2810-faulty-keyboard.js b/solutions/2810-faulty-keyboard.js new file mode 100644 index 00000000..47cb30e8 --- /dev/null +++ b/solutions/2810-faulty-keyboard.js @@ -0,0 +1,30 @@ +/** + * 2810. Faulty Keyboard + * https://leetcode.com/problems/faulty-keyboard/ + * Difficulty: Easy + * + * Your laptop keyboard is faulty, and whenever you type a character 'i' on it, it reverses the + * string that you have written. Typing other characters works as expected. + * + * You are given a 0-indexed string s, and you type each character of s using your faulty keyboard. + * + * Return the final string that will be present on your laptop screen. + */ + +/** + * @param {string} s + * @return {string} + */ +var finalString = function(s) { + const result = []; + + for (const char of s) { + if (char === 'i') { + result.reverse(); + } else { + result.push(char); + } + } + + return result.join(''); +}; diff --git a/solutions/2814-minimum-time-takes-to-reach-destination-without-drowning.js b/solutions/2814-minimum-time-takes-to-reach-destination-without-drowning.js new file mode 100644 index 00000000..c83fc741 --- /dev/null +++ b/solutions/2814-minimum-time-takes-to-reach-destination-without-drowning.js @@ -0,0 +1,90 @@ +/** + * 2814. Minimum Time Takes to Reach Destination Without Drowning + * https://leetcode.com/problems/minimum-time-takes-to-reach-destination-without-drowning/ + * Difficulty: Hard + * + * You are given an n * m 0-indexed grid of string land. Right now, you are standing at the cell + * that contains "S", and you want to get to the cell containing "D". There are three other types + * of cells in this land: + * - ".": These cells are empty. + * - "X": These cells are stone. + * - "*": These cells are flooded. + * + * At each second, you can move to a cell that shares a side with your current cell (if it exists). + * Also, at each second, every empty cell that shares a side with a flooded cell becomes flooded + * as well. + * + * There are two problems ahead of your journey: + * - You can't step on stone cells. + * - You can't step on flooded cells since you will drown (also, you can't step on a cell that will + * be flooded at the same time as you step on it). + * + * Return the minimum time it takes you to reach the destination in seconds, or -1 if it is + * impossible. + * + * Note that the destination will never be flooded. + */ + +/** + * @param {string[][]} land + * @return {number} + */ +var minimumSeconds = function(land) { + const rows = land.length; + const cols = land[0].length; + const directions = [[1, 0], [-1, 0], [0, 1], [0, -1]]; + const floodQueue = []; + const startQueue = []; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (land[i][j] === 'S') { + startQueue.push([i, j]); + } else if (land[i][j] === '*') { + floodQueue.push([i, j]); + } + } + } + + let time = 0; + + while (startQueue.length > 0) { + time++; + + const floodSize = floodQueue.length; + for (let f = 0; f < floodSize; f++) { + const [i, j] = floodQueue.shift(); + for (const [dx, dy] of directions) { + const x = i + dx; + const y = j + dy; + if (isValidPosition(x, y) && land[x][y] === '.') { + land[x][y] = '*'; + floodQueue.push([x, y]); + } + } + } + + const startSize = startQueue.length; + for (let s = 0; s < startSize; s++) { + const [i, j] = startQueue.shift(); + for (const [dx, dy] of directions) { + const x = i + dx; + const y = j + dy; + if (isValidPosition(x, y)) { + if (land[x][y] === 'D') { + return time; + } else if (land[x][y] === '.') { + land[x][y] = 'S'; + startQueue.push([x, y]); + } + } + } + } + } + + return -1; + + function isValidPosition(x, y) { + return x >= 0 && x < rows && y >= 0 && y < cols; + } +}; diff --git a/solutions/2815-max-pair-sum-in-an-array.js b/solutions/2815-max-pair-sum-in-an-array.js new file mode 100644 index 00000000..d6a41368 --- /dev/null +++ b/solutions/2815-max-pair-sum-in-an-array.js @@ -0,0 +1,48 @@ +/** + * 2815. Max Pair Sum in an Array + * https://leetcode.com/problems/max-pair-sum-in-an-array/ + * Difficulty: Easy + * + * You are given an integer array nums. You have to find the maximum sum of a pair of numbers from + * nums such that the largest digit in both numbers is equal. + * + * For example, 2373 is made up of three distinct digits: 2, 3, and 7, where 7 is the largest among + * them. + * + * Return the maximum sum or -1 if no such pair exists. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxSum = function(nums) { + let result = -1; + const map = new Map(); + + for (const num of nums) { + const maxDigit = getMaxDigit(num); + if (!map.has(maxDigit)) { + map.set(maxDigit, []); + } + map.get(maxDigit).push(num); + } + + for (const numbers of map.values()) { + if (numbers.length >= 2) { + numbers.sort((a, b) => b - a); + result = Math.max(result, numbers[0] + numbers[1]); + } + } + + return result; + + function getMaxDigit(num) { + let max = 0; + while (num > 0) { + max = Math.max(max, num % 10); + num = Math.floor(num / 10); + } + return max; + } +}; diff --git a/solutions/2816-double-a-number-represented-as-a-linked-list.js b/solutions/2816-double-a-number-represented-as-a-linked-list.js new file mode 100644 index 00000000..d6ef8c24 --- /dev/null +++ b/solutions/2816-double-a-number-represented-as-a-linked-list.js @@ -0,0 +1,54 @@ +/** + * 2816. Double a Number Represented as a Linked List + * https://leetcode.com/problems/double-a-number-represented-as-a-linked-list/ + * Difficulty: Medium + * + * You are given the head of a non-empty linked list representing a non-negative integer without + * leading zeroes. + * + * Return the head of the linked list after doubling it. + */ + +/** + * 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} + */ +var doubleIt = function(head) { + const reversed = reverseList(head); + let carry = 0; + let current = reversed; + let prev = null; + + while (current) { + const doubled = current.val * 2 + carry; + current.val = doubled % 10; + carry = Math.floor(doubled / 10); + prev = current; + current = current.next; + } + + if (carry) { + prev.next = new ListNode(carry); + } + + return reverseList(reversed); + + function reverseList(node) { + let prev = null; + let current = node; + while (current) { + const next = current.next; + current.next = prev; + prev = current; + current = next; + } + return prev; + } +}; diff --git a/solutions/2819-minimum-relative-loss-after-buying-chocolates.js b/solutions/2819-minimum-relative-loss-after-buying-chocolates.js new file mode 100644 index 00000000..7e32fb22 --- /dev/null +++ b/solutions/2819-minimum-relative-loss-after-buying-chocolates.js @@ -0,0 +1,77 @@ +/** + * 2819. Minimum Relative Loss After Buying Chocolates + * https://leetcode.com/problems/minimum-relative-loss-after-buying-chocolates/ + * Difficulty: Hard + * + * You are given an integer array prices, which shows the chocolate prices and a 2D integer + * array queries, where queries[i] = [ki, mi]. + * + * Alice and Bob went to buy some chocolates, and Alice suggested a way to pay for them, and + * Bob agreed. + * + * The terms for each query are as follows: + * - If the price of a chocolate is less than or equal to ki, Bob pays for it. + * - Otherwise, Bob pays ki of it, and Alice pays the rest. + * + * Bob wants to select exactly mi chocolates such that his relative loss is minimized, more + * formally, if, in total, Alice has paid ai and Bob has paid bi, Bob wants to minimize bi - ai. + * + * Return an integer array ans where ans[i] is Bob's minimum relative loss possible for queries[i]. + */ + +/** + * @param {number[]} prices + * @param {number[][]} queries + * @return {number[]} + */ +var minimumRelativeLosses = function(prices, queries) { + prices.sort((a, b) => a - b); + const n = prices.length; + const result = []; + + const prefixSum = [0]; + for (let i = 0; i < n; i++) { + prefixSum[i + 1] = prefixSum[i] + prices[i]; + } + + for (const [k, m] of queries) { + const split = Math.min(bisectLeft(prices, k), m); + const cut = bisectLeftWithKey(split, 2 * k, x => prices[x] + prices[n - m + x]); + const relativeLoss = (m - cut) * 2 * k + prefixSum[n - m + cut] + prefixSum[cut] - prefixSum[n]; + result.push(relativeLoss); + } + + return result; + + function bisectLeft(arr, target) { + let left = 0; + let right = arr.length; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (arr[mid] < target) { + left = mid + 1; + } else { + right = mid; + } + } + + return left; + } + + function bisectLeftWithKey(length, target, keyFunc) { + let left = 0; + let right = length; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (keyFunc(mid) < target) { + left = mid + 1; + } else { + right = mid; + } + } + + return left; + } +}; diff --git a/solutions/2821-delay-the-resolution-of-each-promise.js b/solutions/2821-delay-the-resolution-of-each-promise.js new file mode 100644 index 00000000..ef498272 --- /dev/null +++ b/solutions/2821-delay-the-resolution-of-each-promise.js @@ -0,0 +1,36 @@ +/** + * 2821. Delay the Resolution of Each Promise + * https://leetcode.com/problems/delay-the-resolution-of-each-promise/ + * Difficulty: Medium + * + * Given an array functions and a number ms, return a new array of functions. + * - functions is an array of functions that return promises. + * - ms represents the delay duration in milliseconds. It determines the amount of time to wait + * before resolving or rejecting each promise in the new array. + * + * Each function in the new array should return a promise that resolves or rejects after an + * additional delay of ms milliseconds, preserving the order of the original functions array. + * + * The delayAll function should ensure that each promise from functions is executed with a + * delay, forming the new array of functions returning delayed promises. + */ + +/** + * @param {Array} functions + * @param {number} ms + * @return {Array} + */ +var delayAll = function(functions, ms) { + return functions.map(fn => { + return async function() { + try { + const result = await fn(); + await new Promise(resolve => setTimeout(resolve, ms)); + return result; + } catch (error) { + await new Promise(resolve => setTimeout(resolve, ms)); + throw error; + } + }; + }); +}; diff --git a/solutions/2822-inversion-of-object.js b/solutions/2822-inversion-of-object.js new file mode 100644 index 00000000..53bae8e5 --- /dev/null +++ b/solutions/2822-inversion-of-object.js @@ -0,0 +1,38 @@ +/** + * 2822. Inversion of Object + * https://leetcode.com/problems/inversion-of-object/ + * Difficulty: Easy + * + * Given an object or an array obj, return an inverted object or array invertedObj. + * + * The invertedObj should have the keys of obj as values and the values of obj as keys. + * The indices of array should be treated as keys. + * + * The function should handle duplicates, meaning that if there are multiple keys in obj + * with the same value, the invertedObj should map the value to an array containing all + * corresponding keys. + * + * It is guaranteed that the values in obj are only strings. + */ + +/** + * @param {Object|Array} obj + * @return {Object} + */ +var invertObject = function(obj) { + const result = {}; + + Object.keys(obj).forEach(key => { + const value = obj[key]; + + if (result[value] === undefined) { + result[value] = key; + } else if (Array.isArray(result[value])) { + result[value].push(key); + } else { + result[value] = [result[value], key]; + } + }); + + return result; +}; diff --git a/solutions/2823-deep-object-filter.js b/solutions/2823-deep-object-filter.js new file mode 100644 index 00000000..99f9cd1b --- /dev/null +++ b/solutions/2823-deep-object-filter.js @@ -0,0 +1,48 @@ +/** + * 2823. Deep Object Filter + * https://leetcode.com/problems/deep-object-filter/ + * Difficulty: Medium + * + * Given an object or an array obj and a function fn, return a filtered object or array + * filteredObject. + * + * Function deepFilter should perform a deep filter operation on the obj. The deep filter + * operation should remove properties for which the output of the filter function fn is + * false, as well as any empty objects or arrays that remain after the keys have been removed. + * + * If the deep filter operation results in an empty object or array, with no remaining + * properties, deepFilter should return undefined to indicate that there is no valid data + * left in the filteredObject. + */ + +/** + * @param {Object|Array} obj + * @param {Function} fn + * @return {Object|Array|undefined} + */ +var deepFilter = function(obj, fn) { + if (Array.isArray(obj)) { + const filteredArray = obj + .map(item => deepFilter(item, fn)) + .filter(item => item !== undefined); + + return filteredArray.length > 0 ? filteredArray : undefined; + } + + if (typeof obj === 'object' && obj !== null) { + const filteredObject = {}; + let hasValidProperties = false; + + Object.keys(obj).forEach(key => { + const filteredValue = deepFilter(obj[key], fn); + if (filteredValue !== undefined) { + filteredObject[key] = filteredValue; + hasValidProperties = true; + } + }); + + return hasValidProperties ? filteredObject : undefined; + } + + return fn(obj) ? obj : undefined; +}; diff --git a/solutions/2824-count-pairs-whose-sum-is-less-than-target.js b/solutions/2824-count-pairs-whose-sum-is-less-than-target.js new file mode 100644 index 00000000..cdf97867 --- /dev/null +++ b/solutions/2824-count-pairs-whose-sum-is-less-than-target.js @@ -0,0 +1,32 @@ +/** + * 2824. Count Pairs Whose Sum is Less than Target + * https://leetcode.com/problems/count-pairs-whose-sum-is-less-than-target/ + * Difficulty: Easy + * + * Given a 0-indexed integer array nums of length n and an integer target, return the number + * of pairs (i, j) where 0 <= i < j < n and nums[i] + nums[j] < target. + */ + +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +var countPairs = function(nums, target) { + let result = 0; + let left = 0; + let right = nums.length - 1; + + nums.sort((a, b) => a - b); + + while (left < right) { + if (nums[left] + nums[right] < target) { + result += right - left; + left++; + } else { + right--; + } + } + + return result; +}; diff --git a/solutions/2825-make-string-a-subsequence-using-cyclic-increments.js b/solutions/2825-make-string-a-subsequence-using-cyclic-increments.js new file mode 100644 index 00000000..b6b96b8f --- /dev/null +++ b/solutions/2825-make-string-a-subsequence-using-cyclic-increments.js @@ -0,0 +1,39 @@ +/** + * 2825. Make String a Subsequence Using Cyclic Increments + * https://leetcode.com/problems/make-string-a-subsequence-using-cyclic-increments/ + * Difficulty: Medium + * + * You are given two 0-indexed strings str1 and str2. + * + * In an operation, you select a set of indices in str1, and for each index i in the set, + * increment str1[i] to the next character cyclically. That is 'a' becomes 'b', 'b' becomes + * 'c', and so on, and 'z' becomes 'a'. + * + * Return true if it is possible to make str2 a subsequence of str1 by performing the operation + * at most once, and false otherwise. + * + * Note: A subsequence of a string is a new string that is formed from the original string by + * deleting some (possibly none) of the characters without disturbing the relative positions + * of the remaining characters. + */ + +/** + * @param {string} str1 + * @param {string} str2 + * @return {boolean} + */ +var canMakeSubsequence = function(str1, str2) { + let i = 0; + let j = 0; + + while (i < str1.length && j < str2.length) { + const curr = str1[i].charCodeAt(0); + const next = curr === 122 ? 97 : curr + 1; + if (str1[i] === str2[j] || String.fromCharCode(next) === str2[j]) { + j++; + } + i++; + } + + return j === str2.length; +}; diff --git a/solutions/2826-sorting-three-groups.js b/solutions/2826-sorting-three-groups.js new file mode 100644 index 00000000..0153b199 --- /dev/null +++ b/solutions/2826-sorting-three-groups.js @@ -0,0 +1,34 @@ +/** + * 2826. Sorting Three Groups + * https://leetcode.com/problems/sorting-three-groups/ + * Difficulty: Medium + * + * You are given an integer array nums. Each element in nums is 1, 2 or 3. In each operation, + * you can remove an element from nums. Return the minimum number of operations to make nums + * non-decreasing. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumOperations = function(nums) { + const n = nums.length; + const dp = new Array(n + 1).fill(0).map(() => new Array(4).fill(Infinity)); + dp[0][0] = 0; + + for (let i = 0; i < n; i++) { + for (let prev = 0; prev <= 3; prev++) { + for (let curr = 1; curr <= 3; curr++) { + if (curr >= prev) { + dp[i + 1][curr] = Math.min( + dp[i + 1][curr], + dp[i][prev] + (nums[i] === curr ? 0 : 1) + ); + } + } + } + } + + return Math.min(...dp[n].slice(1)); +}; diff --git a/solutions/2828-check-if-a-string-is-an-acronym-of-words.js b/solutions/2828-check-if-a-string-is-an-acronym-of-words.js new file mode 100644 index 00000000..c0b34517 --- /dev/null +++ b/solutions/2828-check-if-a-string-is-an-acronym-of-words.js @@ -0,0 +1,23 @@ +/** + * 2828. Check if a String Is an Acronym of Words + * https://leetcode.com/problems/check-if-a-string-is-an-acronym-of-words/ + * Difficulty: Easy + * + * Given an array of strings words and a string s, determine if s is an acronym of words. + * + * The string s is considered an acronym of words if it can be formed by concatenating the + * first character of each string in words in order. For example, "ab" can be formed from + * ["apple", "banana"], but it can't be formed from ["bear", "aardvark"]. + * + * Return true if s is an acronym of words, and false otherwise. + */ + +/** + * @param {string[]} words + * @param {string} s + * @return {boolean} + */ +var isAcronym = function(words, s) { + if (words.length !== s.length) return false; + return words.every((word, index) => word[0] === s[index]); +}; diff --git a/solutions/2829-determine-the-minimum-sum-of-a-k-avoiding-array.js b/solutions/2829-determine-the-minimum-sum-of-a-k-avoiding-array.js new file mode 100644 index 00000000..540df710 --- /dev/null +++ b/solutions/2829-determine-the-minimum-sum-of-a-k-avoiding-array.js @@ -0,0 +1,34 @@ +/** + * 2829. Determine the Minimum Sum of a k-avoiding Array + * https://leetcode.com/problems/determine-the-minimum-sum-of-a-k-avoiding-array/ + * Difficulty: Medium + * + * You are given two integers, n and k. + * + * An array of distinct positive integers is called a k-avoiding array if there does not exist + * any pair of distinct elements that sum to k. + * + * Return the minimum possible sum of a k-avoiding array of length n. + */ + +/** + * @param {number} n + * @param {number} k + * @return {number} + */ +var minimumSum = function(n, k) { + const set = new Set(); + let result = 0; + let num = 1; + + for (let i = 0; i < n; i++) { + while (set.has(k - num)) { + num++; + } + result += num; + set.add(num); + num++; + } + + return result; +}; diff --git a/solutions/2832-maximal-range-that-each-element-is-maximum-in-it.js b/solutions/2832-maximal-range-that-each-element-is-maximum-in-it.js new file mode 100644 index 00000000..b554dd4a --- /dev/null +++ b/solutions/2832-maximal-range-that-each-element-is-maximum-in-it.js @@ -0,0 +1,51 @@ +/** + * 2832. Maximal Range That Each Element Is Maximum in It + * https://leetcode.com/problems/maximal-range-that-each-element-is-maximum-in-it/ + * Difficulty: Medium + * + * You are given a 0-indexed array nums of distinct integers. + * + * Let us define a 0-indexed array ans of the same length as nums in the following way: + * - ans[i] is the maximum length of a subarray nums[l..r], such that the maximum element + * in that subarray is equal to nums[i]. + * + * Return the array ans. + * + * Note that a subarray is a contiguous part of the array. + */ + +/** + * @param {number[]} nums + * @return {number[]} + */ +var maximumLengthOfRanges = function(nums) { + const n = nums.length; + const leftBounds = new Array(n); + const rightBounds = new Array(n); + const stack = []; + + for (let i = 0; i < n; i++) { + while (stack.length > 0 && nums[stack[stack.length - 1]] < nums[i]) { + stack.pop(); + } + leftBounds[i] = stack.length > 0 ? stack[stack.length - 1] + 1 : 0; + stack.push(i); + } + + stack.length = 0; + + for (let i = n - 1; i >= 0; i--) { + while (stack.length > 0 && nums[stack[stack.length - 1]] < nums[i]) { + stack.pop(); + } + rightBounds[i] = stack.length > 0 ? stack[stack.length - 1] - 1 : n - 1; + stack.push(i); + } + + const result = new Array(n); + for (let i = 0; i < n; i++) { + result[i] = rightBounds[i] - leftBounds[i] + 1; + } + + return result; +}; diff --git a/solutions/2833-furthest-point-from-origin.js b/solutions/2833-furthest-point-from-origin.js new file mode 100644 index 00000000..0428216f --- /dev/null +++ b/solutions/2833-furthest-point-from-origin.js @@ -0,0 +1,32 @@ +/** + * 2833. Furthest Point From Origin + * https://leetcode.com/problems/furthest-point-from-origin/ + * Difficulty: Easy + * + * You are given a string moves of length n consisting only of characters 'L', 'R', and '_'. + * The string represents your movement on a number line starting from the origin 0. + * + * In the ith move, you can choose one of the following directions: + * - move to the left if moves[i] = 'L' or moves[i] = '_' + * - move to the right if moves[i] = 'R' or moves[i] = '_' + * + * Return the distance from the origin of the furthest point you can get to after n moves. + */ + +/** + * @param {string} moves + * @return {number} + */ +var furthestDistanceFromOrigin = function(moves) { + let leftCount = 0; + let rightCount = 0; + let wildCount = 0; + + for (const move of moves) { + if (move === 'L') leftCount++; + else if (move === 'R') rightCount++; + else wildCount++; + } + + return Math.abs(leftCount - rightCount) + wildCount; +}; diff --git a/solutions/2838-maximum-coins-heroes-can-collect.js b/solutions/2838-maximum-coins-heroes-can-collect.js new file mode 100644 index 00000000..c32274a3 --- /dev/null +++ b/solutions/2838-maximum-coins-heroes-can-collect.js @@ -0,0 +1,64 @@ +/** + * 2838. Maximum Coins Heroes Can Collect + * https://leetcode.com/problems/maximum-coins-heroes-can-collect/ + * Difficulty: Medium + * + * There is a battle and n heroes are trying to defeat m monsters. You are given two 1-indexed + * arrays of positive integers heroes and monsters of length n and m, respectively. heroes[i] + * is the power of ith hero, and monsters[i] is the power of ith monster. + * + * The ith hero can defeat the jth monster if monsters[j] <= heroes[i]. + * + * You are also given a 1-indexed array coins of length m consisting of positive integers. + * coins[i] is the number of coins that each hero earns after defeating the ith monster. + * + * Return an array ans of length n where ans[i] is the maximum number of coins that the ith + * hero can collect from this battle. + * + * Notes + * - The health of a hero doesn't get reduced after defeating a monster. + * - Multiple heroes can defeat a monster, but each monster can be defeated by a given hero + * only once. + */ + +/** + * @param {number[]} heroes + * @param {number[]} monsters + * @param {number[]} coins + * @return {number[]} + */ +var maximumCoins = function(heroes, monsters, coins) { + const monsterCoinPairs = monsters.map((monster, i) => [monster, coins[i]]); + monsterCoinPairs.sort((a, b) => a[0] - b[0]); + const sortedMonsters = monsterCoinPairs.map(pair => pair[0]); + const sortedCoins = monsterCoinPairs.map(pair => pair[1]); + + const prefixSum = [0]; + for (let i = 0; i < sortedCoins.length; i++) { + prefixSum[i + 1] = prefixSum[i] + sortedCoins[i]; + } + + const result = []; + for (const heroPower of heroes) { + const defeatedCount = bisectRight(sortedMonsters, heroPower); + result.push(prefixSum[defeatedCount]); + } + + return result; + + function bisectRight(arr, target) { + let left = 0; + let right = arr.length; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (arr[mid] <= target) { + left = mid + 1; + } else { + right = mid; + } + } + + return left; + } +}; diff --git a/solutions/2839-check-if-strings-can-be-made-equal-with-operations-i.js b/solutions/2839-check-if-strings-can-be-made-equal-with-operations-i.js new file mode 100644 index 00000000..3eb6dfcb --- /dev/null +++ b/solutions/2839-check-if-strings-can-be-made-equal-with-operations-i.js @@ -0,0 +1,25 @@ +/** + * 2839. Check if Strings Can be Made Equal With Operations I + * https://leetcode.com/problems/check-if-strings-can-be-made-equal-with-operations-i/ + * Difficulty: Easy + * + * You are given two strings s1 and s2, both of length 4, consisting of lowercase English + * letters. + * + * You can apply the following operation on any of the two strings any number of times: + * - Choose any two indices i and j such that j - i = 2, then swap the two characters at those + * indices in the string. + * + * Return true if you can make the strings s1 and s2 equal, and false otherwise. + */ + +/** + * @param {string} s1 + * @param {string} s2 + * @return {boolean} + */ +var canBeEqual = function(s1, s2) { + const firstPair = [s1[0], s1[2]].sort().join() === [s2[0], s2[2]].sort().join(); + const secondPair = [s1[1], s1[3]].sort().join() === [s2[1], s2[3]].sort().join(); + return firstPair && secondPair; +}; diff --git a/solutions/2840-check-if-strings-can-be-made-equal-with-operations-ii.js b/solutions/2840-check-if-strings-can-be-made-equal-with-operations-ii.js new file mode 100644 index 00000000..28a8805e --- /dev/null +++ b/solutions/2840-check-if-strings-can-be-made-equal-with-operations-ii.js @@ -0,0 +1,38 @@ +/** + * 2840. Check if Strings Can be Made Equal With Operations II + * https://leetcode.com/problems/check-if-strings-can-be-made-equal-with-operations-ii/ + * Difficulty: Medium + * + * You are given two strings s1 and s2, both of length n, consisting of lowercase English letters. + * + * You can apply the following operation on any of the two strings any number of times: + * - Choose any two indices i and j such that i < j and the difference j - i is even, then swap the + * two characters at those indices in the string. + * + * Return true if you can make the strings s1 and s2 equal, and false otherwise. + */ + +/** + * @param {string} s1 + * @param {string} s2 + * @return {boolean} + */ +var checkStrings = function(s1, s2) { + const evenChars1 = []; + const oddChars1 = []; + const evenChars2 = []; + const oddChars2 = []; + + for (let i = 0; i < s1.length; i++) { + if (i % 2 === 0) { + evenChars1.push(s1[i]); + evenChars2.push(s2[i]); + } else { + oddChars1.push(s1[i]); + oddChars2.push(s2[i]); + } + } + + return evenChars1.sort().join('') === evenChars2.sort().join('') + && oddChars1.sort().join('') === oddChars2.sort().join(''); +}; diff --git a/solutions/2841-maximum-sum-of-almost-unique-subarray.js b/solutions/2841-maximum-sum-of-almost-unique-subarray.js new file mode 100644 index 00000000..e36e3b1a --- /dev/null +++ b/solutions/2841-maximum-sum-of-almost-unique-subarray.js @@ -0,0 +1,51 @@ +/** + * 2841. Maximum Sum of Almost Unique Subarray + * https://leetcode.com/problems/maximum-sum-of-almost-unique-subarray/ + * Difficulty: Medium + * + * You are given an integer array nums and two positive integers m and k. + * + * Return the maximum sum out of all almost unique subarrays of length k of nums. If no such + * subarray exists, return 0. + * + * A subarray of nums is almost unique if it contains at least m distinct elements. + * + * A subarray is a contiguous non-empty sequence of elements within an array. + */ + +/** + * @param {number[]} nums + * @param {number} m + * @param {number} k + * @return {number} + */ +var maxSum = function(nums, m, k) { + const map = new Map(); + let subarraySum = 0; + let result = 0; + + for (let i = 0; i < k; i++) { + map.set(nums[i], (map.get(nums[i]) || 0) + 1); + subarraySum += nums[i]; + } + + if (map.size >= m) { + result = subarraySum; + } + + for (let i = k; i < nums.length; i++) { + map.set(nums[i - k], map.get(nums[i - k]) - 1); + if (map.get(nums[i - k]) === 0) { + map.delete(nums[i - k]); + } + + map.set(nums[i], (map.get(nums[i]) || 0) + 1); + subarraySum = subarraySum - nums[i - k] + nums[i]; + + if (map.size >= m) { + result = Math.max(result, subarraySum); + } + } + + return result; +}; diff --git a/solutions/2846-minimum-edge-weight-equilibrium-queries-in-a-tree.js b/solutions/2846-minimum-edge-weight-equilibrium-queries-in-a-tree.js new file mode 100644 index 00000000..87c0f17c --- /dev/null +++ b/solutions/2846-minimum-edge-weight-equilibrium-queries-in-a-tree.js @@ -0,0 +1,77 @@ +/** + * 2846. Minimum Edge Weight Equilibrium Queries in a Tree + * https://leetcode.com/problems/minimum-edge-weight-equilibrium-queries-in-a-tree/ + * Difficulty: Hard + * + * There is an undirected tree with n nodes labeled from 0 to n - 1. You are given the integer n and + * a 2D integer array edges of length n - 1, where edges[i] = [ui, vi, wi] indicates that there is + * an edge between nodes ui and vi with weight wi in the tree. + * + * You are also given a 2D integer array queries of length m, where queries[i] = [ai, bi]. For each + * query, find the minimum number of operations required to make the weight of every edge on the + * path from ai to bi equal. In one operation, you can choose any edge of the tree and change its + * weight to any value. + * + * Note that: + * - Queries are independent of each other, meaning that the tree returns to its initial state on + * each new query. + * - The path from ai to bi is a sequence of distinct nodes starting with node ai and ending with + * node bi such that every two adjacent nodes in the sequence share an edge in the tree. + * + * Return an array answer of length m where answer[i] is the answer to the ith query. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number[][]} queries + * @return {number[]} + */ +var minOperationsQueries = function(n, edges, queries) { + const graph = Array.from({ length: n }, () => []); + for (const [u, v, w] of edges) { + graph[u].push([v, w]); + graph[v].push([u, w]); + } + + const parent = new Array(n).fill(-1); + const weightCount = new Array(n).fill().map(() => new Array(27).fill(0)); + const depth = new Array(n).fill(0); + + dfs(0, -1, 0); + + const result = []; + for (const [u, v] of queries) { + const ancestor = lca(u, v); + const counts = Array(27).fill(0); + for (let i = 1; i <= 26; i++) { + counts[i] = weightCount[u][i] + weightCount[v][i] - 2 * weightCount[ancestor][i]; + } + const total = depth[u] + depth[v] - 2 * depth[ancestor]; + const maxCount = Math.max(...counts); + result.push(total - maxCount); + } + + return result; + + function dfs(node, par, dep) { + parent[node] = par; + depth[node] = dep; + for (const [next, w] of graph[node]) { + if (next !== par) { + weightCount[next] = [...weightCount[node]]; + weightCount[next][w]++; + dfs(next, node, dep + 1); + } + } + } + function lca(u, v) { + if (depth[u] < depth[v]) [u, v] = [v, u]; + while (depth[u] > depth[v]) u = parent[u]; + while (u !== v) { + u = parent[u]; + v = parent[v]; + } + return u; + } +}; diff --git a/solutions/2847-smallest-number-with-given-digit-product.js b/solutions/2847-smallest-number-with-given-digit-product.js new file mode 100644 index 00000000..f1eeec41 --- /dev/null +++ b/solutions/2847-smallest-number-with-given-digit-product.js @@ -0,0 +1,30 @@ +/** + * 2847. Smallest Number With Given Digit Product + * https://leetcode.com/problems/smallest-number-with-given-digit-product/ + * Difficulty: Medium + * + * Given a positive integer n, return a string representing the smallest positive integer + * such that the product of its digits is equal to n, or "-1" if no such number exists. + */ + +/** + * @param {number} n + * @return {string} + */ +var smallestNumber = function(n) { + if (n < 10) return n.toString(); + + const digits = []; + let remaining = BigInt(n); + for (let digit = 9; digit > 1 && remaining > 1n; digit--) { + const bigDigit = BigInt(digit); + while (remaining % bigDigit === 0n) { + digits.push(digit); + remaining /= bigDigit; + } + } + + if (remaining !== 1n) return '-1'; + + return digits.reverse().join(''); +}; diff --git a/solutions/2848-points-that-intersect-with-cars.js b/solutions/2848-points-that-intersect-with-cars.js new file mode 100644 index 00000000..fc4f58de --- /dev/null +++ b/solutions/2848-points-that-intersect-with-cars.js @@ -0,0 +1,27 @@ +/** + * 2848. Points That Intersect With Cars + * https://leetcode.com/problems/points-that-intersect-with-cars/ + * Difficulty: Easy + * + * You are given a 0-indexed 2D integer array nums representing the coordinates of the cars + * parking on a number line. For any index i, nums[i] = [starti, endi] where starti is the + * starting point of the ith car and endi is the ending point of the ith car. + * + * Return the number of integer points on the line that are covered with any part of a car. + */ + +/** + * @param {number[][]} nums + * @return {number} + */ +var numberOfPoints = function(nums) { + const set = new Set(); + + for (const [start, end] of nums) { + for (let i = start; i <= end; i++) { + set.add(i); + } + } + + return set.size; +}; diff --git a/solutions/2850-minimum-moves-to-spread-stones-over-grid.js b/solutions/2850-minimum-moves-to-spread-stones-over-grid.js new file mode 100644 index 00000000..b56e1393 --- /dev/null +++ b/solutions/2850-minimum-moves-to-spread-stones-over-grid.js @@ -0,0 +1,59 @@ +/** + * 2850. Minimum Moves to Spread Stones Over Grid + * https://leetcode.com/problems/minimum-moves-to-spread-stones-over-grid/ + * Difficulty: Medium + * + * You are given a 0-indexed 2D integer matrix grid of size 3 * 3, representing the number of + * stones in each cell. The grid contains exactly 9 stones, and there can be multiple stones + * in a single cell. + * + * In one move, you can move a single stone from its current cell to any other cell if the two + * cells share a side. + * + * Return the minimum number of moves required to place one stone in each cell. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var minimumMoves = function(grid) { + const sources = []; + const targets = []; + + for (let i = 0; i < 3; i++) { + for (let j = 0; j < 3; j++) { + if (grid[i][j] > 1) { + for (let k = 1; k < grid[i][j]; k++) { + sources.push([i, j]); + } + } else if (grid[i][j] === 0) { + targets.push([i, j]); + } + } + } + + let minMoves = Infinity; + + permute(0, 0); + return minMoves; + + function permute(index, moves) { + if (index === sources.length) { + minMoves = Math.min(minMoves, moves); + return; + } + + for (let i = 0; i < targets.length; i++) { + if (targets[i]) { + const [si, sj] = sources[index]; + const [ti, tj] = targets[i]; + const dist = Math.abs(si - ti) + Math.abs(sj - tj); + const temp = targets[i]; + targets[i] = null; + permute(index + 1, moves + dist); + targets[i] = temp; + } + } + } +}; diff --git a/solutions/2852-sum-of-remoteness-of-all-cells.js b/solutions/2852-sum-of-remoteness-of-all-cells.js new file mode 100644 index 00000000..94af23c5 --- /dev/null +++ b/solutions/2852-sum-of-remoteness-of-all-cells.js @@ -0,0 +1,66 @@ +/** + * 2852. Sum of Remoteness of All Cells + * https://leetcode.com/problems/sum-of-remoteness-of-all-cells/ + * Difficulty: Medium + * + * You are given a 0-indexed matrix grid of order n * n. Each cell in this matrix has a + * value grid[i][j], which is either a positive integer or -1 representing a blocked cell. + * + * You can move from a non-blocked cell to any non-blocked cell that shares an edge. + * + * For any cell (i, j), we represent its remoteness as R[i][j] which is defined as the following: + * - If the cell (i, j) is a non-blocked cell, R[i][j] is the sum of the values grid[x][y] such + * that there is no path from the non-blocked cell (x, y) to the cell (i, j). + * - For blocked cells, R[i][j] == 0. + * + * Return the sum of R[i][j] over all cells. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var sumRemoteness = function(grid) { + const n = grid.length; + const m = grid[0].length; + const directions = [[-1, 0], [0, 1], [1, 0], [0, -1]]; + + let totalSum = 0; + for (let i = 0; i < n; i++) { + for (let j = 0; j < m; j++) { + totalSum += Math.max(grid[i][j], 0); + } + } + + let result = 0; + for (let i = 0; i < n; i++) { + for (let j = 0; j < m; j++) { + if (grid[i][j] > 0) { + const [componentSum, componentCount] = dfs(i, j, grid); + result += (totalSum - componentSum) * componentCount; + } + } + } + + return result; + + function dfs(x, y, grid) { + if (x < 0 || x >= n || y < 0 || y >= m || grid[x][y] < 0) { + return [0, 0]; + } + + const cellValue = grid[x][y]; + grid[x][y] = -1; + + let componentSum = cellValue; + let componentCount = 1; + + for (const [dx, dy] of directions) { + const [sum, count] = dfs(x + dx, y + dy, grid); + componentSum += sum; + componentCount += count; + } + + return [componentSum, componentCount]; + } +}; diff --git a/solutions/2855-minimum-right-shifts-to-sort-the-array.js b/solutions/2855-minimum-right-shifts-to-sort-the-array.js new file mode 100644 index 00000000..9bf69806 --- /dev/null +++ b/solutions/2855-minimum-right-shifts-to-sort-the-array.js @@ -0,0 +1,33 @@ +/** + * 2855. Minimum Right Shifts to Sort the Array + * https://leetcode.com/problems/minimum-right-shifts-to-sort-the-array/ + * Difficulty: Easy + * + * You are given a 0-indexed array nums of length n containing distinct positive integers. + * Return the minimum number of right shifts required to sort nums and -1 if this is not + * possible. + * + * A right shift is defined as shifting the element at index i to index (i + 1) % n, for + * all indices. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumRightShifts = function(nums) { + const n = nums.length; + let breakPoint = 0; + + for (let i = 1; i < n; i++) { + if (nums[i] < nums[i - 1]) { + breakPoint++; + if (breakPoint > 1) return -1; + } + } + + if (breakPoint === 0) return 0; + if (nums[n - 1] > nums[0]) return -1; + + return n - (nums.indexOf(Math.min(...nums))); +}; diff --git a/solutions/2858-minimum-edge-reversals-so-every-node-is-reachable.js b/solutions/2858-minimum-edge-reversals-so-every-node-is-reachable.js new file mode 100644 index 00000000..dc7b451a --- /dev/null +++ b/solutions/2858-minimum-edge-reversals-so-every-node-is-reachable.js @@ -0,0 +1,62 @@ +/** + * 2858. Minimum Edge Reversals So Every Node Is Reachable + * https://leetcode.com/problems/minimum-edge-reversals-so-every-node-is-reachable/ + * Difficulty: Hard + * + * There is a simple directed graph with n nodes labeled from 0 to n - 1. The graph would form + * a tree if its edges were bi-directional. + * + * You are given an integer n and a 2D integer array edges, where edges[i] = [ui, vi] represents + * a directed edge going from node ui to node vi. + * + * An edge reversal changes the direction of an edge, i.e., a directed edge going from node ui to + * node vi becomes a directed edge going from node vi to node ui. + * + * For every node i in the range [0, n - 1], your task is to independently calculate the minimum + * number of edge reversals required so it is possible to reach any other node starting from node + * i through a sequence of directed edges. + * + * Return an integer array answer, where answer[i] is the minimum number of edge reversals required + * so it is possible to reach any other node starting from node i through a sequence of directed + * edges. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @return {number[]} + */ +var minEdgeReversals = function(n, edges) { + const graph = Array.from({ length: n }, () => []); + + for (const [u, v] of edges) { + graph[u].push([v, 0]); + graph[v].push([u, 1]); + } + + const result = new Array(n); + const rootReversals = dfs(0, -1); + + reroot(0, -1, rootReversals); + + return result; + function dfs(node, parent) { + let reversals = 0; + for (const [neighbor, cost] of graph[node]) { + if (neighbor !== parent) { + reversals += cost + dfs(neighbor, node); + } + } + return reversals; + } + + function reroot(node, parent, parentReversals) { + result[node] = parentReversals; + for (const [neighbor, cost] of graph[node]) { + if (neighbor !== parent) { + const childReversals = result[node] - cost + (1 - cost); + reroot(neighbor, node, childReversals); + } + } + } +}; diff --git a/solutions/2859-sum-of-values-at-indices-with-k-set-bits.js b/solutions/2859-sum-of-values-at-indices-with-k-set-bits.js new file mode 100644 index 00000000..c14b88d3 --- /dev/null +++ b/solutions/2859-sum-of-values-at-indices-with-k-set-bits.js @@ -0,0 +1,31 @@ +/** + * 2859. Sum of Values at Indices With K Set Bits + * https://leetcode.com/problems/sum-of-values-at-indices-with-k-set-bits/ + * Difficulty: Easy + * + * You are given a 0-indexed integer array nums and an integer k. + * + * Return an integer that denotes the sum of elements in nums whose corresponding indices have + * exactly k set bits in their binary representation. + * + * The set bits in an integer are the 1's present when it is written in binary. + * + * For example, the binary representation of 21 is 10101, which has 3 set bits. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var sumIndicesWithKSetBits = function(nums, k) { + let result = 0; + + for (let i = 0; i < nums.length; i++) { + if (i.toString(2).split('1').length - 1 === k) { + result += nums[i]; + } + } + + return result; +}; diff --git a/solutions/2860-happy-students.js b/solutions/2860-happy-students.js new file mode 100644 index 00000000..460015b2 --- /dev/null +++ b/solutions/2860-happy-students.js @@ -0,0 +1,38 @@ +/** + * 2860. Happy Students + * https://leetcode.com/problems/happy-students/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums of length n where n is the total number of + * students in the class. The class teacher tries to select a group of students so that + * all the students remain happy. + * + * The ith student will become happy if one of these two conditions is met: + * - The student is selected and the total number of selected students is strictly greater + * than nums[i]. + * - The student is not selected and the total number of selected students is strictly less + * than nums[i]. + * + * Return the number of ways to select a group of students so that everyone remains happy. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var countWays = function(nums) { + nums.sort((a, b) => a - b); + let result = 0; + let selected = 0; + + if (0 < nums[0]) result++; + + for (let i = 0; i < nums.length; i++) { + selected++; + if (selected > nums[i] && (i + 1 === nums.length || selected < nums[i + 1])) { + result++; + } + } + + return result; +}; diff --git a/solutions/2862-maximum-element-sum-of-a-complete-subset-of-indices.js b/solutions/2862-maximum-element-sum-of-a-complete-subset-of-indices.js new file mode 100644 index 00000000..33a8aa2d --- /dev/null +++ b/solutions/2862-maximum-element-sum-of-a-complete-subset-of-indices.js @@ -0,0 +1,46 @@ +/** + * 2862. Maximum Element-Sum of a Complete Subset of Indices + * https://leetcode.com/problems/maximum-element-sum-of-a-complete-subset-of-indices/ + * Difficulty: Hard + * + * You are given a 1-indexed array nums. Your task is to select a complete subset from nums where + * every pair of selected indices multiplied is a perfect square,. i. e. if you select ai and aj, + * i * j must be a perfect square. + * + * Return the sum of the complete subset with the maximum sum. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maximumSum = function(nums) { + const n = nums.length; + const map = new Map(); + + for (let i = 1; i <= n; i++) { + let factors = 1; + let num = i; + + for (let p = 2; p * p <= num; p++) { + let count = 0; + while (num % p === 0) { + count++; + num /= p; + } + if (count % 2 === 1) factors *= p; + } + if (num > 1) factors *= num; + + if (!map.has(factors)) map.set(factors, []); + map.get(factors).push(nums[i - 1]); + } + + let result = 0; + for (const group of map.values()) { + const sum = group.reduce((a, b) => a + b, 0); + result = Math.max(result, sum); + } + + return result; +}; diff --git a/solutions/2863-maximum-length-of-semi-decreasing-subarrays.js b/solutions/2863-maximum-length-of-semi-decreasing-subarrays.js new file mode 100644 index 00000000..d6b19fc6 --- /dev/null +++ b/solutions/2863-maximum-length-of-semi-decreasing-subarrays.js @@ -0,0 +1,46 @@ +/** + * 2863. Maximum Length of Semi-Decreasing Subarrays + * https://leetcode.com/problems/maximum-length-of-semi-decreasing-subarrays/ + * Difficulty: Medium + * + * You are given an integer array nums. + * + * Return the length of the longest semi-decreasing subarray of nums, and 0 if there are no + * such subarrays. + * - A subarray is a contiguous non-empty sequence of elements within an array. + * - A non-empty array is semi-decreasing if its first element is strictly greater than its + * last element. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxSubarrayLength = function(nums) { + const n = nums.length; + const stack = []; + + for (let i = n - 1; i >= 0; i--) { + if (stack.length === 0 || nums[i] < nums[stack[stack.length - 1]]) { + stack.push(i); + } + } + + let result = 0; + let maxSeen = -Infinity; + for (let i = 0; i < n && stack.length > 0; i++) { + while (stack.length > 0 && stack[stack.length - 1] <= i) { + stack.pop(); + } + + if (nums[i] > maxSeen) { + maxSeen = nums[i]; + while (stack.length > 0 && nums[stack[stack.length - 1]] < maxSeen) { + result = Math.max(result, stack[stack.length - 1] - i + 1); + stack.pop(); + } + } + } + + return result; +}; diff --git a/solutions/2864-maximum-odd-binary-number.js b/solutions/2864-maximum-odd-binary-number.js new file mode 100644 index 00000000..82fd37bc --- /dev/null +++ b/solutions/2864-maximum-odd-binary-number.js @@ -0,0 +1,27 @@ +/** + * 2864. Maximum Odd Binary Number + * https://leetcode.com/problems/maximum-odd-binary-number/ + * Difficulty: Easy + * + * You are given a binary string s that contains at least one '1'. + * + * You have to rearrange the bits in such a way that the resulting binary number is the maximum + * odd binary number that can be created from this combination. + * + * Return a string representing the maximum odd binary number that can be created from the given + * combination. + * + * Note that the resulting string can have leading zeros. + */ + +/** + * @param {string} s + * @return {string} + */ +var maximumOddBinaryNumber = function(s) { + let ones = 0; + for (const bit of s) { + if (bit === '1') ones++; + } + return '1'.padStart(ones, '1').padEnd(s.length, '0').slice(1) + '1'; +}; diff --git a/solutions/2865-beautiful-towers-i.js b/solutions/2865-beautiful-towers-i.js new file mode 100644 index 00000000..f0fa8c07 --- /dev/null +++ b/solutions/2865-beautiful-towers-i.js @@ -0,0 +1,44 @@ +/** + * 2865. Beautiful Towers I + * https://leetcode.com/problems/beautiful-towers-i/ + * Difficulty: Medium + * + * You are given an array heights of n integers representing the number of bricks in n + * consecutive towers. Your task is to remove some bricks to form a mountain-shaped tower + * arrangement. In this arrangement, the tower heights are non-decreasing, reaching a + * maximum peak value with one or multiple consecutive towers and then non-increasing. + * + * Return the maximum possible sum of heights of a mountain-shaped tower arrangement. + */ + +/** + * @param {number[]} heights + * @return {number} + */ +var maximumSumOfHeights = function(heights) { + const n = heights.length; + let result = 0; + + for (let peak = 0; peak < n; peak++) { + let currentSum = heights[peak]; + let prevHeight = heights[peak]; + + for (let i = peak - 1; i >= 0; i--) { + const currentHeight = Math.min(heights[i], prevHeight); + currentSum += currentHeight; + prevHeight = currentHeight; + } + + prevHeight = heights[peak]; + + for (let i = peak + 1; i < n; i++) { + const currentHeight = Math.min(heights[i], prevHeight); + currentSum += currentHeight; + prevHeight = currentHeight; + } + + result = Math.max(result, currentSum); + } + + return result; +}; diff --git a/solutions/2868-the-wording-game.js b/solutions/2868-the-wording-game.js new file mode 100644 index 00000000..56e33a12 --- /dev/null +++ b/solutions/2868-the-wording-game.js @@ -0,0 +1,77 @@ +/** + * 2868. The Wording Game + * https://leetcode.com/problems/the-wording-game/ + * Difficulty: Hard + * + * Alice and Bob each have a lexicographically sorted array of strings named a and b respectively. + * + * They are playing a wording game with the following rules: + * - On each turn, the current player should play a word from their list such that the new word is + * closely greater than the last played word; then it's the other player's turn. + * - If a player can't play a word on their turn, they lose. + * + * Alice starts the game by playing her lexicographically smallest word. + * + * Given a and b, return true if Alice can win knowing that both players play their best, and + * false otherwise. + * + * A word w is closely greater than a word z if the following conditions are met: + * - w is lexicographically greater than z. + * - If w1 is the first letter of w and z1 is the first letter of z, w1 should either be equal + * to z1 or be the letter after z1 in the alphabet. + * - For example, the word "care" is closely greater than "book" and "car", but is not closely + * greater than "ant" or "cook". + * + * A string s is lexicographically greater than a string t if in the first position where s and + * t differ, string s has a letter that appears later in the alphabet than the corresponding + * letter in t. If the first min(s.length, t.length) characters do not differ, then the longer + * string is the lexicographically greater one. + */ + +/** + * @param {string[]} a + * @param {string[]} b + * @return {boolean} + */ +var canAliceWin = function(a, b) { + const dictionaries = [{}, {}]; + + [a, b].forEach((words, playerIndex) => { + for (let i = words.length - 1; i >= 0; i--) { + const firstChar = words[i][0]; + if (!(firstChar in dictionaries[playerIndex])) { + dictionaries[playerIndex][firstChar] = words[i]; + } + } + }); + + const memo = new Map(); + + return !canCurrentPlayerWin(a[0], 1); + + function canCurrentPlayerWin(previousWord, playerIndex) { + const key = `${previousWord},${playerIndex}`; + if (memo.has(key)) return memo.get(key); + + const initialChar = previousWord[0]; + const nextChar = String.fromCharCode(initialChar.charCodeAt(0) + 1); + + if (initialChar in dictionaries[playerIndex] + && dictionaries[playerIndex][initialChar] > previousWord) { + if (!canCurrentPlayerWin(dictionaries[playerIndex][initialChar], playerIndex ^ 1)) { + memo.set(key, true); + return true; + } + } + + if (nextChar in dictionaries[playerIndex]) { + if (!canCurrentPlayerWin(dictionaries[playerIndex][nextChar], playerIndex ^ 1)) { + memo.set(key, true); + return true; + } + } + + memo.set(key, false); + return false; + } +}; diff --git a/solutions/2869-minimum-operations-to-collect-elements.js b/solutions/2869-minimum-operations-to-collect-elements.js new file mode 100644 index 00000000..4f52b704 --- /dev/null +++ b/solutions/2869-minimum-operations-to-collect-elements.js @@ -0,0 +1,29 @@ +/** + * 2869. Minimum Operations to Collect Elements + * https://leetcode.com/problems/minimum-operations-to-collect-elements/ + * Difficulty: Easy + * + * You are given an array nums of positive integers and an integer k. + * + * In one operation, you can remove the last element of the array and add it to your collection. + * + * Return the minimum number of operations needed to collect elements 1, 2, ..., k. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minOperations = function(nums, k) { + const set = new Set(); + let result = 0; + + for (let i = nums.length - 1; i >= 0; i--) { + result++; + if (nums[i] <= k) set.add(nums[i]); + if (set.size === k) return result; + } + + return result; +}; diff --git a/solutions/2870-minimum-number-of-operations-to-make-array-empty.js b/solutions/2870-minimum-number-of-operations-to-make-array-empty.js new file mode 100644 index 00000000..c6376c70 --- /dev/null +++ b/solutions/2870-minimum-number-of-operations-to-make-array-empty.js @@ -0,0 +1,33 @@ +/** + * 2870. Minimum Number of Operations to Make Array Empty + * https://leetcode.com/problems/minimum-number-of-operations-to-make-array-empty/ + * Difficulty: Medium + * + * You are given a 0-indexed array nums consisting of positive integers. + * + * There are two types of operations that you can apply on the array any number of times: + * - Choose two elements with equal values and delete them from the array. + * - Choose three elements with equal values and delete them from the array. + * + * Return the minimum number of operations required to make the array empty, or -1 if it is + * not possible. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minOperations = function(nums) { + const map = new Map(); + for (const num of nums) { + map.set(num, (map.get(num) || 0) + 1); + } + + let result = 0; + for (const count of map.values()) { + if (count === 1) return -1; + result += Math.ceil(count / 3); + } + + return result; +}; diff --git a/solutions/2871-split-array-into-maximum-number-of-subarrays.js b/solutions/2871-split-array-into-maximum-number-of-subarrays.js new file mode 100644 index 00000000..ff3141ce --- /dev/null +++ b/solutions/2871-split-array-into-maximum-number-of-subarrays.js @@ -0,0 +1,41 @@ +/** + * 2871. Split Array Into Maximum Number of Subarrays + * https://leetcode.com/problems/split-array-into-maximum-number-of-subarrays/ + * Difficulty: Medium + * + * You are given an array nums consisting of non-negative integers. + * + * We define the score of subarray nums[l..r] such that l <= r as nums[l] AND nums[l + 1] + * AND ... AND nums[r] where AND is the bitwise AND operation. + * + * Consider splitting the array into one or more subarrays such that the following conditions + * are satisfied: + * - Each element of the array belongs to exactly one subarray. + * - The sum of scores of the subarrays is the minimum possible. + * + * Return the maximum number of subarrays in a split that satisfies the conditions above. + * + * A subarray is a contiguous part of an array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxSubarrays = function(nums) { + const total = nums.reduce((acc, num) => acc & num, nums[0]); + if (total !== 0) return 1; + + let result = 0; + let current = -1; + + for (const num of nums) { + current = current === -1 ? num : current & num; + if (current === 0) { + result++; + current = -1; + } + } + + return result; +}; diff --git a/solutions/2872-maximum-number-of-k-divisible-components.js b/solutions/2872-maximum-number-of-k-divisible-components.js new file mode 100644 index 00000000..6ff1fdcd --- /dev/null +++ b/solutions/2872-maximum-number-of-k-divisible-components.js @@ -0,0 +1,51 @@ +/** + * 2872. Maximum Number of K-Divisible Components + * https://leetcode.com/problems/maximum-number-of-k-divisible-components/ + * Difficulty: Hard + * + * There is an undirected tree with n nodes labeled from 0 to n - 1. You are given the integer + * n and a 2D integer array edges of length n - 1, where edges[i] = [ai, bi] indicates that + * there is an edge between nodes ai and bi in the tree. + * + * You are also given a 0-indexed integer array values of length n, where values[i] is the value + * associated with the ith node, and an integer k. + * + * A valid split of the tree is obtained by removing any set of edges, possibly empty, from the + * tree such that the resulting components all have values that are divisible by k, where the + * value of a connected component is the sum of the values of its nodes. + * + * Return the maximum number of components in any valid split. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number[]} values + * @param {number} k + * @return {number} + */ +var maxKDivisibleComponents = function(n, edges, values, k) { + const graph = Array.from({ length: n }, () => []); + for (const [u, v] of edges) { + graph[u].push(v); + graph[v].push(u); + } + + let result = 0; + dfs(0, -1); + return result; + + function dfs(node, parent) { + let total = values[node]; + for (const neighbor of graph[node]) { + if (neighbor !== parent) { + total += dfs(neighbor, node); + } + } + if (total % k === 0) { + result++; + return 0; + } + return total; + } +}; diff --git a/solutions/2892-minimizing-array-after-replacing-pairs-with-their-product.js b/solutions/2892-minimizing-array-after-replacing-pairs-with-their-product.js new file mode 100644 index 00000000..ce0b9856 --- /dev/null +++ b/solutions/2892-minimizing-array-after-replacing-pairs-with-their-product.js @@ -0,0 +1,52 @@ +/** + * 2892. Minimizing Array After Replacing Pairs With Their Product + * https://leetcode.com/problems/minimizing-array-after-replacing-pairs-with-their-product/ + * Difficulty: Medium + * + * Given an integer array nums and an integer k, you can perform the following operation on the + * array any number of times: + * - Select two adjacent elements of the array like x and y, such that x * y <= k, and replace + * both of them with a single element with value x * y (e.g. in one operation the array + * [1, 2, 2, 3] with k = 5 can become [1, 4, 3] or [2, 2, 3], but can't become [1, 2, 6]). + * + * Return the minimum possible length of nums after any number of operations. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minArrayLength = function(nums, k) { + if (nums.some(num => num === 0)) { + return 1; + } + + const segments = []; + let currentProduct = 1; + let currentLength = 0; + + for (const num of nums) { + if (num > k) { + if (currentLength > 0) { + segments.push(currentLength); + currentProduct = 1; + currentLength = 0; + } + segments.push(1); + } else if (currentProduct * num <= k) { + currentProduct *= num; + currentLength++; + } else { + segments.push(currentLength); + currentProduct = num; + currentLength = 1; + } + } + + if (currentLength > 0) { + segments.push(currentLength); + } + + return segments.length; +}; diff --git a/solutions/2895-minimum-processing-time.js b/solutions/2895-minimum-processing-time.js new file mode 100644 index 00000000..c9ce8504 --- /dev/null +++ b/solutions/2895-minimum-processing-time.js @@ -0,0 +1,33 @@ +/** + * 2895. Minimum Processing Time + * https://leetcode.com/problems/minimum-processing-time/ + * Difficulty: Medium + * + * You have a certain number of processors, each having 4 cores. The number of tasks to be executed + * is four times the number of processors. Each task must be assigned to a unique core, and each + * core can only be used once. + * + * You are given an array processorTime representing the time each processor becomes available and + * an array tasks representing how long each task takes to complete. Return the minimum time needed + * to complete all tasks. + */ + +/** + * @param {number[]} processorTime + * @param {number[]} tasks + * @return {number} + */ +var minProcessingTime = function(processorTime, tasks) { + tasks.sort((a, b) => b - a); + processorTime.sort((a, b) => a - b); + let result = 0; + + for (let i = 0; i < processorTime.length; i++) { + for (let j = 0; j < 4; j++) { + const taskIndex = i * 4 + j; + result = Math.max(result, processorTime[i] + tasks[taskIndex]); + } + } + + return result; +}; diff --git a/solutions/2897-apply-operations-on-array-to-maximize-sum-of-squares.js b/solutions/2897-apply-operations-on-array-to-maximize-sum-of-squares.js new file mode 100644 index 00000000..eab93b10 --- /dev/null +++ b/solutions/2897-apply-operations-on-array-to-maximize-sum-of-squares.js @@ -0,0 +1,48 @@ +/** + * 2897. Apply Operations on Array to Maximize Sum of Squares + * https://leetcode.com/problems/apply-operations-on-array-to-maximize-sum-of-squares/ + * Difficulty: Hard + * + * You are given a 0-indexed integer array nums and a positive integer k. + * + * You can do the following operation on the array any number of times: + * - Choose any two distinct indices i and j and simultaneously update the values of nums[i] + * to (nums[i] AND nums[j]) and nums[j] to (nums[i] OR nums[j]). Here, OR denotes the bitwise + * OR operation, and AND denotes the bitwise AND operation. + * + * You have to choose k elements from the final array and calculate the sum of their squares. + * + * Return the maximum sum of squares you can achieve. + * + * Since the answer can be very large, return it modulo 109 + 7. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var maxSum = function(nums, k) { + const MOD = 1e9 + 7; + const bitCounts = new Array(30).fill(0); + + for (const num of nums) { + for (let i = 0; i < 30; i++) { + if (num & (1 << i)) bitCounts[i]++; + } + } + + let result = 0; + for (let i = 0; i < k; i++) { + let current = 0; + for (let j = 29; j >= 0; j--) { + if (bitCounts[j] > 0) { + current |= (1 << j); + bitCounts[j]--; + } + } + result = (result + Number((BigInt(current) * BigInt(current)) % BigInt(MOD))) % MOD; + } + + return result; +}; diff --git a/solutions/2898-maximum-linear-stock-score.js b/solutions/2898-maximum-linear-stock-score.js new file mode 100644 index 00000000..72c44a7d --- /dev/null +++ b/solutions/2898-maximum-linear-stock-score.js @@ -0,0 +1,38 @@ +/** + * 2898. Maximum Linear Stock Score + * https://leetcode.com/problems/maximum-linear-stock-score/ + * Difficulty: Medium + * + * Given a 1-indexed integer array prices, where prices[i] is the price of a particular stock + * on the ith day, your task is to select some of the elements of prices such that your + * selection is linear. + * + * A selection indexes, where indexes is a 1-indexed integer array of length k which is a + * subsequence of the array [1, 2, ..., n], is linear if: + * - For every 1 < j <= k, + * prices[indexes[j]] - prices[indexes[j - 1]] == indexes[j] - indexes[j - 1]. + * + * A subsequence is an array that can be derived from another array by deleting some or no + * elements without changing the order of the remaining elements. + * + * The score of a selection indexes, is equal to the sum of the following array: + * [prices[indexes[1]], prices[indexes[2]], ..., prices[indexes[k]]. + * + * Return the maximum score that a linear selection can have. + */ + +/** + * @param {number[]} prices + * @return {number} + */ +var maxScore = function(prices) { + const values = prices.map((price, index) => price - index); + const map = new Map(); + + for (let i = 0; i < prices.length; i++) { + const value = values[i]; + map.set(value, (map.get(value) || 0) + prices[i]); + } + + return Math.max(...map.values()); +}; diff --git a/solutions/2899-last-visited-integers.js b/solutions/2899-last-visited-integers.js new file mode 100644 index 00000000..0adcb661 --- /dev/null +++ b/solutions/2899-last-visited-integers.js @@ -0,0 +1,41 @@ +/** + * 2899. Last Visited Integers + * https://leetcode.com/problems/last-visited-integers/ + * Difficulty: Easy + * + * Given an integer array nums where nums[i] is either a positive integer or -1. We need to find + * for each -1 the respective positive integer, which we call the last visited integer. + * + * To achieve this goal, let's define two empty arrays: seen and ans. + * + * Start iterating from the beginning of the array nums. + * - If a positive integer is encountered, prepend it to the front of seen. + * - If -1 is encountered, let k be the number of consecutive -1s seen so far (including the + * current -1), + * - If k is less than or equal to the length of seen, append the k-th element of seen to ans. + * - If k is strictly greater than the length of seen, append -1 to ans. + * + * Return the array ans. + */ + +/** + * @param {number[]} nums + * @return {number[]} + */ +var lastVisitedIntegers = function(nums) { + const seen = []; + const result = []; + let consecutiveNegatives = 0; + + for (const num of nums) { + if (num > 0) { + seen.unshift(num); + consecutiveNegatives = 0; + } else { + consecutiveNegatives++; + result.push(consecutiveNegatives <= seen.length ? seen[consecutiveNegatives - 1] : -1); + } + } + + return result; +}; diff --git a/solutions/2903-find-indices-with-index-and-value-difference-i.js b/solutions/2903-find-indices-with-index-and-value-difference-i.js new file mode 100644 index 00000000..2ef70aeb --- /dev/null +++ b/solutions/2903-find-indices-with-index-and-value-difference-i.js @@ -0,0 +1,36 @@ +/** + * 2903. Find Indices With Index and Value Difference I + * https://leetcode.com/problems/find-indices-with-index-and-value-difference-i/ + * Difficulty: Easy + * + * You are given a 0-indexed integer array nums having length n, an integer indexDifference, + * and an integer valueDifference. + * + * Your task is to find two indices i and j, both in the range [0, n - 1], that satisfy the + * following conditions: + * - abs(i - j) >= indexDifference, and + * - abs(nums[i] - nums[j]) >= valueDifference + * + * Return an integer array answer, where answer = [i, j] if there are two such indices, and + * answer = [-1, -1] otherwise. If there are multiple choices for the two indices, return + * any of them. + * + * Note: i and j may be equal. + */ + +/** + * @param {number[]} nums + * @param {number} indexDifference + * @param {number} valueDifference + * @return {number[]} + */ +var findIndices = function(nums, indexDifference, valueDifference) { + for (let i = 0; i < nums.length; i++) { + for (let j = i; j < nums.length; j++) { + if (Math.abs(i - j) >= indexDifference && Math.abs(nums[i] - nums[j]) >= valueDifference) { + return [i, j]; + } + } + } + return [-1, -1]; +}; diff --git a/solutions/2904-shortest-and-lexicographically-smallest-beautiful-string.js b/solutions/2904-shortest-and-lexicographically-smallest-beautiful-string.js new file mode 100644 index 00000000..d328f151 --- /dev/null +++ b/solutions/2904-shortest-and-lexicographically-smallest-beautiful-string.js @@ -0,0 +1,48 @@ +/** + * 2904. Shortest and Lexicographically Smallest Beautiful String + * https://leetcode.com/problems/shortest-and-lexicographically-smallest-beautiful-string/ + * Difficulty: Medium + * + * You are given a binary string s and a positive integer k. + * + * A substring of s is beautiful if the number of 1's in it is exactly k. + * + * Let len be the length of the shortest beautiful substring. + * + * Return the lexicographically smallest beautiful substring of string s with length equal to + * len. If s doesn't contain a beautiful substring, return an empty string. + * + * A string a is lexicographically larger than a string b (of the same length) if in the first + * position where a and b differ, a has a character strictly larger than the corresponding + * character in b. + * - For example, "abcd" is lexicographically larger than "abcc" because the first position they + * differ is at the fourth character, and d is greater than c. + */ + +/** + * @param {string} s + * @param {number} k + * @return {string} + */ +var shortestBeautifulSubstring = function(s, k) { + let minLength = Infinity; + let result = ''; + + for (let start = 0; start < s.length; start++) { + let onesCount = 0; + for (let end = start; end < s.length; end++) { + if (s[end] === '1') onesCount++; + if (onesCount === k) { + const currentLength = end - start + 1; + const currentSubstring = s.slice(start, end + 1); + if (currentLength < minLength + || (currentLength === minLength && currentSubstring < result)) { + minLength = currentLength; + result = currentSubstring; + } + } + } + } + + return result; +}; diff --git a/solutions/2907-maximum-profitable-triplets-with-increasing-prices-i.js b/solutions/2907-maximum-profitable-triplets-with-increasing-prices-i.js new file mode 100644 index 00000000..387785c4 --- /dev/null +++ b/solutions/2907-maximum-profitable-triplets-with-increasing-prices-i.js @@ -0,0 +1,55 @@ +/** + * 2907. Maximum Profitable Triplets With Increasing Prices I + * https://leetcode.com/problems/maximum-profitable-triplets-with-increasing-prices-i/ + * Difficulty: Medium + * + * Given the 0-indexed arrays prices and profits of length n. There are n items in an store + * where the ith item has a price of prices[i] and a profit of profits[i]. + * + * We have to pick three items with the following condition: + * - prices[i] < prices[j] < prices[k] where i < j < k. + * + * If we pick items with indices i, j and k satisfying the above condition, the profit + * would be profits[i] + profits[j] + profits[k]. + * + * Return the maximum profit we can get, and -1 if it's not possible to pick three items + * with the given condition. + */ + +/** + * @param {number[]} prices + * @param {number[]} profits + * @return {number} + */ +var maxProfit = function(prices, profits) { + const n = prices.length; + let result = -1; + + for (let j = 1; j < n - 1; j++) { + let maxLeftProfit = 0; + let maxRightProfit = 0; + let hasLeft = false; + let hasRight = false; + + for (let i = 0; i < j; i++) { + if (prices[i] < prices[j]) { + maxLeftProfit = Math.max(maxLeftProfit, profits[i]); + hasLeft = true; + } + } + + for (let k = j + 1; k < n; k++) { + if (prices[j] < prices[k]) { + maxRightProfit = Math.max(maxRightProfit, profits[k]); + hasRight = true; + } + } + + if (hasLeft && hasRight) { + const tripletProfit = maxLeftProfit + profits[j] + maxRightProfit; + result = Math.max(result, tripletProfit); + } + } + + return result; +}; diff --git a/solutions/2908-minimum-sum-of-mountain-triplets-i.js b/solutions/2908-minimum-sum-of-mountain-triplets-i.js new file mode 100644 index 00000000..31f04c6a --- /dev/null +++ b/solutions/2908-minimum-sum-of-mountain-triplets-i.js @@ -0,0 +1,34 @@ +/** + * 2908. Minimum Sum of Mountain Triplets I + * https://leetcode.com/problems/minimum-sum-of-mountain-triplets-i/ + * Difficulty: Easy + * + * You are given a 0-indexed array nums of integers. + * + * A triplet of indices (i, j, k) is a mountain if: + * - i < j < k + * - nums[i] < nums[j] and nums[k] < nums[j] + * + * Return the minimum possible sum of a mountain triplet of nums. If no such triplet exists, + * return -1. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumSum = function(nums) { + let minSum = Infinity; + + for (let i = 0; i < nums.length - 2; i++) { + for (let j = i + 1; j < nums.length - 1; j++) { + for (let k = j + 1; k < nums.length; k++) { + if (nums[i] < nums[j] && nums[k] < nums[j]) { + minSum = Math.min(minSum, nums[i] + nums[j] + nums[k]); + } + } + } + } + + return minSum === Infinity ? -1 : minSum; +}; diff --git a/solutions/2909-minimum-sum-of-mountain-triplets-ii.js b/solutions/2909-minimum-sum-of-mountain-triplets-ii.js new file mode 100644 index 00000000..21e15bd7 --- /dev/null +++ b/solutions/2909-minimum-sum-of-mountain-triplets-ii.js @@ -0,0 +1,43 @@ +/** + * 2909. Minimum Sum of Mountain Triplets II + * https://leetcode.com/problems/minimum-sum-of-mountain-triplets-ii/ + * Difficulty: Medium + * + * You are given a 0-indexed array nums of integers. + * + * A triplet of indices (i, j, k) is a mountain if: + * - i < j < k + * - nums[i] < nums[j] and nums[k] < nums[j] + * + * Return the minimum possible sum of a mountain triplet of nums. If no such triplet + * exists, return -1. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumSum = function(nums) { + const n = nums.length; + const leftMin = new Array(n).fill(Infinity); + const rightMin = new Array(n).fill(Infinity); + + leftMin[0] = nums[0]; + for (let i = 1; i < n; i++) { + leftMin[i] = Math.min(leftMin[i - 1], nums[i]); + } + + rightMin[n - 1] = nums[n - 1]; + for (let i = n - 2; i >= 0; i--) { + rightMin[i] = Math.min(rightMin[i + 1], nums[i]); + } + + let minSum = Infinity; + for (let j = 1; j < n - 1; j++) { + if (nums[j] > leftMin[j - 1] && nums[j] > rightMin[j + 1]) { + minSum = Math.min(minSum, leftMin[j - 1] + nums[j] + rightMin[j + 1]); + } + } + + return minSum === Infinity ? -1 : minSum; +}; diff --git a/solutions/2912-number-of-ways-to-reach-destination-in-the-grid.js b/solutions/2912-number-of-ways-to-reach-destination-in-the-grid.js new file mode 100644 index 00000000..030dea47 --- /dev/null +++ b/solutions/2912-number-of-ways-to-reach-destination-in-the-grid.js @@ -0,0 +1,56 @@ +/** + * 2912. Number of Ways to Reach Destination in the Grid + * https://leetcode.com/problems/number-of-ways-to-reach-destination-in-the-grid/ + * Difficulty: Hard + * + * You are given two integers n and m which represent the size of a 1-indexed grid. You are + * also given an integer k, a 1-indexed integer array source and a 1-indexed integer array + * dest, where source and dest are in the form [x, y] representing a cell on the given grid. + * + * You can move through the grid in the following way: + * - You can go from cell [x1, y1] to cell [x2, y2] if either x1 == x2 or y1 == y2. + * - Note that you can't move to the cell you are already in e.g. x1 == x2 and y1 == y2. + * + * Return the number of ways you can reach dest from source by moving through the grid exactly + * k times. + * + * Since the answer may be very large, return it modulo 109 + 7. + */ + +/** + * @param {number} n + * @param {number} m + * @param {number} k + * @param {number[]} source + * @param {number[]} dest + * @return {number} + */ +var numberOfWays = function(n, m, k, source, dest) { + const MOD = 1e9 + 7; + const dp = new Array(k + 1).fill().map(() => new Array(4).fill(0)); + + if (source[0] === dest[0] && source[1] === dest[1]) { + dp[0][0] = 1; + } else if (source[0] === dest[0]) { + dp[0][1] = 1; + } else if (source[1] === dest[1]) { + dp[0][2] = 1; + } else { + dp[0][3] = 1; + } + + for (let i = 1; i <= k; i++) { + dp[i][0] = (dp[i - 1][1] + dp[i - 1][2]) % MOD; + dp[i][1] = (BigInt(dp[i - 1][0]) * BigInt(m - 1) + BigInt(dp[i - 1][1]) + * BigInt(m - 2) + BigInt(dp[i - 1][3])) % BigInt(MOD); + dp[i][2] = (BigInt(dp[i - 1][0]) * BigInt(n - 1) + BigInt(dp[i - 1][2]) + * BigInt(n - 2) + BigInt(dp[i - 1][3])) % BigInt(MOD); + dp[i][3] = (BigInt(dp[i - 1][1]) * BigInt(n - 1) + BigInt(dp[i - 1][2]) + * BigInt(m - 1) + BigInt(dp[i - 1][3]) * BigInt(m + n - 4)) % BigInt(MOD); + dp[i][1] = Number(dp[i][1]); + dp[i][2] = Number(dp[i][2]); + dp[i][3] = Number(dp[i][3]); + } + + return dp[k][0]; +}; diff --git a/solutions/2913-subarrays-distinct-element-sum-of-squares-i.js b/solutions/2913-subarrays-distinct-element-sum-of-squares-i.js new file mode 100644 index 00000000..ebb8fdfb --- /dev/null +++ b/solutions/2913-subarrays-distinct-element-sum-of-squares-i.js @@ -0,0 +1,34 @@ +/** + * 2913. Subarrays Distinct Element Sum of Squares I + * https://leetcode.com/problems/subarrays-distinct-element-sum-of-squares-i/ + * Difficulty: Easy + * + * You are given a 0-indexed integer array nums. + * + * The distinct count of a subarray of nums is defined as: + * - Let nums[i..j] be a subarray of nums consisting of all the indices from i to j such + * that 0 <= i <= j < nums.length. Then the number of distinct values in nums[i..j] is + * called the distinct count of nums[i..j]. + * + * Return the sum of the squares of distinct counts of all subarrays of nums. + * + * A subarray is a contiguous non-empty sequence of elements within an array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var sumCounts = function(nums) { + let result = 0; + + for (let i = 0; i < nums.length; i++) { + const set = new Set(); + for (let j = i; j < nums.length; j++) { + set.add(nums[j]); + result += set.size * set.size; + } + } + + return result; +}; diff --git a/solutions/2914-minimum-number-of-changes-to-make-binary-string-beautiful.js b/solutions/2914-minimum-number-of-changes-to-make-binary-string-beautiful.js new file mode 100644 index 00000000..2c50bf70 --- /dev/null +++ b/solutions/2914-minimum-number-of-changes-to-make-binary-string-beautiful.js @@ -0,0 +1,29 @@ +/** + * 2914. Minimum Number of Changes to Make Binary String Beautiful + * https://leetcode.com/problems/minimum-number-of-changes-to-make-binary-string-beautiful/ + * Difficulty: Medium + * + * You are given a 0-indexed binary string s having an even length. + * + * A string is beautiful if it's possible to partition it into one or more substrings such that: + * - Each substring has an even length. + * - Each substring contains only 1's or only 0's. + * + * You can change any character in s to 0 or 1. + * + * Return the minimum number of changes required to make the string s beautiful. + */ + +/** + * @param {string} s + * @return {number} + */ +var minChanges = function(s) { + let result = 0; + + for (let i = 0; i < s.length; i += 2) { + if (s[i] !== s[i + 1]) result++; + } + + return result; +}; diff --git a/solutions/2917-find-the-k-or-of-an-array.js b/solutions/2917-find-the-k-or-of-an-array.js new file mode 100644 index 00000000..d37773ad --- /dev/null +++ b/solutions/2917-find-the-k-or-of-an-array.js @@ -0,0 +1,30 @@ +/** + * 2917. Find the K-or of an Array + * https://leetcode.com/problems/find-the-k-or-of-an-array/ + * Difficulty: Easy + * + * You are given an integer array nums, and an integer k. Let's introduce K-or operation + * by extending the standard bitwise OR. In K-or, a bit position in the result is set to + * 1 if at least k numbers in nums have a 1 in that position. + * + * Return the K-or of nums. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var findKOr = function(nums, k) { + let result = 0; + + for (let bit = 0; bit < 31; bit++) { + let count = 0; + for (const num of nums) { + if (num & (1 << bit)) count++; + } + if (count >= k) result |= (1 << bit); + } + + return result; +}; diff --git a/solutions/2921-maximum-profitable-triplets-with-increasing-prices-ii.js b/solutions/2921-maximum-profitable-triplets-with-increasing-prices-ii.js new file mode 100644 index 00000000..061d9b36 --- /dev/null +++ b/solutions/2921-maximum-profitable-triplets-with-increasing-prices-ii.js @@ -0,0 +1,63 @@ +/** + * 2921. Maximum Profitable Triplets With Increasing Prices II + * https://leetcode.com/problems/maximum-profitable-triplets-with-increasing-prices-ii/ + * Difficulty: Hard + * + * Given the 0-indexed arrays prices and profits of length n. There are n items in an store + * where the ith item has a price of prices[i] and a profit of profits[i]. + * + * We have to pick three items with the following condition: + * - prices[i] < prices[j] < prices[k] where i < j < k. + * + * If we pick items with indices i, j and k satisfying the above condition, the profit would + * be profits[i] + profits[j] + profits[k]. + * + * Return the maximum profit we can get, and -1 if it's not possible to pick three items with + * the given condition. + */ + +/** + * @param {number[]} prices + * @param {number[]} profits + * @return {number} + */ +var maxProfit = function(prices, profits) { + const bit1 = new Array(5001).fill(0); + const bit2 = new Array(5001).fill(0); + let result = -1; + + for (let i = 0; i < prices.length; i++) { + const price = prices[i]; + const profit = profits[i]; + const maxLeft = query(bit1, price - 1); + const maxPair = query(bit2, price - 1); + + if (maxPair > 0) { + result = Math.max(result, maxPair + profit); + } + + update(bit1, price, profit); + + if (maxLeft > 0) { + update(bit2, price, profit + maxLeft); + } + } + + return result; + + function query(bit, price) { + let maxValue = 0; + while (price > 0) { + maxValue = Math.max(maxValue, bit[price]); + price &= price - 1; + } + return maxValue; + } + + function update(bit, price, value) { + while (price < 5001) { + bit[price] = Math.max(bit[price], value); + price += price & (-price); + } + } +}; diff --git a/solutions/2923-find-champion-i.js b/solutions/2923-find-champion-i.js new file mode 100644 index 00000000..c641cd07 --- /dev/null +++ b/solutions/2923-find-champion-i.js @@ -0,0 +1,37 @@ +/** + * 2923. Find Champion I + * https://leetcode.com/problems/find-champion-i/ + * Difficulty: Easy + * + * There are n teams numbered from 0 to n - 1 in a tournament. + * + * Given a 0-indexed 2D boolean matrix grid of size n * n. For all i, j that 0 <= i, j <= n - 1 + * and i != j team i is stronger than team j if grid[i][j] == 1, otherwise, team j is stronger + * than team i. + * + * Team a will be the champion of the tournament if there is no team b that is stronger than + * team a. + * + * Return the team that will be the champion of the tournament. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var findChampion = function(grid) { + const n = grid.length; + + for (let i = 0; i < n; i++) { + let isChampion = true; + for (let j = 0; j < n; j++) { + if (i !== j && grid[j][i] === 1) { + isChampion = false; + break; + } + } + if (isChampion) return i; + } + + return -1; +}; diff --git a/solutions/2924-find-champion-ii.js b/solutions/2924-find-champion-ii.js new file mode 100644 index 00000000..a475f55d --- /dev/null +++ b/solutions/2924-find-champion-ii.js @@ -0,0 +1,47 @@ +/** + * 2924. Find Champion II + * https://leetcode.com/problems/find-champion-ii/ + * Difficulty: Medium + * + * There are n teams numbered from 0 to n - 1 in a tournament; each team is also a node in a DAG. + * + * You are given the integer n and a 0-indexed 2D integer array edges of length m representing the + * DAG, where edges[i] = [ui, vi] indicates that there is a directed edge from team ui to team vi + * in the graph. + * + * A directed edge from a to b in the graph means that team a is stronger than team b and team b + * is weaker than team a. + * + * Team a will be the champion of the tournament if there is no team b that is stronger than team a. + * + * Return the team that will be the champion of the tournament if there is a unique champion, + * otherwise, return -1. + * + * Notes: + * - A cycle is a series of nodes a1, a2, ..., an, an+1 such that node a1 is the same node as node + * an+1, the nodes a1, a2, ..., an are distinct, and there is a directed edge from the node ai + * to node ai+1 for every i in the range [1, n]. + * - A DAG is a directed graph that does not have any cycle. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @return {number} + */ +var findChampion = function(n, edges) { + const inDegree = new Array(n).fill(0); + + for (const [, v] of edges) { + inDegree[v]++; + } + let champion = -1; + for (let i = 0; i < n; i++) { + if (inDegree[i] === 0) { + if (champion !== -1) return -1; + champion = i; + } + } + + return champion; +}; diff --git a/solutions/2925-maximum-score-after-applying-operations-on-a-tree.js b/solutions/2925-maximum-score-after-applying-operations-on-a-tree.js new file mode 100644 index 00000000..55cb4532 --- /dev/null +++ b/solutions/2925-maximum-score-after-applying-operations-on-a-tree.js @@ -0,0 +1,58 @@ +/** + * 2925. Maximum Score After Applying Operations on a Tree + * https://leetcode.com/problems/maximum-score-after-applying-operations-on-a-tree/ + * Difficulty: Medium + * + * There is an undirected tree with n nodes labeled from 0 to n - 1, and rooted at node 0. You are + * given a 2D integer array edges of length n - 1, where edges[i] = [ai, bi] indicates that there + * is an edge between nodes ai and bi in the tree. + * + * You are also given a 0-indexed integer array values of length n, where values[i] is the value + * associated with the ith node. + * + * You start with a score of 0. In one operation, you can: + * - Pick any node i. + * - Add values[i] to your score. + * - Set values[i] to 0. + * + * A tree is healthy if the sum of values on the path from the root to any leaf node is different + * than zero. + * + * Return the maximum score you can obtain after performing these operations on the tree any + * number of times so that it remains healthy. + */ + +/** + * @param {number[][]} edges + * @param {number[]} values + * @return {number} + */ +var maximumScoreAfterOperations = function(edges, values) { + const n = values.length; + const graph = new Array(n).fill().map(() => []); + + for (const [u, v] of edges) { + graph[u].push(v); + graph[v].push(u); + } + + const totalSum = values.reduce((sum, val) => sum + val, 0); + const minToKeep = dfs(0, -1); + + return totalSum - minToKeep; + + function dfs(node, parent) { + const children = graph[node].filter(child => child !== parent); + + if (children.length === 0) { + return values[node]; + } + + let childrenSum = 0; + for (const child of children) { + childrenSum += dfs(child, node); + } + + return Math.min(values[node], childrenSum); + } +}; diff --git a/solutions/2927-distribute-candies-among-children-iii.js b/solutions/2927-distribute-candies-among-children-iii.js new file mode 100644 index 00000000..984791b0 --- /dev/null +++ b/solutions/2927-distribute-candies-among-children-iii.js @@ -0,0 +1,28 @@ +/** + * 2927. Distribute Candies Among Children III + * https://leetcode.com/problems/distribute-candies-among-children-iii/ + * Difficulty: Hard + * + * You are given two positive integers n and limit. + * + * Return the total number of ways to distribute n candies among 3 children such that no child + * gets more than limit candies. + */ + +/** + * @param {number} n + * @param {number} limit + * @return {number} + */ +var distributeCandies = function(n, limit) { + if (n > 3 * limit) return 0; + + const overLimit = limit + 1; + return countWays(n) - 3 * countWays(n - overLimit) + + 3 * countWays(n - 2 * overLimit) - countWays(n - 3 * overLimit); + + function countWays(candies) { + if (candies < 0) return 0; + return Math.floor((candies + 2) * (candies + 1) / 2); + } +}; diff --git a/solutions/2928-distribute-candies-among-children-i.js b/solutions/2928-distribute-candies-among-children-i.js new file mode 100644 index 00000000..fe0c287d --- /dev/null +++ b/solutions/2928-distribute-candies-among-children-i.js @@ -0,0 +1,28 @@ +/** + * 2928. Distribute Candies Among Children I + * https://leetcode.com/problems/distribute-candies-among-children-i/ + * Difficulty: Easy + * + * You are given two positive integers n and limit. + * + * Return the total number of ways to distribute n candies among 3 children such that no child + * gets more than limit candies. + */ + +/** + * @param {number} n + * @param {number} limit + * @return {number} + */ +var distributeCandies = function(n, limit) { + let result = 0; + + for (let i = 0; i <= Math.min(n, limit); i++) { + for (let j = 0; j <= Math.min(n - i, limit); j++) { + const k = n - i - j; + if (k >= 0 && k <= limit) result++; + } + } + + return result; +}; diff --git a/solutions/2929-distribute-candies-among-children-ii.js b/solutions/2929-distribute-candies-among-children-ii.js new file mode 100644 index 00000000..40e830ec --- /dev/null +++ b/solutions/2929-distribute-candies-among-children-ii.js @@ -0,0 +1,30 @@ +/** + * 2929. Distribute Candies Among Children II + * https://leetcode.com/problems/distribute-candies-among-children-ii/ + * Difficulty: Medium + * + * You are given two positive integers n and limit. + * + * Return the total number of ways to distribute n candies among 3 children such that no child + * gets more than limit candies. + */ + +/** + * @param {number} n + * @param {number} limit + * @return {number} + */ +var distributeCandies = function(n, limit) { + const minCandies = Math.max(0, n - 2 * limit); + const maxCandies = Math.min(n, limit); + let result = 0; + + for (let i = minCandies; i <= maxCandies; i++) { + const remaining = n - i; + const minSecond = Math.max(0, remaining - limit); + const maxSecond = Math.min(remaining, limit); + result += maxSecond - minSecond + 1; + } + + return result; +}; diff --git a/solutions/2932-maximum-strong-pair-xor-i.js b/solutions/2932-maximum-strong-pair-xor-i.js new file mode 100644 index 00000000..67477b17 --- /dev/null +++ b/solutions/2932-maximum-strong-pair-xor-i.js @@ -0,0 +1,37 @@ +/** + * 2932. Maximum Strong Pair XOR I + * https://leetcode.com/problems/maximum-strong-pair-xor-i/ + * Difficulty: Easy + * + * You are given a 0-indexed integer array nums. A pair of integers x and y is called a strong pair + * if it satisfies the condition: + * - |x - y| <= min(x, y) + * + * You need to select two integers from nums such that they form a strong pair and their bitwise + * XOR is the maximum among all strong pairs in the array. + * + * Return the maximum XOR value out of all possible strong pairs in the array nums. + * + * Note that you can pick the same integer twice to form a pair. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maximumStrongPairXor = function(nums) { + let result = 0; + nums.sort((a, b) => a - b); + + for (let i = 0; i < nums.length; i++) { + for (let j = i; j < nums.length; j++) { + if (nums[j] - nums[i] <= Math.min(nums[i], nums[j])) { + result = Math.max(result, nums[i] ^ nums[j]); + } else { + break; + } + } + } + + return result; +}; diff --git a/solutions/2933-high-access-employees.js b/solutions/2933-high-access-employees.js new file mode 100644 index 00000000..98c9a73f --- /dev/null +++ b/solutions/2933-high-access-employees.js @@ -0,0 +1,54 @@ +/** + * 2933. High-Access Employees + * https://leetcode.com/problems/high-access-employees/ + * Difficulty: Medium + * + * You are given a 2D 0-indexed array of strings, accessTimes, with size n. For each i where + * 0 <= i <= n - 1, accessTimes[i][0] represents the name of an employee, and accessTimes[i][1] + * represents the access time of that employee. All entries in accessTimes are within the same day. + * + * The access time is represented as four digits using a 24-hour time format, for example, "0800" + * or "2250". + * + * An employee is said to be high-access if he has accessed the system three or more times within + * a one-hour period. + * + * Times with exactly one hour of difference are not considered part of the same one-hour period. + * For example, "0815" and "0915" are not part of the same one-hour period. + * + * Access times at the start and end of the day are not counted within the same one-hour period. + * For example, "0005" and "2350" are not part of the same one-hour period. + * + * Return a list that contains the names of high-access employees with any order you want. + */ + +/** + * @param {string[][]} accessTimes + * @return {string[]} + */ +var findHighAccessEmployees = function(accessTimes) { + const employeeAccess = new Map(); + + for (const [name, time] of accessTimes) { + const minutes = parseInt(time.slice(0, 2)) * 60 + parseInt(time.slice(2)); + if (!employeeAccess.has(name)) { + employeeAccess.set(name, []); + } + employeeAccess.get(name).push(minutes); + } + + const result = []; + for (const [name, times] of employeeAccess) { + times.sort((a, b) => a - b); + if (times.length >= 3) { + for (let i = 0; i <= times.length - 3; i++) { + if (times[i + 2] - times[i] < 60) { + result.push(name); + break; + } + } + } + } + + return result; +}; diff --git a/solutions/2934-minimum-operations-to-maximize-last-elements-in-arrays.js b/solutions/2934-minimum-operations-to-maximize-last-elements-in-arrays.js new file mode 100644 index 00000000..c2803a60 --- /dev/null +++ b/solutions/2934-minimum-operations-to-maximize-last-elements-in-arrays.js @@ -0,0 +1,57 @@ +/** + * 2934. Minimum Operations to Maximize Last Elements in Arrays + * https://leetcode.com/problems/minimum-operations-to-maximize-last-elements-in-arrays/ + * Difficulty: Medium + * + * You are given two 0-indexed integer arrays, nums1 and nums2, both having length n. + * + * You are allowed to perform a series of operations (possibly none). + * + * In an operation, you select an index i in the range [0, n - 1] and swap the values of + * nums1[i] and nums2[i]. + * + * Your task is to find the minimum number of operations required to satisfy the following + * conditions: + * - nums1[n - 1] is equal to the maximum value among all elements of nums1, i.e., + * nums1[n - 1] = max(nums1[0], nums1[1], ..., nums1[n - 1]). + * - nums2[n - 1] is equal to the maximum value among all elements of nums2, i.e., + * nums2[n - 1] = max(nums2[0], nums2[1], ..., nums2[n - 1]). + * + * Return an integer denoting the minimum number of operations needed to meet both conditions, + * or -1 if it is impossible to satisfy both conditions. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var minOperations = function(nums1, nums2) { + const n = nums1.length; + const last1 = nums1[n - 1]; + const last2 = nums2[n - 1]; + + let swapsNoChange = 0; + let swapsChange = 0; + + for (let i = 0; i < n - 1; i++) { + if (nums1[i] > last1 || nums2[i] > last2) { + if (nums2[i] > last1 || nums1[i] > last2) { + return -1; + } + swapsNoChange++; + } + if (nums1[i] > last2 || nums2[i] > last1) { + if (nums2[i] > last2 || nums1[i] > last1) { + return -1; + } + swapsChange++; + } + } + + if (last1 !== last2) { + swapsChange++; + } + + return Math.min(swapsNoChange, swapsChange); +}; diff --git a/solutions/2936-number-of-equal-numbers-blocks.js b/solutions/2936-number-of-equal-numbers-blocks.js new file mode 100644 index 00000000..c35e60e1 --- /dev/null +++ b/solutions/2936-number-of-equal-numbers-blocks.js @@ -0,0 +1,75 @@ +/** + * 2936. Number of Equal Numbers Blocks + * https://leetcode.com/problems/number-of-equal-numbers-blocks/ + * Difficulty: Medium + * + * You are given a 0-indexed array of integers, nums. The following property holds for nums: + * - All occurrences of a value are adjacent. In other words, if there are two indices i < j + * such that nums[i] == nums[j], then for every index k that i < k < j, nums[k] == nums[i]. + * + * Since nums is a very large array, you are given an instance of the class BigArray which has + * the following functions: + * - int at(long long index): Returns the value of nums[i]. + * - void size(): Returns nums.length. + * + * Let's partition the array into maximal blocks such that each block contains equal values. + * Return the number of these blocks. + * + * Note that if you want to test your solution using a custom test, behavior for tests with + * nums.length > 10 is undefined. + */ + +/** + * Definition for BigArray. + * class BigArray { + * @param {number[]} elements + * constructor(elements); + * + * @param {number} index + * @return {number} + * at(index); + * + * @return {number} + * size(); + * } + */ +/** + * @param {BigArray} nums + * @return {number} + */ +var countBlocks = function(nums) { + const n = nums.size(); + if (n === 0) return 0; + + let blocks = 1; + let currentIndex = 0; + + while (currentIndex < n - 1) { + const nextBlockStart = findNextBlockStart(nums, currentIndex, n); + if (nextBlockStart < n) { + blocks++; + currentIndex = nextBlockStart; + } else { + break; + } + } + + return blocks; + + function findNextBlockStart(nums, startIndex, n) { + const currentValue = nums.at(startIndex); + let left = startIndex + 1; + let right = n; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (nums.at(mid) === currentValue) { + left = mid + 1; + } else { + right = mid; + } + } + + return left; + } +}; diff --git a/solutions/2937-make-three-strings-equal.js b/solutions/2937-make-three-strings-equal.js new file mode 100644 index 00000000..c7dad334 --- /dev/null +++ b/solutions/2937-make-three-strings-equal.js @@ -0,0 +1,35 @@ +/** + * 2937. Make Three Strings Equal + * https://leetcode.com/problems/make-three-strings-equal/ + * Difficulty: Easy + * + * You are given three strings: s1, s2, and s3. In one operation you can choose one of these + * strings and delete its rightmost character. Note that you cannot completely empty a string. + * + * Return the minimum number of operations required to make the strings equal. If it is + * impossible to make them equal, return -1. + */ + +/** + * @param {string} s1 + * @param {string} s2 + * @param {string} s3 + * @return {number} + */ +var findMinimumOperations = function(s1, s2, s3) { + const minLength = Math.min(s1.length, s2.length, s3.length); + + let commonPrefixLength = 0; + for (let i = 0; i < minLength; i++) { + if (s1[i] !== s2[i] || s2[i] !== s3[i]) { + break; + } + commonPrefixLength++; + } + + if (commonPrefixLength === 0) { + return -1; + } + + return s1.length + s2.length + s3.length - 3 * commonPrefixLength; +}; diff --git a/solutions/2938-separate-black-and-white-balls.js b/solutions/2938-separate-black-and-white-balls.js new file mode 100644 index 00000000..cd8d022d --- /dev/null +++ b/solutions/2938-separate-black-and-white-balls.js @@ -0,0 +1,33 @@ +/** + * 2938. Separate Black and White Balls + * https://leetcode.com/problems/separate-black-and-white-balls/ + * Difficulty: Medium + * + * There are n balls on a table, each ball has a color black or white. + * + * You are given a 0-indexed binary string s of length n, where 1 and 0 represent black and white + * balls, respectively. + * + * In each step, you can choose two adjacent balls and swap them. + * + * Return the minimum number of steps to group all the black balls to the right and all the white + * balls to the left. + */ + +/** + * @param {string} s + * @return {number} + */ +var minimumSteps = function(s) { + let result = 0; + let whiteCount = 0; + + for (let i = 0; i < s.length; i++) { + if (s[i] === '0') { + result += i - whiteCount; + whiteCount++; + } + } + + return result; +}; diff --git a/solutions/2941-maximum-gcd-sum-of-a-subarray.js b/solutions/2941-maximum-gcd-sum-of-a-subarray.js new file mode 100644 index 00000000..abfacd26 --- /dev/null +++ b/solutions/2941-maximum-gcd-sum-of-a-subarray.js @@ -0,0 +1,57 @@ +/** + * 2941. Maximum GCD-Sum of a Subarray + * https://leetcode.com/problems/maximum-gcd-sum-of-a-subarray/ + * Difficulty: Hard + * + * You are given an array of integers nums and an integer k. + * + * The gcd-sum of an array a is calculated as follows: + * - Let s be the sum of all the elements of a. + * - Let g be the greatest common divisor of all the elements of a. + * - The gcd-sum of a is equal to s * g. + * + * Return the maximum gcd-sum of a subarray of nums with at least k elements. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var maxGcdSum = function(nums, k) { + const prefixSum = [0]; + let gcdPairs = []; + let result = 0; + + for (let i = 0; i < nums.length; i++) { + prefixSum.push(prefixSum[prefixSum.length - 1] + nums[i]); + + const newGcdPairs = []; + const candidates = [...gcdPairs, [i, nums[i]]]; + for (const [startIndex, currentGcd] of candidates) { + const newGcd = gcd(currentGcd, nums[i]); + if (newGcdPairs.length === 0 || newGcdPairs[newGcdPairs.length - 1][1] !== newGcd) { + newGcdPairs.push([startIndex, newGcd]); + } + } + + gcdPairs = newGcdPairs; + + for (const [startIndex, gcdValue] of gcdPairs) { + if (i - startIndex + 1 < k) break; + const subarraySum = prefixSum[prefixSum.length - 1] - prefixSum[startIndex]; + result = Math.max(result, subarraySum * gcdValue); + } + } + + return result; + + function gcd(a, b) { + while (b !== 0) { + const temp = b; + b = a % b; + a = temp; + } + return a; + } +}; diff --git a/solutions/2946-matrix-similarity-after-cyclic-shifts.js b/solutions/2946-matrix-similarity-after-cyclic-shifts.js new file mode 100644 index 00000000..4d93251f --- /dev/null +++ b/solutions/2946-matrix-similarity-after-cyclic-shifts.js @@ -0,0 +1,35 @@ +/** + * 2946. Matrix Similarity After Cyclic Shifts + * https://leetcode.com/problems/matrix-similarity-after-cyclic-shifts/ + * Difficulty: Easy + * + * You are given an m x n integer matrix mat and an integer k. The matrix rows are 0-indexed. + * + * The following proccess happens k times: + * - Even-indexed rows (0, 2, 4, ...) are cyclically shifted to the left. + * - Odd-indexed rows (1, 3, 5, ...) are cyclically shifted to the right. + * + * Return true if the final modified matrix after k steps is identical to the original matrix, + * and false otherwise. + */ + +/** + * @param {number[][]} mat + * @param {number} k + * @return {boolean} + */ +var areSimilar = function(mat, k) { + const m = mat.length; + const n = mat[0].length; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + const shift = i % 2 === 0 ? (j - k % n + n) % n : (j + k % n) % n; + if (mat[i][j] !== mat[i][shift]) { + return false; + } + } + } + + return true; +}; diff --git a/solutions/2947-count-beautiful-substrings-i.js b/solutions/2947-count-beautiful-substrings-i.js new file mode 100644 index 00000000..0972a990 --- /dev/null +++ b/solutions/2947-count-beautiful-substrings-i.js @@ -0,0 +1,51 @@ +/** + * 2947. Count Beautiful Substrings I + * https://leetcode.com/problems/count-beautiful-substrings-i/ + * Difficulty: Medium + * + * You are given a string s and a positive integer k. + * + * Let vowels and consonants be the number of vowels and consonants in a string. + * + * A string is beautiful if: + * - vowels == consonants. + * - (vowels * consonants) % k == 0, in other terms the multiplication of vowels and + * consonants is divisible by k. + * + * Return the number of non-empty beautiful substrings in the given string s. + * + * A substring is a contiguous sequence of characters in a string. + * + * Vowel letters in English are 'a', 'e', 'i', 'o', and 'u'. + * + * Consonant letters in English are every letter except vowels. + */ + +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +var beautifulSubstrings = function(s, k) { + const vowels = new Set(['a', 'e', 'i', 'o', 'u']); + let result = 0; + + for (let start = 0; start < s.length; start++) { + let vowelCount = 0; + let consonantCount = 0; + + for (let end = start; end < s.length; end++) { + if (vowels.has(s[end])) { + vowelCount++; + } else { + consonantCount++; + } + + if (vowelCount === consonantCount && (vowelCount * consonantCount) % k === 0) { + result++; + } + } + } + + return result; +}; diff --git a/solutions/2950-number-of-divisible-substrings.js b/solutions/2950-number-of-divisible-substrings.js new file mode 100644 index 00000000..62734820 --- /dev/null +++ b/solutions/2950-number-of-divisible-substrings.js @@ -0,0 +1,36 @@ +/** + * 2950. Number of Divisible Substrings + * https://leetcode.com/problems/number-of-divisible-substrings/ + * Difficulty: Medium + * + * Each character of the English alphabet has been mapped to a digit as shown below. + * + * A string is divisible if the sum of the mapped values of its characters is divisible + * by its length. + * + * Given a string s, return the number of divisible substrings of s. + * + * A substring is a contiguous non-empty sequence of characters within a string. + */ + +/** + * @param {string} word + * @return {number} + */ +var countDivisibleSubstrings = function(word) { + let result = 0; + + for (let i = 1; i < 10; i++) { + const prefixCount = new Map([[0, 1]]); + let prefixSum = 0; + + for (const char of word) { + const charValue = 9 - Math.floor((122 - char.charCodeAt(0)) / 3); + prefixSum += charValue - i; + result += prefixCount.get(prefixSum) || 0; + prefixCount.set(prefixSum, (prefixCount.get(prefixSum) || 0) + 1); + } + } + + return result; +}; diff --git a/solutions/2951-find-the-peaks.js b/solutions/2951-find-the-peaks.js new file mode 100644 index 00000000..45e40576 --- /dev/null +++ b/solutions/2951-find-the-peaks.js @@ -0,0 +1,30 @@ +/** + * 2951. Find the Peaks + * https://leetcode.com/problems/find-the-peaks/ + * Difficulty: Easy + * + * You are given a 0-indexed array mountain. Your task is to find all the peaks in the + * mountain array. + * + * Return an array that consists of indices of peaks in the given array in any order. + * + * Notes: + * - A peak is defined as an element that is strictly greater than its neighboring elements. + * - The first and last elements of the array are not a peak. + */ + +/** + * @param {number[]} mountain + * @return {number[]} + */ +var findPeaks = function(mountain) { + const result = []; + + for (let i = 1; i < mountain.length - 1; i++) { + if (mountain[i] > mountain[i - 1] && mountain[i] > mountain[i + 1]) { + result.push(i); + } + } + + return result; +}; diff --git a/solutions/2952-minimum-number-of-coins-to-be-added.js b/solutions/2952-minimum-number-of-coins-to-be-added.js new file mode 100644 index 00000000..8290c3f1 --- /dev/null +++ b/solutions/2952-minimum-number-of-coins-to-be-added.js @@ -0,0 +1,41 @@ +/** + * 2952. Minimum Number of Coins to be Added + * https://leetcode.com/problems/minimum-number-of-coins-to-be-added/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array coins, representing the values of the coins available, + * and an integer target. + * + * An integer x is obtainable if there exists a subsequence of coins that sums to x. + * + * Return the minimum number of coins of any value that need to be added to the array so that every + * integer in the range [1, target] is obtainable. + * + * A subsequence of an array is a new non-empty array that is formed from the original array by + * deleting some (possibly none) of the elements without disturbing the relative positions of the + * remaining elements. + */ + +/** + * @param {number[]} coins + * @param {number} target + * @return {number} + */ +var minimumAddedCoins = function(coins, target) { + coins.sort((a, b) => a - b); + let result = 0; + let currentMax = 0; + let index = 0; + + while (currentMax < target) { + if (index < coins.length && coins[index] <= currentMax + 1) { + currentMax += coins[index]; + index++; + } else { + currentMax += currentMax + 1; + result++; + } + } + + return result; +}; diff --git a/solutions/2955-number-of-same-end-substrings.js b/solutions/2955-number-of-same-end-substrings.js new file mode 100644 index 00000000..c61040ef --- /dev/null +++ b/solutions/2955-number-of-same-end-substrings.js @@ -0,0 +1,49 @@ +/** + * 2955. Number of Same-End Substrings + * https://leetcode.com/problems/number-of-same-end-substrings/ + * Difficulty: Medium + * + * You are given a 0-indexed string s, and a 2D array of integers queries, where + * queries[i] = [li, ri] indicates a substring of s starting from the index li and + * ending at the index ri (both inclusive), i.e. s[li..ri]. + * + * Return an array ans where ans[i] is the number of same-end substrings of queries[i]. + * + * A 0-indexed string t of length n is called same-end if it has the same character at + * both of its ends, i.e., t[0] == t[n - 1]. + * + * A substring is a contiguous non-empty sequence of characters within a string. + */ + +/** + * @param {string} s + * @param {number[][]} queries + * @return {number[]} + */ +var sameEndSubstringCount = function(s, queries) { + const n = s.length; + const prefixCounts = new Array(26).fill().map(() => new Array(n + 1).fill(0)); + + for (let i = 0; i < n; i++) { + const charIndex = s.charCodeAt(i) - 97; + for (let j = 0; j < 26; j++) { + prefixCounts[j][i + 1] = prefixCounts[j][i]; + } + prefixCounts[charIndex][i + 1]++; + } + + const result = []; + + for (const [left, right] of queries) { + let count = 0; + + for (let charIndex = 0; charIndex < 26; charIndex++) { + const charCount = prefixCounts[charIndex][right + 1] - prefixCounts[charIndex][left]; + count += Math.floor(charCount * (charCount + 1) / 2); + } + + result.push(count); + } + + return result; +}; diff --git a/solutions/2956-find-common-elements-between-two-arrays.js b/solutions/2956-find-common-elements-between-two-arrays.js new file mode 100644 index 00000000..8189c0e2 --- /dev/null +++ b/solutions/2956-find-common-elements-between-two-arrays.js @@ -0,0 +1,39 @@ +/** + * 2956. Find Common Elements Between Two Arrays + * https://leetcode.com/problems/find-common-elements-between-two-arrays/ + * Difficulty: Easy + * + * You are given two integer arrays nums1 and nums2 of sizes n and m, respectively. + * Calculate the following values: + * - answer1 : the number of indices i such that nums1[i] exists in nums2. + * - answer2 : the number of indices i such that nums2[i] exists in nums1. + * + * Return [answer1,answer2]. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number[]} + */ +var findIntersectionValues = function(nums1, nums2) { + const set1 = new Set(nums1); + const set2 = new Set(nums2); + + let count1 = 0; + let count2 = 0; + + for (const num of nums1) { + if (set2.has(num)) { + count1++; + } + } + + for (const num of nums2) { + if (set1.has(num)) { + count2++; + } + } + + return [count1, count2]; +}; diff --git a/solutions/2957-remove-adjacent-almost-equal-characters.js b/solutions/2957-remove-adjacent-almost-equal-characters.js new file mode 100644 index 00000000..c62070dc --- /dev/null +++ b/solutions/2957-remove-adjacent-almost-equal-characters.js @@ -0,0 +1,32 @@ +/** + * 2957. Remove Adjacent Almost-Equal Characters + * https://leetcode.com/problems/remove-adjacent-almost-equal-characters/ + * Difficulty: Medium + * + * You are given a 0-indexed string word. + * + * In one operation, you can pick any index i of word and change word[i] to any lowercase + * English letter. + * + * Return the minimum number of operations needed to remove all adjacent almost-equal + * characters from word. + * + * Two characters a and b are almost-equal if a == b or a and b are adjacent in the alphabet. + */ + +/** + * @param {string} word + * @return {number} + */ +var removeAlmostEqualCharacters = function(word) { + let result = 0; + + for (let i = 1; i < word.length; i++) { + if (Math.abs(word.charCodeAt(i) - word.charCodeAt(i - 1)) <= 1) { + result++; + i++; + } + } + + return result; +}; diff --git a/solutions/2958-length-of-longest-subarray-with-at-most-k-frequency.js b/solutions/2958-length-of-longest-subarray-with-at-most-k-frequency.js new file mode 100644 index 00000000..4efcb001 --- /dev/null +++ b/solutions/2958-length-of-longest-subarray-with-at-most-k-frequency.js @@ -0,0 +1,40 @@ +/** + * 2958. Length of Longest Subarray With at Most K Frequency + * https://leetcode.com/problems/length-of-longest-subarray-with-at-most-k-frequency/ + * Difficulty: Medium + * + * You are given an integer array nums and an integer k. + * + * The frequency of an element x is the number of times it occurs in an array. + * + * An array is called good if the frequency of each element in this array is less than or + * equal to k. + * + * Return the length of the longest good subarray of nums. + * + * A subarray is a contiguous non-empty sequence of elements within an array. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var maxSubarrayLength = function(nums, k) { + const map = new Map(); + let result = 0; + let left = 0; + + for (let right = 0; right < nums.length; right++) { + map.set(nums[right], (map.get(nums[right]) || 0) + 1); + + while (map.get(nums[right]) > k) { + map.set(nums[left], map.get(nums[left]) - 1); + left++; + } + + result = Math.max(result, right - left + 1); + } + + return result; +}; diff --git a/solutions/2960-count-tested-devices-after-test-operations.js b/solutions/2960-count-tested-devices-after-test-operations.js new file mode 100644 index 00000000..6c118fb3 --- /dev/null +++ b/solutions/2960-count-tested-devices-after-test-operations.js @@ -0,0 +1,40 @@ +/** + * 2960. Count Tested Devices After Test Operations + * https://leetcode.com/problems/count-tested-devices-after-test-operations/ + * Difficulty: Easy + * + * You are given a 0-indexed integer array batteryPercentages having length n, denoting the + * battery percentages of n 0-indexed devices. + * + * Your task is to test each device i in order from 0 to n - 1, by performing the following + * test operations: + * - If batteryPercentages[i] is greater than 0: + * - Increment the count of tested devices. + * - Decrease the battery percentage of all devices with indices j in the range [i + 1, n - 1] + * by 1, ensuring their battery percentage never goes below 0, i.e, + * batteryPercentages[j] = max(0, batteryPercentages[j] - 1). + * - Move to the next device. + * - Otherwise, move to the next device without performing any test. + * + * Return an integer denoting the number of devices that will be tested after performing the test + * operations in order. + */ + +/** + * @param {number[]} batteryPercentages + * @return {number} + */ +var countTestedDevices = function(batteryPercentages) { + let result = 0; + + for (let i = 0; i < batteryPercentages.length; i++) { + if (batteryPercentages[i] > 0) { + result++; + for (let j = i + 1; j < batteryPercentages.length; j++) { + batteryPercentages[j] = Math.max(0, batteryPercentages[j] - 1); + } + } + } + + return result; +}; diff --git a/solutions/2961-double-modular-exponentiation.js b/solutions/2961-double-modular-exponentiation.js new file mode 100644 index 00000000..1a9f9162 --- /dev/null +++ b/solutions/2961-double-modular-exponentiation.js @@ -0,0 +1,43 @@ +/** + * 2961. Double Modular Exponentiation + * https://leetcode.com/problems/double-modular-exponentiation/ + * Difficulty: Medium + * + * You are given a 0-indexed 2D array variables where variables[i] = [ai, bi, ci, mi], and an + * integer target. + * + * An index i is good if the following formula holds: + * - 0 <= i < variables.length + * - ((aibi % 10)ci) % mi == target + * + * Return an array consisting of good indices in any order. + */ + +/** + * @param {number[][]} variables + * @param {number} target + * @return {number[]} + */ +var getGoodIndices = function(variables, target) { + const result = []; + + for (let i = 0; i < variables.length; i++) { + const [base, exp1, exp2, modulus] = variables[i]; + + let inner = 1; + for (let j = 0; j < exp1; j++) { + inner = (inner * base) % 10; + } + + let count = 1; + for (let j = 0; j < exp2; j++) { + count = (count * inner) % modulus; + } + + if (count === target) { + result.push(i); + } + } + + return result; +}; diff --git a/solutions/2963-count-the-number-of-good-partitions.js b/solutions/2963-count-the-number-of-good-partitions.js new file mode 100644 index 00000000..9144b31e --- /dev/null +++ b/solutions/2963-count-the-number-of-good-partitions.js @@ -0,0 +1,43 @@ +/** + * 2963. Count the Number of Good Partitions + * https://leetcode.com/problems/count-the-number-of-good-partitions/ + * Difficulty: Hard + * + * You are given a 0-indexed array nums consisting of positive integers. + * + * A partition of an array into one or more contiguous subarrays is called good if no two + * subarrays contain the same number. + * + * Return the total number of good partitions of nums. + * + * Since the answer may be large, return it modulo 109 + 7. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var numberOfGoodPartitions = function(nums) { + const mod = 1e9 + 7; + const map = new Map(); + let segments = 0; + let end = -1; + + for (let i = 0; i < nums.length; i++) { + map.set(nums[i], i); + } + + for (let i = 0; i < nums.length; i++) { + if (i > end) { + segments++; + } + end = Math.max(end, map.get(nums[i])); + } + + let result = 1; + for (let i = 1; i < segments; i++) { + result = (result * 2) % mod; + } + + return result; +}; diff --git a/solutions/2964-number-of-divisible-triplet-sums.js b/solutions/2964-number-of-divisible-triplet-sums.js new file mode 100644 index 00000000..bc5a141c --- /dev/null +++ b/solutions/2964-number-of-divisible-triplet-sums.js @@ -0,0 +1,42 @@ +/** + * 2964. Number of Divisible Triplet Sums + * https://leetcode.com/problems/number-of-divisible-triplet-sums/ + * Difficulty: Medium + * + * Given a 0-indexed integer array nums and an integer d, return the number of triplets + * (i, j, k) such that i < j < k and (nums[i] + nums[j] + nums[k]) % d == 0. + */ + +/** + * @param {number[]} nums + * @param {number} d + * @return {number} + */ +var divisibleTripletCount = function(nums, d) { + const n = nums.length; + const pairSums = new Map(); + + for (let i = 0; i < n - 1; i++) { + for (let j = i + 1; j < n; j++) { + const sumMod = (nums[i] + nums[j]) % d; + if (!pairSums.has(sumMod)) { + pairSums.set(sumMod, []); + } + pairSums.get(sumMod).push([i, j]); + } + } + + let result = 0; + for (let k = 0; k < n; k++) { + const targetKey = (d - nums[k] % d) % d; + if (pairSums.has(targetKey)) { + for (const [i, j] of pairSums.get(targetKey)) { + if (j < k) { + result++; + } + } + } + } + + return result; +}; diff --git a/solutions/2966-divide-array-into-arrays-with-max-difference.js b/solutions/2966-divide-array-into-arrays-with-max-difference.js new file mode 100644 index 00000000..3da39b41 --- /dev/null +++ b/solutions/2966-divide-array-into-arrays-with-max-difference.js @@ -0,0 +1,33 @@ +/** + * 2966. Divide Array Into Arrays With Max Difference + * https://leetcode.com/problems/divide-array-into-arrays-with-max-difference/ + * Difficulty: Medium + * + * You are given an integer array nums of size n where n is a multiple of 3 and a positive + * integer k. + * + * Divide the array nums into n / 3 arrays of size 3 satisfying the following condition: + * - The difference between any two elements in one array is less than or equal to k. + * + * Return a 2D array containing the arrays. If it is impossible to satisfy the conditions, return + * an empty array. And if there are multiple answers, return any of them. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number[][]} + */ +var divideArray = function(nums, k) { + nums.sort((a, b) => a - b); + const result = []; + + for (let i = 0; i < nums.length; i += 3) { + if (nums[i + 2] - nums[i] > k) { + return []; + } + result.push([nums[i], nums[i + 1], nums[i + 2]]); + } + + return result; +}; diff --git a/solutions/2969-minimum-number-of-coins-for-fruits-ii.js b/solutions/2969-minimum-number-of-coins-for-fruits-ii.js new file mode 100644 index 00000000..ee4d6479 --- /dev/null +++ b/solutions/2969-minimum-number-of-coins-for-fruits-ii.js @@ -0,0 +1,46 @@ +/** + * 2969. Minimum Number of Coins for Fruits II + * https://leetcode.com/problems/minimum-number-of-coins-for-fruits-ii/ + * Difficulty: Hard + * + * You are at a fruit market with different types of exotic fruits on display. + * + * You are given a 1-indexed array prices, where prices[i] denotes the number of coins + * needed to purchase the ith fruit. + * + * The fruit market has the following offer: + * - If you purchase the ith fruit at prices[i] coins, you can get the next i fruits for free. + * + * Note that even if you can take fruit j for free, you can still purchase it for prices[j] + * coins to receive a new offer. + * + * Return the minimum number of coins needed to acquire all the fruits. + */ + +/** + * @param {number[]} prices + * @return {number} + */ +var minimumCoins = function(prices) { + const n = prices.length; + const dp = new Array(n); + const deque = []; + + dp[0] = prices[0]; + deque.push(0); + + for (let i = 1; i < n; i++) { + dp[i] = dp[deque[0]] + prices[i]; + + while (deque.length > 0 && deque[0] + deque[0] + 1 < i) { + deque.shift(); + } + while (deque.length > 0 && dp[deque[deque.length - 1]] >= dp[i]) { + deque.pop(); + } + + deque.push(i); + } + + return dp[deque[0]]; +}; diff --git a/solutions/2970-count-the-number-of-incremovable-subarrays-i.js b/solutions/2970-count-the-number-of-incremovable-subarrays-i.js new file mode 100644 index 00000000..269065a7 --- /dev/null +++ b/solutions/2970-count-the-number-of-incremovable-subarrays-i.js @@ -0,0 +1,46 @@ +/** + * 2970. Count the Number of Incremovable Subarrays I + * https://leetcode.com/problems/count-the-number-of-incremovable-subarrays-i/ + * Difficulty: Easy + * + * You are given a 0-indexed array of positive integers nums. + * + * A subarray of nums is called incremovable if nums becomes strictly increasing on removing the + * subarray. For example, the subarray [3, 4] is an incremovable subarray of [5, 3, 4, 6, 7] because + * removing this subarray changes the array [5, 3, 4, 6, 7] to [5, 6, 7] which is strictly + * increasing. + * + * Return the total number of incremovable subarrays of nums. + * + * Note that an empty array is considered strictly increasing. + * + * A subarray is a contiguous non-empty sequence of elements within an array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var incremovableSubarrayCount = function(nums) { + let result = 0; + + for (let start = 0; start < nums.length; start++) { + for (let end = start; end < nums.length; end++) { + let isIncreasing = true; + let prev = -Infinity; + + for (let i = 0; i < nums.length; i++) { + if (i >= start && i <= end) continue; + if (nums[i] <= prev) { + isIncreasing = false; + break; + } + prev = nums[i]; + } + + if (isIncreasing) result++; + } + } + + return result; +}; diff --git a/solutions/2971-find-polygon-with-the-largest-perimeter.js b/solutions/2971-find-polygon-with-the-largest-perimeter.js new file mode 100644 index 00000000..15d2e501 --- /dev/null +++ b/solutions/2971-find-polygon-with-the-largest-perimeter.js @@ -0,0 +1,33 @@ +/** + * 2971. Find Polygon With the Largest Perimeter + * https://leetcode.com/problems/find-polygon-with-the-largest-perimeter/ + * Difficulty: Medium + * + * You are given an array of positive integers nums of length n. + * + * A polygon is a closed plane figure that has at least 3 sides. The longest side of a polygon is + * smaller than the sum of its other sides. + * + * Conversely, if you have k (k >= 3) positive real numbers a1, a2, a3, ..., ak where + * a1 <= a2 <= a3 <= ... <= ak and a1 + a2 + a3 + ... + ak-1 > ak, then there always exists + * a polygon with k sides whose lengths are a1, a2, a3, ..., ak. + * + * The perimeter of a polygon is the sum of lengths of its sides. + * + * Return the largest possible perimeter of a polygon whose sides can be formed from nums, or -1 + * if it is not possible to create a polygon. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var largestPerimeter = function(nums) { + nums.sort((a, b) => b - a); + for (let i = 0; i < nums.length - 2; i++) { + if (nums[i] < nums.slice(i + 1).reduce((sum, num) => sum + num, 0)) { + return nums.slice(i).reduce((sum, num) => sum + num, 0); + } + } + return -1; +}; diff --git a/solutions/2976-minimum-cost-to-convert-string-i.js b/solutions/2976-minimum-cost-to-convert-string-i.js new file mode 100644 index 00000000..9107955d --- /dev/null +++ b/solutions/2976-minimum-cost-to-convert-string-i.js @@ -0,0 +1,59 @@ +/** + * 2976. Minimum Cost to Convert String I + * https://leetcode.com/problems/minimum-cost-to-convert-string-i/ + * Difficulty: Medium + * + * You are given two 0-indexed strings source and target, both of length n and consisting of + * lowercase English letters. You are also given two 0-indexed character arrays original and + * changed, and an integer array cost, where cost[i] represents the cost of changing the character + * original[i] to the character changed[i]. + * + * You start with the string source. In one operation, you can pick a character x from the string + * and change it to the character y at a cost of z if there exists any index j such that + * cost[j] == z, original[j] == x, and changed[j] == y. + * + * Return the minimum cost to convert the string source to the string target using any number of + * operations. If it is impossible to convert source to target, return -1. + * + * Note that there may exist indices i, j such that original[j] == original[i] and + * changed[j] == changed[i]. + */ + +/** + * @param {string} source + * @param {string} target + * @param {character[]} original + * @param {character[]} changed + * @param {number[]} cost + * @return {number} + */ +var minimumCost = function(source, target, original, changed, cost) { + const graph = new Array(26).fill().map(() => new Array(26).fill(Infinity)); + for (let i = 0; i < 26; i++) graph[i][i] = 0; + + for (let i = 0; i < original.length; i++) { + const from = original[i].charCodeAt(0) - 97; + const to = changed[i].charCodeAt(0) - 97; + graph[from][to] = Math.min(graph[from][to], cost[i]); + } + + for (let k = 0; k < 26; k++) { + for (let i = 0; i < 26; i++) { + for (let j = 0; j < 26; j++) { + graph[i][j] = Math.min(graph[i][j], graph[i][k] + graph[k][j]); + } + } + } + + let result = 0; + for (let i = 0; i < source.length; i++) { + if (source[i] !== target[i]) { + const from = source[i].charCodeAt(0) - 97; + const to = target[i].charCodeAt(0) - 97; + if (graph[from][to] === Infinity) return -1; + result += graph[from][to]; + } + } + + return result; +}; diff --git a/solutions/2979-most-expensive-item-that-can-not-be-bought.js b/solutions/2979-most-expensive-item-that-can-not-be-bought.js new file mode 100644 index 00000000..b4fe3671 --- /dev/null +++ b/solutions/2979-most-expensive-item-that-can-not-be-bought.js @@ -0,0 +1,24 @@ +/** + * 2979. Most Expensive Item That Can Not Be Bought + * https://leetcode.com/problems/most-expensive-item-that-can-not-be-bought/ + * Difficulty: Medium + * + * You are given two distinct prime numbers primeOne and primeTwo. + * + * Alice and Bob are visiting a market. The market has an infinite number of items, for any + * positive integer x there exists an item whose price is x. Alice wants to buy some items + * from the market to gift to Bob. She has an infinite number of coins in the denomination + * primeOne and primeTwo. She wants to know the most expensive item she can not buy to gift + * to Bob. + * + * Return the price of the most expensive item which Alice can not gift to Bob. + */ + +/** + * @param {number} primeOne + * @param {number} primeTwo + * @return {number} + */ +var mostExpensiveItem = function(primeOne, primeTwo) { + return primeOne * primeTwo - primeOne - primeTwo; +}; diff --git a/solutions/2980-check-if-bitwise-or-has-trailing-zeros.js b/solutions/2980-check-if-bitwise-or-has-trailing-zeros.js new file mode 100644 index 00000000..e3afe838 --- /dev/null +++ b/solutions/2980-check-if-bitwise-or-has-trailing-zeros.js @@ -0,0 +1,36 @@ +/** + * 2980. Check if Bitwise OR Has Trailing Zeros + * https://leetcode.com/problems/check-if-bitwise-or-has-trailing-zeros/ + * Difficulty: Easy + * + * You are given an array of positive integers nums. + * + * You have to check if it is possible to select two or more elements in the array such + * that the bitwise OR of the selected elements has at least one trailing zero in its + * binary representation. + * + * For example, the binary representation of 5, which is "101", does not have any trailing + * zeros, whereas the binary representation of 4, which is "100", has two trailing zeros. + * + * Return true if it is possible to select two or more elements whose bitwise OR has trailing + * zeros, return false otherwise. + */ + +/** + * @param {number[]} nums + * @return {boolean} + */ +var hasTrailingZeros = function(nums) { + let evenCount = 0; + + for (const num of nums) { + if (num % 2 === 0) { + evenCount++; + if (evenCount >= 2) { + return true; + } + } + } + + return false; +}; diff --git a/solutions/2981-find-longest-special-substring-that-occurs-thrice-i.js b/solutions/2981-find-longest-special-substring-that-occurs-thrice-i.js new file mode 100644 index 00000000..ac12f932 --- /dev/null +++ b/solutions/2981-find-longest-special-substring-that-occurs-thrice-i.js @@ -0,0 +1,39 @@ +/** + * 2981. Find Longest Special Substring That Occurs Thrice I + * https://leetcode.com/problems/find-longest-special-substring-that-occurs-thrice-i/ + * Difficulty: Medium + * + * You are given a string s that consists of lowercase English letters. + * + * A string is called special if it is made up of only a single character. For example, the + * string "abc" is not special, whereas the strings "ddd", "zz", and "f" are special. + * + * Return the length of the longest special substring of s which occurs at least thrice, + * or -1 if no special substring occurs at least thrice. + * + * A substring is a contiguous non-empty sequence of characters within a string. + */ + +/** + * @param {string} s + * @return {number} + */ +var maximumLength = function(s) { + const map = new Map(); + let result = -1; + + for (let i = 0; i < s.length; i++) { + for (let len = 1; len <= s.length - i; len++) { + const substr = s.slice(i, i + len); + if (substr.split('').every(c => c === substr[0])) { + const count = (map.get(substr) || 0) + 1; + map.set(substr, count); + if (count >= 3) { + result = Math.max(result, len); + } + } + } + } + + return result; +}; diff --git a/solutions/2992-number-of-self-divisible-permutations.js b/solutions/2992-number-of-self-divisible-permutations.js new file mode 100644 index 00000000..a66cd661 --- /dev/null +++ b/solutions/2992-number-of-self-divisible-permutations.js @@ -0,0 +1,59 @@ +/** + * 2992. Number of Self-Divisible Permutations + * https://leetcode.com/problems/number-of-self-divisible-permutations/ + * Difficulty: Medium + * + * Given an integer n, return the number of permutations of the 1-indexed array + * nums = [1, 2, ..., n], such that it's self-divisible. + * + * A 1-indexed array a of length n is self-divisible if for every 1 <= i <= n, gcd(a[i], i) == 1. + * + * A permutation of an array is a rearrangement of the elements of that array, for example here + * are all of the permutations of the array [1, 2, 3]: + * - [1, 2, 3] + * - [1, 3, 2] + * - [2, 1, 3] + * - [2, 3, 1] + * - [3, 1, 2] + * - [3, 2, 1] + */ + +/** + * @param {number} n + * @return {number} + */ +var selfDivisiblePermutationCount = function(n) { + const graph = new Array(n + 1).fill().map(() => []); + + for (let position = 1; position <= n; position++) { + for (let value = 1; value <= n; value++) { + if (gcd(value, position) === 1) { + graph[position].push(value); + } + } + } + + return countPermutations(1, 0); + + function countPermutations(position, usedMask) { + if (position > n) return 1; + + let count = 0; + for (const value of graph[position]) { + if ((usedMask & (1 << value)) === 0) { + count += countPermutations(position + 1, usedMask | (1 << value)); + } + } + + return count; + } + + function gcd(a, b) { + while (b !== 0) { + const temp = b; + b = a % b; + a = temp; + } + return a; + } +}; diff --git a/solutions/2997-minimum-number-of-operations-to-make-array-xor-equal-to-k.js b/solutions/2997-minimum-number-of-operations-to-make-array-xor-equal-to-k.js new file mode 100644 index 00000000..b1d492eb --- /dev/null +++ b/solutions/2997-minimum-number-of-operations-to-make-array-xor-equal-to-k.js @@ -0,0 +1,38 @@ +/** + * 2997. Minimum Number of Operations to Make Array XOR Equal to K + * https://leetcode.com/problems/minimum-number-of-operations-to-make-array-xor-equal-to-k/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums and a positive integer k. + * + * You can apply the following operation on the array any number of times: + * - Choose any element of the array and flip a bit in its binary representation. Flipping a bit + * means changing a 0 to 1 or vice versa. + * + * Return the minimum number of operations required to make the bitwise XOR of all elements of the + * final array equal to k. + * + * Note that you can flip leading zero bits in the binary representation of elements. For example, + * for the number (101)2 you can flip the fourth bit and obtain (1101)2. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minOperations = function(nums, k) { + let xorResult = 0; + for (const num of nums) { + xorResult ^= num; + } + + let result = 0; + let diff = xorResult ^ k; + while (diff > 0) { + result += diff & 1; + diff >>= 1; + } + + return result; +}; diff --git a/solutions/2998-minimum-number-of-operations-to-make-x-and-y-equal.js b/solutions/2998-minimum-number-of-operations-to-make-x-and-y-equal.js new file mode 100644 index 00000000..cc18c133 --- /dev/null +++ b/solutions/2998-minimum-number-of-operations-to-make-x-and-y-equal.js @@ -0,0 +1,45 @@ +/** + * 2998. Minimum Number of Operations to Make X and Y Equal + * https://leetcode.com/problems/minimum-number-of-operations-to-make-x-and-y-equal/ + * Difficulty: Medium + * + * You are given two positive integers x and y. + * + * In one operation, you can do one of the four following operations: + * 1. Divide x by 11 if x is a multiple of 11. + * 2. Divide x by 5 if x is a multiple of 5. + * 3. Decrement x by 1. + * 4. Increment x by 1. + * + * Return the minimum number of operations required to make x and y equal. + */ + +/** + * @param {number} x + * @param {number} y + * @return {number} + */ +var minimumOperationsToMakeEqual = function(x, y) { + const queue = [[x, 0]]; + const visited = new Set([x]); + + while (queue.length) { + const [current, steps] = queue.shift(); + + if (current === y) return steps; + + const nextStates = []; + if (current % 11 === 0) nextStates.push(current / 11); + if (current % 5 === 0) nextStates.push(current / 5); + nextStates.push(current - 1, current + 1); + + for (const next of nextStates) { + if (next >= 0 && next <= 10000 && !visited.has(next)) { + visited.add(next); + queue.push([next, steps + 1]); + } + } + } + + return -1; +}; diff --git a/solutions/3000-maximum-area-of-longest-diagonal-rectangle.js b/solutions/3000-maximum-area-of-longest-diagonal-rectangle.js new file mode 100644 index 00000000..5cb6ed23 --- /dev/null +++ b/solutions/3000-maximum-area-of-longest-diagonal-rectangle.js @@ -0,0 +1,34 @@ +/** + * 3000. Maximum Area of Longest Diagonal Rectangle + * https://leetcode.com/problems/maximum-area-of-longest-diagonal-rectangle/ + * Difficulty: Easy + * + * You are given a 2D 0-indexed integer array dimensions. + * + * For all indices i, 0 <= i < dimensions.length, dimensions[i][0] represents the length and + * dimensions[i][1] represents the width of the rectangle i. + * + * Return the area of the rectangle having the longest diagonal. If there are multiple rectangles + * with the longest diagonal, return the area of the rectangle having the maximum area. + */ + +/** + * @param {number[][]} dimensions + * @return {number} + */ +var areaOfMaxDiagonal = function(dimensions) { + let maxDiagonal = 0; + let result = 0; + + for (const [length, width] of dimensions) { + const diagonal = length * length + width * width; + const area = length * width; + + if (diagonal > maxDiagonal || (diagonal === maxDiagonal && area > result)) { + maxDiagonal = diagonal; + result = area; + } + } + + return result; +}; diff --git a/solutions/3002-maximum-size-of-a-set-after-removals.js b/solutions/3002-maximum-size-of-a-set-after-removals.js new file mode 100644 index 00000000..66f30fd1 --- /dev/null +++ b/solutions/3002-maximum-size-of-a-set-after-removals.js @@ -0,0 +1,41 @@ +/** + * 3002. Maximum Size of a Set After Removals + * https://leetcode.com/problems/maximum-size-of-a-set-after-removals/ + * Difficulty: Medium + * + * You are given two 0-indexed integer arrays nums1 and nums2 of even length n. + * + * You must remove n / 2 elements from nums1 and n / 2 elements from nums2. After the removals, + * you insert the remaining elements of nums1 and nums2 into a set s. + * + * Return the maximum possible size of the set s. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var maximumSetSize = function(nums1, nums2) { + const n = nums1.length; + const set1 = new Set(nums1); + const set2 = new Set(nums2); + + let unique1 = set1.size; + let unique2 = set2.size; + let common = 0; + + for (const num of set1) { + if (set2.has(num)) common++; + } + + unique1 -= common; + unique2 -= common; + + const max1 = Math.min(unique1, n / 2); + const max2 = Math.min(unique2, n / 2); + const remaining = n / 2 - max1 + n / 2 - max2; + const maxCommon = Math.min(common, remaining); + + return max1 + max2 + maxCommon; +}; diff --git a/solutions/3004-maximum-subtree-of-the-same-color.js b/solutions/3004-maximum-subtree-of-the-same-color.js new file mode 100644 index 00000000..2078b9d2 --- /dev/null +++ b/solutions/3004-maximum-subtree-of-the-same-color.js @@ -0,0 +1,61 @@ +/** + * 3004. Maximum Subtree of the Same Color + * https://leetcode.com/problems/maximum-subtree-of-the-same-color/ + * Difficulty: Medium + * + * You are given a 2D integer array edges representing a tree with n nodes, numbered from + * 0 to n - 1, rooted at node 0, where edges[i] = [ui, vi] means there is an edge between + * the nodes vi and ui. + * + * You are also given a 0-indexed integer array colors of size n, where colors[i] is the + * color assigned to node i. + * + * We want to find a node v such that every node in the subtree of v has the same color. + * + * Return the size of such subtree with the maximum number of nodes possible. + */ + +/** + * @param {number[][]} edges + * @param {number[]} colors + * @return {number} + */ +var maximumSubtreeSize = function(edges, colors) { + const n = colors.length; + const graph = new Array(n).fill().map(() => []); + + for (const [u, v] of edges) { + graph[u].push(v); + graph[v].push(u); + } + + let result = 1; + + dfs(0, -1); + + return result; + + function dfs(node, parent) { + let subtreeSize = 1; + let isValidSubtree = true; + + for (const child of graph[node]) { + if (child !== parent) { + const childSize = dfs(child, node); + + if (colors[child] === colors[node] && childSize > 0) { + subtreeSize += childSize; + } else { + isValidSubtree = false; + } + } + } + + if (isValidSubtree) { + result = Math.max(result, subtreeSize); + return subtreeSize; + } + + return 0; + } +}; diff --git a/solutions/3005-count-elements-with-maximum-frequency.js b/solutions/3005-count-elements-with-maximum-frequency.js new file mode 100644 index 00000000..cb89603e --- /dev/null +++ b/solutions/3005-count-elements-with-maximum-frequency.js @@ -0,0 +1,35 @@ +/** + * 3005. Count Elements With Maximum Frequency + * https://leetcode.com/problems/count-elements-with-maximum-frequency/ + * Difficulty: Easy + * + * You are given an array nums consisting of positive integers. + * + * Return the total frequencies of elements in nums such that those elements all have the + * maximum frequency. + * + * The frequency of an element is the number of occurrences of that element in the array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxFrequencyElements = function(nums) { + const map = new Map(); + let maxFreq = 0; + let result = 0; + + for (const num of nums) { + const count = (map.get(num) || 0) + 1; + map.set(num, count); + if (count > maxFreq) { + maxFreq = count; + result = count; + } else if (count === maxFreq) { + result += count; + } + } + + return result; +}; diff --git a/solutions/3009-maximum-number-of-intersections-on-the-chart.js b/solutions/3009-maximum-number-of-intersections-on-the-chart.js new file mode 100644 index 00000000..5c0f0852 --- /dev/null +++ b/solutions/3009-maximum-number-of-intersections-on-the-chart.js @@ -0,0 +1,42 @@ +/** + * 3009. Maximum Number of Intersections on the Chart + * https://leetcode.com/problems/maximum-number-of-intersections-on-the-chart/ + * Difficulty: Hard + * + * There is a line chart consisting of n points connected by line segments. You are given a + * 1-indexed integer array y. The kth point has coordinates (k, y[k]). There are no horizontal + * lines; that is, no two consecutive points have the same y-coordinate. + * + * We can draw an infinitely long horizontal line. Return the maximum number of points of + * intersection of the line with the chart. + */ + +/** + * @param {number[]} y + * @return {number} + */ +var maxIntersectionCount = function(y) { + const n = y.length; + const coordinateEvents = new Map(); + + for (let segmentIndex = 1; segmentIndex < n; segmentIndex++) { + const segmentStart = 2 * y[segmentIndex - 1]; + const segmentEnd = 2 * y[segmentIndex] + + (segmentIndex === n - 1 ? 0 : y[segmentIndex] > y[segmentIndex - 1] ? -1 : 1); + const intervalStart = Math.min(segmentStart, segmentEnd); + const intervalEnd = Math.max(segmentStart, segmentEnd); + + coordinateEvents.set(intervalStart, (coordinateEvents.get(intervalStart) || 0) + 1); + coordinateEvents.set(intervalEnd + 1, (coordinateEvents.get(intervalEnd + 1) || 0) - 1); + } + + const sortedEvents = [...coordinateEvents.entries()].sort((a, b) => a[0] - b[0]); + let activeSegments = 0; + let result = 0; + for (const [coordinate, segmentChange] of sortedEvents) { + activeSegments += segmentChange; + result = Math.max(result, activeSegments); + } + + return result; +}; diff --git a/solutions/3010-divide-an-array-into-subarrays-with-minimum-cost-i.js b/solutions/3010-divide-an-array-into-subarrays-with-minimum-cost-i.js new file mode 100644 index 00000000..26a184a5 --- /dev/null +++ b/solutions/3010-divide-an-array-into-subarrays-with-minimum-cost-i.js @@ -0,0 +1,32 @@ +/** + * 3010. Divide an Array Into Subarrays With Minimum Cost I + * https://leetcode.com/problems/divide-an-array-into-subarrays-with-minimum-cost-i/ + * Difficulty: Easy + * + * You are given an array of integers nums of length n. + * + * The cost of an array is the value of its first element. For example, the cost of [1,2,3] + * is 1 while the cost of [3,4,1] is 3. + * + * You need to divide nums into 3 disjoint contiguous subarrays. + * + * Return the minimum possible sum of the cost of these subarrays. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumCost = function(nums) { + const n = nums.length; + let result = Infinity; + + for (let i = 1; i < n - 1; i++) { + for (let j = i + 1; j < n; j++) { + const cost = nums[0] + nums[i] + nums[j]; + result = Math.min(result, cost); + } + } + + return result; +}; diff --git a/solutions/3011-find-if-array-can-be-sorted.js b/solutions/3011-find-if-array-can-be-sorted.js new file mode 100644 index 00000000..c395e89e --- /dev/null +++ b/solutions/3011-find-if-array-can-be-sorted.js @@ -0,0 +1,57 @@ +/** + * 3011. Find if Array Can Be Sorted + * https://leetcode.com/problems/find-if-array-can-be-sorted/ + * Difficulty: Medium + * + * You are given a 0-indexed array of positive integers nums. + * + * In one operation, you can swap any two adjacent elements if they have the same number of + * set bits. You are allowed to do this operation any number of times (including zero). + * + * Return true if you can sort the array in ascending order, else return false. + */ + +/** + * @param {number[]} nums + * @return {boolean} + */ +var canSortArray = function(nums) { + const sorted = [...nums].sort((a, b) => a - b); + const bitGroups = []; + let currentBits = countSetBits(nums[0]); + let group = [nums[0]]; + + for (let i = 1; i < nums.length; i++) { + const bits = countSetBits(nums[i]); + if (bits === currentBits) { + group.push(nums[i]); + } else { + bitGroups.push(group); + group = [nums[i]]; + currentBits = bits; + } + } + bitGroups.push(group); + + let index = 0; + for (const group of bitGroups) { + const groupSorted = [...group].sort((a, b) => a - b); + for (const num of groupSorted) { + if (num !== sorted[index]) { + return false; + } + index++; + } + } + + return true; + + function countSetBits(num) { + let count = 0; + while (num) { + count += num & 1; + num >>= 1; + } + return count; + } +}; diff --git a/solutions/3014-minimum-number-of-pushes-to-type-word-i.js b/solutions/3014-minimum-number-of-pushes-to-type-word-i.js new file mode 100644 index 00000000..347e798e --- /dev/null +++ b/solutions/3014-minimum-number-of-pushes-to-type-word-i.js @@ -0,0 +1,42 @@ +/** + * 3014. Minimum Number of Pushes to Type Word I + * https://leetcode.com/problems/minimum-number-of-pushes-to-type-word-i/ + * Difficulty: Easy + * + * You are given a string word containing distinct lowercase English letters. + * + * Telephone keypads have keys mapped with distinct collections of lowercase English letters, + * which can be used to form words by pushing them. For example, the key 2 is mapped with + * ["a","b","c"], we need to push the key one time to type "a", two times to type "b", and + * three times to type "c". + * + * It is allowed to remap the keys numbered 2 to 9 to distinct collections of letters. The + * keys can be remapped to any amount of letters, but each letter must be mapped to exactly + * one key. You need to find the minimum number of times the keys will be pushed to type + * the string word. + * + * Return the minimum number of pushes needed to type word after remapping the keys. + * + * An example mapping of letters to keys on a telephone keypad is given below. Note that + * 1, *, #, and 0 do not map to any letters. + */ + +/** + * @param {string} word + * @return {number} + */ +var minimumPushes = function(word) { + const frequency = new Array(26).fill(0); + for (const char of word) { + frequency[char.charCodeAt(0) - 97]++; + } + frequency.sort((a, b) => b - a); + + let result = 0; + for (let i = 0; i < frequency.length; i++) { + if (frequency[i] === 0) break; + result += frequency[i] * (Math.floor(i / 8) + 1); + } + + return result; +}; diff --git a/solutions/3015-count-the-number-of-houses-at-a-certain-distance-i.js b/solutions/3015-count-the-number-of-houses-at-a-certain-distance-i.js new file mode 100644 index 00000000..02801f91 --- /dev/null +++ b/solutions/3015-count-the-number-of-houses-at-a-certain-distance-i.js @@ -0,0 +1,57 @@ +/** + * 3015. Count the Number of Houses at a Certain Distance I + * https://leetcode.com/problems/count-the-number-of-houses-at-a-certain-distance-i/ + * Difficulty: Medium + * + * You are given three positive integers n, x, and y. + * + * In a city, there exist houses numbered 1 to n connected by n streets. There is a street + * connecting the house numbered i with the house numbered i + 1 for all 1 <= i <= n - 1. + * An additional street connects the house numbered x with the house numbered y. + * + * For each k, such that 1 <= k <= n, you need to find the number of pairs of houses (house1, + * house2) such that the minimum number of streets that need to be traveled to reach house2 + * from house1 is k. + * + * Return a 1-indexed array result of length n where result[k] represents the total number + * of pairs of houses such that the minimum streets required to reach one house from the + * other is k. + * + * Note that x and y can be equal. + */ + +/** + * @param {number} n + * @param {number} x + * @param {number} y + * @return {number[]} + */ +var countOfPairs = function(n, x, y) { + const distances = new Array(n + 1).fill().map(() => new Array(n + 1).fill(Infinity)); + + for (let i = 1; i <= n; i++) { + distances[i][i] = 0; + if (i < n) distances[i][i + 1] = distances[i + 1][i] = 1; + } + + distances[x][y] = distances[y][x] = 1; + + for (let k = 1; k <= n; k++) { + for (let i = 1; i <= n; i++) { + for (let j = 1; j <= n; j++) { + distances[i][j] = Math.min(distances[i][j], distances[i][k] + distances[k][j]); + } + } + } + + const result = new Array(n + 1).fill(0); + for (let i = 1; i <= n; i++) { + for (let j = 1; j <= n; j++) { + if (i !== j && distances[i][j] !== Infinity) { + result[distances[i][j]]++; + } + } + } + + return result.slice(1); +}; diff --git a/solutions/3016-minimum-number-of-pushes-to-type-word-ii.js b/solutions/3016-minimum-number-of-pushes-to-type-word-ii.js new file mode 100644 index 00000000..5a54a46c --- /dev/null +++ b/solutions/3016-minimum-number-of-pushes-to-type-word-ii.js @@ -0,0 +1,41 @@ +/** + * 3016. Minimum Number of Pushes to Type Word II + * https://leetcode.com/problems/minimum-number-of-pushes-to-type-word-ii/ + * Difficulty: Medium + * + * You are given a string word containing lowercase English letters. + * + * Telephone keypads have keys mapped with distinct collections of lowercase English letters, + * which can be used to form words by pushing them. For example, the key 2 is mapped with + * ["a","b","c"], we need to push the key one time to type "a", two times to type "b", and + * three times to type "c". + * + * It is allowed to remap the keys numbered 2 to 9 to distinct collections of letters. The + * keys can be remapped to any amount of letters, but each letter must be mapped to exactly + * one key. You need to find the minimum number of times the keys will be pushed to type the + * string word. + * + * Return the minimum number of pushes needed to type word after remapping the keys. + * + * An example mapping of letters to keys on a telephone keypad is given below. Note that + * 1, *, #, and 0 do not map to any letters. + */ + +/** + * @param {string} word + * @return {number} + */ +var minimumPushes = function(word) { + const frequency = new Array(26).fill(0); + for (const char of word) { + frequency[char.charCodeAt(0) - 97]++; + } + frequency.sort((a, b) => b - a); + + let result = 0; + for (let i = 0; i < frequency.length && frequency[i] > 0; i++) { + result += frequency[i] * (Math.floor(i / 8) + 1); + } + + return result; +}; diff --git a/solutions/3018-maximum-number-of-removal-queries-that-can-be-processed-i.js b/solutions/3018-maximum-number-of-removal-queries-that-can-be-processed-i.js new file mode 100644 index 00000000..f8386a90 --- /dev/null +++ b/solutions/3018-maximum-number-of-removal-queries-that-can-be-processed-i.js @@ -0,0 +1,70 @@ +/** + * 3018. Maximum Number of Removal Queries That Can Be Processed I + * https://leetcode.com/problems/maximum-number-of-removal-queries-that-can-be-processed-i/ + * Difficulty: Hard + * + * You are given a 0-indexed array nums and a 0-indexed array queries. + * + * You can do the following operation at the beginning at most once: + * - Replace nums with a subsequence of nums. + * + * We start processing queries in the given order; for each query, we do the following: + * - If the first and the last element of nums is less than queries[i], the processing of + * queries ends. + * - Otherwise, we choose either the first or the last element of nums if it is greater + * than or equal to queries[i], and we remove the chosen element from nums. + * + * Return the maximum number of queries that can be processed by doing the operation optimally. + */ + +/** + * @param {number[]} nums + * @param {number[]} queries + * @return {number} + */ +var maximumProcessableQueries = function(nums, queries) { + const queryCount = queries.length; + const arrayLength = nums.length; + const dp = new Array(arrayLength + 1).fill().map(() => new Array(arrayLength + 1).fill(0)); + + nums.push(-1); + let result = 0; + + for (let segmentLength = arrayLength - 1; segmentLength >= 0; segmentLength--) { + for (let leftIndex = 0; leftIndex < arrayLength; leftIndex++) { + const rightIndex = leftIndex + segmentLength; + + if (rightIndex < arrayLength) { + dp[leftIndex][rightIndex] = Math.max( + dp[leftIndex - 1] ? dp[leftIndex - 1][rightIndex] : 0, + dp[leftIndex][rightIndex + 1] || 0 + ); + + const prevLeftQueries = dp[leftIndex - 1] ? dp[leftIndex - 1][rightIndex] : 0; + const prevRightQueries = dp[leftIndex][rightIndex + 1] || 0; + if (prevLeftQueries < queryCount && nums[leftIndex - 1] >= queries[prevLeftQueries]) { + dp[leftIndex][rightIndex] = Math.max(dp[leftIndex][rightIndex], prevLeftQueries + 1); + } + + if (prevRightQueries < queryCount && nums[rightIndex + 1] >= queries[prevRightQueries]) { + dp[leftIndex][rightIndex] = Math.max(dp[leftIndex][rightIndex], prevRightQueries + 1); + } + + if (dp[leftIndex][rightIndex] === queryCount) { + return queryCount; + } + } else { + break; + } + } + } + + for (let singleIndex = 0; singleIndex < arrayLength; singleIndex++) { + const currentQueries = dp[singleIndex][singleIndex]; + const canProcessCurrent = currentQueries < queryCount + && nums[singleIndex] >= queries[currentQueries] ? 1 : 0; + result = Math.max(result, currentQueries + canProcessCurrent); + } + + return result; +}; diff --git a/solutions/3019-number-of-changing-keys.js b/solutions/3019-number-of-changing-keys.js new file mode 100644 index 00000000..f48c69f0 --- /dev/null +++ b/solutions/3019-number-of-changing-keys.js @@ -0,0 +1,30 @@ +/** + * 3019. Number of Changing Keys + * https://leetcode.com/problems/number-of-changing-keys/ + * Difficulty: Easy + * + * You are given a 0-indexed string s typed by a user. Changing a key is defined as using a key + * different from the last used key. For example, s = "ab" has a change of a key while s = "bBBb" + * does not have any. + * + * Return the number of times the user had to change the key. + * + * Note: Modifiers like shift or caps lock won't be counted in changing the key that is if a user + * typed the letter 'a' and then the letter 'A' then it will not be considered as a changing of key. + */ + +/** + * @param {string} s + * @return {number} + */ +var countKeyChanges = function(s) { + let result = 0; + + for (let i = 1; i < s.length; i++) { + if (s[i].toLowerCase() !== s[i - 1].toLowerCase()) { + result++; + } + } + + return result; +}; diff --git a/solutions/3021-alice-and-bob-playing-flower-game.js b/solutions/3021-alice-and-bob-playing-flower-game.js new file mode 100644 index 00000000..4335643c --- /dev/null +++ b/solutions/3021-alice-and-bob-playing-flower-game.js @@ -0,0 +1,37 @@ +/** + * 3021. Alice and Bob Playing Flower Game + * https://leetcode.com/problems/alice-and-bob-playing-flower-game/ + * Difficulty: Medium + * + * Alice and Bob are playing a turn-based game on a circular field surrounded by flowers. + * The circle represents the field, and there are x flowers in the clockwise direction + * between Alice and Bob, and y flowers in the anti-clockwise direction between them. + * + * The game proceeds as follows: + * 1. Alice takes the first turn. + * 2. In each turn, a player must choose either the clockwise or anti-clockwise direction + * and pick one flower from that side. + * 3. At the end of the turn, if there are no flowers left at all, the current player + * captures their opponent and wins the game. + * + * Given two integers, n and m, the task is to compute the number of possible pairs (x, y) + * that satisfy the conditions: + * - Alice must win the game according to the described rules. + * - The number of flowers x in the clockwise direction must be in the range [1,n]. + * - The number of flowers y in the anti-clockwise direction must be in the range [1,m]. + * + * Return the number of possible pairs (x, y) that satisfy the conditions mentioned in the + * statement. + */ + +/** + * @param {number} n + * @param {number} m + * @return {number} + */ +var flowerGame = function(n, m) { + const evenN = Math.floor(n / 2); + const evenM = Math.floor(m / 2); + + return evenN * (m - evenM) + (n - evenN) * evenM; +}; diff --git a/solutions/3023-find-pattern-in-infinite-stream-i.js b/solutions/3023-find-pattern-in-infinite-stream-i.js new file mode 100644 index 00000000..7634ac80 --- /dev/null +++ b/solutions/3023-find-pattern-in-infinite-stream-i.js @@ -0,0 +1,59 @@ +/** + * 3023. Find Pattern in Infinite Stream I + * https://leetcode.com/problems/find-pattern-in-infinite-stream-i/ + * Difficulty: Medium + * + * You are given a binary array pattern and an object stream of class InfiniteStream + * representing a 0-indexed infinite stream of bits. + * + * The class InfiniteStream contains the following function: + * - int next(): Reads a single bit (which is either 0 or 1) from the stream and returns it. + * + * Return the first starting index where the pattern matches the bits read from the stream. + * For example, if the pattern is [1, 0], the first match is the highlighted part in the + * stream [0, 1, 0, 1, ...]. + */ + +/** + * Definition for an infinite stream. + * class InfiniteStream { + * @param {number[]} bits + * constructor(bits); + * + * @return {number} + * next(); + * } + */ +/** + * @param {InfiniteStream} stream + * @param {number[]} pattern + * @return {number} + */ +var findPattern = function(stream, pattern) { + const patternLength = pattern.length; + const buffer = []; + let currentIndex = 0; + + while (buffer.length < patternLength) { + buffer.push(stream.next()); + } + + while (true) { + if (isPatternMatch(buffer, pattern)) { + return currentIndex; + } + + buffer.shift(); + buffer.push(stream.next()); + currentIndex++; + } + + function isPatternMatch(buffer, pattern) { + for (let i = 0; i < pattern.length; i++) { + if (buffer[i] !== pattern[i]) { + return false; + } + } + return true; + } +}; diff --git a/solutions/3025-find-the-number-of-ways-to-place-people-i.js b/solutions/3025-find-the-number-of-ways-to-place-people-i.js new file mode 100644 index 00000000..d0b579c1 --- /dev/null +++ b/solutions/3025-find-the-number-of-ways-to-place-people-i.js @@ -0,0 +1,43 @@ +/** + * 3025. Find the Number of Ways to Place People I + * https://leetcode.com/problems/find-the-number-of-ways-to-place-people-i/ + * Difficulty: Medium + * + * You are given a 2D array points of size n x 2 representing integer coordinates of some points + * on a 2D plane, where points[i] = [xi, yi]. + * + * Count the number of pairs of points (A, B), where + * - A is on the upper left side of B, and + * - there are no other points in the rectangle (or line) they make (including the border). + * + * Return the count. + */ + +/** + * @param {number[][]} points + * @return {number} + */ +var numberOfPairs = function(points) { + points.sort((a, b) => a[0] === b[0] ? b[1] - a[1] : a[0] - b[0]); + let result = 0; + + for (let i = 0; i < points.length; i++) { + for (let j = i + 1; j < points.length; j++) { + if (points[i][1] >= points[j][1]) { + let isValid = true; + for (let k = 0; k < points.length; k++) { + if (k !== i && k !== j) { + if (points[k][0] >= points[i][0] && points[k][0] <= points[j][0] + && points[k][1] <= points[i][1] && points[k][1] >= points[j][1]) { + isValid = false; + break; + } + } + } + if (isValid) result++; + } + } + } + + return result; +}; diff --git a/solutions/3027-find-the-number-of-ways-to-place-people-ii.js b/solutions/3027-find-the-number-of-ways-to-place-people-ii.js new file mode 100644 index 00000000..6077d142 --- /dev/null +++ b/solutions/3027-find-the-number-of-ways-to-place-people-ii.js @@ -0,0 +1,68 @@ +/** + * 3027. Find the Number of Ways to Place People II + * https://leetcode.com/problems/find-the-number-of-ways-to-place-people-ii/ + * Difficulty: Hard + * + * You are given a 2D array points of size n x 2 representing integer coordinates of some points + * on a 2D-plane, where points[i] = [xi, yi]. + * + * We define the right direction as positive x-axis (increasing x-coordinate) and the left + * direction as negative x-axis (decreasing x-coordinate). Similarly, we define the up direction + * as positive y-axis (increasing y-coordinate) and the down direction as negative y-axis + * (decreasing y-coordinate) + * + * You have to place n people, including Alice and Bob, at these points such that there is exactly + * one person at every point. Alice wants to be alone with Bob, so Alice will build a rectangular + * fence with Alice's position as the upper left corner and Bob's position as the lower right + * corner of the fence (Note that the fence might not enclose any area, i.e. it can be a line). + * If any person other than Alice and Bob is either inside the fence or on the fence, Alice will + * be sad. + * + * Return the number of pairs of points where you can place Alice and Bob, such that Alice does not + * become sad on building the fence. + * + * Note that Alice can only build a fence with Alice's position as the upper left corner, and Bob's + * position as the lower right corner. For example, Alice cannot build either of the fences in the + * picture below with four corners (1, 1), (1, 3), (3, 1), and (3, 3), because: + * - With Alice at (3, 3) and Bob at (1, 1), Alice's position is not the upper left corner and Bob's + * position is not the lower right corner of the fence. + * - With Alice at (1, 3) and Bob at (1, 1), Bob's position is not the lower right corner of the + * fence. + */ + +/** + * @param {number[][]} points + * @return {number} + */ +var numberOfPairs = function(points) { + points.sort((a, b) => a[0] === b[0] ? b[1] - a[1] : a[0] - b[0]); + let result = 0; + + for (let i = 0; i < points.length; i++) { + const [, maxY] = points[i]; + let minY = -Infinity; + + for (let j = i + 1; j < points.length; j++) { + const [, y] = points[j]; + if (y <= maxY && y > minY) { + let isValid = true; + for (let k = 0; k < points.length; k++) { + if (k !== i && k !== j) { + const [x, ky] = points[k]; + if (x >= points[i][0] && x <= points[j][0] + && ky <= points[i][1] && ky >= points[j][1]) { + isValid = false; + break; + } + } + } + if (isValid) { + result++; + minY = y; + } + } + } + } + + return result; +}; diff --git a/solutions/3028-ant-on-the-boundary.js b/solutions/3028-ant-on-the-boundary.js new file mode 100644 index 00000000..fab768da --- /dev/null +++ b/solutions/3028-ant-on-the-boundary.js @@ -0,0 +1,38 @@ +/** + * 3028. Ant on the Boundary + * https://leetcode.com/problems/ant-on-the-boundary/ + * Difficulty: Easy + * + * An ant is on a boundary. It sometimes goes left and sometimes right. + * + * You are given an array of non-zero integers nums. The ant starts reading nums from the + * first element of it to its end. At each step, it moves according to the value of the + * current element: + * - If nums[i] < 0, it moves left by -nums[i] units. + * - If nums[i] > 0, it moves right by nums[i] units. + * + * Return the number of times the ant returns to the boundary. + * + * Notes: + * - There is an infinite space on both sides of the boundary. + * - We check whether the ant is on the boundary only after it has moved |nums[i]| units. + * In other words, if the ant crosses the boundary during its movement, it does not count. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var returnToBoundaryCount = function(nums) { + let position = 0; + let result = 0; + + for (const step of nums) { + position += step; + if (position === 0) { + result++; + } + } + + return result; +}; diff --git a/solutions/3029-minimum-time-to-revert-word-to-initial-state-i.js b/solutions/3029-minimum-time-to-revert-word-to-initial-state-i.js new file mode 100644 index 00000000..07d7e492 --- /dev/null +++ b/solutions/3029-minimum-time-to-revert-word-to-initial-state-i.js @@ -0,0 +1,33 @@ +/** + * 3029. Minimum Time to Revert Word to Initial State I + * https://leetcode.com/problems/minimum-time-to-revert-word-to-initial-state-i/ + * Difficulty: Medium + * + * You are given a 0-indexed string word and an integer k. + * + * At every second, you must perform the following operations: + * - Remove the first k characters of word. + * - Add any k characters to the end of word. + * + * Note that you do not necessarily need to add the same characters that you removed. + * However, you must perform both operations at every second. + * + * Return the minimum time greater than zero required for word to revert to its initial state. + */ + +/** + * @param {string} word + * @param {number} k + * @return {number} + */ +var minimumTimeToInitialState = function(word, k) { + const n = word.length; + + for (let i = 1; i * k <= n; i++) { + if (word.slice(i * k) === word.slice(0, n - i * k)) { + return i; + } + } + + return Math.ceil(n / k); +}; diff --git a/solutions/3030-find-the-grid-of-region-average.js b/solutions/3030-find-the-grid-of-region-average.js new file mode 100644 index 00000000..d15b7ada --- /dev/null +++ b/solutions/3030-find-the-grid-of-region-average.js @@ -0,0 +1,94 @@ +/** + * 3030. Find the Grid of Region Average + * https://leetcode.com/problems/find-the-grid-of-region-average/ + * Difficulty: Medium + * + * You are given m x n grid image which represents a grayscale image, where image[i][j] + * represents a pixel with intensity in the range [0..255]. You are also given a non-negative + * integer threshold. + * + * Two pixels are adjacent if they share an edge. + * + * A region is a 3 x 3 subgrid where the absolute difference in intensity between any two + * adjacent pixels is less than or equal to threshold. + * + * All pixels in a region belong to that region, note that a pixel can belong to multiple regions. + * + * You need to calculate a m x n grid result, where result[i][j] is the average intensity of the + * regions to which image[i][j] belongs, rounded down to the nearest integer. If image[i][j] + * belongs to multiple regions, result[i][j] is the average of the rounded-down average intensities + * of these regions, rounded down to the nearest integer. If image[i][j] does not belong to any + * region, result[i][j] is equal to image[i][j]. + * + * Return the grid result. + */ + +/** + * @param {number[][]} image + * @param {number} threshold + * @return {number[][]} + */ +var resultGrid = function(image, threshold) { + const rows = image.length; + const cols = image[0].length; + const result = Array.from({ length: rows }, () => new Array(cols).fill(0)); + const regionCount = Array.from({ length: rows }, () => new Array(cols).fill(0)); + + for (let i = 0; i <= rows - 3; i++) { + for (let j = 0; j <= cols - 3; j++) { + if (isValidRegion(i, j)) { + const regionAvg = calculateRegionAverage(i, j); + + for (let r = i; r < i + 3; r++) { + for (let c = j; c < j + 3; c++) { + result[r][c] += regionAvg; + regionCount[r][c]++; + } + } + } + } + } + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (regionCount[i][j] === 0) { + result[i][j] = image[i][j]; + } else { + result[i][j] = Math.floor(result[i][j] / regionCount[i][j]); + } + } + } + + return result; + + function calculateRegionAverage(startRow, startCol) { + let sum = 0; + for (let i = startRow; i < startRow + 3; i++) { + for (let j = startCol; j < startCol + 3; j++) { + sum += image[i][j]; + } + } + return Math.floor(sum / 9); + } + + function isValidRegion(startRow, startCol) { + const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]; + + for (let i = startRow; i < startRow + 3; i++) { + for (let j = startCol; j < startCol + 3; j++) { + for (const [dr, dc] of directions) { + const newRow = i + dr; + const newCol = j + dc; + + if (newRow >= startRow && newRow < startRow + 3 + && newCol >= startCol && newCol < startCol + 3) { + if (Math.abs(image[i][j] - image[newRow][newCol]) > threshold) { + return false; + } + } + } + } + } + return true; + } +}; diff --git a/solutions/3032-count-numbers-with-unique-digits-ii.js b/solutions/3032-count-numbers-with-unique-digits-ii.js new file mode 100644 index 00000000..b332bfaf --- /dev/null +++ b/solutions/3032-count-numbers-with-unique-digits-ii.js @@ -0,0 +1,40 @@ +/** + * 3032. Count Numbers With Unique Digits II + * https://leetcode.com/problems/count-numbers-with-unique-digits-ii/ + * Difficulty: Easy + * + * Given two positive integers a and b, return the count of numbers having unique digits + * in the range [a, b] (inclusive). + */ + +/** + * @param {number} a + * @param {number} b + * @return {number} + */ +var numberCount = function(a, b) { + let result = 0; + + for (let number = a; number <= b; number++) { + if (hasUniqueDigits(number)) { + result++; + } + } + + return result; + + function hasUniqueDigits(number) { + const set = new Set(); + + while (number > 0) { + const digit = number % 10; + if (set.has(digit)) { + return false; + } + set.add(digit); + number = Math.floor(number / 10); + } + + return true; + } +}; diff --git a/solutions/3033-modify-the-matrix.js b/solutions/3033-modify-the-matrix.js new file mode 100644 index 00000000..6d8b09ab --- /dev/null +++ b/solutions/3033-modify-the-matrix.js @@ -0,0 +1,38 @@ +/** + * 3033. Modify the Matrix + * https://leetcode.com/problems/modify-the-matrix/ + * Difficulty: Easy + * + * Given a 0-indexed m x n integer matrix matrix, create a new 0-indexed matrix called answer. + * Make answer equal to matrix, then replace each element with the value -1 with the maximum + * element in its respective column. + * + * Return the matrix answer. + */ + +/** + * @param {number[][]} matrix + * @return {number[][]} + */ +var modifiedMatrix = function(matrix) { + const m = matrix.length; + const n = matrix[0].length; + const result = matrix.map(row => [...row]); + const colMaxes = new Array(n).fill(-Infinity); + + for (let j = 0; j < n; j++) { + for (let i = 0; i < m; i++) { + colMaxes[j] = Math.max(colMaxes[j], matrix[i][j]); + } + } + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + if (result[i][j] === -1) { + result[i][j] = colMaxes[j]; + } + } + } + + return result; +}; diff --git a/solutions/3034-number-of-subarrays-that-match-a-pattern-i.js b/solutions/3034-number-of-subarrays-that-match-a-pattern-i.js new file mode 100644 index 00000000..d95a2c36 --- /dev/null +++ b/solutions/3034-number-of-subarrays-that-match-a-pattern-i.js @@ -0,0 +1,41 @@ +/** + * 3034. Number of Subarrays That Match a Pattern I + * https://leetcode.com/problems/number-of-subarrays-that-match-a-pattern-i/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums of size n, and a 0-indexed integer array pattern + * of size m consisting of integers -1, 0, and 1. + * + * A subarray nums[i..j] of size m + 1 is said to match the pattern if the following conditions + * hold for each element pattern[k]: + * - nums[i + k + 1] > nums[i + k] if pattern[k] == 1. + * - nums[i + k + 1] == nums[i + k] if pattern[k] == 0. + * - nums[i + k + 1] < nums[i + k] if pattern[k] == -1. + * + * Return the count of subarrays in nums that match the pattern. + */ + +/** + * @param {number[]} nums + * @param {number[]} pattern + * @return {number} + */ +var countMatchingSubarrays = function(nums, pattern) { + let result = 0; + const m = pattern.length; + + for (let i = 0; i <= nums.length - m - 1; i++) { + let isMatch = true; + for (let j = 0; j < m; j++) { + const diff = nums[i + j + 1] - nums[i + j]; + if ((pattern[j] === 1 && diff <= 0) || (pattern[j] === 0 && diff !== 0) + || (pattern[j] === -1 && diff >= 0)) { + isMatch = false; + break; + } + } + if (isMatch) result++; + } + + return result; +}; diff --git a/solutions/3035-maximum-palindromes-after-operations.js b/solutions/3035-maximum-palindromes-after-operations.js new file mode 100644 index 00000000..8897c387 --- /dev/null +++ b/solutions/3035-maximum-palindromes-after-operations.js @@ -0,0 +1,46 @@ +/** + * 3035. Maximum Palindromes After Operations + * https://leetcode.com/problems/maximum-palindromes-after-operations/ + * Difficulty: Medium + * + * You are given a 0-indexed string array words having length n and containing 0-indexed strings. + * + * You are allowed to perform the following operation any number of times (including zero): + * - Choose integers i, j, x, and y such that 0 <= i, j < n, 0 <= x < words[i].length, + * 0 <= y < words[j].length, and swap the characters words[i][x] and words[j][y]. + * + * Return an integer denoting the maximum number of palindromes words can contain, after performing + * some operations. + * + * Note: i and j may be equal during an operation. + */ + +/** + * @param {string[]} words + * @return {number} + */ +var maxPalindromesAfterOperations = function(words) { + const charCount = new Array(26).fill(0); + let pairCount = 0; + let result = 0; + + for (const word of words) { + for (const char of word) { + charCount[char.charCodeAt(0) - 97]++; + } + } + + for (const count of charCount) { + pairCount += Math.floor(count / 2); + } + + const lengths = words.map(word => word.length).sort((a, b) => a - b); + for (const length of lengths) { + if (pairCount >= Math.floor(length / 2)) { + pairCount -= Math.floor(length / 2); + result++; + } + } + + return result; +}; diff --git a/solutions/3037-find-pattern-in-infinite-stream-ii.js b/solutions/3037-find-pattern-in-infinite-stream-ii.js new file mode 100644 index 00000000..f1c22607 --- /dev/null +++ b/solutions/3037-find-pattern-in-infinite-stream-ii.js @@ -0,0 +1,74 @@ +/** + * 3037. Find Pattern in Infinite Stream II + * https://leetcode.com/problems/find-pattern-in-infinite-stream-ii/ + * Difficulty: Hard + * + * You are given a binary array pattern and an object stream of class InfiniteStream + * representing a 0-indexed infinite stream of bits. + * + * The class InfiniteStream contains the following function: + * - int next(): Reads a single bit (which is either 0 or 1) from the stream and returns it. + * + * Return the first starting index where the pattern matches the bits read from the stream. + * For example, if the pattern is [1, 0], the first match is the highlighted part in the + * stream [0, 1, 0, 1, ...]. + */ + +/** + * Definition for an infinite stream. + * class InfiniteStream { + * @param {number[]} bits + * constructor(bits); + * + * @return {number} + * next(); + * } + */ +/** + * @param {InfiniteStream} stream + * @param {number[]} pattern + * @return {number} + */ +var findPattern = function(stream, pattern) { + const patternLength = pattern.length; + const failureFunction = buildFailureFunction(pattern); + let streamIndex = 0; + let patternIndex = 0; + + while (true) { + const streamBit = stream.next(); + + while (patternIndex > 0 && pattern[patternIndex] !== streamBit) { + patternIndex = failureFunction[patternIndex - 1]; + } + + if (pattern[patternIndex] === streamBit) { + patternIndex++; + } + + if (patternIndex === patternLength) { + return streamIndex - patternLength + 1; + } + + streamIndex++; + } + + function buildFailureFunction(pattern) { + const failure = new Array(pattern.length).fill(0); + let prefixLength = 0; + + for (let suffixEnd = 1; suffixEnd < pattern.length; suffixEnd++) { + while (prefixLength > 0 && pattern[prefixLength] !== pattern[suffixEnd]) { + prefixLength = failure[prefixLength - 1]; + } + + if (pattern[prefixLength] === pattern[suffixEnd]) { + prefixLength++; + } + + failure[suffixEnd] = prefixLength; + } + + return failure; + } +}; diff --git a/solutions/3038-maximum-number-of-operations-with-the-same-score-i.js b/solutions/3038-maximum-number-of-operations-with-the-same-score-i.js new file mode 100644 index 00000000..d1e825cb --- /dev/null +++ b/solutions/3038-maximum-number-of-operations-with-the-same-score-i.js @@ -0,0 +1,33 @@ +/** + * 3038. Maximum Number of Operations With the Same Score I + * https://leetcode.com/problems/maximum-number-of-operations-with-the-same-score-i/ + * Difficulty: Easy + * + * You are given an array of integers nums. Consider the following operation: + * - Delete the first two elements nums and define the score of the operation as the sum of + * these two elements. + * + * You can perform this operation until nums contains fewer than two elements. Additionally, + * the same score must be achieved in all operations. + * + * Return the maximum number of operations you can perform. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxOperations = function(nums) { + let result = 0; + const targetScore = nums[0] + nums[1]; + + for (let i = 0; i < nums.length - 1; i += 2) { + if (nums[i] + nums[i + 1] === targetScore) { + result++; + } else { + break; + } + } + + return result; +}; diff --git a/solutions/3039-apply-operations-to-make-string-empty.js b/solutions/3039-apply-operations-to-make-string-empty.js new file mode 100644 index 00000000..82cc2e56 --- /dev/null +++ b/solutions/3039-apply-operations-to-make-string-empty.js @@ -0,0 +1,45 @@ +/** + * 3039. Apply Operations to Make String Empty + * https://leetcode.com/problems/apply-operations-to-make-string-empty/ + * Difficulty: Medium + * + * You are given a string s. + * + * Consider performing the following operation until s becomes empty: + * - For every alphabet character from 'a' to 'z', remove the first occurrence of that + * character in s (if it exists). + * + * For example, let initially s = "aabcbbca". We do the following operations: + * - Remove the underlined characters s = "aabcbbca". The resulting string is s = "abbca". + * - Remove the underlined characters s = "abbca". The resulting string is s = "ba". + * - Remove the underlined characters s = "ba". The resulting string is s = "". + * + * Return the value of the string s right before applying the last operation. In the + * example above, answer is "ba". + */ + +/** + * @param {string} s + * @return {string} + */ +var lastNonEmptyString = function(s) { + const charCount = new Array(26).fill(0); + let maxFrequency = 0; + + for (const char of s) { + const index = char.charCodeAt(0) - 97; + charCount[index]++; + maxFrequency = Math.max(maxFrequency, charCount[index]); + } + + let result = ''; + for (let i = s.length - 1; i >= 0; i--) { + const index = s.charCodeAt(i) - 97; + if (charCount[index] === maxFrequency) { + result = s[i] + result; + charCount[index]--; + } + } + + return result; +}; diff --git a/solutions/3043-find-the-length-of-the-longest-common-prefix.js b/solutions/3043-find-the-length-of-the-longest-common-prefix.js new file mode 100644 index 00000000..13ad3b97 --- /dev/null +++ b/solutions/3043-find-the-length-of-the-longest-common-prefix.js @@ -0,0 +1,50 @@ +/** + * 3043. Find the Length of the Longest Common Prefix + * https://leetcode.com/problems/find-the-length-of-the-longest-common-prefix/ + * Difficulty: Medium + * + * You are given two arrays with positive integers arr1 and arr2. + * + * A prefix of a positive integer is an integer formed by one or more of its digits, starting + * from its leftmost digit. For example, 123 is a prefix of the integer 12345, while 234 is not. + * + * A common prefix of two integers a and b is an integer c, such that c is a prefix of both a + * and b. For example, 5655359 and 56554 have common prefixes 565 and 5655 while 1223 and 43456 + * do not have a common prefix. + * + * You need to find the length of the longest common prefix between all pairs of integers (x, y) + * such that x belongs to arr1 and y belongs to arr2. + * + * Return the length of the longest common prefix among all pairs. If no common prefix exists + * among them, return 0. + */ + +/** + * @param {number[]} arr1 + * @param {number[]} arr2 + * @return {number} + */ +var longestCommonPrefix = function(arr1, arr2) { + const prefixSet = new Set(); + let result = 0; + + for (const num of arr1) { + let prefix = num; + while (prefix > 0) { + prefixSet.add(prefix); + prefix = Math.floor(prefix / 10); + } + } + + for (const num of arr2) { + let prefix = num; + while (prefix > 0) { + if (prefixSet.has(prefix)) { + result = Math.max(result, String(prefix).length); + } + prefix = Math.floor(prefix / 10); + } + } + + return result; +}; diff --git a/solutions/3044-most-frequent-prime.js b/solutions/3044-most-frequent-prime.js new file mode 100644 index 00000000..cde4f2e9 --- /dev/null +++ b/solutions/3044-most-frequent-prime.js @@ -0,0 +1,68 @@ +/** + * 3044. Most Frequent Prime + * https://leetcode.com/problems/most-frequent-prime/ + * Difficulty: Medium + * + * You are given a m x n 0-indexed 2D matrix mat. From every cell, you can create numbers + * in the following way: + * - There could be at most 8 paths from the cells namely: east, south-east, south, south-west, + * west, north-west, north, and north-east. + * - Select a path from them and append digits in this path to the number being formed by + * traveling in this direction. + * - Note that numbers are generated at every step, for example, if the digits along the path + * are 1, 9, 1, then there will be three numbers generated along the way: 1, 19, 191. + * + * Return the most frequent prime number greater than 10 out of all the numbers created by + * traversing the matrix or -1 if no such prime number exists. If there are multiple prime + * numbers with the highest frequency, then return the largest among them. + * + * Note: It is invalid to change the direction during the move. + */ + +/** + * @param {number[][]} mat + * @return {number} + */ +var mostFrequentPrime = function(mat) { + const m = mat.length; + const n = mat[0].length; + const frequency = new Map(); + const directions = [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]; + + const isPrime = num => { + if (num <= 1) return false; + for (let i = 2; i * i <= num; i++) { + if (num % i === 0) return false; + } + return true; + }; + + for (let i = 0; i < m; i++) { + for (let j = 0; j < n; j++) { + for (const [dx, dy] of directions) { + let x = i; + let y = j; + let num = 0; + while (x >= 0 && x < m && y >= 0 && y < n) { + num = num * 10 + mat[x][y]; + if (num > 10 && isPrime(num)) { + frequency.set(num, (frequency.get(num) || 0) + 1); + } + x += dx; + y += dy; + } + } + } + } + + let maxFreq = 0; + let result = -1; + for (const [num, freq] of frequency) { + if (freq > maxFreq || (freq === maxFreq && num > result)) { + maxFreq = freq; + result = num; + } + } + + return result; +}; diff --git a/solutions/3046-split-the-array.js b/solutions/3046-split-the-array.js new file mode 100644 index 00000000..14f28868 --- /dev/null +++ b/solutions/3046-split-the-array.js @@ -0,0 +1,28 @@ +/** + * 3046. Split the Array + * https://leetcode.com/problems/split-the-array/ + * Difficulty: Easy + * + * You are given an integer array nums of even length. You have to split the array into two + * parts nums1 and nums2 such that: + * - nums1.length == nums2.length == nums.length / 2. + * - nums1 should contain distinct elements. + * - nums2 should also contain distinct elements. + * + * Return true if it is possible to split the array, and false otherwise. + */ + +/** + * @param {number[]} nums + * @return {boolean} + */ +var isPossibleToSplit = function(nums) { + const map = new Map(); + + for (const num of nums) { + map.set(num, (map.get(num) || 0) + 1); + if (map.get(num) > 2) return false; + } + + return true; +}; diff --git a/solutions/3047-find-the-largest-area-of-square-inside-two-rectangles.js b/solutions/3047-find-the-largest-area-of-square-inside-two-rectangles.js new file mode 100644 index 00000000..7075570e --- /dev/null +++ b/solutions/3047-find-the-largest-area-of-square-inside-two-rectangles.js @@ -0,0 +1,39 @@ +/** + * 3047. Find the Largest Area of Square Inside Two Rectangles + * https://leetcode.com/problems/find-the-largest-area-of-square-inside-two-rectangles/ + * Difficulty: Medium + * + * There exist n rectangles in a 2D plane with edges parallel to the x and y axis. You + * are given two 2D integer arrays bottomLeft and topRight where bottomLeft[i] = [a_i, b_i] + * and topRight[i] = [c_i, d_i] represent the bottom-left and top-right coordinates of the + * ith rectangle, respectively. + * + * You need to find the maximum area of a square that can fit inside the intersecting + * region of at least two rectangles. Return 0 if such a square does not exist. + */ + +/** + * @param {number[][]} bottomLeft + * @param {number[][]} topRight + * @return {number} + */ +var largestSquareArea = function(bottomLeft, topRight) { + const n = bottomLeft.length; + let maxSide = 0; + + for (let i = 0; i < n; i++) { + for (let j = i + 1; j < n; j++) { + const xLeft = Math.max(bottomLeft[i][0], bottomLeft[j][0]); + const yBottom = Math.max(bottomLeft[i][1], bottomLeft[j][1]); + const xRight = Math.min(topRight[i][0], topRight[j][0]); + const yTop = Math.min(topRight[i][1], topRight[j][1]); + + if (xLeft < xRight && yBottom < yTop) { + const side = Math.min(xRight - xLeft, yTop - yBottom); + maxSide = Math.max(maxSide, side); + } + } + } + + return maxSide * maxSide; +}; diff --git a/solutions/3062-winner-of-the-linked-list-game.js b/solutions/3062-winner-of-the-linked-list-game.js new file mode 100644 index 00000000..1576fcfe --- /dev/null +++ b/solutions/3062-winner-of-the-linked-list-game.js @@ -0,0 +1,57 @@ +/** + * 3062. Winner of the Linked List Game + * https://leetcode.com/problems/winner-of-the-linked-list-game/ + * Difficulty: Easy + * + * You are given the head of a linked list of even length containing integers. + * + * Each odd-indexed node contains an odd integer and each even-indexed node contains an + * even integer. + * + * We call each even-indexed node and its next node a pair, e.g., the nodes with indices + * 0 and 1 are a pair, the nodes with indices 2 and 3 are a pair, and so on. + * + * For every pair, we compare the values of the nodes in the pair: + * - If the odd-indexed node is higher, the "Odd" team gets a point. + * - If the even-indexed node is higher, the "Even" team gets a point. + * + * Return the name of the team with the higher points, if the points are equal, return "Tie". + */ + +/** + * 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 {string} + */ +var gameResult = function(head) { + let evenScore = 0; + let oddScore = 0; + let currentNode = head; + + while (currentNode && currentNode.next) { + const evenValue = currentNode.val; + const oddValue = currentNode.next.val; + + if (evenValue > oddValue) { + evenScore++; + } else if (oddValue > evenValue) { + oddScore++; + } + + currentNode = currentNode.next.next; + } + + if (evenScore > oddScore) { + return 'Even'; + } else if (oddScore > evenScore) { + return 'Odd'; + } else { + return 'Tie'; + } +}; diff --git a/solutions/3063-linked-list-frequency.js b/solutions/3063-linked-list-frequency.js new file mode 100644 index 00000000..6b6cf078 --- /dev/null +++ b/solutions/3063-linked-list-frequency.js @@ -0,0 +1,44 @@ +/** + * 3063. Linked List Frequency + * https://leetcode.com/problems/linked-list-frequency/ + * Difficulty: Easy + * + * Given the head of a linked list containing k distinct elements, return the head to a linked + * list of length k containing the frequency of each distinct element in the given linked list + * in any order. + */ + +/** + * 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} + */ +var frequenciesOfElements = function(head) { + const map = new Map(); + let currentNode = head; + + while (currentNode) { + map.set(currentNode.val, (map.get(currentNode.val) || 0) + 1); + currentNode = currentNode.next; + } + + const frequencies = Array.from(map.values()); + + if (frequencies.length === 0) return null; + + const resultHead = new ListNode(frequencies[0]); + let resultCurrent = resultHead; + + for (let i = 1; i < frequencies.length; i++) { + resultCurrent.next = new ListNode(frequencies[i]); + resultCurrent = resultCurrent.next; + } + + return resultHead; +}; diff --git a/solutions/3064-guess-the-number-using-bitwise-questions-i.js b/solutions/3064-guess-the-number-using-bitwise-questions-i.js new file mode 100644 index 00000000..95aa9b8a --- /dev/null +++ b/solutions/3064-guess-the-number-using-bitwise-questions-i.js @@ -0,0 +1,36 @@ +/** + * 3064. Guess the Number Using Bitwise Questions I + * https://leetcode.com/problems/guess-the-number-using-bitwise-questions-i/ + * Difficulty: Medium + * + * There is a number n that you have to find. + * + * There is also a pre-defined API int commonSetBits(int num), which returns the number of bits + * where both n and num are 1 in that position of their binary representation. In other words, + * it returns the number of set bits in n & num, where & is the bitwise AND operator. + * + * Return the number n. + */ + +/** + * Definition of commonSetBits API. + * @param {number} num + * @return {integer} + * var commonSetBits = function(num) {} + */ + +/** + * @return {number} + */ +var findNumber = function() { + let result = 0; + + for (let bitPosition = 0; bitPosition < 30; bitPosition++) { + const powerOfTwo = 1 << bitPosition; + if (commonSetBits(powerOfTwo) === 1) { + result |= powerOfTwo; + } + } + + return result; +}; diff --git a/solutions/3065-minimum-operations-to-exceed-threshold-value-i.js b/solutions/3065-minimum-operations-to-exceed-threshold-value-i.js new file mode 100644 index 00000000..53ae27ae --- /dev/null +++ b/solutions/3065-minimum-operations-to-exceed-threshold-value-i.js @@ -0,0 +1,27 @@ +/** + * 3065. Minimum Operations to Exceed Threshold Value I + * https://leetcode.com/problems/minimum-operations-to-exceed-threshold-value-i/ + * Difficulty: Easy + * + * You are given a 0-indexed integer array nums, and an integer k. + * + * In one operation, you can remove one occurrence of the smallest element of nums. + * + * Return the minimum number of operations needed so that all elements of the array are greater + * than or equal to k. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minOperations = function(nums, k) { + let operations = 0; + + for (const num of nums) { + if (num < k) operations++; + } + + return operations; +}; diff --git a/solutions/3067-count-pairs-of-connectable-servers-in-a-weighted-tree-network.js b/solutions/3067-count-pairs-of-connectable-servers-in-a-weighted-tree-network.js new file mode 100644 index 00000000..cfcb71ff --- /dev/null +++ b/solutions/3067-count-pairs-of-connectable-servers-in-a-weighted-tree-network.js @@ -0,0 +1,64 @@ +/** + * 3067. Count Pairs of Connectable Servers in a Weighted Tree Network + * https://leetcode.com/problems/count-pairs-of-connectable-servers-in-a-weighted-tree-network/ + * Difficulty: Medium + * + * You are given an unrooted weighted tree with n vertices representing servers numbered from 0 + * to n - 1, an array edges where edges[i] = [ai, bi, weighti] represents a bidirectional edge + * between vertices ai and bi of weight weighti. You are also given an integer signalSpeed. + * + * Two servers a and b are connectable through a server c if: + * - a < b, a != c and b != c. + * - The distance from c to a is divisible by signalSpeed. + * - The distance from c to b is divisible by signalSpeed. + * - The path from c to b and the path from c to a do not share any edges. + * + * Return an integer array count of length n where count[i] is the number of server pairs that are + * connectable through the server i. + */ + +/** + * @param {number[][]} edges + * @param {number} signalSpeed + * @return {number[]} + */ +var countPairsOfConnectableServers = function(edges, signalSpeed) { + const n = edges.length + 1; + const graph = Array.from({ length: n }, () => []); + for (const [u, v, w] of edges) { + graph[u].push([v, w]); + graph[v].push([u, w]); + } + + const result = new Array(n).fill(0); + for (let i = 0; i < n; i++) { + result[i] = countValidPairs(i); + } + return result; + + function countValidPairs(root) { + function dfs(node, parent, distance) { + let count = distance % signalSpeed === 0 ? 1 : 0; + for (const [next, weight] of graph[node]) { + if (next !== parent) { + count += dfs(next, node, distance + weight); + } + } + return count; + } + + let totalPairs = 0; + const counts = []; + for (const [child, weight] of graph[root]) { + const count = dfs(child, root, weight); + counts.push(count); + } + + let sum = 0; + for (const count of counts) { + totalPairs += sum * count; + sum += count; + } + return totalPairs; + } +}; diff --git a/solutions/3069-distribute-elements-into-two-arrays-i.js b/solutions/3069-distribute-elements-into-two-arrays-i.js new file mode 100644 index 00000000..ed2f0d96 --- /dev/null +++ b/solutions/3069-distribute-elements-into-two-arrays-i.js @@ -0,0 +1,37 @@ +/** + * 3069. Distribute Elements Into Two Arrays I + * https://leetcode.com/problems/distribute-elements-into-two-arrays-i/ + * Difficulty: Easy + * + * You are given a 1-indexed array of distinct integers nums of length n. + * + * You need to distribute all the elements of nums between two arrays arr1 and arr2 using n + * operations. In the first operation, append nums[1] to arr1. In the second operation, + * append nums[2] to arr2. Afterwards, in the ith operation: + * - If the last element of arr1 is greater than the last element of arr2, append nums[i] to arr1. + * Otherwise, append nums[i] to arr2. + * + * The array result is formed by concatenating the arrays arr1 and arr2. For example, if + * arr1 == [1,2,3] and arr2 == [4,5,6], then result = [1,2,3,4,5,6]. + * + * Return the array result. + */ + +/** + * @param {number[]} nums + * @return {number[]} + */ +var resultArray = function(nums) { + const arr1 = [nums[0]]; + const arr2 = [nums[1]]; + + for (let i = 2; i < nums.length; i++) { + if (arr1[arr1.length - 1] > arr2[arr2.length - 1]) { + arr1.push(nums[i]); + } else { + arr2.push(nums[i]); + } + } + + return [...arr1, ...arr2]; +}; diff --git a/solutions/3070-count-submatrices-with-top-left-element-and-sum-less-than-k.js b/solutions/3070-count-submatrices-with-top-left-element-and-sum-less-than-k.js new file mode 100644 index 00000000..93cd1cb1 --- /dev/null +++ b/solutions/3070-count-submatrices-with-top-left-element-and-sum-less-than-k.js @@ -0,0 +1,39 @@ +/** + * 3070. Count Submatrices with Top-Left Element and Sum Less Than k + * https://leetcode.com/problems/count-submatrices-with-top-left-element-and-sum-less-than-k/ + * Difficulty: Medium + * + * You are given a 0-indexed integer matrix grid and an integer k. + * + * Return the number of submatrices that contain the top-left element of the grid, and have a sum + * less than or equal to k. + */ + +/** + * @param {number[][]} grid + * @param {number} k + * @return {number} + */ +var countSubmatrices = function(grid, k) { + const rows = grid.length; + const cols = grid[0].length; + const prefixSum = Array.from({ length: rows + 1 }, () => new Array(cols + 1).fill(0)); + + for (let i = 1; i <= rows; i++) { + for (let j = 1; j <= cols; j++) { + prefixSum[i][j] = grid[i-1][j-1] + prefixSum[i-1][j] + + prefixSum[i][j-1] - prefixSum[i-1][j-1]; + } + } + + let result = 0; + for (let i = 1; i <= rows; i++) { + for (let j = 1; j <= cols; j++) { + if (prefixSum[i][j] <= k) { + result++; + } + } + } + + return result; +}; diff --git a/solutions/3071-minimum-operations-to-write-the-letter-y-on-a-grid.js b/solutions/3071-minimum-operations-to-write-the-letter-y-on-a-grid.js new file mode 100644 index 00000000..15ad3700 --- /dev/null +++ b/solutions/3071-minimum-operations-to-write-the-letter-y-on-a-grid.js @@ -0,0 +1,63 @@ +/** + * 3071. Minimum Operations to Write the Letter Y on a Grid + * https://leetcode.com/problems/minimum-operations-to-write-the-letter-y-on-a-grid/ + * Difficulty: Medium + * + * You are given a 0-indexed n x n grid where n is odd, and grid[r][c] is 0, 1, or 2. + * + * We say that a cell belongs to the Letter Y if it belongs to one of the following: + * - The diagonal starting at the top-left cell and ending at the center cell of the grid. + * - The diagonal starting at the top-right cell and ending at the center cell of the grid. + * - The vertical line starting at the center cell and ending at the bottom border of the grid. + * + * The Letter Y is written on the grid if and only if: + * - All values at cells belonging to the Y are equal. + * - All values at cells not belonging to the Y are equal. + * - The values at cells belonging to the Y are different from the values at cells not belonging + * to the Y. + * + * Return the minimum number of operations needed to write the letter Y on the grid given that + * in one operation you can change the value at any cell to 0, 1, or 2. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var minimumOperationsToWriteY = function(grid) { + const n = grid.length; + const center = Math.floor(n / 2); + const yCells = []; + const nonYCells = []; + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + if ((i === j && i <= center) || (i === n - 1 - j && i <= center) + || (j === center && i >= center)) { + yCells.push(grid[i][j]); + } else { + nonYCells.push(grid[i][j]); + } + } + } + + const yCounts = [0, 0, 0]; + const nonYCounts = [0, 0, 0]; + + for (const val of yCells) yCounts[val]++; + for (const val of nonYCells) nonYCounts[val]++; + + let minOperations = Infinity; + + for (let yVal = 0; yVal <= 2; yVal++) { + for (let nonYVal = 0; nonYVal <= 2; nonYVal++) { + if (yVal !== nonYVal) { + const yOps = yCells.length - yCounts[yVal]; + const nonYOps = nonYCells.length - nonYCounts[nonYVal]; + minOperations = Math.min(minOperations, yOps + nonYOps); + } + } + } + + return minOperations; +}; diff --git a/solutions/3073-maximum-increasing-triplet-value.js b/solutions/3073-maximum-increasing-triplet-value.js new file mode 100644 index 00000000..856c217c --- /dev/null +++ b/solutions/3073-maximum-increasing-triplet-value.js @@ -0,0 +1,50 @@ +/** + * 3073. Maximum Increasing Triplet Value + * https://leetcode.com/problems/maximum-increasing-triplet-value/ + * Difficulty: Medium + * + * Given an array nums, return the maximum value of a triplet (i, j, k) such that i < j < k + * and nums[i] < nums[j] < nums[k]. + * + * The value of a triplet (i, j, k) is nums[i] - nums[j] + nums[k]. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maximumTripletValue = function(nums) { + const n = nums.length; + const maxRight = new Array(n).fill(-1); + let currentMax = 0; + let result = 0; + + for (let i = n - 1; i >= 0; i--) { + if (nums[i] >= currentMax) { + currentMax = nums[i]; + } else { + maxRight[i] = currentMax; + } + } + + const sortedIndices = Array.from({ length: n }, (_, i) => i) + .sort((a, b) => nums[a] - nums[b] || b - a); + + const stack = []; + + for (const currentIndex of sortedIndices) { + while (stack.length > 0 && stack[stack.length - 1] > currentIndex) { + stack.pop(); + } + + if (stack.length > 0 && maxRight[currentIndex] >= 0) { + const leftIndex = stack[stack.length - 1]; + const tripletValue = nums[leftIndex] - nums[currentIndex] + maxRight[currentIndex]; + result = Math.max(result, tripletValue); + } + + stack.push(currentIndex); + } + + return result; +}; diff --git a/solutions/3074-apple-redistribution-into-boxes.js b/solutions/3074-apple-redistribution-into-boxes.js new file mode 100644 index 00000000..27e3f17a --- /dev/null +++ b/solutions/3074-apple-redistribution-into-boxes.js @@ -0,0 +1,38 @@ +/** + * 3074. Apple Redistribution into Boxes + * https://leetcode.com/problems/apple-redistribution-into-boxes/ + * Difficulty: Easy + * + * You are given an array apple of size n and an array capacity of size m. + * + * There are n packs where the ith pack contains apple[i] apples. There are m boxes as well, + * and the ith box has a capacity of capacity[i] apples. + * + * Return the minimum number of boxes you need to select to redistribute these n packs of + * apples into boxes. + * + * Note that, apples from the same pack can be distributed into different boxes. + */ + +/** + * @param {number[]} apple + * @param {number[]} capacity + * @return {number} + */ +var minimumBoxes = function(apple, capacity) { + const totalApples = apple.reduce((sum, num) => sum + num, 0); + const sortedCapacities = capacity.sort((a, b) => b - a); + let currentCapacity = 0; + let result = 0; + + for (const box of sortedCapacities) { + if (currentCapacity < totalApples) { + currentCapacity += box; + result++; + } else { + break; + } + } + + return result; +}; diff --git a/solutions/3075-maximize-happiness-of-selected-children.js b/solutions/3075-maximize-happiness-of-selected-children.js new file mode 100644 index 00000000..853a0851 --- /dev/null +++ b/solutions/3075-maximize-happiness-of-selected-children.js @@ -0,0 +1,35 @@ +/** + * 3075. Maximize Happiness of Selected Children + * https://leetcode.com/problems/maximize-happiness-of-selected-children/ + * Difficulty: Medium + * + * You are given an array happiness of length n, and a positive integer k. + * + * There are n children standing in a queue, where the ith child has happiness value + * happiness[i]. You want to select k children from these n children in k turns. + * + * In each turn, when you select a child, the happiness value of all the children that + * have not been selected till now decreases by 1. Note that the happiness value cannot + * become negative and gets decremented only if it is positive. + * + * Return the maximum sum of the happiness values of the selected children you can + * achieve by selecting k children. + */ + +/** + * @param {number[]} happiness + * @param {number} k + * @return {number} + */ +var maximumHappinessSum = function(happiness, k) { + const sortedHappiness = happiness.sort((a, b) => b - a); + let result = 0; + + for (let i = 0; i < k; i++) { + const currentHappiness = sortedHappiness[i] - i; + if (currentHappiness <= 0) break; + result += currentHappiness; + } + + return result; +}; diff --git a/solutions/3076-shortest-uncommon-substring-in-an-array.js b/solutions/3076-shortest-uncommon-substring-in-an-array.js new file mode 100644 index 00000000..60559014 --- /dev/null +++ b/solutions/3076-shortest-uncommon-substring-in-an-array.js @@ -0,0 +1,56 @@ +/** + * 3076. Shortest Uncommon Substring in an Array + * https://leetcode.com/problems/shortest-uncommon-substring-in-an-array/ + * Difficulty: Medium + * + * You are given an array arr of size n consisting of non-empty strings. + * + * Find a string array answer of size n such that: + * - answer[i] is the shortest substring of arr[i] that does not occur as a substring in any + * other string in arr. If multiple such substrings exist, answer[i] should be the + * lexicographically smallest. And if no such substring exists, answer[i] should be an + * empty string. + * + * Return the array answer. + */ + +/** + * @param {string[]} arr + * @return {string[]} + */ +var shortestSubstrings = function(arr) { + const n = arr.length; + const result = new Array(n).fill(''); + + for (let i = 0; i < n; i++) { + const str = arr[i]; + let minLen = Infinity; + let minSubstr = ''; + + for (let len = 1; len <= str.length; len++) { + for (let start = 0; start <= str.length - len; start++) { + const substr = str.slice(start, start + len); + if (isUnique(substr, i)) { + if (len < minLen || (len === minLen && substr < minSubstr)) { + minLen = len; + minSubstr = substr; + } + } + } + if (minSubstr) break; + } + + result[i] = minSubstr; + } + + return result; + + function isUnique(substr, strIdx) { + for (let i = 0; i < n; i++) { + if (i !== strIdx && arr[i].includes(substr)) { + return false; + } + } + return true; + } +}; diff --git a/solutions/3078-match-alphanumerical-pattern-in-matrix-i.js b/solutions/3078-match-alphanumerical-pattern-in-matrix-i.js new file mode 100644 index 00000000..cc5fe605 --- /dev/null +++ b/solutions/3078-match-alphanumerical-pattern-in-matrix-i.js @@ -0,0 +1,86 @@ +/** + * 3078. Match Alphanumerical Pattern in Matrix I + * https://leetcode.com/problems/match-alphanumerical-pattern-in-matrix-i/ + * Difficulty: Medium + * + * You are given a 2D integer matrix board and a 2D character matrix pattern. + * Where 0 <= board[r][c] <= 9 and each element of pattern is either a digit or a + * lowercase English letter. + * + * Your task is to find a submatrix of board that matches pattern. + * + * An integer matrix part matches pattern if we can replace cells containing letters in + * pattern with some digits (each distinct letter with a unique digit) in such a way that + * the resulting matrix becomes identical to the integer matrix part. In other words, + * - The matrices have identical dimensions. + * - If pattern[r][c] is a digit, then part[r][c] must be the same digit. + * - If pattern[r][c] is a letter x: + * - For every pattern[i][j] == x, part[i][j] must be the same as part[r][c]. + * - For every pattern[i][j] != x, part[i][j] must be different than part[r][c]. + * + * Return an array of length 2 containing the row number and column number of the upper-left + * corner of a submatrix of board which matches pattern. If there is more than one such submatrix, + * return the coordinates of the submatrix with the lowest row index, and in case there is still + * a tie, return the coordinates of the submatrix with the lowest column index. If there are no + * suitable answers, return [-1, -1]. + */ + +/** + * @param {number[][]} board + * @param {string[]} pattern + * @return {number[]} + */ +var findPattern = function(board, pattern) { + const boardRows = board.length; + const boardCols = board[0].length; + const patternRows = pattern.length; + const patternCols = pattern[0].length; + + for (let startRow = 0; startRow <= boardRows - patternRows; startRow++) { + for (let startCol = 0; startCol <= boardCols - patternCols; startCol++) { + if (isPatternMatch(board, pattern, startRow, startCol)) { + return [startRow, startCol]; + } + } + } + + return [-1, -1]; + + function isPatternMatch(board, pattern, startRow, startCol) { + const letterToDigit = new Map(); + const digitToLetter = new Map(); + const usedDigits = new Set(); + + for (let patternRow = 0; patternRow < pattern.length; patternRow++) { + for (let patternCol = 0; patternCol < pattern[0].length; patternCol++) { + const patternChar = pattern[patternRow][patternCol]; + const boardDigit = board[startRow + patternRow][startCol + patternCol]; + + if (isDigit(patternChar)) { + if (parseInt(patternChar) !== boardDigit) { + return false; + } + } else { + if (letterToDigit.has(patternChar)) { + if (letterToDigit.get(patternChar) !== boardDigit) { + return false; + } + } else { + if (usedDigits.has(boardDigit) || digitToLetter.has(boardDigit)) { + return false; + } + letterToDigit.set(patternChar, boardDigit); + digitToLetter.set(boardDigit, patternChar); + usedDigits.add(boardDigit); + } + } + } + } + + return true; + } + + function isDigit(char) { + return char >= '0' && char <= '9'; + } +}; diff --git a/solutions/3079-find-the-sum-of-encrypted-integers.js b/solutions/3079-find-the-sum-of-encrypted-integers.js new file mode 100644 index 00000000..8bdaf881 --- /dev/null +++ b/solutions/3079-find-the-sum-of-encrypted-integers.js @@ -0,0 +1,41 @@ +/** + * 3079. Find the Sum of Encrypted Integers + * https://leetcode.com/problems/find-the-sum-of-encrypted-integers/ + * Difficulty: Easy + * + * You are given an integer array nums containing positive integers. We define a function + * encrypt such that encrypt(x) replaces every digit in x with the largest digit in x. + * For example, encrypt(523) = 555 and encrypt(213) = 333. + * + * Return the sum of encrypted elements. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var sumOfEncryptedInt = function(nums) { + let result = 0; + + for (const num of nums) { + let maxDigit = 0; + let temp = num; + let digitCount = 0; + + while (temp > 0) { + maxDigit = Math.max(maxDigit, temp % 10); + temp = Math.floor(temp / 10); + digitCount++; + } + + let encrypted = 0; + while (digitCount > 0) { + encrypted = encrypted * 10 + maxDigit; + digitCount--; + } + + result += encrypted; + } + + return result; +}; diff --git a/solutions/3083-existence-of-a-substring-in-a-string-and-its-reverse.js b/solutions/3083-existence-of-a-substring-in-a-string-and-its-reverse.js new file mode 100644 index 00000000..8af3eb50 --- /dev/null +++ b/solutions/3083-existence-of-a-substring-in-a-string-and-its-reverse.js @@ -0,0 +1,26 @@ +/** + * 3083. Existence of a Substring in a String and Its Reverse + * https://leetcode.com/problems/existence-of-a-substring-in-a-string-and-its-reverse/ + * Difficulty: Easy + * + * Given a string s, find any substring of length 2 which is also present in the reverse of s. + * + * Return true if such a substring exists, and false otherwise. + */ + +/** + * @param {string} s + * @return {boolean} + */ +var isSubstringPresent = function(s) { + const reversed = s.split('').reverse().join(''); + + for (let i = 0; i < s.length - 1; i++) { + const substr = s.slice(i, i + 2); + if (reversed.includes(substr)) { + return true; + } + } + + return false; +}; diff --git a/solutions/3084-count-substrings-starting-and-ending-with-given-character.js b/solutions/3084-count-substrings-starting-and-ending-with-given-character.js new file mode 100644 index 00000000..be6b8bc2 --- /dev/null +++ b/solutions/3084-count-substrings-starting-and-ending-with-given-character.js @@ -0,0 +1,21 @@ +/** + * 3084. Count Substrings Starting and Ending with Given Character + * https://leetcode.com/problems/count-substrings-starting-and-ending-with-given-character/ + * Difficulty: Medium + * + * You are given a string s and a character c. Return the total number of substrings of s + * that start and end with c. + */ + +/** + * @param {string} s + * @param {character} c + * @return {number} + */ +var countSubstrings = function(s, c) { + let count = 0; + for (const char of s) { + if (char === c) count++; + } + return (count * (count + 1)) / 2; +}; diff --git a/solutions/3085-minimum-deletions-to-make-string-k-special.js b/solutions/3085-minimum-deletions-to-make-string-k-special.js new file mode 100644 index 00000000..98db902e --- /dev/null +++ b/solutions/3085-minimum-deletions-to-make-string-k-special.js @@ -0,0 +1,45 @@ +/** + * 3085. Minimum Deletions to Make String K-Special + * https://leetcode.com/problems/minimum-deletions-to-make-string-k-special/ + * Difficulty: Medium + * + * You are given a string word and an integer k. + * + * We consider word to be k-special if |freq(word[i]) - freq(word[j])| <= k for all indices i + * and j in the string. + * + * Here, freq(x) denotes the frequency of the character x in word, and |y| denotes the absolute + * value of y. + * + * Return the minimum number of characters you need to delete to make word k-special. + */ + +/** + * @param {string} word + * @param {number} k + * @return {number} + */ +var minimumDeletions = function(word, k) { + const freq = new Array(26).fill(0); + + for (const char of word) { + freq[char.charCodeAt(0) - 97]++; + } + + const counts = freq.filter(x => x > 0).sort((a, b) => a - b); + let minDeletions = Infinity; + for (let i = 0; i < counts.length; i++) { + let deletions = 0; + for (let j = 0; j < i; j++) { + deletions += counts[j]; + } + for (let j = i; j < counts.length; j++) { + if (counts[j] - counts[i] > k) { + deletions += counts[j] - (counts[i] + k); + } + } + minDeletions = Math.min(minDeletions, deletions); + } + + return minDeletions; +}; diff --git a/solutions/3088-make-string-anti-palindrome.js b/solutions/3088-make-string-anti-palindrome.js new file mode 100644 index 00000000..087bd89f --- /dev/null +++ b/solutions/3088-make-string-anti-palindrome.js @@ -0,0 +1,41 @@ +/** + * 3088. Make String Anti-palindrome + * https://leetcode.com/problems/make-string-anti-palindrome/ + * Difficulty: Hard + * + * We call a string s of even length n an anti-palindrome if for each index + * 0 <= i < n, s[i] != s[n - i - 1]. + * + * Given a string s, your task is to make s an anti-palindrome by doing any number of + * operations (including zero). + * + * In one operation, you can select two characters from s and swap them. + * + * Return the resulting string. If multiple strings meet the conditions, return the + * lexicographically smallest one. If it can't be made into an anti-palindrome, return "-1". + */ + +/** + * @param {string} s + * @return {string} + */ +var makeAntiPalindrome = function(s) { + const n = s.length; + const result = Array.from(s).sort(); + let leftIndex = Math.floor((n + 1) / 2); + let rightIndex = Math.floor((n + 1) / 2); + + while (rightIndex < n && result[rightIndex] === result[leftIndex]) { + rightIndex++; + } + while (result[leftIndex] === result[n - leftIndex - 1]) { + if (rightIndex === n) { + return '-1'; + } + [result[leftIndex], result[rightIndex]] = [result[rightIndex], result[leftIndex]]; + leftIndex++; + rightIndex++; + } + + return result.join(''); +}; diff --git a/solutions/3090-maximum-length-substring-with-two-occurrences.js b/solutions/3090-maximum-length-substring-with-two-occurrences.js new file mode 100644 index 00000000..84003cd8 --- /dev/null +++ b/solutions/3090-maximum-length-substring-with-two-occurrences.js @@ -0,0 +1,31 @@ +/** + * 3090. Maximum Length Substring With Two Occurrences + * https://leetcode.com/problems/maximum-length-substring-with-two-occurrences/ + * Difficulty: Easy + * + * Given a string s, return the maximum length of a substring such that it contains at most + * two occurrences of each character. + */ + +/** + * @param {string} s + * @return {number} + */ +var maximumLengthSubstring = function(s) { + let result = 0; + const map = new Map(); + + for (let left = 0, right = 0; right < s.length; right++) { + map.set(s[right], (map.get(s[right]) || 0) + 1); + + while (map.get(s[right]) > 2) { + map.set(s[left], map.get(s[left]) - 1); + if (map.get(s[left]) === 0) map.delete(s[left]); + left++; + } + + result = Math.max(result, right - left + 1); + } + + return result; +}; diff --git a/solutions/3091-apply-operations-to-make-sum-of-array-greater-than-or-equal-to-k.js b/solutions/3091-apply-operations-to-make-sum-of-array-greater-than-or-equal-to-k.js new file mode 100644 index 00000000..a1c50bd6 --- /dev/null +++ b/solutions/3091-apply-operations-to-make-sum-of-array-greater-than-or-equal-to-k.js @@ -0,0 +1,33 @@ +/** + * 3091. Apply Operations to Make Sum of Array Greater Than or Equal to k + * https://leetcode.com/problems/apply-operations-to-make-sum-of-array-greater-than-or-equal-to-k/ + * Difficulty: Medium + * + * You are given a positive integer k. Initially, you have an array nums = [1]. + * + * You can perform any of the following operations on the array any number of times (possibly zero): + * - Choose any element in the array and increase its value by 1. + * - Duplicate any element in the array and add it to the end of the array. + * + * Return the minimum number of operations required to make the sum of elements of the final array + * greater than or equal to k. + */ + +/** + * @param {number} k + * @return {number} + */ +var minOperations = function(k) { + if (k === 1) return 0; + + let result = Infinity; + for (let increments = 0; increments <= Math.ceil(Math.sqrt(k)); increments++) { + const value = 1 + increments; + const duplicates = Math.ceil(k / value) - 1; + if (duplicates >= 0) { + result = Math.min(result, increments + duplicates); + } + } + + return result; +}; diff --git a/solutions/3094-guess-the-number-using-bitwise-questions-ii.js b/solutions/3094-guess-the-number-using-bitwise-questions-ii.js new file mode 100644 index 00000000..e05bc390 --- /dev/null +++ b/solutions/3094-guess-the-number-using-bitwise-questions-ii.js @@ -0,0 +1,43 @@ +/** + * 3094. Guess the Number Using Bitwise Questions II + * https://leetcode.com/problems/guess-the-number-using-bitwise-questions-ii/ + * Difficulty: Medium + * + * There is a number n between 0 and 230 - 1 (both inclusive) that you have to find. + * + * There is a pre-defined API int commonBits(int num) that helps you with your mission. + * But here is the challenge, every time you call this function, n changes in some way. + * But keep in mind, that you have to find the initial value of n. + * + * commonBits(int num) acts as follows: + * - Calculate count which is the number of bits where both n and num have the same value + * in that position of their binary representation. + * - n = n XOR num + * - Return count. + * + * Return the number n. + * + * Note: In this world, all numbers are between 0 and 230 - 1 (both inclusive), thus for counting + * common bits, we see only the first 30 bits of those numbers. + */ + +/** + * Definition of commonBits API. + * @param {number} num + * @return {integer} + * var commonBits = function(num) {} + */ +/** + * @return {number} + */ +var findNumber = function() { + let result = 0; + + for (let bitMask = 1; bitMask < 1073741824; bitMask <<= 1) { + if (commonBits(bitMask) > commonBits(bitMask)) { + result |= bitMask; + } + } + + return result; +}; diff --git a/solutions/3095-shortest-subarray-with-or-at-least-k-i.js b/solutions/3095-shortest-subarray-with-or-at-least-k-i.js new file mode 100644 index 00000000..0f03aa97 --- /dev/null +++ b/solutions/3095-shortest-subarray-with-or-at-least-k-i.js @@ -0,0 +1,35 @@ +/** + * 3095. Shortest Subarray With OR at Least K I + * https://leetcode.com/problems/shortest-subarray-with-or-at-least-k-i/ + * Difficulty: Easy + * + * You are given an array nums of non-negative integers and an integer k. + * + * An array is called special if the bitwise OR of all of its elements is at least k. + * + * Return the length of the shortest special non-empty subarray of nums, or return -1 if + * no special subarray exists. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minimumSubarrayLength = function(nums, k) { + if (k === 0) return 1; + + let minLength = Infinity; + for (let start = 0; start < nums.length; start++) { + let orResult = 0; + for (let end = start; end < nums.length; end++) { + orResult |= nums[end]; + if (orResult >= k) { + minLength = Math.min(minLength, end - start + 1); + break; + } + } + } + + return minLength === Infinity ? -1 : minLength; +}; diff --git a/solutions/3097-shortest-subarray-with-or-at-least-k-ii.js b/solutions/3097-shortest-subarray-with-or-at-least-k-ii.js new file mode 100644 index 00000000..f85c9879 --- /dev/null +++ b/solutions/3097-shortest-subarray-with-or-at-least-k-ii.js @@ -0,0 +1,48 @@ +/** + * 3097. Shortest Subarray With OR at Least K II + * https://leetcode.com/problems/shortest-subarray-with-or-at-least-k-ii/ + * Difficulty: Medium + * + * You are given an array nums of non-negative integers and an integer k. + * + * An array is called special if the bitwise OR of all of its elements is at least k. + * + * Return the length of the shortest special non-empty subarray of nums, or return -1 if no + * special subarray exists. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minimumSubarrayLength = function(nums, k) { + if (k === 0) return 1; + + const bitCounts = new Array(32).fill(0); + let minLength = Infinity; + let orValue = 0; + let left = 0; + + for (let right = 0; right < nums.length; right++) { + const num = nums[right]; + for (let bit = 0; bit < 32; bit++) { + if (num & (1 << bit)) bitCounts[bit]++; + if (bitCounts[bit] > 0) orValue |= 1 << bit; + } + + while (orValue >= k && left <= right) { + minLength = Math.min(minLength, right - left + 1); + const leftNum = nums[left]; + for (let bit = 0; bit < 32; bit++) { + if (leftNum & (1 << bit)) { + bitCounts[bit]--; + if (bitCounts[bit] === 0) orValue &= ~(1 << bit); + } + } + left++; + } + } + + return minLength === Infinity ? -1 : minLength; +}; diff --git a/solutions/3099-harshad-number.js b/solutions/3099-harshad-number.js new file mode 100644 index 00000000..f096f4c8 --- /dev/null +++ b/solutions/3099-harshad-number.js @@ -0,0 +1,22 @@ +/** + * 3099. Harshad Number + * https://leetcode.com/problems/harshad-number/ + * Difficulty: Easy + * + * An integer divisible by the sum of its digits is said to be a Harshad number. You are given + * an integer x. Return the sum of the digits of x if x is a Harshad number, otherwise, return -1. + */ + +/** + * @param {number} x + * @return {number} + */ +var sumOfTheDigitsOfHarshadNumber = function(x) { + let digitSum = 0; + let num = x; + while (num > 0) { + digitSum += num % 10; + num = Math.floor(num / 10); + } + return x % digitSum === 0 ? digitSum : -1; +}; diff --git a/solutions/3100-water-bottles-ii.js b/solutions/3100-water-bottles-ii.js new file mode 100644 index 00000000..a251d5d6 --- /dev/null +++ b/solutions/3100-water-bottles-ii.js @@ -0,0 +1,43 @@ +/** + * 3100. Water Bottles II + * https://leetcode.com/problems/water-bottles-ii/ + * Difficulty: Medium + * + * You are given two integers numBottles and numExchange. + * + * numBottles represents the number of full water bottles that you initially have. In one + * operation, you can perform one of the following operations: + * - Drink any number of full water bottles turning them into empty bottles. + * - Exchange numExchange empty bottles with one full water bottle. Then, increase + * numExchange by one. + * + * Note that you cannot exchange multiple batches of empty bottles for the same value of + * numExchange. For example, if numBottles == 3 and numExchange == 1, you cannot exchange + * 3 empty water bottles for 3 full bottles. + * + * Return the maximum number of water bottles you can drink. + */ + +/** + * @param {number} numBottles + * @param {number} numExchange + * @return {number} + */ +var maxBottlesDrunk = function(numBottles, numExchange) { + let result = 0; + let full = numBottles; + let empty = 0; + + while (full > 0) { + result += full; + empty += full; + full = 0; + if (empty >= numExchange) { + full = 1; + empty -= numExchange; + numExchange++; + } + } + + return result; +}; diff --git a/solutions/3104-find-longest-self-contained-substring.js b/solutions/3104-find-longest-self-contained-substring.js new file mode 100644 index 00000000..78dee0dd --- /dev/null +++ b/solutions/3104-find-longest-self-contained-substring.js @@ -0,0 +1,56 @@ +/** + * 3104. Find Longest Self-Contained Substring + * https://leetcode.com/problems/find-longest-self-contained-substring/ + * Difficulty: Hard + * + * Given a string s, your task is to find the length of the longest self-contained substring + * of s. + * + * A substring t of a string s is called self-contained if t != s and for every character in + * t, it doesn't exist in the rest of s. + * + * Return the length of the longest self-contained substring of s if it exists, otherwise, + * return -1. + */ + +/** + * @param {string} s + * @return {number} + */ +var maxSubstringLength = function(s) { + const firstOccurrences = new Map(); + const lastOccurrences = new Map(); + + for (let i = 0; i < s.length; i++) { + const char = s[i]; + if (!firstOccurrences.has(char)) { + firstOccurrences.set(char, i); + lastOccurrences.set(char, i); + } else { + lastOccurrences.set(char, i); + } + } + + let result = -1; + + for (const [startChar, startIndex] of firstOccurrences) { + const currentStart = startIndex; + let currentEnd = lastOccurrences.get(startChar); + + for (let j = currentStart; j < s.length; j++) { + const currentChar = s[j]; + + if (firstOccurrences.get(currentChar) < currentStart) { + break; + } + + currentEnd = Math.max(currentEnd, lastOccurrences.get(currentChar)); + + if (currentEnd === j && currentEnd - currentStart + 1 !== s.length) { + result = Math.max(result, currentEnd - currentStart + 1); + } + } + } + + return result; +}; diff --git a/solutions/3109-find-the-index-of-permutation.js b/solutions/3109-find-the-index-of-permutation.js new file mode 100644 index 00000000..2304b57e --- /dev/null +++ b/solutions/3109-find-the-index-of-permutation.js @@ -0,0 +1,61 @@ +/** + * 3109. Find the Index of Permutation + * https://leetcode.com/problems/find-the-index-of-permutation/ + * Difficulty: Medium + * + * Given an array perm of length n which is a permutation of [1, 2, ..., n], return the index + * of perm in the lexicographically sorted array of all of the permutations of [1, 2, ..., n]. + * + * Since the answer may be very large, return it modulo 109 + 7. + */ + +/** + * @param {number[]} perm + * @return {number} + */ +var getPermutationIndex = function(perm) { + const smallerToRight = perm.map(() => 0); + + mergeSort(0, perm.length - 1); + + const MOD = 10 ** 9 + 7; + const factorials = computeFactorials(perm.length); + + return perm.reduce((total, _, i) => { + return (total + smallerToRight[i] * factorials[perm.length - 1 - i]) % MOD; + }, 0); + + function mergeSort(left, right) { + if (left >= right) return [left]; + + const mid = (left + right) >> 1; + const leftIndices = mergeSort(left, mid); + const rightIndices = mergeSort(mid + 1, right); + const merged = []; + let [leftPointer, rightPointer] = [0, 0]; + + while (leftPointer < leftIndices.length || rightPointer < rightIndices.length) { + if (rightPointer === rightIndices.length + || (leftPointer < leftIndices.length + && perm[leftIndices[leftPointer]] < perm[rightIndices[rightPointer]])) { + smallerToRight[leftIndices[leftPointer]] += rightPointer; + merged.push(leftIndices[leftPointer++]); + } else { + merged.push(rightIndices[rightPointer++]); + } + } + + return merged; + } + + function computeFactorials(n) { + const MOD = 10n ** 9n + 7n; + const factorials = [1n, 1n]; + + for (let i = 2n; i <= BigInt(n); i++) { + factorials.push(i * factorials[factorials.length - 1] % MOD); + } + + return factorials.map(val => parseInt(val)); + } +}; diff --git a/solutions/3119-maximum-number-of-potholes-that-can-be-fixed.js b/solutions/3119-maximum-number-of-potholes-that-can-be-fixed.js new file mode 100644 index 00000000..f5d16513 --- /dev/null +++ b/solutions/3119-maximum-number-of-potholes-that-can-be-fixed.js @@ -0,0 +1,57 @@ +/** + * 3119. Maximum Number of Potholes That Can Be Fixed + * https://leetcode.com/problems/maximum-number-of-potholes-that-can-be-fixed/ + * Difficulty: Medium + * + * You are given a string road, consisting only of characters "x" and ".", where each "x" denotes + * a pothole and each "." denotes a smooth road, and an integer budget. + * + * In one repair operation, you can repair n consecutive potholes for a price of n + 1. + * + * Return the maximum number of potholes that can be fixed such that the sum of the prices of all + * of the fixes doesn't go over the given budget. + */ + +/** + * @param {string} road + * @param {number} budget + * @return {number} + */ +var maxPotholes = function(road, budget) { + const potholeSections = []; + let currentLength = 0; + + for (const char of road) { + if (char === 'x') { + currentLength++; + } else { + if (currentLength > 0) { + potholeSections.push(currentLength); + currentLength = 0; + } + } + } + + if (currentLength > 0) { + potholeSections.push(currentLength); + } + + potholeSections.sort((a, b) => (a + 1) / a - (b + 1) / b); + + let result = 0; + let remainingBudget = budget; + for (const sectionLength of potholeSections) { + const costToFixAll = sectionLength + 1; + + if (costToFixAll <= remainingBudget) { + result += sectionLength; + remainingBudget -= costToFixAll; + } else { + const maxFixable = Math.max(0, remainingBudget - 1); + result += Math.min(maxFixable, sectionLength); + break; + } + } + + return result; +}; diff --git a/solutions/3125-maximum-number-that-makes-result-of-bitwise-and-zero.js b/solutions/3125-maximum-number-that-makes-result-of-bitwise-and-zero.js new file mode 100644 index 00000000..73305584 --- /dev/null +++ b/solutions/3125-maximum-number-that-makes-result-of-bitwise-and-zero.js @@ -0,0 +1,22 @@ +/** + * 3125. Maximum Number That Makes Result of Bitwise AND Zero + * https://leetcode.com/problems/maximum-number-that-makes-result-of-bitwise-and-zero/ + * Difficulty: Medium + * + * Given an integer n, return the maximum integer x such that x <= n, and the bitwise AND of + * all the numbers in the range [x, n] is 0. + */ + +/** + * @param {number} n + * @return {number} + */ +var maxNumber = function(n) { + let bit = 1; + + while (bit <= n) { + bit *= 2; + } + + return bit / 2 - 1; +}; diff --git a/solutions/3135-equalize-strings-by-adding-or-removing-characters-at-ends.js b/solutions/3135-equalize-strings-by-adding-or-removing-characters-at-ends.js new file mode 100644 index 00000000..afed0bca --- /dev/null +++ b/solutions/3135-equalize-strings-by-adding-or-removing-characters-at-ends.js @@ -0,0 +1,40 @@ +/** + * 3135. Equalize Strings by Adding or Removing Characters at Ends + * https://leetcode.com/problems/equalize-strings-by-adding-or-removing-characters-at-ends/ + * Difficulty: Medium + * + * Given two strings initial and target, your task is to modify initial by performing a series + * of operations to make it equal to target. + * + * In one operation, you can add or remove one character only at the beginning or the end of + * the string initial. + * + * Return the minimum number of operations required to transform initial into target. + */ + +/** + * @param {string} initial + * @param {string} target + * @return {number} + */ +var minOperations = function(initial, target) { + const initialLength = initial.length; + const targetLength = target.length; + let previousRow = new Array(targetLength).fill(0); + let maxCommonSubsequence = 0; + + for (let i = 0; i < initialLength; i++) { + const currentRow = new Array(targetLength).fill(0); + + for (let j = 0; j < targetLength; j++) { + if (initial[i] === target[j]) { + currentRow[j] = 1 + (j - 1 >= 0 ? previousRow[j - 1] : 0); + maxCommonSubsequence = Math.max(maxCommonSubsequence, currentRow[j]); + } + } + + previousRow = currentRow; + } + + return initialLength + targetLength - 2 * maxCommonSubsequence; +}; diff --git a/solutions/3136-valid-word.js b/solutions/3136-valid-word.js new file mode 100644 index 00000000..18d98f13 --- /dev/null +++ b/solutions/3136-valid-word.js @@ -0,0 +1,48 @@ +/** + * 3136. Valid Word + * https://leetcode.com/problems/valid-word/ + * Difficulty: Easy + * + * A word is considered valid if: + * - It contains a minimum of 3 characters. + * - It contains only digits (0-9), and English letters (uppercase and lowercase). + * - It includes at least one vowel. + * - It includes at least one consonant. + * + * You are given a string word. + * + * Return true if word is valid, otherwise, return false. + * + * Notes: + * - 'a', 'e', 'i', 'o', 'u', and their uppercases are vowels. + * - A consonant is an English letter that is not a vowel. + */ + +/** + * @param {string} word + * @return {boolean} + */ +var isValid = function(word) { + if (word.length < 3) return false; + + const vowels = new Set('aeiouAEIOU'); + const special = new Set('@#$'); + const digits = new Set('0123456789'); + const wordSet = new Set(word); + + if (hasIntersection(wordSet, special)) return false; + if (!hasIntersection(wordSet, vowels)) return false; + + const result = new Set([...wordSet].filter(char => { + return !vowels.has(char) && !digits.has(char); + })); + + return result.size > 0; + + function hasIntersection(set1, set2) { + for (const item of set1) { + if (set2.has(item)) return true; + } + return false; + } +}; diff --git a/solutions/3141-maximum-hamming-distances.js b/solutions/3141-maximum-hamming-distances.js new file mode 100644 index 00000000..f8cb1d0e --- /dev/null +++ b/solutions/3141-maximum-hamming-distances.js @@ -0,0 +1,36 @@ +/** + * 3141. Maximum Hamming Distances + * https://leetcode.com/problems/maximum-hamming-distances/ + * Difficulty: Hard + * + * Given an array nums and an integer m, with each element nums[i] satisfying 0 <= nums[i] < 2m, + * return an array answer. The answer array should be of the same length as nums, where each + * element answer[i] represents the maximum Hamming distance between nums[i] and any other element + * nums[j] in the array. + * + * The Hamming distance between two binary integers is defined as the number of positions at which + * the corresponding bits differ (add leading zeroes if needed). + */ + +/** + * @param {number[]} nums + * @param {number} m + * @return {number[]} + */ +var maxHammingDistances = function(nums, m) { + const totalSize = 1 << m; + const maxDistances = new Array(totalSize).fill(-Infinity); + + for (const num of nums) { + maxDistances[num] = 0; + } + for (let bitPosition = 0; bitPosition < m; bitPosition++) { + const previousDistances = [...maxDistances]; + for (let number = 0; number < totalSize; number++) { + const flippedNumber = number ^ (1 << bitPosition); + maxDistances[number] = Math.max(maxDistances[number], previousDistances[flippedNumber] + 1); + } + } + + return nums.map(num => maxDistances[num]); +}; diff --git a/solutions/3147-taking-maximum-energy-from-the-mystic-dungeon.js b/solutions/3147-taking-maximum-energy-from-the-mystic-dungeon.js new file mode 100644 index 00000000..e977aecd --- /dev/null +++ b/solutions/3147-taking-maximum-energy-from-the-mystic-dungeon.js @@ -0,0 +1,39 @@ +/** + * 3147. Taking Maximum Energy From the Mystic Dungeon + * https://leetcode.com/problems/taking-maximum-energy-from-the-mystic-dungeon/ + * Difficulty: Medium + * + * In a mystic dungeon, n magicians are standing in a line. Each magician has an attribute + * that gives you energy. Some magicians can give you negative energy, which means taking + * energy from you. + * + * You have been cursed in such a way that after absorbing energy from magician i, you will + * be instantly transported to magician (i + k). This process will be repeated until you + * reach the magician where (i + k) does not exist. + * + * In other words, you will choose a starting point and then teleport with k jumps until you + * reach the end of the magicians' sequence, absorbing all the energy during the journey. + * + * You are given an array energy and an integer k. Return the maximum possible energy you can gain. + * + * Note that when you are reach a magician, you must take energy from them, whether it is negative + * or positive energy. + */ + +/** + * @param {number[]} energy + * @param {number} k + * @return {number} + */ +var maximumEnergy = function(energy, k) { + const n = energy.length; + const dp = new Array(n).fill(0); + let result = -Infinity; + + for (let i = n - 1; i >= 0; i--) { + dp[i] = energy[i] + (i + k < n ? dp[i + k] : 0); + result = Math.max(result, dp[i]); + } + + return result; +}; diff --git a/solutions/3155-maximum-number-of-upgradable-servers.js b/solutions/3155-maximum-number-of-upgradable-servers.js new file mode 100644 index 00000000..f0bf5045 --- /dev/null +++ b/solutions/3155-maximum-number-of-upgradable-servers.js @@ -0,0 +1,43 @@ +/** + * 3155. Maximum Number of Upgradable Servers + * https://leetcode.com/problems/maximum-number-of-upgradable-servers/ + * Difficulty: Medium + * + * You have n data centers and need to upgrade their servers. + * + * You are given four arrays count, upgrade, sell, and money of length n, which show: + * - The number of servers + * - The cost of upgrading a single server + * - The money you get by selling a server + * - The money you initially have + * - for each data center respectively. + * + * Return an array answer, where for each data center, the corresponding element in answer + * represents the maximum number of servers that can be upgraded. + * + * Note that the money from one data center cannot be used for another data center. + */ + +/** + * @param {number[]} count + * @param {number[]} upgrade + * @param {number[]} sell + * @param {number[]} money + * @return {number[]} + */ +var maxUpgrades = function(count, upgrade, sell, money) { + const n = count.length; + const result = [...count]; + + for (let i = 0; i < n; i++) { + const totalUpgradeCost = count[i] * upgrade[i] - money[i]; + + if (totalUpgradeCost > 0) { + const netGainPerSale = sell[i] + upgrade[i]; + const serversToSell = Math.ceil(totalUpgradeCost / netGainPerSale); + result[i] -= serversToSell; + } + } + + return result; +}; diff --git a/solutions/3157-find-the-level-of-tree-with-minimum-sum.js b/solutions/3157-find-the-level-of-tree-with-minimum-sum.js new file mode 100644 index 00000000..97beb4c7 --- /dev/null +++ b/solutions/3157-find-the-level-of-tree-with-minimum-sum.js @@ -0,0 +1,55 @@ +/** + * 3157. Find the Level of Tree with Minimum Sum + * https://leetcode.com/problems/find-the-level-of-tree-with-minimum-sum/ + * Difficulty: Medium + * + * Given the root of a binary tree root where each node has a value, return the level of the + * tree that has the minimum sum of values among all the levels (in case of a tie, return the + * lowest level). + * + * Note that the root of the tree is at level 1 and the level of any other node is its distance + * from the root + 1. + */ + +/** + * 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} + */ +var minimumLevel = function(root) { + if (!root) return 1; + + const queue = [root]; + let currentLevel = 1; + let minSum = Infinity; + let result = 1; + + while (queue.length > 0) { + const levelSize = queue.length; + let levelSum = 0; + + for (let i = 0; i < levelSize; i++) { + const node = queue.shift(); + levelSum += node.val; + + if (node.left) queue.push(node.left); + if (node.right) queue.push(node.right); + } + + if (levelSum < minSum) { + minSum = levelSum; + result = currentLevel; + } + + currentLevel++; + } + + return result; +}; diff --git a/solutions/3167-better-compression-of-string.js b/solutions/3167-better-compression-of-string.js new file mode 100644 index 00000000..82761258 --- /dev/null +++ b/solutions/3167-better-compression-of-string.js @@ -0,0 +1,45 @@ +/** + * 3167. Better Compression of String + * https://leetcode.com/problems/better-compression-of-string/ + * Difficulty: Medium + * + * You are given a string compressed representing a compressed version of a string. The format + * is a character followed by its frequency. For example, "a3b1a1c2" is a compressed version + * of the string "aaabacc". + * + * We seek a better compression with the following conditions: + * 1. Each character should appear only once in the compressed version. + * 2. The characters should be in alphabetical order. + * + * Return the better compression of compressed. + * + * Note: In the better version of compression, the order of letters may change, which is acceptable. + */ + +/** + * @param {string} compressed + * @return {string} + */ +var betterCompression = function(compressed) { + const map = new Map(); + let i = 0; + + while (i < compressed.length) { + const char = compressed[i]; + i++; + + let frequency = ''; + while (i < compressed.length && !isNaN(compressed[i])) { + frequency += compressed[i]; + i++; + } + + const count = parseInt(frequency); + map.set(char, (map.get(char) || 0) + count); + } + + const sortedChars = [...map.keys()].sort(); + const result = sortedChars.map(char => char + map.get(char)).join(''); + + return result; +}; diff --git a/solutions/3170-lexicographically-minimum-string-after-removing-stars.js b/solutions/3170-lexicographically-minimum-string-after-removing-stars.js new file mode 100644 index 00000000..c0efec6b --- /dev/null +++ b/solutions/3170-lexicographically-minimum-string-after-removing-stars.js @@ -0,0 +1,40 @@ +/** + * 3170. Lexicographically Minimum String After Removing Stars + * https://leetcode.com/problems/lexicographically-minimum-string-after-removing-stars/ + * Difficulty: Medium + * + * You are given a string s. It may contain any number of '*' characters. Your task is to + * remove all '*' characters. + * + * While there is a '*', do the following operation: + * - Delete the leftmost '*' and the smallest non-'*' character to its left. If there are several + * smallest characters, you can delete any of them. + * + * Return the lexicographically smallest resulting string after removing all '*' characters. + */ + +/** + * @param {string} s + * @return {string} + */ +var clearStars = function(s) { + const chars = s.split(''); + const deleted = new Set(); + const stacks = new Array(26).fill().map(() => []); + + for (let i = 0; i < s.length; i++) { + if (s[i] === '*') { + for (let j = 0; j < 26; j++) { + if (stacks[j].length) { + deleted.add(stacks[j].pop()); + deleted.add(i); + break; + } + } + } else { + stacks[s[i].charCodeAt(0) - 97].push(i); + } + } + + return chars.filter((_, i) => !deleted.has(i)).join(''); +}; diff --git a/solutions/3173-bitwise-or-of-adjacent-elements.js b/solutions/3173-bitwise-or-of-adjacent-elements.js new file mode 100644 index 00000000..78f53116 --- /dev/null +++ b/solutions/3173-bitwise-or-of-adjacent-elements.js @@ -0,0 +1,22 @@ +/** + * 3173. Bitwise OR of Adjacent Elements + * https://leetcode.com/problems/bitwise-or-of-adjacent-elements/ + * Difficulty: Easy + * + * Given an array nums of length n, return an array answer of length n - 1 such that + * answer[i] = nums[i] | nums[i + 1] where | is the bitwise OR operation. + */ + +/** + * @param {number[]} nums + * @return {number[]} + */ +var orArray = function(nums) { + const result = []; + + for (let i = 0; i < nums.length - 1; i++) { + result.push(nums[i] | nums[i + 1]); + } + + return result; +}; diff --git a/solutions/3183-the-number-of-ways-to-make-the-sum.js b/solutions/3183-the-number-of-ways-to-make-the-sum.js new file mode 100644 index 00000000..0be1707c --- /dev/null +++ b/solutions/3183-the-number-of-ways-to-make-the-sum.js @@ -0,0 +1,39 @@ +/** + * 3183. The Number of Ways to Make the Sum + * https://leetcode.com/problems/the-number-of-ways-to-make-the-sum/ + * Difficulty: Medium + * + * You have an infinite number of coins with values 1, 2, and 6, and only 2 coins with value 4. + * + * Given an integer n, return the number of ways to make the sum of n with the coins you have. + * + * Since the answer may be very large, return it modulo 109 + 7. + * + * Note that the order of the coins doesn't matter and [2, 2, 3] is the same as [2, 3, 2]. + */ + +/** + * @param {number} n + * @return {number} + */ +var numberOfWays = function(n) { + const MOD = 1e9 + 7; + const dp = new Array(n + 1).fill(0); + dp[0] = 1; + + for (const coin of [1, 2, 6]) { + for (let amount = coin; amount <= n; amount++) { + dp[amount] = (dp[amount] + dp[amount - coin]) % MOD; + } + } + + let result = dp[n]; + if (n >= 4) { + result = (result + dp[n - 4]) % MOD; + } + if (n >= 8) { + result = (result + dp[n - 8]) % MOD; + } + + return result; +}; diff --git a/solutions/3186-maximum-total-damage-with-spell-casting.js b/solutions/3186-maximum-total-damage-with-spell-casting.js new file mode 100644 index 00000000..c392c9ec --- /dev/null +++ b/solutions/3186-maximum-total-damage-with-spell-casting.js @@ -0,0 +1,55 @@ +/** + * 3186. Maximum Total Damage With Spell Casting + * https://leetcode.com/problems/maximum-total-damage-with-spell-casting/ + * Difficulty: Medium + * + * A magician has various spells. + * + * You are given an array power, where each element represents the damage of a spell. Multiple + * spells can have the same damage value. + * + * It is a known fact that if a magician decides to cast a spell with a damage of power[i], + * they cannot cast any spell with a damage of power[i] - 2, power[i] - 1, power[i] + 1, or + * power[i] + 2. + * + * Each spell can be cast only once. + * + * Return the maximum possible total damage that a magician can cast. + */ + +/** + * @param {number[]} power + * @return {number} + */ +var maximumTotalDamage = function(power) { + const frequency = new Map(); + for (const p of power) { + frequency.set(p, (frequency.get(p) || 0) + 1); + } + + const uniquePowers = Array.from(frequency.keys()).sort((a, b) => a - b); + const n = uniquePowers.length; + + if (n === 0) return 0; + if (n === 1) return uniquePowers[0] * frequency.get(uniquePowers[0]); + + const dp = new Array(n).fill(0); + dp[0] = uniquePowers[0] * frequency.get(uniquePowers[0]); + + for (let i = 1; i < n; i++) { + const currentPower = uniquePowers[i]; + const currentDamage = currentPower * frequency.get(currentPower); + + let j = i - 1; + while (j >= 0 && uniquePowers[j] >= currentPower - 2) { + j--; + } + + const withCurrent = currentDamage + (j >= 0 ? dp[j] : 0); + const withoutCurrent = dp[i - 1]; + + dp[i] = Math.max(withCurrent, withoutCurrent); + } + + return dp[n - 1]; +}; diff --git a/solutions/3189-minimum-moves-to-get-a-peaceful-board.js b/solutions/3189-minimum-moves-to-get-a-peaceful-board.js new file mode 100644 index 00000000..0d0e05be --- /dev/null +++ b/solutions/3189-minimum-moves-to-get-a-peaceful-board.js @@ -0,0 +1,31 @@ +/** + * 3189. Minimum Moves to Get a Peaceful Board + * https://leetcode.com/problems/minimum-moves-to-get-a-peaceful-board/ + * Difficulty: Medium + * + * Given a 2D array rooks of length n, where rooks[i] = [xi, yi] indicates the position of a + * rook on an n x n chess board. Your task is to move the rooks 1 cell at a time vertically + * or horizontally (to an adjacent cell) such that the board becomes peaceful. + * + * A board is peaceful if there is exactly one rook in each row and each column. + * + * Return the minimum number of moves required to get a peaceful board. + * + * Note that at no point can there be two rooks in the same cell. + */ + +/** + * @param {number[][]} rooks + * @return {number} + */ +var minMoves = function(rooks) { + const rows = rooks.map(rook => rook[0]).sort((a, b) => a - b); + const cols = rooks.map(rook => rook[1]).sort((a, b) => a - b); + + let result = 0; + for (let i = 0; i < rooks.length; i++) { + result += Math.abs(rows[i] - i) + Math.abs(cols[i] - i); + } + + return result; +}; diff --git a/solutions/3195-find-the-minimum-area-to-cover-all-ones-i.js b/solutions/3195-find-the-minimum-area-to-cover-all-ones-i.js new file mode 100644 index 00000000..d01d8c9c --- /dev/null +++ b/solutions/3195-find-the-minimum-area-to-cover-all-ones-i.js @@ -0,0 +1,36 @@ +/** + * 3195. Find the Minimum Area to Cover All Ones I + * https://leetcode.com/problems/find-the-minimum-area-to-cover-all-ones-i/ + * Difficulty: Medium + * + * You are given a 2D binary array grid. Find a rectangle with horizontal and vertical + * sides with the smallest area, such that all the 1's in grid lie inside this rectangle. + * + * Return the minimum possible area of the rectangle. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var minimumArea = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + let minRow = rows; + let maxRow = -1; + let minCol = cols; + let maxCol = -1; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (grid[i][j] === 1) { + minRow = Math.min(minRow, i); + maxRow = Math.max(maxRow, i); + minCol = Math.min(minCol, j); + maxCol = Math.max(maxCol, j); + } + } + } + + return (maxRow - minRow + 1) * (maxCol - minCol + 1); +}; diff --git a/solutions/3197-find-the-minimum-area-to-cover-all-ones-ii.js b/solutions/3197-find-the-minimum-area-to-cover-all-ones-ii.js new file mode 100644 index 00000000..49c88ebb --- /dev/null +++ b/solutions/3197-find-the-minimum-area-to-cover-all-ones-ii.js @@ -0,0 +1,101 @@ +/** + * 3197. Find the Minimum Area to Cover All Ones II + * https://leetcode.com/problems/find-the-minimum-area-to-cover-all-ones-ii/ + * Difficulty: Hard + * + * You are given a 2D binary array grid. You need to find 3 non-overlapping rectangles having + * non-zero areas with horizontal and vertical sides such that all the 1's in grid lie inside + * these rectangles. + * + * Return the minimum possible sum of the area of these rectangles. + * + * Note that the rectangles are allowed to touch. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var minimumSum = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + let minSum = Infinity; + + for (let i = 0; i < rows; i++) { + const area1 = calculateArea(0, i, 0, cols - 1); + for (let j = 0; j < cols; j++) { + const area2 = calculateArea(i + 1, rows - 1, 0, j); + const area3 = calculateArea(i + 1, rows - 1, j + 1, cols - 1); + minSum = Math.min(minSum, area1 + area2 + area3); + } + } + + for (let j = 0; j < cols; j++) { + const area1 = calculateArea(0, rows - 1, 0, j); + for (let i = 0; i < rows; i++) { + const area2 = calculateArea(0, i, j + 1, cols - 1); + const area3 = calculateArea(i + 1, rows - 1, j + 1, cols - 1); + minSum = Math.min(minSum, area1 + area2 + area3); + } + } + + for (let j = cols - 1; j >= 0; j--) { + const area1 = calculateArea(0, rows - 1, j + 1, cols - 1); + for (let i = 0; i < rows; i++) { + const area2 = calculateArea(0, i, 0, j); + const area3 = calculateArea(i + 1, rows - 1, 0, j); + minSum = Math.min(minSum, area1 + area2 + area3); + } + } + + for (let i = rows - 1; i >= 0; i--) { + const area1 = calculateArea(i + 1, rows - 1, 0, cols - 1); + for (let j = 0; j < cols; j++) { + const area2 = calculateArea(0, i, 0, j); + const area3 = calculateArea(0, i, j + 1, cols - 1); + minSum = Math.min(minSum, area1 + area2 + area3); + } + } + + for (let i = 0; i < rows; i++) { + for (let j = i + 1; j < rows; j++) { + const area1 = calculateArea(0, i, 0, cols - 1); + const area2 = calculateArea(i + 1, j, 0, cols - 1); + const area3 = calculateArea(j + 1, rows - 1, 0, cols - 1); + minSum = Math.min(minSum, area1 + area2 + area3); + } + } + + for (let i = 0; i < cols; i++) { + for (let j = i + 1; j < cols; j++) { + const area1 = calculateArea(0, rows - 1, 0, i); + const area2 = calculateArea(0, rows - 1, i + 1, j); + const area3 = calculateArea(0, rows - 1, j + 1, cols - 1); + minSum = Math.min(minSum, area1 + area2 + area3); + } + } + + return minSum; + + function calculateArea(startRow, endRow, startCol, endCol) { + let minRow = Infinity; + let maxRow = -1; + let minCol = Infinity; + let maxCol = -1; + let found = false; + + for (let i = startRow; i <= endRow; i++) { + for (let j = startCol; j <= endCol; j++) { + if (grid[i][j] === 1) { + minRow = Math.min(minRow, i); + maxRow = Math.max(maxRow, i); + minCol = Math.min(minCol, j); + maxCol = Math.max(maxCol, j); + found = true; + } + } + } + + return found ? (maxRow - minRow + 1) * (maxCol - minCol + 1) : 0; + } +}; diff --git a/solutions/3199-count-triplets-with-even-xor-set-bits-i.js b/solutions/3199-count-triplets-with-even-xor-set-bits-i.js new file mode 100644 index 00000000..8c9838f6 --- /dev/null +++ b/solutions/3199-count-triplets-with-even-xor-set-bits-i.js @@ -0,0 +1,42 @@ +/** + * 3199. Count Triplets with Even XOR Set Bits I + * https://leetcode.com/problems/count-triplets-with-even-xor-set-bits-i/ + * Difficulty: Easy + * + * Given three integer arrays a, b, and c, return the number of triplets (a[i], b[j], c[k]), + * such that the bitwise XOR of the elements of each triplet has an even number of set bits. + */ + +/** + * @param {number[]} a + * @param {number[]} b + * @param {number[]} c + * @return {number} + */ +var tripletCount = function(a, b, c) { + let result = 0; + + for (const numA of a) { + for (const numB of b) { + for (const numC of c) { + const xorResult = numA ^ numB ^ numC; + if (hasEvenSetBits(xorResult)) { + result++; + } + } + } + } + + return result; + + function hasEvenSetBits(num) { + let setBitsCount = 0; + + while (num > 0) { + setBitsCount += num & 1; + num >>= 1; + } + + return setBitsCount % 2 === 0; + } +}; diff --git a/solutions/3201-find-the-maximum-length-of-valid-subsequence-i.js b/solutions/3201-find-the-maximum-length-of-valid-subsequence-i.js new file mode 100644 index 00000000..da026ba9 --- /dev/null +++ b/solutions/3201-find-the-maximum-length-of-valid-subsequence-i.js @@ -0,0 +1,36 @@ +/** + * 3201. Find the Maximum Length of Valid Subsequence I + * https://leetcode.com/problems/find-the-maximum-length-of-valid-subsequence-i/ + * Difficulty: Medium + * + * You are given an integer array nums. + * + * A subsequence sub of nums with length x is called valid if it satisfies: + * - (sub[0] + sub[1]) % 2 == (sub[1] + sub[2]) % 2 == ... == (sub[x - 2] + sub[x - 1]) % 2. + * + * Return the length of the longest valid subsequence of nums. + * + * A subsequence is an array that can be derived from another array by deleting some or no + * elements without changing the order of the remaining elements. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maximumLength = function(nums) { + const evenCount = nums.filter(num => num % 2 === 0).length; + const oddCount = nums.length - evenCount; + + let alternatingCount = 0; + let lastParity = -1; + for (const num of nums) { + const currentParity = num % 2; + if (lastParity === -1 || currentParity !== lastParity) { + alternatingCount++; + lastParity = currentParity; + } + } + + return Math.max(evenCount, oddCount, alternatingCount); +}; diff --git a/solutions/3202-find-the-maximum-length-of-valid-subsequence-ii.js b/solutions/3202-find-the-maximum-length-of-valid-subsequence-ii.js new file mode 100644 index 00000000..e295b891 --- /dev/null +++ b/solutions/3202-find-the-maximum-length-of-valid-subsequence-ii.js @@ -0,0 +1,35 @@ +/** + * 3202. Find the Maximum Length of Valid Subsequence II + * https://leetcode.com/problems/find-the-maximum-length-of-valid-subsequence-ii/ + * Difficulty: Medium + * + * You are given an integer array nums and a positive integer k. + * + * A subsequence sub of nums with length x is called valid if it satisfies: + * - (sub[0] + sub[1]) % k == (sub[1] + sub[2]) % k == ... == (sub[x - 2] + sub[x - 1]) % k. + * + * Return the length of the longest valid subsequence of nums. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var maximumLength = function(nums, k) { + let result = 0; + + for (let target = 0; target < k; target++) { + const dp = new Array(k).fill(0); + + for (const num of nums) { + const mod = num % k; + const prev = (target - mod + k) % k; + dp[mod] = Math.max(dp[mod], dp[prev] + 1); + } + + result = Math.max(result, Math.max(...dp)); + } + + return result; +}; diff --git a/solutions/3205-maximum-array-hopping-score-i.js b/solutions/3205-maximum-array-hopping-score-i.js new file mode 100644 index 00000000..7b4faa30 --- /dev/null +++ b/solutions/3205-maximum-array-hopping-score-i.js @@ -0,0 +1,34 @@ +/** + * 3205. Maximum Array Hopping Score I + * https://leetcode.com/problems/maximum-array-hopping-score-i/ + * Difficulty: Medium + * + * Given an array nums, you have to get the maximum score starting from index 0 and + * hopping until you reach the last element of the array. + * + * In each hop, you can jump from index i to an index j > i, and you get a score of + * (j - i) * nums[j]. + * + * Return the maximum score you can get. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxScore = function(nums) { + const n = nums.length; + const dp = new Array(n).fill(-Infinity); + dp[0] = 0; + + for (let i = 0; i < n; i++) { + if (dp[i] === -Infinity) continue; + + for (let j = i + 1; j < n; j++) { + const jumpScore = (j - i) * nums[j]; + dp[j] = Math.max(dp[j], dp[i] + jumpScore); + } + } + + return dp[n - 1]; +}; diff --git a/solutions/3215-count-triplets-with-even-xor-set-bits-ii.js b/solutions/3215-count-triplets-with-even-xor-set-bits-ii.js new file mode 100644 index 00000000..cf408718 --- /dev/null +++ b/solutions/3215-count-triplets-with-even-xor-set-bits-ii.js @@ -0,0 +1,47 @@ +/** + * 3215. Count Triplets with Even XOR Set Bits II + * https://leetcode.com/problems/count-triplets-with-even-xor-set-bits-ii/ + * Difficulty: Medium + * + * Given three integer arrays a, b, and c, return the number of triplets (a[i], b[j], c[k]), + * such that the bitwise XOR between the elements of each triplet has an even number of set bits. + */ + +/** + * @param {number[]} a + * @param {number[]} b + * @param {number[]} c + * @return {number} + */ +var tripletCount = function(a, b, c) { + const countA = [0, 0]; + const countB = [0, 0]; + const countC = [0, 0]; + + for (const num of a) { + countA[countSetBits(num) % 2]++; + } + for (const num of b) { + countB[countSetBits(num) % 2]++; + } + for (const num of c) { + countC[countSetBits(num) % 2]++; + } + + let result = 0; + result += countA[0] * countB[0] * countC[0]; + result += countA[1] * countB[1] * countC[0]; + result += countA[1] * countB[0] * countC[1]; + result += countA[0] * countB[1] * countC[1]; + + return result; + + function countSetBits(num) { + let count = 0; + while (num > 0) { + count += num & 1; + num >>= 1; + } + return count; + } +}; diff --git a/solutions/3217-delete-nodes-from-linked-list-present-in-array.js b/solutions/3217-delete-nodes-from-linked-list-present-in-array.js new file mode 100644 index 00000000..62329285 --- /dev/null +++ b/solutions/3217-delete-nodes-from-linked-list-present-in-array.js @@ -0,0 +1,37 @@ +/** + * 3217. Delete Nodes From Linked List Present in Array + * https://leetcode.com/problems/delete-nodes-from-linked-list-present-in-array/ + * Difficulty: Medium + * + * You are given an array of integers nums and the head of a linked list. Return the head + * of the modified linked list after removing all nodes from the linked list that have + * a value that exists in nums. + */ + +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {number[]} nums + * @param {ListNode} head + * @return {ListNode} + */ +var modifiedList = function(nums, head) { + const set = new Set(nums); + const temp = new ListNode(0, head); + let current = temp; + + while (current.next) { + if (set.has(current.next.val)) { + current.next = current.next.next; + } else { + current = current.next; + } + } + + return temp.next; +}; diff --git a/solutions/3221-maximum-array-hopping-score-ii.js b/solutions/3221-maximum-array-hopping-score-ii.js new file mode 100644 index 00000000..5abe3e4a --- /dev/null +++ b/solutions/3221-maximum-array-hopping-score-ii.js @@ -0,0 +1,29 @@ +/** + * 3221. Maximum Array Hopping Score II + * https://leetcode.com/problems/maximum-array-hopping-score-ii/ + * Difficulty: Medium + * + * Given an array nums, you have to get the maximum score starting from index 0 and + * hopping until you reach the last element of the array. + * + * In each hop, you can jump from index i to an index j > i, and you get a score of + * (j - i) * nums[j]. + * + * Return the maximum score you can get. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxScore = function(nums) { + let result = 0; + let max = 0; + + for (let i = nums.length - 1; i >= 1; i--) { + max = Math.max(max, nums[i]); + result += max; + } + + return result; +}; diff --git a/solutions/3227-vowels-game-in-a-string.js b/solutions/3227-vowels-game-in-a-string.js new file mode 100644 index 00000000..15dfd693 --- /dev/null +++ b/solutions/3227-vowels-game-in-a-string.js @@ -0,0 +1,35 @@ +/** + * 3227. Vowels Game in a String + * https://leetcode.com/problems/vowels-game-in-a-string/ + * Difficulty: Medium + * + * Alice and Bob are playing a game on a string. + * + * You are given a string s, Alice and Bob will take turns playing the following game where + * Alice starts first: + * - On Alice's turn, she has to remove any non-empty substring from s that contains an odd + * number of vowels. + * - On Bob's turn, he has to remove any non-empty substring from s that contains an even + * number of vowels. + * + * The first player who cannot make a move on their turn loses the game. We assume that both + * Alice and Bob play optimally. + * + * Return true if Alice wins the game, and false otherwise. + * + * The English vowels are: a, e, i, o, and u. + */ + +/** + * @param {string} s + * @return {boolean} + */ +var doesAliceWin = function(s) { + const vowels = new Set(['a', 'e', 'i', 'o', 'u']); + for (const char of s) { + if (vowels.has(char)) { + return true; + } + } + return false; +}; diff --git a/solutions/3231-minimum-number-of-increasing-subsequence-to-be-removed.js b/solutions/3231-minimum-number-of-increasing-subsequence-to-be-removed.js new file mode 100644 index 00000000..8d4897ea --- /dev/null +++ b/solutions/3231-minimum-number-of-increasing-subsequence-to-be-removed.js @@ -0,0 +1,48 @@ +/** + * 3231. Minimum Number of Increasing Subsequence to Be Removed + * https://leetcode.com/problems/minimum-number-of-increasing-subsequence-to-be-removed/ + * Difficulty: Hard + * + * Given an array of integers nums, you are allowed to perform the following operation any + * number of times: + * - Remove a strictly increasing subsequence from the array. + * + * Your task is to find the minimum number of operations required to make the array empty. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minOperations = function(nums) { + const dp = [nums[nums.length - 1]]; + + for (let i = nums.length - 2; i >= 0; i--) { + const currentNum = nums[i]; + + if (currentNum >= dp[dp.length - 1]) { + dp.push(currentNum); + } else { + const insertionIndex = binarySearchRight(dp, currentNum); + dp[insertionIndex] = currentNum; + } + } + + return dp.length; + + function binarySearchRight(arr, target) { + let left = 0; + let right = arr.length; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (arr[mid] <= target) { + left = mid + 1; + } else { + right = mid; + } + } + + return left; + } +}; diff --git a/solutions/3237-alt-and-tab-simulation.js b/solutions/3237-alt-and-tab-simulation.js new file mode 100644 index 00000000..005f9b54 --- /dev/null +++ b/solutions/3237-alt-and-tab-simulation.js @@ -0,0 +1,43 @@ +/** + * 3237. Alt and Tab Simulation + * https://leetcode.com/problems/alt-and-tab-simulation/ + * Difficulty: Medium + * + * There are n windows open numbered from 1 to n, we want to simulate using alt + tab to + * navigate between the windows. + * + * You are given an array windows which contains the initial order of the windows (the + * first element is at the top and the last one is at the bottom). + * + * You are also given an array queries where for each query, the window queries[i] is + * brought to the top. + * + * Return the final state of the array windows. + */ + +/** + * @param {number[]} windows + * @param {number[]} queries + * @return {number[]} + */ +var simulationResult = function(windows, queries) { + const result = []; + const set = new Set(); + + for (let i = queries.length - 1; i >= 0; i--) { + const window = queries[i]; + + if (!set.has(window)) { + result.push(window); + set.add(window); + } + } + + for (const window of windows) { + if (!set.has(window)) { + result.push(window); + } + } + + return result; +}; diff --git a/solutions/3247-number-of-subsequences-with-odd-sum.js b/solutions/3247-number-of-subsequences-with-odd-sum.js new file mode 100644 index 00000000..3e40ac6e --- /dev/null +++ b/solutions/3247-number-of-subsequences-with-odd-sum.js @@ -0,0 +1,33 @@ +/** + * 3247. Number of Subsequences with Odd Sum + * https://leetcode.com/problems/number-of-subsequences-with-odd-sum/ + * Difficulty: Medium + * + * Given an array nums, return the number of subsequences with an odd sum of elements. + * + * Since the answer may be very large, return it modulo 109 + 7. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var subsequenceCount = function(nums) { + const MOD = 1e9 + 7; + let oddCount = 0; + let evenCount = 1; + + for (const num of nums) { + if (num % 2 === 1) { + const newOddCount = (oddCount + evenCount) % MOD; + const newEvenCount = (evenCount + oddCount) % MOD; + oddCount = newOddCount; + evenCount = newEvenCount; + } else { + oddCount = (oddCount * 2) % MOD; + evenCount = (evenCount * 2) % MOD; + } + } + + return oddCount; +}; diff --git a/solutions/3253-construct-string-with-minimum-cost-easy.js b/solutions/3253-construct-string-with-minimum-cost-easy.js new file mode 100644 index 00000000..3475d89e --- /dev/null +++ b/solutions/3253-construct-string-with-minimum-cost-easy.js @@ -0,0 +1,44 @@ +/** + * 3253. Construct String with Minimum Cost (Easy) + * https://leetcode.com/problems/construct-string-with-minimum-cost-easy/ + * Difficulty: Medium + * + * You are given a string target, an array of strings words, and an integer array costs, + * both arrays of the same length. + * + * Imagine an empty string s. + * + * You can perform the following operation any number of times (including zero): + * - Choose an index i in the range [0, words.length - 1]. + * - Append words[i] to s. + * - The cost of operation is costs[i]. + * + * Return the minimum cost to make s equal to target. If it's not possible, return -1. + */ + +/** + * @param {string} target + * @param {string[]} words + * @param {number[]} costs + * @return {number} + */ +var minimumCost = function(target, words, costs) { + const n = target.length; + const dp = new Array(n + 1).fill(Infinity); + dp[0] = 0; + + for (let i = 0; i < n; i++) { + if (dp[i] === Infinity) continue; + + for (let j = 0; j < words.length; j++) { + const word = words[j]; + const cost = costs[j]; + + if (i + word.length <= n && target.substring(i, i + word.length) === word) { + dp[i + word.length] = Math.min(dp[i + word.length], dp[i] + cost); + } + } + } + + return dp[n] === Infinity ? -1 : dp[n]; +}; diff --git a/solutions/3263-convert-doubly-linked-list-to-array-i.js b/solutions/3263-convert-doubly-linked-list-to-array-i.js new file mode 100644 index 00000000..63969081 --- /dev/null +++ b/solutions/3263-convert-doubly-linked-list-to-array-i.js @@ -0,0 +1,34 @@ +/** + * 3263. Convert Doubly Linked List to Array I + * https://leetcode.com/problems/convert-doubly-linked-list-to-array-i/ + * Difficulty: Easy + * + * You are given the head of a doubly linked list, which contains nodes that have a next + * pointer and a previous pointer. + * + * Return an integer array which contains the elements of the linked list in order. + */ + +/** + * // Definition for a _Node. + * function _Node(val,prev,next) { + * this.val = val; + * this.prev = prev; + * this.next = next; + * }; + */ +/** + * @param {_Node} head + * @return {number[]} + */ +var toArray = function(head) { + const result = []; + let currentNode = head; + + while (currentNode) { + result.push(currentNode.val); + currentNode = currentNode.next; + } + + return result; +}; diff --git a/solutions/3269-constructing-two-increasing-arrays.js b/solutions/3269-constructing-two-increasing-arrays.js new file mode 100644 index 00000000..d8db2331 --- /dev/null +++ b/solutions/3269-constructing-two-increasing-arrays.js @@ -0,0 +1,48 @@ +/** + * 3269. Constructing Two Increasing Arrays + * https://leetcode.com/problems/constructing-two-increasing-arrays/ + * Difficulty: Hard + * + * Given 2 integer arrays nums1 and nums2 consisting only of 0 and 1, your task is to calculate + * the minimum possible largest number in arrays nums1 and nums2, after doing the following. + * + * Replace every 0 with an even positive integer and every 1 with an odd positive integer. + * After replacement, both arrays should be increasing and each integer should be used at most once. + * + * Return the minimum possible largest number after applying the changes. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var minLargest = function(nums1, nums2) { + const n1 = nums1.length; + const n2 = nums2.length; + const dp = new Array(n1 + 1).fill().map(() => new Array(n2 + 1).fill(-Infinity)); + + dp[0][0] = 0; + + for (let i = 0; i < n1; i++) { + dp[i + 1][0] = getNextValue(dp[i][0], nums1[i]); + } + for (let j = 0; j < n2; j++) { + dp[0][j + 1] = getNextValue(dp[0][j], nums2[j]); + } + for (let i = 0; i < n1; i++) { + for (let j = 0; j < n2; j++) { + dp[i + 1][j + 1] = Math.min( + getNextValue(dp[i][j + 1], nums1[i]), + getNextValue(dp[i + 1][j], nums2[j]) + ); + } + } + + return dp[n1][n2]; + + function getNextValue(currentValue, targetParity) { + const nextValue = currentValue + 1; + return nextValue % 2 === targetParity % 2 ? nextValue : nextValue + 1; + } +}; diff --git a/solutions/3279-maximum-total-area-occupied-by-pistons.js b/solutions/3279-maximum-total-area-occupied-by-pistons.js new file mode 100644 index 00000000..9c4801f5 --- /dev/null +++ b/solutions/3279-maximum-total-area-occupied-by-pistons.js @@ -0,0 +1,65 @@ +/** + * 3279. Maximum Total Area Occupied by Pistons + * https://leetcode.com/problems/maximum-total-area-occupied-by-pistons/ + * Difficulty: Hard + * + * There are several pistons in an old car engine, and we want to calculate the maximum + * possible area under the pistons. + * + * You are given: + * - An integer height, representing the maximum height a piston can reach. + * - An integer array positions, where positions[i] is the current position of piston i, + * which is equal to the current area under it. + * - A string directions, where directions[i] is the current moving direction of piston + * i, 'U' for up, and 'D' for down. + * + * Each second: + * - Every piston moves in its current direction 1 unit. e.g., if the direction is up, + * positions[i] is incremented by 1. + * - If a piston has reached one of the ends, i.e., positions[i] == 0 or + * positions[i] == height, its direction will change. + * + * Return the maximum possible area under all the pistons. + */ + +/** + * @param {number} height + * @param {number[]} positions + * @param {string} directions + * @return {number} + */ +var maxArea = function(height, positions, directions) { + const n = directions.length; + let upCount = directions.split('').filter(dir => dir === 'U').length; + let result = positions.reduce((sum, pos) => sum + pos, 0); + let currentArea = result; + const vertices = new Map(); + vertices.set(0, 0); + + for (let i = 0; i < n; i++) { + const direction = directions[i]; + const position = positions[i]; + + if (direction === 'U') { + vertices.set(height - position, (vertices.get(height - position) || 0) - 1); + vertices.set(2 * height - position, (vertices.get(2 * height - position) || 0) + 1); + } else { + vertices.set(height + position, (vertices.get(height + position) || 0) - 1); + vertices.set(position, (vertices.get(position) || 0) + 1); + } + } + + const sortedTimes = Array.from(vertices.keys()).sort((a, b) => a - b); + for (let i = 0; i < sortedTimes.length - 1; i++) { + const leftTime = sortedTimes[i]; + const rightTime = sortedTimes[i + 1]; + + currentArea += (rightTime - leftTime) * (2 * upCount - n); + if (currentArea > result) { + result = currentArea; + } + upCount += vertices.get(rightTime) || 0; + } + + return result; +}; diff --git a/solutions/3284-sum-of-consecutive-subarrays.js b/solutions/3284-sum-of-consecutive-subarrays.js new file mode 100644 index 00000000..58d7fe8b --- /dev/null +++ b/solutions/3284-sum-of-consecutive-subarrays.js @@ -0,0 +1,50 @@ +/** + * 3284. Sum of Consecutive Subarrays + * https://leetcode.com/problems/sum-of-consecutive-subarrays/ + * Difficulty: Medium + * + * We call an array arr of length n consecutive if one of the following holds: + * - arr[i] - arr[i - 1] == 1 for all 1 <= i < n. + * - arr[i] - arr[i - 1] == -1 for all 1 <= i < n. + * + * The value of an array is the sum of its elements. + * + * For example, [3, 4, 5] is a consecutive array of value 12 and [9, 8] is another of + * value 17. While [3, 4, 3] and [8, 6] are not consecutive. + * + * Given an array of integers nums, return the sum of the values of all consecutive subarrays. + * + * Since the answer may be very large, return it modulo 109 + 7. + * + * Note that an array of length 1 is also considered consecutive. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var getSum = function(nums) { + const MOD = 1e9 + 7; + let result = nums[0]; + let currentContribution = nums[0]; + let leftBoundary = 0; + let previousDifference = 0; + + for (let rightIndex = 1; rightIndex < nums.length; rightIndex++) { + const currentDifference = nums[rightIndex] - nums[rightIndex - 1]; + if (Math.abs(currentDifference) !== 1) { + previousDifference = 0; + leftBoundary = rightIndex; + currentContribution = 0; + } else if (previousDifference !== currentDifference) { + currentContribution = nums[rightIndex - 1]; + leftBoundary = rightIndex - 1; + previousDifference = currentDifference; + } + + currentContribution += nums[rightIndex] * (rightIndex - leftBoundary + 1); + result = (result + currentContribution) % MOD; + } + + return result; +}; diff --git a/solutions/3289-the-two-sneaky-numbers-of-digitville.js b/solutions/3289-the-two-sneaky-numbers-of-digitville.js new file mode 100644 index 00000000..00f41559 --- /dev/null +++ b/solutions/3289-the-two-sneaky-numbers-of-digitville.js @@ -0,0 +1,31 @@ +/** + * 3289. The Two Sneaky Numbers of Digitville + * https://leetcode.com/problems/the-two-sneaky-numbers-of-digitville/ + * Difficulty: Easy + * + * In the town of Digitville, there was a list of numbers called nums containing integers + * from 0 to n - 1. Each number was supposed to appear exactly once in the list, however, + * two mischievous numbers sneaked in an additional time, making the list longer than usual. + * + * As the town detective, your task is to find these two sneaky numbers. Return an array of + * size two containing the two numbers (in any order), so peace can return to Digitville. + */ + +/** + * @param {number[]} nums + * @return {number[]} + */ +var getSneakyNumbers = function(nums) { + const set = new Set(); + const result = []; + + for (const n of nums) { + if (set.has(n)) { + result.push(n); + } else { + set.add(n); + } + } + + return result; +}; diff --git a/solutions/3294-convert-doubly-linked-list-to-array-ii.js b/solutions/3294-convert-doubly-linked-list-to-array-ii.js new file mode 100644 index 00000000..42fb0c28 --- /dev/null +++ b/solutions/3294-convert-doubly-linked-list-to-array-ii.js @@ -0,0 +1,39 @@ +/** + * 3294. Convert Doubly Linked List to Array II + * https://leetcode.com/problems/convert-doubly-linked-list-to-array-ii/ + * Difficulty: Medium + * + * You are given an arbitrary node from a doubly linked list, which contains nodes that + * have a next pointer and a previous pointer. + * + * Return an integer array which contains the elements of the linked list in order. + */ + +/** + * // Definition for a _Node. + * function _Node(val,prev,next) { + * this.val = val; + * this.prev = prev; + * this.next = next; + * }; + */ +/** + * @param {_Node} node + * @return {number[]} + */ +var toArray = function(node) { + const result = []; + let headNode = node; + + while (headNode.prev) { + headNode = headNode.prev; + } + + let currentNode = headNode; + while (currentNode) { + result.push(currentNode.val); + currentNode = currentNode.next; + } + + return result; +}; diff --git a/solutions/3299-sum-of-consecutive-subsequences.js b/solutions/3299-sum-of-consecutive-subsequences.js new file mode 100644 index 00000000..84340f66 --- /dev/null +++ b/solutions/3299-sum-of-consecutive-subsequences.js @@ -0,0 +1,48 @@ +/** + * 3299. Sum of Consecutive Subsequences + * https://leetcode.com/problems/sum-of-consecutive-subsequences/ + * Difficulty: Hard + * + * We call an array arr of length n consecutive if one of the following holds: + * - arr[i] - arr[i - 1] == 1 for all 1 <= i < n. + * - arr[i] - arr[i - 1] == -1 for all 1 <= i < n. + * + * The value of an array is the sum of its elements. + * + * For example, [3, 4, 5] is a consecutive array of value 12 and [9, 8] is another of + * value 17. While [3, 4, 3] and [8, 6] are not consecutive. + * + * Given an array of integers nums, return the sum of the values of all consecutive + * non-empty subsequences. + * + * Since the answer may be very large, return it modulo 109 + 7. + * + * Note that an array of length 1 is also considered consecutive. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var getSum = function(nums) { + const MOD = 1e9 + 7; + const singleElementSum = nums.reduce((sum, num) => (sum + num) % MOD, 0); + + return (getSubSum(nums, 1) + getSubSum(nums, -1) + singleElementSum) % MOD; + + function getSubSum(nums, direction) { + const count = new Array(100002).fill(0); + const sum = new Array(100002).fill(0); + let result = 0; + + for (const num of nums) { + const prev = num - direction; + const sumAtNum = (sum[prev] + num * (count[prev] + 1)) % MOD; + result = (result + sumAtNum - num + MOD) % MOD; + sum[num] = (sum[num] + sumAtNum) % MOD; + count[num] = (count[num] + count[prev] + 1) % MOD; + } + + return result; + } +}; diff --git a/solutions/3304-find-the-k-th-character-in-string-game-i.js b/solutions/3304-find-the-k-th-character-in-string-game-i.js new file mode 100644 index 00000000..7c192745 --- /dev/null +++ b/solutions/3304-find-the-k-th-character-in-string-game-i.js @@ -0,0 +1,39 @@ +/** + * 3304. Find the K-th Character in String Game I + * https://leetcode.com/problems/find-the-k-th-character-in-string-game-i/ + * Difficulty: Easy + * + * Alice and Bob are playing a game. Initially, Alice has a string word = "a". + * + * You are given a positive integer k. + * + * Now Bob will ask Alice to perform the following operation forever: + * - Generate a new string by changing each character in word to its next character in the + * English alphabet, and append it to the original word. + * + * For example, performing the operation on "c" generates "cd" and performing the operation + * on "zb" generates "zbac". + * + * Return the value of the kth character in word, after enough operations have been done for + * word to have at least k characters. + * + * Note that the character 'z' can be changed to 'a' in the operation. + */ + +/** + * @param {number} k + * @return {character} + */ +var kthCharacter = function(k) { + let word = 'a'; + + while (word.length < k) { + let nextPart = ''; + for (const char of word) { + nextPart += String.fromCharCode(((char.charCodeAt(0) - 97 + 1) % 26) + 97); + } + word += nextPart; + } + + return word[k - 1]; +}; diff --git a/solutions/3307-find-the-k-th-character-in-string-game-ii.js b/solutions/3307-find-the-k-th-character-in-string-game-ii.js new file mode 100644 index 00000000..33329c8c --- /dev/null +++ b/solutions/3307-find-the-k-th-character-in-string-game-ii.js @@ -0,0 +1,54 @@ +/** + * 3307. Find the K-th Character in String Game II + * https://leetcode.com/problems/find-the-k-th-character-in-string-game-ii/ + * Difficulty: Hard + * + * Alice and Bob are playing a game. Initially, Alice has a string word = "a". + * + * You are given a positive integer k. You are also given an integer array operations, + * where operations[i] represents the type of the ith operation. + * + * Now Bob will ask Alice to perform all operations in sequence: + * - If operations[i] == 0, append a copy of word to itself. + * - If operations[i] == 1, generate a new string by changing each character in word to + * its next character in the English alphabet, and append it to the original word. + * For example, performing the operation on "c" generates "cd" and performing the + * operation on "zb" generates "zbac". + * + * Return the value of the kth character in word after performing all the operations. + * + * Note that the character 'z' can be changed to 'a' in the second type of operation. + */ + +/** + * @param {number} k + * @param {number[]} operations + * @return {character} + */ +var kthCharacter = function(k, operations) { + const validOperations = []; + let length = 1; + + for (const op of operations) { + if (length >= k) break; + validOperations.push(op); + length *= 2; + } + + return findCharacter(k, validOperations.length - 1, 0); + + function findCharacter(position, operationIndex, shifts) { + if (operationIndex < 0) { + return String.fromCharCode(97 + (shifts % 26)); + } + + const halfLength = Math.pow(2, operationIndex); + + if (position <= halfLength) { + return findCharacter(position, operationIndex - 1, shifts); + } else { + const newShifts = shifts + validOperations[operationIndex]; + return findCharacter(position - halfLength, operationIndex - 1, newShifts); + } + } +}; diff --git a/solutions/3313-find-the-last-marked-nodes-in-tree.js b/solutions/3313-find-the-last-marked-nodes-in-tree.js new file mode 100644 index 00000000..e72ce1f6 --- /dev/null +++ b/solutions/3313-find-the-last-marked-nodes-in-tree.js @@ -0,0 +1,89 @@ +/** + * 3313. Find the Last Marked Nodes in Tree + * https://leetcode.com/problems/find-the-last-marked-nodes-in-tree/ + * Difficulty: Hard + * + * There exists an undirected tree with n nodes numbered 0 to n - 1. You are given a 2D + * integer array edges of length n - 1, where edges[i] = [ui, vi] indicates that there + * is an edge between nodes ui and vi in the tree. + * + * Initially, all nodes are unmarked. After every second, you mark all unmarked nodes which + * have at least one marked node adjacent to them. + * + * Return an array nodes where nodes[i] is the last node to get marked in the tree, if you + * mark node i at time t = 0. If nodes[i] has multiple answers for any node i, you can + * choose any one answer. + */ + +/** + * @param {number[][]} edges + * @return {number[]} + */ +var lastMarkedNodes = function(edges) { + const n = edges.length + 1; + const tree = new Array(n).fill().map(() => []); + + for (const [u, v] of edges) { + tree[u].push(v); + tree[v].push(u); + } + + const diameterEndpointA = findFarthestNode(0); + const diameterEndpointB = findFarthestNode(diameterEndpointA); + const distancesFromA = getDistances(diameterEndpointA); + const distancesFromB = getDistances(diameterEndpointB); + const result = []; + + for (let i = 0; i < n; i++) { + result.push(distancesFromA[i] > distancesFromB[i] ? diameterEndpointA : diameterEndpointB); + } + + return result; + + function findFarthestNode(startNode) { + const visited = new Array(n).fill(false); + visited[startNode] = true; + const stack = [[startNode, 0]]; + let maxSteps = 0; + let farthestNode = startNode; + + while (stack.length > 0) { + const [node, steps] = stack.pop(); + + if (steps > maxSteps) { + farthestNode = node; + maxSteps = steps; + } + + for (const neighbor of tree[node]) { + if (!visited[neighbor]) { + visited[neighbor] = true; + stack.push([neighbor, steps + 1]); + } + } + } + + return farthestNode; + } + + function getDistances(startNode) { + const visited = new Array(n).fill(false); + visited[startNode] = true; + const stack = [[startNode, 0]]; + const distances = new Array(n); + + while (stack.length > 0) { + const [node, steps] = stack.pop(); + distances[node] = steps; + + for (const neighbor of tree[node]) { + if (!visited[neighbor]) { + visited[neighbor] = true; + stack.push([neighbor, steps + 1]); + } + } + } + + return distances; + } +}; diff --git a/solutions/3318-find-x-sum-of-all-k-long-subarrays-i.js b/solutions/3318-find-x-sum-of-all-k-long-subarrays-i.js new file mode 100644 index 00000000..2a030036 --- /dev/null +++ b/solutions/3318-find-x-sum-of-all-k-long-subarrays-i.js @@ -0,0 +1,60 @@ +/** + * 3318. Find X-Sum of All K-Long Subarrays I + * https://leetcode.com/problems/find-x-sum-of-all-k-long-subarrays-i/ + * Difficulty: Easy + * + * You are given an array nums of n integers and two integers k and x. + * + * The x-sum of an array is calculated by the following procedure: + * - Count the occurrences of all elements in the array. + * - Keep only the occurrences of the top x most frequent elements. If two elements + * have the same number of occurrences, the element with the bigger value is + * considered more frequent. + * - Calculate the sum of the resulting array. + * + * Note that if an array has less than x distinct elements, its x-sum is the sum of the array. + * + Return an integer array answer of length n - k + 1 where answer[i] is the x-sum of the + subarray nums[i..i + k - 1]. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @param {number} x + * @return {number[]} + */ +var findXSum = function(nums, k, x) { + const n = nums.length; + const result = []; + + for (let i = 0; i <= n - k; i++) { + const subarray = nums.slice(i, i + k); + result.push(helper(subarray)); + } + + return result; + + function helper(subarray) { + const frequency = new Map(); + + for (const num of subarray) { + frequency.set(num, (frequency.get(num) || 0) + 1); + } + + const elements = Array.from(frequency.entries()); + elements.sort((a, b) => { + if (a[1] !== b[1]) return b[1] - a[1]; + return b[0] - a[0]; + }); + + const topX = elements.slice(0, x); + let sum = 0; + + for (const [value, count] of topX) { + sum += value * count; + } + + return sum; + } +}; diff --git a/solutions/3323-minimize-connected-groups-by-inserting-interval.js b/solutions/3323-minimize-connected-groups-by-inserting-interval.js new file mode 100644 index 00000000..739e066b --- /dev/null +++ b/solutions/3323-minimize-connected-groups-by-inserting-interval.js @@ -0,0 +1,71 @@ +/** + * 3323. Minimize Connected Groups by Inserting Interval + * https://leetcode.com/problems/minimize-connected-groups-by-inserting-interval/ + * Difficulty: Medium + * + * You are given a 2D array intervals, where intervals[i] = [starti, endi] represents the + * start and the end of interval i. You are also given an integer k. + * + * You must add exactly one new interval [startnew, endnew] to the array such that: + * - The length of the new interval, endnew - startnew, is at most k. + * - After adding, the number of connected groups in intervals is minimized. + * + * A connected group of intervals is a maximal collection of intervals that, when considered + * together, cover a continuous range from the smallest point to the largest point with no gaps + * between them. Here are some examples: + * - A group of intervals [[1, 2], [2, 5], [3, 3]] is connected because together they cover the + * range from 1 to 5 without any gaps. + * - However, a group of intervals [[1, 2], [3, 4]] is not connected because the segment (2, 3) + * is not covered. + * + * Return the minimum number of connected groups after adding exactly one new interval to the array. + */ + +/** + * @param {number[][]} intervals + * @param {number} k + * @return {number} + */ +var minConnectedGroups = function(intervals, k) { + intervals.sort((a, b) => a[0] - b[0]); + + const groupStarts = [intervals[0][0]]; + const groupEnds = [intervals[0][1]]; + + for (let i = 1; i < intervals.length; i++) { + const [start, end] = intervals[i]; + + if (start > groupEnds[groupEnds.length - 1]) { + groupStarts.push(start); + groupEnds.push(end); + } else if (start <= groupEnds[groupEnds.length - 1] && groupEnds[groupEnds.length - 1] < end) { + groupEnds[groupEnds.length - 1] = end; + } + } + + let maxGroupsToMerge = 0; + for (let i = 0; i < groupEnds.length; i++) { + const searchTarget = groupEnds[i] + k + 1; + const rightmostIndex = binarySearchLeft(groupStarts, searchTarget) - 1; + const groupsCanReach = rightmostIndex - i; + maxGroupsToMerge = Math.max(maxGroupsToMerge, groupsCanReach); + } + + return groupStarts.length - maxGroupsToMerge; + + function binarySearchLeft(arr, target) { + let left = 0; + let right = arr.length; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (arr[mid] < target) { + left = mid + 1; + } else { + right = mid; + } + } + + return left; + } +}; diff --git a/solutions/3329-count-substrings-with-k-frequency-characters-ii.js b/solutions/3329-count-substrings-with-k-frequency-characters-ii.js new file mode 100644 index 00000000..e6fb73df --- /dev/null +++ b/solutions/3329-count-substrings-with-k-frequency-characters-ii.js @@ -0,0 +1,34 @@ +/** + * 3329. Count Substrings With K-Frequency Characters II + * https://leetcode.com/problems/count-substrings-with-k-frequency-characters-ii/ + * Difficulty: Hard + * + * Given a string s and an integer k, return the total number of substrings of s where at + * least one character appears at least k times. + */ + +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +var numberOfSubstrings = function(s, k) { + const n = s.length; + const map = new Array(26).fill(0); + let result = 0; + let leftPointer = 0; + + for (let rightPointer = 0; rightPointer < n; rightPointer++) { + const rightCharIndex = s.charCodeAt(rightPointer) - 97; + map[rightCharIndex]++; + + while (map[rightCharIndex] >= k) { + result += n - rightPointer; + const leftCharIndex = s.charCodeAt(leftPointer) - 97; + map[leftCharIndex]--; + leftPointer++; + } + } + + return result; +}; diff --git a/solutions/3330-find-the-original-typed-string-i.js b/solutions/3330-find-the-original-typed-string-i.js new file mode 100644 index 00000000..4613a000 --- /dev/null +++ b/solutions/3330-find-the-original-typed-string-i.js @@ -0,0 +1,41 @@ +/** + * 3330. Find the Original Typed String I + * https://leetcode.com/problems/find-the-original-typed-string-i/ + * Difficulty: Easy + * + * Alice is attempting to type a specific string on her computer. However, she tends to be + * clumsy and may press a key for too long, resulting in a character being typed multiple times. + * + * Although Alice tried to focus on her typing, she is aware that she may still have done this + * at most once. + * + * You are given a string word, which represents the final output displayed on Alice's screen. + * + * Return the total number of possible original strings that Alice might have intended to type. + */ + +/** + * @param {string} word + * @return {number} + */ +var possibleStringCount = function(word) { + let result = 1; + let consecutiveCount = 1; + + for (let i = 1; i < word.length; i++) { + if (word[i] === word[i - 1]) { + consecutiveCount++; + } else { + if (consecutiveCount > 1) { + result += consecutiveCount - 1; + } + consecutiveCount = 1; + } + } + + if (consecutiveCount > 1) { + result += consecutiveCount - 1; + } + + return result; +}; diff --git a/solutions/3333-find-the-original-typed-string-ii.js b/solutions/3333-find-the-original-typed-string-ii.js new file mode 100644 index 00000000..607bf17c --- /dev/null +++ b/solutions/3333-find-the-original-typed-string-ii.js @@ -0,0 +1,78 @@ +/** + * 3333. Find the Original Typed String II + * https://leetcode.com/problems/find-the-original-typed-string-ii/ + * Difficulty: Hard + * + * Alice is attempting to type a specific string on her computer. However, she tends to be + * clumsy and may press a key for too long, resulting in a character being typed multiple times. + * + * You are given a string word, which represents the final output displayed on Alice's screen. + * You are also given a positive integer k. + * + * Return the total number of possible original strings that Alice might have intended to type, + * if she was trying to type a string of size at least k. + * + * Since the answer may be very large, return it modulo 109 + 7. + */ + +/** + * @param {string} word + * @param {number} k + * @return {number} + */ +var possibleStringCount = function(word, k) { + const MOD = 1e9 + 7; + const groups = []; + let count = 1; + + for (let i = 1; i < word.length; i++) { + if (word[i] === word[i - 1]) { + count++; + } else { + groups.push(count); + count = 1; + } + } + groups.push(count); + + const n = groups.length; + + let totalWays = 1; + for (const groupSize of groups) { + totalWays = (totalWays * groupSize) % MOD; + } + + if (k <= n) { + return totalWays; + } + + let dp = new Array(k).fill(0); + dp[0] = 1; + + for (let i = 0; i < n; i++) { + const newDp = new Array(k).fill(0); + const groupSize = groups[i]; + + let sum = 0; + for (let j = 0; j < Math.min(groupSize, k); j++) { + sum = (sum + dp[j]) % MOD; + newDp[j + 1] = sum; + } + + for (let j = groupSize; j < k; j++) { + sum = (sum + dp[j] - dp[j - groupSize] + MOD) % MOD; + if (j + 1 < k) { + newDp[j + 1] = sum; + } + } + + dp = newDp; + } + + let invalidWays = 0; + for (let j = 0; j < k; j++) { + invalidWays = (invalidWays + dp[j]) % MOD; + } + + return (totalWays - invalidWays + MOD) % MOD; +}; diff --git a/solutions/3339-find-the-number-of-k-even-arrays.js b/solutions/3339-find-the-number-of-k-even-arrays.js new file mode 100644 index 00000000..3b499ff4 --- /dev/null +++ b/solutions/3339-find-the-number-of-k-even-arrays.js @@ -0,0 +1,46 @@ +/** + * 3339. Find the Number of K-Even Arrays + * https://leetcode.com/problems/find-the-number-of-k-even-arrays/ + * Difficulty: Medium + * + * You are given three integers n, m, and k. + * + * An array arr is called k-even if there are exactly k indices such that, for each + * of these indices i (0 <= i < n - 1): + * - (arr[i] * arr[i + 1]) - arr[i] - arr[i + 1] is even. + * + * Return the number of possible k-even arrays of size n where all elements are in the range [1, m]. + * + * Since the answer may be very large, return it modulo 109 + 7. + */ + +/** + * @param {number} n + * @param {number} m + * @param {number} k + * @return {number} + */ +var countOfArrays = function(n, m, k) { + const MOD = 1e9 + 7; + const oddCount = Math.floor((m + 1) / 2); + const evenCount = Math.floor(m / 2); + const dpOdd = new Array(k + 1).fill(0); + const dpEven = new Array(k + 1).fill(0); + + dpOdd[0] = oddCount; + dpEven[0] = evenCount; + + for (let position = 1; position < n; position++) { + for (let evenPairs = k; evenPairs >= 0; evenPairs--) { + const tempOdd = dpOdd[evenPairs]; + dpOdd[evenPairs] = ((dpEven[evenPairs] + dpOdd[evenPairs]) * oddCount) % MOD; + if (evenPairs > 0) { + dpEven[evenPairs] = ((dpEven[evenPairs - 1] + tempOdd) * evenCount) % MOD; + } else { + dpEven[evenPairs] = (tempOdd * evenCount) % MOD; + } + } + } + + return (dpOdd[k] + dpEven[k]) % MOD; +}; diff --git a/solutions/3344-maximum-sized-array.js b/solutions/3344-maximum-sized-array.js new file mode 100644 index 00000000..76a47f3f --- /dev/null +++ b/solutions/3344-maximum-sized-array.js @@ -0,0 +1,55 @@ +/** + * 3344. Maximum Sized Array + * https://leetcode.com/problems/maximum-sized-array/ + * Difficulty: Medium + * + * Given a positive integer s, let A be a 3D array of dimensions n × n × n, where each + * element A[i][j][k] is defined as: + * - A[i][j][k] = i * (j OR k), where 0 <= i, j, k < n. + * + * Return the maximum possible value of n such that the sum of all elements in array A + * does not exceed s. + */ + +/** + * @param {number} s + * @return {number} + */ +var maxSizedArray = function(s) { + let left = Math.floor(Math.pow(4 * s, 0.2) / 2); + let right = Math.floor(Math.sqrt(2 * Math.sqrt(s))) + 2; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + + if (calculateArraySum(mid) > s) { + right = mid; + } else { + left = mid + 1; + } + } + + return left - 1; + + function getBitOnesCount(n, bitPosition) { + const blockSize = 1 << bitPosition; + const cycleSize = 1 << (bitPosition + 1); + const fullCycles = Math.floor(n / cycleSize); + const remainder = n % cycleSize; + + return fullCycles * blockSize + (remainder > blockSize ? remainder - blockSize : 0); + } + + function calculateArraySum(n) { + let totalSum = 0; + + for (let bitPos = 0; (1 << bitPos) < n; bitPos++) { + const onesCount = getBitOnesCount(n, bitPos); + const zerosCount = n - onesCount; + + totalSum += (n * n - zerosCount * zerosCount) * (1 << bitPos); + } + + return totalSum * (n - 1) * n / 2; + } +}; diff --git a/solutions/3346-maximum-frequency-of-an-element-after-performing-operations-i.js b/solutions/3346-maximum-frequency-of-an-element-after-performing-operations-i.js new file mode 100644 index 00000000..3bc5e43c --- /dev/null +++ b/solutions/3346-maximum-frequency-of-an-element-after-performing-operations-i.js @@ -0,0 +1,62 @@ +/** + * 3346. Maximum Frequency of an Element After Performing Operations I + * https://leetcode.com/problems/maximum-frequency-of-an-element-after-performing-operations-i/ + * Difficulty: Medium + * + * You are given an integer array nums and two integers k and numOperations. + * + * You must perform an operation numOperations times on nums, where in each operation you: + * - Select an index i that was not selected in any previous operations. + * - Add an integer in the range [-k, k] to nums[i]. + * + * Return the maximum possible frequency of any element in nums after performing the operations. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @param {number} numOperations + * @return {number} + */ +var maxFrequency = function(nums, k, numOperations) { + const n = nums.length; + nums.sort((a, b) => a - b); + + const count = new Map(); + for (const num of nums) { + count.set(num, (count.get(num) || 0) + 1); + } + + let result = 0; + let left = 0; + let right = 0; + for (let mid = 0; mid < n; mid++) { + while (nums[mid] - nums[left] > k) { + left++; + } + + while (right < n - 1 && nums[right + 1] - nums[mid] <= k) { + right++; + } + + const total = right - left + 1; + result = Math.max( + result, + Math.min(total - count.get(nums[mid]), numOperations) + count.get(nums[mid]) + ); + } + + left = 0; + for (right = 0; right < n; right++) { + let mid = Math.floor((nums[left] + nums[right]) / 2); + + while (mid - nums[left] > k || nums[right] - mid > k) { + left++; + mid = Math.floor((nums[left] + nums[right]) / 2); + } + + result = Math.max(result, Math.min(right - left + 1, numOperations)); + } + + return result; +}; diff --git a/solutions/3347-maximum-frequency-of-an-element-after-performing-operations-ii.js b/solutions/3347-maximum-frequency-of-an-element-after-performing-operations-ii.js new file mode 100644 index 00000000..fdbe1898 --- /dev/null +++ b/solutions/3347-maximum-frequency-of-an-element-after-performing-operations-ii.js @@ -0,0 +1,62 @@ +/** + * 3347. Maximum Frequency of an Element After Performing Operations II + * https://leetcode.com/problems/maximum-frequency-of-an-element-after-performing-operations-ii + * Difficulty: Hard + * + * You are given an integer array nums and two integers k and numOperations. + * + * You must perform an operation numOperations times on nums, where in each operation you: + * - Select an index i that was not selected in any previous operations. + * - Add an integer in the range [-k, k] to nums[i]. + * + * Return the maximum possible frequency of any element in nums after performing the operations. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @param {number} numOperations + * @return {number} + */ +var maxFrequency = function(nums, k, numOperations) { + const n = nums.length; + nums.sort((a, b) => a - b); + + const count = new Map(); + for (const num of nums) { + count.set(num, (count.get(num) || 0) + 1); + } + + let result = 0; + let left = 0; + let right = 0; + for (let mid = 0; mid < n; mid++) { + while (nums[mid] - nums[left] > k) { + left++; + } + + while (right < n - 1 && nums[right + 1] - nums[mid] <= k) { + right++; + } + + const total = right - left + 1; + result = Math.max( + result, + Math.min(total - count.get(nums[mid]), numOperations) + count.get(nums[mid]) + ); + } + + left = 0; + for (right = 0; right < n; right++) { + let mid = Math.floor((nums[left] + nums[right]) / 2); + + while (mid - nums[left] > k || nums[right] - mid > k) { + left++; + mid = Math.floor((nums[left] + nums[right]) / 2); + } + + result = Math.max(result, Math.min(right - left + 1, numOperations)); + } + + return result; +}; diff --git a/solutions/3349-adjacent-increasing-subarrays-detection-i.js b/solutions/3349-adjacent-increasing-subarrays-detection-i.js new file mode 100644 index 00000000..e2af9ede --- /dev/null +++ b/solutions/3349-adjacent-increasing-subarrays-detection-i.js @@ -0,0 +1,36 @@ +/** + * 3349. Adjacent Increasing Subarrays Detection I + * https://leetcode.com/problems/adjacent-increasing-subarrays-detection-i/ + * Difficulty: Easy + * + * Given an array nums of n integers and an integer k, determine whether there exist two + * adjacent subarrays of length k such that both subarrays are strictly increasing. + * Specifically, check if there are two subarrays starting at indices a and b (a < b), + * where: + * - Both subarrays nums[a..a + k - 1] and nums[b..b + k - 1] are strictly increasing. + * - The subarrays must be adjacent, meaning b = a + k. + * + * Return true if it is possible to find two such subarrays, and false otherwise. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {boolean} + */ +var hasIncreasingSubarrays = function(nums, k) { + for (let i = 0; i <= nums.length - 2 * k; i++) { + if (helper(i, k) && helper(i + k, k)) { + return true; + } + } + + return false; + + function helper(start, length) { + for (let i = start; i < start + length - 1; i++) { + if (nums[i] >= nums[i + 1]) return false; + } + return true; + } +}; diff --git a/solutions/3350-adjacent-increasing-subarrays-detection-ii.js b/solutions/3350-adjacent-increasing-subarrays-detection-ii.js new file mode 100644 index 00000000..7f103b4a --- /dev/null +++ b/solutions/3350-adjacent-increasing-subarrays-detection-ii.js @@ -0,0 +1,45 @@ +/** + * 3350. Adjacent Increasing Subarrays Detection II + * https://leetcode.com/problems/adjacent-increasing-subarrays-detection-ii/ + * Difficulty: Medium + * + * Given an array nums of n integers, your task is to find the maximum value of k for which + * there exist two adjacent subarrays of length k each, such that both subarrays are strictly + * increasing. Specifically, check if there are two subarrays of length k starting at indices + * a and b (a < b), where: + * - Both subarrays nums[a..a + k - 1] and nums[b..b + k - 1] are strictly increasing. + * - The subarrays must be adjacent, meaning b = a + k. + * + * Return the maximum possible value of k. + * + * A subarray is a contiguous non-empty sequence of elements within an array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxIncreasingSubarrays = function(nums) { + const n = nums.length; + const lengths = new Array(n).fill(1); + + for (let i = n - 2; i >= 0; i--) { + if (nums[i] < nums[i + 1]) { + lengths[i] = lengths[i + 1] + 1; + } + } + + let result = 0; + for (let i = 0; i < n; i++) { + const currentLength = lengths[i]; + result = Math.max(result, Math.floor(currentLength / 2)); + + const nextIndex = i + currentLength; + if (nextIndex < n) { + const minLength = Math.min(currentLength, lengths[nextIndex]); + result = Math.max(result, minLength); + } + } + + return result; +}; diff --git a/solutions/3353-minimum-total-operations.js b/solutions/3353-minimum-total-operations.js new file mode 100644 index 00000000..dcda0262 --- /dev/null +++ b/solutions/3353-minimum-total-operations.js @@ -0,0 +1,32 @@ +/** + * 3353. Minimum Total Operations + * https://leetcode.com/problems/minimum-total-operations/ + * Difficulty: Easy + * + * Given an array of integers nums, you can perform any number of operations on this array. + * + * In each operation, you can: + * - Choose a prefix of the array. + * - Choose an integer k (which can be negative) and add k to each element in the chosen prefix. + * + * A prefix of an array is a subarray that starts from the beginning of the array and extends to + * any point within it. + * + * Return the minimum number of operations required to make all elements in arr equal. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minOperations = function(nums) { + let result = 0; + + for (let i = 1; i < nums.length; i++) { + if (nums[i] !== nums[i - 1]) { + result++; + } + } + + return result; +}; diff --git a/solutions/3354-make-array-elements-equal-to-zero.js b/solutions/3354-make-array-elements-equal-to-zero.js new file mode 100644 index 00000000..865cff41 --- /dev/null +++ b/solutions/3354-make-array-elements-equal-to-zero.js @@ -0,0 +1,60 @@ +/** + * 3354. Make Array Elements Equal to Zero + * https://leetcode.com/problems/make-array-elements-equal-to-zero/ + * Difficulty: Easy + * + * You are given an integer array nums. + * + * Start by selecting a starting position curr such that nums[curr] == 0, and choose a movement + * direction of either left or right. + * + * After that, you repeat the following process: + * - If curr is out of the range [0, n - 1], this process ends. + * - If nums[curr] == 0, move in the current direction by incrementing curr if you are moving + * right, or decrementing curr if you are moving left. + * - Else if nums[curr] > 0: + * - Decrement nums[curr] by 1. + * - Reverse your movement direction (left becomes right and vice versa). + * - Take a step in your new direction. + * + * A selection of the initial position curr and movement direction is considered valid if + * every element in nums becomes 0 by the end of the process. + * + * Return the number of possible valid selections. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var countValidSelections = function(nums) { + const n = nums.length; + let result = 0; + + for (let i = 0; i < n; i++) { + if (nums[i] === 0) { + if (helper(i, -1)) result++; + if (helper(i, 1)) result++; + } + } + + return result; + + function helper(startIndex, direction) { + const arr = [...nums]; + let current = startIndex; + let dir = direction; + + while (current >= 0 && current < n) { + if (arr[current] === 0) { + current += dir; + } else { + arr[current]--; + dir = -dir; + current += dir; + } + } + + return arr.every(val => val === 0); + } +}; diff --git a/solutions/3359-find-sorted-submatrices-with-maximum-element-at-most-k.js b/solutions/3359-find-sorted-submatrices-with-maximum-element-at-most-k.js new file mode 100644 index 00000000..666abb66 --- /dev/null +++ b/solutions/3359-find-sorted-submatrices-with-maximum-element-at-most-k.js @@ -0,0 +1,60 @@ +/** + * 3359. Find Sorted Submatrices With Maximum Element at Most K + * https://leetcode.com/problems/find-sorted-submatrices-with-maximum-element-at-most-k/ + * Difficulty: Hard + * + * You are given a 2D matrix grid of size m x n. You are also given a non-negative integer k. + * + * Return the number of submatrices of grid that satisfy the following conditions: + * - The maximum element in the submatrix less than or equal to k. + * - Each row in the submatrix is sorted in non-increasing order. + * + * A submatrix (x1, y1, x2, y2) is a matrix that forms by choosing all cells grid[x][y] + * where x1 <= x <= x2 and y1 <= y <= y2. + */ + +/** + * @param {number[][]} grid + * @param {number} k + * @return {number} + */ +var countSubmatrices = function(grid, k) { + const rows = grid.length; + const cols = grid[0].length; + const groups = new Array(cols).fill().map(() => []); + const sums = new Array(cols).fill(0); + let result = 0; + + for (let row = 0; row < rows; row++) { + const rowLengths = new Array(cols).fill(0); + + for (let col = 0; col < cols; col++) { + if (grid[row][col] <= k) { + rowLengths[col] = (col > 0 && grid[row][col - 1] >= grid[row][col]) + ? rowLengths[col - 1] + 1 + : 1; + let lengthCount = 1; + const stack = groups[col]; + + while (stack.length > 0 && stack[stack.length - 1][0] > rowLengths[col]) { + const [stackLength, stackCount] = stack.pop(); + lengthCount += stackCount; + sums[col] -= stackLength * stackCount; + } + + if (stack.length === 0 || stack[stack.length - 1][0] !== rowLengths[col]) { + stack.push([rowLengths[col], 0]); + } + + stack[stack.length - 1][1] += lengthCount; + sums[col] += rowLengths[col] * lengthCount; + result += sums[col]; + } else { + groups[col].length = 0; + sums[col] = 0; + } + } + } + + return result; +}; diff --git a/solutions/3363-find-the-maximum-number-of-fruits-collected.js b/solutions/3363-find-the-maximum-number-of-fruits-collected.js new file mode 100644 index 00000000..9e512715 --- /dev/null +++ b/solutions/3363-find-the-maximum-number-of-fruits-collected.js @@ -0,0 +1,84 @@ +/** + * 3363. Find the Maximum Number of Fruits Collected + * https://leetcode.com/problems/find-the-maximum-number-of-fruits-collected/ + * Difficulty: Hard + * + * There is a game dungeon comprised of n x n rooms arranged in a grid. + * + * You are given a 2D array fruits of size n x n, where fruits[i][j] represents the number of fruits + * in the room (i, j). Three children will play in the game dungeon, with initial positions at the + * corner rooms (0, 0), (0, n - 1), and (n - 1, 0). + * + * The children will make exactly n - 1 moves according to the following rules to reach the + * room (n - 1, n - 1): + * - The child starting from (0, 0) must move from their current room (i, j) to one of the rooms + * (i + 1, j + 1), (i + 1, j), and (i, j + 1) if the target room exists. + * - The child starting from (0, n - 1) must move from their current room (i, j) to one of the rooms + * (i + 1, j - 1), (i + 1, j), and (i + 1, j + 1) if the target room exists. + * - The child starting from (n - 1, 0) must move from their current room (i, j) to one of the rooms + * (i - 1, j + 1), (i, j + 1), and (i + 1, j + 1) if the target room exists. + * + * When a child enters a room, they will collect all the fruits there. If two or more children + * enter the same room, only one child will collect the fruits, and the room will be emptied after + * they leave. + * + * Return the maximum number of fruits the children can collect from the dungeon. + */ + +/** + * @param {number[][]} fruits + * @return {number} + */ +var maxCollectedFruits = function(fruits) { + const n = fruits.length; + const dp = Array(n).fill().map(() => Array(n).fill(-1)); + const dp2 = Array(n).fill().map(() => Array(n).fill(-1)); + + let diagonalSum = 0; + for (let i = 0; i < n; i++) { + diagonalSum += fruits[i][i]; + } + + const child2Max = solveChild2(0, n - 1); + const child3Max = solveChild3(n - 1, 0); + + return diagonalSum + child2Max + child3Max; + + function solveChild2(row, col) { + if (row === n - 1 && col === n - 1) return 0; + if (row >= n || col < 0 || col >= n || row > col + 1) return -Infinity; + if (dp[row][col] !== -1) return dp[row][col]; + + const value = (row === col) ? 0 : fruits[row][col]; + let maxNext = -Infinity; + + for (const [dr, dc] of [[1, -1], [1, 0], [1, 1]]) { + const newRow = row + dr; + const newCol = col + dc; + if (newRow < n && newCol >= 0 && newCol < n) { + maxNext = Math.max(maxNext, solveChild2(newRow, newCol)); + } + } + + return dp[row][col] = value + maxNext; + } + + function solveChild3(row, col) { + if (row === n - 1 && col === n - 1) return 0; + if (row < 0 || row >= n || col >= n || row + col < n - 1) return -Infinity; + if (dp2[row][col] !== -1) return dp2[row][col]; + + const value = (row === col) ? 0 : fruits[row][col]; + let maxNext = -Infinity; + + for (const [dr, dc] of [[-1, 1], [0, 1], [1, 1]]) { + const newRow = row + dr; + const newCol = col + dc; + if (newRow >= 0 && newRow < n && newCol < n) { + maxNext = Math.max(maxNext, solveChild3(newRow, newCol)); + } + } + + return dp2[row][col] = value + maxNext; + } +}; diff --git a/solutions/3369-design-an-array-statistics-tracker.js b/solutions/3369-design-an-array-statistics-tracker.js new file mode 100644 index 00000000..4cbeec69 --- /dev/null +++ b/solutions/3369-design-an-array-statistics-tracker.js @@ -0,0 +1,139 @@ +/** + * 3369. Design an Array Statistics Tracker + * https://leetcode.com/problems/design-an-array-statistics-tracker/ + * Difficulty: Hard + * + * Design a data structure that keeps track of the values in it and answers some queries regarding + * their mean, median, and mode. + * + * Implement the StatisticsTracker class. + * - StatisticsTracker(): Initialize the StatisticsTracker object with an empty array. + * - void addNumber(int number): Add number to the data structure. + * - void removeFirstAddedNumber(): Remove the earliest added number from the data structure. + * - int getMean(): Return the floored mean of the numbers in the data structure. + * - int getMedian(): Return the median of the numbers in the data structure. + * - int getMode(): Return the mode of the numbers in the data structure. If there are multiple + * modes, return the smallest one. + * + * Note: + * - The mean of an array is the sum of all the values divided by the number of values in the array. + * - The median of an array is the middle element of the array when it is sorted in non-decreasing + * order. If there are two choices for a median, the larger of the two values is taken. + * - The mode of an array is the element that appears most often in the array. + */ + +var StatisticsTracker = function() { + this.deque = []; + this.count = new Map(); + this.frequencyHeap = new PriorityQueue((a, b) => { + if (a[0] !== b[0]) return b[0] - a[0]; + return a[1] - b[1]; + }); + this.total = 0; + + this.smallHeap = new PriorityQueue((a, b) => b - a); + this.largeHeap = new PriorityQueue((a, b) => a - b); + this.largeRemove = new Map(); + this.smallRemove = new Map(); + this.balance = 0; +}; + +/** + * @param {number} number + * @return {void} + */ +StatisticsTracker.prototype.addNumber = function(number) { + this.deque.push(number); + this.total += number; + + const currentCount = this.count.get(number) || 0; + this.count.set(number, currentCount + 1); + this.frequencyHeap.enqueue([this.count.get(number), number]); + + if (this.largeHeap.isEmpty() || number >= this.largeHeap.front()) { + this.largeHeap.enqueue(number); + this.balance += 1; + } else { + this.smallHeap.enqueue(number); + this.balance -= 1; + } + + this.keepBalance(); +}; + +/** + * @return {void} + */ +StatisticsTracker.prototype.removeFirstAddedNumber = function() { + const value = this.deque.shift(); + + const currentCount = this.count.get(value); + this.count.set(value, currentCount - 1); + if (this.count.get(value) > 0) { + this.frequencyHeap.enqueue([this.count.get(value), value]); + } + + this.total -= value; + + if (!this.largeHeap.isEmpty() && value >= this.largeHeap.front()) { + this.largeRemove.set(value, (this.largeRemove.get(value) || 0) + 1); + this.balance -= 1; + } else { + this.smallRemove.set(value, (this.smallRemove.get(value) || 0) + 1); + this.balance += 1; + } + + this.keepBalance(); +}; + +/** + * @return {void} + */ +StatisticsTracker.prototype.keepBalance = function() { + if (this.balance > 1) { + this.smallHeap.enqueue(this.largeHeap.dequeue()); + this.balance -= 2; + } + if (this.balance < 0) { + this.largeHeap.enqueue(this.smallHeap.dequeue()); + this.balance += 2; + } + + while (!this.smallHeap.isEmpty() && (this.smallRemove.get(this.smallHeap.front()) || 0) > 0) { + const removed = this.smallHeap.dequeue(); + this.smallRemove.set(removed, this.smallRemove.get(removed) - 1); + } + + while (!this.largeHeap.isEmpty() && (this.largeRemove.get(this.largeHeap.front()) || 0) > 0) { + const removed = this.largeHeap.dequeue(); + this.largeRemove.set(removed, this.largeRemove.get(removed) - 1); + } +}; + +/** + * @return {number} + */ +StatisticsTracker.prototype.getMean = function() { + return Math.floor(this.total / this.deque.length); +}; + +/** + * @return {number} + */ +StatisticsTracker.prototype.getMedian = function() { + return this.largeHeap.front(); +}; + +/** + * @return {number} + */ +StatisticsTracker.prototype.getMode = function() { + while (!this.frequencyHeap.isEmpty()) { + const [frequency, value] = this.frequencyHeap.front(); + if (this.count.get(value) === frequency) { + return value; + } else { + this.frequencyHeap.dequeue(); + } + } +}; diff --git a/solutions/3370-smallest-number-with-all-set-bits.js b/solutions/3370-smallest-number-with-all-set-bits.js new file mode 100644 index 00000000..ea6b33ca --- /dev/null +++ b/solutions/3370-smallest-number-with-all-set-bits.js @@ -0,0 +1,20 @@ +/** + * 3370. Smallest Number With All Set Bits + * https://leetcode.com/problems/smallest-number-with-all-set-bits/ + * Difficulty: Easy + * + * You are given a positive number n. + * + * Return the smallest number x greater than or equal to n, such that the binary + * representation of x contains only set bits + */ + +/** + * @param {number} n + * @return {number} + */ +var smallestNumber = function(n) { + const bits = n.toString(2).length; + const result = (1 << bits) - 1; + return result >= n ? result : (1 << (bits + 1)) - 1; +}; diff --git a/solutions/3383-minimum-runes-to-add-to-cast-spell.js b/solutions/3383-minimum-runes-to-add-to-cast-spell.js new file mode 100644 index 00000000..c03f08ee --- /dev/null +++ b/solutions/3383-minimum-runes-to-add-to-cast-spell.js @@ -0,0 +1,95 @@ +/** + * 3383. Minimum Runes to Add to Cast Spell + * https://leetcode.com/problems/minimum-runes-to-add-to-cast-spell/ + * Difficulty: Hard + * + * Alice has just graduated from wizard school, and wishes to cast a magic spell to celebrate. + * The magic spell contains certain focus points where magic needs to be concentrated, and some + * of these focus points contain magic crystals which serve as the spell's energy source. Focus + * points can be linked through directed runes, which channel magic flow from one focus point + * to another. + * + * You are given a integer n denoting the number of focus points and an array of integers crystals + * where crystals[i] indicates a focus point which holds a magic crystal. You are also given two + * integer arrays flowFrom and flowTo, which represent the existing directed runes. The ith rune + * allows magic to freely flow from focus point flowFrom[i] to focus point flowTo[i]. + * + * You need to find the number of directed runes Alice must add to her spell, such that each + * focus point either: + * - Contains a magic crystal. + * - Receives magic flow from another focus point. + * + * Return the minimum number of directed runes that she should add. + */ + +/** + * @param {number} n + * @param {number[]} crystals + * @param {number[]} flowFrom + * @param {number[]} flowTo + * @return {number} + */ +var minRunesToAdd = function(n, crystals, flowFrom, flowTo) { + const graph = Array.from({ length: n }, () => []); + const reverseGraph = Array.from({ length: n }, () => []); + + for (let i = 0; i < flowFrom.length; i++) { + graph[flowFrom[i]].push(flowTo[i]); + reverseGraph[flowTo[i]].push(flowFrom[i]); + } + + const visited = new Array(n).fill(false); + const finishOrder = []; + + const dfsFinish = (node) => { + if (visited[node]) return; + visited[node] = true; + for (const neighbor of graph[node]) { + dfsFinish(neighbor); + } + finishOrder.push(node); + }; + + for (let i = 0; i < n; i++) { + dfsFinish(i); + } + + const componentId = new Array(n).fill(-1); + let componentCount = 0; + + const dfsComponent = (node, id) => { + if (componentId[node] >= 0) return; + componentId[node] = id; + for (const neighbor of reverseGraph[node]) { + dfsComponent(neighbor, id); + } + }; + + for (let i = n - 1; i >= 0; i--) { + const node = finishOrder[i]; + if (componentId[node] < 0) { + dfsComponent(node, componentCount++); + } + } + + const hasIncoming = new Array(componentCount).fill(false); + for (let i = 0; i < flowFrom.length; i++) { + if (componentId[flowFrom[i]] !== componentId[flowTo[i]]) { + hasIncoming[componentId[flowTo[i]]] = true; + } + } + + const hasCrystal = new Array(componentCount).fill(false); + for (const crystal of crystals) { + hasCrystal[componentId[crystal]] = true; + } + + let result = 0; + for (let i = 0; i < componentCount; i++) { + if (!hasIncoming[i] && !hasCrystal[i]) { + result++; + } + } + + return result; +}; diff --git a/solutions/3385-minimum-time-to-break-locks-ii.js b/solutions/3385-minimum-time-to-break-locks-ii.js new file mode 100644 index 00000000..24541298 --- /dev/null +++ b/solutions/3385-minimum-time-to-break-locks-ii.js @@ -0,0 +1,88 @@ +/** + * 3385. Minimum Time to Break Locks II + * https://leetcode.com/problems/minimum-time-to-break-locks-ii/ + * Difficulty: Hard + * + * Bob is stuck in a dungeon and must break n locks, each requiring some amount of energy + * to break. The required energy for each lock is stored in an array called strength where + * strength[i] indicates the energy needed to break the ith lock. + * + * To break a lock, Bob uses a sword with the following characteristics: + * - The initial energy of the sword is 0. + * - The initial factor X by which the energy of the sword increases is 1. + * - Every minute, the energy of the sword increases by the current factor X. + * - To break the ith lock, the energy of the sword must reach at least strength[i]. + * - After breaking a lock, the energy of the sword resets to 0, and the factor X increases by 1. + * + * Your task is to determine the minimum time in minutes required for Bob to break all n locks + * and escape the dungeon. + * + * Return the minimum time required for Bob to break all n locks. + */ + +/** + * @param {number[]} strength + * @return {number} + */ +var findMinimumTime = function(strength) { + const n = strength.length; + const cost = Array.from({ length: n + 1 }, () => new Array(n + 1).fill(0)); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + cost[i + 1][j + 1] = Math.floor((strength[i] + j) / (j + 1)); + } + } + + const rowPotential = new Array(n + 1).fill(0); + const colPotential = new Array(n + 1).fill(0); + const assignment = new Array(n + 1).fill(0); + const parent = new Array(n + 1).fill(0); + + for (let row = 1; row <= n; row++) { + assignment[0] = row; + let col = 0; + const minCol = new Array(n + 1).fill(Number.MAX_SAFE_INTEGER); + const visited = new Array(n + 1).fill(false); + + do { + visited[col] = true; + const currentRow = assignment[col]; + let delta = Number.MAX_SAFE_INTEGER; + let nextCol; + + for (let j = 1; j <= n; j++) { + if (!visited[j]) { + const reducedCost = cost[currentRow][j] - rowPotential[currentRow] - colPotential[j]; + if (reducedCost < minCol[j]) { + minCol[j] = reducedCost; + parent[j] = col; + } + if (minCol[j] < delta) { + delta = minCol[j]; + nextCol = j; + } + } + } + + for (let j = 0; j <= n; j++) { + if (visited[j]) { + rowPotential[assignment[j]] += delta; + colPotential[j] -= delta; + } else { + minCol[j] -= delta; + } + } + + col = nextCol; + } while (assignment[col] !== 0); + + do { + const prevCol = parent[col]; + assignment[col] = assignment[prevCol]; + col = prevCol; + } while (col); + } + + return -colPotential[0]; +}; diff --git a/solutions/3391-design-a-3d-binary-matrix-with-efficient-layer-tracking.js b/solutions/3391-design-a-3d-binary-matrix-with-efficient-layer-tracking.js new file mode 100644 index 00000000..f24ee5f1 --- /dev/null +++ b/solutions/3391-design-a-3d-binary-matrix-with-efficient-layer-tracking.js @@ -0,0 +1,65 @@ +/** + * 3391. Design a 3D Binary Matrix with Efficient Layer Tracking + * https://leetcode.com/problems/design-a-3d-binary-matrix-with-efficient-layer-tracking/ + * Difficulty: Medium + * + * You are given a n x n x n binary 3D array matrix. + * + * Implement the Matrix3D class: + * - Matrix3D(int n) Initializes the object with the 3D binary array matrix, where all elements + * are initially set to 0. + * - void setCell(int x, int y, int z) Sets the value at matrix[x][y][z] to 1. + * - void unsetCell(int x, int y, int z) Sets the value at matrix[x][y][z] to 0. + * - int largestMatrix() Returns the index x where matrix[x] contains the most number of 1's. + * If there are multiple such indices, return the largest x. + */ + +/** + * @param {number} n + */ +var Matrix3D = function(n) { + this.n = n; + this.matrix = new Set(); + this.layerCounts = new Array(n).fill(0); +}; + +/** + * @param {number} x + * @param {number} y + * @param {number} z + * @return {void} + */ +Matrix3D.prototype.setCell = function(x, y, z) { + const key = `${x},${y},${z}`; + if (!this.matrix.has(key)) { + this.matrix.add(key); + this.layerCounts[x]++; + } +}; + +/** + * @param {number} x + * @param {number} y + * @param {number} z + * @return {void} + */ +Matrix3D.prototype.unsetCell = function(x, y, z) { + const key = `${x},${y},${z}`; + if (this.matrix.has(key)) { + this.matrix.delete(key); + this.layerCounts[x]--; + } +}; + +/** + * @return {number} + */ +Matrix3D.prototype.largestMatrix = function() { + const maxCount = Math.max(...this.layerCounts); + for (let i = this.n - 1; i >= 0; i--) { + if (this.layerCounts[i] === maxCount) { + return i; + } + } + return this.n - 1; +}; diff --git a/solutions/3400-maximum-number-of-matching-indices-after-right-shifts.js b/solutions/3400-maximum-number-of-matching-indices-after-right-shifts.js new file mode 100644 index 00000000..6d510880 --- /dev/null +++ b/solutions/3400-maximum-number-of-matching-indices-after-right-shifts.js @@ -0,0 +1,37 @@ +/** + * 3400. Maximum Number of Matching Indices After Right Shifts + * https://leetcode.com/problems/maximum-number-of-matching-indices-after-right-shifts/ + * Difficulty: Medium + * + * You are given two integer arrays, nums1 and nums2, of the same length. + * + * An index i is considered matching if nums1[i] == nums2[i]. + * + * Return the maximum number of matching indices after performing any number of right shifts + * on nums1. + * + * A right shift is defined as shifting the element at index i to index (i + 1) % n, for + * all indices. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var maximumMatchingIndices = function(nums1, nums2) { + const n = nums1.length; + let result = 0; + + for (let shift = 0; shift < n; shift++) { + let currentMatches = 0; + for (let i = 0; i < n; i++) { + if (nums1[(i - shift + n) % n] === nums2[i]) { + currentMatches++; + } + } + result = Math.max(result, currentMatches); + } + + return result; +}; diff --git a/solutions/3403-find-the-lexicographically-largest-string-from-the-box-i.js b/solutions/3403-find-the-lexicographically-largest-string-from-the-box-i.js new file mode 100644 index 00000000..313bc4c7 --- /dev/null +++ b/solutions/3403-find-the-lexicographically-largest-string-from-the-box-i.js @@ -0,0 +1,39 @@ +/** + * 3403. Find the Lexicographically Largest String From the Box I + * https://leetcode.com/problems/find-the-lexicographically-largest-string-from-the-box-i/ + * Difficulty: Medium + * + * You are given a string word, and an integer numFriends. + * + * Alice is organizing a game for her numFriends friends. There are multiple rounds in the game, + * where in each round: + * - word is split into numFriends non-empty strings, such that no previous round has had the + * exact same split. + * - All the split words are put into a box. + * + * Find the lexicographically largest string from the box after all the rounds are finished. + */ + +/** + * @param {string} word + * @param {number} numFriends + * @return {string} + */ +var answerString = function(word, numFriends) { + if (numFriends === 1) return word; + + let result = ''; + const wordLength = word.length; + + for (let startIndex = 0; startIndex < wordLength; startIndex++) { + const maxLength = wordLength - numFriends + 1; + const endIndex = Math.min(startIndex + maxLength, wordLength); + const substring = word.slice(startIndex, endIndex); + + if (substring > result) { + result = substring; + } + } + + return result; +}; diff --git a/solutions/3405-count-the-number-of-arrays-with-k-matching-adjacent-elements.js b/solutions/3405-count-the-number-of-arrays-with-k-matching-adjacent-elements.js new file mode 100644 index 00000000..493e1f28 --- /dev/null +++ b/solutions/3405-count-the-number-of-arrays-with-k-matching-adjacent-elements.js @@ -0,0 +1,69 @@ +/** + * 3405. Count the Number of Arrays with K Matching Adjacent Elements + * https://leetcode.com/problems/count-the-number-of-arrays-with-k-matching-adjacent-elements/ + * Difficulty: Hard + * + * You are given three integers n, m, k. A good array arr of size n is defined as follows: + * - Each element in arr is in the inclusive range [1, m]. + * - Exactly k indices i (where 1 <= i < n) satisfy the condition arr[i - 1] == arr[i]. + * + * Return the number of good arrays that can be formed. + * + * Since the answer may be very large, return it modulo 109 + 7. + */ + +/** + * @param {number} n + * @param {number} m + * @param {number} k + * @return {number} + */ +var countGoodArrays = function(n, m, k) { + const MOD = 1e9 + 7; + + if (m === 1) { + return k === n - 1 ? 1 : 0; + } + + const choose = binomialCoeff(n - 1, k); + const power = modPow(m - 1, n - 1 - k, MOD); + const result = Number((BigInt(choose) * BigInt(m) * BigInt(power)) % BigInt(MOD)); + + return result; + + function modPow(base, exp, mod) { + let result = 1n; + base = ((BigInt(base) % BigInt(mod)) + BigInt(mod)) % BigInt(mod); + exp = BigInt(exp); + mod = BigInt(mod); + + while (exp > 0n) { + if (exp & 1n) result = (result * base) % mod; + base = (base * base) % mod; + exp >>= 1n; + } + return Number(result); + } + + function modInverse(a, mod) { + return modPow(a, mod - 2, mod); + } + + function binomialCoeff(n, k) { + if (k > n || k < 0) return 0; + if (k === 0 || k === n) return 1; + + if (k > n - k) k = n - k; + + let numerator = 1n; + let denominator = 1n; + + for (let i = 0; i < k; i++) { + numerator = (numerator * BigInt(n - i)) % BigInt(MOD); + denominator = (denominator * BigInt(i + 1)) % BigInt(MOD); + } + + const invDenom = modInverse(Number(denominator), MOD); + return Number((numerator * BigInt(invDenom)) % BigInt(MOD)); + } +}; diff --git a/solutions/3406-find-the-lexicographically-largest-string-from-the-box-ii.js b/solutions/3406-find-the-lexicographically-largest-string-from-the-box-ii.js new file mode 100644 index 00000000..86021b16 --- /dev/null +++ b/solutions/3406-find-the-lexicographically-largest-string-from-the-box-ii.js @@ -0,0 +1,52 @@ +/** + * 3406. Find the Lexicographically Largest String From the Box II + * https://leetcode.com/problems/find-the-lexicographically-largest-string-from-the-box-ii/ + * Difficulty: Hard + * + * You are given a string word, and an integer numFriends. + * + * Alice is organizing a game for her numFriends friends. There are multiple rounds in the game, + * where in each round: + * - word is split into numFriends non-empty strings, such that no previous round has had the + * exact same split. + * - All the split words are put into a box. + * + * Find the lexicographically largest string from the box after all the rounds are finished. + * + * A string a is lexicographically smaller than a string b if in the first position where a + * and b differ, string a has a letter that appears earlier in the alphabet than the corresponding + * letter in b. + * + * If the first min(a.length, b.length) characters do not differ, then the shorter string is the + * lexicographically smaller one. + */ + +/** + * @param {string} word + * @param {number} numFriends + * @return {string} + */ +var answerString = function(word, numFriends) { + if (numFriends === 1) return word; + const n = word.length; + const maxLength = n - numFriends + 1; + + const pairs = []; + for (let i = 0; i < n - 1; i++) { + pairs.push(word[i] + word[i + 1]); + } + const maxPair = pairs.reduce((a, b) => a > b ? a : b); + let result = word[n - 1]; + let index = -1; + + while (index < n) { + index = word.indexOf(maxPair, index + 1); + if (index === -1) break; + const candidate = word.substring(index, index + maxLength); + if (candidate > result) { + result = candidate; + } + } + + return result; +}; diff --git a/solutions/3408-design-task-manager.js b/solutions/3408-design-task-manager.js new file mode 100644 index 00000000..8d0a56fb --- /dev/null +++ b/solutions/3408-design-task-manager.js @@ -0,0 +1,91 @@ +/** + * 3408. Design Task Manager + * https://leetcode.com/problems/design-task-manager/ + * Difficulty: Medium + * + * There is a task management system that allows users to manage their tasks, each associated + * with a priority. The system should efficiently handle adding, modifying, executing, and + * removing tasks. + * + * Implement the TaskManager class: + * - TaskManager(vector>& tasks) initializes the task manager with a list of + * user-task-priority triples. Each element in the input list is of the form [userId, + * taskId, priority], which adds a task to the specified user with the given priority. + * - void add(int userId, int taskId, int priority) adds a task with the specified taskId + * and priority to the user with userId. It is guaranteed that taskId does not exist in + * the system. + * - void edit(int taskId, int newPriority) updates the priority of the existing taskId to + * newPriority. It is guaranteed that taskId exists in the system. + * - void rmv(int taskId) removes the task identified by taskId from the system. It is + * guaranteed that taskId exists in the system. + * - int execTop() executes the task with the highest priority across all users. If there + * are multiple tasks with the same highest priority, execute the one with the highest + * taskId. After executing, the taskId is removed from the system. Return the userId + * associated with the executed task. If no tasks are available, return -1. + * + * Note that a user may be assigned multiple tasks. + */ + +/** + * @param {number[][]} tasks + */ +var TaskManager = function(tasks) { + this.taskRegistry = {}; + this.priorityHeap = new PriorityQueue((a, b) => { + return a.priority !== b.priority ? b.priority - a.priority : b.taskId - a.taskId; + }); + + for (const [userId, taskId, priority] of tasks) { + this.taskRegistry[taskId] = { userId, priority, version: 1 }; + this.priorityHeap.enqueue({ taskId, priority, version: 1 }); + } +}; + +/** + * @param {number} userId + * @param {number} taskId + * @param {number} priority + * @return {void} + */ +TaskManager.prototype.add = function(userId, taskId, priority) { + this.taskRegistry[taskId] = { userId, priority, version: 1 }; + this.priorityHeap.enqueue({ taskId, priority, version: 1 }); +}; + +/** + * @param {number} taskId + * @param {number} newPriority + * @return {void} + */ +TaskManager.prototype.edit = function(taskId, newPriority) { + const currentTask = this.taskRegistry[taskId]; + currentTask.priority = newPriority; + currentTask.version++; + this.priorityHeap.enqueue({ taskId, priority: newPriority, version: currentTask.version }); +}; + +/** + * @param {number} taskId + * @return {void} + */ +TaskManager.prototype.rmv = function(taskId) { + delete this.taskRegistry[taskId]; +}; + + +/** + * @return {number} + */ +TaskManager.prototype.execTop = function() { + while (!this.priorityHeap.isEmpty()) { + const { taskId, priority, version } = this.priorityHeap.dequeue(); + const activeTask = this.taskRegistry[taskId]; + + if (activeTask && activeTask.priority === priority && activeTask.version === version) { + const executedUserId = activeTask.userId; + delete this.taskRegistry[taskId]; + return executedUserId; + } + } + return -1; +}; diff --git a/solutions/3416-subsequences-with-a-unique-middle-mode-ii.js b/solutions/3416-subsequences-with-a-unique-middle-mode-ii.js new file mode 100644 index 00000000..154e3e73 --- /dev/null +++ b/solutions/3416-subsequences-with-a-unique-middle-mode-ii.js @@ -0,0 +1,107 @@ +/** + * 3416. Subsequences with a Unique Middle Mode II + * https://leetcode.com/problems/subsequences-with-a-unique-middle-mode-ii/ + * Difficulty: Hard + * + * Given an integer array nums, find the number of subsequences of size 5 of nums with + * a unique middle mode. + * + * Since the answer may be very large, return it modulo 109 + 7. + * + * A mode of a sequence of numbers is defined as the element that appears the maximum number + * of times in the sequence. + * + * A sequence of numbers contains a unique mode if it has only one mode. + * + * A sequence of numbers seq of size 5 contains a unique middle mode if the middle element + * (seq[2]) is a unique mode. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var subsequencesWithMiddleMode = function(nums) { + const MOD = 1e9 + 7; + const HALF = (MOD + 1) / 2; + const [compressedNums, uniqueCount] = compress(nums); + const totalCounts = new Array(uniqueCount).fill(0); + compressedNums.forEach(id => totalCounts[id]++); + + const result = countValid(compressedNums, totalCounts, true); + compressedNums.reverse(); + + return add(result, countValid(compressedNums, totalCounts, false)); + + function mul(x, y) { + return Number((BigInt(x) * BigInt(y)) % BigInt(MOD)); + } + + function add(x, y) { + return (x + y) % MOD; + } + + function sub(x, y) { + return (x - y + MOD) % MOD; + } + + function choose2(n) { + return mul(mul(n, n - 1), HALF); + } + + function compress(arr) { + const valueMap = new Map(); + let nextId = 0; + arr.forEach(val => !valueMap.has(val) && valueMap.set(val, nextId++)); + return [arr.map(val => valueMap.get(val)), nextId]; + } + + function countValid(sequence, counts, includeEqual) { + const length = sequence.length; + const seenCounts = new Array(uniqueCount).fill(0); + let result = 0; + let squareSum = 0; + let weightedSum = 0; + let weightedSquareSum = 0; + + counts.forEach(count => squareSum = add(squareSum, mul(count, count))); + + for (let pos = 0; pos < length; pos++) { + const valueId = sequence[pos]; + let remaining = counts[valueId] - seenCounts[valueId]; + const newSquareSum = sub(squareSum, mul(remaining, remaining)); + const newWeightedSum = sub(weightedSum, mul(remaining, seenCounts[valueId])); + const newWeightedSquareSum = sub( + weightedSquareSum, + mul(mul(remaining, remaining), seenCounts[valueId]) + ); + const suffixSize = length - pos - remaining; + const prefixSize = pos - seenCounts[valueId]; + + let contribution = mul(sub(mul(suffixSize, suffixSize), newSquareSum), prefixSize); + contribution = sub(contribution, mul(mul(2, suffixSize), newWeightedSum)); + contribution = add(contribution, mul(2, newWeightedSquareSum)); + contribution = mul(contribution, mul(seenCounts[valueId], HALF)); + result = add(result, contribution); + result = add(result, mul(choose2(seenCounts[valueId]), choose2(suffixSize))); + + remaining--; + result = add(result, mul(choose2(seenCounts[valueId]), mul(remaining, suffixSize))); + + if (includeEqual) { + result = add(result, mul(mul(seenCounts[valueId], prefixSize), mul(remaining, suffixSize))); + result = add(result, mul(choose2(seenCounts[valueId]), choose2(remaining))); + } + + seenCounts[valueId]++; + squareSum = add(newSquareSum, mul(remaining, remaining)); + weightedSum = add(newWeightedSum, mul(remaining, seenCounts[valueId])); + weightedSquareSum = add( + newWeightedSquareSum, + mul(mul(remaining, remaining), seenCounts[valueId]) + ); + } + + return result; + } +}; diff --git a/solutions/3422-minimum-operations-to-make-subarray-elements-equal.js b/solutions/3422-minimum-operations-to-make-subarray-elements-equal.js new file mode 100644 index 00000000..7ea4cb51 --- /dev/null +++ b/solutions/3422-minimum-operations-to-make-subarray-elements-equal.js @@ -0,0 +1,81 @@ +/** + * 3422. Minimum Operations to Make Subarray Elements Equal + * https://leetcode.com/problems/minimum-operations-to-make-subarray-elements-equal/ + * Difficulty: Medium + * + * You are given an integer array nums and an integer k. You can perform the following operation + * any number of times: + * - Increase or decrease any element of nums by 1. + * + * Return the minimum number of operations required to ensure that at least one subarray of size + * k in nums has all elements equal. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minOperations = function(nums, k) { + const n = nums.length; + const minHeap = new PriorityQueue((a, b) => a[0] < b[0] ? -1 : 1); + const maxHeap = new PriorityQueue((a, b) => a[0] > b[0] ? -1 : 1); + const maxHeapSize = Math.ceil(k / 2); + const minHeapSize = k - maxHeapSize; + + let total = 0; + for (let i = 0; i < k; i++) { + total += nums[i]; + maxHeap.enqueue([nums[i], i]); + } + + let minSum = 0; + const minHeapIndices = new Set(); + for (let i = 0; i < minHeapSize; i++) { + const [num, idx] = maxHeap.dequeue(); + minSum += num; + minHeap.enqueue([num, idx]); + minHeapIndices.add(idx); + } + + let maxSum = total - minSum; + let median = maxHeap.front()[0]; + let result = Math.abs(median * maxHeapSize - maxSum) + Math.abs(minSum - median * minHeapSize); + + for (let i = k; i < n; i++) { + const num = nums[i]; + const leftOut = i - k; + total += num - nums[leftOut]; + + while (!minHeap.isEmpty() && minHeap.front()[1] <= leftOut) minHeap.dequeue(); + while (!maxHeap.isEmpty() && maxHeap.front()[1] <= leftOut) maxHeap.dequeue(); + + if (minHeapIndices.has(leftOut)) { + minHeapIndices.delete(leftOut); + minSum -= nums[leftOut]; + maxHeap.enqueue([num, i]); + const [newNum, newIdx] = maxHeap.dequeue(); + minSum += newNum; + minHeap.enqueue([newNum, newIdx]); + minHeapIndices.add(newIdx); + } else { + minHeap.enqueue([num, i]); + minSum += num; + minHeapIndices.add(i); + const [newNum, newIdx] = minHeap.dequeue(); + minHeapIndices.delete(newIdx); + minSum -= newNum; + maxHeap.enqueue([newNum, newIdx]); + } + + maxSum = total - minSum; + while (!maxHeap.isEmpty() && maxHeap.front()[1] <= leftOut) maxHeap.dequeue(); + median = maxHeap.front()[0]; + result = Math.min( + result, + Math.abs(median * maxHeapSize - maxSum) + Math.abs(minSum - median * minHeapSize) + ); + } + + return result; +}; diff --git a/solutions/3423-maximum-difference-between-adjacent-elements-in-a-circular-array.js b/solutions/3423-maximum-difference-between-adjacent-elements-in-a-circular-array.js new file mode 100644 index 00000000..dae3e36c --- /dev/null +++ b/solutions/3423-maximum-difference-between-adjacent-elements-in-a-circular-array.js @@ -0,0 +1,25 @@ +/** + * 3423. Maximum Difference Between Adjacent Elements in a Circular Array + * https://leetcode.com/problems/maximum-difference-between-adjacent-elements-in-a-circular-array/ + * Difficulty: Easy + * + * Given a circular array nums, find the maximum absolute difference between adjacent elements. + * + * Note: In a circular array, the first and last elements are adjacent. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxAdjacentDistance = function(nums) { + let result = 0; + + for (let i = 0; i < nums.length; i++) { + const next = (i + 1) % nums.length; + const diff = Math.abs(nums[i] - nums[next]); + result = Math.max(result, diff); + } + + return result; +}; diff --git a/solutions/3431-minimum-unlocked-indices-to-sort-nums.js b/solutions/3431-minimum-unlocked-indices-to-sort-nums.js new file mode 100644 index 00000000..b36cc9b1 --- /dev/null +++ b/solutions/3431-minimum-unlocked-indices-to-sort-nums.js @@ -0,0 +1,44 @@ +/** + * 3431. Minimum Unlocked Indices to Sort Nums + * https://leetcode.com/problems/minimum-unlocked-indices-to-sort-nums/ + * Difficulty: Medium + * + * You are given an array nums consisting of integers between 1 and 3, and a binary array + * locked of the same size. + * + * We consider nums sortable if it can be sorted using adjacent swaps, where a swap between + * two indices i and i + 1 is allowed if nums[i] - nums[i + 1] == 1 and locked[i] == 0. + * + * In one operation, you can unlock any index i by setting locked[i] to 0. + * + * Return the minimum number of operations needed to make nums sortable. If it is not possible + * to make nums sortable, return -1. + */ + +/** + * @param {number[]} nums + * @param {number[]} locked + * @return {number} + */ +var minUnlockedIndices = function(nums, locked) { + let currentMax = 1; + let locks = 0; + let result = 0; + + for (let i = 0; i < nums.length; i++) { + if (currentMax < nums[i]) { + currentMax = nums[i]; + locks = 0; + } + if (nums[i] < currentMax) { + if (nums[i] + 1 < currentMax) { + return -1; + } + result += locks; + locks = 0; + } + locks += locked[i]; + } + + return result; +}; diff --git a/solutions/3437-permutations-iii.js b/solutions/3437-permutations-iii.js new file mode 100644 index 00000000..ae3e4b8f --- /dev/null +++ b/solutions/3437-permutations-iii.js @@ -0,0 +1,48 @@ +/** + * 3437. Permutations III + * https://leetcode.com/problems/permutations-iii/ + * Difficulty: Medium + * + * Given an integer n, an alternating permutation is a permutation of the first n positive + * integers such that no two adjacent elements are both odd or both even. + * + * Return all such alternating permutations sorted in lexicographical order. + */ + +/** + * @param {number} n + * @return {number[][]} + */ +var permute = function(n) { + const result = []; + const current = []; + const used = new Array(n + 1).fill(false); + + backtrack(current, used, result, n); + + return result; + + function backtrack(current, used, result, n) { + if (current.length === n) { + result.push([...current]); + return; + } + + for (let num = 1; num <= n; num++) { + if (used[num]) continue; + + if (current.length > 0) { + const lastNum = current[current.length - 1]; + if ((lastNum % 2 === 0 && num % 2 === 0) || (lastNum % 2 === 1 && num % 2 === 1)) { + continue; + } + } + + current.push(num); + used[num] = true; + backtrack(current, used, result, n); + current.pop(); + used[num] = false; + } + } +}; diff --git a/solutions/3439-reschedule-meetings-for-maximum-free-time-i.js b/solutions/3439-reschedule-meetings-for-maximum-free-time-i.js new file mode 100644 index 00000000..fb667cc4 --- /dev/null +++ b/solutions/3439-reschedule-meetings-for-maximum-free-time-i.js @@ -0,0 +1,53 @@ +/** + * 3439. Reschedule Meetings for Maximum Free Time I + * https://leetcode.com/problems/reschedule-meetings-for-maximum-free-time-i/ + * Difficulty: Medium + * + * You are given an integer eventTime denoting the duration of an event, where the event occurs + * from time t = 0 to time t = eventTime. + * + * You are also given two integer arrays startTime and endTime, each of length n. These represent + * the start and end time of n non-overlapping meetings, where the ith meeting occurs during the + * time [startTime[i], endTime[i]]. + * + * You can reschedule at most k meetings by moving their start time while maintaining the same + * duration, to maximize the longest continuous period of free time during the event. + * + * The relative order of all the meetings should stay the same and they should remain + * non-overlapping. + * + * Return the maximum amount of free time possible after rearranging the meetings. + * + * Note that the meetings can not be rescheduled to a time outside the event. + */ + +/** + * @param {number} eventTime + * @param {number} k + * @param {number[]} startTime + * @param {number[]} endTime + * @return {number} + */ +var maxFreeTime = function(eventTime, k, startTime, endTime) { + const n = startTime.length; + const gaps = new Array(n + 1); + + gaps[0] = startTime[0]; + gaps[n] = eventTime - endTime[n - 1]; + for (let i = 1; i < n; i++) { + gaps[i] = startTime[i] - endTime[i - 1]; + } + + let window = 0; + for (let i = 0; i <= k; i++) { + window += gaps[i]; + } + + let result = window; + for (let i = k + 1; i <= n; i++) { + window += gaps[i] - gaps[i - (k + 1)]; + result = Math.max(result, window); + } + + return result; +}; diff --git a/solutions/3440-reschedule-meetings-for-maximum-free-time-ii.js b/solutions/3440-reschedule-meetings-for-maximum-free-time-ii.js new file mode 100644 index 00000000..6e7d301d --- /dev/null +++ b/solutions/3440-reschedule-meetings-for-maximum-free-time-ii.js @@ -0,0 +1,57 @@ +/** + * 3440. Reschedule Meetings for Maximum Free Time II + * https://leetcode.com/problems/reschedule-meetings-for-maximum-free-time-ii/ + * Difficulty: Medium + * + * You are given an integer eventTime denoting the duration of an event. You are also given two + * integer arrays startTime and endTime, each of length n. + * + * These represent the start and end times of n non-overlapping meetings that occur during the + * event between time t = 0 and time t = eventTime, where the ith meeting occurs during the time + * [startTime[i], endTime[i]]. + * + * You can reschedule at most one meeting by moving its start time while maintaining the same + * duration, such that the meetings remain non-overlapping, to maximize the longest continuous + * period of free time during the event. + * + * Return the maximum amount of free time possible after rearranging the meetings. + * + * Note that the meetings can not be rescheduled to a time outside the event and they should + * remain non-overlapping. + * + * Note: In this version, it is valid for the relative ordering of the meetings to change after + * rescheduling one meeting. + */ + +/** + * @param {number} eventTime + * @param {number[]} startTime + * @param {number[]} endTime + * @return {number} + */ +var maxFreeTime = function(eventTime, startTime, endTime) { + const gap = [startTime[0]]; + for (let i = 1; i < startTime.length; i++) { + gap.push(startTime[i] - endTime[i - 1]); + } + gap.push(eventTime - endTime[endTime.length - 1]); + + const largestRight = new Array(gap.length).fill(0); + for (let i = gap.length - 2; i >= 0; i--) { + largestRight[i] = Math.max(largestRight[i + 1], gap[i + 1]); + } + + let result = 0; + let largestLeft = 0; + + for (let i = 1; i < gap.length; i++) { + const currentGap = endTime[i - 1] - startTime[i - 1]; + if (currentGap <= Math.max(largestLeft, largestRight[i])) { + result = Math.max(result, gap[i - 1] + gap[i] + currentGap); + } + result = Math.max(result, gap[i - 1] + gap[i]); + largestLeft = Math.max(largestLeft, gap[i - 1]); + } + + return result; +}; diff --git a/solutions/3442-maximum-difference-between-even-and-odd-frequency-i.js b/solutions/3442-maximum-difference-between-even-and-odd-frequency-i.js new file mode 100644 index 00000000..313d3fb5 --- /dev/null +++ b/solutions/3442-maximum-difference-between-even-and-odd-frequency-i.js @@ -0,0 +1,39 @@ +/** + * 3442. Maximum Difference Between Even and Odd Frequency I + * https://leetcode.com/problems/maximum-difference-between-even-and-odd-frequency-i/ + * Difficulty: Easy + * + * You are given a string s consisting of lowercase English letters. + * + * Your task is to find the maximum difference diff = freq(a1) - freq(a2) between the frequency + * of characters a1 and a2 in the string such that: + * - a1 has an odd frequency in the string. + * - a2 has an even frequency in the string. + * + * Return this maximum difference. + */ + +/** + * @param {string} s + * @return {number} + */ +var maxDifference = function(s) { + const map = new Map(); + + for (const char of s) { + map.set(char, (map.get(char) || 0) + 1); + } + + let maxOdd = 0; + let minEven = Infinity; + + for (const freq of map.values()) { + if (freq % 2 === 1) { + maxOdd = Math.max(maxOdd, freq); + } else { + minEven = Math.min(minEven, freq); + } + } + + return maxOdd - minEven; +}; diff --git a/solutions/3443-maximum-manhattan-distance-after-k-changes.js b/solutions/3443-maximum-manhattan-distance-after-k-changes.js new file mode 100644 index 00000000..21f7f3c7 --- /dev/null +++ b/solutions/3443-maximum-manhattan-distance-after-k-changes.js @@ -0,0 +1,51 @@ +/** + * 3443. Maximum Manhattan Distance After K Changes + * https://leetcode.com/problems/maximum-manhattan-distance-after-k-changes/ + * Difficulty: Medium + * + * You are given a string s consisting of the characters 'N', 'S', 'E', and 'W', where s[i] + * indicates movements in an infinite grid: + * - 'N' : Move north by 1 unit. + * - 'S' : Move south by 1 unit. + * - 'E' : Move east by 1 unit. + * - 'W' : Move west by 1 unit. + * + * Initially, you are at the origin (0, 0). You can change at most k characters to any of the + * four directions. + * + * Find the maximum Manhattan distance from the origin that can be achieved at any time while + * performing the movements in order. + * + * The Manhattan Distance between two cells (xi, yi) and (xj, yj) is |xi - xj| + |yi - yj|. + */ + +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +var maxDistance = function(s, k) { + const directions = { + 'N': [0, 1], + 'S': [0, -1], + 'E': [1, 0], + 'W': [-1, 0] + }; + + let x = 0; + let y = 0; + let result = 0; + + for (let i = 0; i < s.length; i++) { + const [dx, dy] = directions[s[i]]; + x += dx; + y += dy; + + const currentDistance = Math.abs(x) + Math.abs(y); + const maxPossibleExtra = Math.min(2 * k, i + 1 - currentDistance); + + result = Math.max(result, currentDistance + maxPossibleExtra); + } + + return result; +}; diff --git a/solutions/3445-maximum-difference-between-even-and-odd-frequency-ii.js b/solutions/3445-maximum-difference-between-even-and-odd-frequency-ii.js new file mode 100644 index 00000000..3648091e --- /dev/null +++ b/solutions/3445-maximum-difference-between-even-and-odd-frequency-ii.js @@ -0,0 +1,70 @@ +/** + * 3445. Maximum Difference Between Even and Odd Frequency II + * https://leetcode.com/problems/maximum-difference-between-even-and-odd-frequency-ii/ + * Difficulty: Hard + * + * You are given a string s and an integer k. Your task is to find the maximum difference between + * the frequency of two characters, freq[a] - freq[b], in a substring subs of s, such that: + * - subs has a size of at least k. + * - Character a has an odd frequency in subs. + * - Character b has an even frequency in subs. + * + * Return the maximum difference. + * + * Note that subs can contain more than 2 distinct characters. + */ + +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +var maxDifference = function(s, k) { + const n = s.length; + let result = -Infinity; + + const calculateParityStatus = (freqA, freqB) => { + return ((freqA & 1) << 1) | (freqB & 1); + }; + + for (const charA of ['0', '1', '2', '3', '4']) { + for (const charB of ['0', '1', '2', '3', '4']) { + if (charA === charB) continue; + + const minDifferences = [Infinity, Infinity, Infinity, Infinity]; + let currentFreqA = 0; + let currentFreqB = 0; + let prefixFreqA = 0; + let prefixFreqB = 0; + let leftBoundary = -1; + + for (let rightIndex = 0; rightIndex < n; rightIndex++) { + currentFreqA += s[rightIndex] === charA ? 1 : 0; + currentFreqB += s[rightIndex] === charB ? 1 : 0; + + while (rightIndex - leftBoundary >= k && currentFreqB - prefixFreqB >= 2) { + const prefixStatus = calculateParityStatus(prefixFreqA, prefixFreqB); + minDifferences[prefixStatus] = Math.min( + minDifferences[prefixStatus], + prefixFreqA - prefixFreqB + ); + leftBoundary++; + prefixFreqA += s[leftBoundary] === charA ? 1 : 0; + prefixFreqB += s[leftBoundary] === charB ? 1 : 0; + } + + const currentStatus = calculateParityStatus(currentFreqA, currentFreqB); + const targetStatus = currentStatus ^ 0b10; + + if (minDifferences[targetStatus] !== Infinity) { + result = Math.max( + result, + currentFreqA - currentFreqB - minDifferences[targetStatus] + ); + } + } + } + } + + return result; +}; diff --git a/solutions/3446-sort-matrix-by-diagonals.js b/solutions/3446-sort-matrix-by-diagonals.js new file mode 100644 index 00000000..d4772686 --- /dev/null +++ b/solutions/3446-sort-matrix-by-diagonals.js @@ -0,0 +1,40 @@ +/** + * 3446. Sort Matrix by Diagonals + * https://leetcode.com/problems/sort-matrix-by-diagonals/ + * Difficulty: Medium + * + * You are given an n x n square matrix of integers grid. Return the matrix such that: + * - The diagonals in the bottom-left triangle (including the middle diagonal) are sorted + * in non-increasing order. + * - The diagonals in the top-right triangle are sorted in non-decreasing order. + */ + +/** + * @param {number[][]} grid + * @return {number[][]} + */ +var sortMatrix = function(grid) { + const n = grid.length; + const map = new Map(); + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const key = i - j; + if (!map.has(key)) { + map.set(key, key < 0 + ? new PriorityQueue((a, b) => a - b) + : new PriorityQueue((a, b) => b - a)); + } + map.get(key).enqueue(grid[i][j]); + } + } + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n; j++) { + const key = i - j; + grid[i][j] = map.get(key).dequeue(); + } + } + + return grid; +}; diff --git a/solutions/3450-maximum-students-on-a-single-bench.js b/solutions/3450-maximum-students-on-a-single-bench.js new file mode 100644 index 00000000..34d3af04 --- /dev/null +++ b/solutions/3450-maximum-students-on-a-single-bench.js @@ -0,0 +1,37 @@ +/** + * 3450. Maximum Students on a Single Bench + * https://leetcode.com/problems/maximum-students-on-a-single-bench/ + * Difficulty: Easy + * + * You are given a 2D integer array of student data students, where + * students[i] = [student_id, bench_id] represents that student student_id is + * sitting on the bench bench_id. + * + * Return the maximum number of unique students sitting on any single bench. If no + * students are present, return 0. + * + * Note: A student can appear multiple times on the same bench in the input, but + * they should be counted only once per bench. + */ + +/** + * @param {number[][]} students + * @return {number} + */ +var maxStudentsOnBench = function(students) { + const map = new Map(); + + for (const [studentId, benchId] of students) { + if (!map.has(benchId)) { + map.set(benchId, new Set()); + } + map.get(benchId).add(studentId); + } + + let result = 0; + for (const studentSet of map.values()) { + result = Math.max(result, studentSet.size); + } + + return result; +}; diff --git a/solutions/3460-longest-common-prefix-after-at-most-one-removal.js b/solutions/3460-longest-common-prefix-after-at-most-one-removal.js new file mode 100644 index 00000000..6caf272b --- /dev/null +++ b/solutions/3460-longest-common-prefix-after-at-most-one-removal.js @@ -0,0 +1,39 @@ +/** + * 3460. Longest Common Prefix After at Most One Removal + * https://leetcode.com/problems/longest-common-prefix-after-at-most-one-removal/ + * Difficulty: Medium + * + * You are given two strings s and t. + * + * Return the length of the longest common prefix between s and t after removing at most + * one character from s. + * + * Note: s can be left without any removal. + */ + +/** + * @param {string} s + * @param {string} t + * @return {number} + */ +var longestCommonPrefix = function(s, t) { + let i = 0; + let j = 0; + let result = 0; + let isRemoved = false; + + while (i < s.length && j < t.length) { + if (s[i] === t[j]) { + i++; + j++; + result++; + } else if (isRemoved) { + return result; + } else { + isRemoved = true; + i++; + } + } + + return result; +}; diff --git a/solutions/3466-maximum-coin-collection.js b/solutions/3466-maximum-coin-collection.js new file mode 100644 index 00000000..06763a94 --- /dev/null +++ b/solutions/3466-maximum-coin-collection.js @@ -0,0 +1,50 @@ +/** + * 3466. Maximum Coin Collection + * https://leetcode.com/problems/maximum-coin-collection/ + * Difficulty: Medium + * + * Mario drives on a two-lane freeway with coins every mile. You are given two integer arrays, + * lane1 and lane2, where the value at the ith index represents the number of coins he gains + * or loses in the ith mile in that lane. + * - If Mario is in lane 1 at mile i and lane1[i] > 0, Mario gains lane1[i] coins. + * - If Mario is in lane 1 at mile i and lane1[i] < 0, Mario pays a toll and loses abs(lane1[i]) + * coins. + * - The same rules apply for lane2. + * + * Mario can enter the freeway anywhere and exit anytime after traveling at least one mile. Mario + * always enters the freeway on lane 1 but can switch lanes at most 2 times. + * + * A lane switch is when Mario goes from lane 1 to lane 2 or vice versa. + * + * Return the maximum number of coins Mario can earn after performing at most 2 lane switches. + * + * Note: Mario can switch lanes immediately upon entering or just before exiting the freeway. + */ + +/** + * @param {number[]} lane1 + * @param {number[]} lane2 + * @return {number} + */ +var maxCoins = function(lane1, lane2) { + const n = lane1.length; + const dp = new Array(n).fill().map(() => new Array(2).fill().map(() => new Array(3).fill(0))); + + dp[0][0][2] = lane1[0]; + dp[0][0][0] = lane1[0]; + dp[0][1][1] = lane2[0]; + + let result = Math.max(dp[0][0][2], dp[0][1][1]); + for (let i = 1; i < n; i++) { + dp[i][0][0] = Math.max(dp[i - 1][0][0], dp[i - 1][1][1]) + lane1[i]; + + dp[i][0][2] = Math.max(dp[i - 1][0][2] + lane1[i], lane1[i]); + + dp[i][1][1] = Math.max(Math.max(dp[i - 1][0][2], dp[i - 1][1][1]), 0) + lane2[i]; + + const currentMax = Math.max(Math.max(dp[i][0][0], dp[i][0][2]), dp[i][1][1]); + result = Math.max(result, currentMax); + } + + return result; +}; diff --git a/solutions/3476-maximize-profit-from-task-assignment.js b/solutions/3476-maximize-profit-from-task-assignment.js new file mode 100644 index 00000000..c7212ce7 --- /dev/null +++ b/solutions/3476-maximize-profit-from-task-assignment.js @@ -0,0 +1,57 @@ +/** + * 3476. Maximize Profit from Task Assignment + * https://leetcode.com/problems/maximize-profit-from-task-assignment/ + * Difficulty: Medium + * + * You are given an integer array workers, where workers[i] represents the skill level of + * the ith worker. You are also given a 2D integer array tasks, where: + * - tasks[i][0] represents the skill requirement needed to complete the task. + * - tasks[i][1] represents the profit earned from completing the task. + * + * Each worker can complete at most one task, and they can only take a task if their skill + * level is equal to the task's skill requirement. An additional worker joins today who can + * take up any task, regardless of the skill requirement. + * + * Return the maximum total profit that can be earned by optimally assigning the tasks to + * the workers. + */ + +/** + * @param {number[]} workers + * @param {number[][]} tasks + * @return {number} + */ +var maxProfit = function(workers, tasks) { + const map = new Map(); + + for (const [skill, profit] of tasks) { + if (!map.has(skill)) { + map.set(skill, []); + } + map.get(skill).push(profit); + } + + for (const [skill, profits] of map) { + profits.sort((a, b) => b - a); + } + + let totalProfit = 0; + + for (const worker of workers) { + if (map.has(worker) && map.get(worker).length > 0) { + totalProfit += map.get(worker).shift(); + if (map.get(worker).length === 0) { + map.delete(worker); + } + } + } + + let maxRemainingProfit = 0; + for (const profits of map.values()) { + if (profits.length > 0) { + maxRemainingProfit = Math.max(maxRemainingProfit, profits[0]); + } + } + + return totalProfit + maxRemainingProfit; +}; diff --git a/solutions/3477-fruits-into-baskets-ii.js b/solutions/3477-fruits-into-baskets-ii.js new file mode 100644 index 00000000..c95cf785 --- /dev/null +++ b/solutions/3477-fruits-into-baskets-ii.js @@ -0,0 +1,45 @@ +/** + * 3477. Fruits Into Baskets II + * https://leetcode.com/problems/fruits-into-baskets-ii/ + * Difficulty: Easy + * + * You are given two arrays of integers, fruits and baskets, each of length n, where + * fruits[i] represents the quantity of the ith type of fruit, and baskets[j] represents + * the capacity of the jth basket. + * + * From left to right, place the fruits according to these rules: + * - Each fruit type must be placed in the leftmost available basket with a capacity greater + * than or equal to the quantity of that fruit type. + * - Each basket can hold only one type of fruit. + * - If a fruit type cannot be placed in any basket, it remains unplaced. + * + * Return the number of fruit types that remain unplaced after all possible allocations are made. + */ + +/** + * @param {number[]} fruits + * @param {number[]} baskets + * @return {number} + */ +var numOfUnplacedFruits = function(fruits, baskets) { + const availableBaskets = [...baskets]; + let result = 0; + + for (const fruitQuantity of fruits) { + let placed = false; + + for (let i = 0; i < availableBaskets.length; i++) { + if (availableBaskets[i] >= fruitQuantity) { + availableBaskets[i] = 0; + placed = true; + break; + } + } + + if (!placed) { + result++; + } + } + + return result; +}; diff --git a/solutions/3479-fruits-into-baskets-iii.js b/solutions/3479-fruits-into-baskets-iii.js new file mode 100644 index 00000000..65daf446 --- /dev/null +++ b/solutions/3479-fruits-into-baskets-iii.js @@ -0,0 +1,68 @@ +/** + * 3479. Fruits Into Baskets III + * https://leetcode.com/problems/fruits-into-baskets-iii/ + * Difficulty: Medium + * + * You are given two arrays of integers, fruits and baskets, each of length n, where fruits[i] + * represents the quantity of the ith type of fruit, and baskets[j] represents the capacity of + * the jth basket. + * + * From left to right, place the fruits according to these rules: + * - Each fruit type must be placed in the leftmost available basket with a capacity greater + * than or equal to the quantity of that fruit type. + * - Each basket can hold only one type of fruit. + * - If a fruit type cannot be placed in any basket, it remains unplaced. + * + * Return the number of fruit types that remain unplaced after all possible allocations are made. + */ + +/** + * @param {number[]} fruits + * @param {number[]} baskets + * @return {number} + */ +var numOfUnplacedFruits = function(fruits, baskets) { + const n = fruits.length; + const bucketSize = Math.ceil(Math.sqrt(n)); + const buckets = Array.from({ length: bucketSize }, () => []); + + for (let i = 0; i < baskets.length; i++) { + const bucketIndex = Math.floor(i / bucketSize); + buckets[bucketIndex].push([baskets[i], i]); + } + + for (const bucket of buckets) { + bucket.sort((a, b) => a[0] - b[0]); + } + + let result = 0; + for (const fruitQuantity of fruits) { + let placed = false; + + for (const bucket of buckets) { + if (bucket.length > 0 && bucket[bucket.length - 1][0] >= fruitQuantity) { + let chosenIndex = -1; + let minBasketIndex = Infinity; + + for (let i = 0; i < bucket.length; i++) { + if (bucket[i][0] >= fruitQuantity && bucket[i][1] < minBasketIndex) { + chosenIndex = i; + minBasketIndex = bucket[i][1]; + } + } + + if (chosenIndex !== -1) { + bucket.splice(chosenIndex, 1); + placed = true; + break; + } + } + } + + if (!placed) { + result++; + } + } + + return result; +}; diff --git a/solutions/3480-maximize-subarrays-after-removing-one-conflicting-pair.js b/solutions/3480-maximize-subarrays-after-removing-one-conflicting-pair.js new file mode 100644 index 00000000..068940ff --- /dev/null +++ b/solutions/3480-maximize-subarrays-after-removing-one-conflicting-pair.js @@ -0,0 +1,49 @@ +/** + * 3480. Maximize Subarrays After Removing One Conflicting Pair + * https://leetcode.com/problems/maximize-subarrays-after-removing-one-conflicting-pair/ + * Difficulty: Hard + * + * You are given an integer n which represents an array nums containing the numbers from + * 1 to n in order. Additionally, you are given a 2D array conflictingPairs, where + * conflictingPairs[i] = [a, b] indicates that a and b form a conflicting pair. + * + * Remove exactly one element from conflictingPairs. Afterward, count the number of + * non-empty subarrays of nums which do not contain both a and b for any remaining + * conflicting pair [a, b]. + * + * Return the maximum number of subarrays possible after removing exactly one conflicting pair. + */ + +/** + * @param {number} n + * @param {number[][]} conflictingPairs + * @return {number} + */ +var maxSubarrays = function(n, conflictingPairs) { + const right = Array.from({ length: n + 1 }, () => []); + + for (const [a, b] of conflictingPairs) { + right[Math.max(a, b)].push(Math.min(a, b)); + } + + let left = [0, 0]; + let total = 0; + const bonus = new Array(n + 1).fill(0); + for (let r = 1; r <= n; r++) { + for (const l of right[r]) { + if (l > left[0]) { + left = [l, left[0]]; + } else if (l > left[1]) { + left = [left[0], l]; + } + } + + total += r - left[0]; + + if (left[0] > 0) { + bonus[left[0]] += left[0] - left[1]; + } + } + + return total + Math.max(...bonus); +}; diff --git a/solutions/3481-apply-substitutions.js b/solutions/3481-apply-substitutions.js new file mode 100644 index 00000000..92981c97 --- /dev/null +++ b/solutions/3481-apply-substitutions.js @@ -0,0 +1,35 @@ +/** + * 3481. Apply Substitutions + * https://leetcode.com/problems/apply-substitutions/ + * Difficulty: Medium + * + * You are given a replacements mapping and a text string that may contain placeholders + * formatted as %var%, where each var corresponds to a key in the replacements mapping. + * Each replacement value may itself contain one or more such placeholders. Each placeholder + * is replaced by the value associated with its corresponding replacement key. + * + * Return the fully substituted text string which does not contain any placeholders. + */ + +/** + * @param {string[][]} replacements + * @param {string} text + * @return {string} + */ +var applySubstitutions = function(replacements, text) { + const replacementMap = new Map(replacements); + const cache = new Map(); + + return text.replace(/%([A-Z])%/g, (match, key) => helper(key)); + + function helper(key) { + if (cache.has(key)) { + return cache.get(key); + } + + const value = replacementMap.get(key); + const result = value.replace(/%([A-Z])%/g, (match, innerKey) => helper(innerKey)); + cache.set(key, result); + return result; + } +}; diff --git a/solutions/3484-design-spreadsheet.js b/solutions/3484-design-spreadsheet.js new file mode 100644 index 00000000..ff042fa3 --- /dev/null +++ b/solutions/3484-design-spreadsheet.js @@ -0,0 +1,71 @@ +/** + * 3484. Design Spreadsheet + * https://leetcode.com/problems/design-spreadsheet/ + * Difficulty: Medium + * + * A spreadsheet is a grid with 26 columns (labeled from 'A' to 'Z') and a given number + * of rows. Each cell in the spreadsheet can hold an integer value between 0 and 105. + * + * Implement the Spreadsheet class: + * - Spreadsheet(int rows) Initializes a spreadsheet with 26 columns (labeled 'A' to 'Z') + * and the specified number of rows. All cells are initially set to 0. + * - void setCell(String cell, int value) Sets the value of the specified cell. The cell + * reference is provided in the format "AX" (e.g., "A1", "B10"), where the letter represents + * the column (from 'A' to 'Z') and the number represents a 1-indexed row. + * - void resetCell(String cell) Resets the specified cell to 0. + * - int getValue(String formula) Evaluates a formula of the form "=X+Y", where X and Y are + * either cell references or non-negative integers, and returns the computed sum. + * + * Note: If getValue references a cell that has not been explicitly set using setCell, its + * value is considered 0. + */ + +/** + * @param {number} rows + */ +var Spreadsheet = function(rows) { + this.cellValues = new Map(); + this.totalRows = rows; +}; + +/** + * @param {string} cell + * @param {number} value + * @return {void} + */ +Spreadsheet.prototype.setCell = function(cell, value) { + this.cellValues.set(cell, value); +}; + +/** + * @param {string} cell + * @return {void} + */ +Spreadsheet.prototype.resetCell = function(cell) { + this.cellValues.delete(cell); +}; + +/** + * @param {string} formula + * @return {number} + */ +Spreadsheet.prototype.getValue = function(formula) { + const expression = formula.slice(1); + const operands = expression.split('+'); + + const leftValue = this.parseOperand(operands[0]); + const rightValue = this.parseOperand(operands[1]); + + return leftValue + rightValue; +}; + +/** + * @param {string} operand + * @return {number} + */ +Spreadsheet.prototype.parseOperand = function(operand) { + if (/^\d+$/.test(operand)) { + return parseInt(operand); + } + return this.cellValues.get(operand) || 0; +}; diff --git a/solutions/3487-maximum-unique-subarray-sum-after-deletion.js b/solutions/3487-maximum-unique-subarray-sum-after-deletion.js new file mode 100644 index 00000000..52d0449c --- /dev/null +++ b/solutions/3487-maximum-unique-subarray-sum-after-deletion.js @@ -0,0 +1,29 @@ +/** + * 3487. Maximum Unique Subarray Sum After Deletion + * https://leetcode.com/problems/maximum-unique-subarray-sum-after-deletion/ + * Difficulty: Easy + * + * You are given an integer array nums. + * + * You are allowed to delete any number of elements from nums without making it empty. + * After performing the deletions, select a subarray of nums such that: + * 1. All elements in the subarray are unique. + * 2. The sum of the elements in the subarray is maximized. + * + * Return the maximum sum of such a subarray. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxSum = function(nums) { + const uniqueValues = [...new Set(nums)]; + const positiveValues = uniqueValues.filter(val => val > 0); + + if (positiveValues.length === 0) { + return Math.max(...uniqueValues); + } + + return positiveValues.reduce((sum, val) => sum + val, 0); +}; diff --git a/solutions/3491-phone-number-prefix.js b/solutions/3491-phone-number-prefix.js new file mode 100644 index 00000000..b968be0f --- /dev/null +++ b/solutions/3491-phone-number-prefix.js @@ -0,0 +1,24 @@ +/** + * 3491. Phone Number Prefix + * https://leetcode.com/problems/phone-number-prefix/ + * Difficulty: Easy + * + * You are given a string array numbers that represents phone numbers. Return true if no phone + * number is a prefix of any other phone number; otherwise, return false. + */ + +/** + * @param {string[]} numbers + * @return {boolean} + */ +var phonePrefix = function(numbers) { + numbers.sort(); + + for (let i = 0; i < numbers.length - 1; i++) { + if (numbers[i + 1].startsWith(numbers[i])) { + return false; + } + } + + return true; +}; diff --git a/solutions/3494-find-the-minimum-amount-of-time-to-brew-potions.js b/solutions/3494-find-the-minimum-amount-of-time-to-brew-potions.js new file mode 100644 index 00000000..1ddd6793 --- /dev/null +++ b/solutions/3494-find-the-minimum-amount-of-time-to-brew-potions.js @@ -0,0 +1,37 @@ +/** + * 3494. Find the Minimum Amount of Time to Brew Potions + * https://leetcode.com/problems/find-the-minimum-amount-of-time-to-brew-potions/ + * Difficulty: Medium + * + * You are given two integer arrays, skill and mana, of length n and m, respectively. + * + * In a laboratory, n wizards must brew m potions in order. Each potion has a mana capacity + * mana[j] and must pass through all the wizards sequentially to be brewed properly. The + * time taken by the ith wizard on the jth potion is timeij = skill[i] * mana[j]. + * + * Since the brewing process is delicate, a potion must be passed to the next wizard + * immediately after the current wizard completes their work. This means the timing must + * be synchronized so that each wizard begins working on a potion exactly when it arrives. + * + * Return the minimum amount of time required for the potions to be brewed properly. + */ + +/** + * @param {number[]} skill + * @param {number[]} mana + * @return {number} + */ +var minTime = function(skill, mana) { + const result = new Array(skill.length + 1).fill(0); + + for (let j = 0; j < mana.length; j++) { + for (let i = 0; i < skill.length; i++) { + result[i + 1] = Math.max(result[i + 1], result[i]) + mana[j] * skill[i]; + } + for (let i = skill.length - 1; i > 0; i--) { + result[i] = result[i + 1] - mana[j] * skill[i]; + } + } + + return result[skill.length]; +}; diff --git a/solutions/3495-minimum-operations-to-make-array-elements-zero.js b/solutions/3495-minimum-operations-to-make-array-elements-zero.js new file mode 100644 index 00000000..9d3967ff --- /dev/null +++ b/solutions/3495-minimum-operations-to-make-array-elements-zero.js @@ -0,0 +1,44 @@ +/** + * 3495. Minimum Operations to Make Array Elements Zero + * https://leetcode.com/problems/minimum-operations-to-make-array-elements-zero/ + * Difficulty: Hard + * + * You are given a 2D array queries, where queries[i] is of the form [l, r]. Each + * queries[i] defines an array of integers nums consisting of elements ranging + * from l to r, both inclusive. + * + * In one operation, you can: + * - Select two integers a and b from the array. + * - Replace them with floor(a / 4) and floor(b / 4). + * + * Your task is to determine the minimum number of operations required to reduce all + * elements of the array to zero for each query. Return the sum of the results for + * all queries. + */ + +/** + * @param {number[][]} queries + * @return {number} + */ +var minOperations = function(queries) { + let result = 0; + + for (const [start, end] of queries) { + let operationsNeeded = 0; + + for (let depth = 1, previousBound = 1; depth < 17; depth++) { + const currentBound = previousBound * 4; + const intersectionLeft = Math.max(start, previousBound); + const intersectionRight = Math.min(end, currentBound - 1); + + if (intersectionRight >= intersectionLeft) { + operationsNeeded += (intersectionRight - intersectionLeft + 1) * depth; + } + previousBound = currentBound; + } + + result += Math.ceil(operationsNeeded / 2); + } + + return result; +}; diff --git a/solutions/3496-maximize-score-after-pair-deletions.js b/solutions/3496-maximize-score-after-pair-deletions.js new file mode 100644 index 00000000..4a5b10f8 --- /dev/null +++ b/solutions/3496-maximize-score-after-pair-deletions.js @@ -0,0 +1,34 @@ +/** + * 3496. Maximize Score After Pair Deletions + * https://leetcode.com/problems/maximize-score-after-pair-deletions/ + * Difficulty: Medium + * + * You are given an array of integers nums. You must repeatedly perform one of the following + * operations while the array has more than two elements: + * - Remove the first two elements. + * - Remove the last two elements. + * - Remove the first and last element. + * + * For each operation, add the sum of the removed elements to your total score. + * + * Return the maximum possible score you can achieve. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxScore = function(nums) { + const n = nums.length; + const totalSum = nums.reduce((sum, num) => sum + num, 0); + + if (n % 2 === 1) { + return totalSum - Math.min(...nums); + } else { + let minPairSum = Infinity; + for (let i = 0; i < n - 1; i++) { + minPairSum = Math.min(minPairSum, nums[i] + nums[i + 1]); + } + return totalSum - minPairSum; + } +}; diff --git a/solutions/3506-find-time-required-to-eliminate-bacterial-strains.js b/solutions/3506-find-time-required-to-eliminate-bacterial-strains.js new file mode 100644 index 00000000..fa080b4b --- /dev/null +++ b/solutions/3506-find-time-required-to-eliminate-bacterial-strains.js @@ -0,0 +1,54 @@ +/** + * 3506. Find Time Required to Eliminate Bacterial Strains + * https://leetcode.com/problems/find-time-required-to-eliminate-bacterial-strains/ + * Difficulty: Hard + * + * You are given an integer array timeReq and an integer splitTime. + * + * In the microscopic world of the human body, the immune system faces an extraordinary + * challenge: combatting a rapidly multiplying bacterial colony that threatens the body's survival. + * + * Initially, only one white blood cell (WBC) is deployed to eliminate the bacteria. However, the + * lone WBC quickly realizes it cannot keep up with the bacterial growth rate. + * + * The WBC devises a clever strategy to fight the bacteria: + * - The ith bacterial strain takes timeReq[i] units of time to be eliminated. + * - A single WBC can eliminate only one bacterial strain. Afterwards, the WBC is exhausted and + * cannot perform any other tasks. + * - A WBC can split itself into two WBCs, but this requires splitTime units of time. Once split, + * the two WBCs can work in parallel on eliminating the bacteria. + * - Only one WBC can work on a single bacterial strain. Multiple WBCs cannot attack one strain + * in parallel. + * + * You must determine the minimum time required to eliminate all the bacterial strains. + * + * Note that the bacterial strains can be eliminated in any order. + */ + +/** + * @param {number[]} timeReq + * @param {number} splitTime + * @return {number} + */ +var minEliminationTime = function(timeReq, splitTime) { + const heap = new PriorityQueue((a, b) => a - b); + + for (const time of timeReq) { + heap.enqueue(time); + } + + heap.dequeue(); + + let result = 0; + while (!heap.isEmpty()) { + const bacteria = splitTime + heap.dequeue(); + if (!heap.isEmpty()) { + heap.enqueue(bacteria); + result = heap.dequeue(); + } else { + result = bacteria; + } + } + + return result; +}; diff --git a/solutions/3508-implement-router.js b/solutions/3508-implement-router.js new file mode 100644 index 00000000..47b86cfb --- /dev/null +++ b/solutions/3508-implement-router.js @@ -0,0 +1,166 @@ +/** + * 3508. Implement Router + * https://leetcode.com/problems/implement-router/ + * Difficulty: Medium + * + * Design a data structure that can efficiently manage data packets in a network router. + * Each data packet consists of the following attributes: + * - source: A unique identifier for the machine that generated the packet. + * - destination: A unique identifier for the target machine. + * - timestamp: The time at which the packet arrived at the router. + * + * Implement the Router class: + * Router(int memoryLimit): Initializes the Router object with a fixed memory limit. + * - memoryLimit is the maximum number of packets the router can store at any given time. + * - If adding a new packet would exceed this limit, the oldest packet must be removed to + * free up space. + * bool addPacket(int source, int destination, int timestamp): Adds a packet with the + * given attributes to the router. + * - A packet is considered a duplicate if another packet with the same source, destination, + * and timestamp already exists in the router. + * - Return true if the packet is successfully added (i.e., it is not a duplicate); otherwise + * return false. + * int[] forwardPacket(): Forwards the next packet in FIFO (First In First Out) order. + * - Remove the packet from storage. + * - Return the packet as an array [source, destination, timestamp]. + * - If there are no packets to forward, return an empty array. + * int getCount(int destination, int startTime, int endTime): + * - Returns the number of packets currently stored in the router (i.e., not yet forwarded) that + * have the specified destination and have timestamps in the inclusive range [startTime, endTime]. + * + * Note that queries for addPacket will be made in increasing order of timestamp. + */ + +/** + * @param {number} memoryLimit + */ +var Router = function(memoryLimit) { + this.memoryCapacity = memoryLimit; + this.packetQueue = []; + this.packetSet = new Set(); + this.destinationTimestamps = new Map(); + this.removedPacketIndex = new Map(); +}; + +/** + * @param {number} source + * @param {number} destination + * @param {number} timestamp + * @return {boolean} + */ +Router.prototype.addPacket = function(source, destination, timestamp) { + const packetKey = `${source}-${destination}-${timestamp}`; + + if (this.packetSet.has(packetKey)) { + return false; + } + + if (this.packetQueue.length === this.memoryCapacity) { + const [oldSource, oldDestination, oldTimestamp] = this.packetQueue.shift(); + const oldPacketKey = `${oldSource}-${oldDestination}-${oldTimestamp}`; + this.packetSet.delete(oldPacketKey); + this.removedPacketIndex.set( + oldDestination, + (this.removedPacketIndex.get(oldDestination) || 0) + 1, + ); + } + + this.packetQueue.push([source, destination, timestamp]); + this.packetSet.add(packetKey); + + if (!this.destinationTimestamps.has(destination)) { + this.destinationTimestamps.set(destination, []); + } + this.destinationTimestamps.get(destination).push(timestamp); + + return true; +}; + +/** + * @return {number[]} + */ +Router.prototype.forwardPacket = function() { + if (this.packetQueue.length === 0) { + return []; + } + + const [source, destination, timestamp] = this.packetQueue.shift(); + const packetKey = `${source}-${destination}-${timestamp}`; + this.packetSet.delete(packetKey); + this.removedPacketIndex.set(destination, (this.removedPacketIndex.get(destination) || 0) + 1); + + return [source, destination, timestamp]; +}; + +/** + * @param {number} destination + * @param {number} startTime + * @param {number} endTime + * @return {number} + */ +Router.prototype.getCount = function(destination, startTime, endTime) { + if (!this.destinationTimestamps.has(destination)) { + return 0; + } + + const timestampArray = this.destinationTimestamps.get(destination); + const removedCount = this.removedPacketIndex.get(destination) || 0; + const totalLength = timestampArray.length; + + if (removedCount >= totalLength) { + return 0; + } + + const leftBound = this.binarySearchLeft(timestampArray, startTime, removedCount); + const rightBound = this.binarySearchRight(timestampArray, endTime, removedCount) - 1; + + if (leftBound > rightBound) { + return 0; + } + + return rightBound - leftBound + 1; +}; + +/** + * @param {number[]} array + * @param {number} target + * @param {number} startIndex + * @return {number} + */ +Router.prototype.binarySearchLeft = function(array, target, startIndex) { + let left = startIndex; + let right = array.length; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (array[mid] < target) { + left = mid + 1; + } else { + right = mid; + } + } + + return left; +}; + +/** + * @param {number[]} array + * @param {number} target + * @param {number} startIndex + * @return {number} + */ +Router.prototype.binarySearchRight = function(array, target, startIndex) { + let left = startIndex; + let right = array.length; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (array[mid] <= target) { + left = mid + 1; + } else { + right = mid; + } + } + + return left; +}; diff --git a/solutions/3511-make-a-positive-array.js b/solutions/3511-make-a-positive-array.js new file mode 100644 index 00000000..7432eb8f --- /dev/null +++ b/solutions/3511-make-a-positive-array.js @@ -0,0 +1,35 @@ +/** + * 3511. Make a Positive Array + * https://leetcode.com/problems/make-a-positive-array/ + * Difficulty: Medium + * + * You are given an array nums. An array is considered positive if the sum of all numbers in + * each subarray with more than two elements is positive. + * + * You can perform the following operation any number of times: + * - Replace one element in nums with any integer between -1018 and 1018. + * + * Find the minimum number of operations needed to make nums positive. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var makeArrayPositive = function(nums) { + let result = 0; + let lowestSum = nums[0] + nums[1]; + + for (let i = 2; i < nums.length; i++) { + const currentValue = nums[i]; + const currentTriplet = currentValue + nums[i - 1] + nums[i - 2]; + lowestSum = Math.min(lowestSum + currentValue, currentTriplet); + + if (lowestSum <= 0) { + nums[i] = lowestSum = 10 ** 18; + result++; + } + } + + return result; +}; diff --git a/solutions/3516-find-closest-person.js b/solutions/3516-find-closest-person.js new file mode 100644 index 00000000..973cb632 --- /dev/null +++ b/solutions/3516-find-closest-person.js @@ -0,0 +1,39 @@ +/** + * 3516. Find Closest Person + * https://leetcode.com/problems/find-closest-person/ + * Difficulty: Easy + * + * You are given three integers x, y, and z, representing the positions of three people + * on a number line: + * - x is the position of Person 1. + * - y is the position of Person 2. + * - z is the position of Person 3, who does not move. + * + * Both Person 1 and Person 2 move toward Person 3 at the same speed. + * + * Determine which person reaches Person 3 first: + * - Return 1 if Person 1 arrives first. + * - Return 2 if Person 2 arrives first. + * - Return 0 if both arrive at the same time. + * + * Return the result accordingly. + */ + +/** + * @param {number} x + * @param {number} y + * @param {number} z + * @return {number} + */ +var findClosest = function(x, y, z) { + const distancePerson1 = Math.abs(x - z); + const distancePerson2 = Math.abs(y - z); + + if (distancePerson1 < distancePerson2) { + return 1; + } else if (distancePerson2 < distancePerson1) { + return 2; + } else { + return 0; + } +}; diff --git a/solutions/3520-minimum-threshold-for-inversion-pairs-count.js b/solutions/3520-minimum-threshold-for-inversion-pairs-count.js new file mode 100644 index 00000000..a4ea8692 --- /dev/null +++ b/solutions/3520-minimum-threshold-for-inversion-pairs-count.js @@ -0,0 +1,80 @@ +/** + * 3520. Minimum Threshold for Inversion Pairs Count + * https://leetcode.com/problems/minimum-threshold-for-inversion-pairs-count/ + * Difficulty: Medium + * + * You are given an array of integers nums and an integer k. + * + * An inversion pair with a threshold x is defined as a pair of indices (i, j) such that: + * - i < j + * - nums[i] > nums[j] + * - The difference between the two numbers is at most x (i.e. nums[i] - nums[j] <= x). + * + * Your task is to determine the minimum integer min_threshold such that there are at least + * k inversion pairs with threshold min_threshold. + * + * If no such integer exists, return -1. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minThreshold = function(nums, k) { + const maxThreshold = Math.max(...nums) - Math.min(...nums) + 1; + + if (!countInversions(maxThreshold)) return -1; + + let left = 0; + let right = maxThreshold; + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (countInversions(mid)) { + right = mid; + } else { + left = mid + 1; + } + } + + return left; + + function binarySearchLeft(arr, target) { + let left = 0; + let right = arr.length; + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (arr[mid] < target) { + left = mid + 1; + } else { + right = mid; + } + } + return left; + } + + function insertSorted(arr, val) { + const index = binarySearchLeft(arr, val); + arr.splice(index, 0, val); + } + + function countInversions(threshold) { + let count = 0; + const sortedList = []; + + for (let i = nums.length - 1; i >= 0; i--) { + const num = nums[i]; + const leftBound = num - threshold; + const rightBound = num; + const leftIndex = binarySearchLeft(sortedList, leftBound); + const rightIndex = binarySearchLeft(sortedList, rightBound); + + count += rightIndex - leftIndex; + if (count >= k) return true; + + insertSorted(sortedList, num); + } + + return false; + } +}; diff --git a/solutions/3535-unit-conversion-ii.js b/solutions/3535-unit-conversion-ii.js new file mode 100644 index 00000000..18444a36 --- /dev/null +++ b/solutions/3535-unit-conversion-ii.js @@ -0,0 +1,87 @@ +/** + * 3535. Unit Conversion II + * https://leetcode.com/problems/unit-conversion-ii/ + * Difficulty: Medium + * + * There are n types of units indexed from 0 to n - 1. + * + * You are given a 2D integer array conversions of length n - 1, where + * conversions[i] = [sourceUniti, targetUniti, conversionFactori]. This indicates + * that a single unit of type sourceUniti is equivalent to conversionFactori units + * of type targetUniti. + * + * You are also given a 2D integer array queries of length q, where queries[i] = [unitAi, unitBi]. + * + * Return an array answer of length q where answer[i] is the number of units of type unitBi + * equivalent to 1 unit of type unitAi, and can be represented as p/q where p and q are coprime. + * Return each answer[i] as pq-1 modulo 109 + 7, where q-1 represents the multiplicative inverse + * of q modulo 109 + 7. + */ + +/** + * @param {number[][]} conversions + * @param {number[][]} queries + * @return {number[]} + */ +var queryConversions = function(conversions, queries) { + const n = conversions.length + 1; + const adj = Array.from({ length: n }, () => []); + const convMap = new Map(); + for (const [s, t, f] of conversions) { + adj[s].push(t); + adj[t].push(s); + convMap.set(`${s}-${t}`, BigInt(f)); + } + const MOD = 1000000007n; + const ratio = new Array(n).fill(0n); + ratio[0] = 1n; + const visited = new Array(n).fill(false); + visited[0] = true; + const queue = [0]; + let queueIndex = 0; + while (queueIndex < queue.length) { + const current = queue[queueIndex++]; + for (const neighbor of adj[current]) { + if (visited[neighbor]) continue; + visited[neighbor] = true; + queue.push(neighbor); + const forwardKey = `${current}-${neighbor}`; + if (convMap.has(forwardKey)) { + const factor = convMap.get(forwardKey); + ratio[neighbor] = (ratio[current] * factor) % MOD; + } else { + const backwardKey = `${neighbor}-${current}`; + const factor = convMap.get(backwardKey); + const inverseFactor = modInverse(factor, MOD); + ratio[neighbor] = (ratio[current] * inverseFactor) % MOD; + } + } + } + const result = []; + for (const [unitA, unitB] of queries) { + const ratioA = ratio[unitA]; + const ratioB = ratio[unitB]; + const inverseRatioA = modInverse(ratioA, MOD); + const conversion = (ratioB * inverseRatioA) % MOD; + result.push(Number(conversion)); + } + + return result; + + function modPow(base, exponent, modulus) { + let result = 1n; + base %= modulus; + while (exponent > 0n) { + if (exponent % 2n === 1n) { + result = (result * base) % modulus; + } + base = (base * base) % modulus; + exponent /= 2n; + } + return result; + } + + function modInverse(value, modulus) { + return modPow(value, modulus - 2n, modulus); + } +}; diff --git a/solutions/3539-find-sum-of-array-product-of-magical-sequences.js b/solutions/3539-find-sum-of-array-product-of-magical-sequences.js new file mode 100644 index 00000000..5e7fd749 --- /dev/null +++ b/solutions/3539-find-sum-of-array-product-of-magical-sequences.js @@ -0,0 +1,101 @@ +/** + * 3539. Find Sum of Array Product of Magical Sequences + * https://leetcode.com/problems/find-sum-of-array-product-of-magical-sequences/ + * Difficulty: Hard + * + * You are given two integers, m and k, and an integer array nums. + * + * A sequence of integers seq is called magical if: + * - seq has a size of m. + * - 0 <= seq[i] < nums.length + * - The binary representation of 2seq[0] + 2seq[1] + ... + 2seq[m - 1] has k set bits. + * + * The array product of this sequence is defined as prod(seq) = (nums[seq[0]] + * * nums[seq[1]] * ... * nums[seq[m - 1]]). + * + * Return the sum of the array products for all valid magical sequences. + * + * Since the answer may be large, return it modulo 109 + 7. + * + * A set bit refers to a bit in the binary representation of a number that has a value of 1. + */ + +/** + * @param {number} m + * @param {number} k + * @param {number[]} nums + * @return {number} + */ +var magicalSum = function(m, k, nums) { + const MOD = 1000000007n; + const map = new Map(); + const n = nums.length; + + function bitCount(num) { + let count = 0; + while (num > 0) { + count += num & 1; + num >>= 1; + } + return count; + } + + function modPow(base, exp) { + let result = 1n; + base = BigInt(base) % MOD; + let e = BigInt(exp); + while (e > 0n) { + if (e & 1n) result = (result * base) % MOD; + base = (base * base) % MOD; + e >>= 1n; + } + return result; + } + + const factorialCache = [1n]; + function factorial(n) { + while (factorialCache.length <= n) { + factorialCache.push( + factorialCache[factorialCache.length - 1] * BigInt(factorialCache.length) + ); + } + return factorialCache[n]; + } + + function comb(n, r) { + if (r > n || r < 0) return 0n; + if (r === 0 || r === n) return 1n; + return factorial(n) / (factorial(r) * factorial(n - r)); + } + + function dfs(remaining, oddNeeded, index, carry) { + if (remaining < 0 || oddNeeded < 0 || remaining + bitCount(carry) < oddNeeded) { + return 0n; + } + if (remaining === 0) { + return bitCount(carry) === oddNeeded ? 1n : 0n; + } + if (index >= n) { + return 0n; + } + + const key = `${remaining},${oddNeeded},${index},${carry}`; + if (map.has(key)) return map.get(key); + + let result = 0n; + for (let take = 0; take <= remaining; take++) { + const ways = (comb(remaining, take) * modPow(nums[index], take)) % MOD; + const newCarry = carry + take; + const contribution = dfs( + remaining - take, oddNeeded - (newCarry % 2), + index + 1, Math.floor(newCarry / 2), + ); + result = (result + ways * contribution) % MOD; + } + + map.set(key, result); + return result; + } + + return Number(dfs(m, k, 0, 0)); +}; diff --git a/solutions/3541-find-most-frequent-vowel-and-consonant.js b/solutions/3541-find-most-frequent-vowel-and-consonant.js new file mode 100644 index 00000000..69b47b09 --- /dev/null +++ b/solutions/3541-find-most-frequent-vowel-and-consonant.js @@ -0,0 +1,42 @@ +/** + * 3541. Find Most Frequent Vowel and Consonant + * https://leetcode.com/problems/find-most-frequent-vowel-and-consonant/ + * Difficulty: Easy + * + * You are given a string s consisting of lowercase English letters ('a' to 'z'). + * + * Your task is to: + * - Find the vowel (one of 'a', 'e', 'i', 'o', or 'u') with the maximum frequency. + * - Find the consonant (all other letters excluding vowels) with the maximum frequency. + * + * Return the sum of the two frequencies. + * + * Note: If multiple vowels or consonants have the same maximum frequency, you may choose + * any one of them. If there are no vowels or no consonants in the string, consider their + * frequency as 0. + * + * The frequency of a letter x is the number of times it occurs in the string. + */ + +/** + * @param {string} s + * @return {number} + */ +var maxFreqSum = function(s) { + const vowels = new Set(['a', 'e', 'i', 'o', 'u']); + const vowelFreq = {}; + const consonantFreq = {}; + + for (const char of s) { + if (vowels.has(char)) { + vowelFreq[char] = (vowelFreq[char] || 0) + 1; + } else { + consonantFreq[char] = (consonantFreq[char] || 0) + 1; + } + } + + const maxVowelFreq = Math.max(0, ...Object.values(vowelFreq)); + const maxConsonantFreq = Math.max(0, ...Object.values(consonantFreq)); + + return maxVowelFreq + maxConsonantFreq; +};