diff --git a/README.md b/README.md index 267d1c3f..ca4318ab 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 1,335 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,10 +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| @@ -434,28 +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| @@ -465,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| @@ -517,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| @@ -528,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| @@ -535,37 +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| @@ -573,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| @@ -588,8 +726,12 @@ 768|[Max Chunks To Make Sorted II](./solutions/0768-max-chunks-to-make-sorted-ii.js)|Hard| 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| @@ -613,12 +755,14 @@ 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| 804|[Unique Morse Code Words](./solutions/0804-unique-morse-code-words.js)|Easy| 805|[Split Array With Same Average](./solutions/0805-split-array-with-same-average.js)|Hard| 806|[Number of Lines To Write String](./solutions/0806-number-of-lines-to-write-string.js)|Easy| +807|[Max Increase to Keep City Skyline](./solutions/0807-max-increase-to-keep-city-skyline.js)|Medium| 808|[Soup Servings](./solutions/0808-soup-servings.js)|Medium| 809|[Expressive Words](./solutions/0809-expressive-words.js)|Medium| 810|[Chalkboard XOR Game](./solutions/0810-chalkboard-xor-game.js)|Hard| @@ -643,6 +787,7 @@ 829|[Consecutive Numbers Sum](./solutions/0829-consecutive-numbers-sum.js)|Hard| 830|[Positions of Large Groups](./solutions/0830-positions-of-large-groups.js)|Easy| 831|[Masking Personal Information](./solutions/0831-masking-personal-information.js)|Medium| +832|[Flipping an Image](./solutions/0832-flipping-an-image.js)|Easy| 833|[Find And Replace in String](./solutions/0833-find-and-replace-in-string.js)|Medium| 834|[Sum of Distances in Tree](./solutions/0834-sum-of-distances-in-tree.js)|Hard| 835|[Image Overlap](./solutions/0835-image-overlap.js)|Medium| @@ -727,6 +872,7 @@ 914|[X of a Kind in a Deck of Cards](./solutions/0914-x-of-a-kind-in-a-deck-of-cards.js)|Medium| 915|[Partition Array into Disjoint Intervals](./solutions/0915-partition-array-into-disjoint-intervals.js)|Medium| 916|[Word Subsets](./solutions/0916-word-subsets.js)|Medium| +917|[Reverse Only Letters](./solutions/0917-reverse-only-letters.js)|Easy| 918|[Maximum Sum Circular Subarray](./solutions/0918-maximum-sum-circular-subarray.js)|Medium| 919|[Complete Binary Tree Inserter](./solutions/0919-complete-binary-tree-inserter.js)|Medium| 920|[Number of Music Playlists](./solutions/0920-number-of-music-playlists.js)|Hard| @@ -770,6 +916,7 @@ 958|[Check Completeness of a Binary Tree](./solutions/0958-check-completeness-of-a-binary-tree.js)|Medium| 959|[Regions Cut By Slashes](./solutions/0959-regions-cut-by-slashes.js)|Medium| 960|[Delete Columns to Make Sorted III](./solutions/0960-delete-columns-to-make-sorted-iii.js)|Hard| +961|[N-Repeated Element in Size 2N Array](./solutions/0961-n-repeated-element-in-size-2n-array.js)|Easy| 962|[Maximum Width Ramp](./solutions/0962-maximum-width-ramp.js)|Medium| 963|[Minimum Area Rectangle II](./solutions/0963-minimum-area-rectangle-ii.js)|Medium| 964|[Least Operators to Express Number](./solutions/0964-least-operators-to-express-number.js)|Hard| @@ -829,6 +976,7 @@ 1018|[Binary Prefix Divisible By 5](./solutions/1018-binary-prefix-divisible-by-5.js)|Easy| 1019|[Next Greater Node In Linked List](./solutions/1019-next-greater-node-in-linked-list.js)|Medium| 1020|[Number of Enclaves](./solutions/1020-number-of-enclaves.js)|Medium| +1021|[Remove Outermost Parentheses](./solutions/1021-remove-outermost-parentheses.js)|Easy| 1022|[Sum of Root To Leaf Binary Numbers](./solutions/1022-sum-of-root-to-leaf-binary-numbers.js)|Easy| 1023|[Camelcase Matching](./solutions/1023-camelcase-matching.js)|Medium| 1024|[Video Stitching](./solutions/1024-video-stitching.js)|Medium| @@ -860,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| @@ -869,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| @@ -877,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| @@ -885,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| @@ -893,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| @@ -902,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| @@ -910,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| @@ -925,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| @@ -934,22 +1127,36 @@ 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| 1220|[Count Vowels Permutation](./solutions/1220-count-vowels-permutation.js)|Hard| +1221|[Split a String in Balanced Strings](./solutions/1221-split-a-string-in-balanced-strings.js)|Easy| 1222|[Queens That Can Attack the King](./solutions/1222-queens-that-can-attack-the-king.js)|Medium| 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| @@ -958,17 +1165,30 @@ 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| 1278|[Palindrome Partitioning III](./solutions/1278-palindrome-partitioning-iii.js)|Hard| +1281|[Subtract the Product and Sum of Digits of an Integer](./solutions/1281-subtract-the-product-and-sum-of-digits-of-an-integer.js)|Easy| +1282|[Group the People Given the Group Size They Belong To](./solutions/1282-group-the-people-given-the-group-size-they-belong-to.js)|Medium| +1283|[Find the Smallest Divisor Given a Threshold](./solutions/1283-find-the-smallest-divisor-given-a-threshold.js)|Medium| 1284|[Minimum Number of Flips to Convert Binary Matrix to Zero Matrix](./solutions/1284-minimum-number-of-flips-to-convert-binary-matrix-to-zero-matrix.js)|Hard| 1286|[Iterator for Combination](./solutions/1286-iterator-for-combination.js)|Medium| 1287|[Element Appearing More Than 25% In Sorted Array](./solutions/1287-element-appearing-more-than-25-in-sorted-array.js)|Easy| @@ -1091,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| @@ -1123,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| @@ -1135,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| @@ -1147,159 +1376,1057 @@ 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| +1510|[Stone Game IV](./solutions/1510-stone-game-iv.js)|Hard| 1512|[Number of Good Pairs](./solutions/1512-number-of-good-pairs.js)|Easy| +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| +1526|[Minimum Number of Increments on Subarrays to Form a Target Array](./solutions/1526-minimum-number-of-increments-on-subarrays-to-form-a-target-array.js)|Hard| 1528|[Shuffle String](./solutions/1528-shuffle-string.js)|Easy| +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| +1542|[Find Longest Awesome Substring](./solutions/1542-find-longest-awesome-substring.js)|Hard| +1544|[Make The String Great](./solutions/1544-make-the-string-great.js)|Easy| +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| +1559|[Detect Cycles in 2D Grid](./solutions/1559-detect-cycles-in-2d-grid.js)|Medium| +1560|[Most Visited Sector in a Circular Track](./solutions/1560-most-visited-sector-in-a-circular-track.js)|Easy| +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| +1575|[Count All Possible Routes](./solutions/1575-count-all-possible-routes.js)|Hard| 1576|[Replace All ?'s to Avoid Consecutive Repeating Characters](./solutions/1576-replace-all-s-to-avoid-consecutive-repeating-characters.js)|Medium| +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| +1591|[Strange Printer II](./solutions/1591-strange-printer-ii.js)|Hard| +1592|[Rearrange Spaces Between Words](./solutions/1592-rearrange-spaces-between-words.js)|Easy| +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| +1606|[Find Servers That Handled Most Number of Requests](./solutions/1606-find-servers-that-handled-most-number-of-requests.js)|Hard| +1608|[Special Array With X Elements Greater Than or Equal X](./solutions/1608-special-array-with-x-elements-greater-than-or-equal-x.js)|Easy| +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| +1622|[Fancy Sequence](./solutions/1622-fancy-sequence.js)|Hard| +1624|[Largest Substring Between Two Equal Characters](./solutions/1624-largest-substring-between-two-equal-characters.js)|Easy| +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| +1639|[Number of Ways to Form a Target String Given a Dictionary](./solutions/1639-number-of-ways-to-form-a-target-string-given-a-dictionary.js)|Hard| +1640|[Check Array Formation Through Concatenation](./solutions/1640-check-array-formation-through-concatenation.js)|Easy| +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| +1655|[Distribute Repeating Integers](./solutions/1655-distribute-repeating-integers.js)|Hard| +1656|[Design an Ordered Stream](./solutions/1656-design-an-ordered-stream.js)|Easy| 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| +1671|[Minimum Number of Removals to Make Mountain Array](./solutions/1671-minimum-number-of-removals-to-make-mountain-array.js)|Hard| 1672|[Richest Customer Wealth](./solutions/1672-richest-customer-wealth.js)|Easy| +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| +1687|[Delivering Boxes from Storage to Ports](./solutions/1687-delivering-boxes-from-storage-to-ports.js)|Hard| +1688|[Count of Matches in Tournament](./solutions/1688-count-of-matches-in-tournament.js)|Easy| +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| +1703|[Minimum Adjacent Swaps for K Consecutive Ones](./solutions/1703-minimum-adjacent-swaps-for-k-consecutive-ones.js)|Hard| +1704|[Determine if String Halves Are Alike](./solutions/1704-determine-if-string-halves-are-alike.js)|Easy| +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| +1719|[Number Of Ways To Reconstruct A Tree](./solutions/1719-number-of-ways-to-reconstruct-a-tree.js)|Hard| +1720|[Decode XORed Array](./solutions/1720-decode-xored-array.js)|Easy| +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| +1735|[Count Ways to Make Array With Product](./solutions/1735-count-ways-to-make-array-with-product.js)|Hard| +1736|[Latest Time by Replacing Hidden Digits](./solutions/1736-latest-time-by-replacing-hidden-digits.js)|Easy| +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| +1751|[Maximum Number of Events That Can Be Attended II](./solutions/1751-maximum-number-of-events-that-can-be-attended-ii.js)|Hard| 1752|[Check if Array Is Sorted and Rotated](./solutions/1752-check-if-array-is-sorted-and-rotated.js)|Easy| +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| +1766|[Tree of Coprimes](./solutions/1766-tree-of-coprimes.js)|Hard| 1768|[Merge Strings Alternately](./solutions/1768-merge-strings-alternately.js)|Easy| 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| +1782|[Count Pairs Of Nodes](./solutions/1782-count-pairs-of-nodes.js)|Hard| +1784|[Check if Binary String Has at Most One Segment of Ones](./solutions/1784-check-if-binary-string-has-at-most-one-segment-of-ones.js)|Easy| +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| +1799|[Maximize Score After N Operations](./solutions/1799-maximize-score-after-n-operations.js)|Hard| 1800|[Maximum Ascending Subarray Sum](./solutions/1800-maximum-ascending-subarray-sum.js)|Easy| +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| +1815|[Maximum Number of Groups Getting Fresh Donuts](./solutions/1815-maximum-number-of-groups-getting-fresh-donuts.js)|Hard| +1816|[Truncate Sentence](./solutions/1816-truncate-sentence.js)|Easy| 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| +1830|[Minimum Number of Operations to Make String Sorted](./solutions/1830-minimum-number-of-operations-to-make-string-sorted.js)|Hard| 1832|[Check if the Sentence Is Pangram](./solutions/1832-check-if-the-sentence-is-pangram.js)|Easy| 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| +1847|[Closest Room](./solutions/1847-closest-room.js)|Hard| +1848|[Minimum Distance to the Target Element](./solutions/1848-minimum-distance-to-the-target-element.js)|Easy| +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| +1862|[Sum of Floored Pairs](./solutions/1862-sum-of-floored-pairs.js)|Hard| 1863|[Sum of All Subset XOR Totals](./solutions/1863-sum-of-all-subset-xor-totals.js)|Easy| +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| +1879|[Minimum XOR Sum of Two Arrays](./solutions/1879-minimum-xor-sum-of-two-arrays.js)|Hard| 1880|[Check if Word Equals Summation of Two Words](./solutions/1880-check-if-word-equals-summation-of-two-words.js)|Easy| +1881|[Maximum Value after Insertion](./solutions/1881-maximum-value-after-insertion.js)|Medium| +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| +1896|[Minimum Cost to Change the Final Value of Expression](./solutions/1896-minimum-cost-to-change-the-final-value-of-expression.js)|Hard| +1897|[Redistribute Characters to Make All Strings Equal](./solutions/1897-redistribute-characters-to-make-all-strings-equal.js)|Easy| +1898|[Maximum Number of Removable Characters](./solutions/1898-maximum-number-of-removable-characters.js)|Medium| +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| +1912|[Design Movie Rental System](./solutions/1912-design-movie-rental-system.js)|Hard| +1913|[Maximum Product Difference Between Two Pairs](./solutions/1913-maximum-product-difference-between-two-pairs.js)|Easy| +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| +1928|[Minimum Cost to Reach Destination in Time](./solutions/1928-minimum-cost-to-reach-destination-in-time.js)|Hard| 1929|[Concatenation of Array](./solutions/1929-concatenation-of-array.js)|Easy| 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| +1977|[Number of Ways to Separate Numbers](./solutions/1977-number-of-ways-to-separate-numbers.js)|Hard| +1979|[Find Greatest Common Divisor of Array](./solutions/1979-find-greatest-common-divisor-of-array.js)|Easy| 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| +1994|[The Number of Good Subsets](./solutions/1994-the-number-of-good-subsets.js)|Hard| +1995|[Count Special Quadruplets](./solutions/1995-count-special-quadruplets.js)|Easy| 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| +2009|[Minimum Number of Operations to Make Array Continuous](./solutions/2009-minimum-number-of-operations-to-make-array-continuous.js)|Hard| 2011|[Final Value of Variable After Performing Operations](./solutions/2011-final-value-of-variable-after-performing-operations.js)|Easy| +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| +2025|[Maximum Number of Ways to Partition an Array](./solutions/2025-maximum-number-of-ways-to-partition-an-array.js)|Hard| 2027|[Minimum Moves to Convert String](./solutions/2027-minimum-moves-to-convert-string.js)|Easy| +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| +2040|[Kth Smallest Product of Two Sorted Arrays](./solutions/2040-kth-smallest-product-of-two-sorted-arrays.js)|Hard| +2042|[Check if Numbers Are Ascending in a Sentence](./solutions/2042-check-if-numbers-are-ascending-in-a-sentence.js)|Easy| +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| +2088|[Count Fertile Pyramids in a Land](./solutions/2088-count-fertile-pyramids-in-a-land.js)|Hard| +2089|[Find Target Indices After Sorting Array](./solutions/2089-find-target-indices-after-sorting-array.js)|Easy| +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| +2117|[Abbreviating the Product of a Range](./solutions/2117-abbreviating-the-product-of-a-range.js)|Hard| +2119|[A Number After a Double Reversal](./solutions/2119-a-number-after-a-double-reversal.js)|Easy| +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| +2132|[Stamping the Grid](./solutions/2132-stamping-the-grid.js)|Hard| +2133|[Check if Every Row and Column Contains All Numbers](./solutions/2133-check-if-every-row-and-column-contains-all-numbers.js)|Easy| +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| +2193|[Minimum Number of Moves to Make Palindrome](./solutions/2193-minimum-number-of-moves-to-make-palindrome.js)|Hard| +2194|[Cells in a Range on an Excel Sheet](./solutions/2194-cells-in-a-range-on-an-excel-sheet.js)|Easy| +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| +2223|[Sum of Scores of Built Strings](./solutions/2223-sum-of-scores-of-built-strings.js)|Hard| +2224|[Minimum Number of Operations to Convert Time](./solutions/2224-minimum-number-of-operations-to-convert-time.js)|Easy| +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| +2242|[Maximum Score of a Node Sequence](./solutions/2242-maximum-score-of-a-node-sequence.js)|Hard| +2243|[Calculate Digit Sum of a String](./solutions/2243-calculate-digit-sum-of-a-string.js)|Easy| 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| +2258|[Escape the Spreading Fire](./solutions/2258-escape-the-spreading-fire.js)|Hard| +2259|[Remove Digit From Number to Maximize Result](./solutions/2259-remove-digit-from-number-to-maximize-result.js)|Easy| +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| +2272|[Substring With Largest Variance](./solutions/2272-substring-with-largest-variance.js)|Hard| +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| +2302|[Count Subarrays With Score Less Than K](./solutions/2302-count-subarrays-with-score-less-than-k.js)|Hard| +2303|[Calculate Amount Paid in Taxes](./solutions/2303-calculate-amount-paid-in-taxes.js)|Easy| +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| +2318|[Number of Distinct Roll Sequences](./solutions/2318-number-of-distinct-roll-sequences.js)|Hard| +2319|[Check if Matrix Is X-Matrix](./solutions/2319-check-if-matrix-is-x-matrix.js)|Easy| +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| +2366|[Minimum Replacements to Sort the Array](./solutions/2366-minimum-replacements-to-sort-the-array.js)|Hard| +2367|[Number of Arithmetic Triplets](./solutions/2367-number-of-arithmetic-triplets.js)|Easy| +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| +2412|[Minimum Money Required Before Transactions](./solutions/2412-minimum-money-required-before-transactions.js)|Hard| 2413|[Smallest Even Multiple](./solutions/2413-smallest-even-multiple.js)|Easy| +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| +2440|[Create Components With Same Value](./solutions/2440-create-components-with-same-value.js)|Hard| +2441|[Largest Positive Integer That Exists With Its Negative](./solutions/2441-largest-positive-integer-that-exists-with-its-negative.js)|Easy| +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| +2544|[Alternating Digit Sum](./solutions/2544-alternating-digit-sum.js)|Easy| +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| +2567|[Minimum Score by Changing Two Elements](./solutions/2567-minimum-score-by-changing-two-elements.js)|Medium| +2568|[Minimum Impossible OR](./solutions/2568-minimum-impossible-or.js)|Medium| 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| +2582|[Pass the Pillow](./solutions/2582-pass-the-pillow.js)|Easy| +2583|[Kth Largest Sum in a Binary Tree](./solutions/2583-kth-largest-sum-in-a-binary-tree.js)|Medium| +2585|[Number of Ways to Earn Points](./solutions/2585-number-of-ways-to-earn-points.js)|Hard| +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| 2619|[Array Prototype Last](./solutions/2619-array-prototype-last.js)|Easy| 2620|[Counter](./solutions/2620-counter.js)|Easy| 2621|[Sleep](./solutions/2621-sleep.js)|Easy| 2622|[Cache With Time Limit](./solutions/2622-cache-with-time-limit.js)|Medium| 2623|[Memoize](./solutions/2623-memoize.js)|Medium| +2624|[Snail Traversal](./solutions/2624-snail-traversal.js)|Medium| 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| +2682|[Find the Losers of the Circular Game](./solutions/2682-find-the-losers-of-the-circular-game.js)|Easy| 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| @@ -1307,40 +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/0535-encode-and-decode-tinyurl.js b/solutions/0535-encode-and-decode-tinyurl.js new file mode 100644 index 00000000..4875c4bb --- /dev/null +++ b/solutions/0535-encode-and-decode-tinyurl.js @@ -0,0 +1,45 @@ +/** + * 535. Encode and Decode TinyURL + * https://leetcode.com/problems/encode-and-decode-tinyurl/ + * Difficulty: Medium + * + * TinyURL is a URL shortening service where you enter a URL such as + * https://leetcode.com/problems/design-tinyurl and it returns a short URL such as + * http://tinyurl.com/4e9iAk. Design a class to encode a URL and decode a tiny URL. + * + * There is no restriction on how your encode/decode algorithm should work. You just + * need to ensure that a URL can be encoded to a tiny URL and the tiny URL can be + * decoded to the original URL. + * + * Implement the Solution class: + * - Solution() Initializes the object of the system. + * - String encode(String longUrl) Returns a tiny URL for the given longUrl. + * - String decode(String shortUrl) Returns the original long URL for the given shortUrl. + * It is guaranteed that the given shortUrl was encoded by the same object. + */ + +const map = new Map(); +let counter = 1; + +/** + * Encodes a URL to a shortened URL. + * + * @param {string} longUrl + * @return {string} + */ +var encode = function(longUrl) { + const shortUrl = 'https://tinyurl.com/' + counter.toString(); + map.set(shortUrl, longUrl); + counter++; + return shortUrl; +}; + +/** + * Decodes a shortened URL to its original URL. + * + * @param {string} shortUrl + * @return {string} + */ +var decode = function(shortUrl) { + return map.get(shortUrl) || null; +}; 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/0561-array-partition.js b/solutions/0561-array-partition.js new file mode 100644 index 00000000..17596442 --- /dev/null +++ b/solutions/0561-array-partition.js @@ -0,0 +1,18 @@ +/** + * 561. Array Partition + * https://leetcode.com/problems/array-partition/ + * Difficulty: Easy + * + * Given an integer array nums of 2n integers, group these integers into n pairs (a1, b1), + * (a2, b2), ..., (an, bn) such that the sum of min(ai, bi) for all i is maximized. + * Return the maximized sum. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var arrayPairSum = function(nums) { + return nums.sort((a, b) => a - b).reduce((sum, v, i, a) => + sum + (i % 2 === 0 ? Math.min(v, a[i + 1]) : 0), 0); +}; 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/0709-to-lower-case.js b/solutions/0709-to-lower-case.js new file mode 100644 index 00000000..49ef785a --- /dev/null +++ b/solutions/0709-to-lower-case.js @@ -0,0 +1,16 @@ +/** + * 709. To Lower Case + * https://leetcode.com/problems/to-lower-case/ + * Difficulty: Easy + * + * Given a string s, return the string after replacing every uppercase letter with the same + * lowercase letter. + */ + +/** + * @param {string} s + * @return {string} + */ +var toLowerCase = function(s) { + return s.toLowerCase(); +}; 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/0771-jewels-and-stones.js b/solutions/0771-jewels-and-stones.js new file mode 100644 index 00000000..db728558 --- /dev/null +++ b/solutions/0771-jewels-and-stones.js @@ -0,0 +1,29 @@ +/** + * 771. Jewels and Stones + * https://leetcode.com/problems/jewels-and-stones/ + * Difficulty: Easy + * + * You're given strings jewels representing the types of stones that are jewels, and stones + * representing the stones you have. Each character in stones is a type of stone you have. + * You want to know how many of the stones you have are also jewels. + * + * Letters are case sensitive, so "a" is considered a different type of stone from "A". + */ + +/** + * @param {string} jewels + * @param {string} stones + * @return {number} + */ +var numJewelsInStones = function(jewels, stones) { + const set = new Set(jewels); + let result = 0; + + for (const stone of stones) { + if (set.has(stone)) { + result++; + } + } + + 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/0807-max-increase-to-keep-city-skyline.js b/solutions/0807-max-increase-to-keep-city-skyline.js new file mode 100644 index 00000000..efa02a04 --- /dev/null +++ b/solutions/0807-max-increase-to-keep-city-skyline.js @@ -0,0 +1,46 @@ +/** + * 807. Max Increase to Keep City Skyline + * https://leetcode.com/problems/max-increase-to-keep-city-skyline/ + * Difficulty: Medium + * + * There is a city composed of n x n blocks, where each block contains a single building shaped + * like a vertical square prism. You are given a 0-indexed n x n integer matrix grid where + * grid[r][c] represents the height of the building located in the block at row r and column c. + * + * A city's skyline is the outer contour formed by all the building when viewing the side of the + * city from a distance. The skyline from each cardinal direction north, east, south, and west + * may be different. + * + * We are allowed to increase the height of any number of buildings by any amount (the amount can + * be different per building). The height of a 0-height building can also be increased. However, + * increasing the height of a building should not affect the city's skyline from any cardinal + * direction. + * + * Return the maximum total sum that the height of the buildings can be increased by without + * changing the city's skyline from any cardinal direction. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var maxIncreaseKeepingSkyline = function(grid) { + let result = 0; + const rowMaxes = grid.map(row => Math.max(...row)); + const columnMaxes = grid.map((row, index) => grid.map(row => row[index])) + .map(row => Math.max(...row)); + + for (let i = 0; i < grid.length; i++) { + for (let j = 0; j < grid[i].length; j++) { + const currentHeight = grid[i][j]; + const minHeight = Math.min( + Math.max(rowMaxes[i], currentHeight), + Math.max(columnMaxes[j], currentHeight) + ); + + result += (minHeight - currentHeight); + } + } + + return result; +}; diff --git a/solutions/0832-flipping-an-image.js b/solutions/0832-flipping-an-image.js new file mode 100644 index 00000000..9e92cc10 --- /dev/null +++ b/solutions/0832-flipping-an-image.js @@ -0,0 +1,22 @@ +/** + * 832. Flipping an Image + * https://leetcode.com/problems/flipping-an-image/ + * Difficulty: Easy + * + * Given an n x n binary matrix image, flip the image horizontally, then invert it, and + * return the resulting image. + * + * To flip an image horizontally means that each row of the image is reversed. + * - For example, flipping [1,1,0] horizontally results in [0,1,1]. + * + * To invert an image means that each 0 is replaced by 1, and each 1 is replaced by 0. + * - For example, inverting [0,1,1] results in [1,0,0]. + */ + +/** + * @param {number[][]} image + * @return {number[][]} + */ +var flipAndInvertImage = function(image) { + return image.map(row => row.reverse().map(num => 1 ^ num)); +}; diff --git a/solutions/0917-reverse-only-letters.js b/solutions/0917-reverse-only-letters.js new file mode 100644 index 00000000..1c1fe818 --- /dev/null +++ b/solutions/0917-reverse-only-letters.js @@ -0,0 +1,35 @@ +/** + * 917. Reverse Only Letters + * https://leetcode.com/problems/reverse-only-letters/ + * Difficulty: Easy + * + * Given a string s, reverse the string according to the following rules: + * - All the characters that are not English letters remain in the same position. + * - All the English letters (lowercase or uppercase) should be reversed. + * + * Return s after reversing it. + */ + +/** + * @param {string} s + * @return {string} + */ +var reverseOnlyLetters = function(s) { + const chars = s.split(''); + let left = 0; + let right = s.length - 1; + + while (left < right) { + while (left < right && !/[a-zA-Z]/.test(chars[left])) { + left++; + } + while (left < right && !/[a-zA-Z]/.test(chars[right])) { + right--; + } + [chars[left], chars[right]] = [chars[right], chars[left]]; + left++; + right--; + } + + return chars.join(''); +}; diff --git a/solutions/0961-n-repeated-element-in-size-2n-array.js b/solutions/0961-n-repeated-element-in-size-2n-array.js new file mode 100644 index 00000000..6ecd7d83 --- /dev/null +++ b/solutions/0961-n-repeated-element-in-size-2n-array.js @@ -0,0 +1,24 @@ +/** + * 961. N-Repeated Element in Size 2N Array + * https://leetcode.com/problems/n-repeated-element-in-size-2n-array/ + * Difficulty: Easy + * + * You are given an integer array nums with the following properties: + * - nums.length == 2 * n. + * - nums contains n + 1 unique elements. + * - Exactly one element of nums is repeated n times. + * + * Return the element that is repeated n times. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var repeatedNTimes = function(nums) { + const map = {}; + for (let i = 0; i < nums.length; i++) { + if (!map[nums[i]]) map[nums[i]] = 1; + else return nums[i]; + } +}; diff --git a/solutions/1021-remove-outermost-parentheses.js b/solutions/1021-remove-outermost-parentheses.js new file mode 100644 index 00000000..5fc2fe58 --- /dev/null +++ b/solutions/1021-remove-outermost-parentheses.js @@ -0,0 +1,39 @@ +/** + * 1021. Remove Outermost Parentheses + * https://leetcode.com/problems/remove-outermost-parentheses/ + * Difficulty: Easy + * + * A valid parentheses string is either empty "", "(" + A + ")", or A + B, where A and B are valid + * parentheses strings, and + represents string concatenation. + * - For example, "", "()", "(())()", and "(()(()))" are all valid parentheses strings. + * + * A valid parentheses string s is primitive if it is nonempty, and there does not exist a way to + * split it into s = A + B, with A and B nonempty valid parentheses strings. + * + * Given a valid parentheses string s, consider its primitive decomposition: s = P1 + * + P2 + ... + Pk, where Pi are primitive valid parentheses strings. + * + * Return s after removing the outermost parentheses of every primitive string in the primitive + * decomposition of s. + */ + +/** + * @param {string} s + * @return {string} + */ +var removeOuterParentheses = function(s) { + let result = ''; + let depth = 0; + + for (const char of s) { + if (char === '(') { + if (depth > 0) result += char; + depth++; + } else { + depth--; + if (depth > 0) result += char; + } + } + + return result; +}; 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/1221-split-a-string-in-balanced-strings.js b/solutions/1221-split-a-string-in-balanced-strings.js new file mode 100644 index 00000000..aa0d2805 --- /dev/null +++ b/solutions/1221-split-a-string-in-balanced-strings.js @@ -0,0 +1,30 @@ +/** + * 1221. Split a String in Balanced Strings + * https://leetcode.com/problems/split-a-string-in-balanced-strings/ + * Difficulty: Easy + * + * Balanced strings are those that have an equal quantity of 'L' and 'R' characters. + * + * Given a balanced string s, split it into some number of substrings such that: + * - Each substring is balanced. + * + * Return the maximum number of balanced strings you can obtain. + */ + +/** + * @param {string} s + * @return {number} + */ +var balancedStringSplit = function(s) { + let result = 0; + let balance = 0; + + for (const char of s) { + if (char === 'R') balance++; + else balance--; + + if (balance === 0) result++; + } + + return result; +}; 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/1266-minimum-time-visiting-all-points.js b/solutions/1266-minimum-time-visiting-all-points.js new file mode 100644 index 00000000..97eff7f6 --- /dev/null +++ b/solutions/1266-minimum-time-visiting-all-points.js @@ -0,0 +1,28 @@ +/** + * 1266. Minimum Time Visiting All Points + * https://leetcode.com/problems/minimum-time-visiting-all-points/ + * Difficulty: Easy + * + * On a 2D plane, there are n points with integer coordinates points[i] = [xi, yi]. Return the + * minimum time in seconds to visit all the points in the order given by points. + * + * You can move according to these rules: + * - In 1 second, you can either: + * - move vertically by one unit, + * - move horizontally by one unit, or + * - move diagonally sqrt(2) units (in other words, move one unit vertically then one unit + * horizontally in 1 second). + * - You have to visit the points in the same order as they appear in the array. + * - You are allowed to pass through points that appear later in the order, but these do not + * count as visits. + */ + +/** + * @param {number[][]} points + * @return {number} + */ +var minTimeToVisitAllPoints = function(points) { + return points.reduce((steps, point, i) => steps + (!points[i + 1] ? 0 : Math.max( + Math.abs(point[0] - points[i + 1][0]), Math.abs(point[1] - points[i + 1][1]) + )), 0); +}; 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/1281-subtract-the-product-and-sum-of-digits-of-an-integer.js b/solutions/1281-subtract-the-product-and-sum-of-digits-of-an-integer.js new file mode 100644 index 00000000..8854b93f --- /dev/null +++ b/solutions/1281-subtract-the-product-and-sum-of-digits-of-an-integer.js @@ -0,0 +1,26 @@ +/** + * 1281. Subtract the Product and Sum of Digits of an Integer + * https://leetcode.com/problems/subtract-the-product-and-sum-of-digits-of-an-integer/ + * Difficulty: Easy + * + * Given an integer number n, return the difference between the product of its digits and + * the sum of its digits. + */ + +/** + * @param {number} n + * @return {number} + */ +var subtractProductAndSum = function(n) { + let product = 1; + let sum = 0; + + while (n > 0) { + const digit = n % 10; + product *= digit; + sum += digit; + n = Math.floor(n / 10); + } + + return product - sum; +}; diff --git a/solutions/1282-group-the-people-given-the-group-size-they-belong-to.js b/solutions/1282-group-the-people-given-the-group-size-they-belong-to.js new file mode 100644 index 00000000..72a55368 --- /dev/null +++ b/solutions/1282-group-the-people-given-the-group-size-they-belong-to.js @@ -0,0 +1,39 @@ +/** + * 1282. Group the People Given the Group Size They Belong To + * https://leetcode.com/problems/group-the-people-given-the-group-size-they-belong-to/ + * Difficulty: Medium + * + * There are n people that are split into some unknown number of groups. Each person is labeled + * with a unique ID from 0 to n - 1. + * + * You are given an integer array groupSizes, where groupSizes[i] is the size of the group that + * person i is in. For example, if groupSizes[1] = 3, then person 1 must be in a group of size 3. + * + * Return a list of groups such that each person i is in a group of size groupSizes[i]. + * + * Each person should appear in exactly one group, and every person must be in a group. If there + * are multiple answers, return any of them. It is guaranteed that there will be at least one + * valid solution for the given input. + */ + +/** + * @param {number[]} groupSizes + * @return {number[][]} + */ +var groupThePeople = function(groupSizes) { + const map = new Map(); + const grouped = []; + + for (let i = 0; i < groupSizes.length; i++) { + const size = groupSizes[i]; + + map.set(size, map.has(size) ? [...map.get(size), i] : [i]); + + if (map.get(size).length === size) { + grouped.push(map.get(size)); + map.delete(size); + } + } + + return grouped; +}; diff --git a/solutions/1283-find-the-smallest-divisor-given-a-threshold.js b/solutions/1283-find-the-smallest-divisor-given-a-threshold.js new file mode 100644 index 00000000..12eb3776 --- /dev/null +++ b/solutions/1283-find-the-smallest-divisor-given-a-threshold.js @@ -0,0 +1,37 @@ +/** + * 1283. Find the Smallest Divisor Given a Threshold + * https://leetcode.com/problems/find-the-smallest-divisor-given-a-threshold/ + * Difficulty: Medium + * + * Given an array of integers nums and an integer threshold, we will choose a positive integer + * divisor, divide all the array by it, and sum the division's result. Find the smallest divisor + * such that the result mentioned above is less than or equal to threshold. + * + * Each result of the division is rounded to the nearest integer greater than or equal to that + * element. (For example: 7/3 = 3 and 10/2 = 5). + * + * The test cases are generated so that there will be an answer. + */ + +/** + * @param {number[]} nums + * @param {number} threshold + * @return {number} + */ +var smallestDivisor = function(nums, threshold) { + let left = 1; + let right = Math.max(...nums); + + while (left < right) { + const mid = Math.floor((left + right) / 2); + const sum = nums.reduce((acc, num) => acc + Math.ceil(num / mid), 0); + + if (sum <= threshold) { + right = mid; + } else { + left = mid + 1; + } + } + + return left; +}; 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/1508-range-sum-of-sorted-subarray-sums.js b/solutions/1508-range-sum-of-sorted-subarray-sums.js new file mode 100644 index 00000000..611b82da --- /dev/null +++ b/solutions/1508-range-sum-of-sorted-subarray-sums.js @@ -0,0 +1,41 @@ +/** + * 1508. Range Sum of Sorted Subarray Sums + * https://leetcode.com/problems/range-sum-of-sorted-subarray-sums/ + * Difficulty: Medium + * + * You are given the array nums consisting of n positive integers. You computed the sum of all + * non-empty continuous subarrays from the array and then sorted them in non-decreasing order, + * creating a new array of n * (n + 1) / 2 numbers. + * + * Return the sum of the numbers from index left to index right (indexed from 1), inclusive, + * in the new array. Since the answer can be a huge number return it modulo 109 + 7. + */ + +/** + * @param {number[]} nums + * @param {number} n + * @param {number} left + * @param {number} right + * @return {number} + */ +var rangeSum = function(nums, n, left, right) { + const MOD = 1e9 + 7; + const sums = []; + + for (let start = 0; start < n; start++) { + let currentSum = 0; + for (let end = start; end < n; end++) { + currentSum += nums[end]; + sums.push(currentSum); + } + } + + sums.sort((a, b) => a - b); + + let result = 0; + for (let i = left - 1; i < right; i++) { + result = (result + sums[i]) % MOD; + } + + return result; +}; diff --git a/solutions/1509-minimum-difference-between-largest-and-smallest-value-in-three-moves.js b/solutions/1509-minimum-difference-between-largest-and-smallest-value-in-three-moves.js new file mode 100644 index 00000000..ea4a397d --- /dev/null +++ b/solutions/1509-minimum-difference-between-largest-and-smallest-value-in-three-moves.js @@ -0,0 +1,32 @@ +/** + * 1509. Minimum Difference Between Largest and Smallest Value in Three Moves + * https://leetcode.com/problems/minimum-difference-between-largest-and-smallest-value-in-three-moves/ + * Difficulty: Medium + * + * You are given an integer array nums. + * + * In one move, you can choose one element of nums and change it to any value. + * + * Return the minimum difference between the largest and smallest value of nums after performing at + * most three moves. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minDifference = function(nums) { + if (nums.length <= 4) return 0; + + nums.sort((a, b) => a - b); + + const n = nums.length; + let result = Infinity; + + result = Math.min(result, nums[n - 1] - nums[3]); + result = Math.min(result, nums[n - 2] - nums[2]); + result = Math.min(result, nums[n - 3] - nums[1]); + result = Math.min(result, nums[n - 4] - nums[0]); + + return result; +}; diff --git a/solutions/1510-stone-game-iv.js b/solutions/1510-stone-game-iv.js new file mode 100644 index 00000000..51282ddd --- /dev/null +++ b/solutions/1510-stone-game-iv.js @@ -0,0 +1,34 @@ +/** + * 1510. Stone Game IV + * https://leetcode.com/problems/stone-game-iv/ + * Difficulty: Hard + * + * Alice and Bob take turns playing a game, with Alice starting first. + * + * Initially, there are n stones in a pile. On each player's turn, that player makes a move + * consisting of removing any non-zero square number of stones in the pile. + * + * Also, if a player cannot make a move, he/she loses the game. + * + * Given a positive integer n, return true if and only if Alice wins the game otherwise return + * false, assuming both players play optimally. + */ + +/** + * @param {number} n + * @return {boolean} + */ +var winnerSquareGame = function(n) { + const dp = new Array(n + 1).fill(false); + + for (let stones = 1; stones <= n; stones++) { + for (let square = 1; square * square <= stones; square++) { + if (!dp[stones - square * square]) { + dp[stones] = true; + break; + } + } + } + + return dp[n]; +}; diff --git a/solutions/1513-number-of-substrings-with-only-1s.js b/solutions/1513-number-of-substrings-with-only-1s.js new file mode 100644 index 00000000..5052a65d --- /dev/null +++ b/solutions/1513-number-of-substrings-with-only-1s.js @@ -0,0 +1,29 @@ +/** + * 1513. Number of Substrings With Only 1s + * https://leetcode.com/problems/number-of-substrings-with-only-1s/ + * Difficulty: Medium + * + * Given a binary string s, return the number of substrings with all characters 1's. Since the + * answer may be too large, return it modulo 109 + 7. + */ + +/** + * @param {string} s + * @return {number} + */ +var numSub = function(s) { + const MOD = 1e9 + 7; + let result = 0; + let consecutiveOnes = 0; + + for (const char of s) { + if (char === '1') { + consecutiveOnes++; + result = (result + consecutiveOnes) % MOD; + } else { + consecutiveOnes = 0; + } + } + + return result; +}; diff --git a/solutions/1514-path-with-maximum-probability.js b/solutions/1514-path-with-maximum-probability.js new file mode 100644 index 00000000..aba75224 --- /dev/null +++ b/solutions/1514-path-with-maximum-probability.js @@ -0,0 +1,48 @@ +/** + * 1514. Path with Maximum Probability + * https://leetcode.com/problems/path-with-maximum-probability/ + * Difficulty: Medium + * + * You are given an undirected weighted graph of n nodes (0-indexed), represented by an edge list + * where edges[i] = [a, b] is an undirected edge connecting the nodes a and b with a probability + * of success of traversing that edge succProb[i]. + * + * Given two nodes start and end, find the path with the maximum probability of success to go from + * start to end and return its success probability. + * + * If there is no path from start to end, return 0. Your answer will be accepted if it differs from + * the correct answer by at most 1e-5. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number[]} succProb + * @param {number} startNode + * @param {number} endNode + * @return {number} + */ +var maxProbability = function(n, edges, succProb, startNode, endNode) { + const maxProbs = new Array(n).fill(0); + maxProbs[startNode] = 1; + + const graph = Array.from({ length: n }, () => []); + edges.forEach(([a, b], i) => { + graph[a].push([b, succProb[i]]); + graph[b].push([a, succProb[i]]); + }); + + const queue = [startNode]; + while (queue.length) { + const current = queue.shift(); + for (const [next, prob] of graph[current]) { + const newProb = maxProbs[current] * prob; + if (newProb > maxProbs[next]) { + maxProbs[next] = newProb; + queue.push(next); + } + } + } + + return maxProbs[endNode]; +}; diff --git a/solutions/1515-best-position-for-a-service-centre.js b/solutions/1515-best-position-for-a-service-centre.js new file mode 100644 index 00000000..baee8eba --- /dev/null +++ b/solutions/1515-best-position-for-a-service-centre.js @@ -0,0 +1,72 @@ +/** + * 1515. Best Position for a Service Centre + * https://leetcode.com/problems/best-position-for-a-service-centre/ + * Difficulty: Hard + * + * A delivery company wants to build a new service center in a new city. The company knows the + * positions of all the customers in this city on a 2D-Map and wants to build the new center in + * a position such that the sum of the euclidean distances to all customers is minimum. + * + * Given an array positions where positions[i] = [xi, yi] is the position of the ith customer on + * the map, return the minimum sum of the euclidean distances to all customers. + * + * In other words, you need to choose the position of the service center [xcentre, ycentre] such + * that the following formula is minimized: + * - Answers within 10-5 of the actual value will be accepted. + */ + +/** + * @param {number[][]} positions + * @return {number} + */ +var getMinDistSum = function(positions) { + const n = positions.length; + let xSum = 0; + let ySum = 0; + + for (const [x, y] of positions) { + xSum += x; + ySum += y; + } + + let xCenter = xSum / n; + let yCenter = ySum / n; + const epsilon = 1e-7; + const maxIterations = 1000; + + for (let iter = 0; iter < maxIterations; iter++) { + let xNumerator = 0; + let yNumerator = 0; + let denominator = 0; + + for (const [x, y] of positions) { + const dx = xCenter - x; + const dy = yCenter - y; + const dist = Math.sqrt(dx * dx + dy * dy); + if (dist < epsilon) continue; + const weight = 1 / dist; + xNumerator += x * weight; + yNumerator += y * weight; + denominator += weight; + } + + if (denominator < epsilon) break; + + const newX = xNumerator / denominator; + const newY = yNumerator / denominator; + + if (Math.abs(newX - xCenter) < epsilon && Math.abs(newY - yCenter) < epsilon) { + break; + } + + xCenter = newX; + yCenter = newY; + } + + let sumDist = 0; + for (const [x, y] of positions) { + sumDist += Math.sqrt((xCenter - x) ** 2 + (yCenter - y) ** 2); + } + + return sumDist; +}; 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/1518-water-bottles.js b/solutions/1518-water-bottles.js new file mode 100644 index 00000000..fe7ce020 --- /dev/null +++ b/solutions/1518-water-bottles.js @@ -0,0 +1,31 @@ +/** + * 1518. Water Bottles + * https://leetcode.com/problems/water-bottles/ + * Difficulty: Easy + * + * There are numBottles water bottles that are initially full of water. You can exchange numExchange + * empty water bottles from the market with one full water bottle. + * + * The operation of drinking a full water bottle turns it into an empty bottle. + * + * Given the two integers numBottles and numExchange, return the maximum number of water bottles you + * can drink. + */ + +/** + * @param {number} numBottles + * @param {number} numExchange + * @return {number} + */ +var numWaterBottles = function(numBottles, numExchange) { + let result = numBottles; + let emptyBottles = numBottles; + + while (emptyBottles >= numExchange) { + const newBottles = Math.floor(emptyBottles / numExchange); + result += newBottles; + emptyBottles = newBottles + (emptyBottles % numExchange); + } + + return result; +}; diff --git a/solutions/1520-maximum-number-of-non-overlapping-substrings.js b/solutions/1520-maximum-number-of-non-overlapping-substrings.js new file mode 100644 index 00000000..91f48d51 --- /dev/null +++ b/solutions/1520-maximum-number-of-non-overlapping-substrings.js @@ -0,0 +1,66 @@ +/** + * 1520. Maximum Number of Non-Overlapping Substrings + * https://leetcode.com/problems/maximum-number-of-non-overlapping-substrings/ + * Difficulty: Hard + * + * Given a string s of lowercase letters, you need to find the maximum number of non-empty + * substrings of s that meet the following conditions: + * 1. The substrings do not overlap, that is for any two substrings s[i..j] and s[x..y], + * either j < x or i > y is true. + * 2. A substring that contains a certain character c must also contain all occurrences of c. + * + * Find the maximum number of substrings that meet the above conditions. If there are multiple + * solutions with the same number of substrings, return the one with minimum total length. It + * can be shown that there exists a unique solution of minimum total length. + * + * Notice that you can return the substrings in any order. + */ + +/** + * @param {string} s + * @return {string[]} + */ +var maxNumOfSubstrings = function(s) { + const charRange = new Array(26).fill().map(() => [Infinity, -Infinity]); + + for (let i = 0; i < s.length; i++) { + const charIndex = s.charCodeAt(i) - 97; + charRange[charIndex][0] = Math.min(charRange[charIndex][0], i); + charRange[charIndex][1] = Math.max(charRange[charIndex][1], i); + } + + const intervals = []; + for (let c = 0; c < 26; c++) { + if (charRange[c][0] === Infinity) continue; + const start = charRange[c][0]; + let end = charRange[c][1]; + let valid = true; + + for (let i = start; i <= end; i++) { + const charIndex = s.charCodeAt(i) - 97; + if (charRange[charIndex][0] < start) { + valid = false; + break; + } + end = Math.max(end, charRange[charIndex][1]); + } + + if (valid) { + intervals.push([start, end]); + } + } + + intervals.sort((a, b) => a[1] - b[1] || a[0] - b[0]); + + const result = []; + let lastEnd = -1; + + for (const [start, end] of intervals) { + if (start > lastEnd) { + result.push(s.slice(start, end + 1)); + lastEnd = end; + } + } + + return result; +}; diff --git a/solutions/1521-find-a-value-of-a-mysterious-function-closest-to-target.js b/solutions/1521-find-a-value-of-a-mysterious-function-closest-to-target.js new file mode 100644 index 00000000..20f2b679 --- /dev/null +++ b/solutions/1521-find-a-value-of-a-mysterious-function-closest-to-target.js @@ -0,0 +1,38 @@ +/** + * 1521. Find a Value of a Mysterious Function Closest to Target + * https://leetcode.com/problems/find-a-value-of-a-mysterious-function-closest-to-target/ + * Difficulty: Hard + * + * Winston was given the above mysterious function func. He has an integer array arr and an integer + * target and he wants to find the values l and r that make the value |func(arr, l, r) - target| + * minimum possible. + * + * Return the minimum possible value of |func(arr, l, r) - target|. + * + * Notice that func should be called with the values l and r where 0 <= l, r < arr.length. + */ + +/** + * @param {number[]} arr + * @param {number} target + * @return {number} + */ +var closestToTarget = function(arr, target) { + let result = Infinity; + let seen = new Set(); + + for (let right = 0; right < arr.length; right++) { + const current = new Set([arr[right]]); + result = Math.min(result, Math.abs(arr[right] - target)); + + for (const previous of seen) { + const currentAnd = previous & arr[right]; + current.add(currentAnd); + result = Math.min(result, Math.abs(currentAnd - target)); + } + + seen = current; + } + + return result; +}; 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/1523-count-odd-numbers-in-an-interval-range.js b/solutions/1523-count-odd-numbers-in-an-interval-range.js new file mode 100644 index 00000000..40e853a0 --- /dev/null +++ b/solutions/1523-count-odd-numbers-in-an-interval-range.js @@ -0,0 +1,23 @@ +/** + * 1523. Count Odd Numbers in an Interval Range + * https://leetcode.com/problems/count-odd-numbers-in-an-interval-range/ + * Difficulty: Easy + * + * Given two non-negative integers low and high. Return the count of odd numbers between low + * and high (inclusive). + */ + +/** + * @param {number} low + * @param {number} high + * @return {number} + */ +var countOdds = function(low, high) { + const range = high - low + 1; + + if (low % 2 !== 0 && high % 2 !== 0) { + return Math.floor(range / 2) + 1; + } + + return Math.floor(range / 2); +}; diff --git a/solutions/1525-number-of-good-ways-to-split-a-string.js b/solutions/1525-number-of-good-ways-to-split-a-string.js new file mode 100644 index 00000000..2d24d3ce --- /dev/null +++ b/solutions/1525-number-of-good-ways-to-split-a-string.js @@ -0,0 +1,44 @@ +/** + * 1525. Number of Good Ways to Split a String + * https://leetcode.com/problems/number-of-good-ways-to-split-a-string/ + * Difficulty: Medium + * + * You are given a string s. + * + * A split is called good if you can split s into two non-empty strings sleft and sright where + * their concatenation is equal to s (i.e., sleft + sright = s) and the number of distinct letters + * in sleft and sright is the same. + * + * Return the number of good splits you can make in s. + */ + +/** + * @param {string} s + * @return {number} + */ +var numSplits = function(s) { + const leftDistinct = new Map(); + const rightDistinct = new Map(); + let result = 0; + + for (const char of s) { + rightDistinct.set(char, (rightDistinct.get(char) || 0) + 1); + } + + for (let i = 0; i < s.length - 1; i++) { + const char = s[i]; + leftDistinct.set(char, (leftDistinct.get(char) || 0) + 1); + + if (rightDistinct.get(char) === 1) { + rightDistinct.delete(char); + } else { + rightDistinct.set(char, rightDistinct.get(char) - 1); + } + + if (leftDistinct.size === rightDistinct.size) { + result++; + } + } + + return result; +}; diff --git a/solutions/1526-minimum-number-of-increments-on-subarrays-to-form-a-target-array.js b/solutions/1526-minimum-number-of-increments-on-subarrays-to-form-a-target-array.js new file mode 100644 index 00000000..4271112a --- /dev/null +++ b/solutions/1526-minimum-number-of-increments-on-subarrays-to-form-a-target-array.js @@ -0,0 +1,28 @@ +/** + * 1526. Minimum Number of Increments on Subarrays to Form a Target Array + * https://leetcode.com/problems/minimum-number-of-increments-on-subarrays-to-form-a-target-array/ + * Difficulty: Hard + * + * You are given an integer array target. You have an integer array initial of the same size as + * target with all elements initially zeros. + * + * In one operation you can choose any subarray from initial and increment each value by one. + * + * Return the minimum number of operations to form a target array from initial. + * + * The test cases are generated so that the answer fits in a 32-bit integer. + */ + +/** + * @param {number[]} target + * @return {number} + */ +var minNumberOperations = function(target) { + let operations = target[0]; + for (let i = 1; i < target.length; i++) { + if (target[i] > target[i - 1]) { + operations += target[i] - target[i - 1]; + } + } + return operations; +}; diff --git a/solutions/1529-minimum-suffix-flips.js b/solutions/1529-minimum-suffix-flips.js new file mode 100644 index 00000000..bf497b9c --- /dev/null +++ b/solutions/1529-minimum-suffix-flips.js @@ -0,0 +1,31 @@ +/** + * 1529. Minimum Suffix Flips + * https://leetcode.com/problems/minimum-suffix-flips/ + * Difficulty: Medium + * + * You are given a 0-indexed binary string target of length n. You have another binary string s + * of length n that is initially set to all zeros. You want to make s equal to target. + * + * In one operation, you can pick an index i where 0 <= i < n and flip all bits in the inclusive + * range [i, n - 1]. Flip means changing '0' to '1' and '1' to '0'. + * + * Return the minimum number of operations needed to make s equal to target. + */ + +/** + * @param {string} target + * @return {number} + */ +var minFlips = function(target) { + let current = '0'; + let result = 0; + + for (const bit of target) { + if (bit !== current) { + result++; + current = bit; + } + } + + return result; +}; diff --git a/solutions/1530-number-of-good-leaf-nodes-pairs.js b/solutions/1530-number-of-good-leaf-nodes-pairs.js new file mode 100644 index 00000000..a5364874 --- /dev/null +++ b/solutions/1530-number-of-good-leaf-nodes-pairs.js @@ -0,0 +1,51 @@ +/** + * 1530. Number of Good Leaf Nodes Pairs + * https://leetcode.com/problems/number-of-good-leaf-nodes-pairs/ + * Difficulty: Medium + * + * You are given the root of a binary tree and an integer distance. A pair of two different leaf + * nodes of a binary tree is said to be good if the length of the shortest path between them is + * less than or equal to distance. + * + * Return the number of good leaf node pairs in the 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} distance + * @return {number} + */ +var countPairs = function(root, distance) { + let result = 0; + traverseTree(root); + return result; + + function traverseTree(node) { + if (!node) return []; + if (!node.left && !node.right) return [1]; + + const leftDistances = traverseTree(node.left); + const rightDistances = traverseTree(node.right); + + for (const left of leftDistances) { + for (const right of rightDistances) { + if (left + right <= distance) result++; + } + } + + const allDistances = []; + for (const dist of leftDistances.concat(rightDistances)) { + if (dist + 1 <= distance) allDistances.push(dist + 1); + } + + return allDistances; + } +}; diff --git a/solutions/1531-string-compression-ii.js b/solutions/1531-string-compression-ii.js new file mode 100644 index 00000000..099d1eb7 --- /dev/null +++ b/solutions/1531-string-compression-ii.js @@ -0,0 +1,63 @@ +/** + * 1531. String Compression II + * https://leetcode.com/problems/string-compression-ii/ + * Difficulty: Hard + * + * Run-length encoding is a string compression method that works by replacing consecutive + * identical characters (repeated 2 or more times) with the concatenation of the character + * and the number marking the count of the characters (length of the run). For example, + * to compress the string "aabccc" we replace "aa" by "a2" and replace "ccc" by "c3". Thus + * the compressed string becomes "a2bc3". + * + * Notice that in this problem, we are not adding '1' after single characters. + * + * Given a string s and an integer k. You need to delete at most k characters from s such that + * the run-length encoded version of s has minimum length. + * + * Find the minimum length of the run-length encoded version of s after deleting at most + * k characters. + */ + +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +var getLengthOfOptimalCompression = function(s, k) { + const n = s.length; + const dp = new Array(n + 1).fill().map(() => new Array(k + 1).fill(9999)); + dp[0][0] = 0; + + for (let i = 1; i <= n; i++) { + for (let j = 0; j <= k; j++) { + let count = 0; + let deletions = 0; + + for (let m = i; m >= 1; m--) { + if (s[m - 1] === s[i - 1]) count++; + else deletions++; + + if (j - deletions >= 0) { + dp[i][j] = Math.min( + dp[i][j], + dp[m - 1][j - deletions] + calculateEncodedLength(count) + ); + } + } + + if (j > 0) { + dp[i][j] = Math.min(dp[i][j], dp[i - 1][j - 1]); + } + } + } + + return dp[n][k]; + + function calculateEncodedLength(count) { + if (count === 0) return 0; + if (count === 1) return 1; + if (count < 10) return 2; + if (count < 100) return 3; + return 4; + } +}; 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/1536-minimum-swaps-to-arrange-a-binary-grid.js b/solutions/1536-minimum-swaps-to-arrange-a-binary-grid.js new file mode 100644 index 00000000..c479ed57 --- /dev/null +++ b/solutions/1536-minimum-swaps-to-arrange-a-binary-grid.js @@ -0,0 +1,58 @@ +/** + * 1536. Minimum Swaps to Arrange a Binary Grid + * https://leetcode.com/problems/minimum-swaps-to-arrange-a-binary-grid/ + * Difficulty: Medium + * + * Given an n x n binary grid, in one step you can choose two adjacent rows of the grid and + * swap them. + * + * A grid is said to be valid if all the cells above the main diagonal are zeros. + * + * Return the minimum number of steps needed to make the grid valid, or -1 if the grid cannot + * be valid. + * + * The main diagonal of a grid is the diagonal that starts at cell (1, 1) and ends at cell (n, n). + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var minSwaps = function(grid) { + const n = grid.length; + const trailingZeros = new Array(n).fill(0); + + for (let i = 0; i < n; i++) { + trailingZeros[i] = countTrailingZeros(i); + } + + let swaps = 0; + for (let i = 0; i < n - 1; i++) { + const requiredZeros = n - i - 1; + let found = false; + + for (let j = i; j < n; j++) { + if (trailingZeros[j] >= requiredZeros) { + found = true; + for (let k = j; k > i; k--) { + [trailingZeros[k], trailingZeros[k - 1]] = [trailingZeros[k - 1], trailingZeros[k]]; + swaps++; + } + break; + } + } + + if (!found) return -1; + } + + return swaps; + + function countTrailingZeros(row) { + let count = 0; + for (let j = n - 1; j >= 0; j--) { + if (grid[row][j] === 0) count++; + else break; + } + return count; + } +}; diff --git a/solutions/1537-get-the-maximum-score.js b/solutions/1537-get-the-maximum-score.js new file mode 100644 index 00000000..b4be118c --- /dev/null +++ b/solutions/1537-get-the-maximum-score.js @@ -0,0 +1,55 @@ +/** + * 1537. Get the Maximum Score + * https://leetcode.com/problems/get-the-maximum-score/ + * Difficulty: Hard + * + * You are given two sorted arrays of distinct integers nums1 and nums2. + * + * A valid path is defined as follows: + * - Choose array nums1 or nums2 to traverse (from index-0). + * - Traverse the current array from left to right. + * - If you are reading any value that is present in nums1 and nums2 you are allowed to change + * your path to the other array. (Only one repeated value is considered in the valid path). + * + * The score is defined as the sum of unique values in a valid path. + * + * Return the maximum score you can obtain of all possible valid paths. Since the answer may be + * too large, return it modulo 109 + 7. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var maxSum = function(nums1, nums2) { + const MOD = 1e9 + 7; + const m = nums1.length; + const n = nums2.length; + let i = 0; + let j = 0; + let sum1 = 0; + let sum2 = 0; + + while (i < m && j < n) { + if (nums1[i] < nums2[j]) { + sum1 += nums1[i++]; + } else if (nums1[i] > nums2[j]) { + sum2 += nums2[j++]; + } else { + sum1 = sum2 = Math.max(sum1, sum2) + nums1[i]; + i++; + j++; + } + } + + while (i < m) { + sum1 += nums1[i++]; + } + + while (j < n) { + sum2 += nums2[j++]; + } + + return Math.max(sum1, sum2) % MOD; +}; 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/1539-kth-missing-positive-number.js b/solutions/1539-kth-missing-positive-number.js new file mode 100644 index 00000000..2f89676b --- /dev/null +++ b/solutions/1539-kth-missing-positive-number.js @@ -0,0 +1,32 @@ +/** + * 1539. Kth Missing Positive Number + * https://leetcode.com/problems/kth-missing-positive-number/ + * Difficulty: Easy + * + * Given an array arr of positive integers sorted in a strictly increasing order, and an integer k. + * + * Return the kth positive integer that is missing from this array. + */ + +/** + * @param {number[]} arr + * @param {number} k + * @return {number} + */ +var findKthPositive = function(arr, k) { + let left = 0; + let right = arr.length - 1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + const count = arr[mid] - mid - 1; + + if (count < k) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return left + k; +}; diff --git a/solutions/1540-can-convert-string-in-k-moves.js b/solutions/1540-can-convert-string-in-k-moves.js new file mode 100644 index 00000000..3bc55397 --- /dev/null +++ b/solutions/1540-can-convert-string-in-k-moves.js @@ -0,0 +1,45 @@ +/** + * 1540. Can Convert String in K Moves + * https://leetcode.com/problems/can-convert-string-in-k-moves/ + * Difficulty: Medium + * + * Given two strings s and t, your goal is to convert s into t in k moves or less. + * + * During the ith (1 <= i <= k) move you can: + * - Choose any index j (1-indexed) from s, such that 1 <= j <= s.length and j has not been chosen + * in any previous move, and shift the character at that index i times. + * - Do nothing. + * + * Shifting a character means replacing it by the next letter in the alphabet (wrapping around so + * that 'z' becomes 'a'). Shifting a character by i means applying the shift operations i times. + * + * Remember that any index j can be picked at most once. + * + * Return true if it's possible to convert s into t in no more than k moves, otherwise return false. + */ + +/** + * @param {string} s + * @param {string} t + * @param {number} k + * @return {boolean} + */ +var canConvertString = function(source, target, maxMoves) { + if (source.length !== target.length) return false; + const shiftCounts = new Array(26).fill(0); + + for (let i = 0; i < source.length; i++) { + const shiftNeeded = (target.charCodeAt(i) - source.charCodeAt(i) + 26) % 26; + if (shiftNeeded > 0) { + shiftCounts[shiftNeeded]++; + } + } + + for (let shift = 1; shift < 26; shift++) { + if (shiftCounts[shift] === 0) continue; + const totalMoves = shift + 26 * (shiftCounts[shift] - 1); + if (totalMoves > maxMoves) return false; + } + + return true; +}; diff --git a/solutions/1541-minimum-insertions-to-balance-a-parentheses-string.js b/solutions/1541-minimum-insertions-to-balance-a-parentheses-string.js new file mode 100644 index 00000000..83dbd166 --- /dev/null +++ b/solutions/1541-minimum-insertions-to-balance-a-parentheses-string.js @@ -0,0 +1,48 @@ +/** + * 1541. Minimum Insertions to Balance a Parentheses String + * https://leetcode.com/problems/minimum-insertions-to-balance-a-parentheses-string/ + * Difficulty: Medium + * + * Given a parentheses string s containing only the characters '(' and ')'. A parentheses string + * is balanced if: + * - Any left parenthesis '(' must have a corresponding two consecutive right parenthesis '))'. + * - Left parenthesis '(' must go before the corresponding two consecutive right parenthesis '))'. + * + * In other words, we treat '(' as an opening parenthesis and '))' as a closing parenthesis. + * - For example, "())", "())(())))" and "(())())))" are balanced, ")()", "()))" and "(()))" are + * not balanced. + * + * You can insert the characters '(' and ')' at any position of the string to balance it if needed. + * + * Return the minimum number of insertions needed to make s balanced. + */ + +/** + * @param {string} s + * @return {number} + */ +var minInsertions = function(s) { + let result = 0; + let openCount = 0; + + for (let i = 0; i < s.length; i++) { + if (s[i] === '(') { + openCount++; + } else { + if (i + 1 < s.length && s[i + 1] === ')') { + i++; + } else { + result++; + } + if (openCount > 0) { + openCount--; + } else { + result++; + } + } + } + + result += openCount * 2; + + return result; +}; diff --git a/solutions/1542-find-longest-awesome-substring.js b/solutions/1542-find-longest-awesome-substring.js new file mode 100644 index 00000000..45c349a1 --- /dev/null +++ b/solutions/1542-find-longest-awesome-substring.js @@ -0,0 +1,41 @@ +/** + * 1542. Find Longest Awesome Substring + * https://leetcode.com/problems/find-longest-awesome-substring/ + * Difficulty: Hard + * + * You are given a string s. An awesome substring is a non-empty substring of s such that we + * can make any number of swaps in order to make it a palindrome. + * + * Return the length of the maximum length awesome substring of s. + */ + +/** + * @param {string} s + * @return {number} + */ +var longestAwesome = function(s) { + let result = 0; + let prefixMask = 0; + const digitMasks = new Map(); + digitMasks.set(0, -1); + + for (let i = 0; i < s.length; i++) { + const digit = s.charCodeAt(i) - '0'.charCodeAt(0); + prefixMask ^= (1 << digit); + + if (digitMasks.has(prefixMask)) { + result = Math.max(result, i - digitMasks.get(prefixMask)); + } else { + digitMasks.set(prefixMask, i); + } + + for (let j = 0; j < 10; j++) { + const oddMask = prefixMask ^ (1 << j); + if (digitMasks.has(oddMask)) { + result = Math.max(result, i - digitMasks.get(oddMask)); + } + } + } + + return result; +}; diff --git a/solutions/1544-make-the-string-great.js b/solutions/1544-make-the-string-great.js new file mode 100644 index 00000000..edcaeed9 --- /dev/null +++ b/solutions/1544-make-the-string-great.js @@ -0,0 +1,38 @@ +/** + * 1544. Make The String Great + * https://leetcode.com/problems/make-the-string-great/ + * Difficulty: Easy + * + * Given a string s of lower and upper case English letters. + * + * A good string is a string which doesn't have two adjacent characters s[i] and s[i + 1] where: + * - 0 <= i <= s.length - 2 + * - s[i] is a lower-case letter and s[i + 1] is the same letter but in upper-case or vice-versa. + * + * To make the string good, you can choose two adjacent characters that make the string bad and + * remove them. You can keep doing this until the string becomes good. + * + * Return the string after making it good. The answer is guaranteed to be unique under the given + * constraints. + * + * Notice that an empty string is also good. + */ + +/** + * @param {string} s + * @return {string} + */ +var makeGood = function(s) { + const stack = []; + + for (const char of s) { + const lastChar = stack[stack.length - 1]; + if (lastChar && ((char.toLowerCase() === lastChar.toLowerCase()) && (char !== lastChar))) { + stack.pop(); + } else { + stack.push(char); + } + } + + return stack.join(''); +}; diff --git a/solutions/1545-find-kth-bit-in-nth-binary-string.js b/solutions/1545-find-kth-bit-in-nth-binary-string.js new file mode 100644 index 00000000..d2cee786 --- /dev/null +++ b/solutions/1545-find-kth-bit-in-nth-binary-string.js @@ -0,0 +1,48 @@ +/** + * 1545. Find Kth Bit in Nth Binary String + * https://leetcode.com/problems/find-kth-bit-in-nth-binary-string/ + * Difficulty: Medium + * + * Given two positive integers n and k, the binary string Sn is formed as follows: + * - S1 = "0" + * - Si = Si - 1 + "1" + reverse(invert(Si - 1)) for i > 1 + * + * Where + denotes the concatenation operation, reverse(x) returns the reversed string x, and + * invert(x) inverts all the bits in x (0 changes to 1 and 1 changes to 0). + * + * For example, the first four strings in the above sequence are: + * - S1 = "0" + * - S2 = "011" + * - S3 = "0111001" + * - S4 = "011100110110001" + * + * Return the kth bit in Sn. It is guaranteed that k is valid for the given n. + */ + +/** + * @param {number} n + * @param {number} k + * @return {character} + */ +var findKthBit = function(n, k) { + let position = k - 1; + let invertCount = 0; + let length = (1 << n) - 1; + + while (position !== 0) { + const mid = length >> 1; + + if (position === mid) { + return invertCount % 2 === 0 ? '1' : '0'; + } + + if (position > mid) { + position = length - position - 1; + invertCount++; + } else { + length = mid; + } + } + + return invertCount % 2 === 0 ? '0' : '1'; +}; diff --git a/solutions/1546-maximum-number-of-non-overlapping-subarrays-with-sum-equals-target.js b/solutions/1546-maximum-number-of-non-overlapping-subarrays-with-sum-equals-target.js new file mode 100644 index 00000000..094e3d53 --- /dev/null +++ b/solutions/1546-maximum-number-of-non-overlapping-subarrays-with-sum-equals-target.js @@ -0,0 +1,35 @@ +/** + * 1546. Maximum Number of Non-Overlapping Subarrays With Sum Equals Target + * https://leetcode.com/problems/maximum-number-of-non-overlapping-subarrays-with-sum-equals-target/ + * Difficulty: Medium + * + * Given an array nums and an integer target, return the maximum number of non-empty non-overlapping + * subarrays such that the sum of values in each subarray is equal to target. + */ + +/** + * @param {number[]} nums + * @param {number} target + * @return {number} + */ +var maxNonOverlapping = function(nums, target) { + const prefixSums = new Map(); + let currentSum = 0; + let result = 0; + prefixSums.set(0, 0); + + for (let i = 0; i < nums.length; i++) { + currentSum += nums[i]; + + if (prefixSums.has(currentSum - target)) { + result++; + prefixSums.clear(); + prefixSums.set(0, i + 1); + currentSum = 0; + } else { + prefixSums.set(currentSum, i + 1); + } + } + + return result; +}; diff --git a/solutions/1547-minimum-cost-to-cut-a-stick.js b/solutions/1547-minimum-cost-to-cut-a-stick.js new file mode 100644 index 00000000..f7b0cf36 --- /dev/null +++ b/solutions/1547-minimum-cost-to-cut-a-stick.js @@ -0,0 +1,49 @@ +/** + * 1547. Minimum Cost to Cut a Stick + * https://leetcode.com/problems/minimum-cost-to-cut-a-stick/ + * Difficulty: Hard + * + * Given a wooden stick of length n units. The stick is labelled from 0 to n. For example, a + * stick of length 6 is labelled as follows. + * + * Given an integer array cuts where cuts[i] denotes a position you should perform a cut at. + * + * You should perform the cuts in order, you can change the order of the cuts as you wish. + * + * The cost of one cut is the length of the stick to be cut, the total cost is the sum of costs + * of all cuts. When you cut a stick, it will be split into two smaller sticks (i.e. the sum of + * their lengths is the length of the stick before the cut). Please refer to the first example + * for a better explanation. + * + * Return the minimum total cost of the cuts. + */ + +/** + * @param {number} n + * @param {number[]} cuts + * @return {number} + */ +var minCost = function(n, cuts) { + cuts.push(0, n); + cuts.sort((a, b) => a - b); + + const memo = new Map(); + + return computeMinCost(0, cuts.length - 1); + + function computeMinCost(left, right) { + if (right - left <= 1) return 0; + + const key = `${left},${right}`; + if (memo.has(key)) return memo.get(key); + + let minCost = Infinity; + for (let i = left + 1; i < right; i++) { + const cost = (cuts[right] - cuts[left]) + computeMinCost(left, i) + computeMinCost(i, right); + minCost = Math.min(minCost, cost); + } + + memo.set(key, minCost); + return minCost; + } +}; 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/1552-magnetic-force-between-two-balls.js b/solutions/1552-magnetic-force-between-two-balls.js new file mode 100644 index 00000000..ef15f17b --- /dev/null +++ b/solutions/1552-magnetic-force-between-two-balls.js @@ -0,0 +1,53 @@ +/** + * 1552. Magnetic Force Between Two Balls + * https://leetcode.com/problems/magnetic-force-between-two-balls/ + * Difficulty: Medium + * + * In the universe Earth C-137, Rick discovered a special form of magnetic force between two balls + * if they are put in his new invented basket. Rick has n empty baskets, the ith basket is at + * position[i], Morty has m balls and needs to distribute the balls into the baskets such that + * the minimum magnetic force between any two balls is maximum. + * + * Rick stated that magnetic force between two different balls at positions x and y is |x - y|. + * + * Given the integer array position and the integer m. Return the required force. + */ + +/** + * @param {number[]} position + * @param {number} m + * @return {number} + */ +var maxDistance = function(position, m) { + position.sort((a, b) => a - b); + + let left = 1; + let right = position[position.length - 1] - position[0]; + let result = 0; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + if (canPlaceBalls(mid)) { + result = mid; + left = mid + 1; + } else { + right = mid - 1; + } + } + + return result; + + function canPlaceBalls(minForce) { + let count = 1; + let lastPos = position[0]; + + for (let i = 1; i < position.length; i++) { + if (position[i] - lastPos >= minForce) { + count++; + lastPos = position[i]; + } + } + + return count >= m; + } +}; diff --git a/solutions/1553-minimum-number-of-days-to-eat-n-oranges.js b/solutions/1553-minimum-number-of-days-to-eat-n-oranges.js new file mode 100644 index 00000000..7ef834bc --- /dev/null +++ b/solutions/1553-minimum-number-of-days-to-eat-n-oranges.js @@ -0,0 +1,35 @@ +/** + * 1553. Minimum Number of Days to Eat N Oranges + * https://leetcode.com/problems/minimum-number-of-days-to-eat-n-oranges/ + * Difficulty: Hard + * + * There are n oranges in the kitchen and you decided to eat some of these oranges every day as + * follows: + * - Eat one orange. + * - If the number of remaining oranges n is divisible by 2 then you can eat n / 2 oranges. + * - If the number of remaining oranges n is divisible by 3 then you can eat 2 * (n / 3) oranges. + * + * You can only choose one of the actions per day. + * + * Given the integer n, return the minimum number of days to eat n oranges. + */ + +/** + * @param {number} n + * @return {number} + */ +var minDays = function(n) { + const memo = new Map(); + return computeMinDays(n); + + function computeMinDays(oranges) { + if (oranges <= 1) return oranges; + if (memo.has(oranges)) return memo.get(oranges); + + const eatHalf = computeMinDays(Math.floor(oranges / 2)) + (oranges % 2) + 1; + const eatTwoThirds = computeMinDays(Math.floor(oranges / 3)) + (oranges % 3) + 1; + const minDays = Math.min(eatHalf, eatTwoThirds); + memo.set(oranges, minDays); + return minDays; + } +}; 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/1556-thousand-separator.js b/solutions/1556-thousand-separator.js new file mode 100644 index 00000000..c9e078cd --- /dev/null +++ b/solutions/1556-thousand-separator.js @@ -0,0 +1,26 @@ +/** + * 1556. Thousand Separator + * https://leetcode.com/problems/thousand-separator/ + * Difficulty: Easy + * + * Given an integer n, add a dot (".") as the thousands separator and return it in string format. + */ + +/** + * @param {number} n + * @return {string} + */ +var thousandSeparator = function(n) { + const digits = n.toString().split(''); + const result = []; + + while (digits.length > 0) { + const group = digits.splice(-3).join(''); + result.unshift(group); + if (digits.length > 0) { + result.unshift('.'); + } + } + + return result.join(''); +}; diff --git a/solutions/1557-minimum-number-of-vertices-to-reach-all-nodes.js b/solutions/1557-minimum-number-of-vertices-to-reach-all-nodes.js new file mode 100644 index 00000000..2c36e0bc --- /dev/null +++ b/solutions/1557-minimum-number-of-vertices-to-reach-all-nodes.js @@ -0,0 +1,34 @@ +/** + * 1557. Minimum Number of Vertices to Reach All Nodes + * https://leetcode.com/problems/minimum-number-of-vertices-to-reach-all-nodes/ + * Difficulty: Medium + * + * Given a directed acyclic graph, with n vertices numbered from 0 to n-1, and an array edges + * where edges[i] = [fromi, toi] represents a directed edge from node fromi to node toi. + * + * Find the smallest set of vertices from which all nodes in the graph are reachable. It's + * guaranteed that a unique solution exists. + * + * Notice that you can return the vertices in any order. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @return {number[]} + */ +var findSmallestSetOfVertices = function(n, edges) { + const hasIncomingEdge = new Array(n).fill(false); + for (const [_, to] of edges) { + hasIncomingEdge[to] = true; + } + + const result = []; + for (let i = 0; i < n; i++) { + if (!hasIncomingEdge[i]) { + result.push(i); + } + } + + return result; +}; diff --git a/solutions/1558-minimum-numbers-of-function-calls-to-make-target-array.js b/solutions/1558-minimum-numbers-of-function-calls-to-make-target-array.js new file mode 100644 index 00000000..25086640 --- /dev/null +++ b/solutions/1558-minimum-numbers-of-function-calls-to-make-target-array.js @@ -0,0 +1,43 @@ +/** + * 1558. Minimum Numbers of Function Calls to Make Target Array + * https://leetcode.com/problems/minimum-numbers-of-function-calls-to-make-target-array/ + * Difficulty: Medium + * + * You are given an integer array nums. You have an integer array arr of the same length with all + * values set to 0 initially. You also have the following modify function. + * + * You want to use the modify function to convert arr to nums using the minimum number of calls. + * + * Return the minimum number of function calls to make nums from arr. + * + * The test cases are generated so that the answer fits in a 32-bit signed integer. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minOperations = function(nums) { + let totalOperations = 0; + let maxDivisions = 0; + + for (let num of nums) { + let currentDivisions = 0; + let increments = 0; + + while (num > 0) { + if (num % 2 === 1) { + increments++; + num--; + } else { + currentDivisions++; + num /= 2; + } + } + + totalOperations += increments; + maxDivisions = Math.max(maxDivisions, currentDivisions); + } + + return totalOperations + maxDivisions; +}; diff --git a/solutions/1559-detect-cycles-in-2d-grid.js b/solutions/1559-detect-cycles-in-2d-grid.js new file mode 100644 index 00000000..486155dd --- /dev/null +++ b/solutions/1559-detect-cycles-in-2d-grid.js @@ -0,0 +1,58 @@ +/** + * 1559. Detect Cycles in 2D Grid + * https://leetcode.com/problems/detect-cycles-in-2d-grid/ + * Difficulty: Medium + * + * Given a 2D array of characters grid of size m x n, you need to find if there exists any cycle + * consisting of the same value in grid. + * + * A cycle is a path of length 4 or more in the grid that starts and ends at the same cell. From + * a given cell, you can move to one of the cells adjacent to it - in one of the four directions + * (up, down, left, or right), if it has the same value of the current cell. + * + * Also, you cannot move to the cell that you visited in your last move. For example, the cycle + * (1, 1) -> (1, 2) -> (1, 1) is invalid because from (1, 2) we visited (1, 1) which was the last + * visited cell. + * + * Return true if any cycle of the same value exists in grid, otherwise, return false. + */ + +/** + * @param {character[][]} grid + * @return {boolean} + */ +var containsCycle = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const visited = new Set(); + + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + if (!visited.has(`${row},${col}`)) { + if (explorePath(row, col, -1, -1, grid[row][col])) return true; + } + } + } + + return false; + + function explorePath(row, col, prevRow, prevCol, char) { + const key = `${row},${col}`; + if (visited.has(key)) return true; + visited.add(key); + + const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]; + for (const [dx, dy] of directions) { + const newRow = row + dx; + const newCol = col + dy; + + if (newRow === prevRow && newCol === prevCol) continue; + if (newRow < 0 || newRow >= rows || newCol < 0 || newCol >= cols) continue; + if (grid[newRow][newCol] !== char) continue; + + if (explorePath(newRow, newCol, row, col, char)) return true; + } + + return false; + } +}; diff --git a/solutions/1560-most-visited-sector-in-a-circular-track.js b/solutions/1560-most-visited-sector-in-a-circular-track.js new file mode 100644 index 00000000..4c561b2d --- /dev/null +++ b/solutions/1560-most-visited-sector-in-a-circular-track.js @@ -0,0 +1,48 @@ +/** + * 1560. Most Visited Sector in a Circular Track + * https://leetcode.com/problems/most-visited-sector-in-a-circular-track/ + * Difficulty: Easy + * + * Given an integer n and an integer array rounds. We have a circular track which consists of n + * sectors labeled from 1 to n. A marathon will be held on this track, the marathon consists of + * m rounds. The ith round starts at sector rounds[i - 1] and ends at sector rounds[i]. For + * example, round 1 starts at sector rounds[0] and ends at sector rounds[1] + * + * Return an array of the most visited sectors sorted in ascending order. + * + * Notice that you circulate the track in ascending order of sector numbers in the counter-clockwise + * direction (See the first example). + */ + +/** + * @param {number} n + * @param {number[]} rounds + * @return {number[]} + */ +var mostVisited = function(n, rounds) { + const sectorVisits = new Array(n + 1).fill(0); + let maxVisits = 0; + + for (let i = 1; i < rounds.length; i++) { + let start = rounds[i - 1]; + const end = rounds[i]; + + while (start !== end) { + sectorVisits[start]++; + maxVisits = Math.max(maxVisits, sectorVisits[start]); + start = start === n ? 1 : start + 1; + } + } + + sectorVisits[rounds[rounds.length - 1]]++; + maxVisits = Math.max(maxVisits, sectorVisits[rounds[rounds.length - 1]]); + + const result = []; + for (let i = 1; i <= n; i++) { + if (sectorVisits[i] === maxVisits) { + result.push(i); + } + } + + return result; +}; diff --git a/solutions/1561-maximum-number-of-coins-you-can-get.js b/solutions/1561-maximum-number-of-coins-you-can-get.js new file mode 100644 index 00000000..7643b7bd --- /dev/null +++ b/solutions/1561-maximum-number-of-coins-you-can-get.js @@ -0,0 +1,33 @@ +/** + * 1561. Maximum Number of Coins You Can Get + * https://leetcode.com/problems/maximum-number-of-coins-you-can-get/ + * Difficulty: Medium + * + * There are 3n piles of coins of varying size, you and your friends will take piles of coins as + * follows: + * - In each step, you will choose any 3 piles of coins (not necessarily consecutive). + * - Of your choice, Alice will pick the pile with the maximum number of coins. + * - You will pick the next pile with the maximum number of coins. + * - Your friend Bob will pick the last pile. + * - Repeat until there are no more piles of coins. + * + * Given an array of integers piles where piles[i] is the number of coins in the ith pile. + * + * Return the maximum number of coins that you can have. + */ + +/** + * @param {number[]} piles + * @return {number} + */ +var maxCoins = function(piles) { + piles.sort((a, b) => b - a); + let result = 0; + const rounds = piles.length / 3; + + for (let i = 1; i < piles.length - rounds; i += 2) { + result += piles[i]; + } + + return result; +}; diff --git a/solutions/1562-find-latest-group-of-size-m.js b/solutions/1562-find-latest-group-of-size-m.js new file mode 100644 index 00000000..e4d2b3b2 --- /dev/null +++ b/solutions/1562-find-latest-group-of-size-m.js @@ -0,0 +1,48 @@ +/** + * 1562. Find Latest Group of Size M + * https://leetcode.com/problems/find-latest-group-of-size-m/ + * Difficulty: Medium + * + * Given an array arr that represents a permutation of numbers from 1 to n. + * + * You have a binary string of size n that initially has all its bits set to zero. At each step + * i (assuming both the binary string and arr are 1-indexed) from 1 to n, the bit at position + * arr[i] is set to 1. + * + * You are also given an integer m. Find the latest step at which there exists a group of ones + * of length m. A group of ones is a contiguous substring of 1's such that it cannot be extended + * in either direction. + * + * Return the latest step at which there exists a group of ones of length exactly m. If no such + * group exists, return -1. + */ + +/** + * @param {number[]} arr + * @param {number} m + * @return {number} + */ +var findLatestStep = function(arr, m) { + const lengths = new Array(arr.length + 2).fill(0); + const count = new Map(); + let result = -1; + + for (let step = 0; step < arr.length; step++) { + const pos = arr[step]; + const left = lengths[pos - 1]; + const right = lengths[pos + 1]; + const newLength = left + right + 1; + + lengths[pos - left] = newLength; + lengths[pos + right] = newLength; + lengths[pos] = newLength; + + count.set(left, (count.get(left) || 0) - 1); + count.set(right, (count.get(right) || 0) - 1); + count.set(newLength, (count.get(newLength) || 0) + 1); + + if (count.get(m) > 0) result = step + 1; + } + + return result; +}; diff --git a/solutions/1563-stone-game-v.js b/solutions/1563-stone-game-v.js new file mode 100644 index 00000000..e07864b4 --- /dev/null +++ b/solutions/1563-stone-game-v.js @@ -0,0 +1,65 @@ +/** + * 1563. Stone Game V + * https://leetcode.com/problems/stone-game-v/ + * Difficulty: Hard + * + * There are several stones arranged in a row, and each stone has an associated value which + * is an integer given in the array stoneValue. + * + * In each round of the game, Alice divides the row into two non-empty rows (i.e. left row and + * right row), then Bob calculates the value of each row which is the sum of the values of all + * the stones in this row. Bob throws away the row which has the maximum value, and Alice's + * score increases by the value of the remaining row. If the value of the two rows are equal, + * Bob lets Alice decide which row will be thrown away. The next round starts with the remaining + * row. + * + * The game ends when there is only one stone remaining. Alice's is initially zero. + * + * Return the maximum score that Alice can obtain. + */ + +/** + * @param {number[]} stoneValue + * @return {number} + */ +var stoneGameV = function(stoneValue) { + const n = stoneValue.length; + const prefixScore = Array.from({ length: n + 1 }, () => 0); + const dp = Array.from({ length: n }, () => new Array(n).fill(-1)); + + for (let index = 1; index <= n; index++) { + prefixScore[index] = prefixScore[index - 1] + stoneValue[index - 1]; + } + + return getMaxScore(0, n - 1); + + function getMaxScore(left, right) { + if (left >= right) return 0; + if (dp[left][right] !== -1) return dp[left][right]; + let result = 0; + + for (let index = left; index < right; index++) { + const heap1 = prefixScore[index + 1] - prefixScore[left]; + const heap2 = prefixScore[right + 1] - prefixScore[index + 1]; + + if (heap1 > heap2) { + const score = heap2 + getMaxScore(index + 1, right); + + result = Math.max(score, result); + } else if (heap1 < heap2) { + const score = heap1 + getMaxScore(left, index); + + result = Math.max(score, result); + } else { + const score1 = heap2 + getMaxScore(index + 1, right); + const score2 = heap1 + getMaxScore(left, index); + + result = Math.max(result, score1, score2); + } + } + + dp[left][right] = result; + + return result; + } +}; 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/1567-maximum-length-of-subarray-with-positive-product.js b/solutions/1567-maximum-length-of-subarray-with-positive-product.js new file mode 100644 index 00000000..b36a1866 --- /dev/null +++ b/solutions/1567-maximum-length-of-subarray-with-positive-product.js @@ -0,0 +1,49 @@ +/** + * 1567. Maximum Length of Subarray With Positive Product + * https://leetcode.com/problems/maximum-length-of-subarray-with-positive-product/ + * Difficulty: Medium + * + * Given an array of integers nums, find the maximum length of a subarray where the product of + * all its elements is positive. + * + * A subarray of an array is a consecutive sequence of zero or more values taken out of that array. + * + * Return the maximum length of a subarray with positive product. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var getMaxLen = function(nums) { + let result = 0; + let positiveCount = 0; + let negativeCount = 0; + let firstNegativeIndex = -1; + + for (let i = 0; i < nums.length; i++) { + if (nums[i] === 0) { + positiveCount = 0; + negativeCount = 0; + firstNegativeIndex = -1; + continue; + } + + if (nums[i] > 0) { + positiveCount++; + } else { + negativeCount++; + if (firstNegativeIndex === -1) { + firstNegativeIndex = i; + } + } + + if (negativeCount % 2 === 0) { + result = Math.max(result, positiveCount + negativeCount); + } else { + result = Math.max(result, i - firstNegativeIndex); + } + } + + return result; +}; diff --git a/solutions/1568-minimum-number-of-days-to-disconnect-island.js b/solutions/1568-minimum-number-of-days-to-disconnect-island.js new file mode 100644 index 00000000..b7183dd1 --- /dev/null +++ b/solutions/1568-minimum-number-of-days-to-disconnect-island.js @@ -0,0 +1,64 @@ +/** + * 1568. Minimum Number of Days to Disconnect Island + * https://leetcode.com/problems/minimum-number-of-days-to-disconnect-island/ + * Difficulty: Hard + * + * You are given an m x n binary grid grid where 1 represents land and 0 represents water. An + * island is a maximal 4-directionally (horizontal or vertical) connected group of 1's. + * + * The grid is said to be connected if we have exactly one island, otherwise is said disconnected. + * + * In one day, we are allowed to change any single land cell (1) into a water cell (0). + * + * Return the minimum number of days to disconnect the grid. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var minDays = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + + if (countIslands() !== 1) return 0; + + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + if (grid[r][c] === 1) { + grid[r][c] = 0; + if (countIslands() !== 1) return 1; + grid[r][c] = 1; + } + } + } + + return 2; + + function countIslands() { + const visited = Array(rows).fill().map(() => Array(cols).fill(false)); + let islands = 0; + + function dfs(row, col) { + if (row < 0 || row >= rows || col < 0 || col >= cols + || visited[row][col] || grid[row][col] === 0) { + return; + } + visited[row][col] = true; + dfs(row + 1, col); + dfs(row - 1, col); + dfs(row, col + 1); + dfs(row, col - 1); + } + + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + if (grid[r][c] === 1 && !visited[r][c]) { + islands++; + dfs(r, c); + } + } + } + return islands; + } +}; diff --git a/solutions/1569-number-of-ways-to-reorder-array-to-get-same-bst.js b/solutions/1569-number-of-ways-to-reorder-array-to-get-same-bst.js new file mode 100644 index 00000000..b28dc600 --- /dev/null +++ b/solutions/1569-number-of-ways-to-reorder-array-to-get-same-bst.js @@ -0,0 +1,65 @@ +/** + * 1569. Number of Ways to Reorder Array to Get Same BST + * https://leetcode.com/problems/number-of-ways-to-reorder-array-to-get-same-bst/ + * Difficulty: Hard + * + * Given an array nums that represents a permutation of integers from 1 to n. We are going to + * construct a binary search tree (BST) by inserting the elements of nums in order into an + * initially empty BST. Find the number of different ways to reorder nums so that the constructed + * BST is identical to that formed from the original array nums. + * + * For example, given nums = [2,1,3], we will have 2 as the root, 1 as a left child, and 3 as a + * right child. The array [2,3,1] also yields the same BST but [3,2,1] yields a different BST. + * + * Return the number of ways to reorder nums such that the BST formed is identical to the original + * BST formed from nums. + * + * Since the answer may be very large, return it modulo 109 + 7. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var numOfWays = function(nums) { + const MOD = BigInt(10 ** 9 + 7); + const factorialCache = Array(nums.length).fill(null); + factorialCache[0] = 1n; + + function calculatePermutations(arr) { + if (arr.length < 3) return 1n; + + const root = arr[0]; + const leftSubtree = []; + const rightSubtree = []; + + for (let i = 1; i < arr.length; i++) { + if (arr[i] < root) { + leftSubtree.push(arr[i]); + } else { + rightSubtree.push(arr[i]); + } + } + + const leftPermutations = calculatePermutations(leftSubtree); + const rightPermutations = calculatePermutations(rightSubtree); + const totalNodes = BigInt(arr.length - 1); + const leftNodes = BigInt(leftSubtree.length); + + return (helper(totalNodes, leftNodes) * leftPermutations * rightPermutations) % MOD; + } + + function helper(n, k) { + factorialCache[n] = computeFactorial(n); + factorialCache[n - k] = computeFactorial(n - k); + factorialCache[k] = computeFactorial(k); + return factorialCache[n] / (factorialCache[k] * factorialCache[n - k]); + } + + function computeFactorial(n) { + if (factorialCache[n]) return factorialCache[n]; + return n * computeFactorial(n - 1n); + } + + return Number((calculatePermutations(nums) - 1n) % MOD); +}; 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/1572-matrix-diagonal-sum.js b/solutions/1572-matrix-diagonal-sum.js new file mode 100644 index 00000000..0eb5ac63 --- /dev/null +++ b/solutions/1572-matrix-diagonal-sum.js @@ -0,0 +1,30 @@ +/** + * 1572. Matrix Diagonal Sum + * https://leetcode.com/problems/matrix-diagonal-sum/ + * Difficulty: Easy + * + * Given a square matrix mat, return the sum of the matrix diagonals. + * + * Only include the sum of all the elements on the primary diagonal and all the elements on the + * secondary diagonal that are not part of the primary diagonal. + */ + +/** + * @param {number[][]} mat + * @return {number} + */ +var diagonalSum = function(mat) { + const n = mat.length; + let sum = 0; + + for (let i = 0; i < n; i++) { + sum += mat[i][i]; + sum += mat[i][n - 1 - i]; + } + + if (n % 2 === 1) { + sum -= mat[Math.floor(n / 2)][Math.floor(n / 2)]; + } + + return sum; +}; diff --git a/solutions/1573-number-of-ways-to-split-a-string.js b/solutions/1573-number-of-ways-to-split-a-string.js new file mode 100644 index 00000000..0ce0e198 --- /dev/null +++ b/solutions/1573-number-of-ways-to-split-a-string.js @@ -0,0 +1,42 @@ +/** + * 1573. Number of Ways to Split a String + * https://leetcode.com/problems/number-of-ways-to-split-a-string/ + * Difficulty: Medium + * + * Given a binary string s, you can split s into 3 non-empty strings s1, s2, and s3 + * where s1 + s2 + s3 = s. + * + * Return the number of ways s can be split such that the number of ones is the same in s1, + * s2, and s3. Since the answer may be too large, return it modulo 109 + 7. + */ + +/** + * @param {string} s + * @return {number} + */ +var numWays = function(s) { + const MOD = 1e9 + 7; + let ones = 0; + + for (const char of s) { + if (char === '1') ones++; + } + + if (ones % 3 !== 0) return 0; + if (ones === 0) { + return Number((BigInt(s.length - 1) * BigInt(s.length - 2) / 2n) % BigInt(MOD)); + } + + const targetOnes = ones / 3; + let firstCount = 0; + let secondCount = 0; + let currentOnes = 0; + + for (let i = 0; i < s.length; i++) { + if (s[i] === '1') currentOnes++; + if (currentOnes === targetOnes) firstCount++; + else if (currentOnes === 2 * targetOnes) secondCount++; + } + + return Number((BigInt(firstCount) * BigInt(secondCount)) % BigInt(MOD)); +}; diff --git a/solutions/1574-shortest-subarray-to-be-removed-to-make-array-sorted.js b/solutions/1574-shortest-subarray-to-be-removed-to-make-array-sorted.js new file mode 100644 index 00000000..db657500 --- /dev/null +++ b/solutions/1574-shortest-subarray-to-be-removed-to-make-array-sorted.js @@ -0,0 +1,43 @@ +/** + * 1574. Shortest Subarray to be Removed to Make Array Sorted + * https://leetcode.com/problems/shortest-subarray-to-be-removed-to-make-array-sorted/ + * Difficulty: Medium + * + * Given an integer array arr, remove a subarray (can be empty) from arr such that the remaining + * elements in arr are non-decreasing. + * + * Return the length of the shortest subarray to remove. + * + * A subarray is a contiguous subsequence of the array. + */ + +/** + * @param {number[]} arr + * @return {number} + */ +var findLengthOfShortestSubarray = function(arr) { + const n = arr.length; + let left = 0; + + while (left < n - 1 && arr[left] <= arr[left + 1]) { + left++; + } + + if (left === n - 1) return 0; + + let right = n - 1; + while (right > 0 && arr[right - 1] <= arr[right]) { + right--; + } + + let minLength = Math.min(n - left - 1, right); + + for (let i = 0, j = right; i <= left && j < n; i++) { + while (j < n && arr[i] > arr[j]) { + j++; + } + minLength = Math.min(minLength, j - i - 1); + } + + return minLength; +}; diff --git a/solutions/1575-count-all-possible-routes.js b/solutions/1575-count-all-possible-routes.js new file mode 100644 index 00000000..b71afee0 --- /dev/null +++ b/solutions/1575-count-all-possible-routes.js @@ -0,0 +1,51 @@ +/** + * 1575. Count All Possible Routes + * https://leetcode.com/problems/count-all-possible-routes/ + * Difficulty: Hard + * + * You are given an array of distinct positive integers locations where locations[i] represents + * the position of city i. You are also given integers start, finish and fuel representing the + * starting city, ending city, and the initial amount of fuel you have, respectively. + * + * At each step, if you are at city i, you can pick any city j such that j != i and + * 0 <= j < locations.length and move to city j. Moving from city i to city j reduces the + * amount of fuel you have by |locations[i] - locations[j]|. Please notice that |x| denotes + * the absolute value of x. + * + * Notice that fuel cannot become negative at any point in time, and that you are allowed to visit + * any city more than once (including start and finish). + * + * Return the count of all possible routes from start to finish. Since the answer may be too large, + * return it modulo 109 + 7. + */ + +/** + * @param {number[]} locations + * @param {number} start + * @param {number} finish + * @param {number} fuel + * @return {number} + */ +var countRoutes = function(locations, start, finish, fuel) { + const MOD = 1e9 + 7; + const memo = new Array(locations.length).fill().map(() => new Array(fuel + 1).fill(-1)); + + function calculateRoutes(currentCity, remainingFuel) { + if (remainingFuel < 0) return 0; + if (memo[currentCity][remainingFuel] !== -1) return memo[currentCity][remainingFuel]; + + let routes = currentCity === finish ? 1 : 0; + + for (let nextCity = 0; nextCity < locations.length; nextCity++) { + if (nextCity !== currentCity) { + const fuelCost = Math.abs(locations[currentCity] - locations[nextCity]); + routes = (routes + calculateRoutes(nextCity, remainingFuel - fuelCost)) % MOD; + } + } + + memo[currentCity][remainingFuel] = routes; + return routes; + } + + return calculateRoutes(start, fuel); +}; diff --git a/solutions/1577-number-of-ways-where-square-of-number-is-equal-to-product-of-two-numbers.js b/solutions/1577-number-of-ways-where-square-of-number-is-equal-to-product-of-two-numbers.js new file mode 100644 index 00000000..78972574 --- /dev/null +++ b/solutions/1577-number-of-ways-where-square-of-number-is-equal-to-product-of-two-numbers.js @@ -0,0 +1,42 @@ +/** + * 1577. Number of Ways Where Square of Number Is Equal to Product of Two Numbers + * https://leetcode.com/problems/number-of-ways-where-square-of-number-is-equal-to-product-of-two-numbers/ + * Difficulty: Medium + * + * Given two arrays of integers nums1 and nums2, return the number of triplets formed (type 1 and + * type 2) under the following rules: + * - Type 1: Triplet (i, j, k) if nums1[i]2 == nums2[j] * nums2[k] where 0 <= i < nums1.length + * and 0 <= j < k < nums2.length. + * - Type 2: Triplet (i, j, k) if nums2[i]2 == nums1[j] * nums1[k] where 0 <= i < nums2.length + * and 0 <= j < k < nums1.length. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var numTriplets = function(nums1, nums2) { + return countTriplets(nums1, nums2) + countTriplets(nums2, nums1); + + function countTriplets(arr1, arr2) { + const productMap = new Map(); + let count = 0; + + for (let i = 0; i < arr2.length; i++) { + for (let j = i + 1; j < arr2.length; j++) { + const product = BigInt(arr2[i]) * BigInt(arr2[j]); + productMap.set(product, (productMap.get(product) || 0) + 1); + } + } + + for (const num of arr1) { + const square = BigInt(num) * BigInt(num); + if (productMap.has(square)) { + count += productMap.get(square); + } + } + + return count; + } +}; diff --git a/solutions/1578-minimum-time-to-make-rope-colorful.js b/solutions/1578-minimum-time-to-make-rope-colorful.js new file mode 100644 index 00000000..8c787a32 --- /dev/null +++ b/solutions/1578-minimum-time-to-make-rope-colorful.js @@ -0,0 +1,46 @@ +/** + * 1578. Minimum Time to Make Rope Colorful + * https://leetcode.com/problems/minimum-time-to-make-rope-colorful/ + * Difficulty: Medium + * + * Alice has n balloons arranged on a rope. You are given a 0-indexed string colors where colors[i] + * is the color of the ith balloon. + * + * Alice wants the rope to be colorful. She does not want two consecutive balloons to be of the same + * color, so she asks Bob for help. Bob can remove some balloons from the rope to make it colorful. + * You are given a 0-indexed integer array neededTime where neededTime[i] is the time (in seconds) + * that Bob needs to remove the ith balloon from the rope. + * + * Return the minimum time Bob needs to make the rope colorful. + */ + +/** + * @param {string} colors + * @param {number[]} neededTime + * @return {number} + */ +var minCost = function(colors, neededTime) { + let result = 0; + let i = 0; + + while (i < colors.length - 1) { + if (colors[i] === colors[i + 1]) { + let maxTime = neededTime[i]; + let sumTime = neededTime[i]; + let j = i + 1; + + while (j < colors.length && colors[j] === colors[i]) { + maxTime = Math.max(maxTime, neededTime[j]); + sumTime += neededTime[j]; + j++; + } + + result += sumTime - maxTime; + i = j; + } else { + i++; + } + } + + return result; +}; diff --git a/solutions/1579-remove-max-number-of-edges-to-keep-graph-fully-traversable.js b/solutions/1579-remove-max-number-of-edges-to-keep-graph-fully-traversable.js new file mode 100644 index 00000000..3a4cf256 --- /dev/null +++ b/solutions/1579-remove-max-number-of-edges-to-keep-graph-fully-traversable.js @@ -0,0 +1,84 @@ +/** + * 1579. Remove Max Number of Edges to Keep Graph Fully Traversable + * https://leetcode.com/problems/remove-max-number-of-edges-to-keep-graph-fully-traversable/ + * Difficulty: Hard + * + * Alice and Bob have an undirected graph of n nodes and three types of edges: + * - Type 1: Can be traversed by Alice only. + * - Type 2: Can be traversed by Bob only. + * - Type 3: Can be traversed by both Alice and Bob. + * + * Given an array edges where edges[i] = [typei, ui, vi] represents a bidirectional edge of type + * typei between nodes ui and vi, find the maximum number of edges you can remove so that after + * removing the edges, the graph can still be fully traversed by both Alice and Bob. The graph + * is fully traversed by Alice and Bob if starting from any node, they can reach all other nodes. + * + * Return the maximum number of edges you can remove, or return -1 if Alice and Bob cannot fully + * traverse the graph. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @return {number} + */ +var maxNumEdgesToRemove = function(n, edges) { + const alice = new UnionFind(n + 1); + const bob = new UnionFind(n + 1); + let removableEdges = 0; + + for (const [type, u, v] of edges) { + if (type === 3) { + const usedAlice = alice.union(u, v); + const usedBob = bob.union(u, v); + if (!usedAlice && !usedBob) { + removableEdges++; + } + } + } + + for (const [type, u, v] of edges) { + if (type === 1) { + if (!alice.union(u, v)) { + removableEdges++; + } + } else if (type === 2) { + if (!bob.union(u, v)) { + removableEdges++; + } + } + } + + return alice.components === 2 && bob.components === 2 ? removableEdges : -1; +}; + +class UnionFind { + constructor(size) { + this.parent = Array(size).fill().map((_, i) => i); + this.rank = Array(size).fill(0); + this.components = size; + } + + 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) return false; + 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]++; + } + this.components--; + return true; + } +} 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/1582-special-positions-in-a-binary-matrix.js b/solutions/1582-special-positions-in-a-binary-matrix.js new file mode 100644 index 00000000..ea2e1db8 --- /dev/null +++ b/solutions/1582-special-positions-in-a-binary-matrix.js @@ -0,0 +1,41 @@ +/** + * 1582. Special Positions in a Binary Matrix + * https://leetcode.com/problems/special-positions-in-a-binary-matrix/ + * Difficulty: Easy + * + * Given an m x n binary matrix mat, return the number of special positions in mat. + * + * A position (i, j) is called special if mat[i][j] == 1 and all other elements in row i and + * column j are 0 (rows and columns are 0-indexed). + */ + +/** + * @param {number[][]} mat + * @return {number} + */ +var numSpecial = function(mat) { + const rows = mat.length; + const cols = mat[0].length; + const rowSums = new Array(rows).fill(0); + const colSums = new Array(cols).fill(0); + let result = 0; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (mat[i][j] === 1) { + rowSums[i]++; + colSums[j]++; + } + } + } + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (mat[i][j] === 1 && rowSums[i] === 1 && colSums[j] === 1) { + result++; + } + } + } + + return result; +}; diff --git a/solutions/1583-count-unhappy-friends.js b/solutions/1583-count-unhappy-friends.js new file mode 100644 index 00000000..428d7112 --- /dev/null +++ b/solutions/1583-count-unhappy-friends.js @@ -0,0 +1,58 @@ +/** + * 1583. Count Unhappy Friends + * https://leetcode.com/problems/count-unhappy-friends/ + * Difficulty: Medium + * + * You are given a list of preferences for n friends, where n is always even. + * + * For each person i, preferences[i] contains a list of friends sorted in the order of preference. + * In other words, a friend earlier in the list is more preferred than a friend later in the list. + * Friends in each list are denoted by integers from 0 to n-1. + * + * All the friends are divided into pairs. The pairings are given in a list pairs, where + * pairs[i] = [xi, yi] denotes xi is paired with yi and yi is paired with xi. + * + * However, this pairing may cause some of the friends to be unhappy. A friend x is unhappy if x + * is paired with y and there exists a friend u who is paired with v but: + * - x prefers u over y, and + * - u prefers x over v. + * + * Return the number of unhappy friends. + */ + +/** + * @param {number} n + * @param {number[][]} preferences + * @param {number[][]} pairs + * @return {number} + */ +var unhappyFriends = function(n, preferences, pairs) { + const rank = Array.from({ length: n }, () => new Array(n).fill(0)); + const pairMap = new Array(n).fill(0); + let result = 0; + + for (let i = 0; i < n; i++) { + for (let j = 0; j < n - 1; j++) { + rank[i][preferences[i][j]] = j; + } + } + + for (const [x, y] of pairs) { + pairMap[x] = y; + pairMap[y] = x; + } + + for (let x = 0; x < n; x++) { + const y = pairMap[x]; + for (const u of preferences[x]) { + if (u === y) break; + const v = pairMap[u]; + if (rank[u][x] < rank[u][v]) { + result++; + break; + } + } + } + + return result; +}; diff --git a/solutions/1584-min-cost-to-connect-all-points.js b/solutions/1584-min-cost-to-connect-all-points.js new file mode 100644 index 00000000..64cd86dc --- /dev/null +++ b/solutions/1584-min-cost-to-connect-all-points.js @@ -0,0 +1,54 @@ +/** + * 1584. Min Cost to Connect All Points + * https://leetcode.com/problems/min-cost-to-connect-all-points/ + * Difficulty: Medium + * + * You are given an array points representing integer coordinates of some points on a 2D-plane, + * where points[i] = [xi, yi]. + * + * The cost of connecting two points [xi, yi] and [xj, yj] is the manhattan distance between + * them: |xi - xj| + |yi - yj|, where |val| denotes the absolute value of val. + * + * Return the minimum cost to make all points connected. All points are connected if there is + * exactly one simple path between any two points. + */ + +/** + * @param {number[][]} points + * @return {number} + */ +var minCostConnectPoints = function(points) { + const n = points.length; + const minCost = Array(n).fill(Infinity); + const visited = new Set(); + let result = 0; + + minCost[0] = 0; + + for (let i = 0; i < n; i++) { + let minIdx = -1; + let minVal = Infinity; + + for (let j = 0; j < n; j++) { + if (!visited.has(j) && minCost[j] < minVal) { + minVal = minCost[j]; + minIdx = j; + } + } + + if (minIdx === -1) break; + + visited.add(minIdx); + result += minVal; + + for (let j = 0; j < n; j++) { + if (!visited.has(j)) { + const cost = Math.abs(points[minIdx][0] - points[j][0]) + + Math.abs(points[minIdx][1] - points[j][1]); + minCost[j] = Math.min(minCost[j], cost); + } + } + } + + return result; +}; diff --git a/solutions/1585-check-if-string-is-transformable-with-substring-sort-operations.js b/solutions/1585-check-if-string-is-transformable-with-substring-sort-operations.js new file mode 100644 index 00000000..181bccb0 --- /dev/null +++ b/solutions/1585-check-if-string-is-transformable-with-substring-sort-operations.js @@ -0,0 +1,49 @@ +/** + * 1585. Check If String Is Transformable With Substring Sort Operations + * https://leetcode.com/problems/check-if-string-is-transformable-with-substring-sort-operations/ + * Difficulty: Hard + * + * Given two strings s and t, transform string s into string t using the following operation any + * number of times: + * - Choose a non-empty substring in s and sort it in place so the characters are in ascending + * order. + * - For example, applying the operation on the underlined substring in "14234" results + * in "12344". + * + * Return true if it is possible to transform s into t. Otherwise, return false. + * + * A substring is a contiguous sequence of characters within a string. + */ + +/** + * @param {string} s + * @param {string} t + * @return {boolean} + */ +var isTransformable = function(source, target) { + const digitPositions = Array.from({ length: 10 }, () => []); + for (let index = 0; index < source.length; index++) { + digitPositions[source[index]].push(index); + } + + const currentIndices = new Array(10).fill(0); + + for (const digit of target) { + const digitValue = parseInt(digit, 10); + if (currentIndices[digitValue] >= digitPositions[digitValue].length) { + return false; + } + + const position = digitPositions[digitValue][currentIndices[digitValue]]; + for (let smallerDigit = 0; smallerDigit < digitValue; smallerDigit++) { + if (currentIndices[smallerDigit] < digitPositions[smallerDigit].length + && digitPositions[smallerDigit][currentIndices[smallerDigit]] < position) { + return false; + } + } + + currentIndices[digitValue]++; + } + + return true; +}; 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/1588-sum-of-all-odd-length-subarrays.js b/solutions/1588-sum-of-all-odd-length-subarrays.js new file mode 100644 index 00000000..2121c748 --- /dev/null +++ b/solutions/1588-sum-of-all-odd-length-subarrays.js @@ -0,0 +1,24 @@ +/** + * 1588. Sum of All Odd Length Subarrays + * https://leetcode.com/problems/sum-of-all-odd-length-subarrays/ + * Difficulty: Easy + * + * Given an array of positive integers arr, return the sum of all possible odd-length + * subarrays of arr. + * + * A subarray is a contiguous subsequence of the array. + */ + +/** + * @param {number[]} arr + * @return {number} + */ +var sumOddLengthSubarrays = function(arr) { + let result = 0; + + for (let index = 0; index < arr.length; index++) { + result += arr[index] * Math.ceil(((index + 1) * (arr.length - index)) / 2); + } + + return result; +}; diff --git a/solutions/1589-maximum-sum-obtained-of-any-permutation.js b/solutions/1589-maximum-sum-obtained-of-any-permutation.js new file mode 100644 index 00000000..69acb0f6 --- /dev/null +++ b/solutions/1589-maximum-sum-obtained-of-any-permutation.js @@ -0,0 +1,46 @@ +/** + * 1589. Maximum Sum Obtained of Any Permutation + * https://leetcode.com/problems/maximum-sum-obtained-of-any-permutation/ + * Difficulty: Medium + * + * We have an array of integers, nums, and an array of requests where requests[i] = [starti, endi]. + * The ith request asks for the sum of nums[starti] + nums[starti + 1] + ... + nums[endi - 1] + * + nums[endi]. Both starti and endi are 0-indexed. + * + * Return the maximum total sum of all requests among all permutations of nums. + * + * Since the answer may be too large, return it modulo 109 + 7. + */ + +/** + * @param {number[]} nums + * @param {number[][]} requests + * @return {number} + */ +var maxSumRangeQuery = function(nums, requests) { + const MOD = 1e9 + 7; + const n = nums.length; + const freq = new Array(n + 1).fill(0); + + for (const [start, end] of requests) { + freq[start]++; + freq[end + 1]--; + } + + const count = new Array(n).fill(0); + let current = 0; + for (let i = 0; i < n; i++) { + current += freq[i]; + count[i] = current; + } + + count.sort((a, b) => b - a); + nums.sort((a, b) => b - a); + + let total = 0; + for (let i = 0; i < n; i++) { + total = (total + nums[i] * count[i]) % MOD; + } + + return total; +}; diff --git a/solutions/1590-make-sum-divisible-by-p.js b/solutions/1590-make-sum-divisible-by-p.js new file mode 100644 index 00000000..f4ab73cf --- /dev/null +++ b/solutions/1590-make-sum-divisible-by-p.js @@ -0,0 +1,41 @@ +/** + * 1590. Make Sum Divisible by P + * https://leetcode.com/problems/make-sum-divisible-by-p/ + * Difficulty: Medium + * + * Given an array of positive integers nums, remove the smallest subarray (possibly empty) such that + * the sum of the remaining elements is divisible by p. It is not allowed to remove the whole array. + * + * Return the length of the smallest subarray that you need to remove, or -1 if it's impossible. + * + * A subarray is defined as a contiguous block of elements in the array. + */ + +/** + * @param {number[]} nums + * @param {number} p + * @return {number} + */ +var minSubarray = function(nums, p) { + const totalSum = nums.reduce((sum, num) => sum + num, 0); + const remainder = totalSum % p; + + if (remainder === 0) return 0; + + const prefixSums = new Map([[0, -1]]); + let currentSum = 0; + let minLength = nums.length; + + for (let i = 0; i < nums.length; i++) { + currentSum = (currentSum + nums[i]) % p; + const target = (currentSum - remainder + p) % p; + + if (prefixSums.has(target)) { + minLength = Math.min(minLength, i - prefixSums.get(target)); + } + + prefixSums.set(currentSum, i); + } + + return minLength < nums.length ? minLength : -1; +}; diff --git a/solutions/1591-strange-printer-ii.js b/solutions/1591-strange-printer-ii.js new file mode 100644 index 00000000..40aa1509 --- /dev/null +++ b/solutions/1591-strange-printer-ii.js @@ -0,0 +1,83 @@ +/** + * 1591. Strange Printer II + * https://leetcode.com/problems/strange-printer-ii/ + * Difficulty: Hard + * + * There is a strange printer with the following two special requirements: + * - On each turn, the printer will print a solid rectangular pattern of a single color on the + * grid. This will cover up the existing colors in the rectangle. + * - Once the printer has used a color for the above operation, the same color cannot be used again. + * + * You are given a m x n matrix targetGrid, where targetGrid[row][col] is the color in the position + * (row, col) of the grid. + * + * Return true if it is possible to print the matrix targetGrid, otherwise, return false. + */ + +/** + * @param {number[][]} targetGrid + * @return {boolean} + */ +var isPrintable = function(targetGrid) { + const rows = targetGrid.length; + const cols = targetGrid[0].length; + const colorBounds = new Map(); + + for (let color = 1; color <= 60; color++) { + let minRow = rows; + let maxRow = -1; + let minCol = cols; + let maxCol = -1; + + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + if (targetGrid[r][c] === color) { + minRow = Math.min(minRow, r); + maxRow = Math.max(maxRow, r); + minCol = Math.min(minCol, c); + maxCol = Math.max(maxCol, c); + } + } + } + if (maxRow >= 0) { + colorBounds.set(color, [minRow, maxRow, minCol, maxCol]); + } + } + + const dependencies = new Map(); + for (const [color, [minRow, maxRow, minCol, maxCol]] of colorBounds) { + const deps = new Set(); + for (let r = minRow; r <= maxRow; r++) { + for (let c = minCol; c <= maxCol; c++) { + if (targetGrid[r][c] !== color) { + deps.add(targetGrid[r][c]); + } + } + } + dependencies.set(color, deps); + } + + const visited = new Set(); + const recStack = new Set(); + + function hasCycle(color) { + if (recStack.has(color)) return true; + if (visited.has(color)) return false; + + visited.add(color); + recStack.add(color); + + for (const dep of dependencies.get(color) || []) { + if (hasCycle(dep)) return true; + } + + recStack.delete(color); + return false; + } + + for (const color of colorBounds.keys()) { + if (hasCycle(color)) return false; + } + + return true; +}; diff --git a/solutions/1592-rearrange-spaces-between-words.js b/solutions/1592-rearrange-spaces-between-words.js new file mode 100644 index 00000000..b6b8b786 --- /dev/null +++ b/solutions/1592-rearrange-spaces-between-words.js @@ -0,0 +1,32 @@ +/** + * 1592. Rearrange Spaces Between Words + * https://leetcode.com/problems/rearrange-spaces-between-words/ + * Difficulty: Easy + * + * You are given a string text of words that are placed among some number of spaces. Each word + * consists of one or more lowercase English letters and are separated by at least one space. + * It's guaranteed that text contains at least one word. + * + * Rearrange the spaces so that there is an equal number of spaces between every pair of adjacent + * words and that number is maximized. If you cannot redistribute all the spaces equally, place + * the extra spaces at the end, meaning the returned string should be the same length as text. + * + * Return the string after rearranging the spaces. + */ + +/** + * @param {string} text + * @return {string} + */ +var reorderSpaces = function(text) { + const words = text.trim().split(/\s+/); + const spaceCount = text.length - words.join('').length; + const wordCount = words.length; + + if (wordCount === 1) return words[0] + ' '.repeat(spaceCount); + + const spacesBetween = Math.floor(spaceCount / (wordCount - 1)); + const extraSpaces = spaceCount % (wordCount - 1); + + return words.join(' '.repeat(spacesBetween)) + ' '.repeat(extraSpaces); +}; diff --git a/solutions/1593-split-a-string-into-the-max-number-of-unique-substrings.js b/solutions/1593-split-a-string-into-the-max-number-of-unique-substrings.js new file mode 100644 index 00000000..d5f32602 --- /dev/null +++ b/solutions/1593-split-a-string-into-the-max-number-of-unique-substrings.js @@ -0,0 +1,38 @@ +/** + * 1593. Split a String Into the Max Number of Unique Substrings + * https://leetcode.com/problems/split-a-string-into-the-max-number-of-unique-substrings/ + * Difficulty: Medium + * + * Given a string s, return the maximum number of unique substrings that the given string can + * be split into. + * + * You can split string s into any list of non-empty substrings, where the concatenation of + * the substrings forms the original string. However, you must split the substrings such that + * all of them are unique. + * + * A substring is a contiguous sequence of characters within a string. + */ + +/** + * @param {string} s + * @return {number} + */ +var maxUniqueSplit = function(s) { + return backtrack(0, new Set()); + + function backtrack(start, seen) { + if (start === s.length) return seen.size; + + let maxSplits = 0; + for (let end = start + 1; end <= s.length; end++) { + const substring = s.slice(start, end); + if (!seen.has(substring)) { + seen.add(substring); + maxSplits = Math.max(maxSplits, backtrack(end, seen)); + seen.delete(substring); + } + } + + return maxSplits; + } +}; diff --git a/solutions/1594-maximum-non-negative-product-in-a-matrix.js b/solutions/1594-maximum-non-negative-product-in-a-matrix.js new file mode 100644 index 00000000..ec7d75f3 --- /dev/null +++ b/solutions/1594-maximum-non-negative-product-in-a-matrix.js @@ -0,0 +1,71 @@ +/** + * 1594. Maximum Non Negative Product in a Matrix + * https://leetcode.com/problems/maximum-non-negative-product-in-a-matrix/ + * Difficulty: Medium + * + * You are given a m x n matrix grid. Initially, you are located at the top-left corner (0, 0), + * and in each step, you can only move right or down in the matrix. + * + * Among all possible paths starting from the top-left corner (0, 0) and ending in the bottom-right + * corner (m - 1, n - 1), find the path with the maximum non-negative product. The product of a + * path is the product of all integers in the grid cells visited along the path. + * + * Return the maximum non-negative product modulo 109 + 7. If the maximum product is negative, + * return -1. + * + * Notice that the modulo is performed after getting the maximum product. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var maxProductPath = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const dp = Array.from({ length: rows }, () => + Array.from({ length: cols }, () => [1, 1]) + ); + + dp[0][0] = [grid[0][0], grid[0][0]]; + + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + if (row === 0 && col === 0) continue; + + let minProduct = Infinity; + let maxProduct = -Infinity; + + if (row > 0) { + minProduct = Math.min( + minProduct, + dp[row - 1][col][0] * grid[row][col], + dp[row - 1][col][1] * grid[row][col] + ); + maxProduct = Math.max( + maxProduct, + dp[row - 1][col][0] * grid[row][col], + dp[row - 1][col][1] * grid[row][col] + ); + } + + if (col > 0) { + minProduct = Math.min( + minProduct, + dp[row][col - 1][0] * grid[row][col], + dp[row][col - 1][1] * grid[row][col] + ); + maxProduct = Math.max( + maxProduct, + dp[row][col - 1][0] * grid[row][col], + dp[row][col - 1][1] * grid[row][col] + ); + } + + dp[row][col] = [minProduct, maxProduct]; + } + } + + const maxResult = dp[rows - 1][cols - 1][1]; + return maxResult < 0 ? -1 : maxResult % (10 ** 9 + 7); +}; diff --git a/solutions/1595-minimum-cost-to-connect-two-groups-of-points.js b/solutions/1595-minimum-cost-to-connect-two-groups-of-points.js new file mode 100644 index 00000000..cd610a08 --- /dev/null +++ b/solutions/1595-minimum-cost-to-connect-two-groups-of-points.js @@ -0,0 +1,63 @@ +/** + * 1595. Minimum Cost to Connect Two Groups of Points + * https://leetcode.com/problems/minimum-cost-to-connect-two-groups-of-points/ + * Difficulty: Hard + * + * You are given two groups of points where the first group has size1 points, the second group + * has size2 points, and size1 >= size2. + * + * The cost of the connection between any two points are given in an size1 x size2 matrix where + * cost[i][j] is the cost of connecting point i of the first group and point j of the second group. + * The groups are connected if each point in both groups is connected to one or more points in the + * opposite group. In other words, each point in the first group must be connected to at least one + * point in the second group, and each point in the second group must be connected to at least one + * point in the first group. + * + * Return the minimum cost it takes to connect the two groups. + */ + +/** +* @param {number[][]} cost +* @return {number} +*/ +var connectTwoGroups = function(cost) { + const size1 = cost.length; + const size2 = cost[0].length; + + const minCostGroup2 = new Array(size2).fill(Infinity); + for (let j = 0; j < size2; j++) { + for (let i = 0; i < size1; i++) { + minCostGroup2[j] = Math.min(minCostGroup2[j], cost[i][j]); + } + } + + const memo = new Array(size1).fill(0).map(() => new Array(1 << size2).fill(-1)); + + return dfs(0, 0); + + function dfs(i, mask) { + if (i === size1) { + let remainingCost = 0; + for (let j = 0; j < size2; j++) { + if ((mask & (1 << j)) === 0) { + remainingCost += minCostGroup2[j]; + } + } + return remainingCost; + } + + if (memo[i][mask] !== -1) return memo[i][mask]; + + let minCost = Infinity; + + for (let j = 0; j < size2; j++) { + minCost = Math.min( + minCost, + cost[i][j] + dfs(i + 1, mask | (1 << j)) + ); + } + + memo[i][mask] = minCost; + return minCost; + } +}; 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/1599-maximum-profit-of-operating-a-centennial-wheel.js b/solutions/1599-maximum-profit-of-operating-a-centennial-wheel.js new file mode 100644 index 00000000..46911193 --- /dev/null +++ b/solutions/1599-maximum-profit-of-operating-a-centennial-wheel.js @@ -0,0 +1,61 @@ +/** + * 1599. Maximum Profit of Operating a Centennial Wheel + * https://leetcode.com/problems/maximum-profit-of-operating-a-centennial-wheel/ + * Difficulty: Medium + * + * You are the operator of a Centennial Wheel that has four gondolas, and each gondola has room for + * up to four people. You have the ability to rotate the gondolas counterclockwise, which costs you + * runningCost dollars. + * + * You are given an array customers of length n where customers[i] is the number of new customers + * arriving just before the ith rotation (0-indexed). This means you must rotate the wheel i times + * before the customers[i] customers arrive. You cannot make customers wait if there is room in the + * gondola. Each customer pays boardingCost dollars when they board on the gondola closest to the + * ground and will exit once that gondola reaches the ground again. + * + * You can stop the wheel at any time, including before serving all customers. If you decide to stop + * serving customers, all subsequent rotations are free in order to get all the customers down + * safely. Note that if there are currently more than four customers waiting at the wheel, only + * four will board the gondola, and the rest will wait for the next rotation. + * + * Return the minimum number of rotations you need to perform to maximize your profit. If there is + * no scenario where the profit is positive, return -1. + */ + +/** + * @param {number[]} customers + * @param {number} boardingCost + * @param {number} runningCost + * @return {number} + */ +var minOperationsMaxProfit = function(customers, boardingCost, runningCost) { + let waitingCustomers = 0; + let totalBoarded = 0; + let maxProfit = -Infinity; + let rotationAtMaxProfit = -1; + let currentProfit = 0; + let rotations = 0; + + const gondolaCapacity = 4; + + for (let i = 0; i < customers.length || waitingCustomers > 0; i++) { + rotations++; + + if (i < customers.length) { + waitingCustomers += customers[i]; + } + + const boarding = Math.min(waitingCustomers, gondolaCapacity); + waitingCustomers -= boarding; + totalBoarded += boarding; + + currentProfit = totalBoarded * boardingCost - rotations * runningCost; + + if (currentProfit > maxProfit) { + maxProfit = currentProfit; + rotationAtMaxProfit = rotations; + } + } + + return maxProfit > 0 ? rotationAtMaxProfit : -1; +}; diff --git a/solutions/1600-throne-inheritance.js b/solutions/1600-throne-inheritance.js new file mode 100644 index 00000000..6d1f6f4e --- /dev/null +++ b/solutions/1600-throne-inheritance.js @@ -0,0 +1,86 @@ +/** + * 1600. Throne Inheritance + * https://leetcode.com/problems/throne-inheritance/ + * Difficulty: Medium + * + * A kingdom consists of a king, his children, his grandchildren, and so on. Every once in a while, + * someone in the family dies or a child is born. + * + * The kingdom has a well-defined order of inheritance that consists of the king as the first + * member. Let's define the recursive function Successor(x, curOrder), which given a person x and + * the inheritance order so far, returns who should be the next person after x in the order of + * inheritance. + * + * For example, assume we have a kingdom that consists of the king, his children Alice and Bob + * (Alice is older than Bob), and finally Alice's son Jack. + * + * 1. In the beginning, curOrder will be ["king"]. + * 2. Calling Successor(king, curOrder) will return Alice, so we append to curOrder to + * get ["king", "Alice"]. + * 3. Calling Successor(Alice, curOrder) will return Jack, so we append to curOrder to + * get ["king", "Alice", "Jack"]. + * 4. Calling Successor(Jack, curOrder) will return Bob, so we append to curOrder to + * get ["king", "Alice", "Jack", "Bob"]. + * 5. Calling Successor(Bob, curOrder) will return null. Thus the order of inheritance + * will be ["king", "Alice", "Jack", "Bob"]. + * + * Using the above function, we can always obtain a unique order of inheritance. + * + * Implement the ThroneInheritance class: + * - ThroneInheritance(string kingName) Initializes an object of the ThroneInheritance class. + * The name of the king is given as part of the constructor. + * - void birth(string parentName, string childName) Indicates that parentName gave birth + * to childName. + * - void death(string name) Indicates the death of name. The death of the person doesn't + * affect the Successor function nor the current inheritance order. You can treat it as + * just marking the person as dead. + * - string[] getInheritanceOrder() Returns a list representing the current order of inheritance + * excluding dead people. + */ + +/** + * @param {string} kingName + */ +var ThroneInheritance = function(kingName) { + this.king = kingName; + this.familyTree = new Map(); + this.deceased = new Set(); +}; + +/** + * @param {string} parentName + * @param {string} childName + * @return {void} + */ +ThroneInheritance.prototype.birth = function(parentName, childName) { + if (!this.familyTree.has(parentName)) { + this.familyTree.set(parentName, []); + } + this.familyTree.get(parentName).push(childName); +}; + +/** + * @param {string} name + * @return {void} + */ +ThroneInheritance.prototype.death = function(name) { + this.deceased.add(name); +}; + +/** + * @return {string[]} + */ +ThroneInheritance.prototype.getInheritanceOrder = function() { + const result = []; + const traverse = (person) => { + if (!this.deceased.has(person)) { + result.push(person); + } + const children = this.familyTree.get(person) || []; + for (const child of children) { + traverse(child); + } + }; + traverse(this.king); + return result; +}; diff --git a/solutions/1601-maximum-number-of-achievable-transfer-requests.js b/solutions/1601-maximum-number-of-achievable-transfer-requests.js new file mode 100644 index 00000000..d1da07b1 --- /dev/null +++ b/solutions/1601-maximum-number-of-achievable-transfer-requests.js @@ -0,0 +1,49 @@ +/** + * 1601. Maximum Number of Achievable Transfer Requests + * https://leetcode.com/problems/maximum-number-of-achievable-transfer-requests/ + * Difficulty: Hard + * + * We have n buildings numbered from 0 to n - 1. Each building has a number of employees. + * It's transfer season, and some employees want to change the building they reside in. + * + * You are given an array requests where requests[i] = [fromi, toi] represents an employee's + * request to transfer from building fromi to building toi. + * + * All buildings are full, so a list of requests is achievable only if for each building, the + * net change in employee transfers is zero. This means the number of employees leaving is + * equal to the number of employees moving in. For example if n = 3 and two employees are + * leaving building 0, one is leaving building 1, and one is leaving building 2, there should + * be two employees moving to building 0, one employee moving to building 1, and one employee + * moving to building 2. + * + * Return the maximum number of achievable requests. + */ + +/** + * @param {number} n + * @param {number[][]} requests + * @return {number} + */ +var maximumRequests = function(n, requests) { + let maxAchievable = 0; + tryCombination(0, 0, new Array(n).fill(0)); + return maxAchievable; + + function tryCombination(index, count, balance) { + if (index === requests.length) { + if (balance.every(val => val === 0)) { + maxAchievable = Math.max(maxAchievable, count); + } + return; + } + + const [from, to] = requests[index]; + balance[from]--; + balance[to]++; + tryCombination(index + 1, count + 1, balance); + balance[from]++; + balance[to]--; + + tryCombination(index + 1, count, balance); + } +}; 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/1603-design-parking-system.js b/solutions/1603-design-parking-system.js new file mode 100644 index 00000000..040c764d --- /dev/null +++ b/solutions/1603-design-parking-system.js @@ -0,0 +1,38 @@ +/** + * 1603. Design Parking System + * https://leetcode.com/problems/design-parking-system/ + * Difficulty: Easy + * + * Design a parking system for a parking lot. The parking lot has three kinds of parking + * spaces: big, medium, and small, with a fixed number of slots for each size. + * + * Implement the ParkingSystem class: + * - ParkingSystem(int big, int medium, int small) Initializes object of the ParkingSystem class. + * The number of slots for each parking space are given as part of the constructor. + * - bool addCar(int carType) Checks whether there is a parking space of carType for the car that + * wants to get into the parking lot. carType can be of three kinds: big, medium, or small, which + * are represented by 1, 2, and 3 respectively. A car can only park in a parking space of its + * carType. If there is no space available, return false, else park the car in that size space + * and return true. + */ + +/** + * @param {number} big + * @param {number} medium + * @param {number} small + */ +var ParkingSystem = function(big, medium, small) { + this.spaces = { 1: big, 2: medium, 3: small }; +}; + +/** + * @param {number} carType + * @return {boolean} + */ +ParkingSystem.prototype.addCar = function(carType) { + if (this.spaces[carType] > 0) { + this.spaces[carType]--; + return true; + } + return false; +}; diff --git a/solutions/1604-alert-using-same-key-card-three-or-more-times-in-a-one-hour-period.js b/solutions/1604-alert-using-same-key-card-three-or-more-times-in-a-one-hour-period.js new file mode 100644 index 00000000..439bb8a2 --- /dev/null +++ b/solutions/1604-alert-using-same-key-card-three-or-more-times-in-a-one-hour-period.js @@ -0,0 +1,53 @@ +/** + * 1604. Alert Using Same Key-Card Three or More Times in a One Hour Period + * https://leetcode.com/problems/alert-using-same-key-card-three-or-more-times-in-a-one-hour-period/ + * Difficulty: Medium + * + * LeetCode company workers use key-cards to unlock office doors. Each time a worker uses their + * key-card, the security system saves the worker's name and the time when it was used. The system + * emits an alert if any worker uses the key-card three or more times in a one-hour period. + * + * You are given a list of strings keyName and keyTime where [keyName[i], keyTime[i]] corresponds + * to a person's name and the time when their key-card was used in a single day. + * + * Access times are given in the 24-hour time format "HH:MM", such as "23:51" and "09:49". + * + * Return a list of unique worker names who received an alert for frequent keycard use. Sort the + * names in ascending order alphabetically. + * + * Notice that "10:00" - "11:00" is considered to be within a one-hour period, while + * "22:51" - "23:52" is not considered to be within a one-hour period. + */ + +/** + * @param {string[]} keyName + * @param {string[]} keyTime + * @return {string[]} + */ +var alertNames = function(keyName, keyTime) { + const usageMap = new Map(); + for (let i = 0; i < keyName.length; i++) { + if (!usageMap.has(keyName[i])) { + usageMap.set(keyName[i], []); + } + usageMap.get(keyName[i]).push(timeToMinutes(keyTime[i])); + } + + const result = []; + for (const [name, times] of usageMap) { + times.sort((a, b) => a - b); + for (let i = 2; i < times.length; i++) { + if (times[i] - times[i - 2] <= 60) { + result.push(name); + break; + } + } + } + + return result.sort(); + + function timeToMinutes(time) { + const [hours, minutes] = time.split(':').map(Number); + return hours * 60 + minutes; + } +}; diff --git a/solutions/1605-find-valid-matrix-given-row-and-column-sums.js b/solutions/1605-find-valid-matrix-given-row-and-column-sums.js new file mode 100644 index 00000000..4e24c533 --- /dev/null +++ b/solutions/1605-find-valid-matrix-given-row-and-column-sums.js @@ -0,0 +1,38 @@ +/** + * 1605. Find Valid Matrix Given Row and Column Sums + * https://leetcode.com/problems/find-valid-matrix-given-row-and-column-sums/ + * Difficulty: Medium + * + * You are given two arrays rowSum and colSum of non-negative integers where rowSum[i] is the sum + * of the elements in the ith row and colSum[j] is the sum of the elements of the jth column of a + * 2D matrix. In other words, you do not know the elements of the matrix, but you do know the sums + * of each row and column. + * + * Find any matrix of non-negative integers of size rowSum.length x colSum.length that satisfies + * the rowSum and colSum requirements. + * + * Return a 2D array representing any matrix that fulfills the requirements. It's guaranteed that + * at least one matrix that fulfills the requirements exists. + */ + +/** + * @param {number[]} rowSum + * @param {number[]} colSum + * @return {number[][]} + */ +var restoreMatrix = function(rowSum, colSum) { + const rows = rowSum.length; + const cols = colSum.length; + const matrix = Array.from({ length: rows }, () => Array(cols).fill(0)); + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + const value = Math.min(rowSum[i], colSum[j]); + matrix[i][j] = value; + rowSum[i] -= value; + colSum[j] -= value; + } + } + + return matrix; +}; diff --git a/solutions/1606-find-servers-that-handled-most-number-of-requests.js b/solutions/1606-find-servers-that-handled-most-number-of-requests.js new file mode 100644 index 00000000..07ecad21 --- /dev/null +++ b/solutions/1606-find-servers-that-handled-most-number-of-requests.js @@ -0,0 +1,101 @@ +/** + * 1606. Find Servers That Handled Most Number of Requests + * https://leetcode.com/problems/find-servers-that-handled-most-number-of-requests/ + * Difficulty: Hard + * + * You have k servers numbered from 0 to k-1 that are being used to handle multiple requests + * simultaneously. Each server has infinite computational capacity but cannot handle more than + * one request at a time. The requests are assigned to servers according to a specific algorithm: + * - The ith (0-indexed) request arrives. + * - If all servers are busy, the request is dropped (not handled at all). + * - If the (i % k)th server is available, assign the request to that server. + * - Otherwise, assign the request to the next available server (wrapping around the list of servers + * and starting from 0 if necessary). For example, if the ith server is busy, try to assign the + * request to the (i+1)th server, then the (i+2)th server, and so on. + * + * You are given a strictly increasing array arrival of positive integers, where arrival[i] + * represents the arrival time of the ith request, and another array load, where load[i] represents + * the load of the ith request (the time it takes to complete). Your goal is to find the busiest + * server(s). A server is considered busiest if it handled the most number of requests successfully + * among all the servers. + * + * Return a list containing the IDs (0-indexed) of the busiest server(s). You may return the IDs + * in any order. + */ + +/** + * @param {number} k + * @param {number[]} arrival + * @param {number[]} load + * @return {number[]} + */ +var busiestServers = function(k, arrival, load) { + const requests = new Array(k).fill(0); + const busy = new PriorityQueue((a, b) => a[0] - b[0]); + const right = Array.from({length: k}, (_, i) => i); + let left = []; + + for (let i = 0; i < arrival.length; i++) { + const time = arrival[i]; + const target = i % k; + + while (!busy.isEmpty() && busy.front()[0] <= time) { + const serverId = busy.dequeue()[1]; + (serverId >= target) ? binaryInsert(right, serverId) : binaryInsert(left, serverId); + } + + let assigned = -1; + + if (right.length > 0) { + const index = binarySearch(right, target); + if (index < right.length) { + assigned = right[index]; + right.splice(index, 1); + } + } + + if (assigned === -1 && left.length > 0) { + assigned = left[0]; + left.shift(); + } + + if (assigned !== -1) { + requests[assigned]++; + busy.enqueue([time + load[i], assigned]); + } + + if ((i + 1) % k === 0) { + right.push(...left); + right.sort((a, b) => a - b); + left = []; + } + } + + const maxRequests = Math.max(...requests); + return requests.reduce((result, count, index) => { + if (count === maxRequests) result.push(index); + return result; + }, []); +}; + +function binarySearch(arr, target) { + let left = 0; + let right = arr.length - 1; + let result = arr.length; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + if (arr[mid] >= target) { + result = mid; + right = mid - 1; + } else { + left = mid + 1; + } + } + + return result; +} + +function binaryInsert(arr, val) { + arr.splice(binarySearch(arr, val), 0, val); +} diff --git a/solutions/1608-special-array-with-x-elements-greater-than-or-equal-x.js b/solutions/1608-special-array-with-x-elements-greater-than-or-equal-x.js new file mode 100644 index 00000000..1d19e657 --- /dev/null +++ b/solutions/1608-special-array-with-x-elements-greater-than-or-equal-x.js @@ -0,0 +1,39 @@ +/** + * 1608. Special Array With X Elements Greater Than or Equal X + * https://leetcode.com/problems/special-array-with-x-elements-greater-than-or-equal-x/ + * Difficulty: Easy + * + * You are given an array nums of non-negative integers. nums is considered special if there exists + * a number x such that there are exactly x numbers in nums that are greater than or equal to x. + * + * Notice that x does not have to be an element in nums. + * + * Return x if the array is special, otherwise, return -1. It can be proven that if nums is special, + * the value for x is unique. + */ + +/** + * @param {number[]} nums + * @param {number} start + * @param {number} end + * @return {number} + */ +function specialArray(numbers) { + numbers.sort((a, b) => b - a); + let left = 0; + let right = numbers.length; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + if (mid === 0 || numbers[mid - 1] >= mid) { + if (mid === numbers.length || numbers[mid] < mid) { + return mid; + } + left = mid + 1; + } else { + right = mid - 1; + } + } + + return -1; +} diff --git a/solutions/1609-even-odd-tree.js b/solutions/1609-even-odd-tree.js new file mode 100644 index 00000000..43196719 --- /dev/null +++ b/solutions/1609-even-odd-tree.js @@ -0,0 +1,57 @@ +/** + * 1609. Even Odd Tree + * https://leetcode.com/problems/even-odd-tree/ + * Difficulty: Medium + * + * A binary tree is named Even-Odd if it meets the following conditions: + * - The root of the binary tree is at level index 0, its children are at level index 1, their + * children are at level index 2, etc. + * - For every even-indexed level, all nodes at the level have odd integer values in strictly + * increasing order (from left to right). + * - For every odd-indexed level, all nodes at the level have even integer values in strictly + * decreasing order (from left to right). + * + * Given the root of a binary tree, return true if the binary tree is Even-Odd, otherwise + * return false. + */ + +/** + * 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 isEvenOddTree = function(root) { + let queue = [root]; + let level = 0; + + while (queue.length) { + const levelSize = queue.length; + let prevValue = level % 2 === 0 ? -Infinity : Infinity; + const newQueue = []; + + for (let i = 0; i < levelSize; i++) { + const node = queue[i]; + const isEvenLevel = level % 2 === 0; + const isOddValue = node.val % 2 === 1; + + if (isEvenLevel && (!isOddValue || node.val <= prevValue)) return false; + if (!isEvenLevel && (isOddValue || node.val >= prevValue)) return false; + + prevValue = node.val; + if (node.left) newQueue.push(node.left); + if (node.right) newQueue.push(node.right); + } + + queue = newQueue; + level++; + } + + return true; +}; diff --git a/solutions/1610-maximum-number-of-visible-points.js b/solutions/1610-maximum-number-of-visible-points.js new file mode 100644 index 00000000..057119b3 --- /dev/null +++ b/solutions/1610-maximum-number-of-visible-points.js @@ -0,0 +1,60 @@ +/** + * 1610. Maximum Number of Visible Points + * https://leetcode.com/problems/maximum-number-of-visible-points/ + * Difficulty: Hard + * + * You are given an array points, an integer angle, and your location, where location = [posx, posy] + * and points[i] = [xi, yi] both denote integral coordinates on the X-Y plane. + * + * Initially, you are facing directly east from your position. You cannot move from your position, + * but you can rotate. In other words, posx and posy cannot be changed. Your field of view in + * degrees is represented by angle, determining how wide you can see from any given view direction. + * Let d be the amount in degrees that you rotate counterclockwise. Then, your field of view is the + * inclusive range of angles [d - angle/2, d + angle/2]. + * + * You can see some set of points if, for each point, the angle formed by the point, your position, + * and the immediate east direction from your position is in your field of view. + * + * There can be multiple points at one coordinate. There may be points at your location, and you + * can always see these points regardless of your rotation. Points do not obstruct your vision to + * other points. + * + * Return the maximum number of points you can see. + */ + +/** + * @param {number[][]} points + * @param {number} angle + * @param {number[]} location + * @return {number} + */ +var visiblePoints = function(points, angle, location) { + const angles = []; + let originPoints = 0; + const [x0, y0] = location; + + for (const [x, y] of points) { + if (x === x0 && y === y0) { + originPoints++; + continue; + } + const radian = Math.atan2(y - y0, x - x0); + const degree = (radian * 180) / Math.PI; + angles.push(degree); + angles.push(degree + 360); + } + + angles.sort((a, b) => a - b); + const threshold = angle; + let maxVisible = 0; + let left = 0; + + for (let right = 0; right < angles.length; right++) { + while (angles[right] - angles[left] > threshold) { + left++; + } + maxVisible = Math.max(maxVisible, right - left + 1); + } + + return maxVisible + originPoints; +}; diff --git a/solutions/1611-minimum-one-bit-operations-to-make-integers-zero.js b/solutions/1611-minimum-one-bit-operations-to-make-integers-zero.js new file mode 100644 index 00000000..5358ed7a --- /dev/null +++ b/solutions/1611-minimum-one-bit-operations-to-make-integers-zero.js @@ -0,0 +1,32 @@ +/** + * 1611. Minimum One Bit Operations to Make Integers Zero + * https://leetcode.com/problems/minimum-one-bit-operations-to-make-integers-zero/ + * Difficulty: Hard + * + * Given an integer n, you must transform it into 0 using the following operations any number + * of times: + * - Change the rightmost (0th) bit in the binary representation of n. + * - Change the ith bit in the binary representation of n if the (i-1)th bit is set to 1 and the + * (i-2)th through 0th bits are set to 0. + * + * Return the minimum number of operations to transform n into 0. + */ + +/** + * @param {number} n + * @return {number} + */ +var minimumOneBitOperations = function(n) { + if (n === 0) return 0; + + let result = 0; + let bit = 1; + while (bit <= n) { + if (n & bit) { + result = (1 << (bit.toString(2).length)) - 1 - result; + } + bit <<= 1; + } + + return result; +}; 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/1614-maximum-nesting-depth-of-the-parentheses.js b/solutions/1614-maximum-nesting-depth-of-the-parentheses.js new file mode 100644 index 00000000..84e76888 --- /dev/null +++ b/solutions/1614-maximum-nesting-depth-of-the-parentheses.js @@ -0,0 +1,28 @@ +/** + * 1614. Maximum Nesting Depth of the Parentheses + * https://leetcode.com/problems/maximum-nesting-depth-of-the-parentheses/ + * Difficulty: Easy + * + * Given a valid parentheses string s, return the nesting depth of s. The nesting depth is the + * maximum number of nested parentheses. + */ + +/** + * @param {string} s + * @return {number} + */ +var maxDepth = function(s) { + let currentDepth = 0; + let maxDepth = 0; + + for (const char of s) { + if (char === '(') { + currentDepth++; + maxDepth = Math.max(maxDepth, currentDepth); + } else if (char === ')') { + currentDepth--; + } + } + + return maxDepth; +}; diff --git a/solutions/1615-maximal-network-rank.js b/solutions/1615-maximal-network-rank.js new file mode 100644 index 00000000..63992bb7 --- /dev/null +++ b/solutions/1615-maximal-network-rank.js @@ -0,0 +1,48 @@ +/** + * 1615. Maximal Network Rank + * https://leetcode.com/problems/maximal-network-rank/ + * Difficulty: Medium + * + * There is an infrastructure of n cities with some number of roads connecting these cities. + * Each roads[i] = [ai, bi] indicates that there is a bidirectional road between cities ai and bi. + * + * The network rank of two different cities is defined as the total number of directly connected + * roads to either city. If a road is directly connected to both cities, it is only counted once. + * + * The maximal network rank of the infrastructure is the maximum network rank of all pairs of + * different cities. + * + * Given the integer n and the array roads, return the maximal network rank of the entire + * infrastructure. + */ + +/** + * @param {number} n + * @param {number[][]} roads + * @return {number} + */ +var maximalNetworkRank = function(n, citiesConnections) { + const cityRoadCounts = new Array(n).fill(0); + const directConnections = new Set(); + + for (const [cityA, cityB] of citiesConnections) { + cityRoadCounts[cityA]++; + cityRoadCounts[cityB]++; + directConnections.add(`${Math.min(cityA, cityB)}-${Math.max(cityA, cityB)}`); + } + + let maxNetworkRank = 0; + + for (let cityA = 0; cityA < n; cityA++) { + for (let cityB = cityA + 1; cityB < n; cityB++) { + let networkRank = cityRoadCounts[cityA] + cityRoadCounts[cityB]; + if (directConnections.has(`${cityA}-${cityB}`) + || directConnections.has(`${cityB}-${cityA}`)) { + networkRank--; + } + maxNetworkRank = Math.max(maxNetworkRank, networkRank); + } + } + + return maxNetworkRank; +}; diff --git a/solutions/1616-split-two-strings-to-make-palindrome.js b/solutions/1616-split-two-strings-to-make-palindrome.js new file mode 100644 index 00000000..757d8bb2 --- /dev/null +++ b/solutions/1616-split-two-strings-to-make-palindrome.js @@ -0,0 +1,46 @@ +/** + * 1616. Split Two Strings to Make Palindrome + * https://leetcode.com/problems/split-two-strings-to-make-palindrome/ + * Difficulty: Medium + * + * You are given two strings a and b of the same length. Choose an index and split both strings at + * the same index, splitting a into two strings: aprefix and asuffix where a = aprefix + asuffix, + * and splitting b into two strings: bprefix and bsuffix where b = bprefix + bsuffix. Check if + * aprefix + bsuffix or bprefix + asuffix forms a palindrome. + * + * When you split a string s into sprefix and ssuffix, either ssuffix or sprefix is allowed to be + * empty. For example, if s = "abc", then "" + "abc", "a" + "bc", "ab" + "c" , and "abc" + "" are + * valid splits. + * + * Return true if it is possible to form a palindrome string, otherwise return false. + * + * Notice that x + y denotes the concatenation of strings x and y. + */ + +/** + * @param {string} a + * @param {string} b + * @return {boolean} + */ +var checkPalindromeFormation = function(a, b) { + return check(a, b) || check(b, a); + + function isPalindrome(str, left, right) { + while (left < right) { + if (str[left++] !== str[right--]) return false; + } + return true; + } + + function check(str1, str2) { + let left = 0; + let right = str1.length - 1; + + while (left < right && str1[left] === str2[right]) { + left++; + right--; + } + + return isPalindrome(str1, left, right) || isPalindrome(str2, left, right); + } +}; diff --git a/solutions/1617-count-subtrees-with-max-distance-between-cities.js b/solutions/1617-count-subtrees-with-max-distance-between-cities.js new file mode 100644 index 00000000..d4a4f7cd --- /dev/null +++ b/solutions/1617-count-subtrees-with-max-distance-between-cities.js @@ -0,0 +1,86 @@ +/** + * 1617. Count Subtrees With Max Distance Between Cities + * https://leetcode.com/problems/count-subtrees-with-max-distance-between-cities/ + * Difficulty: Hard + * + * There are n cities numbered from 1 to n. You are given an array edges of size n-1, where + * edges[i] = [ui, vi] represents a bidirectional edge between cities ui and vi. There exists + * a unique path between each pair of cities. In other words, the cities form a tree. + * + * A subtree is a subset of cities where every city is reachable from every other city in the + * subset, where the path between each pair passes through only the cities from the subset. + * Two subtrees are different if there is a city in one subtree that is not present in the other. + * + * For each d from 1 to n-1, find the number of subtrees in which the maximum distance between + * any two cities in the subtree is equal to d. + * + * Return an array of size n-1 where the dth element (1-indexed) is the number of subtrees in + * which the maximum distance between any two cities is equal to d. + * + * Notice that the distance between the two cities is the number of edges in the path between them. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @return {number[]} + */ +var countSubgraphsForEachDiameter = function(n, connections) { + const adjacencyList = Array.from({ length: n }, () => []); + for (const [u, v] of connections) { + adjacencyList[u - 1].push(v - 1); + adjacencyList[v - 1].push(u - 1); + } + + const diameterCounts = new Array(n - 1).fill(0); + + for (let mask = 1; mask < 1 << n; mask++) { + const selectedNodes = Array(n).fill(0); + let nodeCount = 0; + for (let i = 0; i < n; i++) { + if (mask & (1 << i)) { + selectedNodes[i] = 1; + nodeCount++; + } + } + + if (nodeCount < 2) continue; + + const start = selectedNodes.findIndex(bit => bit); + const { maxDist: dist1, farthestNode, distances } = findMaxDistance(selectedNodes, start); + + if (distances.some((d, i) => selectedNodes[i] && d === -1)) continue; + + const { maxDist: dist2 } = findMaxDistance(selectedNodes, farthestNode); + + if (dist2 > 0) { + diameterCounts[dist2 - 1]++; + } + } + + return diameterCounts; + + function findMaxDistance(nodes, start) { + const distances = new Array(n).fill(-1); + const queue = [start]; + distances[start] = 0; + let maxDist = 0; + let farthestNode = start; + + while (queue.length) { + const current = queue.shift(); + for (const neighbor of adjacencyList[current]) { + if (nodes[neighbor] && distances[neighbor] === -1) { + distances[neighbor] = distances[current] + 1; + if (distances[neighbor] > maxDist) { + maxDist = distances[neighbor]; + farthestNode = neighbor; + } + queue.push(neighbor); + } + } + } + + return { maxDist, farthestNode, distances }; + } +}; 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/1619-mean-of-array-after-removing-some-elements.js b/solutions/1619-mean-of-array-after-removing-some-elements.js new file mode 100644 index 00000000..d7c37100 --- /dev/null +++ b/solutions/1619-mean-of-array-after-removing-some-elements.js @@ -0,0 +1,23 @@ +/** + * 1619. Mean of Array After Removing Some Elements + * https://leetcode.com/problems/mean-of-array-after-removing-some-elements/ + * Difficulty: Easy + * + * Given an integer array arr, return the mean of the remaining integers after removing the + * smallest 5% and the largest 5% of the elements. + * + * Answers within 10-5 of the actual answer will be considered accepted. + */ + +/** + * @param {number[]} arr + * @return {number} + */ +var trimMean = function(numbers) { + const sortedNumbers = numbers.sort((a, b) => a - b); + const trimSize = numbers.length * 0.05; + const trimmedNumbers = sortedNumbers.slice(trimSize, -trimSize); + const sum = trimmedNumbers.reduce((acc, num) => acc + num, 0); + + return sum / trimmedNumbers.length; +}; diff --git a/solutions/1620-coordinate-with-maximum-network-quality.js b/solutions/1620-coordinate-with-maximum-network-quality.js new file mode 100644 index 00000000..24c01103 --- /dev/null +++ b/solutions/1620-coordinate-with-maximum-network-quality.js @@ -0,0 +1,66 @@ +/** + * 1620. Coordinate With Maximum Network Quality + * https://leetcode.com/problems/coordinate-with-maximum-network-quality/ + * Difficulty: Medium + * + * You are given an array of network towers towers, where towers[i] = [xi, yi, qi] denotes the + * ith network tower with location (xi, yi) and quality factor qi. All the coordinates are + * integral coordinates on the X-Y plane, and the distance between the two coordinates is the + * Euclidean distance. + * + * You are also given an integer radius where a tower is reachable if the distance is less than + * or equal to radius. Outside that distance, the signal becomes garbled, and the tower is not + * reachable. + * + * The signal quality of the ith tower at a coordinate (x, y) is calculated with the formula + * ⌊qi / (1 + d)⌋, where d is the distance between the tower and the coordinate. The network + * quality at a coordinate is the sum of the signal qualities from all the reachable towers. + * + * Return the array [cx, cy] representing the integral coordinate (cx, cy) where the network + * quality is maximum. If there are multiple coordinates with the same network quality, return + * the lexicographically minimum non-negative coordinate. + * + * Note: + * - A coordinate (x1, y1) is lexicographically smaller than (x2, y2) if either: + * - x1 < x2, or + * - x1 == x2 and y1 < y2. + * - ⌊val⌋ is the greatest integer less than or equal to val (the floor function). + */ + +/** + * @param {number[][]} towers + * @param {number} radius + * @return {number[]} + */ +var bestCoordinate = function(towers, radius) { + let maxQuality = 0; + let optimalCoord = [0, 0]; + + for (let x = 0; x <= 50; x++) { + for (let y = 0; y <= 50; y++) { + let currentQuality = 0; + + for (const [towerX, towerY, quality] of towers) { + const distance = calculateDistance(x, y, towerX, towerY); + if (distance <= radius) { + currentQuality += Math.floor(quality / (1 + distance)); + } + } + + if (currentQuality > maxQuality) { + maxQuality = currentQuality; + optimalCoord = [x, y]; + } else if (currentQuality === maxQuality && currentQuality > 0) { + if (x < optimalCoord[0] || (x === optimalCoord[0] && y < optimalCoord[1])) { + optimalCoord = [x, y]; + } + } + } + } + + return optimalCoord; + + function calculateDistance(x1, y1, x2, y2) { + return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); + } +}; diff --git a/solutions/1621-number-of-sets-of-k-non-overlapping-line-segments.js b/solutions/1621-number-of-sets-of-k-non-overlapping-line-segments.js new file mode 100644 index 00000000..de32d068 --- /dev/null +++ b/solutions/1621-number-of-sets-of-k-non-overlapping-line-segments.js @@ -0,0 +1,32 @@ +/** + * 1621. Number of Sets of K Non-Overlapping Line Segments + * https://leetcode.com/problems/number-of-sets-of-k-non-overlapping-line-segments/ + * Difficulty: Medium + * + * Given n points on a 1-D plane, where the ith point (from 0 to n-1) is at x = i, find the number + * of ways we can draw exactly k non-overlapping line segments such that each segment covers two + * or more points. The endpoints of each segment must have integral coordinates. The k line segments + * do not have to cover all n points, and they are allowed to share endpoints. + * + * Return the number of ways we can draw k non-overlapping line segments. Since this number can be + * huge, return it modulo 109 + 7. + */ + +/** + * @param {number} n + * @param {number} k + * @return {number} + */ +var numberOfSets = function(n, k) { + const MOD = 1e9 + 7; + const comb = Array.from({ length: n + k }, () => Array(n + k).fill(0)); + + for (let i = 0; i < n + k; i++) { + comb[i][0] = 1; + for (let j = 1; j <= i; j++) { + comb[i][j] = (comb[i - 1][j - 1] + comb[i - 1][j]) % MOD; + } + } + + return comb[n + k - 1][2 * k]; +}; diff --git a/solutions/1622-fancy-sequence.js b/solutions/1622-fancy-sequence.js new file mode 100644 index 00000000..16864595 --- /dev/null +++ b/solutions/1622-fancy-sequence.js @@ -0,0 +1,80 @@ +/** + * 1622. Fancy Sequence + * https://leetcode.com/problems/fancy-sequence/ + * Difficulty: Hard + * + * Write an API that generates fancy sequences using the append, addAll, and multAll operations. + * + * Implement the Fancy class: + * - Fancy() Initializes the object with an empty sequence. + * - void append(val) Appends an integer val to the end of the sequence. + * - void addAll(inc) Increments all existing values in the sequence by an integer inc. + * - void multAll(m) Multiplies all existing values in the sequence by an integer m. + * - int getIndex(idx) Gets the current value at index idx (0-indexed) of the sequence modulo + * 109 + 7. If the index is greater or equal than the length of the sequence, return -1. + */ + +var Fancy = function() { + this.sequence = []; + this.additive = 0n; + this.multiplicative = 1n; + this.MOD = 1000000007n; +}; + +/** + * @param {number} val + * @return {void} + */ +Fancy.prototype.append = function(val) { + const valBig = BigInt(val); + const inverse = this.modInverse(this.multiplicative); + const adjustedVal = ((valBig - this.additive + this.MOD) * inverse) % this.MOD; + this.sequence.push(adjustedVal); +}; + +/** + * @param {number} inc + * @return {void} + */ +Fancy.prototype.addAll = function(inc) { + this.additive = (this.additive + BigInt(inc)) % this.MOD; +}; + +/** + * @param {number} m + * @return {void} + */ +Fancy.prototype.multAll = function(m) { + const mBig = BigInt(m); + this.additive = (this.additive * mBig) % this.MOD; + this.multiplicative = (this.multiplicative * mBig) % this.MOD; +}; + +/** + * @param {number} idx + * @return {number} + */ +Fancy.prototype.getIndex = function(idx) { + if (idx >= this.sequence.length) return -1; + return Number((this.sequence[idx] * this.multiplicative + this.additive) % this.MOD); +}; + +/** + * @param {number} a + * @return {number} + */ +Fancy.prototype.modInverse = function(a) { + let m = this.MOD; + const m0 = m; + let x = 1n; + let y = 0n; + + a = a % m; + while (a > 1n) { + const q = a / m; + [a, m] = [m, a % m]; + [x, y] = [y, x - q * y]; + } + + return x < 0n ? x + m0 : x; +}; diff --git a/solutions/1624-largest-substring-between-two-equal-characters.js b/solutions/1624-largest-substring-between-two-equal-characters.js new file mode 100644 index 00000000..84a2a15c --- /dev/null +++ b/solutions/1624-largest-substring-between-two-equal-characters.js @@ -0,0 +1,30 @@ +/** + * 1624. Largest Substring Between Two Equal Characters + * https://leetcode.com/problems/largest-substring-between-two-equal-characters/ + * Difficulty: Easy + * + * Given a string s, return the length of the longest substring between two equal characters, + * excluding the two characters. If there is no such substring return -1. + * + * A substring is a contiguous sequence of characters within a string. + */ + +/** + * @param {string} s + * @return {number} + */ +var maxLengthBetweenEqualCharacters = function(s) { + const charFirstIndex = new Map(); + let maxLength = -1; + + for (let i = 0; i < s.length; i++) { + const char = s[i]; + if (charFirstIndex.has(char)) { + maxLength = Math.max(maxLength, i - charFirstIndex.get(char) - 1); + } else { + charFirstIndex.set(char, i); + } + } + + return maxLength; +}; diff --git a/solutions/1625-lexicographically-smallest-string-after-applying-operations.js b/solutions/1625-lexicographically-smallest-string-after-applying-operations.js new file mode 100644 index 00000000..64e4490d --- /dev/null +++ b/solutions/1625-lexicographically-smallest-string-after-applying-operations.js @@ -0,0 +1,60 @@ +/** + * 1625. Lexicographically Smallest String After Applying Operations + * https://leetcode.com/problems/lexicographically-smallest-string-after-applying-operations/ + * Difficulty: Medium + * + * You are given a string s of even length consisting of digits from 0 to 9, and two integers a + * and b. + * + * You can apply either of the following two operations any number of times and in any order on s: + * - Add a to all odd indices of s (0-indexed). Digits post 9 are cycled back to 0. For example, + * if s = "3456" and a = 5, s becomes "3951". + * - Rotate s to the right by b positions. For example, if s = "3456" and b = 1, s becomes "6345". + * + * Return the lexicographically smallest string you can obtain by applying the above operations any + * number of times on s. + * + * A string a is lexicographically smaller than a string b (of the same length) 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. For example, "0158" is lexicographically smaller than "0190" + * because the first position they differ is at the third letter, and '5' comes before '9'. + */ + +/** + * @param {string} s + * @param {number} a + * @param {number} b + * @return {string} + */ +var findLexSmallestString = function(s, a, b) { + const visited = new Set(); + let smallestString = s; + const queue = [s]; + + const addOperation = str => { + const chars = str.split(''); + for (let i = 1; i < str.length; i += 2) { + chars[i] = String((parseInt(chars[i]) + a) % 10); + } + return chars.join(''); + }; + + const rotateOperation = str => { + return str.slice(-b) + str.slice(0, -b); + }; + + while (queue.length) { + const current = queue.shift(); + if (visited.has(current)) continue; + visited.add(current); + if (current < smallestString) smallestString = current; + + const added = addOperation(current); + const rotated = rotateOperation(current); + + queue.push(added); + queue.push(rotated); + } + + return smallestString; +}; diff --git a/solutions/1626-best-team-with-no-conflicts.js b/solutions/1626-best-team-with-no-conflicts.js new file mode 100644 index 00000000..c862c5a3 --- /dev/null +++ b/solutions/1626-best-team-with-no-conflicts.js @@ -0,0 +1,45 @@ +/** + * 1626. Best Team With No Conflicts + * https://leetcode.com/problems/best-team-with-no-conflicts/ + * Difficulty: Medium + * + * You are the manager of a basketball team. For the upcoming tournament, you want to choose the + * team with the highest overall score. The score of the team is the sum of scores of all the + * players in the team. + * + * However, the basketball team is not allowed to have conflicts. A conflict exists if a younger + * player has a strictly higher score than an older player. A conflict does not occur between + * players of the same age. + * + * Given two lists, scores and ages, where each scores[i] and ages[i] represents the score and + * age of the ith player, respectively, return the highest overall score of all possible basketball + * teams. + */ + +/** + * @param {number[]} scores + * @param {number[]} ages + * @return {number} + */ +var bestTeamScore = function(scores, ages) { + const players = ages.map((age, index) => ({ age, score: scores[index] })); + players.sort((a, b) => a.age - b.age || a.score - b.score); + + const maxScores = new Array(players.length).fill(0); + let highestScore = 0; + + for (let current = 0; current < players.length; current++) { + maxScores[current] = players[current].score; + for (let previous = 0; previous < current; previous++) { + if (players[previous].score <= players[current].score) { + maxScores[current] = Math.max( + maxScores[current], + maxScores[previous] + players[current].score + ); + } + } + highestScore = Math.max(highestScore, maxScores[current]); + } + + return highestScore; +}; diff --git a/solutions/1627-graph-connectivity-with-threshold.js b/solutions/1627-graph-connectivity-with-threshold.js new file mode 100644 index 00000000..ce6c554b --- /dev/null +++ b/solutions/1627-graph-connectivity-with-threshold.js @@ -0,0 +1,49 @@ +/** + * 1627. Graph Connectivity With Threshold + * https://leetcode.com/problems/graph-connectivity-with-threshold/ + * Difficulty: Hard + * + * We have n cities labeled from 1 to n. Two different cities with labels x and y are directly + * connected by a bidirectional road if and only if x and y share a common divisor strictly + * greater than some threshold. More formally, cities with labels x and y have a road between + * them if there exists an integer z such that all of the following are true: + * - x % z == 0, + * - y % z == 0, and + * - z > threshold. + * + * Given the two integers, n and threshold, and an array of queries, you must determine for each + * queries[i] = [ai, bi] if cities ai and bi are connected directly or indirectly. (i.e. there + * is some path between them). + * + * Return an array answer, where answer.length == queries.length and answer[i] is true if for + * the ith query, there is a path between ai and bi, or answer[i] is false if there is no path. + */ + +/** + * @param {number} n + * @param {number} threshold + * @param {number[][]} queries + * @return {boolean[]} + */ +var areConnected = function(n, threshold, queries) { + const parent = new Array(n + 1).fill().map((_, i) => i); + + for (let z = threshold + 1; z <= n; z++) { + for (let x = z; x <= n; x += z) { + union(x, z); + } + } + + return queries.map(([a, b]) => find(a) === find(b)); + + function find(x) { + if (parent[x] !== x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + function union(x, y) { + parent[find(x)] = find(y); + } +}; 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/1629-slowest-key.js b/solutions/1629-slowest-key.js new file mode 100644 index 00000000..849c3862 --- /dev/null +++ b/solutions/1629-slowest-key.js @@ -0,0 +1,42 @@ +/** + * 1629. Slowest Key + * https://leetcode.com/problems/slowest-key/ + * Difficulty: Easy + * + * A newly designed keypad was tested, where a tester pressed a sequence of n keys, one at a time. + * + * You are given a string keysPressed of length n, where keysPressed[i] was the ith key pressed in + * the testing sequence, and a sorted list releaseTimes, where releaseTimes[i] was the time the + * ith key was released. Both arrays are 0-indexed. The 0th key was pressed at the time 0, and + * every subsequent key was pressed at the exact time the previous key was released. + * + * The tester wants to know the key of the keypress that had the longest duration. The ith keypress + * had a duration of releaseTimes[i] - releaseTimes[i - 1], and the 0th keypress had a duration of + * releaseTimes[0]. + * + * Note that the same key could have been pressed multiple times during the test, and these multiple + * presses of the same key may not have had the same duration. + * + * Return the key of the keypress that had the longest duration. If there are multiple such + * keypresses, return the lexicographically largest key of the keypresses. + */ + +/** + * @param {number[]} releaseTimes + * @param {string} keysPressed + * @return {character} + */ +var slowestKey = function(releaseTimes, keysPressed) { + let maxDuration = releaseTimes[0]; + let result = keysPressed[0]; + + for (let i = 1; i < releaseTimes.length; i++) { + const duration = releaseTimes[i] - releaseTimes[i - 1]; + if (duration > maxDuration || (duration === maxDuration && keysPressed[i] > result)) { + maxDuration = duration; + result = keysPressed[i]; + } + } + + return result; +}; diff --git a/solutions/1630-arithmetic-subarrays.js b/solutions/1630-arithmetic-subarrays.js new file mode 100644 index 00000000..b56f5709 --- /dev/null +++ b/solutions/1630-arithmetic-subarrays.js @@ -0,0 +1,49 @@ +/** + * 1630. Arithmetic Subarrays + * https://leetcode.com/problems/arithmetic-subarrays/ + * Difficulty: Medium + * + * A sequence of numbers is called arithmetic if it consists of at least two elements, and the + * difference between every two consecutive elements is the same. More formally, a sequence s + * is arithmetic if and only if s[i+1] - s[i] == s[1] - s[0] for all valid i. + * + * For example, these are arithmetic sequences: + * - 1, 3, 5, 7, 9 + * - 7, 7, 7, 7 + * - 3, -1, -5, -9 + * + * The following sequence is not arithmetic: + * - 1, 1, 2, 5, 7 + * + * You are given an array of n integers, nums, and two arrays of m integers each, l and r, + * representing the m range queries, where the ith query is the range [l[i], r[i]]. All the + * arrays are 0-indexed. + * + * Return a list of boolean elements answer, where answer[i] is true if the subarray + * nums[l[i]], nums[l[i]+1], ... , nums[r[i]] can be rearranged to form an arithmetic + * sequence, and false otherwise. + */ + +/** + * @param {number[]} nums + * @param {number[]} l + * @param {number[]} r + * @return {boolean[]} + */ +var checkArithmeticSubarrays = function(nums, l, r) { + return l.map((start, index) => { + const end = r[index]; + const subarray = nums.slice(start, end + 1); + return isArithmetic(subarray); + }); + + function isArithmetic(subarray) { + if (subarray.length < 2) return false; + subarray.sort((a, b) => a - b); + const diff = subarray[1] - subarray[0]; + for (let i = 2; i < subarray.length; i++) { + if (subarray[i] - subarray[i - 1] !== diff) return false; + } + return true; + } +}; diff --git a/solutions/1631-path-with-minimum-effort.js b/solutions/1631-path-with-minimum-effort.js new file mode 100644 index 00000000..75fe9c85 --- /dev/null +++ b/solutions/1631-path-with-minimum-effort.js @@ -0,0 +1,68 @@ +/** + * 1631. Path With Minimum Effort + * https://leetcode.com/problems/path-with-minimum-effort/ + * Difficulty: Medium + * + * You are a hiker preparing for an upcoming hike. You are given heights, a 2D array of size + * rows x columns, where heights[row][col] represents the height of cell (row, col). You are + * situated in the top-left cell, (0, 0), and you hope to travel to the bottom-right cell, + * (rows-1, columns-1) (i.e., 0-indexed). You can move up, down, left, or right, and you wish + * to find a route that requires the minimum effort. + * + * A route's effort is the maximum absolute difference in heights between two consecutive + * cells of the route. + * + * Return the minimum effort required to travel from the top-left cell to the bottom-right cell. + */ + +/** + * @param {number[][]} heights + * @return {number} + */ +var minimumEffortPath = function(heights) { + const rows = heights.length; + const cols = heights[0].length; + const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]; + + function canReach(maxEffort) { + const visited = Array.from({ length: rows }, () => Array(cols).fill(false)); + const queue = [[0, 0]]; + visited[0][0] = true; + + while (queue.length) { + const [row, col] = queue.shift(); + if (row === rows - 1 && col === cols - 1) return true; + + 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]) { + const effort = Math.abs(heights[newRow][newCol] - heights[row][col]); + if (effort <= maxEffort) { + visited[newRow][newCol] = true; + queue.push([newRow, newCol]); + } + } + } + } + return false; + } + + let left = 0; + let right = 1000000; + let result = right; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + if (canReach(mid)) { + result = mid; + right = mid - 1; + } else { + left = mid + 1; + } + } + + return result; +}; diff --git a/solutions/1632-rank-transform-of-a-matrix.js b/solutions/1632-rank-transform-of-a-matrix.js new file mode 100644 index 00000000..50caf43e --- /dev/null +++ b/solutions/1632-rank-transform-of-a-matrix.js @@ -0,0 +1,129 @@ +/** + * 1632. Rank Transform of a Matrix + * https://leetcode.com/problems/rank-transform-of-a-matrix/ + * Difficulty: Hard + * + * Given an m x n matrix, return a new matrix answer where answer[row][col] is the rank of + * matrix[row][col]. + * + * The rank is an integer that represents how large an element is compared to other elements. + * It is calculated using the following rules: + * - The rank is an integer starting from 1. + * - If two elements p and q are in the same row or column, then: + * - If p < q then rank(p) < rank(q) + * - If p == q then rank(p) == rank(q) + * - If p > q then rank(p) > rank(q) + * - The rank should be as small as possible. + * + * The test cases are generated so that answer is unique under the given rules. + */ + +/** + * @param {number[][]} matrix + * @return {number[][]} + */ +var matrixRankTransform = function(matrix) { + const rows = matrix.length; + const cols = matrix[0].length; + const result = Array.from({ length: rows }, () => new Array(cols).fill(0)); + const parent = new Array(rows * cols).fill(-1); + const elements = []; + + for (let row = 0; row < rows; row++) { + const valueToCoords = new Map(); + for (let col = 0; col < cols; col++) { + const value = matrix[row][col]; + if (!valueToCoords.has(value)) valueToCoords.set(value, []); + valueToCoords.get(value).push([row, col]); + } + for (const coords of valueToCoords.values()) { + for (let i = 1; i < coords.length; i++) { + const [r1, c1] = coords[0]; + const [r2, c2] = coords[i]; + union(r1 * cols + c1, r2 * cols + c2); + } + } + } + + for (let col = 0; col < cols; col++) { + const valueToCoords = new Map(); + for (let row = 0; row < rows; row++) { + const value = matrix[row][col]; + if (!valueToCoords.has(value)) valueToCoords.set(value, []); + valueToCoords.get(value).push([row, col]); + } + for (const coords of valueToCoords.values()) { + for (let i = 1; i < coords.length; i++) { + const [r1, c1] = coords[0]; + const [r2, c2] = coords[i]; + union(r1 * cols + c1, r2 * cols + c2); + } + } + } + + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + elements.push([matrix[row][col], row, col]); + } + } + elements.sort((a, b) => a[0] - b[0]); + + const rowMaxRank = new Array(rows).fill(0); + const colMaxRank = new Array(cols).fill(0); + const groups = new Map(); + + for (let i = 0; i < elements.length; i++) { + const [value, row, col] = elements[i]; + const root = find(row * cols + col); + if (!groups.has(root)) groups.set(root, []); + groups.get(root).push([row, col]); + } + + let i = 0; + while (i < elements.length) { + const value = elements[i][0]; + const currentGroups = new Map(); + while (i < elements.length && elements[i][0] === value) { + const [, row, col] = elements[i]; + const root = find(row * cols + col); + if (!currentGroups.has(root)) currentGroups.set(root, []); + currentGroups.get(root).push([row, col]); + i++; + } + + for (const [root, coords] of currentGroups) { + let maxRank = 0; + for (const [row, col] of coords) { + maxRank = Math.max(maxRank, rowMaxRank[row], colMaxRank[col]); + } + const rank = maxRank + 1; + for (const [row, col] of coords) { + result[row][col] = rank; + rowMaxRank[row] = rank; + colMaxRank[col] = rank; + } + } + } + + return result; + + function find(x) { + if (parent[x] < 0) return x; + return parent[x] = find(parent[x]); + } + + function union(x, y) { + const px = find(x); + const py = find(y); + + if (px !== py) { + if (parent[px] < parent[py]) { + parent[px] += parent[py]; + parent[py] = px; + } else { + parent[py] += parent[px]; + parent[px] = py; + } + } + } +}; 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/1636-sort-array-by-increasing-frequency.js b/solutions/1636-sort-array-by-increasing-frequency.js new file mode 100644 index 00000000..25dd28e8 --- /dev/null +++ b/solutions/1636-sort-array-by-increasing-frequency.js @@ -0,0 +1,25 @@ +/** + * 1636. Sort Array by Increasing Frequency + * https://leetcode.com/problems/sort-array-by-increasing-frequency/ + * Difficulty: Easy + * + * Given an array of integers nums, sort the array in increasing order based on the frequency + * of the values. If multiple values have the same frequency, sort them in decreasing order. + * + * Return the sorted array. + */ + +/** + * @param {number[]} nums + * @return {number[]} + */ +var frequencySort = function(nums) { + const map = new Map(); + nums.forEach(num => map.set(num, (map.get(num) || 0) + 1)); + + return nums.sort((a, b) => { + const freqA = map.get(a); + const freqB = map.get(b); + return freqA === freqB ? b - a : freqA - freqB; + }); +}; diff --git a/solutions/1637-widest-vertical-area-between-two-points-containing-no-points.js b/solutions/1637-widest-vertical-area-between-two-points-containing-no-points.js new file mode 100644 index 00000000..8e41dc36 --- /dev/null +++ b/solutions/1637-widest-vertical-area-between-two-points-containing-no-points.js @@ -0,0 +1,26 @@ +/** + * 1637. Widest Vertical Area Between Two Points Containing No Points + * https://leetcode.com/problems/widest-vertical-area-between-two-points-containing-no-points/ + * Difficulty: Easy + * + * Given n points on a 2D plane where points[i] = [xi, yi], Return the widest vertical area between + * two points such that no points are inside the area. + * + * A vertical area is an area of fixed-width extending infinitely along the y-axis (i.e., infinite + * height). The widest vertical area is the one with the maximum width. + * + * Note that points on the edge of a vertical area are not considered included in the area. + */ + +/** + * @param {number[][]} points + * @return {number} + */ +var maxWidthOfVerticalArea = function(points) { + points.sort((a, b) => a[0] - b[0]); + let result = 0; + for (let i = 1; i < points.length; i++) { + result = Math.max(result, points[i][0] - points[i - 1][0]); + } + return result; +}; diff --git a/solutions/1638-count-substrings-that-differ-by-one-character.js b/solutions/1638-count-substrings-that-differ-by-one-character.js new file mode 100644 index 00000000..030b847f --- /dev/null +++ b/solutions/1638-count-substrings-that-differ-by-one-character.js @@ -0,0 +1,39 @@ +/** + * 1638. Count Substrings That Differ by One Character + * https://leetcode.com/problems/count-substrings-that-differ-by-one-character/ + * Difficulty: Medium + * + * Given two strings s and t, find the number of ways you can choose a non-empty substring of s + * and replace a single character by a different character such that the resulting substring is + * a substring of t. In other words, find the number of substrings in s that differ from some + * substring in t by exactly one character. + * + * For example, the underlined substrings in "computer" and "computation" only differ by the + * 'e'/'a', so this is a valid way. + * + * Return the number of substrings that satisfy the condition above. + * + * A substring is a contiguous sequence of characters within a string. + */ + +/** + * @param {string} s + * @param {string} t + * @return {number} + */ +var countSubstrings = function(s, t) { + let result = 0; + + for (let i = 0; i < s.length; i++) { + for (let j = 0; j < t.length; j++) { + let diffCount = 0; + for (let k = 0; i + k < s.length && j + k < t.length; k++) { + if (s[i + k] !== t[j + k]) diffCount++; + if (diffCount === 1) result++; + if (diffCount > 1) break; + } + } + } + + return result; +}; diff --git a/solutions/1639-number-of-ways-to-form-a-target-string-given-a-dictionary.js b/solutions/1639-number-of-ways-to-form-a-target-string-given-a-dictionary.js new file mode 100644 index 00000000..45ccd6a8 --- /dev/null +++ b/solutions/1639-number-of-ways-to-form-a-target-string-given-a-dictionary.js @@ -0,0 +1,55 @@ +/** + * 1639. Number of Ways to Form a Target String Given a Dictionary + * https://leetcode.com/problems/number-of-ways-to-form-a-target-string-given-a-dictionary/ + * Difficulty: Hard + * + * You are given a list of strings of the same length words and a string target. + * + * Your task is to form target using the given words under the following rules: + * - target should be formed from left to right. + * - To form the ith character (0-indexed) of target, you can choose the kth character of the jth + * string in words if target[i] = words[j][k]. + * - Once you use the kth character of the jth string of words, you can no longer use the xth + * character of any string in words where x <= k. In other words, all characters to the left of + * or at index k become unusuable for every string. + * - Repeat the process until you form the string target. + * + * Notice that you can use multiple characters from the same string in words provided the + * conditions above are met. + * + * Return the number of ways to form target from words. Since the answer may be too large, return + * it modulo 109 + 7. + */ + +/** + * @param {string[]} words + * @param {string} target + * @return {number} + */ +var numWays = function(words, target) { + const MOD = 1e9 + 7; + const wordLength = words[0].length; + const targetLength = target.length; + const charCounts = Array(wordLength).fill().map(() => Array(26).fill(0)); + + for (const word of words) { + for (let i = 0; i < wordLength; i++) { + charCounts[i][word.charCodeAt(i) - 97]++; + } + } + + const dp = Array(targetLength + 1).fill().map(() => Array(wordLength + 1).fill(0)); + dp[0][0] = 1; + + for (let i = 0; i <= targetLength; i++) { + for (let j = 0; j < wordLength; j++) { + if (i < targetLength) { + const charIndex = target.charCodeAt(i) - 97; + dp[i + 1][j + 1] = (dp[i + 1][j + 1] + dp[i][j] * charCounts[j][charIndex]) % MOD; + } + dp[i][j + 1] = (dp[i][j + 1] + dp[i][j]) % MOD; + } + } + + return dp[targetLength][wordLength]; +}; diff --git a/solutions/1640-check-array-formation-through-concatenation.js b/solutions/1640-check-array-formation-through-concatenation.js new file mode 100644 index 00000000..eabb17a6 --- /dev/null +++ b/solutions/1640-check-array-formation-through-concatenation.js @@ -0,0 +1,41 @@ +/** + * 1640. Check Array Formation Through Concatenation + * https://leetcode.com/problems/check-array-formation-through-concatenation/ + * Difficulty: Easy + * + * You are given an array of distinct integers arr and an array of integer arrays pieces, + * where the integers in pieces are distinct. Your goal is to form arr by concatenating + * the arrays in pieces in any order. However, you are not allowed to reorder the integers + * in each array pieces[i]. + * + * Return true if it is possible to form the array arr from pieces. Otherwise, return false. + */ + +/** + * @param {number[]} arr + * @param {number[][]} pieces + * @return {boolean} + */ +var canFormArray = function(arr, pieces) { + const numberToPiece = new Map(); + for (const piece of pieces) { + numberToPiece.set(piece[0], piece); + } + + let index = 0; + while (index < arr.length) { + const currentNumber = arr[index]; + if (!numberToPiece.has(currentNumber)) { + return false; + } + const piece = numberToPiece.get(currentNumber); + for (const num of piece) { + if (arr[index] !== num) { + return false; + } + index++; + } + } + + return true; +}; diff --git a/solutions/1641-count-sorted-vowel-strings.js b/solutions/1641-count-sorted-vowel-strings.js new file mode 100644 index 00000000..2e8915b0 --- /dev/null +++ b/solutions/1641-count-sorted-vowel-strings.js @@ -0,0 +1,27 @@ +/** + * 1641. Count Sorted Vowel Strings + * https://leetcode.com/problems/count-sorted-vowel-strings/ + * Difficulty: Medium + * + * Given an integer n, return the number of strings of length n that consist only of vowels + * (a, e, i, o, u) and are lexicographically sorted. + * + * A string s is lexicographically sorted if for all valid i, s[i] is the same as or comes + * before s[i+1] in the alphabet. + */ + +/** + * @param {number} n + * @return {number} + */ +var countVowelStrings = function(n) { + const vowelCounts = [1, 1, 1, 1, 1]; + + for (let i = 1; i < n; i++) { + for (let j = 3; j >= 0; j--) { + vowelCounts[j] += vowelCounts[j + 1]; + } + } + + return vowelCounts.reduce((sum, count) => sum + count, 0); +}; diff --git a/solutions/1642-furthest-building-you-can-reach.js b/solutions/1642-furthest-building-you-can-reach.js new file mode 100644 index 00000000..0aaebdee --- /dev/null +++ b/solutions/1642-furthest-building-you-can-reach.js @@ -0,0 +1,46 @@ +/** + * 1642. Furthest Building You Can Reach + * https://leetcode.com/problems/furthest-building-you-can-reach/ + * Difficulty: Medium + * + * You are given an integer array heights representing the heights of buildings, some bricks, + * and some ladders. + * + * You start your journey from building 0 and move to the next building by possibly using + * bricks or ladders. + * + * While moving from building i to building i+1 (0-indexed): + * - If the current building's height is greater than or equal to the next building's height, + * you do not need a ladder or bricks. + * - If the current building's height is less than the next building's height, you can either + * use one ladder or (h[i+1] - h[i]) bricks. + * + * Return the furthest building index (0-indexed) you can reach if you use the given ladders + * and bricks optimally. + */ + +/** + * @param {number[]} heights + * @param {number} bricks + * @param {number} ladders + * @return {number} + */ +var furthestBuilding = function(heights, bricks, ladders) { + const minHeap = new MinPriorityQueue(); + + for (let i = 0; i < heights.length - 1; i++) { + const climb = heights[i + 1] - heights[i]; + if (climb > 0) { + minHeap.push(climb); + if (minHeap.size() > ladders) { + bricks -= minHeap.pop(); + if (bricks < 0) { + return i; + } + } + } + } + + return heights.length - 1; +}; + diff --git a/solutions/1643-kth-smallest-instructions.js b/solutions/1643-kth-smallest-instructions.js new file mode 100644 index 00000000..e7bd79fd --- /dev/null +++ b/solutions/1643-kth-smallest-instructions.js @@ -0,0 +1,65 @@ +/** + * 1643. Kth Smallest Instructions + * https://leetcode.com/problems/kth-smallest-instructions/ + * Difficulty: Hard + * + * Bob is standing at cell (0, 0), and he wants to reach destination: (row, column). He can only + * travel right and down. You are going to help Bob by providing instructions for him to reach + * destination. + * + * The instructions are represented as a string, where each character is either: + * - 'H', meaning move horizontally (go right), or + * - 'V', meaning move vertically (go down). + * + * Multiple instructions will lead Bob to destination. For example, if destination is (2, 3), + * both "HHHVV" and "HVHVH" are valid instructions. + * + * However, Bob is very picky. Bob has a lucky number k, and he wants the kth lexicographically + * smallest instructions that will lead him to destination. k is 1-indexed. + * + * Given an integer array destination and an integer k, return the kth lexicographically + * smallest instructions that will take Bob to destination. + */ + +/** + * @param {number[]} destination + * @param {number} k + * @return {string} + */ +var kthSmallestPath = function(destination, k) { + let verticalMoves = destination[0]; + let horizontalMoves = destination[1]; + const totalMoves = verticalMoves + horizontalMoves; + let path = ''; + + for (let i = 0; i < totalMoves; i++) { + if (horizontalMoves === 0) { + path += 'V'; + verticalMoves--; + continue; + } + const combinations = calculateCombinations( + verticalMoves + horizontalMoves - 1, + horizontalMoves - 1 + ); + if (k <= combinations) { + path += 'H'; + horizontalMoves--; + } else { + path += 'V'; + verticalMoves--; + k -= combinations; + } + } + + return path; +}; + +function calculateCombinations(n, r) { + if (r < 0 || r > n) return 0; + let result = 1; + for (let i = 1; i <= r; i++) { + result = result * (n - i + 1) / i; + } + return Math.floor(result); +} 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/1646-get-maximum-in-generated-array.js b/solutions/1646-get-maximum-in-generated-array.js new file mode 100644 index 00000000..4c4ae686 --- /dev/null +++ b/solutions/1646-get-maximum-in-generated-array.js @@ -0,0 +1,39 @@ +/** + * 1646. Get Maximum in Generated Array + * https://leetcode.com/problems/get-maximum-in-generated-array/ + * Difficulty: Easy + * + * You are given an integer n. A 0-indexed integer array nums of length n + 1 is generated + * in the following way: + * - nums[0] = 0 + * - nums[1] = 1 + * - nums[2 * i] = nums[i] when 2 <= 2 * i <= n + * - nums[2 * i + 1] = nums[i] + nums[i + 1] when 2 <= 2 * i + 1 <= n + * + * Return the maximum integer in the array nums. + */ + +/** + * @param {number} n + * @return {number} + */ +var getMaximumGenerated = function(n) { + if (n === 0) return 0; + + const generatedArray = new Array(n + 1).fill(0); + generatedArray[1] = 1; + let maximumValue = 1; + + for (let i = 1; i <= Math.floor(n / 2); i++) { + if (2 * i <= n) { + generatedArray[2 * i] = generatedArray[i]; + maximumValue = Math.max(maximumValue, generatedArray[2 * i]); + } + if (2 * i + 1 <= n) { + generatedArray[2 * i + 1] = generatedArray[i] + generatedArray[i + 1]; + maximumValue = Math.max(maximumValue, generatedArray[2 * i + 1]); + } + } + + return maximumValue; +}; diff --git a/solutions/1647-minimum-deletions-to-make-character-frequencies-unique.js b/solutions/1647-minimum-deletions-to-make-character-frequencies-unique.js new file mode 100644 index 00000000..22568c4c --- /dev/null +++ b/solutions/1647-minimum-deletions-to-make-character-frequencies-unique.js @@ -0,0 +1,40 @@ +/** + * 1647. Minimum Deletions to Make Character Frequencies Unique + * https://leetcode.com/problems/minimum-deletions-to-make-character-frequencies-unique/ + * Difficulty: Medium + * + * A string s is called good if there are no two different characters in s that have the + * same frequency. + * + * Given a string s, return the minimum number of characters you need to delete to make s good. + * + * The frequency of a character in a string is the number of times it appears in the string. + * For example, in the string "aab", the frequency of 'a' is 2, while the frequency of 'b' is 1. + */ + +/** + * @param {string} s + * @return {number} + */ +var minDeletions = function(s) { + const charFrequencies = new Array(26).fill(0); + for (const char of s) { + charFrequencies[char.charCodeAt(0) - 97]++; + } + + charFrequencies.sort((a, b) => b - a); + let result = 0; + const usedFrequencies = new Set(); + + for (const freq of charFrequencies) { + if (freq === 0) break; + let currentFreq = freq; + while (usedFrequencies.has(currentFreq) && currentFreq > 0) { + currentFreq--; + result++; + } + usedFrequencies.add(currentFreq); + } + + return result; +}; diff --git a/solutions/1648-sell-diminishing-valued-colored-balls.js b/solutions/1648-sell-diminishing-valued-colored-balls.js new file mode 100644 index 00000000..15594e62 --- /dev/null +++ b/solutions/1648-sell-diminishing-valued-colored-balls.js @@ -0,0 +1,66 @@ +/** + * 1648. Sell Diminishing-Valued Colored Balls + * https://leetcode.com/problems/sell-diminishing-valued-colored-balls/ + * Difficulty: Medium + * + * You have an inventory of different colored balls, and there is a customer that wants orders + * balls of any color. + * + * The customer weirdly values the colored balls. Each colored ball's value is the number of balls + * of that color you currently have in your inventory. For example, if you own 6 yellow balls, + * the customer would pay 6 for the first yellow ball. After the transaction, there are only 5 + * yellow balls left, so the next yellow ball is then valued at 5 (i.e., the value of the balls + * decreases as you sell more to the customer). + * + * You are given an integer array, inventory, where inventory[i] represents the number of balls of + * the ith color that you initially own. You are also given an integer orders, which represents + * the total number of balls that the customer wants. You can sell the balls in any order. + * + * Return the maximum total value that you can attain after selling orders colored balls. As the + * answer may be too large, return it modulo 109 + 7. + */ + +/** + * @param {number[]} inventory + * @param {number} orders + * @return {number} + */ +var maxProfit = function(inventory, orders) { + const MOD = 1e9 + 7; + inventory.sort((a, b) => b - a); + inventory.push(0); + + let totalProfit = 0; + let currentColor = 0; + let ballsSold = 0; + + while (ballsSold < orders) { + const currentCount = inventory[currentColor]; + const nextCount = inventory[currentColor + 1]; + const colors = currentColor + 1; + const ballsToSell = Math.min( + orders - ballsSold, + colors * (currentCount - nextCount) + ); + + const fullSets = Math.floor(ballsToSell / colors); + const remainder = ballsToSell % colors; + + if (fullSets > 0) { + const endValue = currentCount - fullSets + 1; + let sequenceSum = (BigInt(colors) * BigInt(fullSets) % BigInt(MOD)) + * (BigInt(currentCount) + BigInt(endValue)) % BigInt(MOD); + sequenceSum = (sequenceSum * BigInt(500000004)) % BigInt(MOD); + totalProfit = (totalProfit + Number(sequenceSum)) % MOD; + } + + if (remainder > 0) { + totalProfit = (totalProfit + (remainder * (currentCount - fullSets)) % MOD) % MOD; + } + + ballsSold += ballsToSell; + currentColor++; + } + + return totalProfit; +}; diff --git a/solutions/1649-create-sorted-array-through-instructions.js b/solutions/1649-create-sorted-array-through-instructions.js new file mode 100644 index 00000000..6e3937c7 --- /dev/null +++ b/solutions/1649-create-sorted-array-through-instructions.js @@ -0,0 +1,52 @@ +/** + * 1649. Create Sorted Array through Instructions + * https://leetcode.com/problems/create-sorted-array-through-instructions/ + * Difficulty: Hard + * + * Given an integer array instructions, you are asked to create a sorted array from the elements in + * instructions. You start with an empty container nums. For each element from left to right in + * instructions, insert it into nums. The cost of each insertion is the minimum of the following: + * - The number of elements currently in nums that are strictly less than instructions[i]. + * - The number of elements currently in nums that are strictly greater than instructions[i]. + * + * For example, if inserting element 3 into nums = [1,2,3,5], the cost of insertion is min(2, 1) + * (elements 1 and 2 are less than 3, element 5 is greater than 3) and nums will become [1,2,3,3,5]. + * + * Return the total cost to insert all elements from instructions into nums. Since the answer may + * be large, return it modulo 109 + 7 + */ + +/** + * @param {number[]} instructions + * @return {number} + */ +var createSortedArray = function(instructions) { + const MOD = 1e9 + 7; + const maxValue = Math.max(...instructions); + const fenwickTree = new Array(maxValue + 1).fill(0); + let totalCost = 0; + + for (let i = 0; i < instructions.length; i++) { + const value = instructions[i]; + const lessCount = query(value - 1); + const greaterCount = i - query(value); + totalCost = (totalCost + Math.min(lessCount, greaterCount)) % MOD; + update(value); + } + + return totalCost; + + function update(index) { + for (let i = index; i <= maxValue; i += i & -i) { + fenwickTree[i]++; + } + } + + function query(index) { + let sum = 0; + for (let i = index; i > 0; i -= i & -i) { + sum += fenwickTree[i]; + } + return sum; + } +}; 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/1652-defuse-the-bomb.js b/solutions/1652-defuse-the-bomb.js new file mode 100644 index 00000000..69b7a74b --- /dev/null +++ b/solutions/1652-defuse-the-bomb.js @@ -0,0 +1,44 @@ +/** + * 1652. Defuse the Bomb + * https://leetcode.com/problems/defuse-the-bomb/ + * Difficulty: Easy + * + * You have a bomb to defuse, and your time is running out! Your informer will provide you with + * a circular array code of length of n and a key k. + * + * To decrypt the code, you must replace every number. All the numbers are replaced simultaneously. + * - If k > 0, replace the ith number with the sum of the next k numbers. + * - If k < 0, replace the ith number with the sum of the previous k numbers. + * - If k == 0, replace the ith number with 0. + * + * As code is circular, the next element of code[n-1] is code[0], and the previous element of + * code[0] is code[n-1]. + * + * Given the circular array code and an integer key k, return the decrypted code to defuse the bomb! + */ + +/** + * @param {number[]} code + * @param {number} k + * @return {number[]} + */ +var decrypt = function(code, k) { + const n = code.length; + const result = new Array(n).fill(0); + + if (k === 0) return result; + + const isPositive = k > 0; + const steps = Math.abs(k); + + for (let i = 0; i < n; i++) { + let sum = 0; + for (let j = 1; j <= steps; j++) { + const index = isPositive ? (i + j) % n : (i - j + n) % n; + sum += code[index]; + } + result[i] = sum; + } + + return result; +}; diff --git a/solutions/1653-minimum-deletions-to-make-string-balanced.js b/solutions/1653-minimum-deletions-to-make-string-balanced.js new file mode 100644 index 00000000..12ae2c7b --- /dev/null +++ b/solutions/1653-minimum-deletions-to-make-string-balanced.js @@ -0,0 +1,34 @@ +/** + * 1653. Minimum Deletions to Make String Balanced + * https://leetcode.com/problems/minimum-deletions-to-make-string-balanced/ + * Difficulty: Medium + * + * You are given a string s consisting only of characters 'a' and 'b'. + * + * You can delete any number of characters in s to make s balanced. s is balanced if there is + * no pair of indices (i,j) such that i < j and s[i] = 'b' and s[j]= 'a'. + * + * Return the minimum number of deletions needed to make s balanced. + */ + +/** + * @param {string} s + * @return {number} + */ +var minimumDeletions = function(s) { + let aCountRight = 0; + for (const char of s) { + if (char === 'a') aCountRight++; + } + + let bCountLeft = 0; + let result = aCountRight; + + for (const char of s) { + if (char === 'a') aCountRight--; + else bCountLeft++; + result = Math.min(result, aCountRight + bCountLeft); + } + + return result; +}; diff --git a/solutions/1654-minimum-jumps-to-reach-home.js b/solutions/1654-minimum-jumps-to-reach-home.js new file mode 100644 index 00000000..22faac68 --- /dev/null +++ b/solutions/1654-minimum-jumps-to-reach-home.js @@ -0,0 +1,59 @@ +/** + * 1654. Minimum Jumps to Reach Home + * https://leetcode.com/problems/minimum-jumps-to-reach-home/ + * Difficulty: Medium + * + * A certain bug's home is on the x-axis at position x. Help them get there from position 0. + * + * The bug jumps according to the following rules: + * - It can jump exactly a positions forward (to the right). + * - It can jump exactly b positions backward (to the left). + * - It cannot jump backward twice in a row. + * - It cannot jump to any forbidden positions. + * + * The bug may jump forward beyond its home, but it cannot jump to positions numbered with + * negative integers. + * + * Given an array of integers forbidden, where forbidden[i] means that the bug cannot jump to + * the position forbidden[i], and integers a, b, and x, return the minimum number of jumps + * needed for the bug to reach its home. If there is no possible sequence of jumps that lands + * the bug on position x, return -1. + */ + +/** + * @param {number[]} forbidden + * @param {number} a + * @param {number} b + * @param {number} x + * @return {number} + */ +var minimumJumps = function(forbidden, a, b, x) { + const forbiddenSet = new Set(forbidden); + const maxPosition = Math.max(x, Math.max(...forbidden)) + a + b; + const queue = [[0, 0, false]]; + const visited = new Set([`0,false`]); + + while (queue.length) { + const [position, jumps, isBackward] = queue.shift(); + + if (position === x) return jumps; + + const forwardPosition = position + a; + if (forwardPosition <= maxPosition && !forbiddenSet.has(forwardPosition) + && !visited.has(`${forwardPosition},false`)) { + queue.push([forwardPosition, jumps + 1, false]); + visited.add(`${forwardPosition},false`); + } + + if (!isBackward && b > 0) { + const backwardPosition = position - b; + if (backwardPosition >= 0 && !forbiddenSet.has(backwardPosition) + && !visited.has(`${backwardPosition},true`)) { + queue.push([backwardPosition, jumps + 1, true]); + visited.add(`${backwardPosition},true`); + } + } + } + + return -1; +}; diff --git a/solutions/1655-distribute-repeating-integers.js b/solutions/1655-distribute-repeating-integers.js new file mode 100644 index 00000000..d80e920d --- /dev/null +++ b/solutions/1655-distribute-repeating-integers.js @@ -0,0 +1,46 @@ +/** + * 1655. Distribute Repeating Integers + * https://leetcode.com/problems/distribute-repeating-integers/ + * Difficulty: Hard + * + * You are given an array of n integers, nums, where there are at most 50 unique values in + * the array. You are also given an array of m customer order quantities, quantity, where + * quantity[i] is the amount of integers the ith customer ordered. Determine if it is possible + * to distribute nums such that: + * - The ith customer gets exactly quantity[i] integers, + * - The integers the ith customer gets are all equal, and + * - Every customer is satisfied. + * + * Return true if it is possible to distribute nums according to the above conditions. + */ + +/** + * @param {number[]} nums + * @param {number[]} quantity + * @return {boolean} + */ +var canDistribute = function(nums, quantity) { + const frequencyMap = new Map(); + for (const num of nums) { + frequencyMap.set(num, (frequencyMap.get(num) || 0) + 1); + } + + const frequencies = Array.from(frequencyMap.values()).sort((a, b) => b - a); + quantity.sort((a, b) => b - a); + + return canSatisfy(0, frequencies); + + function canSatisfy(index, counts) { + if (index === quantity.length) return true; + + for (let i = 0; i < counts.length; i++) { + if (counts[i] >= quantity[index]) { + counts[i] -= quantity[index]; + if (canSatisfy(index + 1, counts)) return true; + counts[i] += quantity[index]; + } + } + + return false; + } +}; diff --git a/solutions/1656-design-an-ordered-stream.js b/solutions/1656-design-an-ordered-stream.js new file mode 100644 index 00000000..4bf3310f --- /dev/null +++ b/solutions/1656-design-an-ordered-stream.js @@ -0,0 +1,46 @@ +/** + * 1656. Design an Ordered Stream + * https://leetcode.com/problems/design-an-ordered-stream/ + * Difficulty: Easy + * + * There is a stream of n (idKey, value) pairs arriving in an arbitrary order, where idKey is + * an integer between 1 and n and value is a string. No two pairs have the same id. + * + * Design a stream that returns the values in increasing order of their IDs by returning a chunk + * (list) of values after each insertion. The concatenation of all the chunks should result in a + * list of the sorted values. + * + * Implement the OrderedStream class: + * - OrderedStream(int n) Constructs the stream to take n values. + * - String[] insert(int idKey, String value) Inserts the pair (idKey, value) into the stream, + * then returns the largest possible chunk of currently inserted values that appear next in + * the order. + */ + +/** + * @param {number} n + */ +var OrderedStream = function(n) { + this.stream = new Array(n).fill(null); + this.nextIndex = 0; +}; + +/** + * @param {number} idKey + * @param {string} value + * @return {string[]} + */ +OrderedStream.prototype.insert = function(idKey, value) { + const index = idKey - 1; + this.stream[index] = value; + + if (index !== this.nextIndex) return []; + + const result = []; + while (this.nextIndex < this.stream.length && this.stream[this.nextIndex] !== null) { + result.push(this.stream[this.nextIndex]); + this.nextIndex++; + } + + return result; +}; diff --git a/solutions/1658-minimum-operations-to-reduce-x-to-zero.js b/solutions/1658-minimum-operations-to-reduce-x-to-zero.js new file mode 100644 index 00000000..83dd0ee4 --- /dev/null +++ b/solutions/1658-minimum-operations-to-reduce-x-to-zero.js @@ -0,0 +1,42 @@ +/** + * 1658. Minimum Operations to Reduce X to Zero + * https://leetcode.com/problems/minimum-operations-to-reduce-x-to-zero/ + * Difficulty: Medium + * + * You are given an integer array nums and an integer x. In one operation, you can either remove + * the leftmost or the rightmost element from the array nums and subtract its value from x. Note + * that this modifies the array for future operations. + * + * Return the minimum number of operations to reduce x to exactly 0 if it is possible, otherwise, + * return -1. + */ + +/** + * @param {number[]} nums + * @param {number} x + * @return {number} + */ +var minOperations = function(nums, x) { + const targetSum = nums.reduce((sum, num) => sum + num, 0) - x; + if (targetSum < 0) return -1; + if (targetSum === 0) return nums.length; + + let currentSum = 0; + let maxLength = -1; + let left = 0; + + for (let right = 0; right < nums.length; right++) { + currentSum += nums[right]; + + while (currentSum > targetSum && left <= right) { + currentSum -= nums[left]; + left++; + } + + if (currentSum === targetSum) { + maxLength = Math.max(maxLength, right - left + 1); + } + } + + return maxLength === -1 ? -1 : nums.length - maxLength; +}; diff --git a/solutions/1659-maximize-grid-happiness.js b/solutions/1659-maximize-grid-happiness.js new file mode 100644 index 00000000..86c1909c --- /dev/null +++ b/solutions/1659-maximize-grid-happiness.js @@ -0,0 +1,93 @@ +/** + * 1659. Maximize Grid Happiness + * https://leetcode.com/problems/maximize-grid-happiness/ + * Difficulty: Hard + * + * You are given four integers, m, n, introvertsCount, and extrovertsCount. You have an m x n grid, + * and there are two types of people: introverts and extroverts. There are introvertsCount + * introverts and extrovertsCount extroverts. + * + * You should decide how many people you want to live in the grid and assign each of them one grid + * cell. Note that you do not have to have all the people living in the grid. + * + * The happiness of each person is calculated as follows: + * - Introverts start with 120 happiness and lose 30 happiness for each neighbor (introvert or + * extrovert). + * - Extroverts start with 40 happiness and gain 20 happiness for each neighbor (introvert or + * extrovert). + * + * Neighbors live in the directly adjacent cells north, east, south, and west of a person's cell. + * + * The grid happiness is the sum of each person's happiness. Return the maximum possible grid + * happiness. + */ + +/** + * @param {number} m + * @param {number} n + * @param {number} introvertsCount + * @param {number} extrovertsCount + * @return {number} + */ +var getMaxGridHappiness = function(m, n, introvertsCount, extrovertsCount) { + const memo = new Map(); + const maxState = Math.pow(3, n); + + return calculateHappiness(0, 0, introvertsCount, extrovertsCount, 0); + + function calculateHappiness(row, col, introverts, extroverts, prevState) { + if (row === m || (introverts === 0 && extroverts === 0)) return 0; + if (col === n) return calculateHappiness(row + 1, 0, introverts, extroverts, prevState); + + const key = `${row},${col},${introverts},${extroverts},${prevState}`; + if (memo.has(key)) return memo.get(key); + + const nextState = (prevState * 3) % maxState; + let maxHappiness = calculateHappiness(row, col + 1, introverts, extroverts, nextState); + + if (introverts > 0) { + let happiness = 120; + const leftNeighbor = col > 0 ? prevState % 3 : 0; + const upNeighbor = row > 0 ? Math.floor(prevState / Math.pow(3, n - 1)) % 3 : 0; + + if (leftNeighbor) happiness -= 30; + if (upNeighbor) happiness -= 30; + + let neighborHappiness = 0; + if (leftNeighbor === 1) neighborHappiness -= 30; + if (leftNeighbor === 2) neighborHappiness += 20; + if (upNeighbor === 1) neighborHappiness -= 30; + if (upNeighbor === 2) neighborHappiness += 20; + + maxHappiness = Math.max( + maxHappiness, + happiness + neighborHappiness + + calculateHappiness(row, col + 1, introverts - 1, extroverts, nextState + 1) + ); + } + + if (extroverts > 0) { + let happiness = 40; + const leftNeighbor = col > 0 ? prevState % 3 : 0; + const upNeighbor = row > 0 ? Math.floor(prevState / Math.pow(3, n - 1)) % 3 : 0; + + if (leftNeighbor) happiness += 20; + if (upNeighbor) happiness += 20; + + let neighborHappiness = 0; + if (leftNeighbor === 1) neighborHappiness -= 30; + if (leftNeighbor === 2) neighborHappiness += 20; + if (upNeighbor === 1) neighborHappiness -= 30; + if (upNeighbor === 2) neighborHappiness += 20; + + maxHappiness = Math.max( + maxHappiness, + happiness + neighborHappiness + + calculateHappiness(row, col + 1, introverts, extroverts - 1, nextState + 2) + ); + } + + memo.set(key, maxHappiness); + return maxHappiness; + } +}; 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/1662-check-if-two-string-arrays-are-equivalent.js b/solutions/1662-check-if-two-string-arrays-are-equivalent.js new file mode 100644 index 00000000..ebbb213b --- /dev/null +++ b/solutions/1662-check-if-two-string-arrays-are-equivalent.js @@ -0,0 +1,19 @@ +/** + * 1662. Check If Two String Arrays are Equivalent + * https://leetcode.com/problems/check-if-two-string-arrays-are-equivalent/ + * Difficulty: Easy + * + * Given two string arrays word1 and word2, return true if the two arrays represent the same + * string, and false otherwise. + * + * A string is represented by an array if the array elements concatenated in order forms the string. + */ + +/** + * @param {string[]} word1 + * @param {string[]} word2 + * @return {boolean} + */ +var arrayStringsAreEqual = function(word1, word2) { + return word1.join('') === word2.join(''); +}; diff --git a/solutions/1663-smallest-string-with-a-given-numeric-value.js b/solutions/1663-smallest-string-with-a-given-numeric-value.js new file mode 100644 index 00000000..2848c484 --- /dev/null +++ b/solutions/1663-smallest-string-with-a-given-numeric-value.js @@ -0,0 +1,38 @@ +/** + * 1663. Smallest String With A Given Numeric Value + * https://leetcode.com/problems/smallest-string-with-a-given-numeric-value/ + * Difficulty: Medium + * + * The numeric value of a lowercase character is defined as its position (1-indexed) in the + * alphabet, so the numeric value of a is 1, the numeric value of b is 2, the numeric value + * of c is 3, and so on. + * + * The numeric value of a string consisting of lowercase characters is defined as the sum of + * its characters' numeric values. For example, the numeric value of the string "abe" is equal + * to 1 + 2 + 5 = 8. + * + * You are given two integers n and k. Return the lexicographically smallest string with length + * equal to n and numeric value equal to k. + * + * 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 {number} n + * @param {number} k + * @return {string} + */ +var getSmallestString = function(n, k) { + const result = new Array(n).fill('a'); + let remainingValue = k - n; + + for (let i = n - 1; i >= 0 && remainingValue > 0; i--) { + const addValue = Math.min(25, remainingValue); + result[i] = String.fromCharCode(97 + addValue); + remainingValue -= addValue; + } + + return result.join(''); +}; diff --git a/solutions/1664-ways-to-make-a-fair-array.js b/solutions/1664-ways-to-make-a-fair-array.js new file mode 100644 index 00000000..34b241c7 --- /dev/null +++ b/solutions/1664-ways-to-make-a-fair-array.js @@ -0,0 +1,49 @@ +/** + * 1664. Ways to Make a Fair Array + * https://leetcode.com/problems/ways-to-make-a-fair-array/ + * Difficulty: Medium + * + * You are given an integer array nums. You can choose exactly one index (0-indexed) and remove + * the element. Notice that the index of the elements may change after the removal. + * + * For example, if nums = [6,1,7,4,1]: + * - Choosing to remove index 1 results in nums = [6,7,4,1]. + * - Choosing to remove index 2 results in nums = [6,1,4,1]. + * - Choosing to remove index 4 results in nums = [6,1,7,4]. + * + * An array is fair if the sum of the odd-indexed values equals the sum of the even-indexed values. + * + * Return the number of indices that you could choose such that after the removal, nums is fair. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var waysToMakeFair = function(nums) { + let evenSum = 0; + let oddSum = 0; + let result = 0; + + for (let i = 0; i < nums.length; i++) { + if (i % 2 === 0) evenSum += nums[i]; + else oddSum += nums[i]; + } + + let currentEven = 0; + let currentOdd = 0; + + for (let i = 0; i < nums.length; i++) { + if (i % 2 === 0) { + evenSum -= nums[i]; + if (currentEven + oddSum === currentOdd + evenSum) result++; + currentEven += nums[i]; + } else { + oddSum -= nums[i]; + if (currentEven + oddSum === currentOdd + evenSum) result++; + currentOdd += nums[i]; + } + } + + return result; +}; diff --git a/solutions/1665-minimum-initial-energy-to-finish-tasks.js b/solutions/1665-minimum-initial-energy-to-finish-tasks.js new file mode 100644 index 00000000..29da68bc --- /dev/null +++ b/solutions/1665-minimum-initial-energy-to-finish-tasks.js @@ -0,0 +1,37 @@ +/** + * 1665. Minimum Initial Energy to Finish Tasks + * https://leetcode.com/problems/minimum-initial-energy-to-finish-tasks/ + * Difficulty: Hard + * + * You are given an array tasks where tasks[i] = [actuali, minimumi]: + * - actuali is the actual amount of energy you spend to finish the ith task. + * - minimumi is the minimum amount of energy you require to begin the ith task. + * + * For example, if the task is [10, 12] and your current energy is 11, you cannot start + * this task. However, if your current energy is 13, you can complete this task, and your + * energy will be 3 after finishing it. + * + * You can finish the tasks in any order you like. + * + * Return the minimum initial amount of energy you will need to finish all the tasks. + */ + +/** + * @param {number[][]} tasks + * @return {number} + */ +var minimumEffort = function(tasks) { + tasks.sort((a, b) => (b[1] - b[0]) - (a[1] - a[0])); + let result = 0; + let currentEnergy = 0; + + for (const [actual, minimum] of tasks) { + if (currentEnergy < minimum) { + result += minimum - currentEnergy; + currentEnergy = minimum; + } + currentEnergy -= actual; + } + + return result; +}; 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/1670-design-front-middle-back-queue.js b/solutions/1670-design-front-middle-back-queue.js new file mode 100644 index 00000000..61189aae --- /dev/null +++ b/solutions/1670-design-front-middle-back-queue.js @@ -0,0 +1,76 @@ +/** + * 1670. Design Front Middle Back Queue + * https://leetcode.com/problems/design-front-middle-back-queue/ + * Difficulty: Medium + * + * Design a queue that supports push and pop operations in the front, middle, and back. + * + * Implement the FrontMiddleBack class: + * - FrontMiddleBack() Initializes the queue. + * - void pushFront(int val) Adds val to the front of the queue. + * - void pushMiddle(int val) Adds val to the middle of the queue. + * - void pushBack(int val) Adds val to the back of the queue. + * - int popFront() Removes the front element of the queue and returns it. If the queue is + * empty, return -1. + * - int popMiddle() Removes the middle element of the queue and returns it. If the queue is + * empty, return -1. + * - int popBack() Removes the back element of the queue and returns it. If the queue is + * empty, return -1. + * + * Notice that when there are two middle position choices, the operation is performed on the + * frontmost middle position choice. For example: + * - Pushing 6 into the middle of [1, 2, 3, 4, 5] results in [1, 2, 6, 3, 4, 5]. + * - Popping the middle from [1, 2, 3, 4, 5, 6] returns 3 and results in [1, 2, 4, 5, 6]. + */ + +var FrontMiddleBackQueue = function() { + this.elements = []; +}; + +/** + * @param {number} val + * @return {void} + */ +FrontMiddleBackQueue.prototype.pushFront = function(val) { + this.elements.unshift(val); +}; + +/** + * @param {number} val + * @return {void} + */ +FrontMiddleBackQueue.prototype.pushMiddle = function(val) { + const mid = Math.floor(this.elements.length / 2); + this.elements.splice(mid, 0, val); +}; + +/** + * @param {number} val + * @return {void} + */ +FrontMiddleBackQueue.prototype.pushBack = function(val) { + this.elements.push(val); +}; + +/** + * @return {number} + */ +FrontMiddleBackQueue.prototype.popFront = function() { + return this.elements.length ? this.elements.shift() : -1; +}; + +/** + * @return {number} + */ +FrontMiddleBackQueue.prototype.popMiddle = function() { + if (!this.elements.length) return -1; + const mid = Math.floor((this.elements.length - 1) / 2); + return this.elements.splice(mid, 1)[0]; +}; + +/** + * @return {number} + */ +FrontMiddleBackQueue.prototype.popBack = function() { + return this.elements.length ? this.elements.pop() : -1; +}; diff --git a/solutions/1671-minimum-number-of-removals-to-make-mountain-array.js b/solutions/1671-minimum-number-of-removals-to-make-mountain-array.js new file mode 100644 index 00000000..5e949373 --- /dev/null +++ b/solutions/1671-minimum-number-of-removals-to-make-mountain-array.js @@ -0,0 +1,49 @@ +/** + * 1671. Minimum Number of Removals to Make Mountain Array + * https://leetcode.com/problems/minimum-number-of-removals-to-make-mountain-array/ + * Difficulty: Hard + * + * You may recall that an array arr is a mountain array if and only if: + * - arr.length >= 3 + * - There exists some index i (0-indexed) with 0 < i < arr.length - 1 such that: + * - arr[0] < arr[1] < ... < arr[i - 1] < arr[i] + * - arr[i] > arr[i + 1] > ... > arr[arr.length - 1] + * + * Given an integer array nums, return the minimum number of elements to remove to make + * nums a mountain array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumMountainRemovals = function(nums) { + const length = nums.length; + const leftLIS = new Array(length).fill(1); + const rightLIS = new Array(length).fill(1); + + for (let i = 1; i < length; i++) { + for (let j = 0; j < i; j++) { + if (nums[i] > nums[j]) { + leftLIS[i] = Math.max(leftLIS[i], leftLIS[j] + 1); + } + } + } + + for (let i = length - 2; i >= 0; i--) { + for (let j = length - 1; j > i; j--) { + if (nums[i] > nums[j]) { + rightLIS[i] = Math.max(rightLIS[i], rightLIS[j] + 1); + } + } + } + + let maxMountainLength = 0; + for (let i = 1; i < length - 1; i++) { + if (leftLIS[i] > 1 && rightLIS[i] > 1) { + maxMountainLength = Math.max(maxMountainLength, leftLIS[i] + rightLIS[i] - 1); + } + } + + return length - maxMountainLength; +}; diff --git a/solutions/1673-find-the-most-competitive-subsequence.js b/solutions/1673-find-the-most-competitive-subsequence.js new file mode 100644 index 00000000..10bfa262 --- /dev/null +++ b/solutions/1673-find-the-most-competitive-subsequence.js @@ -0,0 +1,37 @@ +/** + * 1673. Find the Most Competitive Subsequence + * https://leetcode.com/problems/find-the-most-competitive-subsequence/ + * Difficulty: Medium + * + * Given an integer array nums and a positive integer k, return the most competitive subsequence + * of nums of size k. + * + * An array's subsequence is a resulting sequence obtained by erasing some (possibly zero) elements + * from the array. + * + * We define that a subsequence a is more competitive than a subsequence b (of the same length) if + * in the first position where a and b differ, subsequence a has a number less than the + * corresponding number in b. For example, [1,3,4] is more competitive than [1,3,5] because the + * first position they differ is at the final number, and 4 is less than 5. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number[]} + */ +var mostCompetitive = function(nums, k) { + const result = []; + const n = nums.length; + + for (let i = 0; i < n; i++) { + while (result.length && result[result.length - 1] > nums[i] && result.length + n - i > k) { + result.pop(); + } + if (result.length < k) { + result.push(nums[i]); + } + } + + return result; +}; diff --git a/solutions/1674-minimum-moves-to-make-array-complementary.js b/solutions/1674-minimum-moves-to-make-array-complementary.js new file mode 100644 index 00000000..b996eff6 --- /dev/null +++ b/solutions/1674-minimum-moves-to-make-array-complementary.js @@ -0,0 +1,45 @@ +/** + * 1674. Minimum Moves to Make Array Complementary + * https://leetcode.com/problems/minimum-moves-to-make-array-complementary/ + * Difficulty: Medium + * + * You are given an integer array nums of even length n and an integer limit. In one move, you + * can replace any integer from nums with another integer between 1 and limit, inclusive. + * + * The array nums is complementary if for all indices i (0-indexed), nums[i] + nums[n - 1 - i] + * equals the same number. For example, the array [1,2,3,4] is complementary because for all + * indices i, nums[i] + nums[n - 1 - i] = 5. + * + * Return the minimum number of moves required to make nums complementary. + */ + +/** + * @param {number[]} nums + * @param {number} limit + * @return {number} + */ +var minMoves = function(nums, limit) { + const n = nums.length; + const delta = new Array(2 * limit + 2).fill(0); + let result = n; + + for (let i = 0; i < n / 2; i++) { + const left = nums[i]; + const right = nums[n - 1 - i]; + const minSum = Math.min(left, right) + 1; + const maxSum = Math.max(left, right) + limit; + delta[2] += 2; + delta[minSum] -= 1; + delta[left + right] -= 1; + delta[left + right + 1] += 1; + delta[maxSum + 1] += 1; + } + + let moves = 0; + for (let i = 2; i <= 2 * limit; i++) { + moves += delta[i]; + result = Math.min(result, moves); + } + + return result; +}; diff --git a/solutions/1675-minimize-deviation-in-array.js b/solutions/1675-minimize-deviation-in-array.js new file mode 100644 index 00000000..add60176 --- /dev/null +++ b/solutions/1675-minimize-deviation-in-array.js @@ -0,0 +1,65 @@ +/** + * 1675. Minimize Deviation in Array + * https://leetcode.com/problems/minimize-deviation-in-array/ + * Difficulty: Hard + * + * You are given an array nums of n positive integers. + * + * You can perform two types of operations on any element of the array any number of times: + * - If the element is even, divide it by 2. + * - For example, if the array is [1,2,3,4], then you can do this operation on the last element, + * and the array will be [1,2,3,2]. + * - If the element is odd, multiply it by 2. + * - For example, if the array is [1,2,3,4], then you can do this operation on the first element, + * and the array will be [2,2,3,4]. + * + * The deviation of the array is the maximum difference between any two elements in the array. + * + * Return the minimum deviation the array can have after performing some number of operations. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumDeviation = function(nums) { + const heap = []; + let minElement = Infinity; + + for (const num of nums) { + const value = num % 2 ? num * 2 : num; + heap.push(value); + minElement = Math.min(minElement, value); + } + + for (let i = Math.floor(heap.length / 2) - 1; i >= 0; i--) { + siftDown(i); + } + + let minDeviation = heap[0] - minElement; + + while (heap[0] % 2 === 0) { + const maxElement = heap[0]; + heap[0] = maxElement / 2; + minElement = Math.min(minElement, heap[0]); + siftDown(0); + minDeviation = Math.min(minDeviation, heap[0] - minElement); + } + + return minDeviation; + + function siftDown(index) { + while (2 * index + 1 < heap.length) { + let maxChild = 2 * index + 1; + if (maxChild + 1 < heap.length && heap[maxChild + 1] > heap[maxChild]) { + maxChild++; + } + if (heap[index] < heap[maxChild]) { + [heap[index], heap[maxChild]] = [heap[maxChild], heap[index]]; + index = maxChild; + } else { + break; + } + } + } +}; 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/1678-goal-parser-interpretation.js b/solutions/1678-goal-parser-interpretation.js new file mode 100644 index 00000000..32bb31f8 --- /dev/null +++ b/solutions/1678-goal-parser-interpretation.js @@ -0,0 +1,34 @@ +/** + * 1678. Goal Parser Interpretation + * https://leetcode.com/problems/goal-parser-interpretation/ + * Difficulty: Easy + * + * You own a Goal Parser that can interpret a string command. The command consists of an alphabet + * of "G", "()" and/or "(al)" in some order. The Goal Parser will interpret "G" as the string + * "G", "()" as the string "o", and "(al)" as the string "al". The interpreted strings are then + * concatenated in the original order. + * + * Given the string command, return the Goal Parser's interpretation of command. + */ + +/** + * @param {string} command + * @return {string} + */ +var interpret = function(command) { + let result = ''; + + for (let i = 0; i < command.length; i++) { + if (command[i] === 'G') { + result += 'G'; + } else if (command[i] === '(' && command[i + 1] === ')') { + result += 'o'; + i++; + } else { + result += 'al'; + i += 3; + } + } + + return result; +}; diff --git a/solutions/1680-concatenation-of-consecutive-binary-numbers.js b/solutions/1680-concatenation-of-consecutive-binary-numbers.js new file mode 100644 index 00000000..d41c5fa5 --- /dev/null +++ b/solutions/1680-concatenation-of-consecutive-binary-numbers.js @@ -0,0 +1,24 @@ +/** + * 1680. Concatenation of Consecutive Binary Numbers + * https://leetcode.com/problems/concatenation-of-consecutive-binary-numbers/ + * Difficulty: Medium + * + * Given an integer n, return the decimal value of the binary string formed by concatenating the + * binary representations of 1 to n in order, modulo 109 + 7. + */ + +/** + * @param {number} n + * @return {number} + */ +var concatenatedBinary = function(n) { + const MOD = 1e9 + 7; + let result = 0; + + for (let i = 1; i <= n; i++) { + const bitLength = Math.floor(Math.log2(i)) + 1; + result = ((result * (1 << bitLength)) % MOD + i) % MOD; + } + + return result; +}; diff --git a/solutions/1681-minimum-incompatibility.js b/solutions/1681-minimum-incompatibility.js new file mode 100644 index 00000000..a65163f4 --- /dev/null +++ b/solutions/1681-minimum-incompatibility.js @@ -0,0 +1,65 @@ +/** + * 1681. Minimum Incompatibility + * https://leetcode.com/problems/minimum-incompatibility/ + * Difficulty: Hard + * + * You are given an integer array nums and an integer k. You are asked to distribute this array + * into k subsets of equal size such that there are no two equal elements in the same subset. + * + * A subset's incompatibility is the difference between the maximum and minimum elements in that + * array. + * + * Return the minimum possible sum of incompatibilities of the k subsets after distributing the + * array optimally, or return -1 if it is not possible. + * + * A subset is a group integers that appear in the array with no particular order. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minimumIncompatibility = function(nums, k) { + const n = nums.length; + const subsetSize = n / k; + const freq = new Array(n + 1).fill(0); + for (const num of nums) { + freq[num]++; + if (freq[num] > k) return -1; + } + + nums.sort((a, b) => a - b); + const subsetValues = new Map(); + + computeSubsets(0, 0, 0, 0, 0, []); + + const dp = new Array(1 << n).fill(Infinity); + dp[0] = 0; + + for (let mask = 0; mask < (1 << n); mask++) { + if (dp[mask] === Infinity) continue; + for (const [subsetMask, value] of subsetValues) { + if ((mask & subsetMask) === 0) { + const newMask = mask | subsetMask; + dp[newMask] = Math.min(dp[newMask], dp[mask] + value); + } + } + } + + return dp[(1 << n) - 1] === Infinity ? -1 : dp[(1 << n) - 1]; + + function computeSubsets(mask, index, count, minVal, maxVal, selected) { + if (count === subsetSize) { + subsetValues.set(mask, maxVal - minVal); + return; + } + if (index >= n || n - index < subsetSize - count) return; + + computeSubsets(mask, index + 1, count, minVal, maxVal, selected); + if (!selected.includes(nums[index])) { + computeSubsets(mask | (1 << index), index + 1, count + 1, + count === 0 ? nums[index] : minVal, nums[index], [...selected, nums[index]]); + } + } +}; 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/1684-count-the-number-of-consistent-strings.js b/solutions/1684-count-the-number-of-consistent-strings.js new file mode 100644 index 00000000..29953369 --- /dev/null +++ b/solutions/1684-count-the-number-of-consistent-strings.js @@ -0,0 +1,33 @@ +/** + * 1684. Count the Number of Consistent Strings + * https://leetcode.com/problems/count-the-number-of-consistent-strings/ + * Difficulty: Easy + * + * You are given a string allowed consisting of distinct characters and an array of strings words. + * A string is consistent if all characters in the string appear in the string allowed. + * + * Return the number of consistent strings in the array words. + */ + +/** + * @param {string} allowed + * @param {string[]} words + * @return {number} + */ +var countConsistentStrings = function(allowed, words) { + const allowedSet = new Set(allowed); + let result = 0; + + for (const word of words) { + let isConsistent = true; + for (const char of word) { + if (!allowedSet.has(char)) { + isConsistent = false; + break; + } + } + if (isConsistent) result++; + } + + return result; +}; diff --git a/solutions/1685-sum-of-absolute-differences-in-a-sorted-array.js b/solutions/1685-sum-of-absolute-differences-in-a-sorted-array.js new file mode 100644 index 00000000..1abbe093 --- /dev/null +++ b/solutions/1685-sum-of-absolute-differences-in-a-sorted-array.js @@ -0,0 +1,34 @@ +/** + * 1685. Sum of Absolute Differences in a Sorted Array + * https://leetcode.com/problems/sum-of-absolute-differences-in-a-sorted-array/ + * Difficulty: Medium + * + * You are given an integer array nums sorted in non-decreasing order. + * + * Build and return an integer array result with the same length as nums such that result[i] is + * equal to the summation of absolute differences between nums[i] and all the other elements + * in the array. + * + * In other words, result[i] is equal to sum(|nums[i]-nums[j]|) where 0 <= j < nums.length + * and j != i (0-indexed). + */ + +/** + * @param {number[]} nums + * @return {number[]} + */ +var getSumAbsoluteDifferences = function(nums) { + const n = nums.length; + const result = new Array(n); + let prefixSum = 0; + let suffixSum = nums.reduce((sum, num) => sum + num, 0); + + for (let i = 0; i < n; i++) { + const current = nums[i]; + suffixSum -= current; + result[i] = (current * i - prefixSum) + (suffixSum - current * (n - 1 - i)); + prefixSum += current; + } + + return result; +}; diff --git a/solutions/1686-stone-game-vi.js b/solutions/1686-stone-game-vi.js new file mode 100644 index 00000000..c0c7f9c9 --- /dev/null +++ b/solutions/1686-stone-game-vi.js @@ -0,0 +1,51 @@ +/** + * 1686. Stone Game VI + * https://leetcode.com/problems/stone-game-vi/ + * Difficulty: Medium + * + * Alice and Bob take turns playing a game, with Alice starting first. + * + * There are n stones in a pile. On each player's turn, they can remove a stone from the pile and + * receive points based on the stone's value. Alice and Bob may value the stones differently. + * + * You are given two integer arrays of length n, aliceValues and bobValues. Each aliceValues[i] + * and bobValues[i] represents how Alice and Bob, respectively, value the ith stone. + * + * The winner is the person with the most points after all the stones are chosen. If both players + * have the same amount of points, the game results in a draw. Both players will play optimally. + * Both players know the other's values. + * + * Determine the result of the game, and: + * - If Alice wins, return 1. + * - If Bob wins, return -1. + * - If the game results in a draw, return 0. + */ + +/** + * @param {number[]} aliceValues + * @param {number[]} bobValues + * @return {number} + */ +var stoneGameVI = function(aliceValues, bobValues) { + const n = aliceValues.length; + const stones = aliceValues.map((alice, i) => ({ + sum: alice + bobValues[i], + alice: alice, + bob: bobValues[i] + })); + + stones.sort((a, b) => b.sum - a.sum); + + let aliceScore = 0; + let bobScore = 0; + + for (let i = 0; i < n; i++) { + if (i % 2 === 0) { + aliceScore += stones[i].alice; + } else { + bobScore += stones[i].bob; + } + } + + return aliceScore > bobScore ? 1 : aliceScore < bobScore ? -1 : 0; +}; diff --git a/solutions/1687-delivering-boxes-from-storage-to-ports.js b/solutions/1687-delivering-boxes-from-storage-to-ports.js new file mode 100644 index 00000000..2a6a53e2 --- /dev/null +++ b/solutions/1687-delivering-boxes-from-storage-to-ports.js @@ -0,0 +1,59 @@ +/** + * 1687. Delivering Boxes from Storage to Ports + * https://leetcode.com/problems/delivering-boxes-from-storage-to-ports/ + * Difficulty: Hard + * + * You have the task of delivering some boxes from storage to their ports using only one ship. + * However, this ship has a limit on the number of boxes and the total weight that it can carry. + * + * You are given an array boxes, where boxes[i] = [portsi, weighti], and three integers + * portsCount, maxBoxes, and maxWeight. + * - portsi is the port where you need to deliver the ith box and weightsi is the weight of + * the ith box. + * - portsCount is the number of ports. + * - maxBoxes and maxWeight are the respective box and weight limits of the ship. + * + * The boxes need to be delivered in the order they are given. The ship will follow these steps: + * - The ship will take some number of boxes from the boxes queue, not violating the maxBoxes and + * maxWeight constraints. + * - For each loaded box in order, the ship will make a trip to the port the box needs to be + * delivered to and deliver it. If the ship is already at the correct port, no trip is needed, + * and the box can immediately be delivered. + * - The ship then makes a return trip to storage to take more boxes from the queue. + * + * The ship must end at storage after all the boxes have been delivered. + * + * Return the minimum number of trips the ship needs to make to deliver all boxes to their + * respective ports. + */ + +/** + * @param {number[][]} boxes + * @param {number} portsCount + * @param {number} maxBoxes + * @param {number} maxWeight + * @return {number} + */ +var boxDelivering = function(boxes, portsCount, maxBoxes, maxWeight) { + const n = boxes.length; + const minTrips = new Array(n + 1).fill(0); + let start = 0; + let portChanges = 0; + + for (let end = 0; end < n; end++) { + maxBoxes--; + maxWeight -= boxes[end][1]; + if (end > 0 && boxes[end][0] !== boxes[end - 1][0]) portChanges++; + + while (maxBoxes < 0 || maxWeight < 0 + || (start < end && minTrips[start + 1] === minTrips[start])) { + maxBoxes++; + maxWeight += boxes[start++][1]; + if (start > 0 && boxes[start][0] !== boxes[start - 1][0]) portChanges--; + } + + minTrips[end + 1] = portChanges + 2 + minTrips[start]; + } + + return minTrips[n]; +}; diff --git a/solutions/1688-count-of-matches-in-tournament.js b/solutions/1688-count-of-matches-in-tournament.js new file mode 100644 index 00000000..320b7376 --- /dev/null +++ b/solutions/1688-count-of-matches-in-tournament.js @@ -0,0 +1,22 @@ +/** + * 1688. Count of Matches in Tournament + * https://leetcode.com/problems/count-of-matches-in-tournament/ + * Difficulty: Easy + * + * You are given an integer n, the number of teams in a tournament that has strange rules: + * - If the current number of teams is even, each team gets paired with another team. A total + * of n / 2 matches are played, and n / 2 teams advance to the next round. + * - If the current number of teams is odd, one team randomly advances in the tournament, and + * the rest gets paired. A total of (n - 1) / 2 matches are played, and (n - 1) / 2 + 1 teams + * advance to the next round. + * + * Return the number of matches played in the tournament until a winner is decided. + */ + +/** + * @param {number} n + * @return {number} + */ +var numberOfMatches = function(n) { + return n - 1; +}; diff --git a/solutions/1689-partitioning-into-minimum-number-of-deci-binary-numbers.js b/solutions/1689-partitioning-into-minimum-number-of-deci-binary-numbers.js new file mode 100644 index 00000000..bae86a27 --- /dev/null +++ b/solutions/1689-partitioning-into-minimum-number-of-deci-binary-numbers.js @@ -0,0 +1,23 @@ +/** + * 1689. Partitioning Into Minimum Number Of Deci-Binary Numbers + * https://leetcode.com/problems/partitioning-into-minimum-number-of-deci-binary-numbers/ + * Difficulty: Medium + * + * A decimal number is called deci-binary if each of its digits is either 0 or 1 without any + * leading zeros. For example, 101 and 1100 are deci-binary, while 112 and 3001 are not. + * + * Given a string n that represents a positive decimal integer, return the minimum number of + * positive deci-binary numbers needed so that they sum up to n. + */ + +/** + * @param {string} n + * @return {number} + */ +var minPartitions = function(n) { + let maxDigit = 0; + for (const digit of n) { + maxDigit = Math.max(maxDigit, parseInt(digit)); + } + return maxDigit; +}; diff --git a/solutions/1690-stone-game-vii.js b/solutions/1690-stone-game-vii.js new file mode 100644 index 00000000..10591983 --- /dev/null +++ b/solutions/1690-stone-game-vii.js @@ -0,0 +1,43 @@ +/** + * 1690. Stone Game VII + * https://leetcode.com/problems/stone-game-vii/ + * Difficulty: Medium + * + * Alice and Bob take turns playing a game, with Alice starting first. + * + * There are n stones arranged in a row. On each player's turn, they can remove either the leftmost + * stone or the rightmost stone from the row and receive points equal to the sum of the remaining + * stones' values in the row. The winner is the one with the higher score when there are no stones + * left to remove. + * + * Bob found that he will always lose this game (poor Bob, he always loses), so he decided to + * minimize the score's difference. Alice's goal is to maximize the difference in the score. + * + * Given an array of integers stones where stones[i] represents the value of the ith stone from + * the left, return the difference in Alice and Bob's score if they both play optimally. + */ + +/** + * @param {number[]} stones + * @return {number} + */ +var stoneGameVII = function(stones) { + const n = stones.length; + const prefixSum = new Array(n + 1).fill(0); + const dp = new Array(n).fill().map(() => new Array(n).fill(0)); + + for (let i = 0; i < n; i++) { + prefixSum[i + 1] = prefixSum[i] + stones[i]; + } + + for (let len = 2; len <= n; len++) { + for (let start = 0; start <= n - len; start++) { + const end = start + len - 1; + const leftScore = prefixSum[end + 1] - prefixSum[start + 1] - dp[start + 1][end]; + const rightScore = prefixSum[end] - prefixSum[start] - dp[start][end - 1]; + dp[start][end] = Math.max(leftScore, rightScore); + } + } + + return dp[0][n - 1]; +}; diff --git a/solutions/1691-maximum-height-by-stacking-cuboids.js b/solutions/1691-maximum-height-by-stacking-cuboids.js new file mode 100644 index 00000000..0a1ee49d --- /dev/null +++ b/solutions/1691-maximum-height-by-stacking-cuboids.js @@ -0,0 +1,40 @@ +/** + * 1691. Maximum Height by Stacking Cuboids + * https://leetcode.com/problems/maximum-height-by-stacking-cuboids/ + * Difficulty: Hard + * + * Given n cuboids where the dimensions of the ith cuboid is cuboids[i] = [widthi, lengthi, heighti] + * (0-indexed). Choose a subset of cuboids and place them on each other. + * + * You can place cuboid i on cuboid j if widthi <= widthj and lengthi <= lengthj and + * heighti <= heightj. You can rearrange any cuboid's dimensions by rotating it to put it on + * another cuboid. + * + * Return the maximum height of the stacked cuboids. + */ + +/** + * @param {number[][]} cuboids + * @return {number} + */ +var maxHeight = function(cuboids) { + const sortedCuboids = cuboids.map(dim => dim.sort((a, b) => a - b)) + .sort((a, b) => a[0] - b[0] || a[1] - b[1] || a[2] - b[2]); + const n = sortedCuboids.length; + const maxHeights = new Array(n).fill(0); + let result = 0; + + for (let i = 0; i < n; i++) { + maxHeights[i] = sortedCuboids[i][2]; + for (let j = 0; j < i; j++) { + if (sortedCuboids[j][0] <= sortedCuboids[i][0] + && sortedCuboids[j][1] <= sortedCuboids[i][1] + && sortedCuboids[j][2] <= sortedCuboids[i][2]) { + maxHeights[i] = Math.max(maxHeights[i], maxHeights[j] + sortedCuboids[i][2]); + } + } + result = Math.max(result, maxHeights[i]); + } + + return result; +}; 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/1694-reformat-phone-number.js b/solutions/1694-reformat-phone-number.js new file mode 100644 index 00000000..0c6b6a87 --- /dev/null +++ b/solutions/1694-reformat-phone-number.js @@ -0,0 +1,46 @@ +/** + * 1694. Reformat Phone Number + * https://leetcode.com/problems/reformat-phone-number/ + * Difficulty: Easy + * + * You are given a phone number as a string number. number consists of digits, spaces ' ', + * and/or dashes '-'. + * + * You would like to reformat the phone number in a certain manner. Firstly, remove all spaces + * and dashes. Then, group the digits from left to right into blocks of length 3 until there + * are 4 or fewer digits. The final digits are then grouped as follows: + * - 2 digits: A single block of length 2. + * - 3 digits: A single block of length 3. + * - 4 digits: Two blocks of length 2 each. + * + * The blocks are then joined by dashes. Notice that the reformatting process should never produce + * any blocks of length 1 and produce at most two blocks of length 2. + * + * Return the phone number after formatting. + */ + +/** + * @param {string} number + * @return {string} + */ +var reformatNumber = function(number) { + const digits = number.replace(/[^0-9]/g, ''); + const blocks = []; + let i = 0; + + while (i < digits.length) { + const remaining = digits.length - i; + if (remaining > 4) { + blocks.push(digits.slice(i, i + 3)); + i += 3; + } else if (remaining === 4) { + blocks.push(digits.slice(i, i + 2), digits.slice(i + 2)); + break; + } else if (remaining === 2 || remaining === 3) { + blocks.push(digits.slice(i)); + break; + } + } + + return blocks.join('-'); +}; diff --git a/solutions/1695-maximum-erasure-value.js b/solutions/1695-maximum-erasure-value.js new file mode 100644 index 00000000..84ae73d4 --- /dev/null +++ b/solutions/1695-maximum-erasure-value.js @@ -0,0 +1,37 @@ +/** + * 1695. Maximum Erasure Value + * https://leetcode.com/problems/maximum-erasure-value/ + * Difficulty: Medium + * + * You are given an array of positive integers nums and want to erase a subarray containing unique + * elements. The score you get by erasing the subarray is equal to the sum of its elements. + * + * Return the maximum score you can get by erasing exactly one subarray. + * + * An array b is called to be a subarray of a if it forms a contiguous subsequence of a, that is, + * if it is equal to a[l],a[l+1],...,a[r] for some (l,r). + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maximumUniqueSubarray = function(nums) { + const seen = new Set(); + let result = 0; + let currentSum = 0; + let start = 0; + + for (let end = 0; end < nums.length; end++) { + while (seen.has(nums[end])) { + seen.delete(nums[start]); + currentSum -= nums[start]; + start++; + } + seen.add(nums[end]); + currentSum += nums[end]; + result = Math.max(result, currentSum); + } + + return result; +}; diff --git a/solutions/1696-jump-game-vi.js b/solutions/1696-jump-game-vi.js new file mode 100644 index 00000000..ad7922f3 --- /dev/null +++ b/solutions/1696-jump-game-vi.js @@ -0,0 +1,46 @@ +/** + * 1696. Jump Game VI + * https://leetcode.com/problems/jump-game-vi/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums and an integer k. + * + * You are initially standing at index 0. In one move, you can jump at most k steps forward without + * going outside the boundaries of the array. That is, you can jump from index i to any index in + * the range [i + 1, min(n - 1, i + k)] inclusive. + * + * You want to reach the last index of the array (index n - 1). Your score is the sum of all + * nums[j] for each index j you visited in the array. + * + * Return the maximum score you can get. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var maxResult = function(nums, k) { + const n = nums.length; + const maxScores = new Array(n).fill(-Infinity); + const deque = []; + + maxScores[0] = nums[0]; + deque.push(0); + + for (let i = 1; i < n; i++) { + while (deque.length && deque[0] < i - k) { + deque.shift(); + } + + maxScores[i] = nums[i] + maxScores[deque[0]]; + + while (deque.length && maxScores[i] >= maxScores[deque[deque.length - 1]]) { + deque.pop(); + } + + deque.push(i); + } + + return maxScores[n - 1]; +}; diff --git a/solutions/1697-checking-existence-of-edge-length-limited-paths.js b/solutions/1697-checking-existence-of-edge-length-limited-paths.js new file mode 100644 index 00000000..77fb4beb --- /dev/null +++ b/solutions/1697-checking-existence-of-edge-length-limited-paths.js @@ -0,0 +1,52 @@ +/** + * 1697. Checking Existence of Edge Length Limited Paths + * https://leetcode.com/problems/checking-existence-of-edge-length-limited-paths/ + * 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. + * + * Given an array queries, where queries[j] = [pj, qj, limitj], your task is to determine for each + * queries[j] whether there is a path between pj and qj such that each edge on the path has a + * distance strictly less than limitj. + * + * Return a boolean array answer, where answer.length == queries.length and the jth value of answer + * is true if there is a path for queries[j] is true, and false otherwise. + */ + +/** + * @param {number} n + * @param {number[][]} edgeList + * @param {number[][]} queries + * @return {boolean[]} + */ +var distanceLimitedPathsExist = function(n, edgeList, queries) { + const parent = new Array(n).fill().map((_, i) => i); + + edgeList.sort((a, b) => a[2] - b[2]); + const sortedQueries = queries.map((q, i) => [...q, i]).sort((a, b) => a[2] - b[2]); + const result = new Array(queries.length).fill(false); + + let edgeIndex = 0; + for (const [p, q, limit, index] of sortedQueries) { + while (edgeIndex < edgeList.length && edgeList[edgeIndex][2] < limit) { + union(edgeList[edgeIndex][0], edgeList[edgeIndex][1]); + edgeIndex++; + } + result[index] = find(p) === find(q); + } + + return result; + + function find(x) { + if (parent[x] !== x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + function union(x, y) { + parent[find(x)] = find(y); + } +}; 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/1700-number-of-students-unable-to-eat-lunch.js b/solutions/1700-number-of-students-unable-to-eat-lunch.js new file mode 100644 index 00000000..c56df9c2 --- /dev/null +++ b/solutions/1700-number-of-students-unable-to-eat-lunch.js @@ -0,0 +1,44 @@ +/** + * 1700. Number of Students Unable to Eat Lunch + * https://leetcode.com/problems/number-of-students-unable-to-eat-lunch/ + * Difficulty: Easy + * + * The school cafeteria offers circular and square sandwiches at lunch break, referred to by + * numbers 0 and 1 respectively. All students stand in a queue. Each student either prefers + * square or circular sandwiches. + * + * The number of sandwiches in the cafeteria is equal to the number of students. The sandwiches + * are placed in a stack. At each step: + * - If the student at the front of the queue prefers the sandwich on the top of the stack, they + * will take it and leave the queue. + * - Otherwise, they will leave it and go to the queue's end. + * + * This continues until none of the queue students want to take the top sandwich and are thus + * unable to eat. + * + * You are given two integer arrays students and sandwiches where sandwiches[i] is the type of + * the ith sandwich in the stack (i = 0 is the top of the stack) and students[j] is the + * preference of the jth student in the initial queue (j = 0 is the front of the queue). + * Return the number of students that are unable to eat. + */ + +/** + * @param {number[]} students + * @param {number[]} sandwiches + * @return {number} + */ +var countStudents = function(students, sandwiches) { + const preferenceCount = [0, 0]; + for (const pref of students) { + preferenceCount[pref]++; + } + + for (const sandwich of sandwiches) { + if (preferenceCount[sandwich] === 0) { + return preferenceCount[0] + preferenceCount[1]; + } + preferenceCount[sandwich]--; + } + + return 0; +}; diff --git a/solutions/1701-average-waiting-time.js b/solutions/1701-average-waiting-time.js new file mode 100644 index 00000000..e8347499 --- /dev/null +++ b/solutions/1701-average-waiting-time.js @@ -0,0 +1,37 @@ +/** + * 1701. Average Waiting Time + * https://leetcode.com/problems/average-waiting-time/ + * Difficulty: Medium + * + * There is a restaurant with a single chef. You are given an array customers, where + * customers[i] = [arrivali, timei]: + * - arrivali is the arrival time of the ith customer. The arrival times are sorted in + * non-decreasing order. + * - timei is the time needed to prepare the order of the ith customer. + * + * When a customer arrives, he gives the chef his order, and the chef starts preparing it once + * he is idle. The customer waits till the chef finishes preparing his order. The chef does not + * prepare food for more than one customer at a time. The chef prepares food for customers in + * the order they were given in the input. + * + * Return the average waiting time of all customers. Solutions within 10-5 from the actual + * answer are considered accepted. + */ + +/** + * @param {number[][]} customers + * @return {number} + */ +var averageWaitingTime = function(customers) { + let totalWait = 0; + let currentTime = 0; + + for (const [arrival, prepTime] of customers) { + const startTime = Math.max(arrival, currentTime); + const finishTime = startTime + prepTime; + totalWait += finishTime - arrival; + currentTime = finishTime; + } + + return totalWait / customers.length; +}; diff --git a/solutions/1702-maximum-binary-string-after-change.js b/solutions/1702-maximum-binary-string-after-change.js new file mode 100644 index 00000000..f888eb99 --- /dev/null +++ b/solutions/1702-maximum-binary-string-after-change.js @@ -0,0 +1,40 @@ +/** + * 1702. Maximum Binary String After Change + * https://leetcode.com/problems/maximum-binary-string-after-change/ + * Difficulty: Medium + * + * You are given a binary string binary consisting of only 0's or 1's. You can apply each of + * the following operations any number of times: + * - Operation 1: If the number contains the substring "00", you can replace it with "10". + * - For example, "00010" -> "10010" + * - Operation 2: If the number contains the substring "10", you can replace it with "01". + * - For example, "00010" -> "00001" + * + * Return the maximum binary string you can obtain after any number of operations. Binary + * string x is greater than binary string y if x's decimal representation is greater than + * y's decimal representation. + */ + +/** + * @param {string} binary + * @return {string} + */ +var maximumBinaryString = function(binary) { + const n = binary.length; + let zeroCount = 0; + let firstZero = -1; + + for (let i = 0; i < n; i++) { + if (binary[i] === '0') { + if (firstZero === -1) firstZero = i; + zeroCount++; + } + } + + if (zeroCount <= 1) return binary; + + const result = new Array(n).fill('1'); + result[firstZero + zeroCount - 1] = '0'; + + return result.join(''); +}; diff --git a/solutions/1703-minimum-adjacent-swaps-for-k-consecutive-ones.js b/solutions/1703-minimum-adjacent-swaps-for-k-consecutive-ones.js new file mode 100644 index 00000000..cb5687c9 --- /dev/null +++ b/solutions/1703-minimum-adjacent-swaps-for-k-consecutive-ones.js @@ -0,0 +1,43 @@ +/** + * 1703. Minimum Adjacent Swaps for K Consecutive Ones + * https://leetcode.com/problems/minimum-adjacent-swaps-for-k-consecutive-ones/ + * Difficulty: Hard + * + * You are given an integer array, nums, and an integer k. nums comprises of only 0's and 1's. In + * one move, you can choose two adjacent indices and swap their values. + * + * Return the minimum number of moves required so that nums has k consecutive 1's. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minMoves = function(nums, k) { + const ones = []; + for (let i = 0; i < nums.length; i++) { + if (nums[i] === 1) ones.push(i); + } + + const prefixSum = [0]; + for (let i = 0; i < ones.length; i++) { + prefixSum.push(prefixSum[i] + ones[i]); + } + + let minSwaps = Infinity; + for (let i = 0; i <= ones.length - k; i++) { + const j = i + k - 1; + const mid = i + Math.floor(k / 2); + const target = ones[mid]; + const leftCount = mid - i; + const rightCount = j - mid; + const leftSum = prefixSum[mid] - prefixSum[i]; + const rightSum = prefixSum[j + 1] - prefixSum[mid + 1]; + const swaps = (target * leftCount - leftSum) + (rightSum - target * rightCount); + minSwaps = Math.min(minSwaps, swaps); + } + + const medianAdjust = Math.floor(k / 2) * Math.ceil(k / 2); + return minSwaps - medianAdjust; +}; diff --git a/solutions/1704-determine-if-string-halves-are-alike.js b/solutions/1704-determine-if-string-halves-are-alike.js new file mode 100644 index 00000000..e2734c96 --- /dev/null +++ b/solutions/1704-determine-if-string-halves-are-alike.js @@ -0,0 +1,31 @@ +/** + * 1704. Determine if String Halves Are Alike + * https://leetcode.com/problems/determine-if-string-halves-are-alike/ + * Difficulty: Easy + * + * You are given a string s of even length. Split this string into two halves of equal lengths, + * and let a be the first half and b be the second half. + * + * Two strings are alike if they have the same number of vowels ('a', 'e', 'i', 'o', 'u', 'A', + * 'E', 'I', 'O', 'U'). Notice that s contains uppercase and lowercase letters. + * + * Return true if a and b are alike. Otherwise, return false. + */ + +/** + * @param {string} s + * @return {boolean} + */ +var halvesAreAlike = function(s) { + const vowels = new Set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']); + let firstHalfVowels = 0; + let secondHalfVowels = 0; + const mid = s.length / 2; + + for (let i = 0; i < mid; i++) { + if (vowels.has(s[i])) firstHalfVowels++; + if (vowels.has(s[i + mid])) secondHalfVowels++; + } + + return firstHalfVowels === secondHalfVowels; +}; diff --git a/solutions/1705-maximum-number-of-eaten-apples.js b/solutions/1705-maximum-number-of-eaten-apples.js new file mode 100644 index 00000000..8457f613 --- /dev/null +++ b/solutions/1705-maximum-number-of-eaten-apples.js @@ -0,0 +1,50 @@ +/** + * 1705. Maximum Number of Eaten Apples + * https://leetcode.com/problems/maximum-number-of-eaten-apples/ + * Difficulty: Medium + * + * There is a special kind of apple tree that grows apples every day for n days. On the ith day, + * the tree grows apples[i] apples that will rot after days[i] days, that is on day i + days[i] + * the apples will be rotten and cannot be eaten. On some days, the apple tree does not grow any + * apples, which are denoted by apples[i] == 0 and days[i] == 0. + * + * You decided to eat at most one apple a day (to keep the doctors away). Note that you can keep + * eating after the first n days. + * + * Given two integer arrays days and apples of length n, return the maximum number of apples you + * can eat. + */ + +/** + * @param {number[]} apples + * @param {number[]} days + * @return {number} + */ +var eatenApples = function(apples, days) { + const expiryCounts = new Array(40001).fill(0); + let result = 0; + let earliestExpiry = Infinity; + let maxExpiry = apples.length; + + for (let day = 0; day <= maxExpiry; day++) { + if (earliestExpiry < day) earliestExpiry = day; + + if (day < apples.length && apples[day]) { + const expiry = day + days[day] - 1; + expiryCounts[expiry] += apples[day]; + earliestExpiry = Math.min(expiry, earliestExpiry); + maxExpiry = Math.max(expiry, maxExpiry); + } + + while (!expiryCounts[earliestExpiry] && earliestExpiry < maxExpiry) { + earliestExpiry++; + } + + if (expiryCounts[earliestExpiry]) { + result++; + expiryCounts[earliestExpiry]--; + } + } + + return result; +}; diff --git a/solutions/1706-where-will-the-ball-fall.js b/solutions/1706-where-will-the-ball-fall.js new file mode 100644 index 00000000..296e3d94 --- /dev/null +++ b/solutions/1706-where-will-the-ball-fall.js @@ -0,0 +1,54 @@ +/** + * 1706. Where Will the Ball Fall + * https://leetcode.com/problems/where-will-the-ball-fall/ + * Difficulty: Medium + * + * You have a 2-D grid of size m x n representing a box, and you have n balls. The box is open on + * the top and bottom sides. + * + * Each cell in the box has a diagonal board spanning two corners of the cell that can redirect a + * ball to the right or to the left. + * - A board that redirects the ball to the right spans the top-left corner to the bottom-right + * corner and is represented in the grid as 1. + * - A board that redirects the ball to the left spans the top-right corner to the bottom-left + * corner and is represented in the grid as -1. + * + * We drop one ball at the top of each column of the box. Each ball can get stuck in the box or fall + * out of the bottom. A ball gets stuck if it hits a "V" shaped pattern between two boards or if a + * board redirects the ball into either wall of the box. + * + * Return an array answer of size n where answer[i] is the column that the ball falls out of at the + * bottom after dropping the ball from the ith column at the top, or -1 if the ball gets stuck in + * the box. + */ + +/** + * @param {number[][]} grid + * @return {number[]} + */ +var findBall = function(grid) { + const m = grid.length; + const n = grid[0].length; + const result = new Array(n); + + for (let col = 0; col < n; col++) { + let currentCol = col; + let row = 0; + + while (row < m) { + const nextCol = currentCol + grid[row][currentCol]; + + if (nextCol < 0 || nextCol >= n || grid[row][currentCol] !== grid[row][nextCol]) { + currentCol = -1; + break; + } + + currentCol = nextCol; + row++; + } + + result[col] = currentCol; + } + + return result; +}; diff --git a/solutions/1707-maximum-xor-with-an-element-from-array.js b/solutions/1707-maximum-xor-with-an-element-from-array.js new file mode 100644 index 00000000..4fb40d17 --- /dev/null +++ b/solutions/1707-maximum-xor-with-an-element-from-array.js @@ -0,0 +1,59 @@ +/** + * 1707. Maximum XOR With an Element From Array + * https://leetcode.com/problems/maximum-xor-with-an-element-from-array/ + * Difficulty: Hard + * + * You are given an array nums consisting of non-negative integers. You are also given a queries + * array, where queries[i] = [xi, mi]. + * + * The answer to the ith query is the maximum bitwise XOR value of xi and any element of nums that + * does not exceed mi. In other words, the answer is max(nums[j] XOR xi) for all j such that + * nums[j] <= mi. If all elements in nums are larger than mi, then the answer is -1. + * + * Return an integer array answer where answer.length == queries.length and answer[i] is the + * answer to the ith query. + */ + +/** + * @param {number[]} nums + * @param {number[][]} queries + * @return {number[]} + */ +var maximizeXor = function(nums, queries) { + nums.sort((a, b) => a - b); + const sortedQueries = queries.map((q, i) => [q[0], q[1], i]).sort((a, b) => a[1] - b[1]); + const result = new Array(queries.length).fill(-1); + + const trie = {}; + let numIndex = 0; + + for (const [x, m, queryIndex] of sortedQueries) { + while (numIndex < nums.length && nums[numIndex] <= m) { + let node = trie; + for (let bit = 30; bit >= 0; bit--) { + const bitValue = (nums[numIndex] >> bit) & 1; + if (!node[bitValue]) node[bitValue] = {}; + node = node[bitValue]; + } + numIndex++; + } + + if (numIndex === 0) continue; + + let maxXor = 0; + let node = trie; + for (let bit = 30; bit >= 0; bit--) { + const bitValue = (x >> bit) & 1; + const oppositeBit = bitValue ^ 1; + if (node[oppositeBit]) { + maxXor |= (1 << bit); + node = node[oppositeBit]; + } else { + node = node[bitValue]; + } + } + result[queryIndex] = maxXor; + } + + return result; +}; 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/1710-maximum-units-on-a-truck.js b/solutions/1710-maximum-units-on-a-truck.js new file mode 100644 index 00000000..5ca9d066 --- /dev/null +++ b/solutions/1710-maximum-units-on-a-truck.js @@ -0,0 +1,36 @@ +/** + * 1710. Maximum Units on a Truck + * https://leetcode.com/problems/maximum-units-on-a-truck/ + * Difficulty: Easy + * + * You are assigned to put some amount of boxes onto one truck. You are given a 2D array + * boxTypes, where boxTypes[i] = [numberOfBoxesi, numberOfUnitsPerBoxi]: + * - numberOfBoxesi is the number of boxes of type i. + * - numberOfUnitsPerBoxi is the number of units in each box of the type i. + * + * You are also given an integer truckSize, which is the maximum number of boxes that can be + * put on the truck. You can choose any boxes to put on the truck as long as the number of + * boxes does not exceed truckSize. + * + * Return the maximum total number of units that can be put on the truck. + */ + +/** + * @param {number[][]} boxTypes + * @param {number} truckSize + * @return {number} + */ +var maximumUnits = function(boxTypes, truckSize) { + boxTypes.sort((a, b) => b[1] - a[1]); + let result = 0; + let remainingBoxes = truckSize; + + for (const [count, units] of boxTypes) { + const boxesToTake = Math.min(count, remainingBoxes); + result += boxesToTake * units; + remainingBoxes -= boxesToTake; + if (remainingBoxes === 0) break; + } + + return result; +}; diff --git a/solutions/1711-count-good-meals.js b/solutions/1711-count-good-meals.js new file mode 100644 index 00000000..870cc7dd --- /dev/null +++ b/solutions/1711-count-good-meals.js @@ -0,0 +1,39 @@ +/** + * 1711. Count Good Meals + * https://leetcode.com/problems/count-good-meals/ + * Difficulty: Medium + * + * A good meal is a meal that contains exactly two different food items with a sum of deliciousness + * equal to a power of two. + * + * You can pick any two different foods to make a good meal. + * + * Given an array of integers deliciousness where deliciousness[i] is the deliciousness of the + * ith item of food, return the number of different good meals you can make from this list + * modulo 109 + 7. + * + * Note that items with different indices are considered different even if they have the same + * deliciousness value. + */ + +/** + * @param {number[]} deliciousness + * @return {number} + */ +var countPairs = function(deliciousness) { + const MOD = 1e9 + 7; + const frequency = new Map(); + let result = 0; + + for (const value of deliciousness) { + for (let power = 1; power <= 1 << 21; power <<= 1) { + const complement = power - value; + if (frequency.has(complement)) { + result = (result + frequency.get(complement)) % MOD; + } + } + frequency.set(value, (frequency.get(value) || 0) + 1); + } + + return result; +}; diff --git a/solutions/1712-ways-to-split-array-into-three-subarrays.js b/solutions/1712-ways-to-split-array-into-three-subarrays.js new file mode 100644 index 00000000..d6eaf44c --- /dev/null +++ b/solutions/1712-ways-to-split-array-into-three-subarrays.js @@ -0,0 +1,76 @@ +/** + * 1712. Ways to Split Array Into Three Subarrays + * https://leetcode.com/problems/ways-to-split-array-into-three-subarrays/ + * Difficulty: Medium + * + * A split of an integer array is good if: + * - The array is split into three non-empty contiguous subarrays - named left, mid, right + * respectively from left to right. + * - The sum of the elements in left is less than or equal to the sum of the elements in mid, + * and the sum of the elements in mid is less than or equal to the sum of the elements in right. + * + * Given nums, an array of non-negative integers, return the number of good ways to split nums. + * As the number may be too large, return it modulo 109 + 7. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var waysToSplit = function(nums) { + const MOD = 1e9 + 7; + const n = nums.length; + const prefixSum = new Array(n).fill(0); + + prefixSum[0] = nums[0]; + for (let i = 1; i < n; i++) { + prefixSum[i] = prefixSum[i - 1] + nums[i]; + } + + let splitCount = 0; + for (let i = 0; i < n - 2; i++) { + let left = i + 1; + let right = n - 2; + let validStart = -1; + let validEnd = -1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + const leftSum = prefixSum[i]; + const midSum = prefixSum[mid] - prefixSum[i]; + const rightSum = prefixSum[n - 1] - prefixSum[mid]; + + if (leftSum <= midSum && midSum <= rightSum) { + validStart = mid; + right = mid - 1; + } else if (leftSum > midSum) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + left = validStart === -1 ? n - 1 : validStart; + right = n - 2; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + const leftSum = prefixSum[i]; + const midSum = prefixSum[mid] - prefixSum[i]; + const rightSum = prefixSum[n - 1] - prefixSum[mid]; + + if (leftSum <= midSum && midSum <= rightSum) { + validEnd = mid; + left = mid + 1; + } else { + right = mid - 1; + } + } + + if (validStart !== -1 && validEnd !== -1 && validStart <= validEnd) { + splitCount = (splitCount + validEnd - validStart + 1) % MOD; + } + } + + return splitCount; +}; diff --git a/solutions/1713-minimum-operations-to-make-a-subsequence.js b/solutions/1713-minimum-operations-to-make-a-subsequence.js new file mode 100644 index 00000000..245e0eac --- /dev/null +++ b/solutions/1713-minimum-operations-to-make-a-subsequence.js @@ -0,0 +1,57 @@ +/** + * 1713. Minimum Operations to Make a Subsequence + * https://leetcode.com/problems/minimum-operations-to-make-a-subsequence/ + * Difficulty: Hard + * + * You are given an array target that consists of distinct integers and another integer array + * arr that can have duplicates. + * + * In one operation, you can insert any integer at any position in arr. For example, if + * arr = [1,4,1,2], you can add 3 in the middle and make it [1,4,3,1,2]. Note that you can + * insert the integer at the very beginning or end of the array. + * + * Return the minimum number of operations needed to make target a subsequence of arr. + * + * A subsequence of an array is a new array generated from the original array by deleting some + * elements (possibly none) without changing the remaining elements' relative order. For + * example, [2,7,4] is a subsequence of [4,2,3,7,2,1,4] (the underlined elements), + * while [2,4,2] is not. + */ + +/** + * @param {number[]} target + * @param {number[]} arr + * @return {number} + */ +var minOperations = function(target, arr) { + const valueToIndex = new Map(target.map((val, i) => [val, i])); + const sequence = arr.filter(val => valueToIndex.has(val)).map(val => valueToIndex.get(val)); + + const lis = []; + for (const index of sequence) { + const pos = binarySearch(lis, index); + if (pos === lis.length) { + lis.push(index); + } else { + lis[pos] = index; + } + } + + return target.length - lis.length; +}; + +function binarySearch(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/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/1717-maximum-score-from-removing-substrings.js b/solutions/1717-maximum-score-from-removing-substrings.js new file mode 100644 index 00000000..75bae662 --- /dev/null +++ b/solutions/1717-maximum-score-from-removing-substrings.js @@ -0,0 +1,52 @@ +/** + * 1717. Maximum Score From Removing Substrings + * https://leetcode.com/problems/maximum-score-from-removing-substrings/ + * Difficulty: Medium + * + * You are given a string s and two integers x and y. You can perform two types of operations + * any number of times. + * + * - Remove substring "ab" and gain x points. + * - For example, when removing "ab" from "cabxbae" it becomes "cxbae". + * - Remove substring "ba" and gain y points. + * - For example, when removing "ba" from "cabxbae" it becomes "cabxe". + * + * Return the maximum points you can gain after applying the above operations on s. + */ + +/** + * @param {string} s + * @param {number} x + * @param {number} y + * @return {number} + */ +var maximumGain = function(s, x, y) { + let result = 0; + const stack = []; + + const [primary, secondary, primaryScore, secondaryScore] = x >= y + ? ['ab', 'ba', x, y] + : ['ba', 'ab', y, x]; + + for (const char of s) { + if (stack.length && stack[stack.length - 1] === primary[0] && char === primary[1]) { + stack.pop(); + result += primaryScore; + } else { + stack.push(char); + } + } + + const remaining = []; + for (const char of stack) { + if (remaining.length && remaining[remaining.length - 1] === secondary[0] + && char === secondary[1]) { + remaining.pop(); + result += secondaryScore; + } else { + remaining.push(char); + } + } + + return result; +}; diff --git a/solutions/1719-number-of-ways-to-reconstruct-a-tree.js b/solutions/1719-number-of-ways-to-reconstruct-a-tree.js new file mode 100644 index 00000000..9e1347d4 --- /dev/null +++ b/solutions/1719-number-of-ways-to-reconstruct-a-tree.js @@ -0,0 +1,76 @@ +/** + * 1719. Number Of Ways To Reconstruct A Tree + * https://leetcode.com/problems/number-of-ways-to-reconstruct-a-tree/ + * Difficulty: Hard + * + * You are given an array pairs, where pairs[i] = [xi, yi], and: + * - There are no duplicates. + * - xi < yi + * + * Let ways be the number of rooted trees that satisfy the following conditions: + * - The tree consists of nodes whose values appeared in pairs. + * - A pair [xi, yi] exists in pairs if and only if xi is an ancestor of yi or yi is + * an ancestor of xi. + * - Note: the tree does not have to be a binary tree. + * + * Two ways are considered to be different if there is at least one node that has different + * parents in both ways. + * + * Return: + * - 0 if ways == 0 + * - 1 if ways == 1 + * - 2 if ways > 1 + * + * A rooted tree is a tree that has a single root node, and all edges are oriented to be + * outgoing from the root. + * + * An ancestor of a node is any node on the path from the root to that node (excluding + * the node itself). The root has no ancestors. + */ + +/** + * @param {number[][]} pairs + * @return {number} + */ +var checkWays = function(pairs) { + const graph = new Map(); + for (const [x, y] of pairs) { + if (!graph.has(x)) graph.set(x, new Set()); + if (!graph.has(y)) graph.set(y, new Set()); + graph.get(x).add(y); + graph.get(y).add(x); + } + + const nodes = [...graph.keys()].sort((a, b) => graph.get(b).size - graph.get(a).size); + const n = nodes.length; + if (n === 1) return 1; + + const root = nodes[0]; + if (graph.get(root).size !== n - 1) return 0; + + let equalDegreeCount = 0; + for (let i = 1; i < n; i++) { + const node = nodes[i]; + let found = false; + + for (let j = i - 1; j >= 0; j--) { + const ancestor = nodes[j]; + if (graph.get(node).has(ancestor)) { + for (const neighbor of graph.get(node)) { + if (neighbor !== ancestor && !graph.get(ancestor).has(neighbor)) { + return 0; + } + } + if (graph.get(node).size === graph.get(ancestor).size) { + equalDegreeCount++; + } + found = true; + break; + } + } + + if (!found) return 0; + } + + return equalDegreeCount > 0 ? 2 : 1; +}; diff --git a/solutions/1720-decode-xored-array.js b/solutions/1720-decode-xored-array.js new file mode 100644 index 00000000..404073f1 --- /dev/null +++ b/solutions/1720-decode-xored-array.js @@ -0,0 +1,30 @@ +/** + * 1720. Decode XORed Array + * https://leetcode.com/problems/decode-xored-array/ + * Difficulty: Easy + * + * There is a hidden integer array arr that consists of n non-negative integers. + * + * It was encoded into another integer array encoded of length n - 1, such that + * encoded[i] = arr[i] XOR arr[i + 1]. For example, if arr = [1,0,2,1], then encoded = [1,2,3]. + * + * You are given the encoded array. You are also given an integer first, that is the first + * element of arr, i.e. arr[0]. + * + * Return the original array arr. It can be proved that the answer exists and is unique. + */ + +/** + * @param {number[]} encoded + * @param {number} first + * @return {number[]} + */ +var decode = function(encoded, first) { + const result = [first]; + + for (let i = 0; i < encoded.length; i++) { + result.push(result[i] ^ encoded[i]); + } + + return result; +}; diff --git a/solutions/1721-swapping-nodes-in-a-linked-list.js b/solutions/1721-swapping-nodes-in-a-linked-list.js new file mode 100644 index 00000000..4ec44bd7 --- /dev/null +++ b/solutions/1721-swapping-nodes-in-a-linked-list.js @@ -0,0 +1,42 @@ +/** + * 1721. Swapping Nodes in a Linked List + * https://leetcode.com/problems/swapping-nodes-in-a-linked-list/ + * Difficulty: Medium + * + * You are given the head of a linked list, and an integer k. + * + * Return the head of the linked list after swapping the values of the kth node from the beginning + * and the kth node from the end (the list is 1-indexed). + */ + +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} head + * @param {number} k + * @return {ListNode} + */ +var swapNodes = function(head, k) { + let firstNode = head; + for (let i = 1; i < k; i++) { + firstNode = firstNode.next; + } + + let slow = head; + let secondNode = firstNode.next; + while (secondNode) { + slow = slow.next; + secondNode = secondNode.next; + } + + const temp = firstNode.val; + firstNode.val = slow.val; + slow.val = temp; + + return head; +}; diff --git a/solutions/1722-minimize-hamming-distance-after-swap-operations.js b/solutions/1722-minimize-hamming-distance-after-swap-operations.js new file mode 100644 index 00000000..9abe3150 --- /dev/null +++ b/solutions/1722-minimize-hamming-distance-after-swap-operations.js @@ -0,0 +1,71 @@ +/** + * 1722. Minimize Hamming Distance After Swap Operations + * https://leetcode.com/problems/minimize-hamming-distance-after-swap-operations/ + * Difficulty: Medium + * + * You are given two integer arrays, source and target, both of length n. You are also given an + * array allowedSwaps where each allowedSwaps[i] = [ai, bi] indicates that you are allowed to + * swap the elements at index ai and index bi (0-indexed) of array source. Note that you can + * swap elements at a specific pair of indices multiple times and in any order. + * + * The Hamming distance of two arrays of the same length, source and target, is the number of + * positions where the elements are different. Formally, it is the number of indices i for + * 0 <= i <= n-1 where source[i] != target[i] (0-indexed). + * + * Return the minimum Hamming distance of source and target after performing any amount of swap + * operations on array source. + */ + +/** + * @param {number[]} source + * @param {number[]} target + * @param {number[][]} allowedSwaps + * @return {number} + */ +var minimumHammingDistance = function(source, target, allowedSwaps) { + const n = source.length; + const parent = new Array(n).fill().map((_, i) => i); + + for (const [a, b] of allowedSwaps) { + union(a, b); + } + + const groups = new Map(); + for (let i = 0; i < n; i++) { + const root = find(i); + if (!groups.has(root)) { + groups.set(root, { source: [], target: [] }); + } + groups.get(root).source.push(source[i]); + groups.get(root).target.push(target[i]); + } + + let result = 0; + for (const { source, target } of groups.values()) { + const sourceCount = new Map(); + for (const num of source) { + sourceCount.set(num, (sourceCount.get(num) || 0) + 1); + } + for (const num of target) { + const count = sourceCount.get(num) || 0; + if (count === 0) { + result++; + } else { + sourceCount.set(num, count - 1); + } + } + } + + return result; + + function find(x) { + if (parent[x] !== x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + function union(x, y) { + parent[find(x)] = find(y); + } +}; diff --git a/solutions/1723-find-minimum-time-to-finish-all-jobs.js b/solutions/1723-find-minimum-time-to-finish-all-jobs.js new file mode 100644 index 00000000..c5624ffb --- /dev/null +++ b/solutions/1723-find-minimum-time-to-finish-all-jobs.js @@ -0,0 +1,50 @@ +/** + * 1723. Find Minimum Time to Finish All Jobs + * https://leetcode.com/problems/find-minimum-time-to-finish-all-jobs/ + * Difficulty: Hard + * + * You are given an integer array jobs, where jobs[i] is the amount of time it takes to complete + * the ith job. + * + * There are k workers that you can assign jobs to. Each job should be assigned to exactly one + * worker. The working time of a worker is the sum of the time it takes to complete all jobs + * assigned to them. Your goal is to devise an optimal assignment such that the maximum working + * time of any worker is minimized. + * + * Return the minimum possible maximum working time of any assignment. + */ + +/** + * @param {number[]} jobs + * @param {number} k + * @return {number} + */ +var minimumTimeRequired = function(jobs, k) { + const n = jobs.length; + const workerTimes = new Array(k).fill(0); + let result = Infinity; + + jobs.sort((a, b) => b - a); + backtrack(0, 0); + + return result; + + function backtrack(jobIndex, maxTime) { + if (jobIndex === n) { + result = Math.min(result, maxTime); + return; + } + + if (maxTime >= result) return; + + for (let i = 0; i < k; i++) { + if (workerTimes[i] + jobs[jobIndex] >= result) continue; + + workerTimes[i] += jobs[jobIndex]; + backtrack(jobIndex + 1, Math.max(maxTime, workerTimes[i])); + workerTimes[i] -= jobs[jobIndex]; + + if (workerTimes[i] === 0) break; + } + } +}; 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/1725-number-of-rectangles-that-can-form-the-largest-square.js b/solutions/1725-number-of-rectangles-that-can-form-the-largest-square.js new file mode 100644 index 00000000..63d92c44 --- /dev/null +++ b/solutions/1725-number-of-rectangles-that-can-form-the-largest-square.js @@ -0,0 +1,38 @@ +/** + * 1725. Number Of Rectangles That Can Form The Largest Square + * https://leetcode.com/problems/number-of-rectangles-that-can-form-the-largest-square/ + * Difficulty: Easy + * + * You are given an array rectangles where rectangles[i] = [li, wi] represents the ith rectangle + * of length li and width wi. + * + * You can cut the ith rectangle to form a square with a side length of k if both k <= li and + * k <= wi. For example, if you have a rectangle [4,6], you can cut it to get a square with a + * side length of at most 4. + * + * Let maxLen be the side length of the largest square you can obtain from any of the given + * rectangles. + * + * Return the number of rectangles that can make a square with a side length of maxLen. + */ + +/** + * @param {number[][]} rectangles + * @return {number} + */ +var countGoodRectangles = function(rectangles) { + let maxSide = 0; + let result = 0; + + for (const [length, width] of rectangles) { + const side = Math.min(length, width); + if (side > maxSide) { + maxSide = side; + result = 1; + } else if (side === maxSide) { + result++; + } + } + + return result; +}; diff --git a/solutions/1727-largest-submatrix-with-rearrangements.js b/solutions/1727-largest-submatrix-with-rearrangements.js new file mode 100644 index 00000000..2c3e36db --- /dev/null +++ b/solutions/1727-largest-submatrix-with-rearrangements.js @@ -0,0 +1,37 @@ +/** + * 1727. Largest Submatrix With Rearrangements + * https://leetcode.com/problems/largest-submatrix-with-rearrangements/ + * Difficulty: Medium + * + * You are given a binary matrix matrix of size m x n, and you are allowed to rearrange the + * columns of the matrix in any order. + * + * Return the area of the largest submatrix within matrix where every element of the submatrix + * is 1 after reordering the columns optimally. + */ + +/** + * @param {number[][]} matrix + * @return {number} + */ +var largestSubmatrix = function(matrix) { + const rows = matrix.length; + const cols = matrix[0].length; + let result = 0; + + for (let row = 0; row < rows; row++) { + for (let col = 0; col < cols; col++) { + if (row > 0 && matrix[row][col] === 1) { + matrix[row][col] += matrix[row - 1][col]; + } + } + + const heights = matrix[row].slice().sort((a, b) => b - a); + for (let i = 0; i < cols; i++) { + if (heights[i] === 0) break; + result = Math.max(result, heights[i] * (i + 1)); + } + } + + return result; +}; diff --git a/solutions/1728-cat-and-mouse-ii.js b/solutions/1728-cat-and-mouse-ii.js new file mode 100644 index 00000000..32eecafa --- /dev/null +++ b/solutions/1728-cat-and-mouse-ii.js @@ -0,0 +1,107 @@ +/** + * 1728. Cat and Mouse II + * https://leetcode.com/problems/cat-and-mouse-ii/ + * Difficulty: Hard + * + * A game is played by a cat and a mouse named Cat and Mouse. + * + * The environment is represented by a grid of size rows x cols, where each element is a wall, + * floor, player (Cat, Mouse), or food. + * - Players are represented by the characters 'C'(Cat),'M'(Mouse). + * - Floors are represented by the character '.' and can be walked on. + * - Walls are represented by the character '#' and cannot be walked on. + * - Food is represented by the character 'F' and can be walked on. + * - There is only one of each character 'C', 'M', and 'F' in grid. + * + * Mouse and Cat play according to the following rules: + * - Mouse moves first, then they take turns to move. + * - During each turn, Cat and Mouse can jump in one of the four directions (left, right, up, down). + * They cannot jump over the wall nor outside of the grid. + * - catJump, mouseJump are the maximum lengths Cat and Mouse can jump at a time, respectively. + * Cat and Mouse can jump less than the maximum length. + * - Staying in the same position is allowed. + * - Mouse can jump over Cat. + * + * The game can end in 4 ways: + * - If Cat occupies the same position as Mouse, Cat wins. + * - If Cat reaches the food first, Cat wins. + * - If Mouse reaches the food first, Mouse wins. + * - If Mouse cannot get to the food within 1000 turns, Cat wins. + * + * Given a rows x cols matrix grid and two integers catJump and mouseJump, return true if Mouse + * can win the game if both Cat and Mouse play optimally, otherwise return false. + */ + +/** + * @param {string[]} grid + * @param {number} catJump + * @param {number} mouseJump + * @return {boolean} + */ +var canMouseWin = function(grid, catJump, mouseJump) { + if (typeof grid === 'string') grid = [grid]; + const rows = grid.length; + const cols = grid[0].length; + const dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]]; + let mouse; + let cat; + let food; + let available = 0; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + const cell = grid[i][j]; + if (cell !== '#') available++; + if (cell === 'M') mouse = [i, j]; + else if (cell === 'C') cat = [i, j]; + else if (cell === 'F') food = [i, j]; + } + } + + const memo = new Map(); + + return canWin(0, mouse, cat); + + function getKey(turn, [mr, mc], [cr, cc]) { + return `${turn},${mr},${mc},${cr},${cc}`; + } + + function isValid(r, c) { + return r >= 0 && r < rows && c >= 0 && c < cols && grid[r][c] !== '#'; + } + + function canWin(turn, mousePos, catPos) { + if (turn >= available * 2) return false; + + const key = getKey(turn, mousePos, catPos); + if (memo.has(key)) return memo.get(key); + + const isMouseTurn = turn % 2 === 0; + const [r, c] = isMouseTurn ? mousePos : catPos; + const maxJump = isMouseTurn ? mouseJump : catJump; + + for (const [dr, dc] of dirs) { + for (let jump = 0; jump <= maxJump; jump++) { + const nr = r + dr * jump; + const nc = c + dc * jump; + if (!isValid(nr, nc)) break; + + if (isMouseTurn) { + if (grid[nr][nc] === 'F' || canWin(turn + 1, [nr, nc], catPos)) { + memo.set(key, true); + return true; + } + } else { + if (grid[nr][nc] === 'F' || (nr === mousePos[0] && nc === mousePos[1]) + || !canWin(turn + 1, mousePos, [nr, nc])) { + memo.set(key, false); + return false; + } + } + } + } + + memo.set(key, !isMouseTurn); + return !isMouseTurn; + } +}; 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/1733-minimum-number-of-people-to-teach.js b/solutions/1733-minimum-number-of-people-to-teach.js new file mode 100644 index 00000000..9307f936 --- /dev/null +++ b/solutions/1733-minimum-number-of-people-to-teach.js @@ -0,0 +1,63 @@ +/** + * 1733. Minimum Number of People to Teach + * https://leetcode.com/problems/minimum-number-of-people-to-teach/ + * Difficulty: Medium + * + * On a social network consisting of m users and some friendships between users, two users can + * communicate with each other if they know a common language. + * + * You are given an integer n, an array languages, and an array friendships where: + * - There are n languages numbered 1 through n, + * - languages[i] is the set of languages the ith user knows, and + * - friendships[i] = [ui, vi] denotes a friendship between the users ui and vi. + * + * You can choose one language and teach it to some users so that all friends can communicate + * with each other. Return the minimum number of users you need to teach. + * + * Note that friendships are not transitive, meaning if x is a friend of y and y is a friend of + * z, this doesn't guarantee that x is a friend of z. + */ + +/** + * @param {number} n + * @param {number[][]} languages + * @param {number[][]} friendships + * @return {number} + */ +var minimumTeachings = function(n, languages, friendships) { + const languageUsers = Array.from({ length: n + 1 }, () => new Set()); + const nonCommunicating = new Set(); + + for (let i = 0; i < languages.length; i++) { + for (const lang of languages[i]) { + languageUsers[lang].add(i + 1); + } + } + + for (const [u, v] of friendships) { + let canCommunicate = false; + for (const lang of languages[u - 1]) { + if (languages[v - 1].includes(lang)) { + canCommunicate = true; + break; + } + } + if (!canCommunicate) { + nonCommunicating.add(u); + nonCommunicating.add(v); + } + } + + let result = Infinity; + for (let lang = 1; lang <= n; lang++) { + let usersToTeach = 0; + for (const user of nonCommunicating) { + if (!languages[user - 1].includes(lang)) { + usersToTeach++; + } + } + result = Math.min(result, usersToTeach); + } + + return result; +}; diff --git a/solutions/1734-decode-xored-permutation.js b/solutions/1734-decode-xored-permutation.js new file mode 100644 index 00000000..72388a1a --- /dev/null +++ b/solutions/1734-decode-xored-permutation.js @@ -0,0 +1,40 @@ +/** + * 1734. Decode XORed Permutation + * https://leetcode.com/problems/decode-xored-permutation/ + * Difficulty: Medium + * + * There is an integer array perm that is a permutation of the first n positive integers, + * where n is always odd. + * + * It was encoded into another integer array encoded of length n - 1, such that + * encoded[i] = perm[i] XOR perm[i + 1]. For example, if perm = [1,3,2], then encoded = [2,1]. + * + * Given the encoded array, return the original array perm. It is guaranteed that the answer + * exists and is unique. + */ + +/** + * @param {number[]} encoded + * @return {number[]} + */ +var decode = function(encoded) { + const n = encoded.length + 1; + let totalXor = 0; + for (let i = 1; i <= n; i++) { + totalXor ^= i; + } + + let oddXor = 0; + for (let i = 1; i < encoded.length; i += 2) { + oddXor ^= encoded[i]; + } + + const result = new Array(n); + result[0] = totalXor ^ oddXor; + + for (let i = 0; i < n - 1; i++) { + result[i + 1] = result[i] ^ encoded[i]; + } + + return result; +}; diff --git a/solutions/1735-count-ways-to-make-array-with-product.js b/solutions/1735-count-ways-to-make-array-with-product.js new file mode 100644 index 00000000..4fa45784 --- /dev/null +++ b/solutions/1735-count-ways-to-make-array-with-product.js @@ -0,0 +1,87 @@ +/** + * 1735. Count Ways to Make Array With Product + * https://leetcode.com/problems/count-ways-to-make-array-with-product/ + * Difficulty: Hard + * + * You are given a 2D integer array, queries. For each queries[i], where queries[i] = [ni, ki], + * find the number of different ways you can place positive integers into an array of size ni + * such that the product of the integers is ki. As the number of ways may be too large, the + * answer to the ith query is the number of ways modulo 109 + 7. + * + * Return an integer array answer where answer.length == queries.length, and answer[i] is the + * answer to the ith query. + */ + +/** + * @param {number[][]} queries + * @return {number[]} + */ +var waysToFillArray = function(queries) { + const MOD = 1000000007n; + const MAX_N = 20000; + const factorial = new Array(MAX_N + 1).fill(1n); + const inverse = new Array(MAX_N + 1).fill(1n); + + for (let i = 1; i <= MAX_N; i++) { + factorial[i] = (factorial[i - 1] * BigInt(i)) % MOD; + } + inverse[MAX_N] = BigInt(modInverse(Number(factorial[MAX_N] % MOD), Number(MOD))); + for (let i = MAX_N - 1; i >= 0; i--) { + inverse[i] = (inverse[i + 1] * BigInt(i + 1)) % MOD; + } + + const result = []; + for (const [size, product] of queries) { + if (product === 1) { + result.push(1); + continue; + } + const factors = getPrimeFactors(product); + let ways = 1n; + for (const count of factors.values()) { + const n = size + count - 1; + ways = (ways * BigInt(combinations(n, count))) % MOD; + } + result.push(Number(ways)); + } + + return result; + + function modInverse(a, m) { + const m0 = m; + let t; + let q; + let x0 = 0; + let x1 = 1; + while (a > 1) { + q = Math.floor(a / m); + t = m; + m = a % m; + a = t; + t = x0; + x0 = x1 - q * x0; + x1 = t; + } + return x1 < 0 ? x1 + m0 : x1; + } + + function combinations(n, k) { + if (k < 0 || k > n || n < 0 || n > MAX_N || n - k < 0) return 0; + const result = (factorial[n] * inverse[k] * inverse[n - k]) % MOD; + return Number(result); + } + + function getPrimeFactors(num) { + const factors = new Map(); + for (let i = 2; i * i <= num; i++) { + while (num % i === 0) { + factors.set(i, (factors.get(i) || 0) + 1); + num /= i; + } + } + if (num > 1) { + factors.set(num, (factors.get(num) || 0) + 1); + } + return factors; + } +}; diff --git a/solutions/1736-latest-time-by-replacing-hidden-digits.js b/solutions/1736-latest-time-by-replacing-hidden-digits.js new file mode 100644 index 00000000..23e72a76 --- /dev/null +++ b/solutions/1736-latest-time-by-replacing-hidden-digits.js @@ -0,0 +1,38 @@ +/** + * 1736. Latest Time by Replacing Hidden Digits + * https://leetcode.com/problems/latest-time-by-replacing-hidden-digits/ + * Difficulty: Easy + * + * You are given a string time in the form of hh:mm, where some of the digits in the string + * are hidden (represented by ?). + * + * The valid times are those inclusively between 00:00 and 23:59. + * + * Return the latest valid time you can get from time by replacing the hidden digits. + */ + +/** + * @param {string} time + * @return {string} + */ +var maximumTime = function(time) { + const result = time.split(''); + + if (result[0] === '?') { + result[0] = result[1] === '?' || result[1] <= '3' ? '2' : '1'; + } + + if (result[1] === '?') { + result[1] = result[0] === '2' ? '3' : '9'; + } + + if (result[3] === '?') { + result[3] = '5'; + } + + if (result[4] === '?') { + result[4] = '9'; + } + + return result.join(''); +}; diff --git a/solutions/1737-change-minimum-characters-to-satisfy-one-of-three-conditions.js b/solutions/1737-change-minimum-characters-to-satisfy-one-of-three-conditions.js new file mode 100644 index 00000000..3a084982 --- /dev/null +++ b/solutions/1737-change-minimum-characters-to-satisfy-one-of-three-conditions.js @@ -0,0 +1,59 @@ +/** + * 1737. Change Minimum Characters to Satisfy One of Three Conditions + * https://leetcode.com/problems/change-minimum-characters-to-satisfy-one-of-three-conditions/ + * Difficulty: Medium + * + * You are given two strings a and b that consist of lowercase letters. In one operation, you can + * change any character in a or b to any lowercase letter. + * + * Your goal is to satisfy one of the following three conditions: + * - Every letter in a is strictly less than every letter in b in the alphabet. + * - Every letter in b is strictly less than every letter in a in the alphabet. + * - Both a and b consist of only one distinct letter. + * + * Return the minimum number of operations needed to achieve your goal. + */ + +/** + * @param {string} a + * @param {string} b + * @return {number} + */ +var minCharacters = function(a, b) { + const aFreq = getFrequency(a); + const bFreq = getFrequency(b); + + const condition1 = operationsForCondition1(aFreq, bFreq); + const condition2 = operationsForCondition1(bFreq, aFreq); + const condition3 = operationsForCondition3(aFreq, bFreq); + + return Math.min(condition1, condition2, condition3); + + function getFrequency(str) { + const freq = Array(26).fill(0); + for (const char of str) { + freq[char.charCodeAt(0) - 97]++; + } + return freq; + } + + function operationsForCondition1(aFreq, bFreq) { + let minOps = Infinity; + for (let i = 0; i < 25; i++) { + let ops = 0; + for (let j = 0; j <= i; j++) ops += aFreq[j]; + for (let j = i + 1; j < 26; j++) ops += bFreq[j]; + minOps = Math.min(minOps, ops); + } + return minOps; + } + + function operationsForCondition3(aFreq, bFreq) { + let minOps = Infinity; + for (let i = 0; i < 26; i++) { + const ops = a.length + b.length - aFreq[i] - bFreq[i]; + minOps = Math.min(minOps, ops); + } + return minOps; + } +}; diff --git a/solutions/1738-find-kth-largest-xor-coordinate-value.js b/solutions/1738-find-kth-largest-xor-coordinate-value.js new file mode 100644 index 00000000..383d4166 --- /dev/null +++ b/solutions/1738-find-kth-largest-xor-coordinate-value.js @@ -0,0 +1,37 @@ +/** + * 1738. Find Kth Largest XOR Coordinate Value + * https://leetcode.com/problems/find-kth-largest-xor-coordinate-value/ + * Difficulty: Medium + * + * You are given a 2D matrix of size m x n, consisting of non-negative integers. You are also + * given an integer k. + * + * The value of coordinate (a, b) of the matrix is the XOR of all matrix[i][j] where + * 0 <= i <= a < m and 0 <= j <= b < n (0-indexed). + * + * Find the kth largest value (1-indexed) of all the coordinates of matrix. + */ + +/** + * @param {number[][]} matrix + * @param {number} k + * @return {number} + */ +var kthLargestValue = function(matrix, k) { + const rows = matrix.length; + const cols = matrix[0].length; + const xorValues = new Array(rows * cols); + const prefixXor = Array.from({ length: rows + 1 }, () => Array(cols + 1).fill(0)); + + let index = 0; + for (let i = 1; i <= rows; i++) { + for (let j = 1; j <= cols; j++) { + prefixXor[i][j] = prefixXor[i-1][j] ^ prefixXor[i][j-1] + ^ prefixXor[i-1][j-1] ^ matrix[i-1][j-1]; + xorValues[index++] = prefixXor[i][j]; + } + } + + xorValues.sort((a, b) => b - a); + return xorValues[k-1]; +}; diff --git a/solutions/1739-building-boxes.js b/solutions/1739-building-boxes.js new file mode 100644 index 00000000..0a80282a --- /dev/null +++ b/solutions/1739-building-boxes.js @@ -0,0 +1,38 @@ +/** + * 1739. Building Boxes + * https://leetcode.com/problems/building-boxes/ + * Difficulty: Hard + * + * You have a cubic storeroom where the width, length, and height of the room are all equal to n + * units. You are asked to place n boxes in this room where each box is a cube of unit side + * length. There are however some rules to placing the boxes: + * - You can place the boxes anywhere on the floor. + * - If box x is placed on top of the box y, then each side of the four vertical sides of the box + * y must either be adjacent to another box or to a wall. + * + * Given an integer n, return the minimum possible number of boxes touching the floor. + */ + +/** + * @param {number} n + * @return {number} + */ +var minimumBoxes = function(n) { + if (n < 4) return n; + + let baseSize = 0; + let totalBoxes = 0; + const triangular = k => k * (k + 1) / 2; + + while (totalBoxes + triangular(baseSize + 1) <= n) { + baseSize++; + totalBoxes += triangular(baseSize); + } + + const remaining = n - totalBoxes; + let extraFloor = 0; + + while (triangular(extraFloor) < remaining) extraFloor++; + + return triangular(baseSize) + extraFloor; +}; 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/1742-maximum-number-of-balls-in-a-box.js b/solutions/1742-maximum-number-of-balls-in-a-box.js new file mode 100644 index 00000000..e16d7ae5 --- /dev/null +++ b/solutions/1742-maximum-number-of-balls-in-a-box.js @@ -0,0 +1,44 @@ +/** + * 1742. Maximum Number of Balls in a Box + * https://leetcode.com/problems/maximum-number-of-balls-in-a-box/ + * Difficulty: Easy + * + * You are working in a ball factory where you have n balls numbered from lowLimit up to + * highLimit inclusive (i.e., n == highLimit - lowLimit + 1), and an infinite number of + * boxes numbered from 1 to infinity. + * + * Your job at this factory is to put each ball in the box with a number equal to the sum + * of digits of the ball's number. For example, the ball number 321 will be put in the + * box number 3 + 2 + 1 = 6 and the ball number 10 will be put in the box number 1 + 0 = 1. + * + * Given two integers lowLimit and highLimit, return the number of balls in the box with + * the most balls. + */ + +/** + * @param {number} lowLimit + * @param {number} highLimit + * @return {number} + */ +var countBalls = function(lowLimit, highLimit) { + const boxCounts = new Map(); + let result = 0; + + for (let ball = lowLimit; ball <= highLimit; ball++) { + const box = sumDigits(ball); + const count = (boxCounts.get(box) || 0) + 1; + boxCounts.set(box, count); + result = Math.max(result, count); + } + + return result; + + function sumDigits(num) { + let sum = 0; + while (num > 0) { + sum += num % 10; + num = Math.floor(num / 10); + } + return sum; + } +}; diff --git a/solutions/1743-restore-the-array-from-adjacent-pairs.js b/solutions/1743-restore-the-array-from-adjacent-pairs.js new file mode 100644 index 00000000..f7cdbb9f --- /dev/null +++ b/solutions/1743-restore-the-array-from-adjacent-pairs.js @@ -0,0 +1,51 @@ +/** + * 1743. Restore the Array From Adjacent Pairs + * https://leetcode.com/problems/restore-the-array-from-adjacent-pairs/ + * Difficulty: Medium + * + * There is an integer array nums that consists of n unique elements, but you have + * forgotten it. However, you do remember every pair of adjacent elements in nums. + * + * You are given a 2D integer array adjacentPairs of size n - 1 where each + * adjacentPairs[i] = [ui, vi] indicates that the elements ui and vi are adjacent in nums. + * + * It is guaranteed that every adjacent pair of elements nums[i] and nums[i+1] will exist in + * adjacentPairs, either as [nums[i], nums[i+1]] or [nums[i+1], nums[i]]. The pairs can appear + * in any order. + * + * Return the original array nums. If there are multiple solutions, return any of them. + */ + +/** + * @param {number[][]} adjacentPairs + * @return {number[]} + */ +var restoreArray = function(adjacentPairs) { + const graph = new Map(); + for (const [u, v] of adjacentPairs) { + graph.set(u, (graph.get(u) || []).concat(v)); + graph.set(v, (graph.get(v) || []).concat(u)); + } + + let start; + for (const [node, neighbors] of graph) { + if (neighbors.length === 1) { + start = node; + break; + } + } + + const result = [start]; + let prev = start; + let curr = graph.get(start)[0]; + + while (graph.get(curr).length > 1) { + result.push(curr); + const next = graph.get(curr).find(n => n !== prev); + prev = curr; + curr = next; + } + result.push(curr); + + return result; +}; diff --git a/solutions/1744-can-you-eat-your-favorite-candy-on-your-favorite-day.js b/solutions/1744-can-you-eat-your-favorite-candy-on-your-favorite-day.js new file mode 100644 index 00000000..ac72e529 --- /dev/null +++ b/solutions/1744-can-you-eat-your-favorite-candy-on-your-favorite-day.js @@ -0,0 +1,45 @@ +/** + * 1744. Can You Eat Your Favorite Candy on Your Favorite Day? + * https://leetcode.com/problems/can-you-eat-your-favorite-candy-on-your-favorite-day/ + * Difficulty: Medium + * + * You are given a (0-indexed) array of positive integers candiesCount where candiesCount[i] + * represents the number of candies of the ith type you have. You are also given a 2D array + * queries where queries[i] = [favoriteTypei, favoriteDayi, dailyCapi]. + * + * You play a game with the following rules: + * - You start eating candies on day 0. + * - You cannot eat any candy of type i unless you have eaten all candies of type i - 1. + * - You must eat at least one candy per day until you have eaten all the candies. + * + * Construct a boolean array answer such that answer.length == queries.length and answer[i] is + * true if you can eat a candy of type favoriteTypei on day favoriteDayi without eating more + * than dailyCapi candies on any day, and false otherwise. Note that you can eat different + * types of candy on the same day, provided that you follow rule 2. + * + * Return the constructed array answer. + */ + +/** + * @param {number[]} candiesCount + * @param {number[][]} queries + * @return {boolean[]} + */ +var canEat = function(candiesCount, queries) { + const prefixSums = [0]; + for (const count of candiesCount) { + prefixSums.push(prefixSums.at(-1) + count); + } + + const result = new Array(queries.length); + for (let i = 0; i < queries.length; i++) { + const [type, day, cap] = queries[i]; + const minCandies = day; + const maxCandies = (day + 1) * cap; + const typeStart = prefixSums[type]; + const typeEnd = prefixSums[type + 1] - 1; + result[i] = maxCandies > typeStart && minCandies <= typeEnd; + } + + return result; +}; diff --git a/solutions/1745-palindrome-partitioning-iv.js b/solutions/1745-palindrome-partitioning-iv.js new file mode 100644 index 00000000..7fefea0f --- /dev/null +++ b/solutions/1745-palindrome-partitioning-iv.js @@ -0,0 +1,37 @@ +/** + * 1745. Palindrome Partitioning IV + * https://leetcode.com/problems/palindrome-partitioning-iv/ + * Difficulty: Hard + * + * Given a string s, return true if it is possible to split the string s into three non-empty + * palindromic substrings. Otherwise, return false. + * + * A string is said to be palindrome if it the same string when reversed. + */ + +/** + * @param {string} s + * @return {boolean} + */ +var checkPartitioning = function(s) { + const n = s.length; + const isPalindrome = Array.from({ length: n }, () => Array(n).fill(false)); + + for (let i = n - 1; i >= 0; i--) { + for (let j = i; j < n; j++) { + if (s[i] === s[j] && (j - i <= 2 || isPalindrome[i + 1][j - 1])) { + isPalindrome[i][j] = true; + } + } + } + + for (let i = 1; i < n - 1; i++) { + for (let j = i; j < n - 1; j++) { + if (isPalindrome[0][i - 1] && isPalindrome[i][j] && isPalindrome[j + 1][n - 1]) { + return true; + } + } + } + + return false; +}; 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/1750-minimum-length-of-string-after-deleting-similar-ends.js b/solutions/1750-minimum-length-of-string-after-deleting-similar-ends.js new file mode 100644 index 00000000..c8cdb813 --- /dev/null +++ b/solutions/1750-minimum-length-of-string-after-deleting-similar-ends.js @@ -0,0 +1,33 @@ +/** + * 1750. Minimum Length of String After Deleting Similar Ends + * https://leetcode.com/problems/minimum-length-of-string-after-deleting-similar-ends/ + * Difficulty: Medium + * + * Given a string s consisting only of characters 'a', 'b', and 'c'. You are asked to apply the + * following algorithm on the string any number of times: + * 1. Pick a non-empty prefix from the string s where all the characters in the prefix are equal. + * 2. Pick a non-empty suffix from the string s where all the characters in this suffix are equal. + * 3. The prefix and the suffix should not intersect at any index. + * 4. The characters from the prefix and suffix must be the same. + * 5. Delete both the prefix and the suffix. + * + * Return the minimum length of s after performing the above operation any number of times + * (possibly zero times). + */ + +/** + * @param {string} s + * @return {number} + */ +var minimumLength = function(s) { + let left = 0; + let right = s.length - 1; + + while (left < right && s[left] === s[right]) { + const char = s[left]; + while (left <= right && s[left] === char) left++; + while (left <= right && s[right] === char) right--; + } + + return Math.max(0, right - left + 1); +}; diff --git a/solutions/1751-maximum-number-of-events-that-can-be-attended-ii.js b/solutions/1751-maximum-number-of-events-that-can-be-attended-ii.js new file mode 100644 index 00000000..74cd6ee3 --- /dev/null +++ b/solutions/1751-maximum-number-of-events-that-can-be-attended-ii.js @@ -0,0 +1,54 @@ +/** + * 1751. Maximum Number of Events That Can Be Attended II + * https://leetcode.com/problems/maximum-number-of-events-that-can-be-attended-ii/ + * Difficulty: Hard + * + * You are given an array of events where events[i] = [startDayi, endDayi, valuei]. The ith event + * starts at startDayi and ends at endDayi, and if you attend this event, you will receive a value + * of valuei. You are also given an integer k which represents the maximum number of events you can + * attend. + * + * You can only attend one event at a time. If you choose to attend an event, you must attend the + * entire event. Note that the end day is inclusive: that is, you cannot attend two events where + * one of them starts and the other ends on the same day. + * + * Return the maximum sum of values that you can receive by attending events. + */ + +/** + * @param {number[][]} events + * @param {number} k + * @return {number} + */ +var maxValue = function(events, k) { + events.sort((a, b) => a[0] - b[0]); + const n = events.length; + const dp = Array.from({ length: k + 1 }, () => new Array(n + 1).fill(-1)); + + return maximize(0, k); + + function findNext(index, end) { + let left = index; + let right = n; + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (events[mid][0] > end) { + right = mid; + } else { + left = mid + 1; + } + } + return left; + } + + function maximize(index, remaining) { + if (index >= n || remaining === 0) return 0; + if (dp[remaining][index] !== -1) return dp[remaining][index]; + + const nextIndex = findNext(index + 1, events[index][1]); + const take = events[index][2] + maximize(nextIndex, remaining - 1); + const skip = maximize(index + 1, remaining); + + return dp[remaining][index] = Math.max(take, skip); + } +}; diff --git a/solutions/1753-maximum-score-from-removing-stones.js b/solutions/1753-maximum-score-from-removing-stones.js new file mode 100644 index 00000000..24dfa2f0 --- /dev/null +++ b/solutions/1753-maximum-score-from-removing-stones.js @@ -0,0 +1,32 @@ +/** + * 1753. Maximum Score From Removing Stones + * https://leetcode.com/problems/maximum-score-from-removing-stones/ + * Difficulty: Medium + * + * You are playing a solitaire game with three piles of stones of sizes a, b, and c respectively. + * Each turn you choose two different non-empty piles, take one stone from each, and add 1 point + * to your score. The game stops when there are fewer than two non-empty piles (meaning there are + * no more available moves). + * + * Given three integers a, b, and c return the maximum score you can get. + */ + +/** + * @param {number} a + * @param {number} b + * @param {number} c + * @return {number} + */ +var maximumScore = function(a, b, c) { + const piles = [a, b, c].sort((x, y) => y - x); + let score = 0; + + while (piles[0] > 0 && piles[1] > 0) { + piles[0]--; + piles[1]--; + score++; + piles.sort((x, y) => y - x); + } + + return score; +}; diff --git a/solutions/1754-largest-merge-of-two-strings.js b/solutions/1754-largest-merge-of-two-strings.js new file mode 100644 index 00000000..0ba08bd4 --- /dev/null +++ b/solutions/1754-largest-merge-of-two-strings.js @@ -0,0 +1,44 @@ +/** + * 1754. Largest Merge Of Two Strings + * https://leetcode.com/problems/largest-merge-of-two-strings/ + * Difficulty: Medium + * + * You are given two strings word1 and word2. You want to construct a string merge in the + * following way: while either word1 or word2 are non-empty, choose one of the following + * options: + * - If word1 is non-empty, append the first character in word1 to merge and delete it from word1. + * - For example, if word1 = "abc" and merge = "dv", then after choosing this operation, + * word1 = "bc" and merge = "dva". + * - If word2 is non-empty, append the first character in word2 to merge and delete it from word2. + * - For example, if word2 = "abc" and merge = "", then after choosing this operation, + * word2 = "bc" and merge = "a". + * + * Return the lexicographically largest merge you can construct. + * + * 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} word1 + * @param {string} word2 + * @return {string} + */ +var largestMerge = function(word1, word2) { + let merge = ''; + let i = 0; + let j = 0; + + while (i < word1.length && j < word2.length) { + if (word1.slice(i) >= word2.slice(j)) { + merge += word1[i++]; + } else { + merge += word2[j++]; + } + } + + merge += word1.slice(i) + word2.slice(j); + return merge; +}; diff --git a/solutions/1755-closest-subsequence-sum.js b/solutions/1755-closest-subsequence-sum.js new file mode 100644 index 00000000..bad15f92 --- /dev/null +++ b/solutions/1755-closest-subsequence-sum.js @@ -0,0 +1,63 @@ +/** + * 1755. Closest Subsequence Sum + * https://leetcode.com/problems/closest-subsequence-sum/ + * Difficulty: Hard + * + * You are given an integer array nums and an integer goal. + * + * You want to choose a subsequence of nums such that the sum of its elements is the closest + * possible to goal. That is, if the sum of the subsequence's elements is sum, then you want + * to minimize the absolute difference abs(sum - goal). + * + * Return the minimum possible value of abs(sum - goal). + * + * Note that a subsequence of an array is an array formed by removing some elements (possibly + * all or none) of the original array. + */ + +/** + * @param {number[]} nums + * @param {number} goal + * @return {number} + */ +var minAbsDifference = function(nums, goal) { + const n = nums.length; + const half = Math.floor(n / 2); + const leftSums = new Set(); + const rightSums = new Set(); + + generateSums(0, half, leftSums); + generateSums(half, n, rightSums); + + const rightArray = [...rightSums].sort((a, b) => a - b); + let minDiff = Infinity; + + for (const leftSum of leftSums) { + const target = goal - leftSum; + let left = 0; + let right = rightArray.length - 1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + const sum = leftSum + rightArray[mid]; + minDiff = Math.min(minDiff, Math.abs(sum - goal)); + + if (sum < goal) { + left = mid + 1; + } else { + right = mid - 1; + } + } + } + + return minDiff; + + function generateSums(start, end, sums, current = 0) { + if (start === end) { + sums.add(current); + return; + } + generateSums(start + 1, end, sums, current); + generateSums(start + 1, end, sums, current + nums[start]); + } +}; 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/1758-minimum-changes-to-make-alternating-binary-string.js b/solutions/1758-minimum-changes-to-make-alternating-binary-string.js new file mode 100644 index 00000000..dad5e376 --- /dev/null +++ b/solutions/1758-minimum-changes-to-make-alternating-binary-string.js @@ -0,0 +1,31 @@ +/** + * 1758. Minimum Changes To Make Alternating Binary String + * https://leetcode.com/problems/minimum-changes-to-make-alternating-binary-string/ + * Difficulty: Easy + * + * You are given a string s consisting only of the characters '0' and '1'. In one operation, you can + * change any '0' to '1' or vice versa. + * + * The string is called alternating if no two adjacent characters are equal. For example, the string + * "010" is alternating, while the string "0100" is not. + * + * Return the minimum number of operations needed to make s alternating. + */ + +/** + * @param {string} s + * @return {number} + */ +var minOperations = function(s) { + let changesToZeroStart = 0; + let changesToOneStart = 0; + + for (let i = 0; i < s.length; i++) { + const expectedZeroStart = i % 2 === 0 ? '0' : '1'; + const expectedOneStart = i % 2 === 0 ? '1' : '0'; + if (s[i] !== expectedZeroStart) changesToZeroStart++; + if (s[i] !== expectedOneStart) changesToOneStart++; + } + + return Math.min(changesToZeroStart, changesToOneStart); +}; diff --git a/solutions/1759-count-number-of-homogenous-substrings.js b/solutions/1759-count-number-of-homogenous-substrings.js new file mode 100644 index 00000000..b6fb8fbc --- /dev/null +++ b/solutions/1759-count-number-of-homogenous-substrings.js @@ -0,0 +1,35 @@ +/** + * 1759. Count Number of Homogenous Substrings + * https://leetcode.com/problems/count-number-of-homogenous-substrings/ + * Difficulty: Medium + * + * Given a string s, return the number of homogenous substrings of s. Since the answer may be + * too large, return it modulo 109 + 7. + * + * A string is homogenous if all the characters of the string are the same. + * + * A substring is a contiguous sequence of characters within a string. + */ + +/** + * @param {string} s + * @return {number} + */ +var countHomogenous = function(s) { + const mod = 1e9 + 7; + let result = 0; + let streak = 1; + + for (let i = 1; i < s.length; i++) { + if (s[i] === s[i - 1]) { + streak++; + } else { + result = (result + (streak * (streak + 1) / 2)) % mod; + streak = 1; + } + } + + result = (result + (streak * (streak + 1) / 2)) % mod; + + return result; +}; diff --git a/solutions/1760-minimum-limit-of-balls-in-a-bag.js b/solutions/1760-minimum-limit-of-balls-in-a-bag.js new file mode 100644 index 00000000..f8ff3efa --- /dev/null +++ b/solutions/1760-minimum-limit-of-balls-in-a-bag.js @@ -0,0 +1,45 @@ +/** + * 1760. Minimum Limit of Balls in a Bag + * https://leetcode.com/problems/minimum-limit-of-balls-in-a-bag/ + * Difficulty: Medium + * + * You are given an integer array nums where the ith bag contains nums[i] balls. You are also + * given an integer maxOperations. + * + * You can perform the following operation at most maxOperations times: + * - Take any bag of balls and divide it into two new bags with a positive number of balls. + * - For example, a bag of 5 balls can become two new bags of 1 and 4 balls, or two new bags + * of 2 and 3 balls. + * + * Your penalty is the maximum number of balls in a bag. You want to minimize your penalty after + * the operations. + * + * Return the minimum possible penalty after performing the operations. + */ + +/** + * @param {number[]} nums + * @param {number} maxOperations + * @return {number} + */ +var minimumSize = function(nums, maxOperations) { + let left = 1; + let right = Math.max(...nums); + + while (left < right) { + const mid = Math.floor((left + right) / 2); + let operations = 0; + + for (const num of nums) { + operations += Math.ceil(num / mid) - 1; + } + + if (operations <= maxOperations) { + right = mid; + } else { + left = mid + 1; + } + } + + return left; +}; diff --git a/solutions/1761-minimum-degree-of-a-connected-trio-in-a-graph.js b/solutions/1761-minimum-degree-of-a-connected-trio-in-a-graph.js new file mode 100644 index 00000000..d913b953 --- /dev/null +++ b/solutions/1761-minimum-degree-of-a-connected-trio-in-a-graph.js @@ -0,0 +1,49 @@ +/** + * 1761. Minimum Degree of a Connected Trio in a Graph + * https://leetcode.com/problems/minimum-degree-of-a-connected-trio-in-a-graph/ + * Difficulty: Hard + * + * You are given an undirected graph. You are given an integer n which is the number of nodes in + * the graph and an array edges, where each edges[i] = [ui, vi] indicates that there is an + * undirected edge between ui and vi. + * + * A connected trio is a set of three nodes where there is an edge between every pair of them. + * + * The degree of a connected trio is the number of edges where one endpoint is in the trio, and + * the other is not. + * + * Return the minimum degree of a connected trio in the graph, or -1 if the graph has no + * connected trios. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @return {number} + */ +var minTrioDegree = function(n, edges) { + const graph = Array.from({ length: n + 1 }, () => new Set()); + const degrees = Array(n + 1).fill(0); + + for (const [u, v] of edges) { + graph[u].add(v); + graph[v].add(u); + degrees[u]++; + degrees[v]++; + } + + let minDegree = Infinity; + + for (let i = 1; i <= n; i++) { + for (const j of graph[i]) { + for (const k of graph[j]) { + if (graph[k].has(i)) { + const trioDegree = degrees[i] + degrees[j] + degrees[k] - 6; + minDegree = Math.min(minDegree, trioDegree); + } + } + } + } + + return minDegree === Infinity ? -1 : minDegree; +}; 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/1763-longest-nice-substring.js b/solutions/1763-longest-nice-substring.js new file mode 100644 index 00000000..00495b99 --- /dev/null +++ b/solutions/1763-longest-nice-substring.js @@ -0,0 +1,38 @@ +/** + * 1763. Longest Nice Substring + * https://leetcode.com/problems/longest-nice-substring/ + * Difficulty: Easy + * + * A string s is nice if, for every letter of the alphabet that s contains, it appears both + * in uppercase and lowercase. For example, "abABB" is nice because 'A' and 'a' appear, + * and 'B' and 'b' appear. However, "abA" is not because 'b' appears, but 'B' does not. + * + * Given a string s, return the longest substring of s that is nice. If there are multiple, + * return the substring of the earliest occurrence. If there are none, return an empty string. + */ + +/** + * @param {string} s + * @return {string} + */ +var longestNiceSubstring = function(s) { + let longest = ''; + + for (let i = 0; i < s.length; i++) { + for (let j = i; j < s.length; j++) { + const substr = s.slice(i, j + 1); + if (substr.length <= longest.length) continue; + const chars = new Set(substr.toLowerCase().split('')); + let isNice = true; + for (const char of chars) { + if (!substr.includes(char.toLowerCase()) || !substr.includes(char.toUpperCase())) { + isNice = false; + break; + } + } + if (isNice) longest = substr; + } + } + + return longest; +}; diff --git a/solutions/1766-tree-of-coprimes.js b/solutions/1766-tree-of-coprimes.js new file mode 100644 index 00000000..31ec7f8d --- /dev/null +++ b/solutions/1766-tree-of-coprimes.js @@ -0,0 +1,76 @@ +/** + * 1766. Tree of Coprimes + * https://leetcode.com/problems/tree-of-coprimes/ + * Difficulty: Hard + * + * There is a tree (i.e., a connected, undirected graph that has no cycles) consisting of n nodes + * numbered from 0 to n - 1 and exactly n - 1 edges. Each node has a value associated with it, + * and the root of the tree is node 0. + * + * To represent this tree, you are given an integer array nums and a 2D array edges. Each nums[i] + * represents the ith node's value, and each edges[j] = [uj, vj] represents an edge between nodes + * uj and vj in the tree. + * + * 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. + * + * An ancestor of a node i is any other node on the shortest path from node i to the root. A node + * is not considered an ancestor of itself. + * + * Return an array ans of size n, where ans[i] is the closest ancestor to node i such that + * nums[i] and nums[ans[i]] are coprime, or -1 if there is no such ancestor. + */ + +/** + * @param {number[]} nums + * @param {number[][]} edges + * @return {number[]} + */ +var getCoprimes = function(nums, edges) { + const n = nums.length; + const graph = Array.from({ length: n }, () => []); + for (const [u, v] of edges) { + graph[u].push(v); + graph[v].push(u); + } + + const result = Array(n).fill(-1); + const valueDepth = Array(51).fill().map(() => []); + const visited = new Set(); + + dfs(0, 0, -1); + return result; + + function dfs(node, depth, parent) { + const val = nums[node]; + let maxDepth = -1; + let closestAncestor = -1; + + for (let i = 1; i <= 50; i++) { + if (gcd(val, i) === 1 && valueDepth[i].length) { + const [ancestor, d] = valueDepth[i].at(-1); + if (d > maxDepth) { + maxDepth = d; + closestAncestor = ancestor; + } + } + } + + result[node] = closestAncestor; + valueDepth[val].push([node, depth]); + visited.add(node); + + for (const neighbor of graph[node]) { + if (!visited.has(neighbor)) { + dfs(neighbor, depth + 1, node); + } + } + + valueDepth[val].pop(); + } + + function gcd(a, b) { + while (b) [a, b] = [b, a % b]; + return a; + } +}; diff --git a/solutions/1770-maximum-score-from-performing-multiplication-operations.js b/solutions/1770-maximum-score-from-performing-multiplication-operations.js new file mode 100644 index 00000000..73ec2746 --- /dev/null +++ b/solutions/1770-maximum-score-from-performing-multiplication-operations.js @@ -0,0 +1,39 @@ +/** + * 1770. Maximum Score from Performing Multiplication Operations + * https://leetcode.com/problems/maximum-score-from-performing-multiplication-operations/ + * Difficulty: Hard + * + * You are given two 0-indexed integer arrays nums and multipliers of size n and m respectively, + * where n >= m. + * + * You begin with a score of 0. You want to perform exactly m operations. On the ith operation + * (0-indexed) you will: + * - Choose one integer x from either the start or the end of the array nums. + * - Add multipliers[i] * x to your score. + * - Note that multipliers[0] corresponds to the first operation, multipliers[1] to the second + * operation, and so on. + * - Remove x from nums. + * + * Return the maximum score after performing m operations. + */ + +/** + * @param {number[]} nums + * @param {number[]} multipliers + * @return {number} + */ +var maximumScore = function(nums, multipliers) { + const m = multipliers.length; + const dp = Array.from({ length: m + 1 }, () => Array(m + 1).fill(0)); + + for (let op = m - 1; op >= 0; op--) { + for (let left = op; left >= 0; left--) { + const right = nums.length - 1 - (op - left); + const takeLeft = multipliers[op] * nums[left] + dp[op + 1][left + 1]; + const takeRight = multipliers[op] * nums[right] + dp[op + 1][left]; + dp[op][left] = Math.max(takeLeft, takeRight); + } + } + + return dp[0][0]; +}; diff --git a/solutions/1771-maximize-palindrome-length-from-subsequences.js b/solutions/1771-maximize-palindrome-length-from-subsequences.js new file mode 100644 index 00000000..f24d48c9 --- /dev/null +++ b/solutions/1771-maximize-palindrome-length-from-subsequences.js @@ -0,0 +1,47 @@ +/** + * 1771. Maximize Palindrome Length From Subsequences + * https://leetcode.com/problems/maximize-palindrome-length-from-subsequences/ + * Difficulty: Hard + * + * You are given two strings, word1 and word2. You want to construct a string in the following + * manner: + * - Choose some non-empty subsequence subsequence1 from word1. + * - Choose some non-empty subsequence subsequence2 from word2. + * - Concatenate the subsequences: subsequence1 + subsequence2, to make the string. + * + * Return the length of the longest palindrome that can be constructed in the described manner. + * If no palindromes can be constructed, return 0. + * + * A subsequence of a string s is a string that can be made by deleting some (possibly none) + * characters from s without changing the order of the remaining characters. + * + * A palindrome is a string that reads the same forward as well as backward. + */ + +/** + * @param {string} word1 + * @param {string} word2 + * @return {number} + */ +var longestPalindrome = function(word1, word2) { + const s = word1 + word2; + const n = s.length; + const dp = Array.from({ length: n }, () => Array(n).fill(0)); + let result = 0; + + for (let i = n - 1; i >= 0; i--) { + dp[i][i] = 1; + for (let j = i + 1; j < n; j++) { + if (s[i] === s[j]) { + dp[i][j] = dp[i + 1][j - 1] + 2; + if (i < word1.length && j >= word1.length) { + result = Math.max(result, dp[i][j]); + } + } else { + dp[i][j] = Math.max(dp[i + 1][j], dp[i][j - 1]); + } + } + } + + return result; +}; 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/1773-count-items-matching-a-rule.js b/solutions/1773-count-items-matching-a-rule.js new file mode 100644 index 00000000..528c7169 --- /dev/null +++ b/solutions/1773-count-items-matching-a-rule.js @@ -0,0 +1,35 @@ +/** + * 1773. Count Items Matching a Rule + * https://leetcode.com/problems/count-items-matching-a-rule/ + * Difficulty: Easy + * + * You are given an array items, where each items[i] = [typei, colori, namei] describes the type, + * color, and name of the ith item. You are also given a rule represented by two strings, + * ruleKey and ruleValue. + * + * The ith item is said to match the rule if one of the following is true: + * - ruleKey == "type" and ruleValue == typei. + * - ruleKey == "color" and ruleValue == colori. + * - ruleKey == "name" and ruleValue == namei. + * + * Return the number of items that match the given rule. + */ + +/** + * @param {string[][]} items + * @param {string} ruleKey + * @param {string} ruleValue + * @return {number} + */ +var countMatches = function(items, ruleKey, ruleValue) { + const keyIndex = { type: 0, color: 1, name: 2 }; + let result = 0; + + for (const item of items) { + if (item[keyIndex[ruleKey]] === ruleValue) { + result++; + } + } + + return result; +}; diff --git a/solutions/1774-closest-dessert-cost.js b/solutions/1774-closest-dessert-cost.js new file mode 100644 index 00000000..707d1812 --- /dev/null +++ b/solutions/1774-closest-dessert-cost.js @@ -0,0 +1,55 @@ +/** + * 1774. Closest Dessert Cost + * https://leetcode.com/problems/closest-dessert-cost/ + * Difficulty: Medium + * + * You would like to make dessert and are preparing to buy the ingredients. You have n ice + * cream base flavors and m types of toppings to choose from. You must follow these rules + * when making your dessert: + * - There must be exactly one ice cream base. + * - You can add one or more types of topping or have no toppings at all. + * - There are at most two of each type of topping. + * + * You are given three inputs: + * - baseCosts, an integer array of length n, where each baseCosts[i] represents the price of + * the ith ice cream base flavor. + * - toppingCosts, an integer array of length m, where each toppingCosts[i] is the price of + * one of the ith topping. + * - target, an integer representing your target price for dessert. + * + * You want to make a dessert with a total cost as close to target as possible. + * + * Return the closest possible cost of the dessert to target. If there are multiple, return + * the lower one. + */ + +/** + * @param {number[]} baseCosts + * @param {number[]} toppingCosts + * @param {number} target + * @return {number} + */ +var closestCost = function(baseCosts, toppingCosts, target) { + let result = Infinity; + + for (const base of baseCosts) { + exploreToppings(0, base); + } + + return result; + + function exploreToppings(index, currentCost) { + const diff = Math.abs(currentCost - target); + const prevDiff = Math.abs(result - target); + + if (diff < prevDiff || (diff === prevDiff && currentCost < result)) { + result = currentCost; + } + + if (index >= toppingCosts.length || currentCost > target) return; + + exploreToppings(index + 1, currentCost); + exploreToppings(index + 1, currentCost + toppingCosts[index]); + exploreToppings(index + 1, currentCost + 2 * toppingCosts[index]); + } +}; diff --git a/solutions/1775-equal-sum-arrays-with-minimum-number-of-operations.js b/solutions/1775-equal-sum-arrays-with-minimum-number-of-operations.js new file mode 100644 index 00000000..8c2f068f --- /dev/null +++ b/solutions/1775-equal-sum-arrays-with-minimum-number-of-operations.js @@ -0,0 +1,65 @@ +/** + * 1775. Equal Sum Arrays With Minimum Number of Operations + * https://leetcode.com/problems/equal-sum-arrays-with-minimum-number-of-operations/ + * Difficulty: Medium + * + * You are given two arrays of integers nums1 and nums2, possibly of different lengths. The values + * in the arrays are between 1 and 6, inclusive. + * + * In one operation, you can change any integer's value in any of the arrays to any value between + * 1 and 6, inclusive. + * + * Return the minimum number of operations required to make the sum of values in nums1 equal to + * the sum of values in nums2. Return -1 if it is not possible to make the sum of the two arrays + * equal. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var minOperations = function(nums1, nums2) { + let sum1 = nums1.reduce((a, b) => a + b, 0); + let sum2 = nums2.reduce((a, b) => a + b, 0); + + if (sum1 < sum2) { + [nums1, nums2, sum1, sum2] = [nums2, nums1, sum2, sum1]; + } + + const maxSum1 = nums1.length * 6; + const minSum1 = nums1.length; + const maxSum2 = nums2.length * 6; + const minSum2 = nums2.length; + + if (maxSum1 < minSum2 || maxSum2 < minSum1) return -1; + + let result = 0; + const gains = []; + const losses = []; + + for (const num of nums1) { + losses.push(num - 1); + } + for (const num of nums2) { + gains.push(6 - num); + } + + losses.sort((a, b) => b - a); + gains.sort((a, b) => b - a); + + let i = 0; + let j = 0; + let diff = sum1 - sum2; + + while (diff > 0 && (i < losses.length || j < gains.length)) { + const change = i < losses.length && (j >= gains.length || losses[i] >= gains[j]) + ? losses[i++] + : gains[j++]; + const take = Math.min(diff, change); + diff -= take; + result++; + } + + return result; +}; diff --git a/solutions/1776-car-fleet-ii.js b/solutions/1776-car-fleet-ii.js new file mode 100644 index 00000000..176303c5 --- /dev/null +++ b/solutions/1776-car-fleet-ii.js @@ -0,0 +1,56 @@ +/** + * 1776. Car Fleet II + * https://leetcode.com/problems/car-fleet-ii/ + * Difficulty: Hard + * + * There are n cars traveling at different speeds in the same direction along a one-lane road. + * You are given an array cars of length n, where cars[i] = [positioni, speedi] represents: + * - positioni is the distance between the ith car and the beginning of the road in meters. + * It is guaranteed that positioni < positioni+1. + * - speedi is the initial speed of the ith car in meters per second. + * + * For simplicity, cars can be considered as points moving along the number line. Two cars + * collide when they occupy the same position. Once a car collides with another car, they + * unite and form a single car fleet. The cars in the formed fleet will have the same position + * and the same speed, which is the initial speed of the slowest car in the fleet. + * + * Return an array answer, where answer[i] is the time, in seconds, at which the ith car + * collides with the next car, or -1 if the car does not collide with the next car. Answers + * within 10-5 of the actual answers are accepted. + */ + +/** + * @param {number[][]} cars + * @return {number[]} + */ +var getCollisionTimes = function(cars) { + const n = cars.length; + const stack = []; + const collisionTimes = Array(n).fill(-1); + + for (let i = n - 1; i >= 0; i--) { + const [pos, speed] = cars[i]; + + while (stack.length > 0) { + const j = stack[stack.length - 1]; + const [nextPos, nextSpeed] = cars[j]; + + if (speed <= nextSpeed || (collisionTimes[j] > 0 + && (nextPos - pos) / (speed - nextSpeed) >= collisionTimes[j])) { + stack.pop(); + } else { + break; + } + } + + if (stack.length > 0) { + const j = stack[stack.length - 1]; + const [nextPos, nextSpeed] = cars[j]; + collisionTimes[i] = (nextPos - pos) / (speed - nextSpeed); + } + + stack.push(i); + } + + return collisionTimes; +}; 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/1779-find-nearest-point-that-has-the-same-x-or-y-coordinate.js b/solutions/1779-find-nearest-point-that-has-the-same-x-or-y-coordinate.js new file mode 100644 index 00000000..faf1f1b2 --- /dev/null +++ b/solutions/1779-find-nearest-point-that-has-the-same-x-or-y-coordinate.js @@ -0,0 +1,40 @@ +/** + * 1779. Find Nearest Point That Has the Same X or Y Coordinate + * https://leetcode.com/problems/find-nearest-point-that-has-the-same-x-or-y-coordinate/ + * Difficulty: Easy + * + * You are given two integers, x and y, which represent your current location on a Cartesian + * grid: (x, y). You are also given an array points where each points[i] = [ai, bi] represents + * that a point exists at (ai, bi). A point is valid if it shares the same x-coordinate or the + * same y-coordinate as your location. + * + * Return the index (0-indexed) of the valid point with the smallest Manhattan distance from + * your current location. If there are multiple, return the valid point with the smallest index. + * If there are no valid points, return -1. + * + * The Manhattan distance between two points (x1, y1) and (x2, y2) is abs(x1 - x2) + abs(y1 - y2). + */ + +/** + * @param {number} x + * @param {number} y + * @param {number[][]} points + * @return {number} + */ +var nearestValidPoint = function(x, y, points) { + let minDistance = Infinity; + let result = -1; + + for (let i = 0; i < points.length; i++) { + const [px, py] = points[i]; + if (px === x || py === y) { + const distance = Math.abs(px - x) + Math.abs(py - y); + if (distance < minDistance) { + minDistance = distance; + result = i; + } + } + } + + return result; +}; diff --git a/solutions/1781-sum-of-beauty-of-all-substrings.js b/solutions/1781-sum-of-beauty-of-all-substrings.js new file mode 100644 index 00000000..6c561b33 --- /dev/null +++ b/solutions/1781-sum-of-beauty-of-all-substrings.js @@ -0,0 +1,35 @@ +/** + * 1781. Sum of Beauty of All Substrings + * https://leetcode.com/problems/sum-of-beauty-of-all-substrings/ + * Difficulty: Medium + * + * The beauty of a string is the difference in frequencies between the most frequent and + * least frequent characters. + * - For example, the beauty of "abaacc" is 3 - 1 = 2. + * + * Given a string s, return the sum of beauty of all of its substrings. + */ + +/** + * @param {string} s + * @return {number} + */ +var beautySum = function(s) { + let result = 0; + + for (let i = 0; i < s.length; i++) { + const freq = new Map(); + for (let j = i; j < s.length; j++) { + freq.set(s[j], (freq.get(s[j]) || 0) + 1); + let maxFreq = 0; + let minFreq = Infinity; + for (const count of freq.values()) { + maxFreq = Math.max(maxFreq, count); + minFreq = Math.min(minFreq, count); + } + result += maxFreq - minFreq; + } + } + + return result; +}; diff --git a/solutions/1782-count-pairs-of-nodes.js b/solutions/1782-count-pairs-of-nodes.js new file mode 100644 index 00000000..d0e4f00c --- /dev/null +++ b/solutions/1782-count-pairs-of-nodes.js @@ -0,0 +1,68 @@ +/** + * 1782. Count Pairs Of Nodes + * https://leetcode.com/problems/count-pairs-of-nodes/ + * Difficulty: Hard + * + * You are given an undirected graph defined by an integer n, the number of nodes, and a 2D + * integer array edges, the edges in the graph, where edges[i] = [ui, vi] indicates that there + * is an undirected edge between ui and vi. You are also given an integer array queries. + * + * Let incident(a, b) be defined as the number of edges that are connected to either node a or b. + * + * The answer to the jth query is the number of pairs of nodes (a, b) that satisfy both of the + * following conditions: + * - a < b + * - incident(a, b) > queries[j] + * + * Return an array answers such that answers.length == queries.length and answers[j] is the + * answer of the jth query. + * + * Note that there can be multiple edges between the same two nodes. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number[]} queries + * @return {number[]} + */ +var countPairs = function(n, edges, queries) { + const degrees = Array(n + 1).fill(0); + const edgeCounts = new Map(); + + for (const [u, v] of edges) { + degrees[u]++; + degrees[v]++; + const key = u < v ? `${u},${v}` : `${v},${u}`; + edgeCounts.set(key, (edgeCounts.get(key) || 0) + 1); + } + + const sortedDegrees = [...degrees].slice(1).sort((a, b) => a - b); + const result = Array(queries.length).fill(0); + + for (let q = 0; q < queries.length; q++) { + let total = 0; + let left = 0; + let right = n - 1; + + while (left < right) { + if (sortedDegrees[left] + sortedDegrees[right] > queries[q]) { + total += right - left; + right--; + } else { + left++; + } + } + + for (const [key, count] of edgeCounts) { + const [u, v] = key.split(',').map(Number); + if (degrees[u] + degrees[v] > queries[q] && degrees[u] + degrees[v] - count <= queries[q]) { + total--; + } + } + + result[q] = total; + } + + return result; +}; diff --git a/solutions/1784-check-if-binary-string-has-at-most-one-segment-of-ones.js b/solutions/1784-check-if-binary-string-has-at-most-one-segment-of-ones.js new file mode 100644 index 00000000..4f3e3fb9 --- /dev/null +++ b/solutions/1784-check-if-binary-string-has-at-most-one-segment-of-ones.js @@ -0,0 +1,26 @@ +/** + * 1784. Check if Binary String Has at Most One Segment of Ones + * https://leetcode.com/problems/check-if-binary-string-has-at-most-one-segment-of-ones/ + * Difficulty: Easy + * + * Given a binary string s without leading zeros, return true if s contains at most one + * contiguous segment of ones. Otherwise, return false. + */ + +/** + * @param {string} s + * @return {boolean} + */ +var checkOnesSegment = function(s) { + let seenZero = false; + + for (let i = 1; i < s.length; i++) { + if (s[i] === '0') { + seenZero = true; + } else if (seenZero) { + return false; + } + } + + return true; +}; diff --git a/solutions/1785-minimum-elements-to-add-to-form-a-given-sum.js b/solutions/1785-minimum-elements-to-add-to-form-a-given-sum.js new file mode 100644 index 00000000..7b27b2c7 --- /dev/null +++ b/solutions/1785-minimum-elements-to-add-to-form-a-given-sum.js @@ -0,0 +1,25 @@ +/** + * 1785. Minimum Elements to Add to Form a Given Sum + * https://leetcode.com/problems/minimum-elements-to-add-to-form-a-given-sum/ + * Difficulty: Medium + * + * You are given an integer array nums and two integers limit and goal. The array nums has + * an interesting property that abs(nums[i]) <= limit. + * + * Return the minimum number of elements you need to add to make the sum of the array equal + * to goal. The array must maintain its property that abs(nums[i]) <= limit. + * + * Note that abs(x) equals x if x >= 0, and -x otherwise. + */ + +/** + * @param {number[]} nums + * @param {number} limit + * @param {number} goal + * @return {number} + */ +var minElements = function(nums, limit, goal) { + const currentSum = nums.reduce((sum, num) => sum + num, 0); + const difference = Math.abs(goal - currentSum); + return Math.ceil(difference / limit); +}; diff --git a/solutions/1786-number-of-restricted-paths-from-first-to-last-node.js b/solutions/1786-number-of-restricted-paths-from-first-to-last-node.js new file mode 100644 index 00000000..e55ddab4 --- /dev/null +++ b/solutions/1786-number-of-restricted-paths-from-first-to-last-node.js @@ -0,0 +1,80 @@ +/** + * 1786. Number of Restricted Paths From First to Last Node + * https://leetcode.com/problems/number-of-restricted-paths-from-first-to-last-node/ + * Difficulty: Medium + * + * There is an undirected weighted connected graph. You are given a positive integer n which + * denotes that the graph has n nodes labeled from 1 to n, and an array edges where each + * edges[i] = [ui, vi, weighti] denotes that there is an edge between nodes ui and vi with + * weight equal to weighti. + * + * A path from node start to node end is a sequence of nodes [z0, z1, z2, ..., zk] such that + * z0 = start and zk = end and there is an edge between zi and zi+1 where 0 <= i <= k-1. + * + * The distance of a path is the sum of the weights on the edges of the path. Let + * distanceToLastNode(x) denote the shortest distance of a path between node n and node x. + * A restricted path is a path that also satisfies that + * distanceToLastNode(zi) > distanceToLastNode(zi+1) where 0 <= i <= k-1. + * + * Return the number of restricted paths from node 1 to node n. Since that number may be too + * large, return it modulo 109 + 7. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @return {number} + */ +var countRestrictedPaths = function(n, edges) { + const MODULO = 1e9 + 7; + const graph = {}; + for (const [u, v, weight] of edges) { + (graph[u] ??= []).push({ edge: v, weight }); + (graph[v] ??= []).push({ edge: u, weight }); + } + + const distances = new Array(n + 1).fill(Number.MAX_SAFE_INTEGER); + distances[n] = 0; + + const NOT_VISITED = 0; + const VISITED = 1; + const IN_QUEUE = 2; + const states = new Array(n + 1).fill(NOT_VISITED); + const queue = [n]; + + while (queue.length) { + const node = queue.shift(); + states[node] = IN_QUEUE; + + for (const { edge, weight } of graph[node]) { + if (distances[node] + weight >= distances[edge]) continue; + + distances[edge] = distances[node] + weight; + + if (states[edge] === NOT_VISITED) { + queue.push(edge); + states[edge] = VISITED; + } else if (states[edge] === IN_QUEUE) { + queue.unshift(edge); + } + } + } + + const memo = new Map([[n, 1]]); + + return countPaths(1); + + function countPaths(node) { + if (memo.has(node)) return memo.get(node); + + let count = 0; + for (const { edge } of graph[node]) { + if (distances[edge] < distances[node]) { + count = (count + countPaths(edge)) % MODULO; + } + } + + memo.set(node, count); + return count; + } +}; diff --git a/solutions/1787-make-the-xor-of-all-segments-equal-to-zero.js b/solutions/1787-make-the-xor-of-all-segments-equal-to-zero.js new file mode 100644 index 00000000..7817c120 --- /dev/null +++ b/solutions/1787-make-the-xor-of-all-segments-equal-to-zero.js @@ -0,0 +1,51 @@ +/** + * 1787. Make the XOR of All Segments Equal to Zero + * https://leetcode.com/problems/make-the-xor-of-all-segments-equal-to-zero/ + * Difficulty: Hard + * + * You are given an array nums and an integer k. The XOR of a segment [left, right] where + * left <= right is the XOR of all the elements with indices between left and right, + * inclusive: nums[left] XOR nums[left+1] XOR ... XOR nums[right]. + * + * Return the minimum number of elements to change in the array such that the XOR of all + * segments of size k is equal to zero. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minChanges = function(nums, k) { + const n = nums.length; + const maxVal = 1 << 10; + const groups = new Array(k).fill().map(() => new Map()); + + for (let i = 0; i < n; i++) { + groups[i % k].set(nums[i], (groups[i % k].get(nums[i]) || 0) + 1); + } + + const dp = new Array(maxVal).fill(n); + dp[0] = 0; + + for (let pos = 0; pos < k; pos++) { + const prevDp = [...dp]; + dp.fill(n); + const groupSize = Math.floor(n / k) + (pos < n % k ? 1 : 0); + const minPrev = Math.min(...prevDp); + + for (let xor = 0; xor < maxVal; xor++) { + if (prevDp[xor] === n) continue; + for (const [val, count] of groups[pos]) { + const newXor = xor ^ val; + dp[newXor] = Math.min(dp[newXor], prevDp[xor] + groupSize - count); + } + } + + for (let xor = 0; xor < maxVal; xor++) { + dp[xor] = Math.min(dp[xor], minPrev + groupSize); + } + } + + return dp[0]; +}; 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/1792-maximum-average-pass-ratio.js b/solutions/1792-maximum-average-pass-ratio.js new file mode 100644 index 00000000..3ff9c5b3 --- /dev/null +++ b/solutions/1792-maximum-average-pass-ratio.js @@ -0,0 +1,107 @@ +/** + * 1792. Maximum Average Pass Ratio + * https://leetcode.com/problems/maximum-average-pass-ratio/ + * Difficulty: Medium + * + * There is a school that has classes of students and each class will be having a final exam. + * You are given a 2D integer array classes, where classes[i] = [passi, totali]. You know + * beforehand that in the ith class, there are totali total students, but only passi number + * of students will pass the exam. + * + * You are also given an integer extraStudents. There are another extraStudents brilliant + * students that are guaranteed to pass the exam of any class they are assigned to. You want + * to assign each of the extraStudents students to a class in a way that maximizes the average + * pass ratio across all the classes. + * + * The pass ratio of a class is equal to the number of students of the class that will pass + * the exam divided by the total number of students of the class. The average pass ratio is + * the sum of pass ratios of all the classes divided by the number of the classes. + * + * Return the maximum possible average pass ratio after assigning the extraStudents students. + * Answers within 10-5 of the actual answer will be accepted. + */ + +/** +* @param {number[][]} classes +* @param {number} extraStudents +* @return {number} +*/ +var maxAverageRatio = function(classes, extraStudents) { + const maxHeap = []; + + for (const [pass, total] of classes) { + const profit = getProfit(pass, total); + maxHeap.push([profit, pass, total]); + } + + heapify(); + + for (let i = 0; i < extraStudents; i++) { + const [_, pass, total] = extractMax(); + const newPass = pass + 1; + const newTotal = total + 1; + const newProfit = getProfit(newPass, newTotal); + insert([newProfit, newPass, newTotal]); + } + + let sumRatio = 0; + for (const [_, pass, total] of maxHeap) { + sumRatio += pass / total; + } + + return sumRatio / classes.length; + + function getProfit(pass, total) { + return (pass + 1) / (total + 1) - pass / total; + } + + function heapify() { + for (let i = Math.floor(maxHeap.length / 2) - 1; i >= 0; i--) { + siftDown(i); + } + } + + function siftDown(i) { + const left = 2 * i + 1; + const right = 2 * i + 2; + let largest = i; + + if (left < maxHeap.length && maxHeap[left][0] > maxHeap[largest][0]) { + largest = left; + } + + if (right < maxHeap.length && maxHeap[right][0] > maxHeap[largest][0]) { + largest = right; + } + + if (largest !== i) { + [maxHeap[i], maxHeap[largest]] = [maxHeap[largest], maxHeap[i]]; + siftDown(largest); + } + } + + function extractMax() { + const max = maxHeap[0]; + const last = maxHeap.pop(); + + if (maxHeap.length > 0) { + maxHeap[0] = last; + siftDown(0); + } + + return max; + } + + function insert(item) { + maxHeap.push(item); + + let i = maxHeap.length - 1; + let parent = Math.floor((i - 1) / 2); + + while (i > 0 && maxHeap[i][0] > maxHeap[parent][0]) { + [maxHeap[i], maxHeap[parent]] = [maxHeap[parent], maxHeap[i]]; + i = parent; + parent = Math.floor((i - 1) / 2); + } + } +}; diff --git a/solutions/1793-maximum-score-of-a-good-subarray.js b/solutions/1793-maximum-score-of-a-good-subarray.js new file mode 100644 index 00000000..9a662c67 --- /dev/null +++ b/solutions/1793-maximum-score-of-a-good-subarray.js @@ -0,0 +1,42 @@ +/** + * 1793. Maximum Score of a Good Subarray + * https://leetcode.com/problems/maximum-score-of-a-good-subarray/ + * Difficulty: Hard + * + * You are given an array of integers nums (0-indexed) and an integer k. + * + * The score of a subarray (i, j) is defined as min(nums[i], nums[i+1], ..., nums[j]) * + * (j - i + 1). A good subarray is a subarray where i <= k <= j. + * + * Return the maximum possible score of a good subarray. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var maximumScore = function(nums, k) { + let result = nums[k]; + let minimum = nums[k]; + let left = k; + let right = k; + const length = nums.length; + + while (left > 0 || right < length - 1) { + const leftValue = left > 0 ? nums[left - 1] : 0; + const rightValue = right < length - 1 ? nums[right + 1] : 0; + + if (leftValue >= rightValue) { + left--; + minimum = Math.min(minimum, leftValue); + } else { + right++; + minimum = Math.min(minimum, rightValue); + } + + result = Math.max(result, minimum * (right - left + 1)); + } + + 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/1796-second-largest-digit-in-a-string.js b/solutions/1796-second-largest-digit-in-a-string.js new file mode 100644 index 00000000..196ba422 --- /dev/null +++ b/solutions/1796-second-largest-digit-in-a-string.js @@ -0,0 +1,33 @@ +/** + * 1796. Second Largest Digit in a String + * https://leetcode.com/problems/second-largest-digit-in-a-string/ + * Difficulty: Easy + * + * Given an alphanumeric string s, return the second largest numerical digit that appears in + * s, or -1 if it does not exist. + * + * An alphanumeric string is a string consisting of lowercase English letters and digits. + */ + +/** + * @param {string} s + * @return {number} + */ +var secondHighest = function(s) { + let largest = -1; + let result = -1; + + for (const char of s) { + if (/\d/.test(char)) { + const digit = parseInt(char); + if (digit > largest) { + result = largest; + largest = digit; + } else if (digit < largest && digit > result) { + result = digit; + } + } + } + + return result; +}; diff --git a/solutions/1797-design-authentication-manager.js b/solutions/1797-design-authentication-manager.js new file mode 100644 index 00000000..e631c416 --- /dev/null +++ b/solutions/1797-design-authentication-manager.js @@ -0,0 +1,68 @@ +/** + * 1797. Design Authentication Manager + * https://leetcode.com/problems/design-authentication-manager/ + * Difficulty: Medium + * + * There is an authentication system that works with authentication tokens. For each session, + * the user will receive a new authentication token that will expire timeToLive seconds after + * the currentTime. If the token is renewed, the expiry time will be extended to expire + * timeToLive seconds after the (potentially different) currentTime. + * + * Implement the AuthenticationManager class: + * - AuthenticationManager(int timeToLive) constructs the AuthenticationManager and sets the + * timeToLive. + * - generate(string tokenId, int currentTime) generates a new token with the given tokenId + * at the given currentTime in seconds. + * - renew(string tokenId, int currentTime) renews the unexpired token with the given tokenId + * at the given currentTime in seconds. If there are no unexpired tokens with the given + * tokenId, the request is ignored, and nothing happens. + * - countUnexpiredTokens(int currentTime) returns the number of unexpired tokens at the + * given currentTime. + * + * Note that if a token expires at time t, and another action happens on time t (renew or + * countUnexpiredTokens), the expiration takes place before the other actions. + */ + +/** + * @param {number} timeToLive + */ +var AuthenticationManager = function(timeToLive) { + this.timeToLive = timeToLive; + this.tokens = new Map(); +}; + +/** + * @param {string} tokenId + * @param {number} currentTime + * @return {void} + */ +AuthenticationManager.prototype.generate = function(tokenId, currentTime) { + this.tokens.set(tokenId, currentTime + this.timeToLive); +}; + +/** + * @param {string} tokenId + * @param {number} currentTime + * @return {void} + */ +AuthenticationManager.prototype.renew = function(tokenId, currentTime) { + if (this.tokens.has(tokenId) && this.tokens.get(tokenId) > currentTime) { + this.tokens.set(tokenId, currentTime + this.timeToLive); + } +}; + +/** + * @param {number} currentTime + * @return {number} + */ +AuthenticationManager.prototype.countUnexpiredTokens = function(currentTime) { + let count = 0; + for (const [tokenId, expiry] of this.tokens) { + if (expiry > currentTime) { + count++; + } else { + this.tokens.delete(tokenId); + } + } + return count; +}; diff --git a/solutions/1798-maximum-number-of-consecutive-values-you-can-make.js b/solutions/1798-maximum-number-of-consecutive-values-you-can-make.js new file mode 100644 index 00000000..0c91d2de --- /dev/null +++ b/solutions/1798-maximum-number-of-consecutive-values-you-can-make.js @@ -0,0 +1,30 @@ +/** + * 1798. Maximum Number of Consecutive Values You Can Make + * https://leetcode.com/problems/maximum-number-of-consecutive-values-you-can-make/ + * Difficulty: Medium + * + * You are given an integer array coins of length n which represents the n coins that you + * own. The value of the ith coin is coins[i]. You can make some value x if you can choose + * some of your n coins such that their values sum up to x. + * + * Return the maximum number of consecutive integer values that you can make with your coins + * starting from and including 0. + * + * Note that you may have multiple coins of the same value. + */ + +/** + * @param {number[]} coins + * @return {number} + */ +var getMaximumConsecutive = function(coins) { + let maxReachable = 0; + + coins.sort((a, b) => a - b); + for (const coin of coins) { + if (coin > maxReachable + 1) break; + maxReachable += coin; + } + + return maxReachable + 1; +}; diff --git a/solutions/1799-maximize-score-after-n-operations.js b/solutions/1799-maximize-score-after-n-operations.js new file mode 100644 index 00000000..eb7a2e3b --- /dev/null +++ b/solutions/1799-maximize-score-after-n-operations.js @@ -0,0 +1,59 @@ +/** + * 1799. Maximize Score After N Operations + * https://leetcode.com/problems/maximize-score-after-n-operations/ + * Difficulty: Hard + * + * You are given nums, an array of positive integers of size 2 * n. You must perform n operations + * on this array. + * + * In the ith operation (1-indexed), you will: + * - Choose two elements, x and y. + * - Receive a score of i * gcd(x, y). + * - Remove x and y from nums. + * + * Return the maximum score you can receive after performing n operations. + * + * The function gcd(x, y) is the greatest common divisor of x and y. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxScore = function(nums) { + const n = nums.length; + const pairsGcd = Array(n).fill().map(() => Array(n).fill(0)); + for (let i = 0; i < n; i++) { + for (let j = i + 1; j < n; j++) { + pairsGcd[i][j] = gcd(nums[i], nums[j]); + } + } + + return solve(1, 0, {}, pairsGcd); + + function gcd(a, b) { + while (b) { + a %= b; + [a, b] = [b, a]; + } + return a; + } + + function solve(operations, mask, memo, pairsGcd) { + if (operations > nums.length / 2) return 0; + if (memo[mask] !== undefined) return memo[mask]; + + let maxScore = 0; + for (let i = 0; i < nums.length; i++) { + if (mask & (1 << i)) continue; + for (let j = i + 1; j < nums.length; j++) { + if (mask & (1 << j)) continue; + const newMask = mask | (1 << i) | (1 << j); + const score = operations * pairsGcd[i][j] + solve(operations + 1, newMask, memo, pairsGcd); + maxScore = Math.max(maxScore, score); + } + } + + return memo[mask] = maxScore; + } +}; diff --git a/solutions/1801-number-of-orders-in-the-backlog.js b/solutions/1801-number-of-orders-in-the-backlog.js new file mode 100644 index 00000000..1c9501c0 --- /dev/null +++ b/solutions/1801-number-of-orders-in-the-backlog.js @@ -0,0 +1,73 @@ +/** + * 1801. Number of Orders in the Backlog + * https://leetcode.com/problems/number-of-orders-in-the-backlog/ + * Difficulty: Medium + * + * You are given a 2D integer array orders, where each orders[i] = [pricei, amounti, orderTypei] + * denotes that amounti orders have been placed of type orderTypei at the price pricei. + * The orderTypei is: + * - 0 if it is a batch of buy orders, or + * - 1 if it is a batch of sell orders. + * + * Note that orders[i] represents a batch of amounti independent orders with the same price and + * order type. All orders represented by orders[i] will be placed before all orders represented + * by orders[i+1] for all valid i. + * + * There is a backlog that consists of orders that have not been executed. The backlog is initially + * empty. When an order is placed, the following happens: + * - If the order is a buy order, you look at the sell order with the smallest price in the backlog. + * If that sell order's price is smaller than or equal to the current buy order's price, they will + * match and be executed, and that sell order will be removed from the backlog. Else, the buy + * order is added to the backlog. + * - Vice versa, if the order is a sell order, you look at the buy order with the largest price in + * the backlog. If that buy order's price is larger than or equal to the current sell order's + * price, they will match and be executed, and that buy order will be removed from the backlog. + * Else, the sell order is added to the backlog. + * + * Return the total amount of orders in the backlog after placing all the orders from the input. + * Since this number can be large, return it modulo 109 + 7. + */ + +/** + * @param {number[][]} orders + * @return {number} + */ +var getNumberOfBacklogOrders = function(orders) { + const MOD = 1e9 + 7; + const buyOrders = new MinPriorityQueue(); + const sellOrders = new MinPriorityQueue(); + + for (let [price, amount, type] of orders) { + if (type === 0) { + const order = { price: -price, amount, originalPrice: price, valueOf: () => -price }; + while (amount > 0 && !sellOrders.isEmpty() && sellOrders.front().price <= price) { + const sellOrder = sellOrders.dequeue(); + const matchAmount = Math.min(amount, sellOrder.amount); + amount -= matchAmount; + sellOrder.amount -= matchAmount; + if (sellOrder.amount > 0) sellOrders.enqueue(sellOrder); + } + if (amount > 0) buyOrders.enqueue({ ...order, amount }); + } else { + const order = { price, amount, valueOf: () => price }; + while (amount > 0 && !buyOrders.isEmpty() && buyOrders.front().originalPrice >= price) { + const buyOrder = buyOrders.dequeue(); + const matchAmount = Math.min(amount, buyOrder.amount); + amount -= matchAmount; + buyOrder.amount -= matchAmount; + if (buyOrder.amount > 0) buyOrders.enqueue(buyOrder); + } + if (amount > 0) sellOrders.enqueue({ ...order, amount }); + } + } + + let total = 0; + while (!buyOrders.isEmpty()) { + total = (total + buyOrders.dequeue().amount) % MOD; + } + while (!sellOrders.isEmpty()) { + total = (total + sellOrders.dequeue().amount) % MOD; + } + + return total; +}; diff --git a/solutions/1802-maximum-value-at-a-given-index-in-a-bounded-array.js b/solutions/1802-maximum-value-at-a-given-index-in-a-bounded-array.js new file mode 100644 index 00000000..bc7fba1a --- /dev/null +++ b/solutions/1802-maximum-value-at-a-given-index-in-a-bounded-array.js @@ -0,0 +1,51 @@ +/** + * 1802. Maximum Value at a Given Index in a Bounded Array + * https://leetcode.com/problems/maximum-value-at-a-given-index-in-a-bounded-array/ + * Difficulty: Medium + * + * You are given three positive integers: n, index, and maxSum. You want to construct an array + * nums (0-indexed) that satisfies the following conditions: + * - nums.length == n + * - nums[i] is a positive integer where 0 <= i < n. + * - abs(nums[i] - nums[i+1]) <= 1 where 0 <= i < n-1. + * - The sum of all the elements of nums does not exceed maxSum. + * - nums[index] is maximized. + * + * Return nums[index] of the constructed array. + * + * Note that abs(x) equals x if x >= 0, and -x otherwise. + */ + +/** + * @param {number} n + * @param {number} index + * @param {number} maxSum + * @return {number} + */ +var maxValue = function(n, index, maxSum) { + function minSumRequired(peak) { + const leftCount = Math.min(index, peak - 1); + const rightCount = Math.min(n - index - 1, peak - 1); + let sum = peak; + sum += (peak - 1 + peak - leftCount) * leftCount / 2; + sum += (peak - 1 + peak - rightCount) * rightCount / 2; + sum += (index - leftCount) + (n - index - 1 - rightCount); + return sum; + } + + let low = 1; + let high = maxSum; + let result = 1; + + while (low <= high) { + const mid = Math.floor((low + high) / 2); + if (minSumRequired(mid) <= maxSum) { + result = mid; + low = mid + 1; + } else { + high = mid - 1; + } + } + + return result; +}; diff --git a/solutions/1803-count-pairs-with-xor-in-a-range.js b/solutions/1803-count-pairs-with-xor-in-a-range.js new file mode 100644 index 00000000..1912bf08 --- /dev/null +++ b/solutions/1803-count-pairs-with-xor-in-a-range.js @@ -0,0 +1,67 @@ +/** + * 1803. Count Pairs With XOR in a Range + * https://leetcode.com/problems/count-pairs-with-xor-in-a-range/ + * Difficulty: Hard + * + * Given a (0-indexed) integer array nums and two integers low and high, return the number + * of nice pairs. + * + * A nice pair is a pair (i, j) where 0 <= i < j < nums.length and low <= (nums[i] XOR + * nums[j]) <= high. + */ + +/** + * @param {number[]} nums + * @param {number} low + * @param {number} high + * @return {number} + */ +var countPairs = function(nums, low, high) { + const root = new TrieNode(); + let total = 0; + + for (const num of nums) { + total += countPairsInRange(num, high, root) - countPairsInRange(num, low - 1, root); + insert(num, root); + } + + return total; +}; + +class TrieNode { + constructor() { + this.children = [null, null]; + this.count = 0; + } +} + +function countPairsInRange(num, limit, root, depth = 14) { + let count = 0; + let node = root; + for (let i = depth; i >= 0 && node; i--) { + const numBit = (num >> i) & 1; + const limitBit = (limit >> i) & 1; + if (limitBit === 0) { + node = node.children[numBit]; + } else { + if (node.children[numBit]) { + count += node.children[numBit].count; + } + node = node.children[numBit ^ 1]; + } + } + return count + (node ? node.count : 0); +} + +function insert(num, root) { + let node = root; + for (let i = 14; i >= 0; i--) { + const bit = (num >> i) & 1; + if (!node.children[bit]) { + node.children[bit] = new TrieNode(); + } + node = node.children[bit]; + node.count++; + } +} + 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/1805-number-of-different-integers-in-a-string.js b/solutions/1805-number-of-different-integers-in-a-string.js new file mode 100644 index 00000000..61b6f693 --- /dev/null +++ b/solutions/1805-number-of-different-integers-in-a-string.js @@ -0,0 +1,40 @@ +/** + * 1805. Number of Different Integers in a String + * https://leetcode.com/problems/number-of-different-integers-in-a-string/ + * Difficulty: Easy + * + * You are given a string word that consists of digits and lowercase English letters. + * + * You will replace every non-digit character with a space. For example, "a123bc34d8ef34" + * will become " 123 34 8 34". Notice that you are left with some integers that are + * separated by at least one space: "123", "34", "8", and "34". + * + * Return the number of different integers after performing the replacement operations on word. + * + * Two integers are considered different if their decimal representations without any leading + * zeros are different. + */ + +/** + * @param {string} word + * @return {number} + */ +var numDifferentIntegers = function(word) { + const uniqueIntegers = new Set(); + let currentNum = ''; + + for (const char of word) { + if (/\d/.test(char)) { + currentNum += char; + } else if (currentNum) { + uniqueIntegers.add(String(BigInt(currentNum))); + currentNum = ''; + } + } + + if (currentNum) { + uniqueIntegers.add(String(BigInt(currentNum))); + } + + return uniqueIntegers.size; +}; diff --git a/solutions/1806-minimum-number-of-operations-to-reinitialize-a-permutation.js b/solutions/1806-minimum-number-of-operations-to-reinitialize-a-permutation.js new file mode 100644 index 00000000..5ba88490 --- /dev/null +++ b/solutions/1806-minimum-number-of-operations-to-reinitialize-a-permutation.js @@ -0,0 +1,37 @@ +/** + * 1806. Minimum Number of Operations to Reinitialize a Permutation + * https://leetcode.com/problems/minimum-number-of-operations-to-reinitialize-a-permutation/ + * Difficulty: Medium + * + * You are given an even integer n. You initially have a permutation perm of size n where + * perm[i] == i (0-indexed). + * + * In one operation, you will create a new array arr, and for each i: + * - If i % 2 == 0, then arr[i] = perm[i / 2]. + * - If i % 2 == 1, then arr[i] = perm[n / 2 + (i - 1) / 2]. + * + * You will then assign arr to perm. + * + * Return the minimum non-zero number of operations you need to perform on perm to return the + * permutation to its initial value. + */ + +/** + * @param {number} n + * @return {number} + */ +var reinitializePermutation = function(n) { + let currentIndex = 1; + let result = 0; + + do { + if (currentIndex % 2 === 0) { + currentIndex = currentIndex / 2; + } else { + currentIndex = n / 2 + (currentIndex - 1) / 2; + } + result++; + } while (currentIndex !== 1); + + return result; +}; diff --git a/solutions/1807-evaluate-the-bracket-pairs-of-a-string.js b/solutions/1807-evaluate-the-bracket-pairs-of-a-string.js new file mode 100644 index 00000000..7fffdc33 --- /dev/null +++ b/solutions/1807-evaluate-the-bracket-pairs-of-a-string.js @@ -0,0 +1,51 @@ +/** + * 1807. Evaluate the Bracket Pairs of a String + * https://leetcode.com/problems/evaluate-the-bracket-pairs-of-a-string/ + * Difficulty: Medium + * + * You are given a string s that contains some bracket pairs, with each pair containing + * a non-empty key. + * + * - For example, in the string "(name)is(age)yearsold", there are two bracket pairs that contain + * the keys "name" and "age". + * + * You know the values of a wide range of keys. This is represented by a 2D string array knowledge + * where each knowledge[i] = [keyi, valuei] indicates that key keyi has a value of valuei. + * + * You are tasked to evaluate all of the bracket pairs. When you evaluate a bracket pair that + * contains some key keyi, you will: + * - Replace keyi and the bracket pair with the key's corresponding valuei. + * - If you do not know the value of the key, you will replace keyi and the bracket pair with a + * question mark "?" (without the quotation marks). + * + * Each key will appear at most once in your knowledge. There will not be any nested brackets in s. + * + * Return the resulting string after evaluating all of the bracket pairs. + */ + +/** + * @param {string} s + * @param {string[][]} knowledge + * @return {string} + */ +var evaluate = function(s, knowledge) { + const keyValueMap = new Map(knowledge); + let result = ''; + let i = 0; + + while (i < s.length) { + if (s[i] === '(') { + i++; + let key = ''; + while (i < s.length && s[i] !== ')') { + key += s[i++]; + } + result += keyValueMap.get(key) || '?'; + i++; + } else { + result += s[i++]; + } + } + + return result; +}; diff --git a/solutions/1808-maximize-number-of-nice-divisors.js b/solutions/1808-maximize-number-of-nice-divisors.js new file mode 100644 index 00000000..49f3697a --- /dev/null +++ b/solutions/1808-maximize-number-of-nice-divisors.js @@ -0,0 +1,48 @@ +/** + * 1808. Maximize Number of Nice Divisors + * https://leetcode.com/problems/maximize-number-of-nice-divisors/ + * Difficulty: Hard + * + * You are given a positive integer primeFactors. You are asked to construct a positive + * integer n that satisfies the following conditions: + * - The number of prime factors of n (not necessarily distinct) is at most primeFactors. + * - The number of nice divisors of n is maximized. Note that a divisor of n is nice if it + * is divisible by every prime factor of n. For example, if n = 12, then its prime factors + * are [2,2,3], then 6 and 12 are nice divisors, while 3 and 4 are not. + * + * Return the number of nice divisors of n. Since that number can be too large, return it + * modulo 109 + 7. + * + * Note that a prime number is a natural number greater than 1 that is not a product of two + * smaller natural numbers. The prime factors of a number n is a list of prime numbers such + * that their product equals n. + */ + +/** + * @param {number} primeFactors + * @return {number} + */ +var maxNiceDivisors = function(primeFactors) { + const MOD = 1e9 + 7; + + if (primeFactors <= 3) return primeFactors; + + const quotient = Math.floor(primeFactors / 3); + const remainder = primeFactors % 3; + + if (remainder === 0) return power(3, quotient); + if (remainder === 1) return (power(3, quotient - 1) * 4) % MOD; + + return (power(3, quotient) * 2) % MOD; + + function power(base, exponent) { + let result = BigInt(1); + base = BigInt(base); + while (exponent > 0) { + if (exponent & 1) result = (result * base) % BigInt(MOD); + base = (base * base) % BigInt(MOD); + exponent >>= 1; + } + return Number(result); + } +}; 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/1813-sentence-similarity-iii.js b/solutions/1813-sentence-similarity-iii.js new file mode 100644 index 00000000..872cea74 --- /dev/null +++ b/solutions/1813-sentence-similarity-iii.js @@ -0,0 +1,46 @@ +/** + * 1813. Sentence Similarity III + * https://leetcode.com/problems/sentence-similarity-iii/ + * Difficulty: Medium + * + * You are given two strings sentence1 and sentence2, each representing a sentence composed of + * words. A sentence is a list of words that are separated by a single space with no leading + * or trailing spaces. Each word consists of only uppercase and lowercase English characters. + * + * Two sentences s1 and s2 are considered similar if it is possible to insert an arbitrary + * sentence (possibly empty) inside one of these sentences such that the two sentences become + * equal. Note that the inserted sentence must be separated from existing words by spaces. + * + * For example: + * - s1 = "Hello Jane" and s2 = "Hello my name is Jane" can be made equal by inserting "my name is" + * between "Hello" and "Jane" in s1. + * - s1 = "Frog cool" and s2 = "Frogs are cool" are not similar, since although there is a sentence + * "s are" inserted into s1, it is not separated from "Frog" by a space. + * + * Given two sentences sentence1 and sentence2, return true if sentence1 and sentence2 are + * similar. Otherwise, return false. + */ + +/** + * @param {string} sentence1 + * @param {string} sentence2 + * @return {boolean} + */ +var areSentencesSimilar = function(sentence1, sentence2) { + let words1 = sentence1.split(' '); + let words2 = sentence2.split(' '); + if (words1.length < words2.length) [words1, words2] = [words2, words1]; + + let prefixLength = 0; + while (prefixLength < words2.length && words1[prefixLength] === words2[prefixLength]) { + prefixLength++; + } + + let suffixLength = 0; + while (suffixLength < words2.length - prefixLength + && words1[words1.length - 1 - suffixLength] === words2[words2.length - 1 - suffixLength]) { + suffixLength++; + } + + return prefixLength + suffixLength >= words2.length; +}; diff --git a/solutions/1814-count-nice-pairs-in-an-array.js b/solutions/1814-count-nice-pairs-in-an-array.js new file mode 100644 index 00000000..f8db6cc5 --- /dev/null +++ b/solutions/1814-count-nice-pairs-in-an-array.js @@ -0,0 +1,37 @@ +/** + * 1814. Count Nice Pairs in an Array + * https://leetcode.com/problems/count-nice-pairs-in-an-array/ + * Difficulty: Medium + * + * You are given an array nums that consists of non-negative integers. Let us define rev(x) + * as the reverse of the non-negative integer x. For example, rev(123) = 321, and rev(120) = 21. + * A pair of indices (i, j) is nice if it satisfies all of the following conditions: + * - 0 <= i < j < nums.length + * - nums[i] + rev(nums[j]) == nums[j] + rev(nums[i]) + * + * Return the number of nice pairs of indices. Since that number can be too large, return it + * modulo 109 + 7. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var countNicePairs = function(nums) { + const MOD = 1e9 + 7; + const map = new Map(); + let result = 0; + + for (const num of nums) { + const diff = num - reverseNumber(num); + const count = map.get(diff) || 0; + result = (result + count) % MOD; + map.set(diff, count + 1); + } + + return result; + + function reverseNumber(num) { + return Number(String(num).split('').reverse().join('')); + } +}; diff --git a/solutions/1815-maximum-number-of-groups-getting-fresh-donuts.js b/solutions/1815-maximum-number-of-groups-getting-fresh-donuts.js new file mode 100644 index 00000000..fcd73dc8 --- /dev/null +++ b/solutions/1815-maximum-number-of-groups-getting-fresh-donuts.js @@ -0,0 +1,59 @@ +/** + * 1815. Maximum Number of Groups Getting Fresh Donuts + * https://leetcode.com/problems/maximum-number-of-groups-getting-fresh-donuts/ + * Difficulty: Hard + * + * There is a donuts shop that bakes donuts in batches of batchSize. They have a rule where they + * must serve all of the donuts of a batch before serving any donuts of the next batch. You are + * given an integer batchSize and an integer array groups, where groups[i] denotes that there is + * a group of groups[i] customers that will visit the shop. Each customer will get exactly one + * donut. + * + * When a group visits the shop, all customers of the group must be served before serving any + * of the following groups. A group will be happy if they all get fresh donuts. That is, the + * first customer of the group does not receive a donut that was left over from the previous group. + * + * You can freely rearrange the ordering of the groups. Return the maximum possible number of + * happy groups after rearranging the groups. + */ + +/** + * @param {number} batchSize + * @param {number[]} groups + * @return {number} + */ +var maxHappyGroups = function(batchSize, groups) { + const remainders = new Array(batchSize).fill(0); + let result = 0; + + for (const size of groups) { + remainders[size % batchSize]++; + } + + result += remainders[0]; + remainders[0] = 0; + + return result + findMaxHappy(remainders, 0); + + function findMaxHappy(remainders, leftover, memo = new Map()) { + const key = remainders.join(',') + ',' + leftover; + if (memo.has(key)) return memo.get(key); + + let maxHappy = 0; + for (let i = 1; i < batchSize; i++) { + if (remainders[i] === 0) continue; + remainders[i]--; + + let current = 0; + if (leftover === 0) current = 1; + maxHappy = Math.max( + maxHappy, current + findMaxHappy(remainders, (leftover + i) % batchSize, memo) + ); + + remainders[i]++; + } + + memo.set(key, maxHappy); + return maxHappy; + } +}; diff --git a/solutions/1816-truncate-sentence.js b/solutions/1816-truncate-sentence.js new file mode 100644 index 00000000..d0d91e32 --- /dev/null +++ b/solutions/1816-truncate-sentence.js @@ -0,0 +1,22 @@ +/** + * 1816. Truncate Sentence + * https://leetcode.com/problems/truncate-sentence/ + * Difficulty: Easy + * + * A sentence is a list of words that are separated by a single space with no leading or + * trailing spaces. Each of the words consists of only uppercase and lowercase English + * letters (no punctuation). + * - For example, "Hello World", "HELLO", and "hello world hello world" are all sentences. + * + * You are given a sentence s and an integer k. You want to truncate s such that it contains + * only the first k words. Return s after truncating it. + */ + +/** + * @param {string} s + * @param {number} k + * @return {string} + */ +var truncateSentence = function(s, k) { + return s.split(' ').slice(0, k).join(' '); +}; diff --git a/solutions/1818-minimum-absolute-sum-difference.js b/solutions/1818-minimum-absolute-sum-difference.js new file mode 100644 index 00000000..fb1cc1dc --- /dev/null +++ b/solutions/1818-minimum-absolute-sum-difference.js @@ -0,0 +1,51 @@ +/** + * 1818. Minimum Absolute Sum Difference + * https://leetcode.com/problems/minimum-absolute-sum-difference/ + * Difficulty: Medium + * + * You are given two positive integer arrays nums1 and nums2, both of length n. + * + * The absolute sum difference of arrays nums1 and nums2 is defined as the sum of + * |nums1[i] - nums2[i]| for each 0 <= i < n (0-indexed). + * + * You can replace at most one element of nums1 with any other element in nums1 to minimize + * the absolute sum difference. + * + * Return the minimum absolute sum difference after replacing at most one element in the + * array nums1. Since the answer may be large, return it modulo 109 + 7. + * + * |x| is defined as: + * - x if x >= 0, or + * - -x if x < 0. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var minAbsoluteSumDiff = function(nums1, nums2) { + const MOD = 1e9 + 7; + const sortedNums1 = [...nums1].sort((a, b) => a - b); + let totalDiff = 0; + let maxReduction = 0; + + for (let i = 0; i < nums1.length; i++) { + const currentDiff = Math.abs(nums1[i] - nums2[i]); + totalDiff = (totalDiff + currentDiff) % MOD; + + let left = 0; + let right = nums1.length - 1; + while (left <= right) { + const mid = Math.floor((left + right) / 2); + const newDiff = Math.abs(sortedNums1[mid] - nums2[i]); + const reduction = currentDiff - newDiff; + maxReduction = Math.max(maxReduction, reduction); + + if (sortedNums1[mid] < nums2[i]) left = mid + 1; + else right = mid - 1; + } + } + + return (totalDiff - maxReduction + MOD) % MOD; +}; diff --git a/solutions/1819-number-of-different-subsequences-gcds.js b/solutions/1819-number-of-different-subsequences-gcds.js new file mode 100644 index 00000000..04842fef --- /dev/null +++ b/solutions/1819-number-of-different-subsequences-gcds.js @@ -0,0 +1,48 @@ +/** + * 1819. Number of Different Subsequences GCDs + * https://leetcode.com/problems/number-of-different-subsequences-gcds/ + * Difficulty: Hard + * + * You are given an array nums that consists of positive integers. + * + * The GCD of a sequence of numbers is defined as the greatest integer that divides all the + * numbers in the sequence evenly. + * - For example, the GCD of the sequence [4,6,16] is 2. + * + * A subsequence of an array is a sequence that can be formed by removing some elements (possibly + * none) of the array. + * - For example, [2,5,10] is a subsequence of [1,2,1,2,4,1,5,10]. + * + * Return the number of different GCDs among all non-empty subsequences of nums. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var countDifferentSubsequenceGCDs = function(nums) { + const maxNum = Math.max(...nums); + const exists = new Array(maxNum + 1).fill(false); + let result = 0; + + function gcd(a, b) { + while (b) [a, b] = [b, a % b]; + return a; + } + + for (const num of nums) { + exists[num] = true; + } + + for (let i = 1; i <= maxNum; i++) { + let currentGcd = 0; + for (let j = i; j <= maxNum; j += i) { + if (exists[j]) { + currentGcd = currentGcd ? gcd(currentGcd, j) : j; + } + } + if (currentGcd === i) result++; + } + + return result; +}; 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/1822-sign-of-the-product-of-an-array.js b/solutions/1822-sign-of-the-product-of-an-array.js new file mode 100644 index 00000000..f235ea51 --- /dev/null +++ b/solutions/1822-sign-of-the-product-of-an-array.js @@ -0,0 +1,29 @@ +/** + * 1822. Sign of the Product of an Array + * https://leetcode.com/problems/sign-of-the-product-of-an-array/ + * Difficulty: Easy + * + * Implement a function signFunc(x) that returns: + * - 1 if x is positive. + * - -1 if x is negative. + * - 0 if x is equal to 0. + * + * You are given an integer array nums. Let product be the product of all values in the array nums. + * + * Return signFunc(product). + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var arraySign = function(nums) { + let negativeCount = 0; + + for (const num of nums) { + if (num === 0) return 0; + if (num < 0) negativeCount++; + } + + return negativeCount % 2 === 0 ? 1 : -1; +}; diff --git a/solutions/1823-find-the-winner-of-the-circular-game.js b/solutions/1823-find-the-winner-of-the-circular-game.js new file mode 100644 index 00000000..3138d5bb --- /dev/null +++ b/solutions/1823-find-the-winner-of-the-circular-game.js @@ -0,0 +1,36 @@ +/** + * 1823. Find the Winner of the Circular Game + * https://leetcode.com/problems/find-the-winner-of-the-circular-game/ + * Difficulty: Medium + * + * There are n friends that are playing a game. The friends are sitting in a circle and are + * numbered from 1 to n in clockwise order. More formally, moving clockwise from the ith + * friend brings you to the (i+1)th friend for 1 <= i < n, and moving clockwise from the + * nth friend brings you to the 1st friend. + * + * The rules of the game are as follows: + * 1. Start at the 1st friend. + * 2. Count the next k friends in the clockwise direction including the friend you started at. + * The counting wraps around the circle and may count some friends more than once. + * 3. The last friend you counted leaves the circle and loses the game. + * 4. If there is still more than one friend in the circle, go back to step 2 starting from the + * friend immediately clockwise of the friend who just lost and repeat. + * 5. Else, the last friend in the circle wins the game. + * + * Given the number of friends, n, and an integer k, return the winner of the game. + */ + +/** + * @param {number} n + * @param {number} k + * @return {number} + */ +var findTheWinner = function(n, k) { + let winner = 0; + + for (let i = 1; i <= n; i++) { + winner = (winner + k) % i; + } + + return winner + 1; +}; diff --git a/solutions/1824-minimum-sideway-jumps.js b/solutions/1824-minimum-sideway-jumps.js new file mode 100644 index 00000000..e4eb60d3 --- /dev/null +++ b/solutions/1824-minimum-sideway-jumps.js @@ -0,0 +1,55 @@ +/** + * 1824. Minimum Sideway Jumps + * https://leetcode.com/problems/minimum-sideway-jumps/ + * Difficulty: Medium + * + * There is a 3 lane road of length n that consists of n + 1 points labeled from 0 to n. A frog + * starts at point 0 in the second lane and wants to jump to point n. However, there could be + * obstacles along the way. + * + * You are given an array obstacles of length n + 1 where each obstacles[i] (ranging from 0 to 3) + * describes an obstacle on the lane obstacles[i] at point i. If obstacles[i] == 0, there are no + * obstacles at point i. There will be at most one obstacle in the 3 lanes at each point. + * - For example, if obstacles[2] == 1, then there is an obstacle on lane 1 at point 2. + * + * The frog can only travel from point i to point i + 1 on the same lane if there is not an obstacle + * on the lane at point i + 1. To avoid obstacles, the frog can also perform a side jump to jump + * to another lane (even if they are not adjacent) at the same point if there is no obstacle on + * the new lane. + * - For example, the frog can jump from lane 3 at point 3 to lane 1 at point 3. + * + * Return the minimum number of side jumps the frog needs to reach any lane at point n starting + * from lane 2 at point 0. + * + * Note: There will be no obstacles on points 0 and n. + */ + +/** + * @param {number[]} obstacles + * @return {number} + */ +var minSideJumps = function(obstacles) { + const n = obstacles.length; + let dp = [1, 0, 1]; + + for (let i = 1; i < n; i++) { + const currentObstacle = obstacles[i]; + const nextDp = [Infinity, Infinity, Infinity]; + + for (let lane = 1; lane <= 3; lane++) { + if (lane === currentObstacle) continue; + + nextDp[lane - 1] = dp[lane - 1]; + + for (let fromLane = 1; fromLane <= 3; fromLane++) { + if (fromLane !== lane && fromLane !== currentObstacle) { + nextDp[lane - 1] = Math.min(nextDp[lane - 1], dp[fromLane - 1] + 1); + } + } + } + + dp = nextDp; + } + + return Math.min(...dp); +}; diff --git a/solutions/1825-finding-mk-average.js b/solutions/1825-finding-mk-average.js new file mode 100644 index 00000000..ddc2b83e --- /dev/null +++ b/solutions/1825-finding-mk-average.js @@ -0,0 +1,93 @@ +/** + * 1825. Finding MK Average + * https://leetcode.com/problems/finding-mk-average/ + * Difficulty: Hard + * + * You are given two integers, m and k, and a stream of integers. You are tasked to implement a data + * structure that calculates the MKAverage for the stream. + * + * The MKAverage can be calculated using these steps: + * - If the number of the elements in the stream is less than m you should consider the MKAverage to + * be -1. Otherwise, copy the last m elements of the stream to a separate container. + * - Remove the smallest k elements and the largest k elements from the container. + * - Calculate the average value for the rest of the elements rounded down to the nearest integer. + * + * Implement the MKAverage class: + * - MKAverage(int m, int k) Initializes the MKAverage object with an empty stream and the two + * integers m and k. + * - void addElement(int num) Inserts a new element num into the stream. + * - int calculateMKAverage() Calculates and returns the MKAverage for the current stream rounded + * down to the nearest integer. + */ + +/** + * @param {number} m + * @param {number} k + */ +var MKAverage = function(m, k) { + this.m = m; + this.k = k; + this.stream = []; + this.sortedStream = []; + this.sum = 0; +}; + +/** + * @param {number} num + * @return {void} + */ +MKAverage.prototype.addElement = function(num) { + this.stream.push(num); + + const insertIndex = this.findInsertPosition(num); + this.sortedStream.splice(insertIndex, 0, num); + this.sum += num; + + if (this.stream.length > this.m) { + const oldestElement = this.stream.shift(); + const oldestIndex = this.sortedStream.indexOf(oldestElement); + this.sortedStream.splice(oldestIndex, 1); + this.sum -= oldestElement; + } +}; + +/** + * @return {number} + */ +MKAverage.prototype.calculateMKAverage = function() { + if (this.stream.length < this.m) { + return -1; + } + + let adjustedSum = this.sum; + + for (let i = 0; i < this.k; i++) { + adjustedSum -= this.sortedStream[i]; + } + for (let i = this.sortedStream.length - this.k; i < this.sortedStream.length; i++) { + adjustedSum -= this.sortedStream[i]; + } + + return Math.floor(adjustedSum / (this.m - 2 * this.k)); +}; + +/** + * Helper method to find insert position using binary search + * @param {number} num + * @return {number} + */ +MKAverage.prototype.findInsertPosition = function(num) { + let left = 0; + let right = this.sortedStream.length - 1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + if (this.sortedStream[mid] < num) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return left; +}; 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/1827-minimum-operations-to-make-the-array-increasing.js b/solutions/1827-minimum-operations-to-make-the-array-increasing.js new file mode 100644 index 00000000..5eef57d6 --- /dev/null +++ b/solutions/1827-minimum-operations-to-make-the-array-increasing.js @@ -0,0 +1,35 @@ +/** + * 1827. Minimum Operations to Make the Array Increasing + * https://leetcode.com/problems/minimum-operations-to-make-the-array-increasing/ + * Difficulty: Easy + * + * You are given an integer array nums (0-indexed). In one operation, you can choose an + * element of the array and increment it by 1. + * - For example, if nums = [1,2,3], you can choose to increment nums[1] to make nums = [1,3,3]. + * + * Return the minimum number of operations needed to make nums strictly increasing. + * + * An array nums is strictly increasing if nums[i] < nums[i+1] for all 0 <= i < nums.length - 1. + * An array of length 1 is trivially strictly increasing. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minOperations = function(nums) { + let result = 0; + let previousValue = nums[0]; + + for (let i = 1; i < nums.length; i++) { + if (nums[i] <= previousValue) { + const requiredValue = previousValue + 1; + result += requiredValue - nums[i]; + previousValue = requiredValue; + } else { + previousValue = nums[i]; + } + } + + return result; +}; diff --git a/solutions/1828-queries-on-number-of-points-inside-a-circle.js b/solutions/1828-queries-on-number-of-points-inside-a-circle.js new file mode 100644 index 00000000..bfc1e4b8 --- /dev/null +++ b/solutions/1828-queries-on-number-of-points-inside-a-circle.js @@ -0,0 +1,38 @@ +/** + * 1828. Queries on Number of Points Inside a Circle + * https://leetcode.com/problems/queries-on-number-of-points-inside-a-circle/ + * Difficulty: Medium + * + * You are given an array points where points[i] = [xi, yi] is the coordinates of the ith + * point on a 2D plane. Multiple points can have the same coordinates. + * + * You are also given an array queries where queries[j] = [xj, yj, rj] describes a circle + * centered at (xj, yj) with a radius of rj. + * + * For each query queries[j], compute the number of points inside the jth circle. Points on + * the border of the circle are considered inside. + * + * Return an array answer, where answer[j] is the answer to the jth query. + */ + +/** + * @param {number[][]} points + * @param {number[][]} queries + * @return {number[]} + */ +var countPoints = function(points, queries) { + const result = []; + + for (const [centerX, centerY, radius] of queries) { + let pointsInside = 0; + for (const [pointX, pointY] of points) { + const distance = Math.sqrt((centerX - pointX) ** 2 + (centerY - pointY) ** 2); + if (distance <= radius) { + pointsInside++; + } + } + result.push(pointsInside); + } + + return result; +}; diff --git a/solutions/1829-maximum-xor-for-each-query.js b/solutions/1829-maximum-xor-for-each-query.js new file mode 100644 index 00000000..43a867f6 --- /dev/null +++ b/solutions/1829-maximum-xor-for-each-query.js @@ -0,0 +1,36 @@ +/** + * 1829. Maximum XOR for Each Query + * https://leetcode.com/problems/maximum-xor-for-each-query/ + * Difficulty: Medium + * + * You are given a sorted array nums of n non-negative integers and an integer maximumBit. + * You want to perform the following query n times: + * - Find a non-negative integer k < 2maximumBit such that nums[0] XOR nums[1] XOR ... XOR + * nums[nums.length-1] XOR k is maximized. k is the answer to the ith query. + * - Remove the last element from the current array nums. + * + * Return an array answer, where answer[i] is the answer to the ith query. + */ + +/** + * @param {number[]} nums + * @param {number} maximumBit + * @return {number[]} + */ +var getMaximumXor = function(nums, maximumBit) { + const result = []; + let currentXor = 0; + const maxValue = (1 << maximumBit) - 1; + + for (const num of nums) { + currentXor ^= num; + } + + for (let i = nums.length - 1; i >= 0; i--) { + const optimalK = currentXor ^ maxValue; + result.push(optimalK); + currentXor ^= nums[i]; + } + + return result; +}; diff --git a/solutions/1830-minimum-number-of-operations-to-make-string-sorted.js b/solutions/1830-minimum-number-of-operations-to-make-string-sorted.js new file mode 100644 index 00000000..51cbb535 --- /dev/null +++ b/solutions/1830-minimum-number-of-operations-to-make-string-sorted.js @@ -0,0 +1,71 @@ +/** + * 1830. Minimum Number of Operations to Make String Sorted + * https://leetcode.com/problems/minimum-number-of-operations-to-make-string-sorted/ + * Difficulty: Hard + * + * You are given a string s (0-indexed). You are asked to perform the following operation on + * s until you get a sorted string: + * 1. Find the largest index i such that 1 <= i < s.length and s[i] < s[i - 1]. + * 2. Find the largest index j such that i <= j < s.length and s[k] < s[i - 1] for all the + * possible values of k in the range [i, j] inclusive. + * 3. Swap the two characters at indices i - 1 and j. + * 4. Reverse the suffix starting at index i. + * + * Return the number of operations needed to make the string sorted. Since the answer can be too + * large, return it modulo 109 + 7. + */ + +/** + * @param {string} s + * @return {number} + */ +var makeStringSorted = function(s) { + const MOD = 1e9 + 7; + const length = s.length; + const factorials = new Array(length + 1).fill(1n); + const inverses = new Array(length + 1).fill(1n); + + for (let i = 2; i <= length; i++) { + factorials[i] = (factorials[i - 1] * BigInt(i)) % BigInt(MOD); + } + + for (let i = 1; i <= length; i++) { + inverses[i] = modInverse(factorials[i], BigInt(MOD)); + } + + let result = 0n; + const charCounts = new Array(26).fill(0); + for (let i = length - 1; i >= 0; i--) { + const charIndex = s.charCodeAt(i) - 97; + charCounts[charIndex]++; + let smallerChars = 0; + for (let j = 0; j < charIndex; j++) { + smallerChars += charCounts[j]; + } + let totalPermutations = factorials[length - i - 1]; + for (const count of charCounts) { + totalPermutations = (totalPermutations * inverses[count]) % BigInt(MOD); + } + result = (result + BigInt(smallerChars) * totalPermutations) % BigInt(MOD); + } + + return Number(result); + + function modInverse(a, m) { + const m0 = m; + let q; + let x0 = 0n; + let x1 = 1n; + while (a > 1n) { + q = a / m; + [a, m] = [m, a % m]; + [x0, x1] = [x1 - q * x0, x0]; + } + return x1 < 0n ? x1 + m0 : x1; + } + + function combinations(n, k) { + if (k < 0 || k > n) return 0n; + return (factorials[n] * inverses[k] % BigInt(MOD)) * inverses[n - k] % BigInt(MOD); + } +}; diff --git a/solutions/1834-single-threaded-cpu.js b/solutions/1834-single-threaded-cpu.js new file mode 100644 index 00000000..e07dd7dc --- /dev/null +++ b/solutions/1834-single-threaded-cpu.js @@ -0,0 +1,51 @@ +/** + * 1834. Single-Threaded CPU + * https://leetcode.com/problems/single-threaded-cpu/ + * Difficulty: Medium + * + * You are given n tasks labeled from 0 to n - 1 represented by a 2D integer array tasks, + * where tasks[i] = [enqueueTimei, processingTimei] means that the ith task will be available + * to process at enqueueTimei and will take processingTimei to finish processing. + * + * You have a single-threaded CPU that can process at most one task at a time and will act in + * the following way: + * - If the CPU is idle and there are no available tasks to process, the CPU remains idle. + * - If the CPU is idle and there are available tasks, the CPU will choose the one with the shortest + * processing time. If multiple tasks have the same shortest processing time, it will choose the + * task with the smallest index. + * - Once a task is started, the CPU will process the entire task without stopping. + * - The CPU can finish a task then start a new one instantly. + * + * Return the order in which the CPU will process the tasks. + */ + +/** + * @param {number[][]} tasks + * @return {number[]} + */ +var getOrder = function(tasks) { + const indexedTasks = tasks.map(([enqueue, process], index) => ({ enqueue, process, index })) + .sort((a, b) => a.enqueue - b.enqueue); + + const result = []; + const availableTasks = new PriorityQueue((a, b) => a.process - b.process || a.index - b.index); + let currentTime = indexedTasks[0].enqueue; + let taskIndex = 0; + + while (result.length < tasks.length) { + while (taskIndex < tasks.length && indexedTasks[taskIndex].enqueue <= currentTime) { + availableTasks.push(indexedTasks[taskIndex]); + taskIndex++; + } + + if (availableTasks.size() > 0) { + const task = availableTasks.pop(); + result.push(task.index); + currentTime += task.process; + } else { + currentTime = indexedTasks[taskIndex].enqueue; + } + } + + return result; +}; diff --git a/solutions/1835-find-xor-sum-of-all-pairs-bitwise-and.js b/solutions/1835-find-xor-sum-of-all-pairs-bitwise-and.js new file mode 100644 index 00000000..f57b405d --- /dev/null +++ b/solutions/1835-find-xor-sum-of-all-pairs-bitwise-and.js @@ -0,0 +1,37 @@ +/** + * 1835. Find XOR Sum of All Pairs Bitwise AND + * https://leetcode.com/problems/find-xor-sum-of-all-pairs-bitwise-and/ + * Difficulty: Hard + * + * The XOR sum of a list is the bitwise XOR of all its elements. If the list only contains one + * element, then its XOR sum will be equal to this element. + * - For example, the XOR sum of [1,2,3,4] is equal to 1 XOR 2 XOR 3 XOR 4 = 4, and the XOR + * sum of [3] is equal to 3. + * + * You are given two 0-indexed arrays arr1 and arr2 that consist only of non-negative integers. + * + * Consider the list containing the result of arr1[i] AND arr2[j] (bitwise AND) for every (i, j) + * pair where 0 <= i < arr1.length and 0 <= j < arr2.length. + * + * Return the XOR sum of the aforementioned list. + */ + +/** + * @param {number[]} arr1 + * @param {number[]} arr2 + * @return {number} + */ +var getXORSum = function(arr1, arr2) { + let xor1 = 0; + let xor2 = 0; + + for (const num of arr1) { + xor1 ^= num; + } + + for (const num of arr2) { + xor2 ^= num; + } + + return xor1 & xor2; +}; 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/1837-sum-of-digits-in-base-k.js b/solutions/1837-sum-of-digits-in-base-k.js new file mode 100644 index 00000000..48223a4d --- /dev/null +++ b/solutions/1837-sum-of-digits-in-base-k.js @@ -0,0 +1,27 @@ +/** + * 1837. Sum of Digits in Base K + * https://leetcode.com/problems/sum-of-digits-in-base-k/ + * Difficulty: Easy + * + * Given an integer n (in base 10) and a base k, return the sum of the digits of n after + * converting n from base 10 to base k. + * + * After converting, each digit should be interpreted as a base 10 number, and the sum should + * be returned in base 10. + */ + +/** + * @param {number} n + * @param {number} k + * @return {number} + */ +var sumBase = function(n, k) { + let digitSum = 0; + + while (n > 0) { + digitSum += n % k; + n = Math.floor(n / k); + } + + return digitSum; +}; diff --git a/solutions/1838-frequency-of-the-most-frequent-element.js b/solutions/1838-frequency-of-the-most-frequent-element.js new file mode 100644 index 00000000..d13b8eb2 --- /dev/null +++ b/solutions/1838-frequency-of-the-most-frequent-element.js @@ -0,0 +1,36 @@ +/** + * 1838. Frequency of the Most Frequent Element + * https://leetcode.com/problems/frequency-of-the-most-frequent-element/ + * Difficulty: Medium + * + * The frequency of an element is the number of times it occurs in an array. + * + * You are given an integer array nums and an integer k. In one operation, you can choose + * an index of nums and increment the element at that index by 1. + * + * Return the maximum possible frequency of an element after performing at most k operations. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var maxFrequency = function(nums, k) { + nums.sort((a, b) => a - b); + + let result = 0; + let currentSum = 0; + let left = 0; + + for (let right = 0; right < nums.length; right++) { + currentSum += nums[right]; + while (currentSum + k < nums[right] * (right - left + 1)) { + currentSum -= nums[left]; + left++; + } + result = Math.max(result, right - left + 1); + } + + return result; +}; diff --git a/solutions/1839-longest-substring-of-all-vowels-in-order.js b/solutions/1839-longest-substring-of-all-vowels-in-order.js new file mode 100644 index 00000000..343f0279 --- /dev/null +++ b/solutions/1839-longest-substring-of-all-vowels-in-order.js @@ -0,0 +1,43 @@ +/** + * 1839. Longest Substring Of All Vowels in Order + * https://leetcode.com/problems/longest-substring-of-all-vowels-in-order/ + * Difficulty: Medium + * + * A string is considered beautiful if it satisfies the following conditions: + * - Each of the 5 English vowels ('a', 'e', 'i', 'o', 'u') must appear at least once in it. + * - The letters must be sorted in alphabetical order (i.e. all 'a's before 'e's, all 'e's + * before 'i's, etc.). + * + * For example, strings "aeiou" and "aaaaaaeiiiioou" are considered beautiful, but "uaeio", "aeoiu", + * and "aaaeeeooo" are not beautiful. + * + * Given a string word consisting of English vowels, return the length of the longest beautiful + * substring of word. If no such substring exists, return 0. + * + * A substring is a contiguous sequence of characters in a string. + */ + +/** + * @param {string} word + * @return {number} + */ +var longestBeautifulSubstring = function(word) { + let result = 0; + let start = 0; + let vowelCount = 1; + + for (let i = 1; i < word.length; i++) { + if (word[i] < word[i - 1]) { + start = i; + vowelCount = 1; + } else if (word[i] > word[i - 1]) { + vowelCount++; + } + + if (vowelCount === 5) { + result = Math.max(result, i - start + 1); + } + } + + return result; +}; diff --git a/solutions/1840-maximum-building-height.js b/solutions/1840-maximum-building-height.js new file mode 100644 index 00000000..d77cdd46 --- /dev/null +++ b/solutions/1840-maximum-building-height.js @@ -0,0 +1,60 @@ +/** + * 1840. Maximum Building Height + * https://leetcode.com/problems/maximum-building-height/ + * Difficulty: Hard + * + * You want to build n new buildings in a city. The new buildings will be built in a line + * and are labeled from 1 to n. + * + * However, there are city restrictions on the heights of the new buildings: + * - The height of each building must be a non-negative integer. + * - The height of the first building must be 0. + * - The height difference between any two adjacent buildings cannot exceed 1. + * + * Additionally, there are city restrictions on the maximum height of specific buildings. + * These restrictions are given as a 2D integer array restrictions where + * restrictions[i] = [idi, maxHeighti] indicates that building idi must have a height + * less than or equal to maxHeighti. + * + * It is guaranteed that each building will appear at most once in restrictions, and building + * 1 will not be in restrictions. + * + * Return the maximum possible height of the tallest building. + */ + +/** + * @param {number} n + * @param {number[][]} restrictions + * @return {number} + */ +var maxBuilding = function(n, restrictions) { + restrictions.push([1, 0], [n, n - 1]); + restrictions.sort((a, b) => a[0] - b[0]); + + const length = restrictions.length; + + for (let i = 1; i < length; i++) { + const [currId, currHeight] = restrictions[i]; + const [prevId, prevHeight] = restrictions[i - 1]; + restrictions[i][1] = Math.min(currHeight, prevHeight + (currId - prevId)); + } + + for (let i = length - 2; i >= 0; i--) { + const [currId, currHeight] = restrictions[i]; + const [nextId, nextHeight] = restrictions[i + 1]; + restrictions[i][1] = Math.min(currHeight, nextHeight + (nextId - currId)); + } + + let maxHeight = 0; + + for (let i = 1; i < length; i++) { + const [leftId, leftHeight] = restrictions[i - 1]; + const [rightId, rightHeight] = restrictions[i]; + const distance = rightId - leftId; + const heightDiff = Math.abs(rightHeight - leftHeight); + const peakHeight = Math.max(leftHeight, rightHeight) + Math.floor((distance - heightDiff) / 2); + maxHeight = Math.max(maxHeight, peakHeight); + } + + return maxHeight; +}; 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/1844-replace-all-digits-with-characters.js b/solutions/1844-replace-all-digits-with-characters.js new file mode 100644 index 00000000..c5efb48c --- /dev/null +++ b/solutions/1844-replace-all-digits-with-characters.js @@ -0,0 +1,39 @@ +/** + * 1844. Replace All Digits with Characters + * https://leetcode.com/problems/replace-all-digits-with-characters/ + * Difficulty: Easy + * + * You are given a 0-indexed string s that has lowercase English letters in its even indices and + * digits in its odd indices. + * + * You must perform an operation shift(c, x), where c is a character and x is a digit, that returns + * the xth character after c. + * - For example, shift('a', 5) = 'f' and shift('x', 0) = 'x'. + * + * For every odd index i, you want to replace the digit s[i] with the result of the + * shift(s[i-1], s[i]) operation. + * + * Return s after replacing all digits. It is guaranteed that shift(s[i-1], s[i]) will never + * exceed 'z'. + * + * Note that shift(c, x) is not a preloaded function, but an operation to be implemented as part + * of the solution. + */ + +/** + * @param {string} s + * @return {string} + */ +var replaceDigits = function(s) { + const result = s.split(''); + + for (let i = 1; i < s.length; i += 2) { + result[i] = shiftChar(s[i - 1], s[i]); + } + + return result.join(''); + + function shiftChar(char, shift) { + return String.fromCharCode(char.charCodeAt(0) + parseInt(shift)); + } +}; diff --git a/solutions/1845-seat-reservation-manager.js b/solutions/1845-seat-reservation-manager.js new file mode 100644 index 00000000..53bc7edd --- /dev/null +++ b/solutions/1845-seat-reservation-manager.js @@ -0,0 +1,44 @@ +/** + * 1845. Seat Reservation Manager + * https://leetcode.com/problems/seat-reservation-manager/ + * Difficulty: Medium + * + * Design a system that manages the reservation state of n seats that are numbered from 1 to n. + * + * Implement the SeatManager class: + * - SeatManager(int n) Initializes a SeatManager object that will manage n seats numbered from + * 1 to n. All seats are initially available. + * - int reserve() Fetches the smallest-numbered unreserved seat, reserves it, and returns its + * number. + * - void unreserve(int seatNumber) Unreserves the seat with the given seatNumber. + */ + +/** + * @param {number} n + */ +var SeatManager = function(n) { + this.nextAvailable = 1; + this.unreservedSeats = new Set(); +}; + +/** + * @return {number} + */ +SeatManager.prototype.reserve = function() { + if (this.unreservedSeats.size > 0) { + const minSeat = Math.min(...this.unreservedSeats); + if (minSeat < this.nextAvailable) { + this.unreservedSeats.delete(minSeat); + return minSeat; + } + } + return this.nextAvailable++; +}; + +/** + * @param {number} seatNumber + * @return {void} + */ +SeatManager.prototype.unreserve = function(seatNumber) { + this.unreservedSeats.add(seatNumber); +}; diff --git a/solutions/1846-maximum-element-after-decreasing-and-rearranging.js b/solutions/1846-maximum-element-after-decreasing-and-rearranging.js new file mode 100644 index 00000000..266a8dc1 --- /dev/null +++ b/solutions/1846-maximum-element-after-decreasing-and-rearranging.js @@ -0,0 +1,36 @@ +/** + * 1846. Maximum Element After Decreasing and Rearranging + * https://leetcode.com/problems/maximum-element-after-decreasing-and-rearranging/ + * Difficulty: Medium + * + * You are given an array of positive integers arr. Perform some operations (possibly none) on + * arr so that it satisfies these conditions: + * - The value of the first element in arr must be 1. + * - The absolute difference between any 2 adjacent elements must be less than or equal to 1. + * In other words, abs(arr[i] - arr[i - 1]) <= 1 for each i where 1 <= i < arr.length + * (0-indexed). abs(x) is the absolute value of x. + * + * There are 2 types of operations that you can perform any number of times: + * - Decrease the value of any element of arr to a smaller positive integer. + * - Rearrange the elements of arr to be in any order. + * + * Return the maximum possible value of an element in arr after performing the operations to + * satisfy the conditions. + */ + +/** + * @param {number[]} arr + * @return {number} + */ +var maximumElementAfterDecrementingAndRearranging = function(arr) { + arr.sort((a, b) => a - b); + let maxPossible = 1; + + for (let i = 1; i < arr.length; i++) { + if (arr[i] > maxPossible) { + maxPossible++; + } + } + + return maxPossible; +}; diff --git a/solutions/1847-closest-room.js b/solutions/1847-closest-room.js new file mode 100644 index 00000000..49963145 --- /dev/null +++ b/solutions/1847-closest-room.js @@ -0,0 +1,83 @@ +/** + * 1847. Closest Room + * https://leetcode.com/problems/closest-room/ + * Difficulty: Hard + * + * There is a hotel with n rooms. The rooms are represented by a 2D integer array rooms where + * rooms[i] = [roomIdi, sizei] denotes that there is a room with room number roomIdi and size + * equal to sizei. Each roomIdi is guaranteed to be unique. + * + * You are also given k queries in a 2D array queries where queries[j] = [preferredj, minSizej]. + * The answer to the jth query is the room number id of a room such that: + * - The room has a size of at least minSizej, and + * - abs(id - preferredj) is minimized, where abs(x) is the absolute value of x. + * + * If there is a tie in the absolute difference, then use the room with the smallest such id. + * If there is no such room, the answer is -1. + * + * Return an array answer of length k where answer[j] contains the answer to the jth query. + */ + +/** + * @param {number[][]} rooms + * @param {number[][]} queries + * @return {number[]} + */ +var closestRoom = function(rooms, queries) { + rooms.sort((a, b) => b[1] - a[1]); + const sortedQueries = queries + .map((q, i) => [q[0], q[1], i]) + .sort((a, b) => b[1] - a[1]); + + const result = new Array(queries.length).fill(-1); + const roomIds = []; + let roomIndex = 0; + + for (const [preferred, minSize, queryIndex] of sortedQueries) { + while (roomIndex < rooms.length && rooms[roomIndex][1] >= minSize) { + insertSorted(rooms[roomIndex][0]); + roomIndex++; + } + + result[queryIndex] = findClosestId(preferred); + } + + return result; + + function insertSorted(id) { + let left = 0; + let right = roomIds.length; + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (roomIds[mid] < id) left = mid + 1; + else right = mid; + } + roomIds.splice(left, 0, id); + } + + function findClosestId(target) { + if (!roomIds.length) return -1; + + let left = 0; + let right = roomIds.length - 1; + let closest = roomIds[0]; + let minDiff = Math.abs(closest - target); + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + const id = roomIds[mid]; + const diff = Math.abs(id - target); + + if (diff < minDiff || (diff === minDiff && id < closest)) { + minDiff = diff; + closest = id; + } + + if (id < target) left = mid + 1; + else if (id > target) right = mid - 1; + else break; + } + + return closest; + } +}; diff --git a/solutions/1848-minimum-distance-to-the-target-element.js b/solutions/1848-minimum-distance-to-the-target-element.js new file mode 100644 index 00000000..567427d2 --- /dev/null +++ b/solutions/1848-minimum-distance-to-the-target-element.js @@ -0,0 +1,32 @@ +/** + * 1848. Minimum Distance to the Target Element + * https://leetcode.com/problems/minimum-distance-to-the-target-element/ + * Difficulty: Easy + * + * Given an integer array nums (0-indexed) and two integers target and start, find an index i + * such that nums[i] == target and abs(i - start) is minimized. Note that abs(x) is the absolute + * value of x. + * + * Return abs(i - start). + * + * It is guaranteed that target exists in nums. + */ + +/** + * @param {number[]} nums + * @param {number} target + * @param {number} start + * @return {number} + */ +var getMinDistance = function(nums, target, start) { + let result = Infinity; + + for (let i = 0; i < nums.length; i++) { + if (nums[i] === target) { + const distance = Math.abs(i - start); + result = Math.min(result, distance); + } + } + + return result; +}; diff --git a/solutions/1849-splitting-a-string-into-descending-consecutive-values.js b/solutions/1849-splitting-a-string-into-descending-consecutive-values.js new file mode 100644 index 00000000..d993db28 --- /dev/null +++ b/solutions/1849-splitting-a-string-into-descending-consecutive-values.js @@ -0,0 +1,50 @@ +/** + * 1849. Splitting a String Into Descending Consecutive Values + * https://leetcode.com/problems/splitting-a-string-into-descending-consecutive-values/ + * Difficulty: Medium + * + * You are given a string s that consists of only digits. + * + * Check if we can split s into two or more non-empty substrings such that the numerical values of + * the substrings are in descending order and the difference between numerical values of every two + * adjacent substrings is equal to 1. + * - For example, the string s = "0090089" can be split into ["0090", "089"] with numerical values + * [90,89]. The values are in descending order and adjacent values differ by 1, so this way is + * valid. + * - Another example, the string s = "001" can be split into ["0", "01"], ["00", "1"], or + * ["0", "0", "1"]. However all the ways are invalid because they have numerical values + * [0,1], [0,1], and [0,0,1] respectively, all of which are not in descending order. + * + * Return true if it is possible to split s as described above, or false otherwise. + * + * A substring is a contiguous sequence of characters in a string. + */ + +/** + * @param {string} s + * @return {boolean} + */ +var splitString = function(s) { + let firstValue = 0; + for (let i = 0; i < s.length - 1; i++) { + firstValue = firstValue * 10 + parseInt(s[i]); + if (trySplit(i + 1, firstValue)) return true; + } + + return false; + + function trySplit(index, prevValue) { + if (index === s.length) return true; + + let currentValue = 0; + for (let i = index; i < s.length; i++) { + currentValue = currentValue * 10 + parseInt(s[i]); + if (currentValue >= prevValue) break; + if (prevValue - currentValue === 1 && trySplit(i + 1, currentValue)) { + return true; + } + } + + return false; + } +}; diff --git a/solutions/1850-minimum-adjacent-swaps-to-reach-the-kth-smallest-number.js b/solutions/1850-minimum-adjacent-swaps-to-reach-the-kth-smallest-number.js new file mode 100644 index 00000000..d4853138 --- /dev/null +++ b/solutions/1850-minimum-adjacent-swaps-to-reach-the-kth-smallest-number.js @@ -0,0 +1,70 @@ +/** + * 1850. Minimum Adjacent Swaps to Reach the Kth Smallest Number + * https://leetcode.com/problems/minimum-adjacent-swaps-to-reach-the-kth-smallest-number/ + * Difficulty: Medium + * + * You are given a string num, representing a large integer, and an integer k. + * + * We call some integer wonderful if it is a permutation of the digits in num and is greater in + * value than num. There can be many wonderful integers. However, we only care about the + * smallest-valued ones. + * - For example, when num = "5489355142": + * - The 1st smallest wonderful integer is "5489355214". + * - The 2nd smallest wonderful integer is "5489355241". + * - The 3rd smallest wonderful integer is "5489355412". + * - The 4th smallest wonderful integer is "5489355421". + * + * Return the minimum number of adjacent digit swaps that needs to be applied to num to reach + * the kth smallest wonderful integer. + * + * The tests are generated in such a way that kth smallest wonderful integer exists. + */ + +/** + * @param {string} num + * @param {number} k + * @return {number} + */ +var getMinSwaps = function(num, k) { + const original = num.split(''); + const target = num.split(''); + + for (let i = 0; i < k; i++) { + nextPermutation(target); + } + + let result = 0; + for (let i = 0; i < original.length; i++) { + if (original[i] !== target[i]) { + let j = i + 1; + while (j < original.length && original[j] !== target[i]) j++; + while (j > i) { + [original[j], original[j - 1]] = [original[j - 1], original[j]]; + result++; + j--; + } + } + } + + return result; + + function nextPermutation(arr) { + let i = arr.length - 2; + while (i >= 0 && arr[i] >= arr[i + 1]) i--; + if (i < 0) return false; + + let j = arr.length - 1; + while (arr[j] <= arr[i]) j--; + + [arr[i], arr[j]] = [arr[j], arr[i]]; + + let left = i + 1; + let right = arr.length - 1; + while (left < right) { + [arr[left], arr[right]] = [arr[right], arr[left]]; + left++; + right--; + } + return true; + } +}; diff --git a/solutions/1851-minimum-interval-to-include-each-query.js b/solutions/1851-minimum-interval-to-include-each-query.js new file mode 100644 index 00000000..a81d82ea --- /dev/null +++ b/solutions/1851-minimum-interval-to-include-each-query.js @@ -0,0 +1,49 @@ +/** + * 1851. Minimum Interval to Include Each Query + * https://leetcode.com/problems/minimum-interval-to-include-each-query/ + * Difficulty: Hard + * + * You are given a 2D integer array intervals, where intervals[i] = [lefti, righti] describes + * the ith interval starting at lefti and ending at righti (inclusive). The size of an interval + * is defined as the number of integers it contains, or more formally righti - lefti + 1. + * + * You are also given an integer array queries. The answer to the jth query is the size of the + * smallest interval i such that lefti <= queries[j] <= righti. If no such interval exists, + * the answer is -1. + * + * Return an array containing the answers to the queries. + */ + +/** + * @param {number[][]} intervals + * @param {number[]} queries + * @return {number[]} + */ +var minInterval = function(intervals, queries) { + intervals.sort((a, b) => a[0] - b[0]); + const sortedQueries = queries + .map((q, i) => [q, i]) + .sort((a, b) => a[0] - b[0]); + + const activeIntervals = new PriorityQueue((a, b) => a[0] - b[0]); + const result = new Array(queries.length).fill(-1); + let intervalIndex = 0; + + for (const [queryValue, queryIndex] of sortedQueries) { + while (intervalIndex < intervals.length && intervals[intervalIndex][0] <= queryValue) { + const [start, end] = intervals[intervalIndex]; + activeIntervals.enqueue([end - start + 1, end]); + intervalIndex++; + } + + while (!activeIntervals.isEmpty() && activeIntervals.front()?.[1] < queryValue) { + activeIntervals.dequeue(); + } + + if (!activeIntervals.isEmpty()) { + result[queryIndex] = activeIntervals.front()[0]; + } + } + + return result; +}; 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/1854-maximum-population-year.js b/solutions/1854-maximum-population-year.js new file mode 100644 index 00000000..9ea9aec0 --- /dev/null +++ b/solutions/1854-maximum-population-year.js @@ -0,0 +1,42 @@ +/** + * 1854. Maximum Population Year + * https://leetcode.com/problems/maximum-population-year/ + * Difficulty: Easy + * + * You are given a 2D integer array logs where each logs[i] = [birthi, deathi] indicates the + * birth and death years of the ith person. + * + * The population of some year x is the number of people alive during that year. The ith person + * is counted in year x's population if x is in the inclusive range [birthi, deathi - 1]. Note + * that the person is not counted in the year that they die. + * + * Return the earliest year with the maximum population. + */ + +/** + * @param {number[][]} logs + * @return {number} + */ +var maximumPopulation = function(logs) { + const populationChanges = new Array(101).fill(0); + const baseYear = 1950; + + for (const [birth, death] of logs) { + populationChanges[birth - baseYear]++; + populationChanges[death - baseYear]--; + } + + let maxPopulation = 0; + let currentPopulation = 0; + let result = baseYear; + + for (let i = 0; i < populationChanges.length; i++) { + currentPopulation += populationChanges[i]; + if (currentPopulation > maxPopulation) { + maxPopulation = currentPopulation; + result = baseYear + i; + } + } + + return result; +}; diff --git a/solutions/1855-maximum-distance-between-a-pair-of-values.js b/solutions/1855-maximum-distance-between-a-pair-of-values.js new file mode 100644 index 00000000..d94af4d5 --- /dev/null +++ b/solutions/1855-maximum-distance-between-a-pair-of-values.js @@ -0,0 +1,35 @@ +/** + * 1855. Maximum Distance Between a Pair of Values + * https://leetcode.com/problems/maximum-distance-between-a-pair-of-values/ + * Difficulty: Medium + * + * You are given two non-increasing 0-indexed integer arrays nums2 and nums2. + * + * A pair of indices (i, j), where 0 <= i < nums1.length and 0 <= j < nums2.length, + * is valid if both i <= j and nums1[i] <= nums2[j]. The distance of the pair is j - i. + * + * Return the maximum distance of any valid pair (i, j). If there are no valid pairs, return 0. + * + * An array arr is non-increasing if arr[i-1] >= arr[i] for every 1 <= i < arr.length. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var maxDistance = function(nums1, nums2) { + let result = 0; + let left = 0; + + for (let right = 0; right < nums2.length; right++) { + while (left < nums1.length && nums1[left] > nums2[right]) { + left++; + } + if (left <= right && left < nums1.length) { + result = Math.max(result, right - left); + } + } + + return result; +}; diff --git a/solutions/1856-maximum-subarray-min-product.js b/solutions/1856-maximum-subarray-min-product.js new file mode 100644 index 00000000..02a5f6bc --- /dev/null +++ b/solutions/1856-maximum-subarray-min-product.js @@ -0,0 +1,47 @@ +/** + * 1856. Maximum Subarray Min-Product + * https://leetcode.com/problems/maximum-subarray-min-product/ + * Difficulty: Medium + * + * The min-product of an array is equal to the minimum value in the array multiplied by + * the array's sum. + * - For example, the array [3,2,5] (minimum value is 2) has a min-product of + * 2 * (3+2+5) = 2 * 10 = 20. + * + * Given an array of integers nums, return the maximum min-product of any non-empty + * subarray of nums. Since the answer may be large, return it modulo 109 + 7. + * + * Note that the min-product should be maximized before performing the modulo operation. + * Testcases are generated such that the maximum min-product without modulo will fit in + * a 64-bit signed integer. + * + * A subarray is a contiguous part of an array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxSumMinProduct = function(nums) { + const modulo = 1000000007n; + const stack = []; + const prefixSums = [0n]; + let maxMinProduct = 0n; + + for (let i = 0; i < nums.length; i++) { + prefixSums.push(prefixSums[i] + BigInt(nums[i])); + } + + for (let right = 0; right <= nums.length; right++) { + const current = right < nums.length ? BigInt(nums[right]) : 0n; + while (stack.length && stack[stack.length - 1].value > current) { + const { index, value } = stack.pop(); + const left = stack.length ? stack[stack.length - 1].index + 1 : 0; + const subarraySum = prefixSums[right] - prefixSums[left]; + maxMinProduct = maxMinProduct > value * subarraySum ? maxMinProduct : value * subarraySum; + } + stack.push({ index: right, value: current }); + } + + return Number(maxMinProduct % modulo); +}; diff --git a/solutions/1857-largest-color-value-in-a-directed-graph.js b/solutions/1857-largest-color-value-in-a-directed-graph.js new file mode 100644 index 00000000..c592996b --- /dev/null +++ b/solutions/1857-largest-color-value-in-a-directed-graph.js @@ -0,0 +1,60 @@ +/** + * 1857. Largest Color Value in a Directed Graph + * https://leetcode.com/problems/largest-color-value-in-a-directed-graph/ + * Difficulty: Hard + * + * There is a directed graph of n colored nodes and m edges. The nodes are numbered from 0 to n - 1. + * + * You are given a string colors where colors[i] is a lowercase English letter representing the + * color of the ith node in this graph (0-indexed). You are also given a 2D array edges where + * edges[j] = [aj, bj] indicates that there is a directed edge from node aj to node bj. + * + * A valid path in the graph is a sequence of nodes x1 -> x2 -> x3 -> ... -> xk such that there + * is a directed edge from xi to xi+1 for every 1 <= i < k. The color value of the path is the + * number of nodes that are colored the most frequently occurring color along that path. + * + * Return the largest color value of any valid path in the given graph, or -1 if the graph + * contains a cycle. + */ + +/** + * @param {string} colors + * @param {number[][]} edges + * @return {number} + */ +var largestPathValue = function(colors, edges) { + const nodeCount = colors.length; + const adjacencyList = Array.from({ length: nodeCount }, () => []); + const inDegree = new Array(nodeCount).fill(0); + const colorCounts = Array.from({ length: nodeCount }, () => new Array(26).fill(0)); + const queue = []; + let maxColorValue = 0; + let processedNodes = 0; + + for (const [from, to] of edges) { + adjacencyList[from].push(to); + inDegree[to]++; + } + + for (let i = 0; i < nodeCount; i++) { + if (inDegree[i] === 0) queue.push(i); + } + + while (queue.length) { + const current = queue.shift(); + processedNodes++; + const colorIndex = colors.charCodeAt(current) - 97; + colorCounts[current][colorIndex]++; + + for (const next of adjacencyList[current]) { + for (let i = 0; i < 26; i++) { + colorCounts[next][i] = Math.max(colorCounts[next][i], colorCounts[current][i]); + } + if (--inDegree[next] === 0) queue.push(next); + } + + maxColorValue = Math.max(maxColorValue, ...colorCounts[current]); + } + + return processedNodes === nodeCount ? maxColorValue : -1; +}; 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/1859-sorting-the-sentence.js b/solutions/1859-sorting-the-sentence.js new file mode 100644 index 00000000..d2d9c81f --- /dev/null +++ b/solutions/1859-sorting-the-sentence.js @@ -0,0 +1,32 @@ +/** + * 1859. Sorting the Sentence + * https://leetcode.com/problems/sorting-the-sentence/ + * Difficulty: Easy + * + * A sentence is a list of words that are separated by a single space with no leading or trailing + * spaces. Each word consists of lowercase and uppercase English letters. + * + * A sentence can be shuffled by appending the 1-indexed word position to each word then rearranging + * the words in the sentence. + * - For example, the sentence "This is a sentence" can be shuffled as "sentence4 a3 is2 This1" or + * "is2 sentence4 This1 a3". + * + * Given a shuffled sentence s containing no more than 9 words, reconstruct and return the original + * sentence. + */ + +/** + * @param {string} s + * @return {string} + */ +var sortSentence = function(s) { + const words = s.split(' '); + const sortedWords = new Array(words.length); + + for (const word of words) { + const position = parseInt(word.slice(-1)) - 1; + sortedWords[position] = word.slice(0, -1); + } + + return sortedWords.join(' '); +}; diff --git a/solutions/1860-incremental-memory-leak.js b/solutions/1860-incremental-memory-leak.js new file mode 100644 index 00000000..fd72b849 --- /dev/null +++ b/solutions/1860-incremental-memory-leak.js @@ -0,0 +1,41 @@ +/** + * 1860. Incremental Memory Leak + * https://leetcode.com/problems/incremental-memory-leak/ + * Difficulty: Medium + * + * You are given two integers memory1 and memory2 representing the available memory in bits on + * two memory sticks. There is currently a faulty program running that consumes an increasing + * amount of memory every second. + * + * At the ith second (starting from 1), i bits of memory are allocated to the stick with more + * available memory (or from the first memory stick if both have the same available memory). + * If neither stick has at least i bits of available memory, the program crashes. + * + * Return an array containing [crashTime, memory1crash, memory2crash], where crashTime is the + * time (in seconds) when the program crashed and memory1crash and memory2crash are the + * available bits of memory in the first and second sticks respectively. + */ + +/** + * @param {number} memory1 + * @param {number} memory2 + * @return {number[]} + */ +var memLeak = function(memory1, memory2) { + let time = 1; + let stick1 = memory1; + let stick2 = memory2; + + while (time <= stick1 || time <= stick2) { + if (stick1 >= stick2) { + if (stick1 < time) break; + stick1 -= time; + } else { + if (stick2 < time) break; + stick2 -= time; + } + time++; + } + + return [time, stick1, stick2]; +}; diff --git a/solutions/1861-rotating-the-box.js b/solutions/1861-rotating-the-box.js new file mode 100644 index 00000000..0b874c74 --- /dev/null +++ b/solutions/1861-rotating-the-box.js @@ -0,0 +1,46 @@ +/** + * 1861. Rotating the Box + * https://leetcode.com/problems/rotating-the-box/ + * Difficulty: Medium + * + * You are given an m x n matrix of characters boxGrid representing a side-view of a box. + * Each cell of the box is one of the following: + * - A stone '#' + * - A stationary obstacle '*' + * - Empty '.' + * + * The box is rotated 90 degrees clockwise, causing some of the stones to fall due to gravity. + * Each stone falls down until it lands on an obstacle, another stone, or the bottom of the box. + * Gravity does not affect the obstacles' positions, and the inertia from the box's rotation + * does not affect the stones' horizontal positions. + * + * It is guaranteed that each stone in boxGrid rests on an obstacle, another stone, or the + * bottom of the box. + * + * Return an n x m matrix representing the box after the rotation described above. + */ + +/** + * @param {character[][]} boxGrid + * @return {character[][]} + */ +var rotateTheBox = function(boxGrid) { + const rows = boxGrid.length; + const cols = boxGrid[0].length; + const result = Array.from({ length: cols }, () => new Array(rows).fill('.')); + + for (let row = 0; row < rows; row++) { + let freePosition = cols - 1; + for (let col = cols - 1; col >= 0; col--) { + if (boxGrid[row][col] === '*') { + result[col][rows - 1 - row] = '*'; + freePosition = col - 1; + } else if (boxGrid[row][col] === '#') { + result[freePosition][rows - 1 - row] = '#'; + freePosition--; + } + } + } + + return result; +}; diff --git a/solutions/1862-sum-of-floored-pairs.js b/solutions/1862-sum-of-floored-pairs.js new file mode 100644 index 00000000..4d470c3c --- /dev/null +++ b/solutions/1862-sum-of-floored-pairs.js @@ -0,0 +1,44 @@ +/** + * 1862. Sum of Floored Pairs + * https://leetcode.com/problems/sum-of-floored-pairs/ + * Difficulty: Hard + * + * Given an integer array nums, return the sum of floor(nums[i] / nums[j]) for all pairs of + * indices 0 <= i, j < nums.length in the array. Since the answer may be too large, return + * it modulo 109 + 7. + * + * The floor() function returns the integer part of the division. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var sumOfFlooredPairs = function(nums) { + const modulo = 1e9 + 7; + const maxValue = Math.max(...nums); + const frequency = new Array(maxValue + 1).fill(0); + const prefixSum = new Array(maxValue + 1).fill(0); + let result = 0; + + for (const num of nums) { + frequency[num]++; + } + + for (let i = 1; i <= maxValue; i++) { + prefixSum[i] = prefixSum[i - 1] + frequency[i]; + } + + for (let i = 1; i <= maxValue; i++) { + if (frequency[i] === 0) continue; + for (let divisor = i; divisor <= maxValue; divisor += i) { + const quotient = Math.floor(divisor / i); + const count = ( + prefixSum[Math.min(maxValue, divisor + i - 1)] - prefixSum[divisor - 1] + ) % modulo; + result = (result + quotient * frequency[i] * count) % modulo; + } + } + + return result; +}; diff --git a/solutions/1864-minimum-number-of-swaps-to-make-the-binary-string-alternating.js b/solutions/1864-minimum-number-of-swaps-to-make-the-binary-string-alternating.js new file mode 100644 index 00000000..28378e0b --- /dev/null +++ b/solutions/1864-minimum-number-of-swaps-to-make-the-binary-string-alternating.js @@ -0,0 +1,49 @@ +/** + * 1864. Minimum Number of Swaps to Make the Binary String Alternating + * https://leetcode.com/problems/minimum-number-of-swaps-to-make-the-binary-string-alternating/ + * Difficulty: Medium + * + * Given a binary string s, return the minimum number of character swaps to make it alternating, + * or -1 if it is impossible. + * + * The string is called alternating if no two adjacent characters are equal. For example, the + * strings "010" and "1010" are alternating, while the string "0100" is not. + * + * Any two characters may be swapped, even if they are not adjacent. + */ + +/** + * @param {string} s + * @return {number} + */ +var minSwaps = function(s) { + const length = s.length; + let ones = 0; + let zeros = 0; + + for (const char of s) { + if (char === '1') ones++; + else zeros++; + } + + if (Math.abs(ones - zeros) > 1) return -1; + + let mismatchesStartWithZero = 0; + let mismatchesStartWithOne = 0; + + for (let i = 0; i < length; i++) { + if (i % 2 === 0) { + if (s[i] !== '0') mismatchesStartWithZero++; + if (s[i] !== '1') mismatchesStartWithOne++; + } else { + if (s[i] !== '1') mismatchesStartWithZero++; + if (s[i] !== '0') mismatchesStartWithOne++; + } + } + + if (ones === zeros) { + return Math.min(mismatchesStartWithZero, mismatchesStartWithOne) >> 1; + } + + return (ones > zeros ? mismatchesStartWithOne : mismatchesStartWithZero) >> 1; +}; diff --git a/solutions/1865-finding-pairs-with-a-certain-sum.js b/solutions/1865-finding-pairs-with-a-certain-sum.js new file mode 100644 index 00000000..9a100a1b --- /dev/null +++ b/solutions/1865-finding-pairs-with-a-certain-sum.js @@ -0,0 +1,60 @@ +/** + * 1865. Finding Pairs With a Certain Sum + * https://leetcode.com/problems/finding-pairs-with-a-certain-sum/ + * Difficulty: Medium + * + * You are given two integer arrays nums1 and nums2. You are tasked to implement a data structure + * that supports queries of two types: + * 1. Add a positive integer to an element of a given index in the array nums2. + * 2. Count the number of pairs (i, j) such that nums1[i] + nums2[j] equals a given + * value (0 <= i < nums1.length and 0 <= j < nums2.length). + * + * Implement the FindSumPairs class: + * - FindSumPairs(int[] nums1, int[] nums2) Initializes the FindSumPairs object with two integer + * arrays nums1 and nums2. + * - void add(int index, int val) Adds val to nums2[index], i.e., apply nums2[index] += val. + * - int count(int tot) Returns the number of pairs (i, j) such that nums1[i] + nums2[j] == tot. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + */ +var FindSumPairs = function(nums1, nums2) { + this.firstArray = nums1; + this.secondArray = nums2; + this.frequency = new Map(); + + for (const num of nums2) { + this.frequency.set(num, (this.frequency.get(num) || 0) + 1); + } +}; + +/** + * @param {number} index + * @param {number} val + * @return {void} + */ +FindSumPairs.prototype.add = function(index, val) { + const oldValue = this.secondArray[index]; + this.secondArray[index] += val; + const newValue = this.secondArray[index]; + + this.frequency.set(oldValue, this.frequency.get(oldValue) - 1); + this.frequency.set(newValue, (this.frequency.get(newValue) || 0) + 1); +}; + +/** + * @param {number} tot + * @return {number} + */ +FindSumPairs.prototype.count = function(tot) { + let result = 0; + + for (const num of this.firstArray) { + const complement = tot - num; + result += this.frequency.get(complement) || 0; + } + + return result; +}; diff --git a/solutions/1866-number-of-ways-to-rearrange-sticks-with-k-sticks-visible.js b/solutions/1866-number-of-ways-to-rearrange-sticks-with-k-sticks-visible.js new file mode 100644 index 00000000..3a2ffed6 --- /dev/null +++ b/solutions/1866-number-of-ways-to-rearrange-sticks-with-k-sticks-visible.js @@ -0,0 +1,37 @@ +/** + * 1866. Number of Ways to Rearrange Sticks With K Sticks Visible + * https://leetcode.com/problems/number-of-ways-to-rearrange-sticks-with-k-sticks-visible/ + * Difficulty: Hard + * + * There are n uniquely-sized sticks whose lengths are integers from 1 to n. You want to arrange + * the sticks such that exactly k sticks are visible from the left. A stick is visible from the + * left if there are no longer sticks to the left of it. + * - For example, if the sticks are arranged [1,3,2,5,4], then the sticks with lengths 1, 3, + * and 5 are visible from the left. + * + * Given n and k, return the number of such arrangements. Since the answer may be large, return + * it modulo 109 + 7. + */ + +/** + * @param {number} n + * @param {number} k + * @return {number} + */ +var rearrangeSticks = function(n, k) { + const modulo = 1e9 + 7; + const dp = Array.from({ length: n + 1 }, () => new Array(k + 1).fill(0)); + dp[0][0] = 1; + + for (let sticks = 1; sticks <= n; sticks++) { + for (let visible = 0; visible <= k; visible++) { + if (visible > sticks) continue; + if (visible > 0) { + dp[sticks][visible] = (dp[sticks][visible] + dp[sticks - 1][visible - 1]) % modulo; + } + dp[sticks][visible] = (dp[sticks][visible] + dp[sticks - 1][visible] * (sticks - 1)) % modulo; + } + } + + return dp[n][k]; +}; 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/1869-longer-contiguous-segments-of-ones-than-zeros.js b/solutions/1869-longer-contiguous-segments-of-ones-than-zeros.js new file mode 100644 index 00000000..bc6acf26 --- /dev/null +++ b/solutions/1869-longer-contiguous-segments-of-ones-than-zeros.js @@ -0,0 +1,38 @@ +/** + * 1869. Longer Contiguous Segments of Ones than Zeros + * https://leetcode.com/problems/longer-contiguous-segments-of-ones-than-zeros/ + * Difficulty: Easy + * + * Given a binary string s, return true if the longest contiguous segment of 1's is strictly + * longer than the longest contiguous segment of 0's in s, or return false otherwise. + * - For example, in s = "110100010" the longest continuous segment of 1s has length 2, and the + * longest continuous segment of 0s has length 3. + * + * Note that if there are no 0's, then the longest continuous segment of 0's is considered to + * have a length 0. The same applies if there is no 1's. + */ + +/** + * @param {string} s + * @return {boolean} + */ +var checkZeroOnes = function(s) { + let maxOnes = 0; + let maxZeros = 0; + let currentOnes = 0; + let currentZeros = 0; + + for (const char of s) { + if (char === '1') { + currentOnes++; + currentZeros = 0; + maxOnes = Math.max(maxOnes, currentOnes); + } else { + currentZeros++; + currentOnes = 0; + maxZeros = Math.max(maxZeros, currentZeros); + } + } + + return maxOnes > maxZeros; +}; diff --git a/solutions/1870-minimum-speed-to-arrive-on-time.js b/solutions/1870-minimum-speed-to-arrive-on-time.js new file mode 100644 index 00000000..fd7633a5 --- /dev/null +++ b/solutions/1870-minimum-speed-to-arrive-on-time.js @@ -0,0 +1,54 @@ +/** + * 1870. Minimum Speed to Arrive on Time + * https://leetcode.com/problems/minimum-speed-to-arrive-on-time/ + * Difficulty: Medium + * + * You are given a floating-point number hour, representing the amount of time you have to reach + * the office. To commute to the office, you must take n trains in sequential order. You are also + * given an integer array dist of length n, where dist[i] describes the distance (in kilometers) + * of the ith train ride. + * + * Each train can only depart at an integer hour, so you may need to wait in between each train + * ride. + * - For example, if the 1st train ride takes 1.5 hours, you must wait for an additional 0.5 hours + * before you can depart on the 2nd train ride at the 2 hour mark. + * + * Return the minimum positive integer speed (in kilometers per hour) that all the trains must + * travel at for you to reach the office on time, or -1 if it is impossible to be on time. + * + * Tests are generated such that the answer will not exceed 107 and hour will have at most two + * digits after the decimal point. + */ + +/** + * @param {number[]} dist + * @param {number} hour + * @return {number} + */ +var minSpeedOnTime = function(dist, hour) { + const trainCount = dist.length; + if (Math.ceil(trainCount - 1) > hour) return -1; + + let minSpeed = 1; + let maxSpeed = 10000000; + let result = -1; + + while (minSpeed <= maxSpeed) { + const midSpeed = (minSpeed + maxSpeed) >> 1; + let totalTime = 0; + + for (let i = 0; i < trainCount - 1; i++) { + totalTime += Math.ceil(dist[i] / midSpeed); + } + totalTime += dist[trainCount - 1] / midSpeed; + + if (totalTime <= hour) { + result = midSpeed; + maxSpeed = midSpeed - 1; + } else { + minSpeed = midSpeed + 1; + } + } + + return result; +}; diff --git a/solutions/1871-jump-game-vii.js b/solutions/1871-jump-game-vii.js new file mode 100644 index 00000000..92a47cc2 --- /dev/null +++ b/solutions/1871-jump-game-vii.js @@ -0,0 +1,44 @@ +/** + * 1871. Jump Game VII + * https://leetcode.com/problems/jump-game-vii/ + * Difficulty: Medium + * + * You are given a 0-indexed binary string s and two integers minJump and maxJump. In the + * beginning, you are standing at index 0, which is equal to '0'. You can move from index + * i to index j if the following conditions are fulfilled: + * - i + minJump <= j <= min(i + maxJump, s.length - 1), and + * - s[j] == '0'. + * + * Return true if you can reach index s.length - 1 in s, or false otherwise. + */ + +/** + * @param {string} s + * @param {number} minJump + * @param {number} maxJump + * @return {boolean} + */ +var canReach = function(s, minJump, maxJump) { + const length = s.length; + const reachable = new Array(length).fill(false); + reachable[0] = true; + const queue = [0]; + let farthest = 0; + + while (queue.length) { + const current = queue.shift(); + const start = current + minJump; + const end = Math.min(current + maxJump, length - 1); + + for (let next = Math.max(start, farthest + 1); next <= end; next++) { + if (s[next] === '0' && !reachable[next]) { + reachable[next] = true; + queue.push(next); + if (next === length - 1) return true; + } + } + farthest = Math.max(farthest, end); + } + + return false; +}; diff --git a/solutions/1872-stone-game-viii.js b/solutions/1872-stone-game-viii.js new file mode 100644 index 00000000..c8e74328 --- /dev/null +++ b/solutions/1872-stone-game-viii.js @@ -0,0 +1,42 @@ +/** + * 1872. Stone Game VIII + * https://leetcode.com/problems/stone-game-viii/ + * Difficulty: Hard + * + * Alice and Bob take turns playing a game, with Alice starting first. + * + * There are n stones arranged in a row. On each player's turn, while the number of stones is more + * than one, they will do the following: + * 1. Choose an integer x > 1, and remove the leftmost x stones from the row. + * 2. Add the sum of the removed stones' values to the player's score. + * 3. Place a new stone, whose value is equal to that sum, on the left side of the row. + * + * The game stops when only one stone is left in the row. + * + * The score difference between Alice and Bob is (Alice's score - Bob's score). Alice's goal is to + * maximize the score difference, and Bob's goal is the minimize the score difference. + * + * Given an integer array stones of length n where stones[i] represents the value of the ith stone + * from the left, return the score difference between Alice and Bob if they both play optimally. + */ + +/** + * @param {number[]} stones + * @return {number} + */ +var stoneGameVIII = function(stones) { + const length = stones.length; + const prefixSums = new Array(length).fill(0); + prefixSums[0] = stones[0]; + + for (let i = 1; i < length; i++) { + prefixSums[i] = prefixSums[i - 1] + stones[i]; + } + + let result = prefixSums[length - 1]; + for (let i = length - 2; i >= 1; i--) { + result = Math.max(result, prefixSums[i] - result); + } + + 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/1876-substrings-of-size-three-with-distinct-characters.js b/solutions/1876-substrings-of-size-three-with-distinct-characters.js new file mode 100644 index 00000000..cbe56e47 --- /dev/null +++ b/solutions/1876-substrings-of-size-three-with-distinct-characters.js @@ -0,0 +1,41 @@ +/** + * 1876. Substrings of Size Three with Distinct Characters + * https://leetcode.com/problems/substrings-of-size-three-with-distinct-characters/ + * Difficulty: Easy + * + * A string is good if there are no repeated characters. + * + * Given a string s, return the number of good substrings of length three in s. + * + * Note that if there are multiple occurrences of the same substring, every occurrence should + * be counted. + * + * A substring is a contiguous sequence of characters in a string. + */ + +/** + * @param {string} s + * @return {number} + */ +var countGoodSubstrings = function(s) { + if (s.length < 3) return 0; + + let result = 0; + const charCount = new Map(); + + for (let i = 0; i < 3; i++) { + charCount.set(s[i], (charCount.get(s[i]) || 0) + 1); + } + if (charCount.size === 3) result++; + + for (let i = 3; i < s.length; i++) { + const oldChar = s[i - 3]; + charCount.set(oldChar, charCount.get(oldChar) - 1); + if (charCount.get(oldChar) === 0) charCount.delete(oldChar); + + charCount.set(s[i], (charCount.get(s[i]) || 0) + 1); + if (charCount.size === 3) result++; + } + + return result; +}; diff --git a/solutions/1877-minimize-maximum-pair-sum-in-array.js b/solutions/1877-minimize-maximum-pair-sum-in-array.js new file mode 100644 index 00000000..264d9569 --- /dev/null +++ b/solutions/1877-minimize-maximum-pair-sum-in-array.js @@ -0,0 +1,35 @@ +/** + * 1877. Minimize Maximum Pair Sum in Array + * https://leetcode.com/problems/minimize-maximum-pair-sum-in-array/ + * Difficulty: Medium + * + * The pair sum of a pair (a,b) is equal to a + b. The maximum pair sum is the largest pair sum + * in a list of pairs. + * - For example, if we have pairs (1,5), (2,3), and (4,4), the maximum pair sum would be + * max(1+5, 2+3, 4+4) = max(6, 5, 8) = 8. + * + * Given an array nums of even length n, pair up the elements of nums into n / 2 pairs such that: + * - Each element of nums is in exactly one pair, and + * - The maximum pair sum is minimized. + * + * Return the minimized maximum pair sum after optimally pairing up the elements. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minPairSum = function(nums) { + nums.sort((a, b) => a - b); + let result = 0; + let left = 0; + let right = nums.length - 1; + + while (left < right) { + result = Math.max(result, nums[left] + nums[right]); + left++; + right--; + } + + return result; +}; diff --git a/solutions/1878-get-biggest-three-rhombus-sums-in-a-grid.js b/solutions/1878-get-biggest-three-rhombus-sums-in-a-grid.js new file mode 100644 index 00000000..f10c1b56 --- /dev/null +++ b/solutions/1878-get-biggest-three-rhombus-sums-in-a-grid.js @@ -0,0 +1,46 @@ +/** + * 1878. Get Biggest Three Rhombus Sums in a Grid + * https://leetcode.com/problems/get-biggest-three-rhombus-sums-in-a-grid/ + * Difficulty: Medium + * + * You are given an m x n integer matrix grid. + * + * A rhombus sum is the sum of the elements that form the border of a regular rhombus shape in + * grid. The rhombus must have the shape of a square rotated 45 degrees with each of the corners + * centered in a grid cell. Below is an image of four valid rhombus shapes with the corresponding + * colored cells that should be included in each rhombus sum. + * + * Note that the rhombus can have an area of 0, which is depicted by the purple rhombus in the + * bottom right corner. + * + * Return the biggest three distinct rhombus sums in the grid in descending order. If there are + * less than three distinct values, return all of them. + */ + +/** + * @param {number[][]} grid + * @return {number[]} + */ +var getBiggestThree = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const sums = new Set(); + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + sums.add(grid[i][j]); + for (let size = 1; size <= Math.min(i, rows - 1 - i, j, cols - 1 - j); size++) { + let rhombusSum = 0; + rhombusSum += grid[i - size][j] + grid[i + size][j] + grid[i][j - size] + grid[i][j + size]; + for (let offset = 1; offset < size; offset++) { + rhombusSum += grid[i - size + offset][j + offset] + grid[i + size - offset][j + offset]; + rhombusSum += grid[i - size + offset][j - offset] + grid[i + size - offset][j - offset]; + } + sums.add(rhombusSum); + } + } + } + + const sortedSums = [...sums].sort((a, b) => b - a); + return sortedSums.slice(0, Math.min(3, sortedSums.length)); +}; diff --git a/solutions/1879-minimum-xor-sum-of-two-arrays.js b/solutions/1879-minimum-xor-sum-of-two-arrays.js new file mode 100644 index 00000000..2f7c4f61 --- /dev/null +++ b/solutions/1879-minimum-xor-sum-of-two-arrays.js @@ -0,0 +1,39 @@ +/** + * 1879. Minimum XOR Sum of Two Arrays + * https://leetcode.com/problems/minimum-xor-sum-of-two-arrays/ + * Difficulty: Hard + * + * You are given two integer arrays nums1 and nums2 of length n. + * + * The XOR sum of the two integer arrays is (nums1[0] XOR nums2[0]) + (nums1[1] XOR nums2[1]) + * + ... + (nums1[n - 1] XOR nums2[n - 1]) (0-indexed). + * - For example, the XOR sum of [1,2,3] and [3,2,1] is equal to (1 XOR 3) + (2 XOR 2) + + * (3 XOR 1) = 2 + 0 + 2 = 4. + * + * Rearrange the elements of nums2 such that the resulting XOR sum is minimized. + * + * Return the XOR sum after the rearrangement. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @return {number} + */ +var minimumXORSum = function(nums1, nums2) { + const n = nums1.length; + const dp = new Array(1 << n).fill(Infinity); + dp[0] = 0; + + for (let mask = 0; mask < (1 << n); mask++) { + const usedCount = mask.toString(2).split('1').length - 1; + for (let j = 0; j < n; j++) { + if (!(mask & (1 << j))) { + const newMask = mask | (1 << j); + dp[newMask] = Math.min(dp[newMask], dp[mask] + (nums1[usedCount] ^ nums2[j])); + } + } + } + + return dp[(1 << n) - 1]; +}; diff --git a/solutions/1881-maximum-value-after-insertion.js b/solutions/1881-maximum-value-after-insertion.js new file mode 100644 index 00000000..4ba804d7 --- /dev/null +++ b/solutions/1881-maximum-value-after-insertion.js @@ -0,0 +1,46 @@ +/** + * 1881. Maximum Value after Insertion + * https://leetcode.com/problems/maximum-value-after-insertion/ + * Difficulty: Medium + * + * You are given a very large integer n, represented as a string, and an integer digit x. + * The digits in n and the digit x are in the inclusive range [1, 9], and n may represent + * a negative number. + * + * You want to maximize n's numerical value by inserting x anywhere in the decimal representation + * of n. You cannot insert x to the left of the negative sign. + * - For example, if n = 73 and x = 6, it would be best to insert it between 7 and 3, making + * n = 763. + * - If n = -55 and x = 2, it would be best to insert it before the first 5, making n = -255. + * + * Return a string representing the maximum value of n after the insertion. + */ + +/** + * @param {string} n + * @param {number} x + * @return {string} + */ +var maxValue = function(n, x) { + const isNegative = n[0] === '-'; + const digits = n.slice(isNegative ? 1 : 0); + let result = ''; + + if (isNegative) { + for (let i = 0; i <= digits.length; i++) { + if (i === digits.length || x < parseInt(digits[i])) { + result = '-' + digits.slice(0, i) + x + digits.slice(i); + break; + } + } + } else { + for (let i = 0; i <= digits.length; i++) { + if (i === digits.length || x > parseInt(digits[i])) { + result = digits.slice(0, i) + x + digits.slice(i); + break; + } + } + } + + return result; +}; diff --git a/solutions/1882-process-tasks-using-servers.js b/solutions/1882-process-tasks-using-servers.js new file mode 100644 index 00000000..e82ad99f --- /dev/null +++ b/solutions/1882-process-tasks-using-servers.js @@ -0,0 +1,71 @@ +/** + * 1882. Process Tasks Using Servers + * https://leetcode.com/problems/process-tasks-using-servers/ + * Difficulty: Medium + * + * You are given two 0-indexed integer arrays servers and tasks of lengths n and m respectively. + * servers[i] is the weight of the ith server, and tasks[j] is the time needed to process the + * jth task in seconds. + * + * Tasks are assigned to the servers using a task queue. Initially, all servers are free, and + * the queue is empty. + * + * At second j, the jth task is inserted into the queue (starting with the 0th task being inserted + * at second 0). As long as there are free servers and the queue is not empty, the task in the front + * of the queue will be assigned to a free server with the smallest weight, and in case of a tie, + * it is assigned to a free server with the smallest index. + * + * If there are no free servers and the queue is not empty, we wait until a server becomes free + * and immediately assign the next task. If multiple servers become free at the same time, then + * multiple tasks from the queue will be assigned in order of insertion following the weight and + * index priorities above. + * + * A server that is assigned task j at second t will be free again at second t + tasks[j]. + * + * Build an array ans of length m, where ans[j] is the index of the server the jth task will + * be assigned to. + * + * Return the array ans. + */ + +/** + * @param {number[]} servers + * @param {number[]} tasks + * @return {number[]} + */ +var assignTasks = function(servers, tasks) { + const serverHeap = new PriorityQueue((a, b) => a[0] * 1000000 + a[1] - (b[0] * 1000000 + b[1])); + const busyHeap = new PriorityQueue((a, b) => a[0] - b[0]); + const result = new Array(tasks.length); + + for (let i = 0; i < servers.length; i++) { + serverHeap.enqueue([servers[i], i]); + } + + let time = 0; + let taskIndex = 0; + + while (taskIndex < tasks.length) { + time = Math.max(time, taskIndex); + + while (!busyHeap.isEmpty() && busyHeap.front()[0] <= time) { + const [, weight, index] = busyHeap.dequeue(); + serverHeap.enqueue([weight, index]); + } + + while (serverHeap.size() && taskIndex < tasks.length && taskIndex <= time) { + const [weight, index] = serverHeap.dequeue(); + result[taskIndex] = index; + busyHeap.enqueue([time + tasks[taskIndex], weight, index]); + taskIndex++; + } + + if (serverHeap.isEmpty() && taskIndex < tasks.length) { + const [freeTime, weight, index] = busyHeap.dequeue(); + time = freeTime; + serverHeap.enqueue([weight, index]); + } + } + + return result; +}; diff --git a/solutions/1883-minimum-skips-to-arrive-at-meeting-on-time.js b/solutions/1883-minimum-skips-to-arrive-at-meeting-on-time.js new file mode 100644 index 00000000..23d83b18 --- /dev/null +++ b/solutions/1883-minimum-skips-to-arrive-at-meeting-on-time.js @@ -0,0 +1,66 @@ +/** + * 1883. Minimum Skips to Arrive at Meeting On Time + * https://leetcode.com/problems/minimum-skips-to-arrive-at-meeting-on-time/ + * Difficulty: Hard + * + * You are given an integer hoursBefore, the number of hours you have to travel to your meeting. + * To arrive at your meeting, you have to travel through n roads. The road lengths are given as + * an integer array dist of length n, where dist[i] describes the length of the ith road in + * kilometers. In addition, you are given an integer speed, which is the speed (in km/h) you + * will travel at. + * + * After you travel road i, you must rest and wait for the next integer hour before you can begin + * traveling on the next road. Note that you do not have to rest after traveling the last road + * because you are already at the meeting. + * - For example, if traveling a road takes 1.4 hours, you must wait until the 2 hour mark before + * traveling the next road. If traveling a road takes exactly 2 hours, you do not need to wait. + * + * However, you are allowed to skip some rests to be able to arrive on time, meaning you do not + * need to wait for the next integer hour. Note that this means you may finish traveling future + * roads at different hour marks. + * - For example, suppose traveling the first road takes 1.4 hours and traveling the second road + * takes 0.6 hours. Skipping the rest after the first road will mean you finish traveling the + * second road right at the 2 hour mark, letting you start traveling the third road immediately. + * + * Return the minimum number of skips required to arrive at the meeting on time, or -1 if it is + * impossible. + */ + +/** + * @param {number[]} dist + * @param {number} speed + * @param {number} hoursBefore + * @return {number} + */ +var minSkips = function(dist, speed, hoursBefore) { + const n = dist.length; + const dp = Array.from({ length: n + 1 }, () => new Array(n + 1).fill(Infinity)); + dp[0][0] = 0; + + for (let i = 1; i <= n; i++) { + for (let skips = 0; skips <= i; skips++) { + if (skips < i) { + const prevTime = dp[i - 1][skips]; + if (prevTime !== Infinity) { + const time = prevTime + dist[i - 1]; + dp[i][skips] = Math.min(dp[i][skips], Math.ceil(time / speed) * speed); + } + } + if (skips > 0) { + const prevTime = dp[i - 1][skips - 1]; + if (prevTime !== Infinity) { + dp[i][skips] = Math.min(dp[i][skips], prevTime + dist[i - 1]); + } + } + } + } + + const targetTime = hoursBefore * speed; + for (let skips = 0; skips <= n; skips++) { + if (dp[n][skips] <= targetTime) { + return skips; + } + } + + return -1; +}; diff --git a/solutions/1884-egg-drop-with-2-eggs-and-n-floors.js b/solutions/1884-egg-drop-with-2-eggs-and-n-floors.js new file mode 100644 index 00000000..4b5ccb3f --- /dev/null +++ b/solutions/1884-egg-drop-with-2-eggs-and-n-floors.js @@ -0,0 +1,42 @@ +/** + * 1884. Egg Drop With 2 Eggs and N Floors + * https://leetcode.com/problems/egg-drop-with-2-eggs-and-n-floors/ + * Difficulty: Medium + * + * You are given two identical eggs and you have access to a building with n floors labeled + * from 1 to n. + * + * You know that there exists a floor f where 0 <= f <= n such that any egg dropped at a floor + * higher than f will break, and any egg dropped at or below floor f will not break. + * + * In each move, you may take an unbroken egg and drop it from any floor x (where 1 <= x <= n). + * If the egg breaks, you can no longer use it. However, if the egg does not break, you may + * reuse it in future moves. + * + * Return the minimum number of moves that you need to determine with certainty what the value + * of f is. + */ + +/** + * @param {number} n + * @return {number} + */ +var twoEggDrop = function(n) { + const dp = Array.from({ length: 3 }, () => new Array(n + 1).fill(Infinity)); + dp[0][0] = 0; + dp[1][0] = 0; + dp[2][0] = 0; + + for (let floors = 1; floors <= n; floors++) { + dp[1][floors] = floors; + for (let eggs = 2; eggs <= 2; eggs++) { + for (let k = 1; k <= floors; k++) { + const breaks = dp[eggs - 1][k - 1]; + const survives = dp[eggs][floors - k]; + dp[eggs][floors] = Math.min(dp[eggs][floors], 1 + Math.max(breaks, survives)); + } + } + } + + return dp[2][n]; +}; 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/1887-reduction-operations-to-make-the-array-elements-equal.js b/solutions/1887-reduction-operations-to-make-the-array-elements-equal.js new file mode 100644 index 00000000..d6672d7b --- /dev/null +++ b/solutions/1887-reduction-operations-to-make-the-array-elements-equal.js @@ -0,0 +1,34 @@ +/** + * 1887. Reduction Operations to Make the Array Elements Equal + * https://leetcode.com/problems/reduction-operations-to-make-the-array-elements-equal/ + * Difficulty: Medium + * + * Given an integer array nums, your goal is to make all elements in nums equal. To complete one + * operation, follow these steps: + * 1. Find the largest value in nums. Let its index be i (0-indexed) and its value be largest. + * If there are multiple elements with the largest value, pick the smallest i. + * 2. Find the next largest value in nums strictly smaller than largest. Let its value be + * nextLargest. + * 3. Reduce nums[i] to nextLargest. + * + * Return the number of operations to make all elements in nums equal. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var reductionOperations = function(nums) { + nums.sort((a, b) => a - b); + let result = 0; + let count = 0; + + for (let i = 1; i < nums.length; i++) { + if (nums[i] !== nums[i - 1]) { + count++; + } + result += count; + } + + return result; +}; diff --git a/solutions/1888-minimum-number-of-flips-to-make-the-binary-string-alternating.js b/solutions/1888-minimum-number-of-flips-to-make-the-binary-string-alternating.js new file mode 100644 index 00000000..24795a9f --- /dev/null +++ b/solutions/1888-minimum-number-of-flips-to-make-the-binary-string-alternating.js @@ -0,0 +1,47 @@ +/** + * 1888. Minimum Number of Flips to Make the Binary String Alternating + * https://leetcode.com/problems/minimum-number-of-flips-to-make-the-binary-string-alternating/ + * Difficulty: Medium + * + * You are given a binary string s. You are allowed to perform two types of operations on the + * string in any sequence: + * - Type-1: Remove the character at the start of the string s and append it to the end of + * the string. + * - Type-2: Pick any character in s and flip its value, i.e., if its value is '0' it becomes + * '1' and vice-versa. + * + * Return the minimum number of type-2 operations you need to perform such that s becomes + * alternating. + * + * The string is called alternating if no two adjacent characters are equal. + * + * For example, the strings "010" and "1010" are alternating, while the string "0100" is not. + */ + +/** + * @param {string} s + * @return {number} + */ +var minFlips = function(s) { + const n = s.length; + let result = n; + let flipsZeroStart = 0; + let flipsOneStart = 0; + + for (let i = 0; i < n; i++) { + if (s[i] !== (i % 2 === 0 ? '0' : '1')) flipsZeroStart++; + if (s[i] !== (i % 2 === 0 ? '1' : '0')) flipsOneStart++; + } + + result = Math.min(flipsZeroStart, flipsOneStart); + + for (let i = 0; i < n - 1; i++) { + if (s[i] !== (i % 2 === 0 ? '0' : '1')) flipsZeroStart--; + if (s[i] !== (i % 2 === 0 ? '1' : '0')) flipsOneStart--; + if (s[i] !== ((n + i) % 2 === 0 ? '0' : '1')) flipsZeroStart++; + if (s[i] !== ((n + i) % 2 === 0 ? '1' : '0')) flipsOneStart++; + result = Math.min(result, flipsZeroStart, flipsOneStart); + } + + return result; +}; diff --git a/solutions/1889-minimum-space-wasted-from-packaging.js b/solutions/1889-minimum-space-wasted-from-packaging.js new file mode 100644 index 00000000..de010d0f --- /dev/null +++ b/solutions/1889-minimum-space-wasted-from-packaging.js @@ -0,0 +1,82 @@ +/** + * 1889. Minimum Space Wasted From Packaging + * https://leetcode.com/problems/minimum-space-wasted-from-packaging/ + * Difficulty: Hard + * + * You have n packages that you are trying to place in boxes, one package in each box. There are + * m suppliers that each produce boxes of different sizes (with infinite supply). A package can + * be placed in a box if the size of the package is less than or equal to the size of the box. + * + * The package sizes are given as an integer array packages, where packages[i] is the size of the + * ith package. The suppliers are given as a 2D integer array boxes, where boxes[j] is an array + * of box sizes that the jth supplier produces. + * + * You want to choose a single supplier and use boxes from them such that the total wasted space + * is minimized. For each package in a box, we define the space wasted to be size of the box - size + * of the package. The total wasted space is the sum of the space wasted in all the boxes. + * - For example, if you have to fit packages with sizes [2,3,5] and the supplier offers boxes of + * sizes [4,8], you can fit the packages of size-2 and size-3 into two boxes of size-4 and the + * package with size-5 into a box of size-8. This would result in a waste + * of (4-2) + (4-3) + (8-5) = 6. + * + * Return the minimum total wasted space by choosing the box supplier optimally, or -1 if it is + * impossible to fit all the packages inside boxes. Since the answer may be large, return it + * modulo 109 + 7. + */ + +/** + * @param {number[]} packages + * @param {number[][]} boxes + * @return {number} + */ +var minWastedSpace = function(packages, boxes) { + const modulo = 1e9 + 7; + packages.sort((a, b) => a - b); + let minWaste = BigInt(2) ** BigInt(60); + const n = packages.length; + + const prefixSums = new Array(n + 1).fill(BigInt(0)); + for (let i = 0; i < n; i++) { + prefixSums[i + 1] = prefixSums[i] + BigInt(packages[i]); + } + + for (const supplier of boxes) { + supplier.sort((a, b) => a - b); + if (supplier[supplier.length - 1] < packages[n - 1]) continue; + + let waste = BigInt(0); + let packageIndex = 0; + + for (const box of supplier) { + if (packageIndex >= n) break; + const upperBound = binarySearch(packages, box, packageIndex); + if (upperBound > packageIndex) { + const count = BigInt(upperBound - packageIndex); + waste += count * BigInt(box) - (prefixSums[upperBound] - prefixSums[packageIndex]); + packageIndex = upperBound; + } + } + + if (packageIndex === n) { + minWaste = minWaste < waste ? minWaste : waste; + } + } + + return minWaste === BigInt(2) ** BigInt(60) ? -1 : Number(minWaste % BigInt(modulo)); +}; + +function binarySearch(arr, target, start) { + let left = start; + let right = arr.length; + + while (left < right) { + const mid = (left + right) >> 1; + if (arr[mid] <= target) { + left = mid + 1; + } else { + right = mid; + } + } + + return left; +} 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/1893-check-if-all-the-integers-in-a-range-are-covered.js b/solutions/1893-check-if-all-the-integers-in-a-range-are-covered.js new file mode 100644 index 00000000..def56b8c --- /dev/null +++ b/solutions/1893-check-if-all-the-integers-in-a-range-are-covered.js @@ -0,0 +1,35 @@ +/** + * 1893. Check if All the Integers in a Range Are Covered + * https://leetcode.com/problems/check-if-all-the-integers-in-a-range-are-covered/ + * Difficulty: Easy + * + * You are given a 2D integer array ranges and two integers left and right. Each + * ranges[i] = [starti, endi] represents an inclusive interval between starti and endi. + * + * Return true if each integer in the inclusive range [left, right] is covered by at least + * one interval in ranges. Return false otherwise. + * + * An integer x is covered by an interval ranges[i] = [starti, endi] if starti <= x <= endi. + */ + +/** + * @param {number[][]} ranges + * @param {number} left + * @param {number} right + * @return {boolean} + */ +var isCovered = function(ranges, left, right) { + const covered = new Array(51).fill(false); + + for (const [start, end] of ranges) { + for (let i = start; i <= end; i++) { + covered[i] = true; + } + } + + for (let i = left; i <= right; i++) { + if (!covered[i]) return false; + } + + return true; +}; diff --git a/solutions/1894-find-the-student-that-will-replace-the-chalk.js b/solutions/1894-find-the-student-that-will-replace-the-chalk.js new file mode 100644 index 00000000..387fd854 --- /dev/null +++ b/solutions/1894-find-the-student-that-will-replace-the-chalk.js @@ -0,0 +1,38 @@ +/** + * 1894. Find the Student that Will Replace the Chalk + * https://leetcode.com/problems/find-the-student-that-will-replace-the-chalk/ + * Difficulty: Medium + * + * There are n students in a class numbered from 0 to n - 1. The teacher will give each student + * a problem starting with the student number 0, then the student number 1, and so on until the + * teacher reaches the student number n - 1. After that, the teacher will restart the process, + * starting with the student number 0 again. + * + * You are given a 0-indexed integer array chalk and an integer k. There are initially k pieces + * of chalk. When the student number i is given a problem to solve, they will use chalk[i] + * pieces of chalk to solve that problem. However, if the current number of chalk pieces is + * strictly less than chalk[i], then the student number i will be asked to replace the chalk. + * + * Return the index of the student that will replace the chalk pieces. + */ + +/** + * @param {number[]} chalk + * @param {number} k + * @return {number} + */ +var chalkReplacer = function(chalk, k) { + let totalChalk = 0; + for (const amount of chalk) { + totalChalk += amount; + } + + k = k % totalChalk; + + for (let i = 0; i < chalk.length; i++) { + if (k < chalk[i]) return i; + k -= chalk[i]; + } + + return 0; +}; diff --git a/solutions/1895-largest-magic-square.js b/solutions/1895-largest-magic-square.js new file mode 100644 index 00000000..e23a71cc --- /dev/null +++ b/solutions/1895-largest-magic-square.js @@ -0,0 +1,71 @@ +/** + * 1895. Largest Magic Square + * https://leetcode.com/problems/largest-magic-square/ + * Difficulty: Medium + * + * A k x k magic square is a k x k grid filled with integers such that every row sum, every + * column sum, and both diagonal sums are all equal. The integers in the magic square do not + * have to be distinct. Every 1 x 1 grid is trivially a magic square. + * + * Given an m x n integer grid, return the size (i.e., the side length k) of the largest magic + * square that can be found within this grid. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var largestMagicSquare = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + const rowSums = Array.from({ length: rows + 1 }, () => new Array(cols + 1).fill(0)); + const colSums = 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++) { + rowSums[i][j] = rowSums[i][j - 1] + grid[i - 1][j - 1]; + colSums[i][j] = colSums[i - 1][j] + grid[i - 1][j - 1]; + } + } + + const maxSize = 1; + for (let size = Math.min(rows, cols); size >= 2; size--) { + for (let i = size; i <= rows; i++) { + for (let j = size; j <= cols; j++) { + const rowSum = rowSums[i][j] - rowSums[i][j - size]; + let isMagic = true; + + for (let k = 1; k < size; k++) { + if (rowSums[i - k][j] - rowSums[i - k][j - size] !== rowSum) { + isMagic = false; + break; + } + } + + if (!isMagic) continue; + + for (let k = 0; k < size; k++) { + if (colSums[i][j - k] - colSums[i - size][j - k] !== rowSum) { + isMagic = false; + break; + } + } + + if (!isMagic) continue; + + let diagSum1 = 0; + let diagSum2 = 0; + for (let k = 0; k < size; k++) { + diagSum1 += grid[i - size + k][j - size + k]; + diagSum2 += grid[i - size + k][j - 1 - k]; + } + + if (diagSum1 === rowSum && diagSum2 === rowSum) { + return size; + } + } + } + } + + return maxSize; +}; diff --git a/solutions/1896-minimum-cost-to-change-the-final-value-of-expression.js b/solutions/1896-minimum-cost-to-change-the-final-value-of-expression.js new file mode 100644 index 00000000..1e430149 --- /dev/null +++ b/solutions/1896-minimum-cost-to-change-the-final-value-of-expression.js @@ -0,0 +1,113 @@ +/** + * 1896. Minimum Cost to Change the Final Value of Expression + * https://leetcode.com/problems/minimum-cost-to-change-the-final-value-of-expression/ + * Difficulty: Hard + * + * You are given a valid boolean expression as a string expression consisting of the + * characters '1','0','&' (bitwise AND operator),'|' (bitwise OR operator),'(', and ')'. + * - For example, "()1|1" and "(1)&()" are not valid while "1", "(((1))|(0))", and "1|(0&(1))" + * are valid expressions. + * + * Return the minimum cost to change the final value of the expression. + * - For example, if expression = "1|1|(0&0)&1", its value is + * 1|1|(0&0)&1 = 1|1|0&1 = 1|0&1 = 1&1 = 1. We want to apply operations so that the new + * expression evaluates to 0. + * + * The cost of changing the final value of an expression is the number of operations performed + * on the expression. The types of operations are described as follows: + * - Turn a '1' into a '0'. + * - Turn a '0' into a '1'. + * - Turn a '&' into a '|'. + * - Turn a '|' into a '&'. + * + * Note: '&' does not take precedence over '|' in the order of calculation. Evaluate parentheses + * first, then in left-to-right order. + */ + +/** + * @param {string} expression + * @return {number} + */ +var minOperationsToFlip = function(expression) { + const stack = []; + for (const char of expression) { + if (char === ')') { + const values = []; + while (stack.length && stack[stack.length - 1][0] !== '(') { + values.push(stack.pop()); + } + stack.pop(); + let [val1, cost1] = values.pop(); + while (values.length) { + const [op] = values.pop(); + const [val2, cost2] = values.pop(); + if (op === '&') { + if (val1 === 1 && val2 === 1) { + val1 = 1; + cost1 = Math.min(cost1, cost2); + } else if (val1 === 0 && val2 === 0) { + val1 = 0; + cost1 = Math.min(cost1 + 1, cost2 + 1); + } else { + val1 = 0; + cost1 = Math.min(cost1 + cost2, 1); + } + } else { + if (val1 === 1 && val2 === 1) { + val1 = 1; + cost1 = Math.min(cost1 + 1, cost2 + 1); + } else if (val1 === 0 && val2 === 0) { + val1 = 0; + cost1 = Math.min(cost1, cost2); + } else { + val1 = 1; + cost1 = Math.min(cost1 + cost2, 1); + } + } + } + stack.push([val1, cost1]); + } else if (char === '1') { + stack.push([1, 1]); + } else if (char === '0') { + stack.push([0, 1]); + } else { + stack.push([char]); + } + } + + const values = []; + while (stack.length) { + values.push(stack.pop()); + } + + let [val1, cost1] = values.pop(); + while (values.length) { + const [op] = values.pop(); + const [val2, cost2] = values.pop(); + if (op === '&') { + if (val1 === 1 && val2 === 1) { + val1 = 1; + cost1 = Math.min(cost1, cost2); + } else if (val1 === 0 && val2 === 0) { + val1 = 0; + cost1 = Math.min(cost1 + 1, cost2 + 1); + } else { + val1 = 0; + cost1 = Math.min(cost1 + cost2, 1); + } + } else { + if (val1 === 1 && val2 === 1) { + val1 = 1; + cost1 = Math.min(cost1 + 1, cost2 + 1); + } else if (val1 === 0 && val2 === 0) { + val1 = 0; + cost1 = Math.min(cost1, cost2); + } else { + val1 = 1; + cost1 = Math.min(cost1 + cost2, 1); + } + } + } + + return cost1; +}; diff --git a/solutions/1897-redistribute-characters-to-make-all-strings-equal.js b/solutions/1897-redistribute-characters-to-make-all-strings-equal.js new file mode 100644 index 00000000..b58b05ba --- /dev/null +++ b/solutions/1897-redistribute-characters-to-make-all-strings-equal.js @@ -0,0 +1,34 @@ +/** + * 1897. Redistribute Characters to Make All Strings Equal + * https://leetcode.com/problems/redistribute-characters-to-make-all-strings-equal/ + * Difficulty: Easy + * + * You are given an array of strings words (0-indexed). + * + * In one operation, pick two distinct indices i and j, where words[i] is a non-empty string, + * and move any character from words[i] to any position in words[j]. + * + * Return true if you can make every string in words equal using any number of operations, and + * false otherwise. + */ + +/** + * @param {string[]} words + * @return {boolean} + */ +var makeEqual = function(words) { + const charCount = new Array(26).fill(0); + const wordCount = words.length; + + for (const word of words) { + for (const char of word) { + charCount[char.charCodeAt(0) - 97]++; + } + } + + for (const count of charCount) { + if (count % wordCount !== 0) return false; + } + + return true; +}; diff --git a/solutions/1898-maximum-number-of-removable-characters.js b/solutions/1898-maximum-number-of-removable-characters.js new file mode 100644 index 00000000..1a4c15fa --- /dev/null +++ b/solutions/1898-maximum-number-of-removable-characters.js @@ -0,0 +1,51 @@ +/** + * 1898. Maximum Number of Removable Characters + * https://leetcode.com/problems/maximum-number-of-removable-characters/ + * Difficulty: Medium + * + * You are given two strings s and p where p is a subsequence of s. You are also given a distinct + * 0-indexed integer array removable containing a subset of indices of s (s is also 0-indexed). + * + * You want to choose an integer k (0 <= k <= removable.length) such that, after removing k + * characters from s using the first k indices in removable, p is still a subsequence of s. + * More formally, you will mark the character at s[removable[i]] for each 0 <= i < k, then + * remove all marked characters and check if p is still a subsequence. + * + * Return the maximum k you can choose such that p is still a subsequence of s after the removals. + * + * A subsequence of a string is a new string generated from the original string with some + * characters (can be none) deleted without changing the relative order of the remaining characters. + */ + +/** + * @param {string} s + * @param {string} p + * @param {number[]} removable + * @return {number} + */ +var maximumRemovals = function(s, p, removable) { + let left = 0; + let right = removable.length; + + while (left <= right) { + const mid = (left + right) >> 1; + const removed = new Set(removable.slice(0, mid)); + let i = 0; + let j = 0; + + while (i < s.length && j < p.length) { + if (!removed.has(i) && s[i] === p[j]) { + j++; + } + i++; + } + + if (j === p.length) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return right; +}; diff --git a/solutions/1899-merge-triplets-to-form-target-triplet.js b/solutions/1899-merge-triplets-to-form-target-triplet.js new file mode 100644 index 00000000..606dacf4 --- /dev/null +++ b/solutions/1899-merge-triplets-to-form-target-triplet.js @@ -0,0 +1,40 @@ +/** + * 1899. Merge Triplets to Form Target Triplet + * https://leetcode.com/problems/merge-triplets-to-form-target-triplet/ + * Difficulty: Medium + * + * A triplet is an array of three integers. You are given a 2D integer array triplets, where + * triplets[i] = [ai, bi, ci] describes the ith triplet. You are also given an integer array + * target = [x, y, z] that describes the triplet you want to obtain. + * + * To obtain target, you may apply the following operation on triplets any number of times + * (possibly zero): + * - Choose two indices (0-indexed) i and j (i != j) and update triplets[j] to become + * [max(ai, aj), max(bi, bj), max(ci, cj)]. + * - For example, if triplets[i] = [2, 5, 3] and triplets[j] = [1, 7, 5], triplets[j] will + * be updated to [max(2, 1), max(5, 7), max(3, 5)] = [2, 7, 5]. + * + * Return true if it is possible to obtain the target triplet [x, y, z] as an element of triplets, + * or false otherwise. + */ + +/** + * @param {number[][]} triplets + * @param {number[]} target + * @return {boolean} + */ +var mergeTriplets = function(triplets, target) { + let canFormX = false; + let canFormY = false; + let canFormZ = false; + + for (const [a, b, c] of triplets) { + if (a <= target[0] && b <= target[1] && c <= target[2]) { + if (a === target[0]) canFormX = true; + if (b === target[1]) canFormY = true; + if (c === target[2]) canFormZ = true; + } + } + + return canFormX && canFormY && canFormZ; +}; diff --git a/solutions/1900-the-earliest-and-latest-rounds-where-players-compete.js b/solutions/1900-the-earliest-and-latest-rounds-where-players-compete.js new file mode 100644 index 00000000..47d9293b --- /dev/null +++ b/solutions/1900-the-earliest-and-latest-rounds-where-players-compete.js @@ -0,0 +1,86 @@ +/** + * 1900. The Earliest and Latest Rounds Where Players Compete + * https://leetcode.com/problems/the-earliest-and-latest-rounds-where-players-compete/ + * Difficulty: Hard + * + * There is a tournament where n players are participating. The players are standing in a single row + * and are numbered from 1 to n based on their initial standing position (player 1 is the first + * player in the row, player 2 is the second player in the row, etc.). + * + * The tournament consists of multiple rounds (starting from round number 1). In each round, the ith + * player from the front of the row competes against the ith player from the end of the row, and the + * winner advances to the next round. When the number of players is odd for the current round, the + * player in the middle automatically advances to the next round. + * - For example, if the row consists of players 1, 2, 4, 6, 7 + * - Player 1 competes against player 7. + * - Player 2 competes against player 6. + * - Player 4 automatically advances to the next round. + * + * After each round is over, the winners are lined back up in the row based on the original ordering + * assigned to them initially (ascending order). + * + * The players numbered firstPlayer and secondPlayer are the best in the tournament. They can win + * against any other player before they compete against each other. If any two other players compete + * against each other, either of them might win, and thus you may choose the outcome of this round. + * + * Given the integers n, firstPlayer, and secondPlayer, return an integer array containing two + * values, the earliest possible round number and the latest possible round number in which these + * two players will compete against each other, respectively. + */ + +/** + * @param {number} n + * @param {number} firstPlayer + * @param {number} secondPlayer + * @return {number[]} + */ +var earliestAndLatest = function(numPlayers, firstPlayer, secondPlayer) { + let minRounds = Infinity; + let maxRounds = 0; + + dfs(0, 1); + + return [minRounds, maxRounds]; + + function dfs(playersEliminated, numRounds) { + let roundResults = [playersEliminated]; + let i = 1; + let j = numPlayers; + + while (true) { + while (playersEliminated & (1 << i)) i++; + while (playersEliminated & (1 << j)) j--; + + if (i >= j) break; + + if (i === firstPlayer && j === secondPlayer) { + minRounds = Math.min(minRounds, numRounds); + maxRounds = Math.max(maxRounds, numRounds); + return; + } + + const newRoundResults = []; + + if (j !== firstPlayer && j !== secondPlayer) { + for (const roundResult of roundResults) { + newRoundResults.push(roundResult | (1 << j)); + } + } + + if (i !== firstPlayer && i !== secondPlayer) { + for (const roundResult of roundResults) { + newRoundResults.push(roundResult | (1 << i)); + } + } + + i++; + j--; + roundResults = newRoundResults; + } + + if (!roundResults.length) return; + + numRounds++; + roundResults.forEach(roundResult => dfs(roundResult, numRounds)); + } +}; diff --git a/solutions/1901-find-a-peak-element-ii.js b/solutions/1901-find-a-peak-element-ii.js new file mode 100644 index 00000000..fc0a48ca --- /dev/null +++ b/solutions/1901-find-a-peak-element-ii.js @@ -0,0 +1,61 @@ +/** + * 1901. Find a Peak Element II + * https://leetcode.com/problems/find-a-peak-element-ii/ + * Difficulty: Medium + * + * A peak element in a 2D grid is an element that is strictly greater than all of its adjacent + * neighbors to the left, right, top, and bottom. + * + * Given a 0-indexed m x n matrix mat where no two adjacent cells are equal, find any peak element + * mat[i][j] and return the length 2 array [i,j]. + * + * You may assume that the entire matrix is surrounded by an outer perimeter with the value -1 in + * each cell. + * + * You must write an algorithm that runs in O(m log(n)) or O(n log(m)) time. + */ + +/** + * @param {number[][]} mat + * @return {number[]} + */ +var findPeakGrid = function(mat) { + const rows = mat.length; + const cols = mat[0].length; + + return binarySearch(0, rows - 1); + + function getMaxIndexInRow(row, left, right) { + let maxIndex = left; + for (let i = left; i <= right; i++) { + if (mat[row][i] > mat[row][maxIndex]) { + maxIndex = i; + } + } + return maxIndex; + } + + function binarySearch(startRow, endRow) { + if (startRow > endRow) return null; + + const midRow = Math.floor((startRow + endRow) / 2); + const maxCol = getMaxIndexInRow(midRow, 0, cols - 1); + const maxValue = mat[midRow][maxCol]; + + const topValue = midRow > 0 ? mat[midRow - 1][maxCol] : -1; + const bottomValue = midRow < rows - 1 ? mat[midRow + 1][maxCol] : -1; + const leftValue = maxCol > 0 ? mat[midRow][maxCol - 1] : -1; + const rightValue = maxCol < cols - 1 ? mat[midRow][maxCol + 1] : -1; + + if (maxValue > topValue && maxValue > bottomValue + && maxValue > leftValue && maxValue > rightValue) { + return [midRow, maxCol]; + } + + if (midRow > 0 && topValue > maxValue) { + return binarySearch(startRow, midRow - 1); + } + + return binarySearch(midRow + 1, endRow); + } +}; 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/1903-largest-odd-number-in-string.js b/solutions/1903-largest-odd-number-in-string.js new file mode 100644 index 00000000..9914883e --- /dev/null +++ b/solutions/1903-largest-odd-number-in-string.js @@ -0,0 +1,24 @@ +/** + * 1903. Largest Odd Number in String + * https://leetcode.com/problems/largest-odd-number-in-string/ + * Difficulty: Easy + * + * You are given a string num, representing a large integer. Return the largest-valued odd + * integer (as a string) that is a non-empty substring of num, or an empty string "" if no + * odd integer exists. + * + * A substring is a contiguous sequence of characters within a string. + */ + +/** + * @param {string} num + * @return {string} + */ +var largestOddNumber = function(num) { + for (let i = num.length - 1; i >= 0; i--) { + if (parseInt(num[i]) % 2 === 1) { + return num.slice(0, i + 1); + } + } + return ''; +}; diff --git a/solutions/1904-the-number-of-full-rounds-you-have-played.js b/solutions/1904-the-number-of-full-rounds-you-have-played.js new file mode 100644 index 00000000..4c7ad2d6 --- /dev/null +++ b/solutions/1904-the-number-of-full-rounds-you-have-played.js @@ -0,0 +1,47 @@ +/** + * 1904. The Number of Full Rounds You Have Played + * https://leetcode.com/problems/the-number-of-full-rounds-you-have-played/ + * Difficulty: Medium + * + * You are participating in an online chess tournament. There is a chess round that starts + * every 15 minutes. The first round of the day starts at 00:00, and after every 15 minutes, + * a new round starts. + * - For example, the second round starts at 00:15, the fourth round starts at 00:45, and the + * seventh round starts at 01:30. + * + * You are given two strings loginTime and logoutTime where: + * - loginTime is the time you will login to the game, and + * - logoutTime is the time you will logout from the game. + * + * If logoutTime is earlier than loginTime, this means you have played from loginTime to midnight + * and from midnight to logoutTime. + * + * Return the number of full chess rounds you have played in the tournament. + * + * Note: All the given times follow the 24-hour clock. That means the first round of the day starts + * at 00:00 and the last round of the day starts at 23:45. + */ + +/** + * @param {string} loginTime + * @param {string} logoutTime + * @return {number} + */ +var numberOfRounds = function(loginTime, logoutTime) { + let start = toMinutes(loginTime); + let end = toMinutes(logoutTime); + + if (end < start) { + end += 24 * 60; + } + + start = Math.ceil(start / 15); + end = Math.floor(end / 15); + + return Math.max(0, end - start); + + function toMinutes(time) { + const [hours, minutes] = time.split(':').map(Number); + return hours * 60 + minutes; + } +}; diff --git a/solutions/1905-count-sub-islands.js b/solutions/1905-count-sub-islands.js new file mode 100644 index 00000000..d6cf98c8 --- /dev/null +++ b/solutions/1905-count-sub-islands.js @@ -0,0 +1,51 @@ +/** + * 1905. Count Sub Islands + * https://leetcode.com/problems/count-sub-islands/ + * Difficulty: Medium + * + * You are given two m x n binary matrices grid1 and grid2 containing only 0's (representing water) + * and 1's (representing land). An island is a group of 1's connected 4-directionally (horizontal + * or vertical). Any cells outside of the grid are considered water cells. + * + * An island in grid2 is considered a sub-island if there is an island in grid1 that contains all + * the cells that make up this island in grid2. + * + * Return the number of islands in grid2 that are considered sub-islands. + */ + +/** + * @param {number[][]} grid1 + * @param {number[][]} grid2 + * @return {number} + */ +var countSubIslands = function(grid1, grid2) { + const rows = grid1.length; + const cols = grid1[0].length; + let result = 0; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (grid2[i][j] === 1 && isValidSubIsland(i, j)) { + result++; + } + } + } + + return result; + + function isValidSubIsland(row, col) { + if (row < 0 || row >= rows || col < 0 || col >= cols || grid2[row][col] === 0) { + return true; + } + + grid2[row][col] = 0; + let isSubIsland = grid1[row][col] === 1; + + isSubIsland &= isValidSubIsland(row - 1, col); + isSubIsland &= isValidSubIsland(row + 1, col); + isSubIsland &= isValidSubIsland(row, col - 1); + isSubIsland &= isValidSubIsland(row, col + 1); + + return isSubIsland; + } +}; diff --git a/solutions/1906-minimum-absolute-difference-queries.js b/solutions/1906-minimum-absolute-difference-queries.js new file mode 100644 index 00000000..62cfc15f --- /dev/null +++ b/solutions/1906-minimum-absolute-difference-queries.js @@ -0,0 +1,57 @@ +/** + * 1906. Minimum Absolute Difference Queries + * https://leetcode.com/problems/minimum-absolute-difference-queries/ + * Difficulty: Medium + * + * The minimum absolute difference of an array a is defined as the minimum value of |a[i] - a[j]|, + * where 0 <= i < j < a.length and a[i] != a[j]. If all elements of a are the same, the minimum + * absolute difference is -1. + * - For example, the minimum absolute difference of the array [5,2,3,7,2] is |2 - 3| = 1. Note + * that it is not 0 because a[i] and a[j] must be different. + * + * You are given an integer array nums and the array queries where queries[i] = [li, ri]. For each + * query i, compute the minimum absolute difference of the subarray nums[li...ri] containing the + * elements of nums between the 0-based indices li and ri (inclusive). + * + * Return an array ans where ans[i] is the answer to the ith query. + * + * A subarray is a contiguous sequence of elements in an array. + * + * The value of |x| is defined as: + * - x if x >= 0. + * - -x if x < 0. + */ + +/** + * @param {number[]} nums + * @param {number[][]} queries + * @return {number[]} + */ +var minDifference = function(nums, queries) { + const maxValue = 100; + const prefixCounts = new Array(nums.length + 1).fill().map(() => new Array(maxValue + 1).fill(0)); + + for (let i = 0; i < nums.length; i++) { + for (let j = 1; j <= maxValue; j++) { + prefixCounts[i + 1][j] = prefixCounts[i][j] + (nums[i] === j ? 1 : 0); + } + } + + return queries.map(([start, end]) => getMinDiff(start, end)); + + function getMinDiff(start, end) { + let minDiff = Infinity; + let prevValue = -1; + + for (let j = 1; j <= maxValue; j++) { + if (prefixCounts[end + 1][j] - prefixCounts[start][j] > 0) { + if (prevValue !== -1) { + minDiff = Math.min(minDiff, j - prevValue); + } + prevValue = j; + } + } + + return minDiff === Infinity ? -1 : minDiff; + } +}; 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/1909-remove-one-element-to-make-the-array-strictly-increasing.js b/solutions/1909-remove-one-element-to-make-the-array-strictly-increasing.js new file mode 100644 index 00000000..3e47a059 --- /dev/null +++ b/solutions/1909-remove-one-element-to-make-the-array-strictly-increasing.js @@ -0,0 +1,33 @@ +/** + * 1909. Remove One Element to Make the Array Strictly Increasing + * https://leetcode.com/problems/remove-one-element-to-make-the-array-strictly-increasing/ + * Difficulty: Easy + * + * Given a 0-indexed integer array nums, return true if it can be made strictly increasing after + * removing exactly one element, or false otherwise. If the array is already strictly increasing, + * return true. + * + * The array nums is strictly increasing if nums[i - 1] < nums[i] for each index + * (1 <= i < nums.length). + */ + +/** + * @param {number[]} nums + * @return {boolean} + */ +var canBeIncreasing = function(nums) { + for (let i = 0; i < nums.length; i++) { + if (isStrictlyIncreasing(nums, i)) return true; + } + + return false; + + function isStrictlyIncreasing(arr, skipIndex) { + for (let i = 1; i < arr.length; i++) { + if (i === skipIndex) continue; + const prev = i - 1 === skipIndex ? i - 2 : i - 1; + if (prev >= 0 && arr[i] <= arr[prev]) return false; + } + return true; + } +}; diff --git a/solutions/1911-maximum-alternating-subsequence-sum.js b/solutions/1911-maximum-alternating-subsequence-sum.js new file mode 100644 index 00000000..cd33635e --- /dev/null +++ b/solutions/1911-maximum-alternating-subsequence-sum.js @@ -0,0 +1,34 @@ +/** + * 1911. Maximum Alternating Subsequence Sum + * https://leetcode.com/problems/maximum-alternating-subsequence-sum/ + * Difficulty: Medium + * + * The alternating sum of a 0-indexed array is defined as the sum of the elements at even + * indices minus the sum of the elements at odd indices. + * - For example, the alternating sum of [4,2,5,3] is (4 + 5) - (2 + 3) = 4. + * + * Given an array nums, return the maximum alternating sum of any subsequence of nums (after + * reindexing the elements of the subsequence). + * + * A subsequence of an array is a new array generated from the original array by deleting some + * elements (possibly none) without changing the remaining elements' relative order. For + * example, [2,7,4] is a subsequence of [4,2,3,7,2,1,4] (the underlined elements), + * while [2,4,2] is not. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxAlternatingSum = function(nums) { + let result = 0; + let oddSum = 0; + + for (const num of nums) { + const prevEven = result; + result = Math.max(result, oddSum + num); + oddSum = Math.max(oddSum, prevEven - num); + } + + return result; +}; diff --git a/solutions/1912-design-movie-rental-system.js b/solutions/1912-design-movie-rental-system.js new file mode 100644 index 00000000..8f07b991 --- /dev/null +++ b/solutions/1912-design-movie-rental-system.js @@ -0,0 +1,147 @@ +/** + * 1912. Design Movie Rental System + * https://leetcode.com/problems/design-movie-rental-system/ + * Difficulty: Hard + * + * You have a movie renting company consisting of n shops. You want to implement a renting system + * that supports searching for, booking, and returning movies. The system should also support + * generating a report of the currently rented movies. + * + * Each movie is given as a 2D integer array entries where entries[i] = [shopi, moviei, pricei] + * indicates that there is a copy of movie moviei at shop shopi with a rental price of pricei. + * Each shop carries at most one copy of a movie moviei. + * + * The system should support the following functions: + * - Search: Finds the cheapest 5 shops that have an unrented copy of a given movie. The shops + * should be sorted by price in ascending order, and in case of a tie, the one with the smaller + * shopi should appear first. If there are less than 5 matching shops, then all of them should be + * returned. If no shop has an unrented copy, then an empty list should be returned. + * - Rent: Rents an unrented copy of a given movie from a given shop. + * - Drop: Drops off a previously rented copy of a given movie at a given shop. + * - Report: Returns the cheapest 5 rented movies (possibly of the same movie ID) as a 2D list res + * where res[j] = [shopj, moviej] describes that the jth cheapest rented movie moviej was rented + * from the shop shopj. The movies in res should be sorted by price in ascending order, and in + * case of a tie, the one with the smaller shopj should appear first, and if there is still tie, + * the one with the smaller moviej should appear first. If there are fewer than 5 rented movies, + * then all of them should be returned. If no movies are currently being rented, then an empty + * list should be returned. + * + * Implement the MovieRentingSystem class: + * - MovieRentingSystem(int n, int[][] entries) Initializes the MovieRentingSystem object with n + * shops and the movies in entries. + * - List search(int movie) Returns a list of shops that have an unrented copy of the + * given movie as described above. + * - void rent(int shop, int movie) Rents the given movie from the given shop. + * - void drop(int shop, int movie) Drops off a previously rented movie at the given shop. + * - List> report() Returns a list of cheapest rented movies as described above. + * + * Note: The test cases will be generated such that rent will only be called if the shop has an + * unrented copy of the movie, and drop will only be called if the shop had previously rented out + * the movie. + */ + +/** + * @param {number} n + * @param {number[][]} entries + */ +var MovieRentingSystem = function(n, entries) { + this.shopMovies = new Map(); + this.movieShops = new Map(); + this.rented = new PriorityQueue((a, b) => { + if (a[2] !== b[2]) return a[2] - b[2]; + if (a[0] !== b[0]) return a[0] - b[0]; + return a[1] - b[1]; + }); + this.rentedLookup = new Map(); + + for (const [shop, movie, price] of entries) { + if (!this.shopMovies.has(shop)) { + this.shopMovies.set(shop, new Map()); + } + this.shopMovies.get(shop).set(movie, price); + + if (!this.movieShops.has(movie)) { + this.movieShops.set(movie, new PriorityQueue((a, b) => { + if (a[1] !== b[1]) return a[1] - b[1]; + return a[0] - b[0]; + })); + } + this.movieShops.get(movie).enqueue([shop, price]); + } +}; + +/** + * @param {number} movie + * @return {number[]} + */ +MovieRentingSystem.prototype.search = function(movie) { + if (!this.movieShops.has(movie)) return []; + + const queue = this.movieShops.get(movie); + const result = []; + const seen = new Set(); + + while (!queue.isEmpty() && result.length < 5) { + const [shop, price] = queue.dequeue(); + if (this.shopMovies.get(shop)?.has(movie) && !seen.has(shop)) { + result.push(shop); + seen.add(shop); + } + } + + for (const shop of result) { + queue.enqueue([shop, this.shopMovies.get(shop).get(movie)]); + } + + return result; +}; + +/** + * @param {number} shop + * @param {number} movie + * @return {void} + */ +MovieRentingSystem.prototype.rent = function(shop, movie) { + const price = this.shopMovies.get(shop).get(movie); + this.shopMovies.get(shop).delete(movie); + this.rented.enqueue([shop, movie, price]); + this.rentedLookup.set(`${shop}:${movie}`, price); +}; + +/** + * @param {number} shop + * @param {number} movie + * @return {void} + */ +MovieRentingSystem.prototype.drop = function(shop, movie) { + const price = this.rentedLookup.get(`${shop}:${movie}`); + this.rentedLookup.delete(`${shop}:${movie}`); + if (!this.shopMovies.get(shop).has(movie)) { + this.shopMovies.get(shop).set(movie, price); + this.movieShops.get(movie).enqueue([shop, price]); + } +}; + +/** + * @return {number[][]} + */ +MovieRentingSystem.prototype.report = function() { + const result = []; + const seen = new Set(); + + while (!this.rented.isEmpty() && result.length < 5) { + const [shop, movie, price] = this.rented.dequeue(); + const key = `${shop}:${movie}`; + if (this.rentedLookup.has(key) && !seen.has(key)) { + result.push([shop, movie]); + seen.add(key); + } + } + + for (const [shop, movie] of result) { + const price = this.rentedLookup.get(`${shop}:${movie}`); + this.rented.enqueue([shop, movie, price]); + } + + return result; +}; diff --git a/solutions/1913-maximum-product-difference-between-two-pairs.js b/solutions/1913-maximum-product-difference-between-two-pairs.js new file mode 100644 index 00000000..91e73220 --- /dev/null +++ b/solutions/1913-maximum-product-difference-between-two-pairs.js @@ -0,0 +1,42 @@ +/** + * 1913. Maximum Product Difference Between Two Pairs + * https://leetcode.com/problems/maximum-product-difference-between-two-pairs/ + * Difficulty: Easy + * + * The product difference between two pairs (a, b) and (c, d) is defined as (a * b) - (c * d). + * - For example, the product difference between (5, 6) and (2, 7) is (5 * 6) - (2 * 7) = 16. + * + * Given an integer array nums, choose four distinct indices w, x, y, and z such that the product + * difference between pairs (nums[w], nums[x]) and (nums[y], nums[z]) is maximized. + * + * Return the maximum such product difference. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var maxProductDifference = function(nums) { + let max1 = 0; + let max2 = 0; + let min1 = Infinity; + let min2 = Infinity; + + for (const num of nums) { + if (num > max1) { + max2 = max1; + max1 = num; + } else if (num > max2) { + max2 = num; + } + + if (num < min1) { + min2 = min1; + min1 = num; + } else if (num < min2) { + min2 = num; + } + } + + return max1 * max2 - min1 * min2; +}; diff --git a/solutions/1914-cyclically-rotating-a-grid.js b/solutions/1914-cyclically-rotating-a-grid.js new file mode 100644 index 00000000..84724945 --- /dev/null +++ b/solutions/1914-cyclically-rotating-a-grid.js @@ -0,0 +1,66 @@ +/** + * 1914. Cyclically Rotating a Grid + * https://leetcode.com/problems/cyclically-rotating-a-grid/ + * Difficulty: Medium + * + * You are given an m x n integer matrix grid, where m and n are both even integers, and + * an integer k. + * + * The matrix is composed of several layers, which is shown in the below image, where each + * color is its own layer. + * + * A cyclic rotation of the matrix is done by cyclically rotating each layer in the matrix. + * To cyclically rotate a layer once, each element in the layer will take the place of the + * adjacent element in the counter-clockwise direction. An example rotation is shown below. + */ + +/** + * @param {number[][]} grid + * @param {number} k + * @return {number[][]} + */ +var rotateGrid = function(grid, k) { + const rows = grid.length; + const cols = grid[0].length; + const result = grid.map(row => [...row]); + + for (let layer = 0; layer < Math.min(rows, cols) / 2; layer++) { + rotateLayer(layer, layer, rows - 1 - layer, cols - 1 - layer, k); + } + + return result; + + function rotateLayer(top, left, bottom, right, rotations) { + if (top >= bottom || left >= right) return; + + const perimeter = 2 * (bottom - top + right - left); + const effectiveRotations = rotations % perimeter; + if (effectiveRotations === 0) return; + + const elements = []; + for (let i = top; i <= bottom; i++) elements.push(grid[i][left]); + for (let j = left + 1; j <= right; j++) elements.push(grid[bottom][j]); + for (let i = bottom - 1; i >= top; i--) elements.push(grid[i][right]); + for (let j = right - 1; j > left; j--) elements.push(grid[top][j]); + + const offset = (perimeter - effectiveRotations) % perimeter; + let index = offset; + + for (let i = top; i <= bottom; i++) { + result[i][left] = elements[index % perimeter]; + index++; + } + for (let j = left + 1; j <= right; j++) { + result[bottom][j] = elements[index % perimeter]; + index++; + } + for (let i = bottom - 1; i >= top; i--) { + result[i][right] = elements[index % perimeter]; + index++; + } + for (let j = right - 1; j > left; j--) { + result[top][j] = elements[index % perimeter]; + index++; + } + } +}; diff --git a/solutions/1915-number-of-wonderful-substrings.js b/solutions/1915-number-of-wonderful-substrings.js new file mode 100644 index 00000000..b9aaf680 --- /dev/null +++ b/solutions/1915-number-of-wonderful-substrings.js @@ -0,0 +1,39 @@ +/** + * 1915. Number of Wonderful Substrings + * https://leetcode.com/problems/number-of-wonderful-substrings/ + * Difficulty: Medium + * + * A wonderful string is a string where at most one letter appears an odd number of times. + * - For example, "ccjjc" and "abab" are wonderful, but "ab" is not. + * + * Given a string word that consists of the first ten lowercase English letters ('a' through + * 'j'), return the number of wonderful non-empty substrings in word. If the same substring + * appears multiple times in word, then count each occurrence separately. + * + * A substring is a contiguous sequence of characters in a string. + */ + +/** + * @param {string} word + * @return {number} + */ +var wonderfulSubstrings = function(word) { + let count = 0; + const freq = new Map([[0, 1]]); + let state = 0; + + for (const char of word) { + const bit = 1 << (char.charCodeAt(0) - 97); + state ^= bit; + + count += freq.get(state) || 0; + freq.set(state, (freq.get(state) || 0) + 1); + + for (let i = 0; i < 10; i++) { + const oddBit = state ^ (1 << i); + count += freq.get(oddBit) || 0; + } + } + + return count; +}; diff --git a/solutions/1916-count-ways-to-build-rooms-in-an-ant-colony.js b/solutions/1916-count-ways-to-build-rooms-in-an-ant-colony.js new file mode 100644 index 00000000..93f715af --- /dev/null +++ b/solutions/1916-count-ways-to-build-rooms-in-an-ant-colony.js @@ -0,0 +1,71 @@ +/** + * 1916. Count Ways to Build Rooms in an Ant Colony + * https://leetcode.com/problems/count-ways-to-build-rooms-in-an-ant-colony/ + * Difficulty: Hard + * + * You are an ant tasked with adding n new rooms numbered 0 to n-1 to your colony. You are given + * the expansion plan as a 0-indexed integer array of length n, prevRoom, where prevRoom[i] + * indicates that you must build room prevRoom[i] before building room i, and these two rooms + * must be connected directly. Room 0 is already built, so prevRoom[0] = -1. The expansion plan + * is given such that once all the rooms are built, every room will be reachable from room 0. + * + * You can only build one room at a time, and you can travel freely between rooms you have + * already built only if they are connected. You can choose to build any room as long as its + * previous room is already built. + * + * Return the number of different orders you can build all the rooms in. Since the answer may + * be large, return it modulo 109 + 7. + */ + +/** + * @param {number[]} prevRoom + * @return {number} + */ +var waysToBuildRooms = function(prevRoom) { + const n = prevRoom.length; + const mod = 1e9 + 7; + const graph = Array(n).fill().map(() => []); + const factorial = Array(n + 1).fill(1n); + const invFactorial = Array(n + 1).fill(1n); + + for (let i = 1; i <= n; i++) { + factorial[i] = (factorial[i - 1] * BigInt(i)) % BigInt(mod); + } + + for (let i = 1; i <= n; i++) { + invFactorial[i] = modInverse(factorial[i], BigInt(mod)); + } + + for (let i = 1; i < n; i++) { + graph[prevRoom[i]].push(i); + } + + return Number(countSubtreeSizes(0)[1]); + + function countSubtreeSizes(node) { + let size = 1; + let result = 1n; + + for (const child of graph[node]) { + const [childSize, childResult] = countSubtreeSizes(child); + size += childSize; + result = (result * childResult * invFactorial[childSize]) % BigInt(mod); + } + + return [size, (result * factorial[size - 1]) % BigInt(mod)]; + } + + function modInverse(a, m) { + const m0 = m; + let q; + let x0 = 0n; + let x1 = 1n; + + while (a > 1n) { + q = a / m; + [a, m] = [m, a % m]; + [x0, x1] = [x1 - q * x0, x0]; + } + return x1 < 0n ? x1 + m0 : x1; + } +}; 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/1921-eliminate-maximum-number-of-monsters.js b/solutions/1921-eliminate-maximum-number-of-monsters.js new file mode 100644 index 00000000..e9f43cd1 --- /dev/null +++ b/solutions/1921-eliminate-maximum-number-of-monsters.js @@ -0,0 +1,47 @@ +/** + * 1921. Eliminate Maximum Number of Monsters + * https://leetcode.com/problems/eliminate-maximum-number-of-monsters/ + * Difficulty: Medium + * + * You are playing a video game where you are defending your city from a group of n monsters. You + * are given a 0-indexed integer array dist of size n, where dist[i] is the initial distance in + * kilometers of the ith monster from the city. + * + * The monsters walk toward the city at a constant speed. The speed of each monster is given to + * you in an integer array speed of size n, where speed[i] is the speed of the ith monster in + * kilometers per minute. + * + * You have a weapon that, once fully charged, can eliminate a single monster. However, the weapon + * takes one minute to charge. The weapon is fully charged at the very start. + * + * You lose when any monster reaches your city. If a monster reaches the city at the exact moment + * the weapon is fully charged, it counts as a loss, and the game ends before you can use your + * weapon. + * + * Return the maximum number of monsters that you can eliminate before you lose, or n if you can + * eliminate all the monsters before they reach the city. + */ + +/** + * @param {number[]} dist + * @param {number[]} speed + * @return {number} + */ +var eliminateMaximum = function(dist, speed) { + const n = dist.length; + const arrivalTimes = new Array(n); + + for (let i = 0; i < n; i++) { + arrivalTimes[i] = dist[i] / speed[i]; + } + + arrivalTimes.sort((a, b) => a - b); + + for (let i = 0; i < n; i++) { + if (arrivalTimes[i] <= i) { + return i; + } + } + + return n; +}; diff --git a/solutions/1923-longest-common-subpath.js b/solutions/1923-longest-common-subpath.js new file mode 100644 index 00000000..1c2e1b0d --- /dev/null +++ b/solutions/1923-longest-common-subpath.js @@ -0,0 +1,148 @@ +/** + * 1923. Longest Common Subpath + * https://leetcode.com/problems/longest-common-subpath/ + * Difficulty: Hard + * + * There is a country of n cities numbered from 0 to n - 1. In this country, there is a road + * connecting every pair of cities. + * + * There are m friends numbered from 0 to m - 1 who are traveling through the country. Each one + * of them will take a path consisting of some cities. Each path is represented by an integer + * array that contains the visited cities in order. The path may contain a city more than once, + * but the same city will not be listed consecutively. + * + * Given an integer n and a 2D integer array paths where paths[i] is an integer array representing + * the path of the ith friend, return the length of the longest common subpath that is shared + * by every friend's path, or 0 if there is no common subpath at all. + * + * A subpath of a path is a contiguous sequence of cities within that path. + */ + +/** + * @param {number} n + * @param {number[][]} paths + * @return {number} + */ +var longestCommonSubpath = function(n, paths) { + if (paths.length === 0) return 0; + + paths.sort((a, b) => a.length - b.length); + + let left = 0; + let right = paths[0].length; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + + if (checkCommonSubpathExists(paths, mid)) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + return right; +}; + +function checkCommonSubpathExists(paths, length) { + if (length === 0) return true; + + const firstPath = paths[0]; + + if (firstPath.length < length) return false; + + const prime = 1000000007; + const base = 100003; + + let highestPower = 1; + for (let i = 0; i < length - 1; i++) { + highestPower = (highestPower * base) % prime; + } + + let hashToPositions = new Map(); + + let hash = 0; + for (let i = 0; i < length; i++) { + hash = (hash * base + firstPath[i]) % prime; + } + + if (!hashToPositions.has(hash)) { + hashToPositions.set(hash, []); + } + hashToPositions.get(hash).push(0); + + for (let i = 1; i <= firstPath.length - length; i++) { + hash = ((hash - firstPath[i - 1] * highestPower % prime + prime) + % prime * base + firstPath[i + length - 1]) % prime; + + if (!hashToPositions.has(hash)) { + hashToPositions.set(hash, []); + } + hashToPositions.get(hash).push(i); + } + + for (let pathIdx = 1; pathIdx < paths.length; pathIdx++) { + const path = paths[pathIdx]; + + if (path.length < length) return false; + + const newHashToPositions = new Map(); + hash = 0; + for (let i = 0; i < length; i++) { + hash = (hash * base + path[i]) % prime; + } + + if (hashToPositions.has(hash)) { + const positions = hashToPositions.get(hash); + for (const pos of positions) { + let isMatch = true; + for (let j = 0; j < length; j++) { + if (firstPath[pos + j] !== path[j]) { + isMatch = false; + break; + } + } + + if (isMatch) { + if (!newHashToPositions.has(hash)) { + newHashToPositions.set(hash, []); + } + newHashToPositions.get(hash).push(pos); + break; + } + } + } + + for (let i = 1; i <= path.length - length; i++) { + hash = ((hash - path[i - 1] * highestPower % prime + prime) + % prime * base + path[i + length - 1]) % prime; + + if (hashToPositions.has(hash)) { + const positions = hashToPositions.get(hash); + for (const pos of positions) { + let isMatch = true; + for (let j = 0; j < length; j++) { + if (firstPath[pos + j] !== path[i + j]) { + isMatch = false; + break; + } + } + + if (isMatch) { + if (!newHashToPositions.has(hash)) { + newHashToPositions.set(hash, []); + } + newHashToPositions.get(hash).push(pos); + break; + } + } + } + } + + if (newHashToPositions.size === 0) return false; + + hashToPositions = newHashToPositions; + } + + return hashToPositions.size > 0; +} 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/1925-count-square-sum-triples.js b/solutions/1925-count-square-sum-triples.js new file mode 100644 index 00000000..b917c4e1 --- /dev/null +++ b/solutions/1925-count-square-sum-triples.js @@ -0,0 +1,29 @@ +/** + * 1925. Count Square Sum Triples + * https://leetcode.com/problems/count-square-sum-triples/ + * Difficulty: Easy + * + * A square triple (a,b,c) is a triple where a, b, and c are integers and a2 + b2 = c2. + * + * Given an integer n, return the number of square triples such that 1 <= a, b, c <= n. + */ + +/** + * @param {number} n + * @return {number} + */ +var countTriples = function(n) { + let result = 0; + + for (let a = 1; a <= n; a++) { + for (let b = 1; b <= n; b++) { + const sum = a * a + b * b; + const c = Math.sqrt(sum); + if (c <= n && Number.isInteger(c)) { + result++; + } + } + } + + return result; +}; diff --git a/solutions/1927-sum-game.js b/solutions/1927-sum-game.js new file mode 100644 index 00000000..178435f2 --- /dev/null +++ b/solutions/1927-sum-game.js @@ -0,0 +1,56 @@ +/** + * 1927. Sum Game + * https://leetcode.com/problems/sum-game/ + * Difficulty: Medium + * + * Alice and Bob take turns playing a game, with Alice starting first. + * + * You are given a string num of even length consisting of digits and '?' characters. On each + * turn, a player will do the following if there is still at least one '?' in num: + * 1. Choose an index i where num[i] == '?'. + * 2. Replace num[i] with any digit between '0' and '9'. + * + * The game ends when there are no more '?' characters in num. + * + * For Bob to win, the sum of the digits in the first half of num must be equal to the sum of + * the digits in the second half. For Alice to win, the sums must not be equal. + * - For example, if the game ended with num = "243801", then Bob wins because 2+4+3 = 8+0+1. + * If the game ended with num = "243803", then Alice wins because 2+4+3 != 8+0+3. + * + * Assuming Alice and Bob play optimally, return true if Alice will win and false if Bob will win. + */ + +/** + * @param {string} num + * @return {boolean} + */ +var sumGame = function(num) { + const n = num.length; + const half = n / 2; + + let leftSum = 0; + let rightSum = 0; + let leftQuestionMarks = 0; + let rightQuestionMarks = 0; + + for (let i = 0; i < n; i++) { + if (i < half) { + if (num[i] === '?') { + leftQuestionMarks++; + } else { + leftSum += parseInt(num[i]); + } + } else { + if (num[i] === '?') { + rightQuestionMarks++; + } else { + rightSum += parseInt(num[i]); + } + } + } + + const sumDiff = leftSum - rightSum; + const diff = leftQuestionMarks - rightQuestionMarks; + + return (diff % 2 !== 0) || (sumDiff + diff * 4.5 !== 0); +}; diff --git a/solutions/1928-minimum-cost-to-reach-destination-in-time.js b/solutions/1928-minimum-cost-to-reach-destination-in-time.js new file mode 100644 index 00000000..a601d545 --- /dev/null +++ b/solutions/1928-minimum-cost-to-reach-destination-in-time.js @@ -0,0 +1,66 @@ +/** + * 1928. Minimum Cost to Reach Destination in Time + * https://leetcode.com/problems/minimum-cost-to-reach-destination-in-time/ + * Difficulty: Hard + * + * There is a country of n cities numbered from 0 to n - 1 where all the cities are connected by + * bi-directional roads. The roads are represented as a 2D integer array edges where + * edges[i] = [xi, yi, timei] denotes a road between cities xi and yi that takes timei minutes + * to travel. There may be multiple roads of differing travel times connecting the same two + * cities, but no road connects a city to itself. + * + * Each time you pass through a city, you must pay a passing fee. This is represented as a + * 0-indexed integer array passingFees of length n where passingFees[j] is the amount of dollars + * you must pay when you pass through city j. + * + * In the beginning, you are at city 0 and want to reach city n - 1 in maxTime minutes or less. + * The cost of your journey is the summation of passing fees for each city that you passed + * through at some moment of your journey (including the source and destination cities). + * + * Given maxTime, edges, and passingFees, return the minimum cost to complete your journey, + * or -1 if you cannot complete it within maxTime minutes. + */ + +/** + * @param {number} maxTime + * @param {number[][]} edges + * @param {number[]} passingFees + * @return {number} + */ +var minCost = function(maxTime, edges, passingFees) { + const n = passingFees.length; + const dp = new Array(n).fill().map(() => new Array(maxTime + 1).fill(Infinity)); + dp[0][0] = passingFees[0]; + + const graph = new Array(n).fill().map(() => []); + for (const [u, v, time] of edges) { + graph[u].push([v, time]); + graph[v].push([u, time]); + } + + const pq = new PriorityQueue((a, b) => a.cost - b.cost); + pq.enqueue({ cost: passingFees[0], city: 0, time: 0 }); + + while (!pq.isEmpty()) { + const { cost, city, time } = pq.dequeue(); + if (cost > dp[city][time]) continue; + + for (const [nextCity, travelTime] of graph[city]) { + const newTime = time + travelTime; + if (newTime > maxTime) continue; + + const newCost = cost + passingFees[nextCity]; + if (newCost < dp[nextCity][newTime]) { + dp[nextCity][newTime] = newCost; + pq.enqueue({ cost: newCost, city: nextCity, time: newTime }); + } + } + } + + let minCost = Infinity; + for (let t = 0; t <= maxTime; t++) { + minCost = Math.min(minCost, dp[n - 1][t]); + } + + return minCost === Infinity ? -1 : minCost; +}; diff --git a/solutions/1931-painting-a-grid-with-three-different-colors.js b/solutions/1931-painting-a-grid-with-three-different-colors.js new file mode 100644 index 00000000..ef8bf15b --- /dev/null +++ b/solutions/1931-painting-a-grid-with-three-different-colors.js @@ -0,0 +1,72 @@ +/** + * 1931. Painting a Grid With Three Different Colors + * https://leetcode.com/problems/painting-a-grid-with-three-different-colors/ + * Difficulty: Hard + * + * You are given two integers m and n. Consider an m x n grid where each cell is initially white. + * You can paint each cell red, green, or blue. All cells must be painted. + * + * Return the number of ways to color the grid with no two adjacent cells having the same color. + * Since the answer can be very large, return it modulo 109 + 7. + */ + +/** + * @param {number} m + * @param {number} n + * @return {number} + */ +var colorTheGrid = function(m, n) { + const MOD = 1e9 + 7; + const colors = 3; + const validStates = generateValidStates(m, colors); + const stateCount = validStates.length; + let dp = new Array(stateCount).fill(1); + + for (let col = 1; col < n; col++) { + const nextDp = new Array(stateCount).fill(0); + for (let i = 0; i < stateCount; i++) { + for (let j = 0; j < stateCount; j++) { + if (isCompatible(validStates[i], validStates[j])) { + nextDp[j] = (nextDp[j] + dp[i]) % MOD; + } + } + } + dp = nextDp; + } + + let totalWays = 0; + for (const count of dp) { + totalWays = (totalWays + count) % MOD; + } + + return totalWays; + + function generateValidStates(rows, colors) { + const states = []; + generateStates([], rows, colors, states); + return states; + } + + function generateStates(current, rows, colors, states) { + if (current.length === rows) { + states.push([...current]); + return; + } + for (let c = 0; c < colors; c++) { + if (current.length === 0 || current[current.length - 1] !== c) { + current.push(c); + generateStates(current, rows, colors, states); + current.pop(); + } + } + } + + function isCompatible(prevState, currState) { + for (let i = 0; i < prevState.length; i++) { + if (prevState[i] === currState[i]) { + return false; + } + } + return true; + } +}; diff --git a/solutions/1932-merge-bsts-to-create-single-bst.js b/solutions/1932-merge-bsts-to-create-single-bst.js new file mode 100644 index 00000000..a118a41a --- /dev/null +++ b/solutions/1932-merge-bsts-to-create-single-bst.js @@ -0,0 +1,86 @@ +/** + * 1932. Merge BSTs to Create Single BST + * https://leetcode.com/problems/merge-bsts-to-create-single-bst/ + * Difficulty: Hard + * + * You are given n BST (binary search tree) root nodes for n separate BSTs stored in an array + * trees (0-indexed). Each BST in trees has at most 3 nodes, and no two roots have the same + * value. In one operation, you can: + * - Select two distinct indices i and j such that the value stored at one of the leaves of + * trees[i] is equal to the root value of trees[j]. + * - Replace the leaf node in trees[i] with trees[j]. + * - Remove trees[j] from trees. + * + * Return the root of the resulting BST if it is possible to form a valid BST after + * performing n - 1 operations, or null if it is impossible to create a valid BST. + * + * A BST (binary search tree) is a binary tree where each node satisfies the following property: + * - Every node in the node's left subtree has a value strictly less than the node's value. + * - Every node in the node's right subtree has a value strictly greater than the node's value. + * + * A leaf is a node that 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[]} trees + * @return {TreeNode} + */ +var canMerge = function(trees) { + const valueToTree = new Map(); + const leafValues = new Set(); + const inDegree = new Map(); + + for (const tree of trees) { + valueToTree.set(tree.val, tree); + if (tree.left) leafValues.add(tree.left.val); + if (tree.right) leafValues.add(tree.right.val); + } + + let root = null; + for (const tree of trees) { + if (!leafValues.has(tree.val)) { + if (root) return null; + root = tree; + } + if (tree.left) inDegree.set(tree.left.val, (inDegree.get(tree.left.val) || 0) + 1); + if (tree.right) inDegree.set(tree.right.val, (inDegree.get(tree.right.val) || 0) + 1); + } + + if (!root) return null; + + const merged = mergeTrees(root, valueToTree, inDegree); + if (!merged || valueToTree.size > 1 || !isValidBST(merged, -Infinity, Infinity)) { + return null; + } + + return merged; + + function mergeTrees(node, valueToTree, inDegree) { + if (!node) return node; + + if (!node.left && !node.right && valueToTree.has(node.val) && inDegree.get(node.val) === 1) { + const tree = valueToTree.get(node.val); + if (tree === node) return node; + valueToTree.delete(node.val); + return mergeTrees(tree, valueToTree, inDegree); + } + + node.left = mergeTrees(node.left, valueToTree, inDegree); + node.right = mergeTrees(node.right, valueToTree, inDegree); + return node; + } + + function isValidBST(node, min, max) { + if (!node) return true; + if (node.val <= min || node.val >= max) return false; + return isValidBST(node.left, min, node.val) && isValidBST(node.right, node.val, max); + } +}; 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/1936-add-minimum-number-of-rungs.js b/solutions/1936-add-minimum-number-of-rungs.js new file mode 100644 index 00000000..2dba6511 --- /dev/null +++ b/solutions/1936-add-minimum-number-of-rungs.js @@ -0,0 +1,36 @@ +/** + * 1936. Add Minimum Number of Rungs + * https://leetcode.com/problems/add-minimum-number-of-rungs/ + * Difficulty: Medium + * + * You are given a strictly increasing integer array rungs that represents the height of rungs + * on a ladder. You are currently on the floor at height 0, and you want to reach the last rung. + * + * You are also given an integer dist. You can only climb to the next highest rung if the + * distance between where you are currently at (the floor or on a rung) and the next rung is + * at most dist. You are able to insert rungs at any positive integer height if a rung is not + * already there. + * + * Return the minimum number of rungs that must be added to the ladder in order for you to climb + * to the last rung. + */ + +/** + * @param {number[]} rungs + * @param {number} dist + * @return {number} + */ +var addRungs = function(rungs, dist) { + let currentHeight = 0; + let result = 0; + + for (const rung of rungs) { + const gap = rung - currentHeight; + if (gap > dist) { + result += Math.ceil(gap / dist) - 1; + } + currentHeight = rung; + } + + return result; +}; diff --git a/solutions/1937-maximum-number-of-points-with-cost.js b/solutions/1937-maximum-number-of-points-with-cost.js new file mode 100644 index 00000000..288c1888 --- /dev/null +++ b/solutions/1937-maximum-number-of-points-with-cost.js @@ -0,0 +1,55 @@ +/** + * 1937. Maximum Number of Points with Cost + * https://leetcode.com/problems/maximum-number-of-points-with-cost/ + * Difficulty: Medium + * + * You are given an m x n integer matrix points (0-indexed). Starting with 0 points, you want + * to maximize the number of points you can get from the matrix. + * + * To gain points, you must pick one cell in each row. Picking the cell at coordinates (r, c) + * will add points[r][c] to your score. + * + * However, you will lose points if you pick a cell too far from the cell that you picked in + * the previous row. For every two adjacent rows r and r + 1 (where 0 <= r < m - 1), picking + * cells at coordinates (r, c1) and (r + 1, c2) will subtract abs(c1 - c2) from your score. + * + * Return the maximum number of points you can achieve. + * + * abs(x) is defined as: + * - x for x >= 0. + * - -x for x < 0. + */ + +/** + * @param {number[][]} points + * @return {number} + */ +var maxPoints = function(points) { + const rows = points.length; + const cols = points[0].length; + let prevRow = points[0].slice(); + + for (let r = 1; r < rows; r++) { + const currRow = new Array(cols).fill(0); + const leftMax = new Array(cols).fill(0); + const rightMax = new Array(cols).fill(0); + + leftMax[0] = prevRow[0]; + for (let c = 1; c < cols; c++) { + leftMax[c] = Math.max(leftMax[c - 1] - 1, prevRow[c]); + } + + rightMax[cols - 1] = prevRow[cols - 1]; + for (let c = cols - 2; c >= 0; c--) { + rightMax[c] = Math.max(rightMax[c + 1] - 1, prevRow[c]); + } + + for (let c = 0; c < cols; c++) { + currRow[c] = points[r][c] + Math.max(leftMax[c], rightMax[c]); + } + + prevRow = currRow; + } + + return Math.max(...prevRow); +}; diff --git a/solutions/1938-maximum-genetic-difference-query.js b/solutions/1938-maximum-genetic-difference-query.js new file mode 100644 index 00000000..e7b88f18 --- /dev/null +++ b/solutions/1938-maximum-genetic-difference-query.js @@ -0,0 +1,97 @@ +/** + * 1938. Maximum Genetic Difference Query + * https://leetcode.com/problems/maximum-genetic-difference-query/ + * Difficulty: Hard + * + * There is a rooted tree consisting of n nodes numbered 0 to n - 1. Each node's number denotes + * its unique genetic value (i.e. the genetic value of node x is x). The genetic difference + * between two genetic values is defined as the bitwise-XOR of their values. You are given + * the integer array parents, where parents[i] is the parent for node i. If node x is the root + * of the tree, then parents[x] == -1. + * + * You are also given the array queries where queries[i] = [nodei, vali]. For each query i, + * find the maximum genetic difference between vali and pi, where pi is the genetic value of + * any node that is on the path between nodei and the root (including nodei and the root). + * More formally, you want to maximize vali XOR pi. + * + * Return an array ans where ans[i] is the answer to the ith query. + */ + +/** + * @param {number[]} parents + * @param {number[][]} queries + * @return {number[]} + */ +var maxGeneticDifference = function(parents, queries) { + const n = parents.length; + const graph = Array(n).fill().map(() => []); + let root = -1; + + for (let i = 0; i < n; i++) { + if (parents[i] === -1) { + root = i; + } else { + graph[parents[i]].push(i); + } + } + + const trie = { count: 0, children: {} }; + const queryMap = Array(n).fill().map(() => []); + const result = new Array(queries.length).fill(0); + + for (let i = 0; i < queries.length; i++) { + queryMap[queries[i][0]].push([queries[i][1], i]); + } + + dfs(root); + return result; + + function insertTrie(val) { + let node = trie; + for (let bit = 17; bit >= 0; bit--) { + const b = (val >> bit) & 1; + if (!node.children[b]) { + node.children[b] = { count: 0, children: {} }; + } + node = node.children[b]; + node.count++; + } + } + + function removeTrie(val) { + let node = trie; + for (let bit = 17; bit >= 0; bit--) { + const b = (val >> bit) & 1; + node = node.children[b]; + node.count--; + } + } + + function queryTrie(val) { + let node = trie; + let maxXor = 0; + for (let bit = 17; bit >= 0; bit--) { + const b = (val >> bit) & 1; + if (node.children[1 - b]?.count > 0) { + maxXor |= (1 << bit); + node = node.children[1 - b]; + } else if (node.children[b]?.count > 0) { + node = node.children[b]; + } else { + return maxXor; + } + } + return maxXor; + } + + function dfs(node) { + insertTrie(node); + for (const [val, idx] of queryMap[node]) { + result[idx] = queryTrie(val); + } + for (const child of graph[node]) { + dfs(child); + } + removeTrie(node); + } +}; 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/1941-check-if-all-characters-have-equal-number-of-occurrences.js b/solutions/1941-check-if-all-characters-have-equal-number-of-occurrences.js new file mode 100644 index 00000000..aa742eb2 --- /dev/null +++ b/solutions/1941-check-if-all-characters-have-equal-number-of-occurrences.js @@ -0,0 +1,24 @@ +/** + * 1941. Check if All Characters Have Equal Number of Occurrences + * https://leetcode.com/problems/check-if-all-characters-have-equal-number-of-occurrences/ + * Difficulty: Easy + * + * Given a string s, return true if s is a good string, or false otherwise. + * + * A string s is good if all the characters that appear in s have the same number of occurrences + * (i.e., the same frequency). + */ + +/** + * @param {string} s + * @return {boolean} + */ +var areOccurrencesEqual = function(s) { + const map = new Map(); + for (const char of s) { + map.set(char, (map.get(char) || 0) + 1); + } + + const frequencies = new Set(map.values()); + return frequencies.size === 1; +}; 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/1943-describe-the-painting.js b/solutions/1943-describe-the-painting.js new file mode 100644 index 00000000..3e5c287a --- /dev/null +++ b/solutions/1943-describe-the-painting.js @@ -0,0 +1,60 @@ +/** + * 1943. Describe the Painting + * https://leetcode.com/problems/describe-the-painting/ + * Difficulty: Medium + * + * There is a long and thin painting that can be represented by a number line. The painting was + * painted with multiple overlapping segments where each segment was painted with a unique color. + * You are given a 2D integer array segments, where segments[i] = [starti, endi, colori] + * represents the half-closed segment [starti, endi) with colori as the color. + * + * The colors in the overlapping segments of the painting were mixed when it was painted. When + * two or more colors mix, they form a new color that can be represented as a set of mixed colors. + * - For example, if colors 2, 4, and 6 are mixed, then the resulting mixed color is {2,4,6}. + * + * For the sake of simplicity, you should only output the sum of the elements in the set rather + * than the full set. + * + * You want to describe the painting with the minimum number of non-overlapping half-closed + * segments of these mixed colors. These segments can be represented by the 2D array painting + * where painting[j] = [leftj, rightj, mixj] describes a half-closed segment [leftj, rightj) + * with the mixed color sum of mixj. + * - For example, the painting created with segments = [[1,4,5],[1,7,7]] can be described by + * painting = [[1,4,12],[4,7,7]] because: + * - [1,4) is colored {5,7} (with a sum of 12) from both the first and second segments. + * - [4,7) is colored {7} from only the second segment. + * + * Return the 2D array painting describing the finished painting (excluding any parts that are + * not painted). You may return the segments in any order. + * + * 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[][]} segments + * @return {number[][]} + */ +var splitPainting = function(segments) { + const events = []; + for (const [start, end, color] of segments) { + events.push([start, color]); + events.push([end, -color]); + } + + events.sort((a, b) => a[0] - b[0] || a[1] - b[1]); + + const result = []; + let currentSum = 0; + let prevPoint = events[0][0]; + + for (const [point, color] of events) { + if (currentSum > 0 && point > prevPoint) { + result.push([prevPoint, point, currentSum]); + } + currentSum += color; + prevPoint = point; + } + + return result; +}; diff --git a/solutions/1944-number-of-visible-people-in-a-queue.js b/solutions/1944-number-of-visible-people-in-a-queue.js new file mode 100644 index 00000000..8297710b --- /dev/null +++ b/solutions/1944-number-of-visible-people-in-a-queue.js @@ -0,0 +1,39 @@ +/** + * 1944. Number of Visible People in a Queue + * https://leetcode.com/problems/number-of-visible-people-in-a-queue/ + * Difficulty: Hard + * + * There are n people standing in a queue, and they numbered from 0 to n - 1 in left to right + * order. You are given an array heights of distinct integers where heights[i] represents the + * height of the ith person. + * + * A person can see another person to their right in the queue if everybody in between is + * shorter than both of them. More formally, the ith person can see the jth person + * if i < j and min(heights[i], heights[j]) > max(heights[i+1], heights[i+2], ..., heights[j-1]). + * + * Return an array answer of length n where answer[i] is the number of people the ith person + * can see to their right in the queue. + */ + +/** + * @param {number[]} heights + * @return {number[]} + */ +var canSeePersonsCount = function(heights) { + const n = heights.length; + const result = new Array(n).fill(0); + const stack = []; + + for (let i = n - 1; i >= 0; i--) { + while (stack.length && heights[i] > stack[stack.length - 1]) { + stack.pop(); + result[i]++; + } + if (stack.length) { + result[i]++; + } + stack.push(heights[i]); + } + + return result; +}; diff --git a/solutions/1945-sum-of-digits-of-string-after-convert.js b/solutions/1945-sum-of-digits-of-string-after-convert.js new file mode 100644 index 00000000..7e6e47d1 --- /dev/null +++ b/solutions/1945-sum-of-digits-of-string-after-convert.js @@ -0,0 +1,44 @@ +/** + * 1945. Sum of Digits of String After Convert + * https://leetcode.com/problems/sum-of-digits-of-string-after-convert/ + * Difficulty: Easy + * + * You are given a string s consisting of lowercase English letters, and an integer k. Your task + * is to convert the string into an integer by a special process, and then transform it by + * summing its digits repeatedly k times. More specifically, perform the following steps: + * 1. Convert s into an integer by replacing each letter with its position in the alphabet (i.e. + * replace 'a' with 1, 'b' with 2, ..., 'z' with 26). + * 2. Transform the integer by replacing it with the sum of its digits. + * 3. Repeat the transform operation (step 2) k times in total. + * + * For example, if s = "zbax" and k = 2, then the resulting integer would be 8 by the following + * operations: + * 1. Convert: "zbax" ➝ "(26)(2)(1)(24)" ➝ "262124" ➝ 262124 + * 2. Transform #1: 262124 ➝ 2 + 6 + 2 + 1 + 2 + 4 ➝ 17 + * 3. Transform #2: 17 ➝ 1 + 7 ➝ 8 + * + * Return the resulting integer after performing the operations described above. + */ + +/** + * @param {string} s + * @param {number} k + * @return {number} + */ +var getLucky = function(s, k) { + let number = ''; + for (const char of s) { + number += (char.charCodeAt(0) - 96).toString(); + } + + let result = 0; + for (let i = 0; i < k; i++) { + result = 0; + for (const digit of number) { + result += parseInt(digit); + } + number = result.toString(); + } + + return result; +}; diff --git a/solutions/1946-largest-number-after-mutating-substring.js b/solutions/1946-largest-number-after-mutating-substring.js new file mode 100644 index 00000000..f64e4db0 --- /dev/null +++ b/solutions/1946-largest-number-after-mutating-substring.js @@ -0,0 +1,41 @@ +/** + * 1946. Largest Number After Mutating Substring + * https://leetcode.com/problems/largest-number-after-mutating-substring/ + * Difficulty: Medium + * + * You are given a string num, which represents a large integer. You are also given a 0-indexed + * integer array change of length 10 that maps each digit 0-9 to another digit. More formally, + * digit d maps to digit change[d]. + * + * You may choose to mutate a single substring of num. To mutate a substring, replace each digit + * num[i] with the digit it maps to in change (i.e. replace num[i] with change[num[i]]). + * + * Return a string representing the largest possible integer after mutating (or choosing not to) + * a single substring of num. + * + * A substring is a contiguous sequence of characters within the string. + */ + +/** + * @param {string} num + * @param {number[]} change + * @return {string} + */ +var maximumNumber = function(num, change) { + const digits = num.split(''); + let mutated = false; + + for (let i = 0; i < digits.length; i++) { + const currentDigit = parseInt(digits[i]); + const mappedDigit = change[currentDigit]; + + if (mappedDigit > currentDigit) { + digits[i] = mappedDigit.toString(); + mutated = true; + } else if (mappedDigit < currentDigit && mutated) { + break; + } + } + + return digits.join(''); +}; diff --git a/solutions/1947-maximum-compatibility-score-sum.js b/solutions/1947-maximum-compatibility-score-sum.js new file mode 100644 index 00000000..985d1deb --- /dev/null +++ b/solutions/1947-maximum-compatibility-score-sum.js @@ -0,0 +1,63 @@ +/** + * 1947. Maximum Compatibility Score Sum + * https://leetcode.com/problems/maximum-compatibility-score-sum/ + * Difficulty: Medium + * + * There is a survey that consists of n questions where each question's answer is either 0 + * (no) or 1 (yes). + * + * The survey was given to m students numbered from 0 to m - 1 and m mentors numbered from + * 0 to m - 1. The answers of the students are represented by a 2D integer array students + * where students[i] is an integer array that contains the answers of the ith student + * (0-indexed). The answers of the mentors are represented by a 2D integer array mentors + * where mentors[j] is an integer array that contains the answers of the jth mentor (0-indexed). + * + * Each student will be assigned to one mentor, and each mentor will have one student assigned + * to them. The compatibility score of a student-mentor pair is the number of answers that + * are the same for both the student and the mentor. + * - For example, if the student's answers were [1, 0, 1] and the mentor's answers were + * [0, 0, 1], then their compatibility score is 2 because only the second and the third + * answers are the same. + * + * You are tasked with finding the optimal student-mentor pairings to maximize the sum of the + * compatibility scores. + * + * Given students and mentors, return the maximum compatibility score sum that can be achieved. + */ + +/** + * @param {number[][]} students + * @param {number[][]} mentors + * @return {number} + */ +var maxCompatibilitySum = function(students, mentors) { + const m = students.length; + let maxScore = 0; + + backtrack(0, new Array(m).fill(false), 0); + return maxScore; + + function calculateScore(student, mentor) { + let score = 0; + for (let i = 0; i < student.length; i++) { + if (student[i] === mentor[i]) score++; + } + return score; + } + + function backtrack(studentIndex, usedMentors, currentScore) { + if (studentIndex === m) { + maxScore = Math.max(maxScore, currentScore); + return; + } + + for (let mentorIndex = 0; mentorIndex < m; mentorIndex++) { + if (!usedMentors[mentorIndex]) { + usedMentors[mentorIndex] = true; + backtrack(studentIndex + 1, usedMentors, + currentScore + calculateScore(students[studentIndex], mentors[mentorIndex])); + usedMentors[mentorIndex] = false; + } + } + } +}; diff --git a/solutions/1948-delete-duplicate-folders-in-system.js b/solutions/1948-delete-duplicate-folders-in-system.js new file mode 100644 index 00000000..085f6d72 --- /dev/null +++ b/solutions/1948-delete-duplicate-folders-in-system.js @@ -0,0 +1,115 @@ +/** + * 1948. Delete Duplicate Folders in System + * https://leetcode.com/problems/delete-duplicate-folders-in-system/ + * Difficulty: Hard + * + * Due to a bug, there are many duplicate folders in a file system. You are given a 2D array + * paths, where paths[i] is an array representing an absolute path to the ith folder in the + * file system. + * - For example, ["one", "two", "three"] represents the path "/one/two/three". + * + * Two folders (not necessarily on the same level) are identical if they contain the same + * non-empty set of identical subfolders and underlying subfolder structure. The folders do + * not need to be at the root level to be identical. If two or more folders are identical, + * then mark the folders as well as all their subfolders. + * - For example, folders "/a" and "/b" in the file structure below are identical. They (as + * well as their subfolders) should all be marked: + * - /a + * - /a/x + * - /a/x/y + * - /a/z + * - /b + * - /b/x + * - /b/x/y + * - /b/z + * - However, if the file structure also included the path "/b/w", then the folders "/a" and "/b" + * would not be identical. Note that "/a/x" and "/b/x" would still be considered identical + * even with the added folder. + * + * Once all the identical folders and their subfolders have been marked, the file system will delete + * all of them. The file system only runs the deletion once, so any folders that become identical + * after the initial deletion are not deleted. + * + * Return the 2D array ans containing the paths of the remaining folders after deleting all the + * marked folders. The paths may be returned in any order. + */ + +/** + * @param {string[][]} paths + * @return {string[][]} + */ +var deleteDuplicateFolder = function(paths) { + const root = {}; + + for (const path of paths) { + let node = root; + for (const folder of path) { + if (!node[folder]) node[folder] = {}; + node = node[folder]; + } + } + + const structures = new Map(); + + const serialize = (node, path) => { + if (Object.keys(node).length === 0) return ''; + + const folders = []; + const keys = Object.keys(node); + for (const folder of keys) { + const serialized = serialize(node[folder], [...path, folder]); + if (serialized !== null) { + folders.push(`${folder}(${serialized})`); + } else { + delete node[folder]; + } + } + + folders.sort(); + const key = folders.join(''); + + if (key.length > 0) { + if (!structures.has(key)) { + structures.set(key, []); + } + structures.get(key).push(path); + } + + return key; + }; + + serialize(root, []); + + const toDelete = new Set(); + + for (const [structure, paths] of structures.entries()) { + if (paths.length > 1) { + for (const path of paths) { + toDelete.add(path.join('/')); + } + } + } + + const result = []; + + const collectPaths = (node, path) => { + const currentPath = path.join('/'); + if (toDelete.has(currentPath)) return; + + if (path.length > 0) { + result.push([...path]); + } + + const keys = Object.keys(node); + for (const folder of keys) { + collectPaths(node[folder], [...path, folder]); + } + }; + + const rootFolders = Object.keys(root); + for (const folder of rootFolders) { + collectPaths(root[folder], [folder]); + } + + return result; +}; 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/1952-three-divisors.js b/solutions/1952-three-divisors.js new file mode 100644 index 00000000..c09cf96e --- /dev/null +++ b/solutions/1952-three-divisors.js @@ -0,0 +1,27 @@ +/** + * 1952. Three Divisors + * https://leetcode.com/problems/three-divisors/ + * Difficulty: Easy + * + * Given an integer n, return true if n has exactly three positive divisors. Otherwise, + * return false. + * + * An integer m is a divisor of n if there exists an integer k such that n = k * m. + */ + +/** + * @param {number} n + * @return {boolean} + */ +var isThree = function(n) { + let divisorCount = 0; + + for (let i = 1; i <= n; i++) { + if (n % i === 0) { + divisorCount++; + if (divisorCount > 3) return false; + } + } + + return divisorCount === 3; +}; diff --git a/solutions/1953-maximum-number-of-weeks-for-which-you-can-work.js b/solutions/1953-maximum-number-of-weeks-for-which-you-can-work.js new file mode 100644 index 00000000..730198a0 --- /dev/null +++ b/solutions/1953-maximum-number-of-weeks-for-which-you-can-work.js @@ -0,0 +1,34 @@ +/** + * 1953. Maximum Number of Weeks for Which You Can Work + * https://leetcode.com/problems/maximum-number-of-weeks-for-which-you-can-work/ + * Difficulty: Medium + * + * There are n projects numbered from 0 to n - 1. You are given an integer array milestones where + * each milestones[i] denotes the number of milestones the ith project has. + * + * You can work on the projects following these two rules: + * - Every week, you will finish exactly one milestone of one project. You must work every week. + * - You cannot work on two milestones from the same project for two consecutive weeks. + * - Once all the milestones of all the projects are finished, or if the only milestones that you + * can work on will cause you to violate the above rules, you will stop working. Note that you + * may not be able to finish every project's milestones due to these constraints. + * + * Return the maximum number of weeks you would be able to work on the projects without violating + * the rules mentioned above. + */ + +/** + * @param {number[]} milestones + * @return {number} + */ +var numberOfWeeks = function(milestones) { + let total = 0; + let maxMilestones = 0; + + for (const count of milestones) { + total += count; + maxMilestones = Math.max(maxMilestones, count); + } + + return Math.min(total, 2 * (total - maxMilestones) + 1); +}; diff --git a/solutions/1954-minimum-garden-perimeter-to-collect-enough-apples.js b/solutions/1954-minimum-garden-perimeter-to-collect-enough-apples.js new file mode 100644 index 00000000..e064083c --- /dev/null +++ b/solutions/1954-minimum-garden-perimeter-to-collect-enough-apples.js @@ -0,0 +1,34 @@ +/** + * 1954. Minimum Garden Perimeter to Collect Enough Apples + * https://leetcode.com/problems/minimum-garden-perimeter-to-collect-enough-apples/ + * Difficulty: Medium + * + * In a garden represented as an infinite 2D grid, there is an apple tree planted at every + * integer coordinate. The apple tree planted at an integer coordinate (i, j) has |i| + |j| + * apples growing on it. + * + * You will buy an axis-aligned square plot of land that is centered at (0, 0). + * + * Given an integer neededApples, return the minimum perimeter of a plot such that at least + * neededApples apples are inside or on the perimeter of that plot. + * + * The value of |x| is defined as: + * - x if x >= 0 + * - -x if x < 0 + */ + +/** + * @param {number} neededApples + * @return {number} + */ +var minimumPerimeter = function(neededApples) { + let n = 0; + let totalApples = 0; + + while (totalApples < neededApples) { + n++; + totalApples = 2 * n * (n + 1) * (2 * n + 1); + } + + return 8 * n; +}; diff --git a/solutions/1955-count-number-of-special-subsequences.js b/solutions/1955-count-number-of-special-subsequences.js new file mode 100644 index 00000000..5daa07ec --- /dev/null +++ b/solutions/1955-count-number-of-special-subsequences.js @@ -0,0 +1,32 @@ +/** + * 1955. Count Number of Special Subsequences + * https://leetcode.com/problems/count-number-of-special-subsequences/ + * Difficulty: Hard + * + * A sequence is special if it consists of a positive number of 0s, followed by a positive number + * of 1s, then a positive number of 2s. + * - For example, [0,1,2] and [0,0,1,1,1,2] are special. + * - In contrast, [2,1,0], [1], and [0,1,2,0] are not special. + * + * Given an array nums (consisting of only integers 0, 1, and 2), return the number of different + * subsequences that are special. Since the answer may be very large, return it modulo 109 + 7. + * + * A subsequence of an array is a sequence that can be derived from the array by deleting some + * or no elements without changing the order of the remaining elements. Two subsequences are + * different if the set of indices chosen are different. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var countSpecialSubsequences = function(nums) { + const MOD = 1e9 + 7; + const dp = [1, 0, 0, 0]; + + for (const num of nums) { + dp[num + 1] = (dp[num + 1] * 2 % MOD + dp[num]) % MOD; + } + + return dp[3]; +}; 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/1957-delete-characters-to-make-fancy-string.js b/solutions/1957-delete-characters-to-make-fancy-string.js new file mode 100644 index 00000000..39c92ece --- /dev/null +++ b/solutions/1957-delete-characters-to-make-fancy-string.js @@ -0,0 +1,36 @@ +/** + * 1957. Delete Characters to Make Fancy String + * https://leetcode.com/problems/delete-characters-to-make-fancy-string/ + * Difficulty: Easy + * + * A fancy string is a string where no three consecutive characters are equal. + * + * Given a string s, delete the minimum possible number of characters from s to make + * it fancy. + * + * Return the final string after the deletion. It can be shown that the answer will + * always be unique. + */ + +/** + * @param {string} s + * @return {string} + */ +var makeFancyString = function(s) { + let result = s[0]; + let count = 1; + + for (let i = 1; i < s.length; i++) { + if (s[i] === s[i - 1]) { + if (count < 2) { + result += s[i]; + count++; + } + } else { + result += s[i]; + count = 1; + } + } + + return result; +}; diff --git a/solutions/1958-check-if-move-is-legal.js b/solutions/1958-check-if-move-is-legal.js new file mode 100644 index 00000000..7fef6e2a --- /dev/null +++ b/solutions/1958-check-if-move-is-legal.js @@ -0,0 +1,54 @@ +/** + * 1958. Check if Move is Legal + * https://leetcode.com/problems/check-if-move-is-legal/ + * Difficulty: Medium + * + * You are given a 0-indexed 8 x 8 grid board, where board[r][c] represents the cell (r, c) on a + * game board. On the board, free cells are represented by '.', white cells are represented by + * 'W', and black cells are represented by 'B'. + * + * Each move in this game consists of choosing a free cell and changing it to the color you are + * playing as (either white or black). However, a move is only legal if, after changing it, the + * cell becomes the endpoint of a good line (horizontal, vertical, or diagonal). + * + * A good line is a line of three or more cells (including the endpoints) where the endpoints of + * the line are one color, and the remaining cells in the middle are the opposite color (no cells + * in the line are free). You can find examples for good lines in the figure below. + * + * Given two integers rMove and cMove and a character color representing the color you are playing + * as (white or black), return true if changing cell (rMove, cMove) to color color is a legal move, + * or false if it is not legal. + */ + +/** + * @param {character[][]} board + * @param {number} rMove + * @param {number} cMove + * @param {character} color + * @return {boolean} + */ +var checkMove = function(board, rMove, cMove, color) { + const opposite = color === 'B' ? 'W' : 'B'; + const directions = [ + [0, 1], [0, -1], [1, 0], [-1, 0], + [1, 1], [1, -1], [-1, 1], [-1, -1] + ]; + + for (const [dr, dc] of directions) { + let row = rMove + dr; + let col = cMove + dc; + let count = 1; + + while (row >= 0 && row < 8 && col >= 0 && col < 8 && board[row][col] === opposite) { + row += dr; + col += dc; + count++; + } + + if (count >= 2 && row >= 0 && row < 8 && col >= 0 && col < 8 && board[row][col] === color) { + return true; + } + } + + return false; +}; diff --git a/solutions/1959-minimum-total-space-wasted-with-k-resizing-operations.js b/solutions/1959-minimum-total-space-wasted-with-k-resizing-operations.js new file mode 100644 index 00000000..9576849d --- /dev/null +++ b/solutions/1959-minimum-total-space-wasted-with-k-resizing-operations.js @@ -0,0 +1,54 @@ +/** + * 1959. Minimum Total Space Wasted With K Resizing Operations + * https://leetcode.com/problems/minimum-total-space-wasted-with-k-resizing-operations/ + * Difficulty: Medium + * + * You are currently designing a dynamic array. You are given a 0-indexed integer array nums, + * where nums[i] is the number of elements that will be in the array at time i. In addition, + * you are given an integer k, the maximum number of times you can resize the array (to any size). + * + * The size of the array at time t, sizet, must be at least nums[t] because there needs to be + * enough space in the array to hold all the elements. The space wasted at time t is defined + * as sizet - nums[t], and the total space wasted is the sum of the space wasted across every + * time t where 0 <= t < nums.length. + * + * Return the minimum total space wasted if you can resize the array at most k times. + * + * Note: The array can have any size at the start and does not count towards the number of + * resizing operations. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minSpaceWastedKResizing = function(nums, k) { + const n = nums.length; + const dp = new Array(n + 1).fill().map(() => new Array(k + 2).fill(Infinity)); + dp[0][0] = 0; + + for (let i = 1; i <= n; i++) { + let maxVal = 0; + let sum = 0; + + for (let j = i; j > 0; j--) { + maxVal = Math.max(maxVal, nums[j - 1]); + sum += nums[j - 1]; + const waste = maxVal * (i - j + 1) - sum; + + for (let resizes = 0; resizes <= k; resizes++) { + if (dp[j - 1][resizes] !== Infinity) { + dp[i][resizes + 1] = Math.min(dp[i][resizes + 1], dp[j - 1][resizes] + waste); + } + } + } + } + + let result = Infinity; + for (let resizes = 1; resizes <= k + 1; resizes++) { + result = Math.min(result, dp[n][resizes]); + } + + return result; +}; diff --git a/solutions/1960-maximum-product-of-the-length-of-two-palindromic-substrings.js b/solutions/1960-maximum-product-of-the-length-of-two-palindromic-substrings.js new file mode 100644 index 00000000..10d34b76 --- /dev/null +++ b/solutions/1960-maximum-product-of-the-length-of-two-palindromic-substrings.js @@ -0,0 +1,67 @@ +/** + * 1960. Maximum Product of the Length of Two Palindromic Substrings + * https://leetcode.com/problems/maximum-product-of-the-length-of-two-palindromic-substrings/ + * Difficulty: Hard + * + * You are given a 0-indexed string s and are tasked with finding two non-intersecting palindromic + * substrings of odd length such that the product of their lengths is maximized. + * + * More formally, you want to choose four integers i, j, k, l such that + * 0 <= i <= j < k <= l < s.length and both the substrings s[i...j] and s[k...l] are palindromes + * and have odd lengths. s[i...j] denotes a substring from index i to index j inclusive. + * + * Return the maximum possible product of the lengths of the two non-intersecting palindromic + * substrings. + * + * A palindrome is a string that is the same forward and backward. A substring is a contiguous + * sequence of characters in a string. + */ + +/** +* @param {string} s +* @return {number} +*/ +var maxProduct = function(s) { + const n = s.length; + const before = new Array(n).fill(0); + const after = new Array(n).fill(0); + + let center = -1; + let right = -1; + const dp = new Array(n).fill(0); + + for (let i = 0; i < n; i++) { + const radius = i <= right ? Math.min(dp[2 * center - i], right - i) : 0; + let left = i - radius; + let rt = i + radius; + + while (left >= 0 && rt < n && s[left] === s[rt]) { + before[rt] = Math.max(before[rt], rt - left + 1); + after[left] = Math.max(after[left], rt - left + 1); + left--; + rt++; + } + + dp[i] = rt - i - 1; + + if (rt - 1 > right) { + center = i; + right = rt - 1; + } + } + + for (let i = 1; i < n; i++) { + before[i] = Math.max(before[i - 1], before[i]); + } + + for (let i = n - 2; i >= 0; i--) { + after[i] = Math.max(after[i + 1], after[i]); + } + + let result = 0; + for (let i = 1; i < n; i++) { + result = Math.max(result, before[i - 1] * after[i]); + } + + return result; +}; diff --git a/solutions/1961-check-if-string-is-a-prefix-of-array.js b/solutions/1961-check-if-string-is-a-prefix-of-array.js new file mode 100644 index 00000000..68aaf4c0 --- /dev/null +++ b/solutions/1961-check-if-string-is-a-prefix-of-array.js @@ -0,0 +1,30 @@ +/** + * 1961. Check If String Is a Prefix of Array + * https://leetcode.com/problems/check-if-string-is-a-prefix-of-array/ + * Difficulty: Easy + * + * Given a string s and an array of strings words, determine whether s is a prefix string of words. + * + * A string s is a prefix string of words if s can be made by concatenating the first k strings in + * words for some positive k no larger than words.length. + * + * Return true if s is a prefix string of words, or false otherwise. + */ + +/** + * @param {string} s + * @param {string[]} words + * @return {boolean} + */ +var isPrefixString = function(s, words) { + let currentIndex = 0; + + for (const word of words) { + if (currentIndex + word.length > s.length) return false; + if (s.slice(currentIndex, currentIndex + word.length) !== word) return false; + currentIndex += word.length; + if (currentIndex === s.length) 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/1963-minimum-number-of-swaps-to-make-the-string-balanced.js b/solutions/1963-minimum-number-of-swaps-to-make-the-string-balanced.js new file mode 100644 index 00000000..2f687a52 --- /dev/null +++ b/solutions/1963-minimum-number-of-swaps-to-make-the-string-balanced.js @@ -0,0 +1,37 @@ +/** + * 1963. Minimum Number of Swaps to Make the String Balanced + * https://leetcode.com/problems/minimum-number-of-swaps-to-make-the-string-balanced/ + * Difficulty: Medium + * + * You are given a 0-indexed string s of even length n. The string consists of exactly n / 2 opening + * brackets '[' and n / 2 closing brackets ']'. + * + * A string is called balanced if and only if: + * - It is the empty string, or + * - It can be written as AB, where both A and B are balanced strings, or + * - It can be written as [C], where C is a balanced string. + * + * You may swap the brackets at any two indices any number of times. + * + * Return the minimum number of swaps to make s balanced. + */ + +/** + * @param {string} s + * @return {number} + */ +var minSwaps = function(s) { + let imbalance = 0; + let maxImbalance = 0; + + for (const bracket of s) { + if (bracket === '[') { + imbalance--; + } else { + imbalance++; + maxImbalance = Math.max(maxImbalance, imbalance); + } + } + + return Math.ceil(maxImbalance / 2); +}; diff --git a/solutions/1964-find-the-longest-valid-obstacle-course-at-each-position.js b/solutions/1964-find-the-longest-valid-obstacle-course-at-each-position.js new file mode 100644 index 00000000..cafb25a7 --- /dev/null +++ b/solutions/1964-find-the-longest-valid-obstacle-course-at-each-position.js @@ -0,0 +1,54 @@ +/** + * 1964. Find the Longest Valid Obstacle Course at Each Position + * https://leetcode.com/problems/find-the-longest-valid-obstacle-course-at-each-position/ + * Difficulty: Hard + * + * You want to build some obstacle courses. You are given a 0-indexed integer array obstacles of + * length n, where obstacles[i] describes the height of the ith obstacle. + * + * For every index i between 0 and n - 1 (inclusive), find the length of the longest obstacle + * course in obstacles such that: + * - You choose any number of obstacles between 0 and i inclusive. + * - You must include the ith obstacle in the course. + * - You must put the chosen obstacles in the same order as they appear in obstacles. + * - Every obstacle (except the first) is taller than or the same height as the obstacle immediately + * before it. + * + * Return an array ans of length n, where ans[i] is the length of the longest obstacle course for + * index i as described above. + */ + +/** + * @param {number[]} obstacles + * @return {number[]} + */ +var longestObstacleCourseAtEachPosition = function(obstacles) { + const n = obstacles.length; + const result = new Array(n).fill(1); + const stack = []; + + for (let i = 0; i < n; i++) { + const height = obstacles[i]; + let left = 0; + let right = stack.length; + + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (stack[mid] <= height) { + left = mid + 1; + } else { + right = mid; + } + } + + if (left < stack.length) { + stack[left] = height; + } else { + stack.push(height); + } + + result[i] = left + 1; + } + + 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/1967-number-of-strings-that-appear-as-substrings-in-word.js b/solutions/1967-number-of-strings-that-appear-as-substrings-in-word.js new file mode 100644 index 00000000..b0cb45d5 --- /dev/null +++ b/solutions/1967-number-of-strings-that-appear-as-substrings-in-word.js @@ -0,0 +1,19 @@ +/** + * 1967. Number of Strings That Appear as Substrings in Word + * https://leetcode.com/problems/number-of-strings-that-appear-as-substrings-in-word/ + * Difficulty: Easy + * + * Given an array of strings patterns and a string word, return the number of strings in patterns + * that exist as a substring in word. + * + * A substring is a contiguous sequence of characters within a string. + */ + +/** + * @param {string[]} patterns + * @param {string} word + * @return {number} + */ +var numOfStrings = function(patterns, word) { + return patterns.reduce((count, pattern) => word.includes(pattern) ? count + 1 : count, 0); +}; diff --git a/solutions/1968-array-with-elements-not-equal-to-average-of-neighbors.js b/solutions/1968-array-with-elements-not-equal-to-average-of-neighbors.js new file mode 100644 index 00000000..67994987 --- /dev/null +++ b/solutions/1968-array-with-elements-not-equal-to-average-of-neighbors.js @@ -0,0 +1,29 @@ +/** + * 1968. Array With Elements Not Equal to Average of Neighbors + * https://leetcode.com/problems/array-with-elements-not-equal-to-average-of-neighbors/ + * Difficulty: Medium + * + * You are given a 0-indexed array nums of distinct integers. You want to rearrange the elements + * in the array such that every element in the rearranged array is not equal to the average of + * its neighbors. + * + * More formally, the rearranged array should have the property such that for every i in the + * range 1 <= i < nums.length - 1, (nums[i-1] + nums[i+1]) / 2 is not equal to nums[i]. + * + * Return any rearrangement of nums that meets the requirements. + */ + +/** + * @param {number[]} nums + * @return {number[]} + */ +var rearrangeArray = function(nums) { + const result = new Array(nums.length); + nums.sort((a, b) => a - b); + + for (let i = 0, left = 0, right = nums.length - 1; i < nums.length; i++) { + result[i] = i % 2 === 0 ? nums[left++] : nums[right--]; + } + + return result; +}; diff --git a/solutions/1969-minimum-non-zero-product-of-the-array-elements.js b/solutions/1969-minimum-non-zero-product-of-the-array-elements.js new file mode 100644 index 00000000..9165df8e --- /dev/null +++ b/solutions/1969-minimum-non-zero-product-of-the-array-elements.js @@ -0,0 +1,44 @@ +/** + * 1969. Minimum Non-Zero Product of the Array Elements + * https://leetcode.com/problems/minimum-non-zero-product-of-the-array-elements/ + * Difficulty: Medium + * + * You are given a positive integer p. Consider an array nums (1-indexed) that consists of the + * integers in the inclusive range [1, 2p - 1] in their binary representations. You are allowed + * to do the following operation any number of times: + * - Choose two elements x and y from nums. + * - Choose a bit in x and swap it with its corresponding bit in y. Corresponding bit refers to + * the bit that is in the same position in the other integer. + * + * For example, if x = 1101 and y = 0011, after swapping the 2nd bit from the right, we have + * x = 1111 and y = 0001. + * + * Find the minimum non-zero product of nums after performing the above operation any number + * of times. Return this product modulo 109 + 7. + * + * Note: The answer should be the minimum product before the modulo operation is done. + */ + +/** + * @param {number} p + * @return {number} + */ +var minNonZeroProduct = function(p) { + const MOD = 1000000007n; + const maxVal = (1n << BigInt(p)) - 1n; + const halfCount = (maxVal - 1n) / 2n; + const base = maxVal - 1n; + + function pow(base, exp, mod) { + let result = 1n; + base = base % mod; + while (exp > 0n) { + if (exp & 1n) result = (result * base) % mod; + base = (base * base) % mod; + exp >>= 1n; + } + return result; + } + + return Number((maxVal * pow(base, halfCount, MOD)) % MOD); +}; diff --git a/solutions/1970-last-day-where-you-can-still-cross.js b/solutions/1970-last-day-where-you-can-still-cross.js new file mode 100644 index 00000000..7b36cd06 --- /dev/null +++ b/solutions/1970-last-day-where-you-can-still-cross.js @@ -0,0 +1,78 @@ +/** + * 1970. Last Day Where You Can Still Cross + * https://leetcode.com/problems/last-day-where-you-can-still-cross/ + * Difficulty: Hard + * + * There is a 1-based binary matrix where 0 represents land and 1 represents water. You are given + * integers row and col representing the number of rows and columns in the matrix, respectively. + * + * Initially on day 0, the entire matrix is land. However, each day a new cell becomes flooded + * with water. You are given a 1-based 2D array cells, where cells[i] = [ri, ci] represents that + * on the ith day, the cell on the rith row and cith column (1-based coordinates) will be covered + * with water (i.e., changed to 1). + * + * You want to find the last day that it is possible to walk from the top to the bottom by only + * walking on land cells. You can start from any cell in the top row and end at any cell in the + * bottom row. You can only travel in the four cardinal directions (left, right, up, and down). + * + * Return the last day where it is possible to walk from the top to the bottom by only walking + * on land cells. + */ + +/** + * @param {number} row + * @param {number} col + * @param {number[][]} cells + * @return {number} + */ +var latestDayToCross = function(row, col, cells) { + const directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]; + let left = 1; + let right = cells.length; + let result = 0; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + if (canCross(mid)) { + result = mid; + left = mid + 1; + } else { + right = mid - 1; + } + } + + return result; + + function canCross(day) { + const grid = new Array(row).fill().map(() => new Array(col).fill(0)); + for (let i = 0; i < day; i++) { + const [r, c] = cells[i]; + grid[r - 1][c - 1] = 1; + } + + const queue = []; + const visited = new Array(row).fill().map(() => new Array(col).fill(false)); + + for (let c = 0; c < col; c++) { + if (grid[0][c] === 0) { + queue.push([0, c]); + visited[0][c] = true; + } + } + + while (queue.length) { + const [r, c] = queue.shift(); + if (r === row - 1) return true; + + for (const [dr, dc] of directions) { + const nr = r + dr; + const nc = c + dc; + if (nr >= 0 && nr < row && nc >= 0 && nc < col && !visited[nr][nc] && grid[nr][nc] === 0) { + queue.push([nr, nc]); + visited[nr][nc] = true; + } + } + } + return false; + } +}; diff --git a/solutions/1971-find-if-path-exists-in-graph.js b/solutions/1971-find-if-path-exists-in-graph.js new file mode 100644 index 00000000..4b032666 --- /dev/null +++ b/solutions/1971-find-if-path-exists-in-graph.js @@ -0,0 +1,50 @@ +/** + * 1971. Find if Path Exists in Graph + * https://leetcode.com/problems/find-if-path-exists-in-graph/ + * Difficulty: Easy + * + * There is a bi-directional graph with n vertices, where each vertex is labeled from 0 to + * n - 1 (inclusive). The edges in the graph are represented as a 2D integer array edges, + * where each edges[i] = [ui, vi] denotes a bi-directional edge between vertex ui and + * vertex vi. Every vertex pair is connected by at most one edge, and no vertex has an + * edge to itself. + * + * You want to determine if there is a valid path that exists from vertex source to vertex + * destination. + * + * Given edges and the integers n, source, and destination, return true if there is a valid + * path from source to destination, or false otherwise. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number} source + * @param {number} destination + * @return {boolean} + */ +var validPath = function(n, edges, source, destination) { + const graph = Array.from({ length: n }, () => []); + for (const [u, v] of edges) { + graph[u].push(v); + graph[v].push(u); + } + + const visited = new Set(); + const queue = [source]; + + while (queue.length) { + const vertex = queue.shift(); + if (vertex === destination) return true; + if (visited.has(vertex)) continue; + visited.add(vertex); + + for (const neighbor of graph[vertex]) { + if (!visited.has(neighbor)) { + queue.push(neighbor); + } + } + } + + return false; +}; 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/1974-minimum-time-to-type-word-using-special-typewriter.js b/solutions/1974-minimum-time-to-type-word-using-special-typewriter.js new file mode 100644 index 00000000..9c1641e7 --- /dev/null +++ b/solutions/1974-minimum-time-to-type-word-using-special-typewriter.js @@ -0,0 +1,34 @@ +/** + * 1974. Minimum Time to Type Word Using Special Typewriter + * https://leetcode.com/problems/minimum-time-to-type-word-using-special-typewriter/ + * Difficulty: Easy + * + * There is a special typewriter with lowercase English letters 'a' to 'z' arranged in a circle + * with a pointer. A character can only be typed if the pointer is pointing to that character. + * The pointer is initially pointing to the character 'a'. + * + * Each second, you may perform one of the following operations: + * - Move the pointer one character counterclockwise or clockwise. + * - Type the character the pointer is currently on. + * + * Given a string word, return the minimum number of seconds to type out the characters in word. + */ + +/** + * @param {string} word + * @return {number} + */ +var minTimeToType = function(word) { + let position = 'a'; + let result = 0; + + for (const char of word) { + const clockwise = Math.abs(char.charCodeAt(0) - position.charCodeAt(0)); + const counterclockwise = 26 - clockwise; + const moves = Math.min(clockwise, counterclockwise); + result += moves + 1; + position = char; + } + + return result; +}; diff --git a/solutions/1975-maximum-matrix-sum.js b/solutions/1975-maximum-matrix-sum.js new file mode 100644 index 00000000..92b65dd2 --- /dev/null +++ b/solutions/1975-maximum-matrix-sum.js @@ -0,0 +1,33 @@ +/** + * 1975. Maximum Matrix Sum + * https://leetcode.com/problems/maximum-matrix-sum/ + * Difficulty: Medium + * + * You are given an n x n integer matrix. You can do the following operation any number of times: + * - Choose any two adjacent elements of matrix and multiply each of them by -1. + * + * Two elements are considered adjacent if and only if they share a border. + * + * Your goal is to maximize the summation of the matrix's elements. Return the maximum sum of the + * matrix's elements using the operation mentioned above. + */ + +/** + * @param {number[][]} matrix + * @return {number} + */ +var maxMatrixSum = function(matrix) { + let totalSum = 0; + let negativeCount = 0; + let minAbs = Infinity; + + for (const row of matrix) { + for (const num of row) { + totalSum += Math.abs(num); + if (num < 0) negativeCount++; + minAbs = Math.min(minAbs, Math.abs(num)); + } + } + + return negativeCount % 2 === 0 ? totalSum : totalSum - 2 * minAbs; +}; diff --git a/solutions/1977-number-of-ways-to-separate-numbers.js b/solutions/1977-number-of-ways-to-separate-numbers.js new file mode 100644 index 00000000..6fad6b5d --- /dev/null +++ b/solutions/1977-number-of-ways-to-separate-numbers.js @@ -0,0 +1,77 @@ +/** + * 1977. Number of Ways to Separate Numbers + * https://leetcode.com/problems/number-of-ways-to-separate-numbers/ + * Difficulty: Hard + * + * You wrote down many positive integers in a string called num. However, you realized that you + * forgot to add commas to seperate the different numbers. You remember that the list of integers + * was non-decreasing and that no integer had leading zeros. + * + * Return the number of possible lists of integers that you could have written down to get the + * string num. Since the answer may be large, return it modulo 109 + 7. + */ + +/** + * @param {string} num + * @return {number} + */ +var numberOfCombinations = function(num) { + const n = num.length; + if (num[0] === '0') return 0; + + const MOD = 1e9 + 7; + const lcp = new Array(n + 1).fill().map(() => new Array(n + 1).fill(0)); + + for (let i = n - 1; i >= 0; i--) { + for (let j = n - 1; j >= 0; j--) { + if (num[i] === num[j]) { + lcp[i][j] = lcp[i + 1][j + 1] + 1; + } + } + } + + const dp = new Array(n).fill().map(() => new Array(n + 1).fill(0)); + const prefixSum = new Array(n).fill().map(() => new Array(n + 1).fill(0)); + + dp[0][1] = 1; + prefixSum[0][1] = 1; + + for (let i = 1; i < n; i++) { + for (let j = 1; j <= i; j++) { + prefixSum[i - 1][j] = (prefixSum[i - 1][j - 1] + dp[i - 1][j]) % MOD; + } + + for (let len = 1; len <= i + 1; len++) { + if (num[i - len + 1] === '0') continue; + + if (i - len < 0) { + dp[i][len] = 1; + continue; + } + + dp[i][len] = prefixSum[i - len][Math.min(i - len + 1, len)]; + + if (len <= i - len + 1) { + const start1 = i - 2 * len + 1; + const start2 = i - len + 1; + + if (!compare(start1, start2, len)) { + dp[i][len] = (dp[i][len] - dp[i - len][len] + MOD) % MOD; + } + } + } + + prefixSum[i][0] = 0; + for (let j = 1; j <= i + 1; j++) { + prefixSum[i][j] = (prefixSum[i][j - 1] + dp[i][j]) % MOD; + } + } + + return prefixSum[n - 1][n]; + + function compare(i1, i2, len) { + const commonLen = lcp[i1][i2]; + if (commonLen >= len) return true; + return i1 + commonLen < n && i2 + commonLen < n && num[i1 + commonLen] <= num[i2 + commonLen]; + } +}; diff --git a/solutions/1979-find-greatest-common-divisor-of-array.js b/solutions/1979-find-greatest-common-divisor-of-array.js new file mode 100644 index 00000000..acf2c5df --- /dev/null +++ b/solutions/1979-find-greatest-common-divisor-of-array.js @@ -0,0 +1,23 @@ +/** + * 1979. Find Greatest Common Divisor of Array + * https://leetcode.com/problems/find-greatest-common-divisor-of-array/ + * Difficulty: Easy + * + * Given an integer array nums, return the greatest common divisor of the smallest number and + * largest number in nums. + * + * The greatest common divisor of two numbers is the largest positive integer that evenly + * divides both numbers. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var findGCD = function(nums) { + return gcd(Math.min(...nums), Math.max(...nums)); + + function gcd(a, b) { + return b === 0 ? a : gcd(b, a % b); + } +}; diff --git a/solutions/1981-minimize-the-difference-between-target-and-chosen-elements.js b/solutions/1981-minimize-the-difference-between-target-and-chosen-elements.js new file mode 100644 index 00000000..6e66a493 --- /dev/null +++ b/solutions/1981-minimize-the-difference-between-target-and-chosen-elements.js @@ -0,0 +1,45 @@ +/** + * 1981. Minimize the Difference Between Target and Chosen Elements + * https://leetcode.com/problems/minimize-the-difference-between-target-and-chosen-elements/ + * Difficulty: Medium + * + * You are given an m x n integer matrix mat and an integer target. + * + * Choose one integer from each row in the matrix such that the absolute difference between + * target and the sum of the chosen elements is minimized. + * + * Return the minimum absolute difference. + * + * The absolute difference between two numbers a and b is the absolute value of a - b. + */ + +/** + * @param {number[][]} mat + * @param {number} target + * @return {number} + */ +var minimizeTheDifference = function(mat, target) { + const m = mat.length; + const maxSum = 70 * m; + let possibleSums = new Set([0]); + + for (const row of mat) { + const nextSums = new Set(); + for (const num of row) { + for (const sum of possibleSums) { + const newSum = sum + num; + if (newSum <= target + maxSum) { + nextSums.add(newSum); + } + } + } + possibleSums = nextSums; + } + + let result = Infinity; + for (const sum of possibleSums) { + result = Math.min(result, Math.abs(sum - target)); + } + + return result; +}; diff --git a/solutions/1982-find-array-given-subset-sums.js b/solutions/1982-find-array-given-subset-sums.js new file mode 100644 index 00000000..da9ab09f --- /dev/null +++ b/solutions/1982-find-array-given-subset-sums.js @@ -0,0 +1,63 @@ +/** + * 1982. Find Array Given Subset Sums + * https://leetcode.com/problems/find-array-given-subset-sums/ + * Difficulty: Hard + * + * You are given an integer n representing the length of an unknown array that you are trying + * to recover. You are also given an array sums containing the values of all 2n subset sums of + * the unknown array (in no particular order). + * + * Return the array ans of length n representing the unknown array. If multiple answers exist, + * return any of them. + * + * An array sub is a subset of an array arr if sub can be obtained from arr by deleting some + * (possibly zero or all) elements of arr. The sum of the elements in sub is one possible + * subset sum of arr. The sum of an empty array is considered to be 0. + * + * Note: Test cases are generated such that there will always be at least one correct answer. + */ + +/** +* @param {number} n +* @param {number[]} sums +* @return {number[]} +*/ +var recoverArray = function(n, sums) { + sums.sort((a, b) => a - b); + + const result = []; + while (result.length < n) { + const diff = sums[1] - sums[0]; + + const withNum = []; + const withoutNum = []; + const freq = new Map(); + for (const sum of sums) { + freq.set(sum, (freq.get(sum) || 0) + 1); + } + + for (const sum of sums) { + if (freq.get(sum) > 0) { + freq.set(sum, freq.get(sum) - 1); + + if (freq.get(sum + diff) > 0) { + freq.set(sum + diff, freq.get(sum + diff) - 1); + withoutNum.push(sum); + withNum.push(sum + diff); + } else { + return []; + } + } + } + + if (withoutNum.includes(0)) { + result.push(diff); + sums = withoutNum; + } else { + result.push(-diff); + sums = withNum; + } + } + + return result; +}; 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/1984-minimum-difference-between-highest-and-lowest-of-k-scores.js b/solutions/1984-minimum-difference-between-highest-and-lowest-of-k-scores.js new file mode 100644 index 00000000..889aae95 --- /dev/null +++ b/solutions/1984-minimum-difference-between-highest-and-lowest-of-k-scores.js @@ -0,0 +1,29 @@ +/** + * 1984. Minimum Difference Between Highest and Lowest of K Scores + * https://leetcode.com/problems/minimum-difference-between-highest-and-lowest-of-k-scores/ + * Difficulty: Easy + * + * You are given a 0-indexed integer array nums, where nums[i] represents the score of the + * ith student. You are also given an integer k. + * + * Pick the scores of any k students from the array so that the difference between the highest + * and the lowest of the k scores is minimized. + * + * Return the minimum possible difference. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var minimumDifference = function(nums, k) { + nums.sort((a, b) => a - b); + let result = Infinity; + + for (let i = 0; i <= nums.length - k; i++) { + result = Math.min(result, nums[i + k - 1] - nums[i]); + } + + return result; +}; diff --git a/solutions/1986-minimum-number-of-work-sessions-to-finish-the-tasks.js b/solutions/1986-minimum-number-of-work-sessions-to-finish-the-tasks.js new file mode 100644 index 00000000..f6174274 --- /dev/null +++ b/solutions/1986-minimum-number-of-work-sessions-to-finish-the-tasks.js @@ -0,0 +1,59 @@ +/** + * 1986. Minimum Number of Work Sessions to Finish the Tasks + * https://leetcode.com/problems/minimum-number-of-work-sessions-to-finish-the-tasks/ + * Difficulty: Medium + * + * There are n tasks assigned to you. The task times are represented as an integer array tasks of + * length n, where the ith task takes tasks[i] hours to finish. A work session is when you work + * for at most sessionTime consecutive hours and then take a break. + * + * You should finish the given tasks in a way that satisfies the following conditions: + * - If you start a task in a work session, you must complete it in the same work session. + * - You can start a new task immediately after finishing the previous one. + * - You may complete the tasks in any order. + * + * Given tasks and sessionTime, return the minimum number of work sessions needed to finish all the + * tasks following the conditions above. + * + * The tests are generated such that sessionTime is greater than or equal to the maximum element + * in tasks[i]. + */ + +/** + * @param {number[]} tasks + * @param {number} sessionTime + * @return {number} + */ +var minSessions = function(tasks, sessionTime) { + const n = tasks.length; + const dp = new Array(1 << n).fill(n + 1); + dp[0] = 0; + + for (let mask = 1; mask < 1 << n; mask++) { + let time = 0; + for (let i = 0; i < n; i++) { + if (mask & (1 << i)) { + time += tasks[i]; + } + } + + for (let subset = mask; subset; subset = (subset - 1) & mask) { + if (subset === mask) continue; + let subsetTime = 0; + for (let i = 0; i < n; i++) { + if (subset & (1 << i)) { + subsetTime += tasks[i]; + } + } + if (subsetTime <= sessionTime) { + dp[mask] = Math.min(dp[mask], dp[mask ^ subset] + 1); + } + } + + if (time <= sessionTime) { + dp[mask] = 1; + } + } + + return dp[(1 << n) - 1]; +}; diff --git a/solutions/1987-number-of-unique-good-subsequences.js b/solutions/1987-number-of-unique-good-subsequences.js new file mode 100644 index 00000000..e0d6651c --- /dev/null +++ b/solutions/1987-number-of-unique-good-subsequences.js @@ -0,0 +1,41 @@ +/** + * 1987. Number of Unique Good Subsequences + * https://leetcode.com/problems/number-of-unique-good-subsequences/ + * Difficulty: Hard + * + * You are given a binary string binary. A subsequence of binary is considered good if it is not + * empty and has no leading zeros (with the exception of "0"). + * + * Find the number of unique good subsequences of binary. + * - For example, if binary = "001", then all the good subsequences are ["0", "0", "1"], so the + * unique good subsequences are "0" and "1". Note that subsequences "00", "01", and "001" are + * not good because they have leading zeros. + * + * Return the number of unique good subsequences of binary. Since the answer may be very large, + * return it modulo 109 + 7. + * + * 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 {string} binary + * @return {number} + */ +var numberOfUniqueGoodSubsequences = function(binary) { + const MOD = 1e9 + 7; + let endsWithZero = 0; + let endsWithOne = 0; + let hasZero = false; + + for (const digit of binary) { + if (digit === '0') { + hasZero = true; + endsWithZero = (endsWithZero + endsWithOne) % MOD; + } else { + endsWithOne = (endsWithOne + endsWithZero + 1) % MOD; + } + } + + return (endsWithZero + endsWithOne + (hasZero ? 1 : 0)) % MOD; +}; 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/1991-find-the-middle-index-in-array.js b/solutions/1991-find-the-middle-index-in-array.js new file mode 100644 index 00000000..fa993684 --- /dev/null +++ b/solutions/1991-find-the-middle-index-in-array.js @@ -0,0 +1,35 @@ +/** + * 1991. Find the Middle Index in Array + * https://leetcode.com/problems/find-the-middle-index-in-array/ + * Difficulty: Easy + * + * Given a 0-indexed integer array nums, find the leftmost middleIndex (i.e., the smallest amongst + * all the possible ones). + * + * A middleIndex is an index where nums[0] + nums[1] + ... + + * nums[middleIndex-1] == nums[middleIndex+1] + nums[middleIndex+2] + ... + nums[nums.length-1]. + * + * If middleIndex == 0, the left side sum is considered to be 0. Similarly, if + * middleIndex == nums.length - 1, the right side sum is considered to be 0. + * + * Return the leftmost middleIndex that satisfies the condition, or -1 if there is no such index. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var findMiddleIndex = function(nums) { + let left = 0; + let right = nums.reduce((sum, n) => sum + n, 0); + + for (let i = 0; i < nums.length; i++) { + left += nums[i]; + right -= nums[i]; + if (left - nums[i] === right) { + return i; + } + } + + return -1; +}; diff --git a/solutions/1992-find-all-groups-of-farmland.js b/solutions/1992-find-all-groups-of-farmland.js new file mode 100644 index 00000000..0e39fd7f --- /dev/null +++ b/solutions/1992-find-all-groups-of-farmland.js @@ -0,0 +1,55 @@ +/** + * 1992. Find All Groups of Farmland + * https://leetcode.com/problems/find-all-groups-of-farmland/ + * Difficulty: Medium + * + * You are given a 0-indexed m x n binary matrix land where a 0 represents a hectare of forested + * land and a 1 represents a hectare of farmland. + * + * To keep the land organized, there are designated rectangular areas of hectares that consist + * entirely of farmland. These rectangular areas are called groups. No two groups are adjacent, + * meaning farmland in one group is not four-directionally adjacent to another farmland in a + * different group. + * + * land can be represented by a coordinate system where the top left corner of land is (0, 0) + * and the bottom right corner of land is (m-1, n-1). Find the coordinates of the top left and + * bottom right corner of each group of farmland. A group of farmland with a top left corner + * at (r1, c1) and a bottom right corner at (r2, c2) is represented by the 4-length + * array [r1, c1, r2, c2]. + * + * Return a 2D array containing the 4-length arrays described above for each group of farmland + * in land. If there are no groups of farmland, return an empty array. You may return the answer + * in any order. + */ + +/** + * @param {number[][]} land + * @return {number[][]} + */ +var findFarmland = function(land) { + const m = land.length; + const n = land[0].length; + const result = []; + + for (let r = 0; r < m; r++) { + for (let c = 0; c < n; c++) { + if (land[r][c] === 1) { + let r2 = r; + let c2 = c; + + while (r2 + 1 < m && land[r2 + 1][c] === 1) r2++; + while (c2 + 1 < n && land[r][c2 + 1] === 1) c2++; + + result.push([r, c, r2, c2]); + + for (let i = r; i <= r2; i++) { + for (let j = c; j <= c2; j++) { + land[i][j] = 0; + } + } + } + } + } + + return result; +}; diff --git a/solutions/1993-operations-on-tree.js b/solutions/1993-operations-on-tree.js new file mode 100644 index 00000000..e1f5952c --- /dev/null +++ b/solutions/1993-operations-on-tree.js @@ -0,0 +1,101 @@ +/** + * 1993. Operations on Tree + * https://leetcode.com/problems/operations-on-tree/ + * Difficulty: Medium + * + * You are given a tree with n nodes numbered from 0 to n - 1 in the form of a parent array + * parent where parent[i] is the parent of the ith node. The root of the tree is node 0, + * so parent[0] = -1 since it has no parent. You want to design a data structure that + * allows users to lock, unlock, and upgrade nodes in the tree. + * + * The data structure should support the following functions: + * - Lock: Locks the given node for the given user and prevents other users from locking + * the same node. You may only lock a node using this function if the node is unlocked. + * - Unlock: Unlocks the given node for the given user. You may only unlock a node using + * this function if it is currently locked by the same user. + * - Upgrade: Locks the given node for the given user and unlocks all of its descendants + * regardless of who locked it. You may only upgrade a node if all 3 conditions are true: + * - The node is unlocked, + * - It has at least one locked descendant (by any user), and + * - It does not have any locked ancestors. + * + * Implement the LockingTree class: + * - LockingTree(int[] parent) initializes the data structure with the parent array. + * - lock(int num, int user) returns true if it is possible for the user with id user to lock + * the node num, or false otherwise. If it is possible, the node num will become locked by + * the user with id user. + * - unlock(int num, int user) returns true if it is possible for the user with id user to + * unlock the node num, or false otherwise. If it is possible, the node num will become unlocked. + * - upgrade(int num, int user) returns true if it is possible for the user with id user to + * upgrade the node num, or false otherwise. If it is possible, the node num will be upgraded. + */ + +/** + * @param {number[]} parent + */ +var LockingTree = function(parent) { + this.parent = parent; + this.locked = new Map(); + this.children = new Array(parent.length).fill().map(() => []); + for (let i = 1; i < parent.length; i++) { + this.children[parent[i]].push(i); + } +}; + +/** + * @param {number} num + * @param {number} user + * @return {boolean} + */ +LockingTree.prototype.lock = function(num, user) { + if (this.locked.has(num)) return false; + this.locked.set(num, user); + return true; +}; + +/** + * @param {number} num + * @param {number} user + * @return {boolean} + */ +LockingTree.prototype.unlock = function(num, user) { + if (!this.locked.has(num) || this.locked.get(num) !== user) return false; + this.locked.delete(num); + return true; +}; + +/** + * @param {number} num + * @param {number} user + * @return {boolean} + */ +LockingTree.prototype.upgrade = function(num, user) { + if (this.locked.has(num)) return false; + + let node = num; + while (node !== -1) { + if (this.locked.has(node)) return false; + node = this.parent[node]; + } + + const descendants = []; + const queue = [num]; + let hasLockedDescendant = false; + + while (queue.length) { + const curr = queue.shift(); + if (this.locked.has(curr)) { + hasLockedDescendant = true; + descendants.push(curr); + } + queue.push(...this.children[curr]); + } + + if (!hasLockedDescendant) return false; + + for (const descendant of descendants) { + this.locked.delete(descendant); + } + this.locked.set(num, user); + return true; +}; diff --git a/solutions/1994-the-number-of-good-subsets.js b/solutions/1994-the-number-of-good-subsets.js new file mode 100644 index 00000000..7fb63535 --- /dev/null +++ b/solutions/1994-the-number-of-good-subsets.js @@ -0,0 +1,75 @@ +/** + * 1994. The Number of Good Subsets + * https://leetcode.com/problems/the-number-of-good-subsets/ + * Difficulty: Hard + * + * You are given an integer array nums. We call a subset of nums good if its product can be + * represented as a product of one or more distinct prime numbers. + * + * - For example, if nums = [1, 2, 3, 4]: + * - [2, 3], [1, 2, 3], and [1, 3] are good subsets with products 6 = 2*3, 6 = 2*3, and 3 = 3 + * respectively. + * - [1, 4] and [4] are not good subsets with products 4 = 2*2 and 4 = 2*2 respectively. + * + * Return the number of different good subsets in nums modulo 109 + 7. + * + * A subset of nums is any array that can be obtained by deleting some (possibly none or all) + * elements from nums. Two subsets are different if and only if the chosen indices to delete + * are different. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var numberOfGoodSubsets = function(nums) { + const MOD = 1e9 + 7; + const primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]; + const freq = new Array(31).fill(0); + for (const num of nums) { + freq[num]++; + } + + const dp = new Array(1 << primes.length).fill(0); + dp[0] = 1; + for (let i = 0; i < freq[1]; i++) { + dp[0] = (dp[0] * 2) % MOD; + } + + for (let num = 2; num <= 30; num++) { + if (freq[num] === 0) continue; + let mask = 0; + let valid = true; + for (let i = 0; i < primes.length; i++) { + let count = 0; + let temp = num; + while (temp % primes[i] === 0) { + count++; + temp /= primes[i]; + } + if (count > 1) { + valid = false; + break; + } + if (count === 1) { + mask |= 1 << i; + } + } + + if (!valid) continue; + + const prev = dp.slice(); + for (let j = 0; j < 1 << primes.length; j++) { + if ((j & mask) === 0) { + dp[j | mask] = (dp[j | mask] + prev[j] * freq[num]) % MOD; + } + } + } + + let result = 0; + for (let i = 1; i < 1 << primes.length; i++) { + result = (result + dp[i]) % MOD; + } + + return result; +}; diff --git a/solutions/1995-count-special-quadruplets.js b/solutions/1995-count-special-quadruplets.js new file mode 100644 index 00000000..e37902ac --- /dev/null +++ b/solutions/1995-count-special-quadruplets.js @@ -0,0 +1,31 @@ +/** + * 1995. Count Special Quadruplets + * https://leetcode.com/problems/count-special-quadruplets/ + * Difficulty: Easy + * + * Given a 0-indexed integer array nums, return the number of distinct quadruplets + * (a, b, c, d) such that: + * - nums[a] + nums[b] + nums[c] == nums[d], and + * - a < b < c < d + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var countQuadruplets = function(nums) { + const map = new Map(); + let result = 0; + + for (let c = nums.length - 2; c >= 2; c--) { + map.set(nums[c + 1], (map.get(nums[c + 1]) || 0) + 1); + for (let a = 0; a < c - 1; a++) { + for (let b = a + 1; b < c; b++) { + const sum = nums[a] + nums[b] + nums[c]; + result += map.get(sum) || 0; + } + } + } + + return result; +}; diff --git a/solutions/1997-first-day-where-you-have-been-in-all-the-rooms.js b/solutions/1997-first-day-where-you-have-been-in-all-the-rooms.js new file mode 100644 index 00000000..6dde2362 --- /dev/null +++ b/solutions/1997-first-day-where-you-have-been-in-all-the-rooms.js @@ -0,0 +1,36 @@ +/** + * 1997. First Day Where You Have Been in All the Rooms + * https://leetcode.com/problems/first-day-where-you-have-been-in-all-the-rooms/ + * Difficulty: Medium + * + * There are n rooms you need to visit, labeled from 0 to n - 1. Each day is labeled, starting + * from 0. You will go in and visit one room a day. + * + * Initially on day 0, you visit room 0. The order you visit the rooms for the coming days is + * determined by the following rules and a given 0-indexed array nextVisit of length n: + * - Assuming that on a day, you visit room i, + * - if you have been in room i an odd number of times (including the current visit), on the next + * day you will visit a room with a lower or equal room number specified by nextVisit[i] + * where 0 <= nextVisit[i] <= i; + * - if you have been in room i an even number of times (including the current visit), on the + * next day you will visit room (i + 1) mod n. + * + * Return the label of the first day where you have been in all the rooms. It can be shown + * that such a day exists. Since the answer may be very large, return it modulo 109 + 7. + */ + +/** + * @param {number[]} nextVisit + * @return {number} + */ +var firstDayBeenInAllRooms = function(nextVisit) { + const MOD = 1e9 + 7; + const n = nextVisit.length; + const dp = new Array(n).fill(0); + + for (let i = 1; i < n; i++) { + dp[i] = (2 * dp[i - 1] + 2 - dp[nextVisit[i - 1]] + MOD) % MOD; + } + + return dp[n - 1]; +}; diff --git a/solutions/1998-gcd-sort-of-an-array.js b/solutions/1998-gcd-sort-of-an-array.js new file mode 100644 index 00000000..97bb5a39 --- /dev/null +++ b/solutions/1998-gcd-sort-of-an-array.js @@ -0,0 +1,69 @@ +/** + * 1998. GCD Sort of an Array + * https://leetcode.com/problems/gcd-sort-of-an-array/ + * Difficulty: Hard + * + * You are given an integer array nums, and you can perform the following operation any + * number of times on nums: + * - Swap the positions of two elements nums[i] and nums[j] if gcd(nums[i], nums[j]) > 1 + * where gcd(nums[i], nums[j]) is the greatest common divisor of nums[i] and nums[j]. + * + * Return true if it is possible to sort nums in non-decreasing order using the above swap + * method, or false otherwise. + */ + +/** + * @param {number[]} nums + * @return {boolean} + */ +var gcdSort = function(nums) { + const maxNum = Math.max(...nums); + const parent = new Array(maxNum + 1).fill().map((_, i) => i); + const minPrime = new Array(maxNum + 1).fill(0); + for (let i = 2; i <= maxNum; i++) { + if (minPrime[i] === 0) { + for (let j = i; j <= maxNum; j += i) { + minPrime[j] = i; + } + } + } + + const groups = new Map(); + for (const num of nums) { + let curr = num; + const primes = new Set(); + while (curr > 1) { + const prime = minPrime[curr]; + primes.add(prime); + curr /= prime; + } + for (const prime of primes) { + if (!groups.has(prime)) groups.set(prime, []); + groups.get(prime).push(num); + } + } + + for (const numbers of groups.values()) { + for (let i = 1; i < numbers.length; i++) { + union(numbers[i - 1], numbers[i], parent); + } + } + + const sorted = [...nums].sort((a, b) => a - b); + for (let i = 0; i < nums.length; i++) { + if (find(nums[i], parent) !== find(sorted[i], parent)) { + return false; + } + } + + return true; + + function find(x, parent) { + if (parent[x] !== x) parent[x] = find(parent[x], parent); + return parent[x]; + } + + function union(x, y, parent) { + parent[find(x, parent)] = find(y, parent); + } +}; 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/2001-number-of-pairs-of-interchangeable-rectangles.js b/solutions/2001-number-of-pairs-of-interchangeable-rectangles.js new file mode 100644 index 00000000..89f2611e --- /dev/null +++ b/solutions/2001-number-of-pairs-of-interchangeable-rectangles.js @@ -0,0 +1,38 @@ +/** + * 2001. Number of Pairs of Interchangeable Rectangles + * https://leetcode.com/problems/number-of-pairs-of-interchangeable-rectangles/ + * Difficulty: Medium + * + * You are given n rectangles represented by a 0-indexed 2D integer array rectangles, + * where rectangles[i] = [widthi, heighti] denotes the width and height of the ith rectangle. + * + * Two rectangles i and j (i < j) are considered interchangeable if they have the same + * width-to-height ratio. More formally, two rectangles are interchangeable if + * widthi/heighti == widthj/heightj (using decimal division, not integer division). + * + * Return the number of pairs of interchangeable rectangles in rectangles. + */ + +/** + * @param {number[][]} rectangles + * @return {number} + */ +var interchangeableRectangles = function(rectangles) { + const map = new Map(); + let result = 0; + + for (const [width, height] of rectangles) { + const gcd = (a, b) => b === 0 ? a : gcd(b, a % b); + const divisor = gcd(width, height); + const ratio = `${width / divisor}/${height / divisor}`; + + if (map.has(ratio)) { + result += map.get(ratio); + map.set(ratio, map.get(ratio) + 1); + } else { + map.set(ratio, 1); + } + } + + return result; +}; diff --git a/solutions/2002-maximum-product-of-the-length-of-two-palindromic-subsequences.js b/solutions/2002-maximum-product-of-the-length-of-two-palindromic-subsequences.js new file mode 100644 index 00000000..ae489e83 --- /dev/null +++ b/solutions/2002-maximum-product-of-the-length-of-two-palindromic-subsequences.js @@ -0,0 +1,50 @@ +/** + * 2002. Maximum Product of the Length of Two Palindromic Subsequences + * https://leetcode.com/problems/maximum-product-of-the-length-of-two-palindromic-subsequences/ + * Difficulty: Medium + * + * Given a string s, find two disjoint palindromic subsequences of s such that the product of their + * lengths is maximized. The two subsequences are disjoint if they do not both pick a character at + * the same index. + * + * Return the maximum possible product of the lengths of the two palindromic subsequences. + * + * 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. A string is palindromic + * if it reads the same forward and backward. + */ + +/** + * @param {string} s + * @return {number} + */ +var maxProduct = function(s) { + const n = s.length; + let result = 0; + + for (let mask1 = 1; mask1 < (1 << n); mask1++) { + for (let mask2 = 1; mask2 < (1 << n); mask2++) { + if (mask1 & mask2) continue; + const len1 = isPalindrome(s, mask1); + if (len1 === 0) continue; + const len2 = isPalindrome(s, mask2); + if (len2 === 0) continue; + result = Math.max(result, len1 * len2); + } + } + + return result; + + function isPalindrome(str, mask) { + const chars = []; + for (let i = 0; i < n; i++) { + if (mask & (1 << i)) chars.push(str[i]); + } + let left = 0; + let right = chars.length - 1; + while (left < right) { + if (chars[left++] !== chars[right--]) return 0; + } + return chars.length; + } +}; diff --git a/solutions/2003-smallest-missing-genetic-value-in-each-subtree.js b/solutions/2003-smallest-missing-genetic-value-in-each-subtree.js new file mode 100644 index 00000000..f57b89d8 --- /dev/null +++ b/solutions/2003-smallest-missing-genetic-value-in-each-subtree.js @@ -0,0 +1,55 @@ +/** + * 2003. Smallest Missing Genetic Value in Each Subtree + * https://leetcode.com/problems/smallest-missing-genetic-value-in-each-subtree/ + * Difficulty: Hard + * + * There is a family tree rooted at 0 consisting of n nodes numbered 0 to n - 1. You are given a + * 0-indexed integer array parents, where parents[i] is the parent for node i. Since node 0 is + * the root, parents[0] == -1. + * + * There are 105 genetic values, each represented by an integer in the inclusive range [1, 105]. + * You are given a 0-indexed integer array nums, where nums[i] is a distinct genetic value for + * node i. + * + * Return an array ans of length n where ans[i] is the smallest genetic value that is missing + * from the subtree rooted at node i. + * + * The subtree rooted at a node x contains node x and all of its descendant nodes. + */ + +/** + * @param {number[]} parents + * @param {number[]} nums + * @return {number[]} + */ +var smallestMissingValueSubtree = function(parents, nums) { + const n = parents.length; + const result = new Array(n).fill(1); + const children = Array.from({ length: n }, () => []); + const seen = new Set(); + let maxMissing = 1; + + for (let i = 1; i < n; i++) { + children[parents[i]].push(i); + } + + const nodeWithOne = nums.indexOf(1); + if (nodeWithOne === -1) return result; + + let current = nodeWithOne; + while (current !== -1) { + const stack = [current]; + while (stack.length) { + const node = stack.pop(); + seen.add(nums[node]); + for (const child of children[node]) { + if (!seen.has(nums[child])) stack.push(child); + } + } + while (seen.has(maxMissing)) maxMissing++; + result[current] = maxMissing; + current = parents[current]; + } + + return result; +}; 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/2006-count-number-of-pairs-with-absolute-difference-k.js b/solutions/2006-count-number-of-pairs-with-absolute-difference-k.js new file mode 100644 index 00000000..022c9b4d --- /dev/null +++ b/solutions/2006-count-number-of-pairs-with-absolute-difference-k.js @@ -0,0 +1,29 @@ +/** + * 2006. Count Number of Pairs With Absolute Difference K + * https://leetcode.com/problems/count-number-of-pairs-with-absolute-difference-k/ + * Difficulty: Easy + * + * Given an integer array nums and an integer k, return the number of pairs (i, j) where + * i < j such that |nums[i] - nums[j]| == k. + * + * The value of |x| is defined as: + * - x if x >= 0. + * - -x if x < 0. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var countKDifference = function(nums, k) { + const map = new Map(); + let result = 0; + + for (const num of nums) { + result += (map.get(num - k) || 0) + (map.get(num + k) || 0); + map.set(num, (map.get(num) || 0) + 1); + } + + return result; +}; diff --git a/solutions/2007-find-original-array-from-doubled-array.js b/solutions/2007-find-original-array-from-doubled-array.js new file mode 100644 index 00000000..ca1d1357 --- /dev/null +++ b/solutions/2007-find-original-array-from-doubled-array.js @@ -0,0 +1,42 @@ +/** + * 2007. Find Original Array From Doubled Array + * https://leetcode.com/problems/find-original-array-from-doubled-array/ + * Difficulty: Medium + * + * An integer array original is transformed into a doubled array changed by appending twice the + * value of every element in original, and then randomly shuffling the resulting array. + * + * Given an array changed, return original if changed is a doubled array. If changed is not a + * doubled array, return an empty array. The elements in original may be returned in any order. + */ + +/** + * @param {number[]} changed + * @return {number[]} + */ +var findOriginalArray = function(changed) { + if (changed.length % 2 !== 0) return []; + + const frequency = new Map(); + const result = []; + + changed.sort((a, b) => a - b); + + for (const num of changed) { + frequency.set(num, (frequency.get(num) || 0) + 1); + } + + for (const num of changed) { + if (frequency.get(num) === 0) continue; + + frequency.set(num, frequency.get(num) - 1); + + const doubled = num * 2; + if (!frequency.has(doubled) || frequency.get(doubled) === 0) return []; + + frequency.set(doubled, frequency.get(doubled) - 1); + result.push(num); + } + + return result; +}; diff --git a/solutions/2008-maximum-earnings-from-taxi.js b/solutions/2008-maximum-earnings-from-taxi.js new file mode 100644 index 00000000..fd7cbaac --- /dev/null +++ b/solutions/2008-maximum-earnings-from-taxi.js @@ -0,0 +1,43 @@ +/** + * 2008. Maximum Earnings From Taxi + * https://leetcode.com/problems/maximum-earnings-from-taxi/ + * Difficulty: Medium + * + * There are n points on a road you are driving your taxi on. The n points on the road are + * labeled from 1 to n in the direction you are going, and you want to drive from point 1 + * to point n to make money by picking up passengers. You cannot change the direction of the taxi. + * + * The passengers are represented by a 0-indexed 2D integer array rides, where + * rides[i] = [starti, endi, tipi] denotes the ith passenger requesting a ride from point + * starti to point endi who is willing to give a tipi dollar tip. + * + * For each passenger i you pick up, you earn endi - starti + tipi dollars. You may only drive + * at most one passenger at a time. + * + * Given n and rides, return the maximum number of dollars you can earn by picking up the + * passengers optimally. + * + * Note: You may drop off a passenger and pick up a different passenger at the same point. + */ + +/** + * @param {number} n + * @param {number[][]} rides + * @return {number} + */ +var maxTaxiEarnings = function(n, rides) { + rides.sort((a, b) => a[1] - b[1]); + const dp = new Array(n + 1).fill(0); + let rideIndex = 0; + + for (let point = 1; point <= n; point++) { + dp[point] = dp[point - 1]; + while (rideIndex < rides.length && rides[rideIndex][1] === point) { + const [start, end, tip] = rides[rideIndex]; + dp[point] = Math.max(dp[point], dp[start] + (end - start + tip)); + rideIndex++; + } + } + + return dp[n]; +}; diff --git a/solutions/2009-minimum-number-of-operations-to-make-array-continuous.js b/solutions/2009-minimum-number-of-operations-to-make-array-continuous.js new file mode 100644 index 00000000..d4cd063e --- /dev/null +++ b/solutions/2009-minimum-number-of-operations-to-make-array-continuous.js @@ -0,0 +1,36 @@ +/** + * 2009. Minimum Number of Operations to Make Array Continuous + * https://leetcode.com/problems/minimum-number-of-operations-to-make-array-continuous/ + * Difficulty: Hard + * + * You are given an integer array nums. In one operation, you can replace any element in nums + * with any integer. + * + * nums is considered continuous if both of the following conditions are fulfilled: + * - All elements in nums are unique. + * - The difference between the maximum element and the minimum element in nums equals + * nums.length - 1. + * + * For example, nums = [4, 2, 5, 3] is continuous, but nums = [1, 2, 3, 5, 6] is not continuous. + * + * Return the minimum number of operations to make nums continuous. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minOperations = function(nums) { + const n = nums.length; + const uniqueNums = [...new Set(nums)].sort((a, b) => a - b); + let result = n; + + for (let i = 0, j = 0; i < uniqueNums.length; i++) { + while (j < uniqueNums.length && uniqueNums[j] - uniqueNums[i] <= n - 1) { + j++; + } + result = Math.min(result, n - (j - i)); + } + + return result; +}; diff --git a/solutions/2012-sum-of-beauty-in-the-array.js b/solutions/2012-sum-of-beauty-in-the-array.js new file mode 100644 index 00000000..957da790 --- /dev/null +++ b/solutions/2012-sum-of-beauty-in-the-array.js @@ -0,0 +1,42 @@ +/** + * 2012. Sum of Beauty in the Array + * https://leetcode.com/problems/sum-of-beauty-in-the-array/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums. For each index i (1 <= i <= nums.length - 2) + * the beauty of nums[i] equals: + * - 2, if nums[j] < nums[i] < nums[k], for all 0 <= j < i and for all i < k <= nums.length - 1. + * - 1, if nums[i - 1] < nums[i] < nums[i + 1], and the previous condition is not satisfied. + * - 0, if none of the previous conditions holds. + * + * Return the sum of beauty of all nums[i] where 1 <= i <= nums.length - 2. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var sumOfBeauties = function(nums) { + const n = nums.length; + let result = 0; + const leftMax = new Array(n).fill(nums[0]); + const rightMin = new Array(n).fill(nums[n - 1]); + + for (let i = 1; i < n; i++) { + leftMax[i] = Math.max(leftMax[i - 1], nums[i - 1]); + } + + for (let i = n - 2; i >= 0; i--) { + rightMin[i] = Math.min(rightMin[i + 1], nums[i + 1]); + } + + for (let i = 1; i < n - 1; i++) { + if (leftMax[i] < nums[i] && nums[i] < rightMin[i]) { + result += 2; + } else if (nums[i - 1] < nums[i] && nums[i] < nums[i + 1]) { + result += 1; + } + } + + return result; +}; diff --git a/solutions/2013-detect-squares.js b/solutions/2013-detect-squares.js new file mode 100644 index 00000000..606076c3 --- /dev/null +++ b/solutions/2013-detect-squares.js @@ -0,0 +1,54 @@ +/** + * 2013. Detect Squares + * https://leetcode.com/problems/detect-squares/ + * Difficulty: Medium + * + * You are given a stream of points on the X-Y plane. Design an algorithm that: + * - Adds new points from the stream into a data structure. Duplicate points are allowed and should + * be treated as different points. + * - Given a query point, counts the number of ways to choose three points from the data structure + * such that the three points and the query point form an axis-aligned square with positive area. + * + * An axis-aligned square is a square whose edges are all the same length and are either parallel + * or perpendicular to the x-axis and y-axis. + * + * Implement the DetectSquares class: + * - DetectSquares() Initializes the object with an empty data structure. + * - void add(int[] point) Adds a new point point = [x, y] to the data structure. + * - int count(int[] point) Counts the number of ways to form axis-aligned squares with point + * point = [x, y] as described above. + */ + +var DetectSquares = function() { + this.points = new Map(); +}; + +/** + * @param {number[]} point + * @return {void} + */ +DetectSquares.prototype.add = function(point) { + const [x, y] = point; + const key = `${x},${y}`; + this.points.set(key, (this.points.get(key) || 0) + 1); +}; + +/** + * @param {number[]} point + * @return {number} + */ +DetectSquares.prototype.count = function(point) { + const [x, y] = point; + let result = 0; + + for (const [key, count] of this.points) { + const [px, py] = key.split(',').map(Number); + if (px === x || py === y || Math.abs(px - x) !== Math.abs(py - y)) continue; + + const point1 = `${x},${py}`; + const point2 = `${px},${y}`; + result += count * (this.points.get(point1) || 0) * (this.points.get(point2) || 0); + } + + return result; +}; diff --git a/solutions/2014-longest-subsequence-repeated-k-times.js b/solutions/2014-longest-subsequence-repeated-k-times.js new file mode 100644 index 00000000..ec575695 --- /dev/null +++ b/solutions/2014-longest-subsequence-repeated-k-times.js @@ -0,0 +1,64 @@ +/** + * 2014. Longest Subsequence Repeated k Times + * https://leetcode.com/problems/longest-subsequence-repeated-k-times/ + * Difficulty: Hard + * + * You are given a string s of length n, and an integer k. You are tasked to find the longest + * subsequence repeated k times in string s. + * + * 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. + * + * A subsequence seq is repeated k times in the string s if seq * k is a subsequence of s, + * where seq * k represents a string constructed by concatenating seq k times. + * - For example, "bba" is repeated 2 times in the string "bababcba", because the string + * "bbabba", constructed by concatenating "bba" 2 times, is a subsequence of the + * string "bababcba". + * + * Return the longest subsequence repeated k times in string s. If multiple such subsequences + * are found, return the lexicographically largest one. If there is no such subsequence, + * return an empty string. + */ + +/** + * @param {string} s + * @param {number} k + * @return {string} + */ +var longestSubsequenceRepeatedK = function(s, k) { + const n = s.length; + const freq = new Array(26).fill(0); + for (const char of s) { + freq[char.charCodeAt(0) - 97]++; + } + + let candidates = ''; + for (let i = 0; i < 26; i++) { + const count = Math.floor(freq[i] / k); + candidates += String.fromCharCode(97 + i).repeat(count); + } + + function canFormSubsequence(seq) { + let j = 0; + for (let i = 0; i < n && j < seq.length * k; i++) { + if (s[i] === seq[j % seq.length]) j++; + } + return j >= seq.length * k; + } + + let result = ''; + backtrack('', candidates); + return result; + + function backtrack(curr, remaining) { + if (curr.length > result.length || (curr.length === result.length && curr > result)) { + if (canFormSubsequence(curr)) result = curr; + } + if (!remaining) return; + + for (let i = remaining.length - 1; i >= 0; i--) { + const nextChar = remaining[i]; + backtrack(curr + nextChar, remaining.slice(0, i) + remaining.slice(i + 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/2018-check-if-word-can-be-placed-in-crossword.js b/solutions/2018-check-if-word-can-be-placed-in-crossword.js new file mode 100644 index 00000000..0a22bd5c --- /dev/null +++ b/solutions/2018-check-if-word-can-be-placed-in-crossword.js @@ -0,0 +1,66 @@ +/** + * 2018. Check if Word Can Be Placed In Crossword + * https://leetcode.com/problems/check-if-word-can-be-placed-in-crossword/ + * Difficulty: Medium + * + * You are given an m x n matrix board, representing the current state of a crossword puzzle. + * The crossword contains lowercase English letters (from solved words), ' ' to represent any + * empty cells, and '#' to represent any blocked cells. + * + * A word can be placed horizontally (left to right or right to left) or vertically (top to + * bottom or bottom to top) in the board if: + * - It does not occupy a cell containing the character '#'. + * - The cell each letter is placed in must either be ' ' (empty) or match the letter already + * on the board. + * - There must not be any empty cells ' ' or other lowercase letters directly left or right + * of the word if the word was placed horizontally. + * - There must not be any empty cells ' ' or other lowercase letters directly above or below + * the word if the word was placed vertically. + * + * Given a string word, return true if word can be placed in board, or false otherwise. + */ + +/** + * @param {character[][]} board + * @param {string} word + * @return {boolean} + */ +var placeWordInCrossword = function(board, word) { + const rows = board.length; + const cols = board[0].length; + const wordLen = word.length; + + function canPlace(row, col, dr, dc) { + for (let i = 0; i < wordLen; i++) { + const r = row + i * dr; + const c = col + i * dc; + if (r < 0 || r >= rows || c < 0 || c >= cols || board[r][c] === '#') return false; + if (board[r][c] !== ' ' && board[r][c] !== word[i]) return false; + } + + const beforeR = row - dr; + const beforeC = col - dc; + const afterR = row + wordLen * dr; + const afterC = col + wordLen * dc; + + if ((beforeR >= 0 && beforeR < rows && beforeC >= 0 + && beforeC < cols && board[beforeR][beforeC] !== '#') + || (afterR >= 0 && afterR < rows && afterC >= 0 + && afterC < cols && board[afterR][afterC] !== '#')) { + return false; + } + + return true; + } + + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + if (canPlace(r, c, 0, 1) || canPlace(r, c, 0, -1) + || canPlace(r, c, 1, 0) || canPlace(r, c, -1, 0)) { + return true; + } + } + } + + return false; +}; diff --git a/solutions/2019-the-score-of-students-solving-math-expression.js b/solutions/2019-the-score-of-students-solving-math-expression.js new file mode 100644 index 00000000..b4391da2 --- /dev/null +++ b/solutions/2019-the-score-of-students-solving-math-expression.js @@ -0,0 +1,72 @@ +/** + * 2019. The Score of Students Solving Math Expression + * https://leetcode.com/problems/the-score-of-students-solving-math-expression/ + * Difficulty: Hard + * + * You are given a string s that contains digits 0-9, addition symbols '+', and multiplication + * symbols '*' only, representing a valid math expression of single digit numbers (e.g., 3+5*2). + * This expression was given to n elementary school students. The students were instructed to + * get the answer of the expression by following this order of operations: + * 1. Compute multiplication, reading from left to right; Then, + * 2. Compute addition, reading from left to right. + * + * You are given an integer array answers of length n, which are the submitted answers of the + * students in no particular order. You are asked to grade the answers, by following these rules: + * - If an answer equals the correct answer of the expression, this student will be rewarded + * 5 points; + * - Otherwise, if the answer could be interpreted as if the student applied the operators in + * the wrong order but had correct arithmetic, this student will be rewarded 2 points; + * - Otherwise, this student will be rewarded 0 points. + * + * Return the sum of the points of the students. + */ + +/** + * @param {string} s + * @param {number[]} answers + * @return {number} + */ +var scoreOfStudents = function(s, answers) { + const correct = eval(s.replace(/(\d)([*+])/g, '$1 $2 ')); + + const n = s.length; + const dp = new Map(); + + function compute(start, end) { + const key = `${start},${end}`; + if (dp.has(key)) return dp.get(key); + + const results = new Set(); + if (start === end) { + results.add(Number(s[start])); + dp.set(key, results); + return results; + } + + for (let i = start + 1; i < end; i += 2) { + const leftResults = compute(start, i - 1); + const rightResults = compute(i + 1, end); + const op = s[i]; + + for (const left of leftResults) { + for (const right of rightResults) { + const val = op === '+' ? left + right : left * right; + if (val <= 1000) results.add(val); + } + } + } + + dp.set(key, results); + return results; + } + + const wrongAnswers = compute(0, n - 1); + let result = 0; + + for (const answer of answers) { + if (answer === correct) result += 5; + else if (wrongAnswers.has(answer)) result += 2; + } + + 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/2022-convert-1d-array-into-2d-array.js b/solutions/2022-convert-1d-array-into-2d-array.js new file mode 100644 index 00000000..a550b710 --- /dev/null +++ b/solutions/2022-convert-1d-array-into-2d-array.js @@ -0,0 +1,33 @@ +/** + * 2022. Convert 1D Array Into 2D Array + * https://leetcode.com/problems/convert-1d-array-into-2d-array/ + * Difficulty: Easy + * + * You are given a 0-indexed 1-dimensional (1D) integer array original, and two integers, + * m and n. You are tasked with creating a 2-dimensional (2D) array with m rows and n + * columns using all the elements from original. + * + * The elements from indices 0 to n - 1 (inclusive) of original should form the first row + * of the constructed 2D array, the elements from indices n to 2 * n - 1 (inclusive) should + * form the second row of the constructed 2D array, and so on. + * + * Return an m x n 2D array constructed according to the above procedure, or an empty 2D array + * if it is impossible. + */ + +/** + * @param {number[]} original + * @param {number} m + * @param {number} n + * @return {number[][]} + */ +var construct2DArray = function(original, m, n) { + if (original.length !== m * n) return []; + + const result = []; + for (let i = 0; i < m; i++) { + result.push(original.slice(i * n, (i + 1) * n)); + } + + return result; +}; diff --git a/solutions/2023-number-of-pairs-of-strings-with-concatenation-equal-to-target.js b/solutions/2023-number-of-pairs-of-strings-with-concatenation-equal-to-target.js new file mode 100644 index 00000000..f2e98de0 --- /dev/null +++ b/solutions/2023-number-of-pairs-of-strings-with-concatenation-equal-to-target.js @@ -0,0 +1,32 @@ +/** + * 2023. Number of Pairs of Strings With Concatenation Equal to Target + * https://leetcode.com/problems/number-of-pairs-of-strings-with-concatenation-equal-to-target/ + * Difficulty: Medium + * + * Given an array of digit strings nums and a digit string target, return the number of pairs of + * indices (i, j) (where i != j) such that the concatenation of nums[i] + nums[j] equals target. + */ + +/** + * @param {string[]} nums + * @param {string} target + * @return {number} + */ +var numOfPairs = function(nums, target) { + const map = new Map(); + let result = 0; + + for (const num of nums) { + if (target.startsWith(num)) { + const suffix = target.slice(num.length); + result += map.get(suffix) || 0; + } + if (target.endsWith(num)) { + const prefix = target.slice(0, target.length - num.length); + result += map.get(prefix) || 0; + } + map.set(num, (map.get(num) || 0) + 1); + } + + return result; +}; diff --git a/solutions/2024-maximize-the-confusion-of-an-exam.js b/solutions/2024-maximize-the-confusion-of-an-exam.js new file mode 100644 index 00000000..f79d25b1 --- /dev/null +++ b/solutions/2024-maximize-the-confusion-of-an-exam.js @@ -0,0 +1,43 @@ +/** + * 2024. Maximize the Confusion of an Exam + * https://leetcode.com/problems/maximize-the-confusion-of-an-exam/ + * Difficulty: Medium + * + * A teacher is writing a test with n true/false questions, with 'T' denoting true and 'F' denoting + * false. He wants to confuse the students by maximizing the number of consecutive questions with + * the same answer (multiple trues or multiple falses in a row). + * + * You are given a string answerKey, where answerKey[i] is the original answer to the ith question. + * In addition, you are given an integer k, the maximum number of times you may perform the + * following operation: + * - Change the answer key for any question to 'T' or 'F' (i.e., set answerKey[i] to 'T' or 'F'). + * + * Return the maximum number of consecutive 'T's or 'F's in the answer key after performing the + * operation at most k times. + */ + +/** + * @param {string} answerKey + * @param {number} k + * @return {number} + */ +var maxConsecutiveAnswers = function(answerKey, k) { + const flipsLeft = k; + const count = { T: 0, F: 0 }; + let result = 0; + let left = 0; + + for (let right = 0; right < answerKey.length; right++) { + count[answerKey[right]]++; + const maxCount = Math.max(count.T, count.F); + + while (right - left + 1 - maxCount > flipsLeft) { + count[answerKey[left]]--; + left++; + } + + result = Math.max(result, right - left + 1); + } + + return result; +}; diff --git a/solutions/2025-maximum-number-of-ways-to-partition-an-array.js b/solutions/2025-maximum-number-of-ways-to-partition-an-array.js new file mode 100644 index 00000000..2e28cd39 --- /dev/null +++ b/solutions/2025-maximum-number-of-ways-to-partition-an-array.js @@ -0,0 +1,57 @@ +/** + * 2025. Maximum Number of Ways to Partition an Array + * https://leetcode.com/problems/maximum-number-of-ways-to-partition-an-array/ + * Difficulty: Hard + * + * You are given a 0-indexed integer array nums of length n. The number of ways to partition + * nums is the number of pivot indices that satisfy both conditions: + * - 1 <= pivot < n + * - nums[0] + nums[1] + ... + nums[pivot - 1] == nums[pivot] + nums[pivot + 1] + ... + nums[n - 1] + * + * You are also given an integer k. You can choose to change the value of one element of nums to + * k, or to leave the array unchanged. + * + * Return the maximum possible number of ways to partition nums to satisfy both conditions after + * changing at most one element. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number} + */ +var waysToPartition = function(nums, k) { + const n = nums.length; + const prefixSums = [nums[0]]; + const leftDiffs = new Map(); + const rightDiffs = new Map(); + + for (let i = 1; i < n; i++) { + prefixSums[i] = prefixSums[i - 1] + nums[i]; + const diff = prefixSums[i - 1]; + rightDiffs.set(diff, (rightDiffs.get(diff) || 0) + 1); + } + + const totalSum = prefixSums[n - 1]; + let result = totalSum % 2 === 0 ? (rightDiffs.get(totalSum / 2) || 0) : 0; + + for (let i = 0; i < n; i++) { + const delta = k - nums[i]; + const newTotalSum = totalSum + delta; + + if (newTotalSum % 2 === 0) { + const targetSum = newTotalSum / 2; + const waysFromLeft = leftDiffs.get(targetSum) || 0; + const waysFromRight = rightDiffs.get(targetSum - delta) || 0; + result = Math.max(result, waysFromLeft + waysFromRight); + } + + if (i < n - 1) { + const currentDiff = prefixSums[i]; + leftDiffs.set(currentDiff, (leftDiffs.get(currentDiff) || 0) + 1); + rightDiffs.set(currentDiff, rightDiffs.get(currentDiff) - 1); + } + } + + return result; +}; diff --git a/solutions/2028-find-missing-observations.js b/solutions/2028-find-missing-observations.js new file mode 100644 index 00000000..29296fbc --- /dev/null +++ b/solutions/2028-find-missing-observations.js @@ -0,0 +1,49 @@ +/** + * 2028. Find Missing Observations + * https://leetcode.com/problems/find-missing-observations/ + * Difficulty: Medium + * + * You have observations of n + m 6-sided dice rolls with each face numbered from 1 to 6. n + * of the observations went missing, and you only have the observations of m rolls. + * Fortunately, you have also calculated the average value of the n + m rolls. + * + * You are given an integer array rolls of length m where rolls[i] is the value of the ith + * observation. You are also given the two integers mean and n. + * + * Return an array of length n containing the missing observations such that the average + * value of the n + m rolls is exactly mean. If there are multiple valid answers, return + * any of them. If no such array exists, return an empty array. + * + * The average value of a set of k numbers is the sum of the numbers divided by k. + * + * Note that mean is an integer, so the sum of the n + m rolls should be divisible by n + m. + */ + +/** + * @param {number[]} rolls + * @param {number} mean + * @param {number} n + * @return {number[]} + */ +var missingRolls = function(rolls, mean, n) { + const totalRolls = rolls.length + n; + const targetSum = mean * totalRolls; + const currentSum = rolls.reduce((sum, roll) => sum + roll, 0); + const missingSum = targetSum - currentSum; + + if (missingSum < n || missingSum > 6 * n) return []; + + const baseValue = Math.floor(missingSum / n); + const remainder = missingSum % n; + const result = []; + + for (let i = 0; i < n; i++) { + if (i < remainder) { + result.push(baseValue + 1); + } else { + result.push(baseValue); + } + } + + return result; +}; diff --git a/solutions/2029-stone-game-ix.js b/solutions/2029-stone-game-ix.js new file mode 100644 index 00000000..31ea3bb8 --- /dev/null +++ b/solutions/2029-stone-game-ix.js @@ -0,0 +1,33 @@ +/** + * 2029. Stone Game IX + * https://leetcode.com/problems/stone-game-ix/ + * Difficulty: Medium + * + * Alice and Bob continue their games with stones. There is a row of n stones, and each stone has + * an associated value. You are given an integer array stones, where stones[i] is the value of the + * ith stone. + * + * Alice and Bob take turns, with Alice starting first. On each turn, the player may remove any + * stone from stones. The player who removes a stone loses if the sum of the values of all + * removed stones is divisible by 3. Bob will win automatically if there are no remaining stones + * (even if it is Alice's turn). + * + * Assuming both players play optimally, return true if Alice wins and false if Bob wins. + */ + +/** + * @param {number[]} stones + * @return {boolean} + */ +var stoneGameIX = function(stones) { + const remainderCount = [0, 0, 0]; + for (const stone of stones) { + remainderCount[stone % 3]++; + } + + if (remainderCount[0] % 2 === 0) { + return remainderCount[1] >= 1 && remainderCount[2] >= 1; + } + + return Math.abs(remainderCount[1] - remainderCount[2]) > 2; +}; diff --git a/solutions/2030-smallest-k-length-subsequence-with-occurrences-of-a-letter.js b/solutions/2030-smallest-k-length-subsequence-with-occurrences-of-a-letter.js new file mode 100644 index 00000000..9e3f916b --- /dev/null +++ b/solutions/2030-smallest-k-length-subsequence-with-occurrences-of-a-letter.js @@ -0,0 +1,83 @@ +/** + * 2030. Smallest K-Length Subsequence With Occurrences of a Letter + * https://leetcode.com/problems/smallest-k-length-subsequence-with-occurrences-of-a-letter/ + * Difficulty: Hard + * + * You are given a string s, an integer k, a letter letter, and an integer repetition. + * + * Return the lexicographically smallest subsequence of s of length k that has the letter + * letter appear at least repetition times. The test cases are generated so that the letter + * appears in s at least repetition times. + * + * 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. + * + * 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. + */ + +/** + * @param {string} s + * @param {number} k + * @param {character} letter + * @param {number} repetition + * @return {string} + */ +var smallestSubsequence = function(s, k, letter, repetition) { + const n = s.length; + let letterTotal = 0; + for (let i = 0; i < n; i++) { + if (s[i] === letter) letterTotal++; + } + + const stack = []; + let stackLetterCount = 0; + let remainingCount = letterTotal; + + for (let i = 0; i < n; i++) { + const char = s[i]; + + if (char === letter) { + remainingCount--; + } + + while ( + stack.length > 0 && stack[stack.length - 1] > char && stack.length - 1 + (n - i) >= k + && (stack[stack.length - 1] !== letter || stackLetterCount + remainingCount > repetition) + ) { + if (stack[stack.length - 1] === letter) { + stackLetterCount--; + } + stack.pop(); + } + + if (stack.length < k) { + if (char === letter) { + stackLetterCount++; + } + + const neededLetters = repetition - stackLetterCount; + const remainingPositions = k - stack.length - 1; + if (char === letter || remainingPositions >= neededLetters) { + stack.push(char); + } + } + } + + if (stackLetterCount < repetition) { + let missingLetters = repetition - stackLetterCount; + const result = [...stack]; + + for (let i = k - 1; i >= 0 && missingLetters > 0; i--) { + if (result[i] !== letter) { + result[i] = letter; + missingLetters--; + } + } + + return result.join(''); + } + + return stack.join(''); +}; 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/2032-two-out-of-three.js b/solutions/2032-two-out-of-three.js new file mode 100644 index 00000000..566e6033 --- /dev/null +++ b/solutions/2032-two-out-of-three.js @@ -0,0 +1,41 @@ +/** + * 2032. Two Out of Three + * https://leetcode.com/problems/two-out-of-three/ + * Difficulty: Easy + * + * Given three integer arrays nums1, nums2, and nums3, return a distinct array containing all + * the values that are present in at least two out of the three arrays. You may return the + * values in any order. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @param {number[]} nums3 + * @return {number[]} + */ +var twoOutOfThree = function(nums1, nums2, nums3) { + const set1 = new Set(nums1); + const set2 = new Set(nums2); + const set3 = new Set(nums3); + const count = new Map(); + + for (const num of set1) { + count.set(num, (count.get(num) || 0) + 1); + } + + for (const num of set2) { + count.set(num, (count.get(num) || 0) + 1); + } + + for (const num of set3) { + count.set(num, (count.get(num) || 0) + 1); + } + + const result = []; + for (const [num, freq] of count) { + if (freq >= 2) result.push(num); + } + + return result; +}; 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/2035-partition-array-into-two-arrays-to-minimize-sum-difference.js b/solutions/2035-partition-array-into-two-arrays-to-minimize-sum-difference.js new file mode 100644 index 00000000..1f3266b1 --- /dev/null +++ b/solutions/2035-partition-array-into-two-arrays-to-minimize-sum-difference.js @@ -0,0 +1,93 @@ +/** + * 2035. Partition Array Into Two Arrays to Minimize Sum Difference + * https://leetcode.com/problems/partition-array-into-two-arrays-to-minimize-sum-difference/ + * Difficulty: Hard + * + * You are given an integer array nums of 2 * n integers. You need to partition nums into two arrays + * of length n to minimize the absolute difference of the sums of the arrays. To partition nums, + * put each element of nums into one of the two arrays. + * + * Return the minimum possible absolute difference. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumDifference = function(nums) { + const n = nums.length / 2; + let result = Infinity; + const totalSum = nums.reduce((sum, num) => sum + num, 0); + const firstHalfSubsets = new Map(); + + for (let mask = 0; mask < (1 << n); mask++) { + let size = 0; + let subsetSum = 0; + + for (let i = 0; i < n; i++) { + if ((mask & (1 << i)) !== 0) { + size++; + subsetSum += nums[i]; + } + } + + if (!firstHalfSubsets.has(size)) { + firstHalfSubsets.set(size, []); + } + firstHalfSubsets.get(size).push(subsetSum); + } + + for (const [size, sums] of firstHalfSubsets) { + sums.sort((a, b) => a - b); + } + + for (let mask = 0; mask < (1 << n); mask++) { + let size = 0; + let secondHalfSum = 0; + + for (let i = 0; i < n; i++) { + if ((mask & (1 << i)) !== 0) { + size++; + secondHalfSum += nums[n + i]; + } + } + + const complementSize = n - size; + const firstHalfSums = firstHalfSubsets.get(complementSize); + const target = (totalSum - 2 * secondHalfSum) / 2; + const closestIndex = binarySearch(firstHalfSums, target); + + if (closestIndex < firstHalfSums.length) { + result = Math.min( + result, Math.abs(totalSum - 2 * (secondHalfSum + firstHalfSums[closestIndex])) + ); + } + + if (closestIndex > 0) { + result = Math.min( + result, Math.abs(totalSum - 2 * (secondHalfSum + firstHalfSums[closestIndex - 1])) + ); + } + } + + return result; +}; + +function binarySearch(arr, target) { + let left = 0; + let right = arr.length - 1; + + if (right < 0) return 0; + + 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/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/2038-remove-colored-pieces-if-both-neighbors-are-the-same-color.js b/solutions/2038-remove-colored-pieces-if-both-neighbors-are-the-same-color.js new file mode 100644 index 00000000..7a42cfcb --- /dev/null +++ b/solutions/2038-remove-colored-pieces-if-both-neighbors-are-the-same-color.js @@ -0,0 +1,38 @@ +/** + * 2038. Remove Colored Pieces if Both Neighbors are the Same Color + * https://leetcode.com/problems/remove-colored-pieces-if-both-neighbors-are-the-same-color/ + * Difficulty: Medium + * + * There are n pieces arranged in a line, and each piece is colored either by 'A' or by 'B'. + * You are given a string colors of length n where colors[i] is the color of the ith piece. + * + * Alice and Bob are playing a game where they take alternating turns removing pieces from the + * line. In this game, Alice moves first. + * - Alice is only allowed to remove a piece colored 'A' if both its neighbors are also colored + * 'A'. She is not allowed to remove pieces that are colored 'B'. + * - Bob is only allowed to remove a piece colored 'B' if both its neighbors are also colored + * 'B'. He is not allowed to remove pieces that are colored 'A'. + * - Alice and Bob cannot remove pieces from the edge of the line. + * - If a player cannot make a move on their turn, that player loses and the other player wins. + * + * Assuming Alice and Bob play optimally, return true if Alice wins, or return false if Bob wins. + */ + +/** + * @param {string} colors + * @return {boolean} + */ +var winnerOfGame = function(colors) { + let aliceMoves = 0; + let bobMoves = 0; + + for (let i = 1; i < colors.length - 1; i++) { + if (colors[i] === 'A' && colors[i - 1] === 'A' && colors[i + 1] === 'A') { + aliceMoves++; + } else if (colors[i] === 'B' && colors[i - 1] === 'B' && colors[i + 1] === 'B') { + bobMoves++; + } + } + + return aliceMoves > bobMoves; +}; diff --git a/solutions/2039-the-time-when-the-network-becomes-idle.js b/solutions/2039-the-time-when-the-network-becomes-idle.js new file mode 100644 index 00000000..38287340 --- /dev/null +++ b/solutions/2039-the-time-when-the-network-becomes-idle.js @@ -0,0 +1,71 @@ +/** + * 2039. The Time When the Network Becomes Idle + * https://leetcode.com/problems/the-time-when-the-network-becomes-idle/ + * Difficulty: Medium + * + * There is a network of n servers, labeled from 0 to n - 1. You are given a 2D integer array + * edges, where edges[i] = [ui, vi] indicates there is a message channel between servers ui + * and vi, and they can pass any number of messages to each other directly in one second. + * You are also given a 0-indexed integer array patience of length n. + * + * All servers are connected, i.e., a message can be passed from one server to any other + * server(s) directly or indirectly through the message channels. + * + * The server labeled 0 is the master server. The rest are data servers. Each data server + * needs to send its message to the master server for processing and wait for a reply. + * Messages move between servers optimally, so every message takes the least amount of + * time to arrive at the master server. The master server will process all newly arrived + * messages instantly and send a reply to the originating server via the reversed path + * the message had gone through. + * + * At the beginning of second 0, each data server sends its message to be processed. Starting + * from second 1, at the beginning of every second, each data server will check if it has + * received a reply to the message it sent (including any newly arrived replies) from the + * master server: + * - If it has not, it will resend the message periodically. The data server i will resend + * the message every patience[i] second(s), i.e., the data server i will resend the message + * if patience[i] second(s) have elapsed since the last time the message was sent from this + * server. + * - Otherwise, no more resending will occur from this server. + * + * The network becomes idle when there are no messages passing between servers or arriving + * at servers. + * + * Return the earliest second starting from which the network becomes idle. + */ + +/** + * @param {number[][]} edges + * @param {number[]} patience + * @return {number} + */ +var networkBecomesIdle = function(edges, patience) { + const n = patience.length; + const adjList = Array.from({ length: n }, () => []); + for (const [u, v] of edges) { + adjList[u].push(v); + adjList[v].push(u); + } + + const distances = new Array(n).fill(Infinity); + distances[0] = 0; + const queue = [0]; + let maxTime = 0; + + while (queue.length) { + const curr = queue.shift(); + for (const next of adjList[curr]) { + if (distances[next] === Infinity) { + distances[next] = distances[curr] + 1; + queue.push(next); + if (next !== 0) { + const roundTrip = 2 * distances[next]; + const lastSent = Math.floor((roundTrip - 1) / patience[next]) * patience[next]; + maxTime = Math.max(maxTime, lastSent + roundTrip); + } + } + } + } + + return maxTime + 1; +}; diff --git a/solutions/2040-kth-smallest-product-of-two-sorted-arrays.js b/solutions/2040-kth-smallest-product-of-two-sorted-arrays.js new file mode 100644 index 00000000..80a4da8c --- /dev/null +++ b/solutions/2040-kth-smallest-product-of-two-sorted-arrays.js @@ -0,0 +1,53 @@ +/** + * 2040. Kth Smallest Product of Two Sorted Arrays + * https://leetcode.com/problems/kth-smallest-product-of-two-sorted-arrays/ + * Difficulty: Hard + * + * Given two sorted 0-indexed integer arrays nums1 and nums2 as well as an integer k, return + * the kth (1-based) smallest product of nums1[i] * nums2[j] where 0 <= i < nums1.length + * and 0 <= j < nums2.length. + */ + +/** + * @param {number[]} nums1 + * @param {number[]} nums2 + * @param {number} k + * @return {number} + */ +var kthSmallestProduct = function(nums1, nums2, k) { + function countProducts(maxProduct) { + let count = 0; + for (const num1 of nums1) { + let left = 0; + let right = nums2.length; + + if (num1 >= 0) { + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (num1 * nums2[mid] <= maxProduct) left = mid + 1; + else right = mid; + } + count += left; + } else { + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (num1 * nums2[mid] <= maxProduct) right = mid; + else left = mid + 1; + } + count += nums2.length - left; + } + } + return count; + } + + let low = -(10 ** 10); + let high = 10 ** 10; + + while (low < high) { + const mid = Math.floor((low + high) / 2); + if (countProducts(mid) >= k) high = mid; + else low = mid + 1; + } + + return low; +}; diff --git a/solutions/2042-check-if-numbers-are-ascending-in-a-sentence.js b/solutions/2042-check-if-numbers-are-ascending-in-a-sentence.js new file mode 100644 index 00000000..5b91979b --- /dev/null +++ b/solutions/2042-check-if-numbers-are-ascending-in-a-sentence.js @@ -0,0 +1,29 @@ +/** + * 2042. Check if Numbers Are Ascending in a Sentence + * https://leetcode.com/problems/check-if-numbers-are-ascending-in-a-sentence/ + * Difficulty: Easy + * + * A sentence is a list of tokens separated by a single space with no leading or trailing spaces. + * Every token is either a positive number consisting of digits 0-9 with no leading zeros, or a + * word consisting of lowercase English letters. + * - For example, "a puppy has 2 eyes 4 legs" is a sentence with seven tokens: "2" and "4" are + * numbers and the other tokens such as "puppy" are words. + * + * Given a string s representing a sentence, you need to check if all the numbers in s are strictly + * increasing from left to right (i.e., other than the last number, each number is strictly smaller + * than the number on its right in s). + * + * Return true if so, or false otherwise. + */ + +/** + * @param {string} s + * @return {boolean} + */ +var areNumbersAscending = function(s) { + const numbers = s.split(' ').filter(token => !isNaN(token)).map(Number); + for (let i = 1; i < numbers.length; i++) { + if (numbers[i] <= numbers[i - 1]) return false; + } + return true; +}; diff --git a/solutions/2043-simple-bank-system.js b/solutions/2043-simple-bank-system.js new file mode 100644 index 00000000..3cb80cb1 --- /dev/null +++ b/solutions/2043-simple-bank-system.js @@ -0,0 +1,71 @@ +/** + * 2043. Simple Bank System + * https://leetcode.com/problems/simple-bank-system/ + * Difficulty: Medium + * + * You have been tasked with writing a program for a popular bank that will automate all its + * incoming transactions (transfer, deposit, and withdraw). The bank has n accounts numbered + * from 1 to n. The initial balance of each account is stored in a 0-indexed integer array + * balance, with the (i + 1)th account having an initial balance of balance[i]. + * + * Execute all the valid transactions. A transaction is valid if: + * - The given account number(s) are between 1 and n, and + * - The amount of money withdrawn or transferred from is less than or equal to the balance + * of the account. + * + * Implement the Bank class: + * - Bank(long[] balance) Initializes the object with the 0-indexed integer array balance. + * - boolean transfer(int account1, int account2, long money) Transfers money dollars from the + * account numbered account1 to the account numbered account2. Return true if the transaction + * was successful, false otherwise. + * - boolean deposit(int account, long money) Deposit money dollars into the account numbered + * account. Return true if the transaction was successful, false otherwise. + * - boolean withdraw(int account, long money) Withdraw money dollars from the account numbered + * account. Return true if the transaction was successful, false otherwise. + */ + +/** + * @param {number[]} balance + */ +var Bank = function(balance) { + this.accounts = balance; +}; + +/** + * @param {number} account1 + * @param {number} account2 + * @param {number} money + * @return {boolean} + */ +Bank.prototype.transfer = function(account1, account2, money) { + if (account1 > this.accounts.length || account2 > this.accounts.length) return false; + if (this.accounts[account1 - 1] < money) return false; + + this.accounts[account1 - 1] -= money; + this.accounts[account2 - 1] += money; + return true; +}; + +/** + * @param {number} account + * @param {number} money + * @return {boolean} + */ +Bank.prototype.deposit = function(account, money) { + if (account > this.accounts.length) return false; + + this.accounts[account - 1] += money; + return true; +}; + +/** + * @param {number} account + * @param {number} money + * @return {boolean} + */ +Bank.prototype.withdraw = function(account, money) { + if (account > this.accounts.length || this.accounts[account - 1] < money) return false; + + this.accounts[account - 1] -= money; + return true; +}; diff --git a/solutions/2044-count-number-of-maximum-bitwise-or-subsets.js b/solutions/2044-count-number-of-maximum-bitwise-or-subsets.js new file mode 100644 index 00000000..c318115a --- /dev/null +++ b/solutions/2044-count-number-of-maximum-bitwise-or-subsets.js @@ -0,0 +1,34 @@ +/** + * 2044. Count Number of Maximum Bitwise-OR Subsets + * https://leetcode.com/problems/count-number-of-maximum-bitwise-or-subsets/ + * Difficulty: Medium + * + * Given an integer array nums, find the maximum possible bitwise OR of a subset of nums and return + * the number of different non-empty subsets with the maximum bitwise OR. + * + * An array a is a subset of an array b if a can be obtained from b by deleting some (possibly zero) + * elements of b. Two subsets are considered different if the indices of the elements chosen are + * different. + * + * The bitwise OR of an array a is equal to a[0] OR a[1] OR ... OR a[a.length - 1] (0-indexed). + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var countMaxOrSubsets = function(nums) { + const maxOr = nums.reduce((or, num) => or | num, 0); + let count = 0; + + backtrack(0, 0); + + return count; + + function backtrack(index, currentOr) { + if (currentOr === maxOr) count++; + for (let i = index; i < nums.length; i++) { + backtrack(i + 1, currentOr | nums[i]); + } + } +}; diff --git a/solutions/2045-second-minimum-time-to-reach-destination.js b/solutions/2045-second-minimum-time-to-reach-destination.js new file mode 100644 index 00000000..522eabab --- /dev/null +++ b/solutions/2045-second-minimum-time-to-reach-destination.js @@ -0,0 +1,67 @@ +/** + * 2045. Second Minimum Time to Reach Destination + * https://leetcode.com/problems/second-minimum-time-to-reach-destination/ + * Difficulty: Hard + * + * A city is represented as a bi-directional connected graph with n vertices where each vertex + * is labeled from 1 to n (inclusive). The edges in the graph are represented as a 2D integer + * array edges, where each edges[i] = [ui, vi] denotes a bi-directional edge between vertex + * ui and vertex vi. Every vertex pair is connected by at most one edge, and no vertex has + * an edge to itself. The time taken to traverse any edge is time minutes. + * + * Each vertex has a traffic signal which changes its color from green to red and vice versa + * every change minutes. All signals change at the same time. You can enter a vertex at any + * time, but can leave a vertex only when the signal is green. You cannot wait at a vertex + * if the signal is green. + * + * The second minimum value is defined as the smallest value strictly larger than the minimum value. + * - For example the second minimum value of [2, 3, 4] is 3, and the second minimum value of + * [2, 2, 4] is 4. + * + * Given n, edges, time, and change, return the second minimum time it will take to go from + * vertex 1 to vertex n. + */ + +/** + * @param {number} n + * @param {number[][]} edges + * @param {number} time + * @param {number} change + * @return {number} + */ +var secondMinimum = function(n, edges, time, change) { + const adjList = Array.from({ length: n + 1 }, () => []); + for (const [u, v] of edges) { + adjList[u].push(v); + adjList[v].push(u); + } + + const distances = Array.from({ length: n + 1 }, () => [Infinity, Infinity]); + const queue = [[1, 0]]; + distances[1][0] = 0; + + while (queue.length) { + const [node, currTime] = queue.shift(); + + for (const next of adjList[node]) { + const signalCycle = Math.floor(currTime / change); + const isGreen = signalCycle % 2 === 0; + let nextTime = currTime + time; + + if (!isGreen) { + nextTime = (signalCycle + 1) * change + time; + } + + if (nextTime < distances[next][0]) { + distances[next][1] = distances[next][0]; + distances[next][0] = nextTime; + queue.push([next, nextTime]); + } else if (nextTime > distances[next][0] && nextTime < distances[next][1]) { + distances[next][1] = nextTime; + queue.push([next, nextTime]); + } + } + } + + return distances[n][1]; +}; 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/2048-next-greater-numerically-balanced-number.js b/solutions/2048-next-greater-numerically-balanced-number.js new file mode 100644 index 00000000..523a302a --- /dev/null +++ b/solutions/2048-next-greater-numerically-balanced-number.js @@ -0,0 +1,39 @@ +/** + * 2048. Next Greater Numerically Balanced Number + * https://leetcode.com/problems/next-greater-numerically-balanced-number/ + * Difficulty: Medium + * + * An integer x is numerically balanced if for every digit d in the number x, there are exactly + * d occurrences of that digit in x. + * + * Given an integer n, return the smallest numerically balanced number strictly greater than n. + */ + +/** + * @param {number} n + * @return {number} + */ +var nextBeautifulNumber = function(n) { + let candidate = n + 1; + while (candidate <= 10000000) { + if (isBalanced(candidate)) return candidate; + candidate++; + } + + return -1; + + function isBalanced(num) { + const freq = new Array(10).fill(0); + const str = num.toString(); + + for (const digit of str) { + freq[digit]++; + } + + for (const digit of str) { + if (freq[digit] !== parseInt(digit)) return false; + } + + return true; + } +}; diff --git a/solutions/2049-count-nodes-with-the-highest-score.js b/solutions/2049-count-nodes-with-the-highest-score.js new file mode 100644 index 00000000..1f13961e --- /dev/null +++ b/solutions/2049-count-nodes-with-the-highest-score.js @@ -0,0 +1,61 @@ +/** + * 2049. Count Nodes With the Highest Score + * https://leetcode.com/problems/count-nodes-with-the-highest-score/ + * Difficulty: Medium + * + * There is a binary tree rooted at 0 consisting of n nodes. The nodes are labeled from 0 to n - 1. + * You are given a 0-indexed integer array parents representing the tree, where parents[i] is the + * parent of node i. Since node 0 is the root, parents[0] == -1. + * + * Each node has a score. To find the score of a node, consider if the node and the edges connected + * to it were removed. The tree would become one or more non-empty subtrees. The size of a subtree + * is the number of the nodes in it. The score of the node is the product of the sizes of all + * those subtrees. + * + * Return the number of nodes that have the highest score. + */ + +/** + * @param {number[]} parents + * @return {number} + */ +var countHighestScoreNodes = function(parents) { + const n = parents.length; + const children = Array.from({ length: n }, () => []); + for (let i = 1; i < n; i++) { + children[parents[i]].push(i); + } + + const sizes = new Array(n).fill(0); + let maxScore = 0n; + let maxScoreCount = 0; + + calculateSize(0); + + return maxScoreCount; + + function calculateSize(node) { + let leftSize = 0; + let rightSize = 0; + + if (children[node].length > 0) leftSize = calculateSize(children[node][0]); + if (children[node].length > 1) rightSize = calculateSize(children[node][1]); + + sizes[node] = leftSize + rightSize + 1; + + let score = 1n; + if (leftSize > 0) score *= BigInt(leftSize); + if (rightSize > 0) score *= BigInt(rightSize); + const parentSize = n - sizes[node]; + if (parentSize > 0) score *= BigInt(parentSize); + + if (score > maxScore) { + maxScore = score; + maxScoreCount = 1; + } else if (score === maxScore) { + maxScoreCount++; + } + + return sizes[node]; + } +}; diff --git a/solutions/2050-parallel-courses-iii.js b/solutions/2050-parallel-courses-iii.js new file mode 100644 index 00000000..62cdec65 --- /dev/null +++ b/solutions/2050-parallel-courses-iii.js @@ -0,0 +1,61 @@ +/** + * 2050. Parallel Courses III + * https://leetcode.com/problems/parallel-courses-iii/ + * Difficulty: Hard + * + * You are given an integer n, which indicates that there are n courses labeled from 1 to n. + * You are also given a 2D integer array relations where relations[j] = [prevCoursej, nextCoursej] + * denotes that course prevCoursej has to be completed before course nextCoursej (prerequisite + * relationship). Furthermore, you are given a 0-indexed integer array time where time[i] denotes + * how many months it takes to complete the (i+1)th course. + * + * You must find the minimum number of months needed to complete all the courses following these + * rules: + * - You may start taking a course at any time if the prerequisites are met. + * - Any number of courses can be taken at the same time. + * + * Return the minimum number of months needed to complete all the courses. + * + * Note: The test cases are generated such that it is possible to complete every course (i.e., the + * graph is a directed acyclic graph). + */ + +/** + * @param {number} n + * @param {number[][]} relations + * @param {number[]} time + * @return {number} + */ +var minimumTime = function(n, relations, time) { + const adjacencyList = Array.from({ length: n + 1 }, () => []); + const inDegree = new Array(n + 1).fill(0); + const completionTime = new Array(n + 1).fill(0); + + for (const [prev, next] of relations) { + adjacencyList[prev].push(next); + inDegree[next]++; + } + + const queue = []; + for (let i = 1; i <= n; i++) { + if (inDegree[i] === 0) { + queue.push(i); + completionTime[i] = time[i - 1]; + } + } + + while (queue.length) { + const current = queue.shift(); + for (const next of adjacencyList[current]) { + completionTime[next] = Math.max( + completionTime[next], + completionTime[current] + time[next - 1] + ); + if (--inDegree[next] === 0) { + queue.push(next); + } + } + } + + return Math.max(...completionTime); +}; 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/2055-plates-between-candles.js b/solutions/2055-plates-between-candles.js new file mode 100644 index 00000000..347ed4ae --- /dev/null +++ b/solutions/2055-plates-between-candles.js @@ -0,0 +1,55 @@ +/** + * 2055. Plates Between Candles + * https://leetcode.com/problems/plates-between-candles/ + * Difficulty: Medium + * + * There is a long table with a line of plates and candles arranged on top of it. You are given + * a 0-indexed string s consisting of characters '*' and '|' only, where a '*' represents a plate + * and a '|' represents a candle. + * + * You are also given a 0-indexed 2D integer array queries where queries[i] = [lefti, righti] + * denotes the substring s[lefti...righti] (inclusive). For each query, you need to find the + * number of plates between candles that are in the substring. A plate is considered between + * candles if there is at least one candle to its left and at least one candle to its right + * in the substring. + * - For example, s = "||**||**|*", and a query [3, 8] denotes the substring "*||**|". The number + * of plates between candles in this substring is 2, as each of the two plates has at least one + * candle in the substring to its left and right. + * + * Return an integer array answer where answer[i] is the answer to the ith query. + */ + +/** + * @param {string} s + * @param {number[][]} queries + * @return {number[]} + */ +var platesBetweenCandles = function(s, queries) { + const n = s.length; + const prefixPlates = new Array(n + 1).fill(0); + const leftCandle = new Array(n).fill(-1); + const rightCandle = new Array(n).fill(-1); + + for (let i = 0, candle = -1; i < n; i++) { + prefixPlates[i + 1] = prefixPlates[i] + (s[i] === '*' ? 1 : 0); + if (s[i] === '|') candle = i; + leftCandle[i] = candle; + } + + for (let i = n - 1, candle = -1; i >= 0; i--) { + if (s[i] === '|') candle = i; + rightCandle[i] = candle; + } + + const result = new Array(queries.length).fill(0); + for (let i = 0; i < queries.length; i++) { + const [start, end] = queries[i]; + const left = rightCandle[start]; + const right = leftCandle[end]; + if (left !== -1 && right !== -1 && left < right) { + result[i] = prefixPlates[right] - prefixPlates[left]; + } + } + + return result; +}; diff --git a/solutions/2056-number-of-valid-move-combinations-on-chessboard.js b/solutions/2056-number-of-valid-move-combinations-on-chessboard.js new file mode 100644 index 00000000..94716f2b --- /dev/null +++ b/solutions/2056-number-of-valid-move-combinations-on-chessboard.js @@ -0,0 +1,108 @@ +/** + * 2056. Number of Valid Move Combinations On Chessboard + * https://leetcode.com/problems/number-of-valid-move-combinations-on-chessboard/ + * Difficulty: Hard + * + * There is an 8 x 8 chessboard containing n pieces (rooks, queens, or bishops). You are given a + * string array pieces of length n, where pieces[i] describes the type (rook, queen, or bishop) + * of the ith piece. In addition, you are given a 2D integer array positions also of length n, + * where positions[i] = [ri, ci] indicates that the ith piece is currently at the 1-based + * coordinate (ri, ci) on the chessboard. + * + * When making a move for a piece, you choose a destination square that the piece will travel + * toward and stop on. + * - A rook can only travel horizontally or vertically from (r, c) to the direction of (r+1, c), + * (r-1, c), (r, c+1), or (r, c-1). + * - A queen can only travel horizontally, vertically, or diagonally from (r, c) to the direction + * of (r+1, c), (r-1, c), (r, c+1), (r, c-1), (r+1, c+1), (r+1, c-1), (r-1, c+1), (r-1, c-1). + * - A bishop can only travel diagonally from (r, c) to the direction of (r+1, c+1), (r+1, c-1), + * (r-1, c+1), (r-1, c-1). + * + * You must make a move for every piece on the board simultaneously. A move combination consists of + * all the moves performed on all the given pieces. Every second, each piece will instantaneously + * travel one square towards their destination if they are not already at it. All pieces start + * traveling at the 0th second. A move combination is invalid if, at a given time, two or more + * pieces occupy the same square. + * + * Return the number of valid move combinations. + * + * Notes: + * - No two pieces will start in the same square. + * - You may choose the square a piece is already on as its destination. + * - If two pieces are directly adjacent to each other, it is valid for them to move past each other + * and swap positions in one second. + */ + +/** + * @param {string[]} pieces + * @param {number[][]} positions + * @return {number} + */ +var countCombinations = function(pieces, positions) { + const n = pieces.length; + const directions = { + rook: [[0, 1], [0, -1], [1, 0], [-1, 0]], + bishop: [[1, 1], [1, -1], [-1, 1], [-1, -1]], + queen: [[0, 1], [0, -1], [1, 0], [-1, 0], [1, 1], [1, -1], [-1, 1], [-1, -1]] + }; + + return generateCombinations(0, [], []); + + function isValidPosition(row, col) { + return row >= 1 && row <= 8 && col >= 1 && col <= 8; + } + + function simulateMoves(moves, steps) { + const current = positions.map(([r, c]) => [r, c]); + const maxSteps = Math.max(...steps); + + for (let t = 0; t <= maxSteps; t++) { + const positionsAtTime = new Set(); + for (let i = 0; i < n; i++) { + const [dr, dc] = moves[i]; + const step = Math.min(t, steps[i]); + const newRow = current[i][0] + dr * step; + const newCol = current[i][1] + dc * step; + + if (t > steps[i] && steps[i] > 0 && !isValidPosition(newRow, newCol)) continue; + + const posKey = `${newRow},${newCol}`; + if (positionsAtTime.has(posKey)) return false; + positionsAtTime.add(posKey); + } + } + + return true; + } + + function generateCombinations(index, selectedMoves, selectedSteps) { + if (index === n) { + return simulateMoves(selectedMoves, selectedSteps) ? 1 : 0; + } + + let total = 0; + const [startRow, startCol] = positions[index]; + const pieceDirections = directions[pieces[index]]; + + total += generateCombinations(index + 1, [...selectedMoves, [0, 0]], [...selectedSteps, 0]); + + for (const [dr, dc] of pieceDirections) { + let row = startRow; + let col = startCol; + let step = 0; + + while (isValidPosition(row + dr, col + dc)) { + row += dr; + col += dc; + step++; + total += generateCombinations( + index + 1, + [...selectedMoves, [dr, dc]], + [...selectedSteps, step] + ); + } + } + + return total; + } +}; diff --git a/solutions/2057-smallest-index-with-equal-value.js b/solutions/2057-smallest-index-with-equal-value.js new file mode 100644 index 00000000..3fe1c453 --- /dev/null +++ b/solutions/2057-smallest-index-with-equal-value.js @@ -0,0 +1,23 @@ +/** + * 2057. Smallest Index With Equal Value + * https://leetcode.com/problems/smallest-index-with-equal-value/ + * Difficulty: Easy + * + * Given a 0-indexed integer array nums, return the smallest index i of nums such that i mod + * 10 == nums[i], or -1 if such index does not exist. + * + * x mod y denotes the remainder when x is divided by y. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var smallestEqual = function(nums) { + for (let i = 0; i < nums.length; i++) { + if (i % 10 === nums[i]) { + return i; + } + } + return -1; +}; diff --git a/solutions/2058-find-the-minimum-and-maximum-number-of-nodes-between-critical-points.js b/solutions/2058-find-the-minimum-and-maximum-number-of-nodes-between-critical-points.js new file mode 100644 index 00000000..da92ff90 --- /dev/null +++ b/solutions/2058-find-the-minimum-and-maximum-number-of-nodes-between-critical-points.js @@ -0,0 +1,63 @@ +/** + * 2058. Find the Minimum and Maximum Number of Nodes Between Critical Points + * https://leetcode.com/problems/find-the-minimum-and-maximum-number-of-nodes-between-critical-points/ + * Difficulty: Medium + * + * A critical point in a linked list is defined as either a local maxima or a local minima. + * + * A node is a local maxima if the current node has a value strictly greater than the previous node + * and the next node. + * + * A node is a local minima if the current node has a value strictly smaller than the previous node + * and the next node. + * + * Note that a node can only be a local maxima/minima if there exists both a previous node and a + * next node. + * + * Given a linked list head, return an array of length 2 containing [minDistance, maxDistance] + * where minDistance is the minimum distance between any two distinct critical points and + * maxDistance is the maximum distance between any two distinct critical points. If there are + * fewer than two critical points, return [-1, -1]. + */ + +/** + * Definition for singly-linked list. + * function ListNode(val, next) { + * this.val = (val===undefined ? 0 : val) + * this.next = (next===undefined ? null : next) + * } + */ +/** + * @param {ListNode} head + * @return {number[]} + */ +var nodesBetweenCriticalPoints = function(head) { + const criticalPositions = []; + let position = 1; + let prev = head; + let current = head.next; + + while (current.next) { + const next = current.next; + if ((current.val > prev.val && current.val > next.val) || + (current.val < prev.val && current.val < next.val)) { + criticalPositions.push(position); + } + prev = current; + current = next; + position++; + } + + if (criticalPositions.length < 2) { + return [-1, -1]; + } + + let minDistance = Infinity; + for (let i = 1; i < criticalPositions.length; i++) { + minDistance = Math.min(minDistance, criticalPositions[i] - criticalPositions[i - 1]); + } + + const maxDistance = criticalPositions[criticalPositions.length - 1] - criticalPositions[0]; + + return [minDistance, maxDistance]; +}; diff --git a/solutions/2059-minimum-operations-to-convert-number.js b/solutions/2059-minimum-operations-to-convert-number.js new file mode 100644 index 00000000..677e5de9 --- /dev/null +++ b/solutions/2059-minimum-operations-to-convert-number.js @@ -0,0 +1,57 @@ +/** + * 2059. Minimum Operations to Convert Number + * https://leetcode.com/problems/minimum-operations-to-convert-number/ + * Difficulty: Medium + * + * You are given a 0-indexed integer array nums containing distinct numbers, an integer start, + * and an integer goal. There is an integer x that is initially set to start, and you want to + * perform operations on x such that it is converted to goal. You can perform the following + * operation repeatedly on the number x: + * + * If 0 <= x <= 1000, then for any index i in the array (0 <= i < nums.length), you can set x + * to any of the following: + * - x + nums[i] + * - x - nums[i] + * - x ^ nums[i] (bitwise-XOR) + * + * Note that you can use each nums[i] any number of times in any order. Operations that set x + * to be out of the range 0 <= x <= 1000 are valid, but no more operations can be done afterward. + * + * Return the minimum number of operations needed to convert x = start into goal, and -1 if it + * is not possible. + */ + +/** + * @param {number[]} nums + * @param {number} start + * @param {number} goal + * @return {number} + */ +var minimumOperations = function(nums, start, goal) { + const queue = [[start, 0]]; + const visited = new Set([start]); + + while (queue.length) { + const [current, steps] = queue.shift(); + + for (const num of nums) { + const candidates = [ + current + num, + current - num, + current ^ num + ]; + + for (const next of candidates) { + if (next === goal) { + return steps + 1; + } + if (next >= 0 && next <= 1000 && !visited.has(next)) { + visited.add(next); + queue.push([next, steps + 1]); + } + } + } + } + + return -1; +}; diff --git a/solutions/2060-check-if-an-original-string-exists-given-two-encoded-strings.js b/solutions/2060-check-if-an-original-string-exists-given-two-encoded-strings.js new file mode 100644 index 00000000..520e531e --- /dev/null +++ b/solutions/2060-check-if-an-original-string-exists-given-two-encoded-strings.js @@ -0,0 +1,73 @@ +/** + * 2060. Check if an Original String Exists Given Two Encoded Strings + * https://leetcode.com/problems/check-if-an-original-string-exists-given-two-encoded-strings/ + * Difficulty: Hard + * + * An original string, consisting of lowercase English letters, can be encoded by the following + * steps: + * - Arbitrarily split it into a sequence of some number of non-empty substrings. + * - Arbitrarily choose some elements (possibly none) of the sequence, and replace each with its + * length (as a numeric string). + * - Concatenate the sequence as the encoded string. + * + * For example, one way to encode an original string "abcdefghijklmnop" might be: + * - Split it as a sequence: ["ab", "cdefghijklmn", "o", "p"]. + * - Choose the second and third elements to be replaced by their lengths, respectively. The + * sequence becomes ["ab", "12", "1", "p"]. + * - Concatenate the elements of the sequence to get the encoded string: "ab121p". + * + * Given two encoded strings s1 and s2, consisting of lowercase English letters and digits 1-9 + * (inclusive), return true if there exists an original string that could be encoded as both s1 + * and s2. Otherwise, return false. + * + * Note: The test cases are generated such that the number of consecutive digits in s1 and s2 + * does not exceed 3. + */ + +/** + * @param {string} s1 + * @param {string} s2 + * @return {boolean} + */ +var possiblyEquals = function(s1, s2) { + const memo = new Array(s1.length + 1).fill().map(() => new Array(s2.length + 1).fill() + .map(() => ({}))); + + function match(pos1, pos2, diff) { + if (pos1 === s1.length && pos2 === s2.length) return diff === 0; + if (memo[pos1][pos2][diff] !== undefined) return memo[pos1][pos2][diff]; + + const char1 = s1[pos1]; + const char2 = s2[pos2]; + + if (pos1 < s1.length && pos2 < s2.length && char1 === char2 && diff === 0) { + if (match(pos1 + 1, pos2 + 1, 0)) return true; + } + + if (pos1 < s1.length && isNaN(char1) && diff < 0) { + if (match(pos1 + 1, pos2, diff + 1)) return true; + } + + if (pos2 < s2.length && isNaN(char2) && diff > 0) { + if (match(pos1, pos2 + 1, diff - 1)) return true; + } + + let num = 0; + for (let i = 0; i < 3 && pos1 + i < s1.length; i++) { + if (isNaN(s1[pos1 + i])) break; + num = num * 10 + parseInt(s1[pos1 + i]); + if (match(pos1 + i + 1, pos2, diff + num)) return true; + } + + num = 0; + for (let i = 0; i < 3 && pos2 + i < s2.length; i++) { + if (isNaN(s2[pos2 + i])) break; + num = num * 10 + parseInt(s2[pos2 + i]); + if (match(pos1, pos2 + i + 1, diff - num)) return true; + } + + return memo[pos1][pos2][diff] = false; + } + + return match(0, 0, 0); +}; 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/2062-count-vowel-substrings-of-a-string.js b/solutions/2062-count-vowel-substrings-of-a-string.js new file mode 100644 index 00000000..8d427ac8 --- /dev/null +++ b/solutions/2062-count-vowel-substrings-of-a-string.js @@ -0,0 +1,33 @@ +/** + * 2062. Count Vowel Substrings of a String + * https://leetcode.com/problems/count-vowel-substrings-of-a-string/ + * Difficulty: Easy + * + * A substring is a contiguous (non-empty) sequence of characters within a string. + * + * A vowel substring is a substring that only consists of vowels ('a', 'e', 'i', 'o', and 'u') + * and has all five vowels present in it. + * + * Given a string word, return the number of vowel substrings in word. + */ + +/** + * @param {string} word + * @return {number} + */ +var countVowelSubstrings = function(word) { + const vowels = new Set(['a', 'e', 'i', 'o', 'u']); + let total = 0; + + for (let start = 0; start < word.length; start++) { + const vowelCount = new Map(); + for (let end = start; end < word.length && vowels.has(word[end]); end++) { + vowelCount.set(word[end], (vowelCount.get(word[end]) || 0) + 1); + if (vowelCount.size === 5) { + total++; + } + } + } + + return total; +}; diff --git a/solutions/2063-vowels-of-all-substrings.js b/solutions/2063-vowels-of-all-substrings.js new file mode 100644 index 00000000..bde705e8 --- /dev/null +++ b/solutions/2063-vowels-of-all-substrings.js @@ -0,0 +1,30 @@ +/** + * 2063. Vowels of All Substrings + * https://leetcode.com/problems/vowels-of-all-substrings/ + * Difficulty: Medium + * + * Given a string word, return the sum of the number of vowels ('a', 'e', 'i', 'o', and 'u') in + * every substring of word. + * + * A substring is a contiguous (non-empty) sequence of characters within a string. + * + * Note: Due to the large constraints, the answer may not fit in a signed 32-bit integer. Please + * be careful during the calculations. + */ + +/** + * @param {string} word + * @return {number} + */ +var countVowels = function(word) { + const vowels = new Set(['a', 'e', 'i', 'o', 'u']); + let total = 0; + + for (let i = 0; i < word.length; i++) { + if (vowels.has(word[i])) { + total += (i + 1) * (word.length - i); + } + } + + return total; +}; diff --git a/solutions/2064-minimized-maximum-of-products-distributed-to-any-store.js b/solutions/2064-minimized-maximum-of-products-distributed-to-any-store.js new file mode 100644 index 00000000..b1781081 --- /dev/null +++ b/solutions/2064-minimized-maximum-of-products-distributed-to-any-store.js @@ -0,0 +1,45 @@ +/** + * 2064. Minimized Maximum of Products Distributed to Any Store + * https://leetcode.com/problems/minimized-maximum-of-products-distributed-to-any-store/ + * Difficulty: Medium + * + * You are given an integer n indicating there are n specialty retail stores. There are m product + * types of varying amounts, which are given as a 0-indexed integer array quantities, where + * quantities[i] represents the number of products of the ith product type. + * + * You need to distribute all products to the retail stores following these rules: + * - A store can only be given at most one product type but can be given any amount of it. + * - After distribution, each store will have been given some number of products (possibly 0). + * Let x represent the maximum number of products given to any store. You want x to be as small + * as possible, i.e., you want to minimize the maximum number of products that are given to any + * store. + * + * Return the minimum possible x. + */ + +/** + * @param {number} n + * @param {number[]} quantities + * @return {number} + */ +var minimizedMaximum = function(n, quantities) { + let left = 1; + let right = Math.max(...quantities); + + while (left < right) { + const mid = Math.floor((left + right) / 2); + let storesNeeded = 0; + + for (const quantity of quantities) { + storesNeeded += Math.ceil(quantity / mid); + } + + if (storesNeeded <= n) { + right = mid; + } else { + left = mid + 1; + } + } + + return left; +}; diff --git a/solutions/2065-maximum-path-quality-of-a-graph.js b/solutions/2065-maximum-path-quality-of-a-graph.js new file mode 100644 index 00000000..9d07048c --- /dev/null +++ b/solutions/2065-maximum-path-quality-of-a-graph.js @@ -0,0 +1,59 @@ +/** + * 2065. Maximum Path Quality of a Graph + * https://leetcode.com/problems/maximum-path-quality-of-a-graph/ + * Difficulty: Hard + * + * There is an undirected graph with n nodes numbered from 0 to n - 1 (inclusive). You are given a + * 0-indexed integer array values where values[i] is the value of the ith node. You are also given + * a 0-indexed 2D integer array edges, where each edges[j] = [uj, vj, timej] indicates that there + * is an undirected edge between the nodes uj and vj, and it takes timej seconds to travel between + * the two nodes. Finally, you are given an integer maxTime. + * + * A valid path in the graph is any path that starts at node 0, ends at node 0, and takes at most + * maxTime seconds to complete. You may visit the same node multiple times. The quality of a valid + * path is the sum of the values of the unique nodes visited in the path (each node's value is + * added at most once to the sum). + * + * Return the maximum quality of a valid path. + * + * Note: There are at most four edges connected to each node. + */ + +/** + * @param {number[]} values + * @param {number[][]} edges + * @param {number} maxTime + * @return {number} + */ +var maximalPathQuality = function(values, edges, maxTime) { + const n = values.length; + const adjList = Array.from({ length: n }, () => []); + + for (const [u, v, time] of edges) { + adjList[u].push([v, time]); + adjList[v].push([u, time]); + } + + let result = 0; + const initialVisited = new Set([0]); + + dfs(0, maxTime, values[0], initialVisited); + + return result; + + function dfs(node, timeLeft, quality, visited) { + if (timeLeft < 0) return 0; + if (node === 0) { + result = Math.max(result, quality); + } + + for (const [nextNode, travelTime] of adjList[node]) { + const newVisited = new Set(visited); + const newQuality = newVisited.has(nextNode) ? quality : quality + values[nextNode]; + newVisited.add(nextNode); + dfs(nextNode, timeLeft - travelTime, newQuality, newVisited); + } + + return result; + } +}; 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/2068-check-whether-two-strings-are-almost-equivalent.js b/solutions/2068-check-whether-two-strings-are-almost-equivalent.js new file mode 100644 index 00000000..210aeb88 --- /dev/null +++ b/solutions/2068-check-whether-two-strings-are-almost-equivalent.js @@ -0,0 +1,29 @@ +/** + * 2068. Check Whether Two Strings are Almost Equivalent + * https://leetcode.com/problems/check-whether-two-strings-are-almost-equivalent/ + * Difficulty: Easy + * + * Two strings word1 and word2 are considered almost equivalent if the differences between the + * frequencies of each letter from 'a' to 'z' between word1 and word2 is at most 3. + * + * Given two strings word1 and word2, each of length n, return true if word1 and word2 are almost + * equivalent, or false otherwise. + * + * The frequency of a letter x is the number of times it occurs in the string. + */ + +/** + * @param {string} word1 + * @param {string} word2 + * @return {boolean} + */ +var checkAlmostEquivalent = function(word1, word2) { + const map = new Array(26).fill(0); + + for (let i = 0; i < word1.length; i++) { + map[word1.charCodeAt(i) - 97]++; + map[word2.charCodeAt(i) - 97]--; + } + + return map.every(diff => Math.abs(diff) <= 3); +}; diff --git a/solutions/2069-walking-robot-simulation-ii.js b/solutions/2069-walking-robot-simulation-ii.js new file mode 100644 index 00000000..e4896040 --- /dev/null +++ b/solutions/2069-walking-robot-simulation-ii.js @@ -0,0 +1,84 @@ +/** + * 2069. Walking Robot Simulation II + * https://leetcode.com/problems/walking-robot-simulation-ii/ + * Difficulty: Medium + * + * A width x height grid is on an XY-plane with the bottom-left cell at (0, 0) and the + * top-right cell at (width - 1, height - 1). The grid is aligned with the four cardinal + * directions ("North", "East", "South", and "West"). A robot is initially at cell (0, 0) + * facing direction "East". + * + * The robot can be instructed to move for a specific number of steps. For each step, it does + * the following. + * 1. Attempts to move forward one cell in the direction it is facing. + * 2. If the cell the robot is moving to is out of bounds, the robot instead turns 90 degrees + * counterclockwise and retries the step. + * + * After the robot finishes moving the number of steps required, it stops and awaits the next + * instruction. + * + * Implement the Robot class: + * - Robot(int width, int height) Initializes the width x height grid with the robot at (0, 0) + * facing "East". + * - void step(int num) Instructs the robot to move forward num steps. + * - int[] getPos() Returns the current cell the robot is at, as an array of length 2, [x, y]. + * - String getDir() Returns the current direction of the robot, "North", "East", "South", or + * "West". + */ + +/** + * @param {number} width + * @param {number} height + */ +var Robot = function(width, height) { + this.width = width; + this.height = height; + this.position = [0, 0]; + this.directionIndex = 0; + this.directions = ['East', 'North', 'West', 'South']; + this.moves = [[1, 0], [0, 1], [-1, 0], [0, -1]]; + this.perimeter = 2 * (width + height - 2); +}; + +/** + * @param {number} num + * @return {void} + */ +Robot.prototype.step = function(num) { + num %= this.perimeter; + if (num === 0) num = this.perimeter; + + while (num > 0) { + const [dx, dy] = this.moves[this.directionIndex]; + const [x, y] = this.position; + let steps; + + if (this.directionIndex === 0) steps = this.width - 1 - x; + else if (this.directionIndex === 1) steps = this.height - 1 - y; + else if (this.directionIndex === 2) steps = x; + else steps = y; + + if (steps >= num) { + this.position = [x + dx * num, y + dy * num]; + num = 0; + } else { + this.position = [x + dx * steps, y + dy * steps]; + this.directionIndex = (this.directionIndex + 1) % 4; + num -= steps; + } + } +}; + +/** + * @return {number[]} + */ +Robot.prototype.getPos = function() { + return this.position; +}; + +/** + * @return {string} + */ +Robot.prototype.getDir = function() { + return this.directions[this.directionIndex]; +}; diff --git a/solutions/2070-most-beautiful-item-for-each-query.js b/solutions/2070-most-beautiful-item-for-each-query.js new file mode 100644 index 00000000..1931e875 --- /dev/null +++ b/solutions/2070-most-beautiful-item-for-each-query.js @@ -0,0 +1,54 @@ +/** + * 2070. Most Beautiful Item for Each Query + * https://leetcode.com/problems/most-beautiful-item-for-each-query/ + * Difficulty: Medium + * + * You are given a 2D integer array items where items[i] = [pricei, beautyi] denotes the price and + * beauty of an item respectively. + * + * You are also given a 0-indexed integer array queries. For each queries[j], you want to determine + * the maximum beauty of an item whose price is less than or equal to queries[j]. If no such item + * exists, then the answer to this query is 0. + * + * Return an array answer of the same length as queries where answer[j] is the answer to the jth + * query. + */ + +/** + * @param {number[][]} items + * @param {number[]} queries + * @return {number[]} + */ +var maximumBeauty = function(items, queries) { + items.sort((a, b) => a[0] - b[0]); + const maxBeauty = []; + let currentMax = 0; + + for (const [, beauty] of items) { + currentMax = Math.max(currentMax, beauty); + maxBeauty.push(currentMax); + } + + const result = new Array(queries.length).fill(0); + + for (let i = 0; i < queries.length; i++) { + const price = queries[i]; + let left = 0; + let right = items.length - 1; + + while (left <= right) { + const mid = Math.floor((left + right) / 2); + if (items[mid][0] <= price) { + left = mid + 1; + } else { + right = mid - 1; + } + } + + if (right >= 0) { + result[i] = maxBeauty[right]; + } + } + + return result; +}; diff --git a/solutions/2071-maximum-number-of-tasks-you-can-assign.js b/solutions/2071-maximum-number-of-tasks-you-can-assign.js new file mode 100644 index 00000000..5382d5d5 --- /dev/null +++ b/solutions/2071-maximum-number-of-tasks-you-can-assign.js @@ -0,0 +1,79 @@ +/** + * 2071. Maximum Number of Tasks You Can Assign + * https://leetcode.com/problems/maximum-number-of-tasks-you-can-assign/ + * Difficulty: Hard + * + * You have n tasks and m workers. Each task has a strength requirement stored in a 0-indexed + * integer array tasks, with the ith task requiring tasks[i] strength to complete. The strength + * of each worker is stored in a 0-indexed integer array workers, with the jth worker having + * workers[j] strength. Each worker can only be assigned to a single task and must have a + * strength greater than or equal to the task's strength requirement (i.e., workers[j] >= tasks[i]). + * + * Additionally, you have pills magical pills that will increase a worker's strength by strength. + * You can decide which workers receive the magical pills, however, you may only give each worker + * at most one magical pill. + * + * Given the 0-indexed integer arrays tasks and workers and the integers pills and strength, + * return the maximum number of tasks that can be completed. + */ + +/** + * @param {number[]} tasks + * @param {number[]} workers + * @param {number} pills + * @param {number} strength + * @return {number} + */ +var maxTaskAssign = function(tasks, workers, pills, strength) { + tasks.sort((a, b) => a - b); + workers.sort((a, b) => a - b); + + const n = tasks.length; + const m = workers.length; + + let left = 0; + let right = Math.min(n, m); + + while (left < right) { + const mid = Math.floor((left + right + 1) / 2); + + if (canAssign(mid)) { + left = mid; + } else { + right = mid - 1; + } + } + + return left; + + function canAssign(k) { + const availableTasks = tasks.slice(0, k); + const availableWorkers = workers.slice(m - k); + let remainingPills = pills; + + for (let i = k - 1; i >= 0; i--) { + const task = availableTasks[i]; + + if (availableWorkers[availableWorkers.length - 1] >= task) { + availableWorkers.pop(); + continue; + } + + if (remainingPills === 0) return false; + + let found = false; + for (let j = 0; j < availableWorkers.length; j++) { + if (availableWorkers[j] + strength >= task) { + availableWorkers.splice(j, 1); + remainingPills--; + found = true; + break; + } + } + + if (!found) return false; + } + + return true; + } +}; 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/2074-reverse-nodes-in-even-length-groups.js b/solutions/2074-reverse-nodes-in-even-length-groups.js new file mode 100644 index 00000000..2608277e --- /dev/null +++ b/solutions/2074-reverse-nodes-in-even-length-groups.js @@ -0,0 +1,72 @@ +/** + * 2074. Reverse Nodes in Even Length Groups + * https://leetcode.com/problems/reverse-nodes-in-even-length-groups/ + * Difficulty: Medium + * + * You are given the head of a linked list. + * + * The nodes in the linked list are sequentially assigned to non-empty groups whose lengths form + * the sequence of the natural numbers (1, 2, 3, 4, ...). The length of a group is the number + * of nodes assigned to it. In other words: + * - The 1st node is assigned to the first group. + * - The 2nd and the 3rd nodes are assigned to the second group. + * - The 4th, 5th, and 6th nodes are assigned to the third group, and so on. + * + * Note that the length of the last group may be less than or equal to 1 + the length of the second + * to last group. + * + * Reverse the nodes in each group with an even length, and return the head of the modified linked + * 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 reverseEvenLengthGroups = function(head) { + let prevGroup = head; + let groupLength = 2; + + while (prevGroup.next) { + let count = 0; + let current = prevGroup.next; + const groupStart = current; + + while (current && count < groupLength) { + current = current.next; + count++; + } + + if (count % 2 === 0) { + prevGroup.next = reverseGroup(groupStart, count); + } + + for (let i = 0; i < count; i++) { + prevGroup = prevGroup.next; + } + + groupLength++; + } + + return head; + + function reverseGroup(start, length) { + let prev = null; + let current = start; + for (let i = 0; i < length; i++) { + const next = current.next; + current.next = prev; + prev = current; + current = next; + } + start.next = current; + return prev; + } +}; diff --git a/solutions/2075-decode-the-slanted-ciphertext.js b/solutions/2075-decode-the-slanted-ciphertext.js new file mode 100644 index 00000000..63f5a41d --- /dev/null +++ b/solutions/2075-decode-the-slanted-ciphertext.js @@ -0,0 +1,51 @@ +/** + * 2075. Decode the Slanted Ciphertext + * https://leetcode.com/problems/decode-the-slanted-ciphertext/ + * Difficulty: Medium + * + * A string originalText is encoded using a slanted transposition cipher to a string encodedText + * with the help of a matrix having a fixed number of rows rows. + * + * originalText is placed first in a top-left to bottom-right manner. + * + * The blue cells are filled first, followed by the red cells, then the yellow cells, and so on, + * until we reach the end of originalText. The arrow indicates the order in which the cells are + * filled. All empty cells are filled with ' '. The number of columns is chosen such that the + * rightmost column will not be empty after filling in originalText. + * + * encodedText is then formed by appending all characters of the matrix in a row-wise fashion. + * + * The characters in the blue cells are appended first to encodedText, then the red cells, and so + * on, and finally the yellow cells. The arrow indicates the order in which the cells are accessed. + * + * For example, if originalText = "cipher" and rows = 3, then we encode it in the following manner. + * + * The blue arrows depict how originalText is placed in the matrix, and the red arrows denote the + * order in which encodedText is formed. In the above example, encodedText = "ch ie pr". + * + * Given the encoded string encodedText and number of rows rows, return the original string + * originalText. + * + * Note: originalText does not have any trailing spaces ' '. The test cases are generated such that + * there is only one possible originalText. + */ + +/** + * @param {string} encodedText + * @param {number} rows + * @return {string} + */ +var decodeCiphertext = function(encodedText, rows) { + if (rows === 1) return encodedText; + + const count = encodedText.length / rows; + let result = ''; + + for (let i = 0; i < count; i++) { + for (let row = 0; row < rows && row + i < count; row++) { + result += encodedText[row * count + i + row]; + } + } + + return result.trimEnd(); +}; diff --git a/solutions/2076-process-restricted-friend-requests.js b/solutions/2076-process-restricted-friend-requests.js new file mode 100644 index 00000000..dff94d09 --- /dev/null +++ b/solutions/2076-process-restricted-friend-requests.js @@ -0,0 +1,70 @@ +/** + * 2076. Process Restricted Friend Requests + * https://leetcode.com/problems/process-restricted-friend-requests/ + * Difficulty: Hard + * + * You are given an integer n indicating the number of people in a network. Each person is + * labeled from 0 to n - 1. + * + * You are also given a 0-indexed 2D integer array restrictions, where restrictions[i] = [xi, yi] + * means that person xi and person yi cannot become friends, either directly or indirectly through + * other people. + * + * Initially, no one is friends with each other. You are given a list of friend requests as a + * 0-indexed 2D integer array requests, where requests[j] = [uj, vj] is a friend request between + * person uj and person vj. + * + * A friend request is successful if uj and vj can be friends. Each friend request is processed + * in the given order (i.e., requests[j] occurs before requests[j + 1]), and upon a successful + * request, uj and vj become direct friends for all future friend requests. + * + * Return a boolean array result, where each result[j] is true if the jth friend request is + * successful or false if it is not. + * + * Note: If uj and vj are already direct friends, the request is still successful. + */ + +/** + * @param {number} n + * @param {number[][]} restrictions + * @param {number[][]} requests + * @return {boolean[]} + */ +var friendRequests = function(n, restrictions, requests) { + const parent = Array.from({ length: n }, (_, i) => i); + const result = new Array(requests.length).fill(true); + + for (let j = 0; j < requests.length; j++) { + const [u, v] = requests[j]; + const pu = find(u); + const pv = find(v); + + let canBeFriends = true; + for (const [x, y] of restrictions) { + const px = find(x); + const py = find(y); + if ((pu === px && pv === py) || (pu === py && pv === px)) { + canBeFriends = false; + break; + } + } + + result[j] = canBeFriends; + if (canBeFriends) { + union(u, v); + } + } + + return result; + + function find(x) { + if (parent[x] !== x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + function union(x, y) { + parent[find(x)] = find(y); + } +}; 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/2078-two-furthest-houses-with-different-colors.js b/solutions/2078-two-furthest-houses-with-different-colors.js new file mode 100644 index 00000000..9a42b696 --- /dev/null +++ b/solutions/2078-two-furthest-houses-with-different-colors.js @@ -0,0 +1,32 @@ +/** + * 2078. Two Furthest Houses With Different Colors + * https://leetcode.com/problems/two-furthest-houses-with-different-colors/ + * Difficulty: Easy + * + * There are n houses evenly lined up on the street, and each house is beautifully painted. + * You are given a 0-indexed integer array colors of length n, where colors[i] represents + * the color of the ith house. + * + * Return the maximum distance between two houses with different colors. + * + * The distance between the ith and jth houses is abs(i - j), where abs(x) is the absolute + * value of x. + */ + +/** + * @param {number[]} colors + * @return {number} + */ +var maxDistance = function(colors) { + let result = 0; + + for (let i = 0; i < colors.length; i++) { + for (let j = i + 1; j < colors.length; j++) { + if (colors[i] !== colors[j]) { + result = Math.max(result, j - i); + } + } + } + + return result; +}; diff --git a/solutions/2079-watering-plants.js b/solutions/2079-watering-plants.js new file mode 100644 index 00000000..ba77b302 --- /dev/null +++ b/solutions/2079-watering-plants.js @@ -0,0 +1,42 @@ +/** + * 2079. Watering Plants + * https://leetcode.com/problems/watering-plants/ + * Difficulty: Medium + * + * You want to water n plants in your garden with a watering can. The plants are arranged in + * a row and are labeled from 0 to n - 1 from left to right where the ith plant is located at + * x = i. There is a river at x = -1 that you can refill your watering can at. + * + * Each plant needs a specific amount of water. You will water the plants in the following way: + * - Water the plants in order from left to right. + * - After watering the current plant, if you do not have enough water to completely water the + * next plant, return to the river to fully refill the watering can. + * - You cannot refill the watering can early. + * + * You are initially at the river (i.e., x = -1). It takes one step to move one unit on the x-axis. + * + * Given a 0-indexed integer array plants of n integers, where plants[i] is the amount of water + * the ith plant needs, and an integer capacity representing the watering can capacity, return + * the number of steps needed to water all the plants. + */ + +/** + * @param {number[]} plants + * @param {number} capacity + * @return {number} + */ +var wateringPlants = function(plants, capacity) { + let water = capacity; + let result = 0; + + for (let i = 0; i < plants.length; i++) { + if (water < plants[i]) { + result += 2 * i; + water = capacity; + } + water -= plants[i]; + result++; + } + + return result; +}; diff --git a/solutions/2080-range-frequency-queries.js b/solutions/2080-range-frequency-queries.js new file mode 100644 index 00000000..32b1bb27 --- /dev/null +++ b/solutions/2080-range-frequency-queries.js @@ -0,0 +1,72 @@ +/** + * 2080. Range Frequency Queries + * https://leetcode.com/problems/range-frequency-queries/ + * Difficulty: Medium + * + * Design a data structure to find the frequency of a given value in a given subarray. + * + * The frequency of a value in a subarray is the number of occurrences of that value in + * the subarray. + * + * Implement the RangeFreqQuery class: + * - RangeFreqQuery(int[] arr) Constructs an instance of the class with the given 0-indexed + * integer array arr. + * - int query(int left, int right, int value) Returns the frequency of value in the subarray + * arr[left...right]. + * - A subarray is a contiguous sequence of elements within an array. arr[left...right] denotes + * the subarray that contains the elements of nums between indices left and right (inclusive). + */ + +/** + * @param {number[]} arr + */ +var RangeFreqQuery = function(arr) { + this.frequencyMap = new Map(); + + for (let i = 0; i < arr.length; i++) { + if (!this.frequencyMap.has(arr[i])) { + this.frequencyMap.set(arr[i], []); + } + this.frequencyMap.get(arr[i]).push(i); + } +}; + +/** + * @param {number} left + * @param {number} right + * @param {number} value + * @return {number} + */ +RangeFreqQuery.prototype.query = function(left, right, value) { + if (!this.frequencyMap.has(value)) return 0; + + const indices = this.frequencyMap.get(value); + let start = 0; + let end = indices.length - 1; + let leftBound = -1; + let rightBound = -1; + + while (start <= end) { + const mid = Math.floor((start + end) / 2); + if (indices[mid] >= left) { + leftBound = mid; + end = mid - 1; + } else { + start = mid + 1; + } + } + + start = 0; + end = indices.length - 1; + while (start <= end) { + const mid = Math.floor((start + end) / 2); + if (indices[mid] <= right) { + rightBound = mid; + start = mid + 1; + } else { + end = mid - 1; + } + } + + return leftBound === -1 || rightBound === -1 ? 0 : rightBound - leftBound + 1; +}; diff --git a/solutions/2081-sum-of-k-mirror-numbers.js b/solutions/2081-sum-of-k-mirror-numbers.js new file mode 100644 index 00000000..600d62d8 --- /dev/null +++ b/solutions/2081-sum-of-k-mirror-numbers.js @@ -0,0 +1,105 @@ +/** + * 2081. Sum of k-Mirror Numbers + * https://leetcode.com/problems/sum-of-k-mirror-numbers/ + * Difficulty: Hard + * + * A k-mirror number is a positive integer without leading zeros that reads the same both forward + * and backward in base-10 as well as in base-k. + * - For example, 9 is a 2-mirror number. The representation of 9 in base-10 and base-2 are 9 and + * 1001 respectively, which read the same both forward and backward. + * - On the contrary, 4 is not a 2-mirror number. The representation of 4 in base-2 is 100, which + * does not read the same both forward and backward. + * + * Given the base k and the number n, return the sum of the n smallest k-mirror numbers. + */ + +/** + * @param {number} k + * @param {number} n + * @return {number} + */ +var kMirror = function(k, n) { + const kMirrorNumbers = []; + let sum = 0; + let length = 1; + + while (kMirrorNumbers.length < n) { + generatePalindromes(length).forEach(num => { + if (kMirrorNumbers.length < n && isKMirror(num, k)) { + kMirrorNumbers.push(num); + sum += num; + } + }); + length++; + } + + return sum; +}; + +function toBaseK(num, k) { + if (num === 0) return '0'; + + let result = ''; + while (num > 0) { + result = (num % k) + result; + num = Math.floor(num / k); + } + + return result; +} + +function isKMirror(num, k) { + const baseKRepresentation = toBaseK(num, k); + return isPalindrome(baseKRepresentation); +} + +function isPalindrome(str) { + let left = 0; + let right = str.length - 1; + + while (left < right) { + if (str[left] !== str[right]) return false; + left++; + right--; + } + + return true; +} + +function generatePalindromes(length) { + const palindromes = []; + + if (length === 1) { + for (let i = 1; i <= 9; i++) { + palindromes.push(i); + } + return palindromes; + } + + if (length % 2 === 0) { + const half = length / 2; + const start = Math.pow(10, half - 1); + const end = Math.pow(10, half) - 1; + + for (let i = start; i <= end; i++) { + const firstHalf = i.toString(); + const secondHalf = firstHalf.split('').reverse().join(''); + palindromes.push(parseInt(firstHalf + secondHalf)); + } + } else { + const half = Math.floor(length / 2); + const start = Math.pow(10, half); + const end = Math.pow(10, half + 1) - 1; + + for (let i = start; i <= end; i++) { + const withoutMiddle = Math.floor(i / 10); + const middle = i % 10; + const firstHalf = withoutMiddle.toString(); + const secondHalf = firstHalf.split('').reverse().join(''); + palindromes.push(parseInt(firstHalf + middle + secondHalf)); + } + } + + return palindromes; +} + 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/2086-minimum-number-of-food-buckets-to-feed-the-hamsters.js b/solutions/2086-minimum-number-of-food-buckets-to-feed-the-hamsters.js new file mode 100644 index 00000000..5cda9132 --- /dev/null +++ b/solutions/2086-minimum-number-of-food-buckets-to-feed-the-hamsters.js @@ -0,0 +1,43 @@ +/** + * 2086. Minimum Number of Food Buckets to Feed the Hamsters + * https://leetcode.com/problems/minimum-number-of-food-buckets-to-feed-the-hamsters/ + * Difficulty: Medium + * + * You are given a 0-indexed string hamsters where hamsters[i] is either: + * - 'H' indicating that there is a hamster at index i, or + * - '.' indicating that index i is empty. + * + * You will add some number of food buckets at the empty indices in order to feed the hamsters. + * A hamster can be fed if there is at least one food bucket to its left or to its right. More + * formally, a hamster at index i can be fed if you place a food bucket at index i - 1 and/or + * at index i + 1. + * + * Return the minimum number of food buckets you should place at empty indices to feed all the + * hamsters or -1 if it is impossible to feed all of them. + */ + +/** + * @param {string} hamsters + * @return {number} + */ +var minimumBuckets = function(hamsters) { + const n = hamsters.length; + let result = 0; + + for (let i = 0; i < n; i++) { + if (hamsters[i] === 'H') { + if (i > 0 && hamsters[i - 1] === 'B') continue; + if (i < n - 1 && hamsters[i + 1] === '.') { + result++; + hamsters = hamsters.slice(0, i + 1) + 'B' + hamsters.slice(i + 2); + } else if (i > 0 && hamsters[i - 1] === '.') { + result++; + hamsters = hamsters.slice(0, i - 1) + 'B' + hamsters.slice(i); + } else { + return -1; + } + } + } + + return result; +}; diff --git a/solutions/2087-minimum-cost-homecoming-of-a-robot-in-a-grid.js b/solutions/2087-minimum-cost-homecoming-of-a-robot-in-a-grid.js new file mode 100644 index 00000000..8fde0697 --- /dev/null +++ b/solutions/2087-minimum-cost-homecoming-of-a-robot-in-a-grid.js @@ -0,0 +1,45 @@ +/** + * 2087. Minimum Cost Homecoming of a Robot in a Grid + * https://leetcode.com/problems/minimum-cost-homecoming-of-a-robot-in-a-grid/ + * Difficulty: Medium + * + * There is an m x n grid, where (0, 0) is the top-left cell and (m - 1, n - 1) is the bottom-right + * cell. You are given an integer array startPos where startPos = [startrow, startcol] indicates + * that initially, a robot is at the cell (startrow, startcol). You are also given an integer array + * homePos where homePos = [homerow, homecol] indicates that its home is at the cell (homerow, + * homecol). + * + * The robot needs to go to its home. It can move one cell in four directions: left, right, up, + * or down, and it can not move outside the boundary. Every move incurs some cost. You are further + * given two 0-indexed integer arrays: rowCosts of length m and colCosts of length n. + * - If the robot moves up or down into a cell whose row is r, then this move costs rowCosts[r]. + * - If the robot moves left or right into a cell whose column is c, then this move costs + * colCosts[c]. + * + * Return the minimum total cost for this robot to return home. + */ + +/** + * @param {number[]} startPos + * @param {number[]} homePos + * @param {number[]} rowCosts + * @param {number[]} colCosts + * @return {number} + */ +var minCost = function(startPos, homePos, rowCosts, colCosts) { + let result = 0; + const [startRow, startCol] = startPos; + const [homeRow, homeCol] = homePos; + + const rowStep = startRow < homeRow ? 1 : -1; + for (let row = startRow + rowStep; row !== homeRow + rowStep; row += rowStep) { + result += rowCosts[row]; + } + + const colStep = startCol < homeCol ? 1 : -1; + for (let col = startCol + colStep; col !== homeCol + colStep; col += colStep) { + result += colCosts[col]; + } + + return result; +}; diff --git a/solutions/2088-count-fertile-pyramids-in-a-land.js b/solutions/2088-count-fertile-pyramids-in-a-land.js new file mode 100644 index 00000000..0780710b --- /dev/null +++ b/solutions/2088-count-fertile-pyramids-in-a-land.js @@ -0,0 +1,71 @@ +/** + * 2088. Count Fertile Pyramids in a Land + * https://leetcode.com/problems/count-fertile-pyramids-in-a-land/ + * Difficulty: Hard + * + * A farmer has a rectangular grid of land with m rows and n columns that can be divided into + * unit cells. Each cell is either fertile (represented by a 1) or barren (represented by a 0). + * All cells outside the grid are considered barren. + * + * A pyramidal plot of land can be defined as a set of cells with the following criteria: + * 1. The number of cells in the set has to be greater than 1 and all cells must be fertile. + * 2. The apex of a pyramid is the topmost cell of the pyramid. The height of a pyramid is the + * number of rows it covers. Let (r, c) be the apex of the pyramid, and its height be h. + * Then, the plot comprises of cells (i, j) where r <= i <= r + h - 1 and + * c - (i - r) <= j <= c + (i - r). + * + * An inverse pyramidal plot of land can be defined as a set of cells with similar criteria: + * 1. The number of cells in the set has to be greater than 1 and all cells must be fertile. + * 2. The apex of an inverse pyramid is the bottommost cell of the inverse pyramid. The height + * of an inverse pyramid is the number of rows it covers. Let (r, c) be the apex of the + * pyramid, and its height be h. Then, the plot comprises of cells (i, j) where + * r - h + 1 <= i <= r and c - (r - i) <= j <= c + (r - i). + * + * Some examples of valid and invalid pyramidal (and inverse pyramidal) plots are shown below. + * Black cells indicate fertile cells. + * + * Given a 0-indexed m x n binary matrix grid representing the farmland, return the total number + * of pyramidal and inverse pyramidal plots that can be found in grid. + */ + +/** + * @param {number[][]} grid + * @return {number} + */ +var countPyramids = function(grid) { + const rows = grid.length; + const cols = grid[0].length; + let result = 0; + + for (let i = 0; i < rows; i++) { + for (let j = 0; j < cols; j++) { + if (grid[i][j] === 1) { + result += countPyramidAt(i, j, false); + result += countPyramidAt(i, j, true); + } + } + } + + return result; + + function countPyramidAt(row, col, isInverse) { + let height = 0; + for (let h = 1; ; h++) { + const r = isInverse ? row - h : row + h; + if (r < 0 || r >= rows) break; + const left = col - h; + const right = col + h; + if (left < 0 || right >= cols) break; + let valid = true; + for (let j = left; j <= right; j++) { + if (grid[r][j] === 0) { + valid = false; + break; + } + } + if (!valid) break; + height++; + } + return height; + } +}; diff --git a/solutions/2089-find-target-indices-after-sorting-array.js b/solutions/2089-find-target-indices-after-sorting-array.js new file mode 100644 index 00000000..c7235faa --- /dev/null +++ b/solutions/2089-find-target-indices-after-sorting-array.js @@ -0,0 +1,32 @@ +/** + * 2089. Find Target Indices After Sorting Array + * https://leetcode.com/problems/find-target-indices-after-sorting-array/ + * Difficulty: Easy + * + * You are given a 0-indexed integer array nums and a target element target. + * + * A target index is an index i such that nums[i] == target. + * + * Return a list of the target indices of nums after sorting nums in non-decreasing order. + * If there are no target indices, return an empty list. The returned list must be sorted + * in increasing order. + */ + +/** + * @param {number[]} nums + * @param {number} target + * @return {number[]} + */ +var targetIndices = function(nums, target) { + const result = []; + + nums.sort((a, b) => a - b); + + for (let i = 0; i < nums.length; i++) { + if (nums[i] === target) { + result.push(i); + } + } + + return result; +}; diff --git a/solutions/2090-k-radius-subarray-averages.js b/solutions/2090-k-radius-subarray-averages.js new file mode 100644 index 00000000..3808077d --- /dev/null +++ b/solutions/2090-k-radius-subarray-averages.js @@ -0,0 +1,46 @@ +/** + * 2090. K Radius Subarray Averages + * https://leetcode.com/problems/k-radius-subarray-averages/ + * Difficulty: Medium + * + * You are given a 0-indexed array nums of n integers, and an integer k. + * + * The k-radius average for a subarray of nums centered at some index i with the radius k is + * the average of all elements in nums between the indices i - k and i + k (inclusive). If + * there are less than k elements before or after the index i, then the k-radius average is -1. + * + * Build and return an array avgs of length n where avgs[i] is the k-radius average for the + * subarray centered at index i. + * + * The average of x elements is the sum of the x elements divided by x, using integer division. + * The integer division truncates toward zero, which means losing its fractional part. + * - For example, the average of four elements 2, 3, 1, and + * 5 is (2 + 3 + 1 + 5) / 4 = 11 / 4 = 2.75, which truncates to 2. + */ + +/** + * @param {number[]} nums + * @param {number} k + * @return {number[]} + */ +var getAverages = function(nums, k) { + const n = nums.length; + const windowSize = 2 * k + 1; + const result = new Array(n).fill(-1); + + if (windowSize > n) return result; + + let sum = 0; + for (let i = 0; i < windowSize; i++) { + sum += nums[i]; + } + + result[k] = Math.floor(sum / windowSize); + + for (let i = k + 1; i < n - k; i++) { + sum = sum - nums[i - k - 1] + nums[i + k]; + result[i] = Math.floor(sum / windowSize); + } + + return result; +}; diff --git a/solutions/2091-removing-minimum-and-maximum-from-array.js b/solutions/2091-removing-minimum-and-maximum-from-array.js new file mode 100644 index 00000000..b62e781e --- /dev/null +++ b/solutions/2091-removing-minimum-and-maximum-from-array.js @@ -0,0 +1,41 @@ +/** + * 2091. Removing Minimum and Maximum From Array + * https://leetcode.com/problems/removing-minimum-and-maximum-from-array/ + * Difficulty: Medium + * + * You are given a 0-indexed array of distinct integers nums. + * + * There is an element in nums that has the lowest value and an element that has the highest + * value. We call them the minimum and maximum respectively. Your goal is to remove both these + * elements from the array. + * + * A deletion is defined as either removing an element from the front of the array or removing + * an element from the back of the array. + * + * Return the minimum number of deletions it would take to remove both the minimum and maximum + * element from the array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var minimumDeletions = function(nums) { + const n = nums.length; + let minIndex = 0; + let maxIndex = 0; + + for (let i = 1; i < n; i++) { + if (nums[i] < nums[minIndex]) minIndex = i; + if (nums[i] > nums[maxIndex]) maxIndex = i; + } + + const left = Math.min(minIndex, maxIndex); + const right = Math.max(minIndex, maxIndex); + + return Math.min( + right + 1, + n - left, + left + 1 + n - right + ); +}; diff --git a/solutions/2092-find-all-people-with-secret.js b/solutions/2092-find-all-people-with-secret.js new file mode 100644 index 00000000..f5fecbdc --- /dev/null +++ b/solutions/2092-find-all-people-with-secret.js @@ -0,0 +1,73 @@ +/** + * 2092. Find All People With Secret + * https://leetcode.com/problems/find-all-people-with-secret/ + * Difficulty: Hard + * + * You are given an integer n indicating there are n people numbered from 0 to n - 1. You are also + * given a 0-indexed 2D integer array meetings where meetings[i] = [xi, yi, timei] indicates that + * person xi and person yi have a meeting at timei. A person may attend multiple meetings at the + * same time. Finally, you are given an integer firstPerson. + * + * Person 0 has a secret and initially shares the secret with a person firstPerson at time 0. This + * secret is then shared every time a meeting takes place with a person that has the secret. More + * formally, for every meeting, if a person xi has the secret at timei, then they will share the + * secret with person yi, and vice versa. + * + * The secrets are shared instantaneously. That is, a person may receive the secret and share it + * with people in other meetings within the same time frame. + * + * Return a list of all the people that have the secret after all the meetings have taken place. + * You may return the answer in any order. + */ + +/** + * @param {number} n + * @param {number[][]} meetings + * @param {number} firstPerson + * @return {number[]} + */ +var findAllPeople = function(n, meetings, firstPerson) { + const parent = Array.from({ length: n }, (_, i) => i); + + union(0, firstPerson); + meetings.sort((a, b) => a[2] - b[2]); + + let i = 0; + while (i < meetings.length) { + const currentTime = meetings[i][2]; + const group = []; + + while (i < meetings.length && meetings[i][2] === currentTime) { + const [x, y] = meetings[i]; + group.push(x, y); + union(x, y); + i++; + } + + for (const person of group) { + if (find(person) !== find(0)) { + parent[person] = person; + } + } + } + + const result = []; + for (let j = 0; j < n; j++) { + if (find(j) === find(0)) { + result.push(j); + } + } + + return result; + + function find(x) { + if (parent[x] !== x) { + parent[x] = find(parent[x]); + } + return parent[x]; + } + + function union(x, y) { + parent[find(x)] = find(y); + } +}; 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/2094-finding-3-digit-even-numbers.js b/solutions/2094-finding-3-digit-even-numbers.js new file mode 100644 index 00000000..f021bdff --- /dev/null +++ b/solutions/2094-finding-3-digit-even-numbers.js @@ -0,0 +1,51 @@ +/** + * 2094. Finding 3-Digit Even Numbers + * https://leetcode.com/problems/finding-3-digit-even-numbers/ + * Difficulty: Easy + * + * You are given an integer array digits, where each element is a digit. The array may contain + * duplicates. + * + * You need to find all the unique integers that follow the given requirements: + * - The integer consists of the concatenation of three elements from digits in any arbitrary order. + * - The integer does not have leading zeros. + * - The integer is even. + * + * For example, if the given digits were [1, 2, 3], integers 132 and 312 follow the requirements. + * + * Return a sorted array of the unique integers. + */ + +/** + * @param {number[]} digits + * @return {number[]} + */ +var findEvenNumbers = function(digits) { + const frequency = new Array(10).fill(0); + const uniqueNumbers = new Set(); + + for (const digit of digits) { + frequency[digit]++; + } + + for (let hundreds = 1; hundreds <= 9; hundreds++) { + if (frequency[hundreds] === 0) continue; + frequency[hundreds]--; + + for (let tens = 0; tens <= 9; tens++) { + if (frequency[tens] === 0) continue; + frequency[tens]--; + + for (let ones = 0; ones <= 8; ones += 2) { + if (frequency[ones] === 0) continue; + uniqueNumbers.add(hundreds * 100 + tens * 10 + ones); + } + + frequency[tens]++; + } + + frequency[hundreds]++; + } + + return Array.from(uniqueNumbers).sort((a, b) => a - b); +}; diff --git a/solutions/2096-step-by-step-directions-from-a-binary-tree-node-to-another.js b/solutions/2096-step-by-step-directions-from-a-binary-tree-node-to-another.js new file mode 100644 index 00000000..4eb7d4e9 --- /dev/null +++ b/solutions/2096-step-by-step-directions-from-a-binary-tree-node-to-another.js @@ -0,0 +1,65 @@ +/** + * 2096. Step-By-Step Directions From a Binary Tree Node to Another + * https://leetcode.com/problems/step-by-step-directions-from-a-binary-tree-node-to-another/ + * Difficulty: Medium + * + * You are given the root of a binary tree with n nodes. Each node is uniquely assigned a value + * from 1 to n. You are also given an integer startValue representing the value of the start node + * s, and a different integer destValue representing the value of the destination node t. + * + * Find the shortest path starting from node s and ending at node t. Generate step-by-step + * directions of such path as a string consisting of only the uppercase letters 'L', 'R', and + * 'U'. Each letter indicates a specific direction: + * - 'L' means to go from a node to its left child node. + * - 'R' means to go from a node to its right child node. + * - 'U' means to go from a node to its parent node. + * + * Return the step-by-step directions of the shortest path from node s to node t. + */ + +/** + * 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} startValue + * @param {number} destValue + * @return {string} + */ +var getDirections = function(root, startValue, destValue) { + const startPath = []; + const destPath = []; + + findPath(root, startValue, startPath); + findPath(root, destValue, destPath); + + let i = 0; + while (i < startPath.length && i < destPath.length && startPath[i] === destPath[i]) { + i++; + } + + const upMoves = 'U'.repeat(startPath.length - i); + const downMoves = destPath.slice(i).join(''); + + return upMoves + downMoves; + + function findPath(node, value, path) { + if (!node) return false; + if (node.val === value) return true; + + path.push('L'); + if (findPath(node.left, value, path)) return true; + path.pop(); + + path.push('R'); + if (findPath(node.right, value, path)) return true; + path.pop(); + + return false; + } +}; diff --git a/solutions/2097-valid-arrangement-of-pairs.js b/solutions/2097-valid-arrangement-of-pairs.js new file mode 100644 index 00000000..d3c5ee1c --- /dev/null +++ b/solutions/2097-valid-arrangement-of-pairs.js @@ -0,0 +1,50 @@ +/** + * 2097. Valid Arrangement of Pairs + * https://leetcode.com/problems/valid-arrangement-of-pairs/ + * Difficulty: Hard + * + * You are given a 0-indexed 2D integer array pairs where pairs[i] = [starti, endi]. An arrangement + * of pairs is valid if for every index i where 1 <= i < pairs.length, we have endi-1 == starti. + * + * Return any valid arrangement of pairs. + * + * Note: The inputs will be generated such that there exists a valid arrangement of pairs. + */ + +/** + * @param {number[][]} pairs + * @return {number[][]} + */ +var validArrangement = function(pairs) { + const graph = new Map(); + const degree = new Map(); + + for (const [start, end] of pairs) { + if (!graph.has(start)) graph.set(start, []); + graph.get(start).push(end); + + degree.set(start, (degree.get(start) || 0) + 1); + degree.set(end, (degree.get(end) || 0) - 1); + } + + let startNode = pairs[0][0]; + for (const [node, deg] of degree) { + if (deg > 0) { + startNode = node; + break; + } + } + + const result = []; + helper(startNode); + + return result.reverse(); + + function helper(node) { + while (graph.get(node)?.length) { + const next = graph.get(node).pop(); + helper(next); + result.push([node, next]); + } + } +}; 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/2100-find-good-days-to-rob-the-bank.js b/solutions/2100-find-good-days-to-rob-the-bank.js new file mode 100644 index 00000000..1dc59611 --- /dev/null +++ b/solutions/2100-find-good-days-to-rob-the-bank.js @@ -0,0 +1,50 @@ +/** + * 2100. Find Good Days to Rob the Bank + * https://leetcode.com/problems/find-good-days-to-rob-the-bank/ + * Difficulty: Medium + * + * You and a gang of thieves are planning on robbing a bank. You are given a 0-indexed integer + * array security, where security[i] is the number of guards on duty on the ith day. The days + * are numbered starting from 0. You are also given an integer time. + * + * The ith day is a good day to rob the bank if: + * - There are at least time days before and after the ith day, + * - The number of guards at the bank for the time days before i are non-increasing, and + * - The number of guards at the bank for the time days after i are non-decreasing. + * + * More formally, this means day i is a good day to rob the bank if and only if + * security[i - time] >= security[i - time + 1] >= ... >= security[i] + * <= ... <= security[i + time - 1] <= security[i + time]. + * + * Return a list of all days (0-indexed) that are good days to rob the bank. The order that the + * days are returned in does not matter. + */ + +/** + * @param {number[]} security + * @param {number} time + * @return {number[]} + */ +var goodDaysToRobBank = function(security, time) { + const n = security.length; + const nonIncreasing = new Array(n).fill(0); + const nonDecreasing = new Array(n).fill(0); + const result = []; + + for (let i = 1; i < n; i++) { + if (security[i] <= security[i - 1]) { + nonIncreasing[i] = nonIncreasing[i - 1] + 1; + } + if (security[n - i - 1] <= security[n - i]) { + nonDecreasing[n - i - 1] = nonDecreasing[n - i] + 1; + } + } + + for (let i = time; i < n - time; i++) { + if (nonIncreasing[i] >= time && nonDecreasing[i] >= time) { + result.push(i); + } + } + + return result; +}; diff --git a/solutions/2101-detonate-the-maximum-bombs.js b/solutions/2101-detonate-the-maximum-bombs.js new file mode 100644 index 00000000..11069857 --- /dev/null +++ b/solutions/2101-detonate-the-maximum-bombs.js @@ -0,0 +1,57 @@ +/** + * 2101. Detonate the Maximum Bombs + * https://leetcode.com/problems/detonate-the-maximum-bombs/ + * Difficulty: Medium + * + * You are given a list of bombs. The range of a bomb is defined as the area where its effect + * can be felt. This area is in the shape of a circle with the center as the location of the bomb. + * + * The bombs are represented by a 0-indexed 2D integer array bombs where bombs[i] = [xi, yi, ri]. + * xi and yi denote the X-coordinate and Y-coordinate of the location of the ith bomb, whereas ri + * denotes the radius of its range. + * + * You may choose to detonate a single bomb. When a bomb is detonated, it will detonate all bombs + * that lie in its range. These bombs will further detonate the bombs that lie in their ranges. + * + * Given the list of bombs, return the maximum number of bombs that can be detonated if you are + * allowed to detonate only one bomb. + */ + +/** + * @param {number[][]} bombs + * @return {number} + */ +var maximumDetonation = function(bombs) { + const n = bombs.length; + const graph = Array.from({ length: n }, () => []); + + for (let i = 0; i < n; i++) { + const [x1, y1, r1] = bombs[i]; + for (let j = 0; j < n; j++) { + if (i === j) continue; + const [x2, y2] = bombs[j]; + const distance = Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2); + if (distance <= r1) { + graph[i].push(j); + } + } + } + + let result = 0; + for (let i = 0; i < n; i++) { + result = Math.max(result, dfs(i, new Set())); + } + + return result; + + function dfs(node, visited) { + visited.add(node); + let count = 1; + for (const neighbor of graph[node]) { + if (!visited.has(neighbor)) { + count += dfs(neighbor, visited); + } + } + return count; + } +}; 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/2103-rings-and-rods.js b/solutions/2103-rings-and-rods.js new file mode 100644 index 00000000..b7cc219e --- /dev/null +++ b/solutions/2103-rings-and-rods.js @@ -0,0 +1,42 @@ +/** + * 2103. Rings and Rods + * https://leetcode.com/problems/rings-and-rods/ + * Difficulty: Easy + * + * There are n rings and each ring is either red, green, or blue. The rings are distributed across + * ten rods labeled from 0 to 9. + * + * You are given a string rings of length 2n that describes the n rings that are placed onto the + * rods. Every two characters in rings forms a color-position pair that is used to describe each + * ring where: + * - The first character of the ith pair denotes the ith ring's color ('R', 'G', 'B'). + * - The second character of the ith pair denotes the rod that the ith ring is placed on + * ('0' to '9'). + * + * For example, "R3G2B1" describes n == 3 rings: a red ring placed onto the rod labeled 3, a green + * ring placed onto the rod labeled 2, and a blue ring placed onto the rod labeled 1. + * + * Return the number of rods that have all three colors of rings on them. + */ + +/** + * @param {string} rings + * @return {number} + */ +var countPoints = function(rings) { + const map = new Map(); + + for (let i = 0; i < rings.length; i += 2) { + const color = rings[i]; + const rod = rings[i + 1]; + if (!map.has(rod)) map.set(rod, new Set()); + map.get(rod).add(color); + } + + let result = 0; + for (const colors of map.values()) { + if (colors.size === 3) result++; + } + + return result; +}; diff --git a/solutions/2104-sum-of-subarray-ranges.js b/solutions/2104-sum-of-subarray-ranges.js new file mode 100644 index 00000000..0efaf1d7 --- /dev/null +++ b/solutions/2104-sum-of-subarray-ranges.js @@ -0,0 +1,33 @@ +/** + * 2104. Sum of Subarray Ranges + * https://leetcode.com/problems/sum-of-subarray-ranges/ + * Difficulty: Medium + * + * You are given an integer array nums. The range of a subarray of nums is the difference between + * the largest and smallest element in the subarray. + * + * Return the sum of all subarray ranges of nums. + * + * A subarray is a contiguous non-empty sequence of elements within an array. + */ + +/** + * @param {number[]} nums + * @return {number} + */ +var subArrayRanges = function(nums) { + let result = 0; + + for (let i = 0; i < nums.length; i++) { + let min = nums[i]; + let max = nums[i]; + + for (let j = i; j < nums.length; j++) { + min = Math.min(min, nums[j]); + max = Math.max(max, nums[j]); + result += max - min; + } + } + + return result; +}; diff --git a/solutions/2105-watering-plants-ii.js b/solutions/2105-watering-plants-ii.js new file mode 100644 index 00000000..dcdaf994 --- /dev/null +++ b/solutions/2105-watering-plants-ii.js @@ -0,0 +1,61 @@ +/** + * 2105. Watering Plants II + * https://leetcode.com/problems/watering-plants-ii/ + * Difficulty: Medium + * + * Alice and Bob want to water n plants in their garden. The plants are arranged in a row and are + * labeled from 0 to n - 1 from left to right where the ith plant is located at x = i. + * + * Each plant needs a specific amount of water. Alice and Bob have a watering can each, initially + * full. They water the plants in the following way: + * - Alice waters the plants in order from left to right, starting from the 0th plant. Bob waters + * the plants in order from right to left, starting from the (n - 1)th plant. They begin watering + * the plants simultaneously. + * - It takes the same amount of time to water each plant regardless of how much water it needs. + * - Alice/Bob must water the plant if they have enough in their can to fully water it. Otherwise, + * they first refill their can (instantaneously) then water the plant. + * - In case both Alice and Bob reach the same plant, the one with more water currently in his/her + * watering can should water this plant. If they have the same amount of water, then Alice should + * water this plant. + * + * Given a 0-indexed integer array plants of n integers, where plants[i] is the amount of water the + * ith plant needs, and two integers capacityA and capacityB representing the capacities of Alice's + * and Bob's watering cans respectively, return the number of times they have to refill to water all + * the plants. + */ + +/** + * @param {number[]} plants + * @param {number} capacityA + * @param {number} capacityB + * @return {number} + */ +var minimumRefill = function(plants, capacityA, capacityB) { + let result = 0; + let left = 0; + let right = plants.length - 1; + let waterA = capacityA; + let waterB = capacityB; + + while (left <= right) { + if (left === right) { + if (waterA >= waterB && waterA < plants[left]) result++; + if (waterB > waterA && waterB < plants[right]) result++; + break; + } + + if (waterA < plants[left]) { + waterA = capacityA; + result++; + } + waterA -= plants[left++]; + + if (waterB < plants[right]) { + waterB = capacityB; + result++; + } + waterB -= plants[right--]; + } + + return result; +}; diff --git a/solutions/2106-maximum-fruits-harvested-after-at-most-k-steps.js b/solutions/2106-maximum-fruits-harvested-after-at-most-k-steps.js new file mode 100644 index 00000000..bd81e17e --- /dev/null +++ b/solutions/2106-maximum-fruits-harvested-after-at-most-k-steps.js @@ -0,0 +1,52 @@ +/** + * 2106. Maximum Fruits Harvested After at Most K Steps + * https://leetcode.com/problems/maximum-fruits-harvested-after-at-most-k-steps/ + * Difficulty: Hard + * + * Fruits are available at some positions on an infinite x-axis. You are given a 2D integer array + * fruits where fruits[i] = [positioni, amounti] depicts amounti fruits at the position positioni. + * fruits is already sorted by positioni in ascending order, and each positioni is unique. + * + * You are also given an integer startPos and an integer k. Initially, you are at the position + * startPos. From any position, you can either walk to the left or right. It takes one step to + * move one unit on the x-axis, and you can walk at most k steps in total. For every position + * you reach, you harvest all the fruits at that position, and the fruits will disappear from + * that position. + * + * Return the maximum total number of fruits you can harvest. + */ + +/** + * @param {number[][]} fruits + * @param {number} startPos + * @param {number} k + * @return {number} + */ +var maxTotalFruits = function(fruits, startPos, k) { + let result = 0; + let left = 0; + let currentSum = 0; + + for (let right = 0; right < fruits.length; right++) { + currentSum += fruits[right][1]; + + while (left <= right) { + const minPos = fruits[left][0]; + const maxPos = fruits[right][0]; + const steps = Math.min( + Math.abs(startPos - minPos) + (maxPos - minPos), + Math.abs(startPos - maxPos) + (maxPos - minPos) + ); + + if (steps <= k) break; + currentSum -= fruits[left][1]; + left++; + } + + if (left <= right) { + result = Math.max(result, currentSum); + } + } + + return result; +}; 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/2108-find-first-palindromic-string-in-the-array.js b/solutions/2108-find-first-palindromic-string-in-the-array.js new file mode 100644 index 00000000..a72a02b0 --- /dev/null +++ b/solutions/2108-find-first-palindromic-string-in-the-array.js @@ -0,0 +1,23 @@ +/** + * 2108. Find First Palindromic String in the Array + * https://leetcode.com/problems/find-first-palindromic-string-in-the-array/ + * Difficulty: Easy + * + * Given an array of strings words, return the first palindromic string in the array. If there is + * no such string, return an empty string "". + * + * A string is palindromic if it reads the same forward and backward. + */ + +/** + * @param {string[]} words + * @return {string} + */ +var firstPalindrome = function(words) { + for (const word of words) { + if (word === word.split('').reverse().join('')) { + return word; + } + } + return ''; +}; diff --git a/solutions/2109-adding-spaces-to-a-string.js b/solutions/2109-adding-spaces-to-a-string.js new file mode 100644 index 00000000..7f4a85ba --- /dev/null +++ b/solutions/2109-adding-spaces-to-a-string.js @@ -0,0 +1,33 @@ +/** + * 2109. Adding Spaces to a String + * https://leetcode.com/problems/adding-spaces-to-a-string/ + * Difficulty: Medium + * + * You are given a 0-indexed string s and a 0-indexed integer array spaces that describes the + * indices in the original string where spaces will be added. Each space should be inserted + * before the character at the given index. + * - For example, given s = "EnjoyYourCoffee" and spaces = [5, 9], we place spaces before 'Y' + * and 'C', which are at indices 5 and 9 respectively. Thus, we obtain "Enjoy Your Coffee". + * + * Return the modified string after the spaces have been added. + */ + +/** + * @param {string} s + * @param {number[]} spaces + * @return {string} + */ +var addSpaces = function(s, spaces) { + let result = ''; + let spaceIndex = 0; + + for (let i = 0; i < s.length; i++) { + if (spaceIndex < spaces.length && i === spaces[spaceIndex]) { + result += ' '; + spaceIndex++; + } + result += s[i]; + } + + return result; +}; diff --git a/solutions/2110-number-of-smooth-descent-periods-of-a-stock.js b/solutions/2110-number-of-smooth-descent-periods-of-a-stock.js new file mode 100644 index 00000000..09a08e95 --- /dev/null +++ b/solutions/2110-number-of-smooth-descent-periods-of-a-stock.js @@ -0,0 +1,34 @@ +/** + * 2110. Number of Smooth Descent Periods of a Stock + * https://leetcode.com/problems/number-of-smooth-descent-periods-of-a-stock/ + * Difficulty: Medium + * + * You are given an integer array prices representing the daily price history of a stock, + * where prices[i] is the stock price on the ith day. + * + * A smooth descent period of a stock consists of one or more contiguous days such that the + * price on each day is lower than the price on the preceding day by exactly 1. The first + * day of the period is exempted from this rule. + * + * Return the number of smooth descent periods. + */ + +/** + * @param {number[]} prices + * @return {number} + */ +var getDescentPeriods = function(prices) { + let result = 1; + let currentLength = 1; + + for (let i = 1; i < prices.length; i++) { + if (prices[i] === prices[i - 1] - 1) { + currentLength++; + } else { + currentLength = 1; + } + result += currentLength; + } + + return result; +}; diff --git a/solutions/2111-minimum-operations-to-make-the-array-k-increasing.js b/solutions/2111-minimum-operations-to-make-the-array-k-increasing.js new file mode 100644 index 00000000..8f861b84 --- /dev/null +++ b/solutions/2111-minimum-operations-to-make-the-array-k-increasing.js @@ -0,0 +1,58 @@ +/** + * 2111. Minimum Operations to Make the Array K-Increasing + * https://leetcode.com/problems/minimum-operations-to-make-the-array-k-increasing/ + * Difficulty: Hard + * + * You are given a 0-indexed array arr consisting of n positive integers, and a positive integer k. + * + * The array arr is called K-increasing if arr[i-k] <= arr[i] holds for every index i, where + * k <= i <= n-1. + * + * - For example, arr = [4, 1, 5, 2, 6, 2] is K-increasing for k = 2 because: + * - arr[0] <= arr[2] (4 <= 5) + * - arr[1] <= arr[3] (1 <= 2) + * - arr[2] <= arr[4] (5 <= 6) + * - arr[3] <= arr[5] (2 <= 2) + * - However, the same arr is not K-increasing for k = 1 (because arr[0] > arr[1]) or k = 3 (because + * arr[0] > arr[3]). + * + * In one operation, you can choose an index i and change arr[i] into any positive integer. + * + * Return the minimum number of operations required to make the array K-increasing for the given k. + */ + +/** + * @param {number[]} arr + * @param {number} k + * @return {number} + */ +var kIncreasing = function(arr, k) { + let result = 0; + for (let i = 0; i < k; i++) { + const subsequence = []; + for (let j = i; j < arr.length; j += k) { + subsequence.push(arr[j]); + } + result += longestNonDecreasingSubsequence(subsequence); + } + + return result; + + function longestNonDecreasingSubsequence(nums) { + const tails = []; + for (const num of nums) { + let left = 0; + let right = tails.length; + while (left < right) { + const mid = Math.floor((left + right) / 2); + if (tails[mid] <= num) { + left = mid + 1; + } else { + right = mid; + } + } + tails[left] = num; + } + return nums.length - tails.length; + } +}; 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/2117-abbreviating-the-product-of-a-range.js b/solutions/2117-abbreviating-the-product-of-a-range.js new file mode 100644 index 00000000..4334b25b --- /dev/null +++ b/solutions/2117-abbreviating-the-product-of-a-range.js @@ -0,0 +1,91 @@ +/** + * 2117. Abbreviating the Product of a Range + * https://leetcode.com/problems/abbreviating-the-product-of-a-range/ + * Difficulty: Hard + * + * You are given two positive integers left and right with left <= right. Calculate the product of + * all integers in the inclusive range [left, right]. + * + * Since the product may be very large, you will abbreviate it following these steps: + * 1. Count all trailing zeros in the product and remove them. Let us denote this count as C. + * - For example, there are 3 trailing zeros in 1000, and there are 0 trailing zeros in 546. + * 2. Denote the remaining number of digits in the product as d. If d > 10, then express the product + * as
... where 
 denotes the first 5 digits of the product, and  denotes the
+ *    last 5 digits of the product after removing all trailing zeros. If d <= 10, we keep it
+ *    unchanged.
+ *    - For example, we express 1234567654321 as 12345...54321, but 1234567 is represented as
+ *      1234567.
+ * 3. Finally, represent the product as a string "
...eC".
+ *    - For example, 12345678987600000 will be represented as "12345...89876e5".
+ *
+ * Return a string denoting the abbreviated product of all integers in the inclusive range [left,
+ * right].
+ */
+
+/**
+ * @param {number} left
+ * @param {number} right
+ * @return {string}
+ */
+var abbreviateProduct = function(left, right) {
+  let zeros = 0;
+  let count2 = 0;
+  let count5 = 0;
+
+  for (let i = left; i <= right; i++) {
+    let n = i;
+    while (n % 2 === 0) {
+      count2++;
+      n = Math.floor(n / 2);
+    }
+    n = i;
+    while (n % 5 === 0) {
+      count5++;
+      n = Math.floor(n / 5);
+    }
+  }
+  zeros = Math.min(count2, count5);
+
+  let digits = 0;
+  for (let i = left; i <= right; i++) {
+    digits += Math.log10(i);
+  }
+  digits = Math.floor(digits) + 1;
+
+  if (digits - zeros <= 10) {
+    let product = 1n;
+    for (let i = left; i <= right; i++) {
+      product *= BigInt(i);
+    }
+    for (let i = 0; i < zeros; i++) {
+      product /= 10n;
+    }
+    return product.toString() + 'e' + zeros;
+  }
+
+  let prefix = 1;
+  for (let i = left; i <= right; i++) {
+    prefix *= i;
+    while (prefix >= 1e10) {
+      prefix /= 10;
+    }
+  }
+  prefix = prefix.toString().slice(0, 5);
+
+  let suffix = 1n;
+  for (let i = right; i >= left; i--) {
+    suffix = (suffix * BigInt(i));
+    while (suffix % 10n === 0n) {
+      suffix /= 10n;
+    }
+    suffix = suffix % (10n ** 15n);
+  }
+
+  suffix = suffix.toString();
+  while (suffix.length < 5) {
+    suffix = '0' + suffix;
+  }
+  suffix = suffix.slice(-5);
+
+  return prefix + '...' + suffix + 'e' + zeros;
+};
diff --git a/solutions/2119-a-number-after-a-double-reversal.js b/solutions/2119-a-number-after-a-double-reversal.js
new file mode 100644
index 00000000..efc1d321
--- /dev/null
+++ b/solutions/2119-a-number-after-a-double-reversal.js
@@ -0,0 +1,20 @@
+/**
+ * 2119. A Number After a Double Reversal
+ * https://leetcode.com/problems/a-number-after-a-double-reversal/
+ * Difficulty: Easy
+ *
+ * Reversing an integer means to reverse all its digits.
+ * - For example, reversing 2021 gives 1202. Reversing 12300 gives 321 as the leading zeros
+ *   are not retained.
+ *
+ * Given an integer num, reverse num to get reversed1, then reverse reversed1 to get reversed2.
+ * Return true if reversed2 equals num. Otherwise return false.
+ */
+
+/**
+ * @param {number} num
+ * @return {boolean}
+ */
+var isSameAfterReversals = function(num) {
+  return num === 0 || num % 10 !== 0;
+};
diff --git a/solutions/2120-execution-of-all-suffix-instructions-staying-in-a-grid.js b/solutions/2120-execution-of-all-suffix-instructions-staying-in-a-grid.js
new file mode 100644
index 00000000..940ddc72
--- /dev/null
+++ b/solutions/2120-execution-of-all-suffix-instructions-staying-in-a-grid.js
@@ -0,0 +1,51 @@
+/**
+ * 2120. Execution of All Suffix Instructions Staying in a Grid
+ * https://leetcode.com/problems/execution-of-all-suffix-instructions-staying-in-a-grid/
+ * Difficulty: Medium
+ *
+ * There is an n x n grid, with the top-left cell at (0, 0) and the bottom-right cell at
+ * (n - 1, n - 1). You are given the integer n and an integer array startPos where
+ * startPos = [startrow, startcol] indicates that a robot is initially at cell (startrow, startcol).
+ *
+ * You are also given a 0-indexed string s of length m where s[i] is the ith instruction for the
+ * robot: 'L' (move left), 'R' (move right), 'U' (move up), and 'D' (move down).
+ *
+ * The robot can begin executing from any ith instruction in s. It executes the instructions one
+ * by one towards the end of s but it stops if either of these conditions is met:
+ * - The next instruction will move the robot off the grid.
+ * - There are no more instructions left to execute.
+ *
+ * Return an array answer of length m where answer[i] is the number of instructions the robot can
+ * execute if the robot begins executing from the ith instruction in s.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[]} startPos
+ * @param {string} s
+ * @return {number[]}
+ */
+var executeInstructions = function(n, startPos, s) {
+  const m = s.length;
+  const result = new Array(m).fill(0);
+
+  for (let i = 0; i < m; i++) {
+    let row = startPos[0];
+    let col = startPos[1];
+    let steps = 0;
+
+    for (let j = i; j < m; j++) {
+      if (s[j] === 'L') col--;
+      else if (s[j] === 'R') col++;
+      else if (s[j] === 'U') row--;
+      else row++;
+
+      if (row < 0 || row >= n || col < 0 || col >= n) break;
+      steps++;
+    }
+
+    result[i] = steps;
+  }
+
+  return result;
+};
diff --git a/solutions/2121-intervals-between-identical-elements.js b/solutions/2121-intervals-between-identical-elements.js
new file mode 100644
index 00000000..3686726b
--- /dev/null
+++ b/solutions/2121-intervals-between-identical-elements.js
@@ -0,0 +1,48 @@
+/**
+ * 2121. Intervals Between Identical Elements
+ * https://leetcode.com/problems/intervals-between-identical-elements/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed array of n integers arr.
+ *
+ * The interval between two elements in arr is defined as the absolute difference between their
+ * indices. More formally, the interval between arr[i] and arr[j] is |i - j|.
+ *
+ * Return an array intervals of length n where intervals[i] is the sum of intervals between arr[i]
+ * and each element in arr with the same value as arr[i].
+ *
+ * Note: |x| is the absolute value of x.
+ */
+
+/**
+ * @param {number[]} arr
+ * @return {number[]}
+ */
+var getDistances = function(arr) {
+  const valueIndices = new Map();
+  const result = new Array(arr.length).fill(0);
+
+  for (let i = 0; i < arr.length; i++) {
+    if (!valueIndices.has(arr[i])) {
+      valueIndices.set(arr[i], []);
+    }
+    valueIndices.get(arr[i]).push(i);
+  }
+
+  for (const indices of valueIndices.values()) {
+    let prefixSum = 0;
+    for (let i = 1; i < indices.length; i++) {
+      prefixSum += indices[i] - indices[0];
+    }
+
+    result[indices[0]] = prefixSum;
+
+    for (let i = 1; i < indices.length; i++) {
+      const diff = indices[i] - indices[i - 1];
+      prefixSum += diff * (i - (indices.length - i));
+      result[indices[i]] = prefixSum;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2122-recover-the-original-array.js b/solutions/2122-recover-the-original-array.js
new file mode 100644
index 00000000..7b6030fb
--- /dev/null
+++ b/solutions/2122-recover-the-original-array.js
@@ -0,0 +1,55 @@
+/**
+ * 2122. Recover the Original Array
+ * https://leetcode.com/problems/recover-the-original-array/
+ * Difficulty: Hard
+ *
+ * Alice had a 0-indexed array arr consisting of n positive integers. She chose an arbitrary
+ * positive integer k and created two new 0-indexed integer arrays lower and higher in the
+ * following manner:
+ * 1. lower[i] = arr[i] - k, for every index i where 0 <= i < n
+ * 2. higher[i] = arr[i] + k, for every index i where 0 <= i < n
+ *
+ * Unfortunately, Alice lost all three arrays. However, she remembers the integers that were
+ * present in the arrays lower and higher, but not the array each integer belonged to. Help
+ * Alice and recover the original array.
+ *
+ * Given an array nums consisting of 2n integers, where exactly n of the integers were present
+ * in lower and the remaining in higher, return the original array arr. In case the answer is
+ * not unique, return any valid array.
+ *
+ * Note: The test cases are generated such that there exists at least one valid array arr.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var recoverArray = function(nums) {
+  const n = nums.length / 2;
+  nums.sort((a, b) => a - b);
+
+  for (let i = 1; i < 2 * n; i++) {
+    const k = nums[i] - nums[0];
+    if (k <= 0 || k % 2 !== 0) continue;
+
+    const original = [];
+    const used = new Array(2 * n).fill(false);
+    let count = 0;
+
+    for (let left = 0, right = i; right < 2 * n && count < n; right++) {
+      while (left < right && used[left]) left++;
+      if (left >= right) continue;
+
+      if (nums[right] - nums[left] === k) {
+        original.push(nums[left] + k / 2);
+        used[left] = used[right] = true;
+        count++;
+        left++;
+      }
+    }
+
+    if (count === n) return original;
+  }
+
+  return [];
+};
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/2124-check-if-all-as-appears-before-all-bs.js b/solutions/2124-check-if-all-as-appears-before-all-bs.js
new file mode 100644
index 00000000..57f06772
--- /dev/null
+++ b/solutions/2124-check-if-all-as-appears-before-all-bs.js
@@ -0,0 +1,23 @@
+/**
+ * 2124. Check if All A's Appears Before All B's
+ * https://leetcode.com/problems/check-if-all-as-appears-before-all-bs/
+ * Difficulty: Easy
+ *
+ * Given a string s consisting of only the characters 'a' and 'b', return true if every 'a' appears
+ * before every 'b' in the string. Otherwise, return false.
+ */
+
+/**
+ * @param {string} s
+ * @return {boolean}
+ */
+var checkString = function(s) {
+  let seen = false;
+
+  for (const char of s) {
+    if (char === 'b') seen = true;
+    else if (seen) return false;
+  }
+
+  return true;
+};
diff --git a/solutions/2125-number-of-laser-beams-in-a-bank.js b/solutions/2125-number-of-laser-beams-in-a-bank.js
new file mode 100644
index 00000000..58a8afb7
--- /dev/null
+++ b/solutions/2125-number-of-laser-beams-in-a-bank.js
@@ -0,0 +1,40 @@
+/**
+ * 2125. Number of Laser Beams in a Bank
+ * https://leetcode.com/problems/number-of-laser-beams-in-a-bank/
+ * Difficulty: Medium
+ *
+ * Anti-theft security devices are activated inside a bank. You are given a 0-indexed binary string
+ * array bank representing the floor plan of the bank, which is an m x n 2D matrix. bank[i]
+ * represents the ith row, consisting of '0's and '1's. '0' means the cell is empty, while'1'
+ * means the cell has a security device.
+ *
+ * There is one laser beam between any two security devices if both conditions are met:
+ * - The two devices are located on two different rows: r1 and r2, where r1 < r2.
+ * - For each row i where r1 < i < r2, there are no security devices in the ith row.
+ *
+ * Laser beams are independent, i.e., one beam does not interfere nor join with another.
+ *
+ * Return the total number of laser beams in the bank.
+ */
+
+/**
+ * @param {string[]} bank
+ * @return {number}
+ */
+var numberOfBeams = function(bank) {
+  let result = 0;
+  let prevDevices = 0;
+
+  for (const row of bank) {
+    let currentDevices = 0;
+    for (const cell of row) {
+      if (cell === '1') currentDevices++;
+    }
+    if (currentDevices > 0) {
+      result += prevDevices * currentDevices;
+      prevDevices = currentDevices;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2126-destroying-asteroids.js b/solutions/2126-destroying-asteroids.js
new file mode 100644
index 00000000..8c0ff17e
--- /dev/null
+++ b/solutions/2126-destroying-asteroids.js
@@ -0,0 +1,31 @@
+/**
+ * 2126. Destroying Asteroids
+ * https://leetcode.com/problems/destroying-asteroids/
+ * Difficulty: Medium
+ *
+ * You are given an integer mass, which represents the original mass of a planet. You are further
+ * given an integer array asteroids, where asteroids[i] is the mass of the ith asteroid.
+ *
+ * You can arrange for the planet to collide with the asteroids in any arbitrary order. If the mass
+ * of the planet is greater than or equal to the mass of the asteroid, the asteroid is destroyed
+ * and the planet gains the mass of the asteroid. Otherwise, the planet is destroyed.
+ *
+ * Return true if all asteroids can be destroyed. Otherwise, return false.
+ */
+
+/**
+ * @param {number} mass
+ * @param {number[]} asteroids
+ * @return {boolean}
+ */
+var asteroidsDestroyed = function(mass, asteroids) {
+  asteroids.sort((a, b) => a - b);
+
+  let planetMass = BigInt(mass);
+  for (const asteroid of asteroids) {
+    if (planetMass < BigInt(asteroid)) return false;
+    planetMass += BigInt(asteroid);
+  }
+
+  return true;
+};
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/2131-longest-palindrome-by-concatenating-two-letter-words.js b/solutions/2131-longest-palindrome-by-concatenating-two-letter-words.js
new file mode 100644
index 00000000..296b3bd0
--- /dev/null
+++ b/solutions/2131-longest-palindrome-by-concatenating-two-letter-words.js
@@ -0,0 +1,47 @@
+/**
+ * 2131. Longest Palindrome by Concatenating Two Letter Words
+ * https://leetcode.com/problems/longest-palindrome-by-concatenating-two-letter-words/
+ * Difficulty: Medium
+ *
+ * You are given an array of strings words. Each element of words consists of two lowercase
+ * English letters.
+ *
+ * Create the longest possible palindrome by selecting some elements from words and concatenating
+ * them in any order. Each element can be selected at most once.
+ *
+ * Return the length of the longest palindrome that you can create. If it is impossible to create
+ * any palindrome, return 0.
+ *
+ * A palindrome is a string that reads the same forward and backward.
+ */
+
+/**
+ * @param {string[]} words
+ * @return {number}
+ */
+var longestPalindrome = function(words) {
+  const map = new Map();
+  let length = 0;
+  let hasCenter = false;
+
+  for (const word of words) {
+    map.set(word, (map.get(word) || 0) + 1);
+  }
+
+  for (const word of map.keys()) {
+    const reverse = word[1] + word[0];
+
+    if (word === reverse) {
+      const count = map.get(word);
+      length += Math.floor(count / 2) * 4;
+      if (count % 2 === 1) hasCenter = true;
+    } else if (map.has(reverse)) {
+      const pairs = Math.min(map.get(word), map.get(reverse));
+      length += pairs * 4;
+      map.set(word, 0);
+      map.set(reverse, 0);
+    }
+  }
+
+  return hasCenter ? length + 2 : length;
+};
diff --git a/solutions/2132-stamping-the-grid.js b/solutions/2132-stamping-the-grid.js
new file mode 100644
index 00000000..3143e1e3
--- /dev/null
+++ b/solutions/2132-stamping-the-grid.js
@@ -0,0 +1,64 @@
+/**
+ * 2132. Stamping the Grid
+ * https://leetcode.com/problems/stamping-the-grid/
+ * Difficulty: Hard
+ *
+ * You are given an m x n binary matrix grid where each cell is either 0 (empty) or 1 (occupied).
+ *
+ * You are then given stamps of size stampHeight x stampWidth. We want to fit the stamps such that
+ * they follow the given restrictions and requirements:
+ * 1. Cover all the empty cells.
+ * 2. Do not cover any of the occupied cells.
+ * 3. We can put as many stamps as we want.
+ * 4. Stamps can overlap with each other.
+ * 5. Stamps are not allowed to be rotated.
+ * 6. Stamps must stay completely inside the grid.
+ *
+ * Return true if it is possible to fit the stamps while following the given restrictions and
+ * requirements. Otherwise, return false.
+ */
+
+/**
+ * @param {number[][]} grid
+ * @param {number} stampHeight
+ * @param {number} stampWidth
+ * @return {boolean}
+ */
+var possibleToStamp = function(grid, stampHeight, stampWidth) {
+  const rows = grid.length;
+  const cols = grid[0].length;
+  const prefixSum = new Array(rows + 1).fill().map(() => new Array(cols + 1).fill(0));
+  const diff = new Array(rows + 1).fill().map(() => new Array(cols + 1).fill(0));
+
+  for (let i = 0; i < rows; i++) {
+    for (let j = 0; j < cols; j++) {
+      prefixSum[i + 1][j + 1] = prefixSum[i + 1][j] + prefixSum[i][j + 1]
+        - prefixSum[i][j] + grid[i][j];
+    }
+  }
+
+  for (let i = 0; i <= rows - stampHeight; i++) {
+    for (let j = 0; j <= cols - stampWidth; j++) {
+      const x = i + stampHeight;
+      const y = j + stampWidth;
+      if (prefixSum[x][y] - prefixSum[x][j] - prefixSum[i][y] + prefixSum[i][j] === 0) {
+        diff[i][j]++;
+        diff[i][y]--;
+        diff[x][j]--;
+        diff[x][y]++;
+      }
+    }
+  }
+
+  const covered = new Array(rows).fill().map(() => new Array(cols).fill(0));
+  for (let i = 0; i < rows; i++) {
+    for (let j = 0; j < cols; j++) {
+      covered[i][j] = (i > 0 ? covered[i - 1][j] : 0)
+        + (j > 0 ? covered[i][j - 1] : 0)
+        - (i > 0 && j > 0 ? covered[i - 1][j - 1] : 0) + diff[i][j];
+      if (grid[i][j] === 0 && covered[i][j] === 0) return false;
+    }
+  }
+
+  return true;
+};
diff --git a/solutions/2133-check-if-every-row-and-column-contains-all-numbers.js b/solutions/2133-check-if-every-row-and-column-contains-all-numbers.js
new file mode 100644
index 00000000..e8d6990a
--- /dev/null
+++ b/solutions/2133-check-if-every-row-and-column-contains-all-numbers.js
@@ -0,0 +1,33 @@
+/**
+ * 2133. Check if Every Row and Column Contains All Numbers
+ * https://leetcode.com/problems/check-if-every-row-and-column-contains-all-numbers/
+ * Difficulty: Easy
+ *
+ * An n x n matrix is valid if every row and every column contains all the integers from 1
+ * to n (inclusive).
+ *
+ * Given an n x n integer matrix matrix, return true if the matrix is valid. Otherwise,
+ * return false.
+ */
+
+/**
+ * @param {number[][]} matrix
+ * @return {boolean}
+ */
+var checkValid = function(matrix) {
+  const n = matrix.length;
+
+  for (let i = 0; i < n; i++) {
+    const rowSet = new Set();
+    const colSet = new Set();
+
+    for (let j = 0; j < n; j++) {
+      rowSet.add(matrix[i][j]);
+      colSet.add(matrix[j][i]);
+    }
+
+    if (rowSet.size !== n || colSet.size !== n) return false;
+  }
+
+  return true;
+};
diff --git a/solutions/2134-minimum-swaps-to-group-all-1s-together-ii.js b/solutions/2134-minimum-swaps-to-group-all-1s-together-ii.js
new file mode 100644
index 00000000..1105dced
--- /dev/null
+++ b/solutions/2134-minimum-swaps-to-group-all-1s-together-ii.js
@@ -0,0 +1,38 @@
+/**
+ * 2134. Minimum Swaps to Group All 1's Together II
+ * https://leetcode.com/problems/minimum-swaps-to-group-all-1s-together-ii/
+ * Difficulty: Medium
+ *
+ * A swap is defined as taking two distinct positions in an array and swapping the values in them.
+ *
+ * A circular array is defined as an array where we consider the first element and the last element
+ * to be adjacent.
+ *
+ * Given a binary circular array nums, return the minimum number of swaps required to group all
+ * 1's present in the array together at any location.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var minSwaps = function(nums) {
+  const onesCount = nums.reduce((sum, num) => sum + num, 0);
+  const n = nums.length;
+  let result = Infinity;
+  let currentZeros = 0;
+
+  for (let i = 0; i < onesCount; i++) {
+    if (nums[i] === 0) currentZeros++;
+  }
+
+  result = currentZeros;
+
+  for (let i = 1; i < n; i++) {
+    if (nums[(i - 1) % n] === 0) currentZeros--;
+    if (nums[(i + onesCount - 1) % n] === 0) currentZeros++;
+    result = Math.min(result, currentZeros);
+  }
+
+  return result;
+};
diff --git a/solutions/2135-count-words-obtained-after-adding-a-letter.js b/solutions/2135-count-words-obtained-after-adding-a-letter.js
new file mode 100644
index 00000000..c7b08943
--- /dev/null
+++ b/solutions/2135-count-words-obtained-after-adding-a-letter.js
@@ -0,0 +1,49 @@
+/**
+ * 2135. Count Words Obtained After Adding a Letter
+ * https://leetcode.com/problems/count-words-obtained-after-adding-a-letter/
+ * Difficulty: Medium
+ *
+ * You are given two 0-indexed arrays of strings startWords and targetWords. Each string consists
+ * of lowercase English letters only.
+ *
+ * For each string in targetWords, check if it is possible to choose a string from startWords and
+ * perform a conversion operation on it to be equal to that from targetWords.
+ *
+ * The conversion operation is described in the following two steps:
+ * 1. Append any lowercase letter that is not present in the string to its end.
+ *    - For example, if the string is "abc", the letters 'd', 'e', or 'y' can be added to it, but
+ *      not 'a'. If 'd' is added, the resulting string will be "abcd".
+ * 2. Rearrange the letters of the new string in any arbitrary order.
+ *    - For example, "abcd" can be rearranged to "acbd", "bacd", "cbda", and so on. Note that it
+ *      can also be rearranged to "abcd" itself.
+ *
+ * Return the number of strings in targetWords that can be obtained by performing the operations
+ * on any string of startWords.
+ *
+ * Note that you will only be verifying if the string in targetWords can be obtained from a string
+ * in startWords by performing the operations. The strings in startWords do not actually change
+ * during this process.
+ */
+
+/**
+ * @param {string[]} startWords
+ * @param {string[]} targetWords
+ * @return {number}
+ */
+var wordCount = function(startWords, targetWords) {
+  const sortedStartWords = new Set(startWords.map(word => [...word].sort().join('')));
+  let result = 0;
+
+  for (const target of targetWords) {
+    const sortedTarget = [...target].sort().join('');
+    for (let i = 0; i < target.length; i++) {
+      const candidate = sortedTarget.slice(0, i) + sortedTarget.slice(i + 1);
+      if (sortedStartWords.has(candidate)) {
+        result++;
+        break;
+      }
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2136-earliest-possible-day-of-full-bloom.js b/solutions/2136-earliest-possible-day-of-full-bloom.js
new file mode 100644
index 00000000..e4a07b6c
--- /dev/null
+++ b/solutions/2136-earliest-possible-day-of-full-bloom.js
@@ -0,0 +1,39 @@
+/**
+ * 2136. Earliest Possible Day of Full Bloom
+ * https://leetcode.com/problems/earliest-possible-day-of-full-bloom/
+ * Difficulty: Hard
+ *
+ * You have n flower seeds. Every seed must be planted first before it can begin to grow, then
+ * bloom. Planting a seed takes time and so does the growth of a seed. You are given two 0-indexed
+ * integer arrays plantTime and growTime, of length n each:
+ * - plantTime[i] is the number of full days it takes you to plant the ith seed. Every day, you can
+ *   work on planting exactly one seed. You do not have to work on planting the same seed on
+ *   consecutive days, but the planting of a seed is not complete until you have worked plantTime[i]
+ *   days on planting it in total.
+ * - growTime[i] is the number of full days it takes the ith seed to grow after being completely
+ *   planted. After the last day of its growth, the flower blooms and stays bloomed forever.
+ *
+ * From the beginning of day 0, you can plant the seeds in any order.
+ *
+ * Return the earliest possible day where all seeds are blooming.
+ */
+
+/**
+ * @param {number[]} plantTime
+ * @param {number[]} growTime
+ * @return {number}
+ */
+var earliestFullBloom = function(plantTime, growTime) {
+  const seeds = plantTime.map((plant, index) => ({ plant, grow: growTime[index] }));
+  seeds.sort((a, b) => b.grow - a.grow);
+
+  let plantingDays = 0;
+  let result = 0;
+
+  for (const { plant, grow } of seeds) {
+    plantingDays += plant;
+    result = Math.max(result, plantingDays + grow);
+  }
+
+  return result;
+};
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/2138-divide-a-string-into-groups-of-size-k.js b/solutions/2138-divide-a-string-into-groups-of-size-k.js
new file mode 100644
index 00000000..24d0197f
--- /dev/null
+++ b/solutions/2138-divide-a-string-into-groups-of-size-k.js
@@ -0,0 +1,35 @@
+/**
+ * 2138. Divide a String Into Groups of Size k
+ * https://leetcode.com/problems/divide-a-string-into-groups-of-size-k/
+ * Difficulty: Easy
+ *
+ * A string s can be partitioned into groups of size k using the following procedure:
+ * - The first group consists of the first k characters of the string, the second group consists
+ *   of the next k characters of the string, and so on. Each element can be a part of exactly one
+ *   group.
+ * - For the last group, if the string does not have k characters remaining, a character fill is
+ *   used to complete the group.
+ *
+ * Note that the partition is done so that after removing the fill character from the last group
+ * (if it exists) and concatenating all the groups in order, the resultant string should be s.
+ *
+ * Given the string s, the size of each group k and the character fill, return a string array
+ * denoting the composition of every group s has been divided into, using the above procedure.
+ */
+
+/**
+ * @param {string} s
+ * @param {number} k
+ * @param {character} fill
+ * @return {string[]}
+ */
+var divideString = function(s, k, fill) {
+  const paddedString = s + fill.repeat((k - s.length % k) % k);
+  const result = [];
+
+  for (let i = 0; i < paddedString.length; i += k) {
+    result.push(paddedString.slice(i, i + k));
+  }
+
+  return result;
+};
diff --git a/solutions/2139-minimum-moves-to-reach-target-score.js b/solutions/2139-minimum-moves-to-reach-target-score.js
new file mode 100644
index 00000000..a074595f
--- /dev/null
+++ b/solutions/2139-minimum-moves-to-reach-target-score.js
@@ -0,0 +1,40 @@
+/**
+ * 2139. Minimum Moves to Reach Target Score
+ * https://leetcode.com/problems/minimum-moves-to-reach-target-score/
+ * Difficulty: Medium
+ *
+ * You are playing a game with integers. You start with the integer 1 and you want to reach
+ * the integer target.
+ *
+ * In one move, you can either:
+ * - Increment the current integer by one (i.e., x = x + 1).
+ * - Double the current integer (i.e., x = 2 * x).
+ *
+ * You can use the increment operation any number of times, however, you can only use the double
+ * operation at most maxDoubles times.
+ *
+ * Given the two integers target and maxDoubles, return the minimum number of moves needed to
+ * reach target starting with 1.
+ */
+
+/**
+ * @param {number} target
+ * @param {number} maxDoubles
+ * @return {number}
+ */
+var minMoves = function(target, maxDoubles) {
+  let moves = 0;
+  let current = target;
+
+  while (current > 1 && maxDoubles > 0) {
+    if (current % 2 === 0) {
+      current /= 2;
+      maxDoubles--;
+    } else {
+      current--;
+    }
+    moves++;
+  }
+
+  return moves + (current - 1);
+};
diff --git a/solutions/2141-maximum-running-time-of-n-computers.js b/solutions/2141-maximum-running-time-of-n-computers.js
new file mode 100644
index 00000000..b5f7b090
--- /dev/null
+++ b/solutions/2141-maximum-running-time-of-n-computers.js
@@ -0,0 +1,41 @@
+/**
+ * 2141. Maximum Running Time of N Computers
+ * https://leetcode.com/problems/maximum-running-time-of-n-computers/
+ * Difficulty: Hard
+ *
+ * You have n computers. You are given the integer n and a 0-indexed integer array batteries
+ * where the ith battery can run a computer for batteries[i] minutes. You are interested in
+ * running all n computers simultaneously using the given batteries.
+ *
+ * Initially, you can insert at most one battery into each computer. After that and at any
+ * integer time moment, you can remove a battery from a computer and insert another battery
+ * any number of times. The inserted battery can be a totally new battery or a battery from
+ * another computer. You may assume that the removing and inserting processes take no time.
+ *
+ * Note that the batteries cannot be recharged.
+ *
+ * Return the maximum number of minutes you can run all the n computers simultaneously.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[]} batteries
+ * @return {number}
+ */
+var maxRunTime = function(n, batteries) {
+  let left = 1;
+  let right = Math.floor(batteries.reduce((sum, battery) => sum + battery, 0) / n);
+
+  while (left < right) {
+    const mid = Math.floor((left + right + 1) / 2);
+    const total = batteries.reduce((sum, battery) => sum + Math.min(battery, mid), 0);
+
+    if (total >= n * mid) {
+      left = mid;
+    } else {
+      right = mid - 1;
+    }
+  }
+
+  return left;
+};
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/2144-minimum-cost-of-buying-candies-with-discount.js b/solutions/2144-minimum-cost-of-buying-candies-with-discount.js
new file mode 100644
index 00000000..86eca1e2
--- /dev/null
+++ b/solutions/2144-minimum-cost-of-buying-candies-with-discount.js
@@ -0,0 +1,33 @@
+/**
+ * 2144. Minimum Cost of Buying Candies With Discount
+ * https://leetcode.com/problems/minimum-cost-of-buying-candies-with-discount/
+ * Difficulty: Easy
+ *
+ * A shop is selling candies at a discount. For every two candies sold, the shop gives a
+ * third candy for free.
+ *
+ * The customer can choose any candy to take away for free as long as the cost of the
+ * chosen candy is less than or equal to the minimum cost of the two candies bought.
+ *
+ * - For example, if there are 4 candies with costs 1, 2, 3, and 4, and the customer buys
+ *   candies with costs 2 and 3, they can take the candy with cost 1 for free, but not the
+ *   candy with cost 4.
+ *
+ * Given a 0-indexed integer array cost, where cost[i] denotes the cost of the ith candy,
+ * return the minimum cost of buying all the candies.
+ */
+
+/**
+ * @param {number[]} cost
+ * @return {number}
+ */
+var minimumCost = function(cost) {
+  cost.sort((a, b) => b - a);
+  let result = 0;
+
+  for (let i = 0; i < cost.length; i += 3) {
+    result += cost[i] + (cost[i + 1] || 0);
+  }
+
+  return result;
+};
diff --git a/solutions/2145-count-the-hidden-sequences.js b/solutions/2145-count-the-hidden-sequences.js
new file mode 100644
index 00000000..48406074
--- /dev/null
+++ b/solutions/2145-count-the-hidden-sequences.js
@@ -0,0 +1,44 @@
+/**
+ * 2145. Count the Hidden Sequences
+ * https://leetcode.com/problems/count-the-hidden-sequences/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed array of n integers differences, which describes the differences
+ * between each pair of consecutive integers of a hidden sequence of length (n + 1). More formally,
+ * call the hidden sequence hidden, then we have that differences[i] = hidden[i + 1] - hidden[i].
+ *
+ * You are further given two integers lower and upper that describe the inclusive range of values
+ * [lower, upper] that the hidden sequence can contain.
+ *
+ * - For example, given differences = [1, -3, 4], lower = 1, upper = 6, the hidden sequence is a
+ *   sequence of length 4 whose elements are in between 1 and 6 (inclusive).
+ *   - [3, 4, 1, 5] and [4, 5, 2, 6] are possible hidden sequences.
+ *   - [5, 6, 3, 7] is not possible since it contains an element greater than 6.
+ *   - [1, 2, 3, 4] is not possible since the differences are not correct.
+ *
+ * Return the number of possible hidden sequences there are. If there are no possible sequences,
+ * return 0.
+ */
+
+/**
+ * @param {number[]} differences
+ * @param {number} lower
+ * @param {number} upper
+ * @return {number}
+ */
+var numberOfArrays = function(differences, lower, upper) {
+  let minValue = 0;
+  let maxValue = 0;
+  let current = 0;
+
+  for (const diff of differences) {
+    current += diff;
+    minValue = Math.min(minValue, current);
+    maxValue = Math.max(maxValue, current);
+  }
+
+  const range = upper - lower;
+  const validRange = range - (maxValue - minValue);
+
+  return validRange >= 0 ? validRange + 1 : 0;
+};
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/2147-number-of-ways-to-divide-a-long-corridor.js b/solutions/2147-number-of-ways-to-divide-a-long-corridor.js
new file mode 100644
index 00000000..e504b765
--- /dev/null
+++ b/solutions/2147-number-of-ways-to-divide-a-long-corridor.js
@@ -0,0 +1,58 @@
+/**
+ * 2147. Number of Ways to Divide a Long Corridor
+ * https://leetcode.com/problems/number-of-ways-to-divide-a-long-corridor/
+ * Difficulty: Hard
+ *
+ * Along a long library corridor, there is a line of seats and decorative plants. You are given
+ * a 0-indexed string corridor of length n consisting of letters 'S' and 'P' where each 'S'
+ * represents a seat and each 'P' represents a plant.
+ *
+ * One room divider has already been installed to the left of index 0, and another to the right
+ * of index n - 1. Additional room dividers can be installed. For each position between indices
+ * i - 1 and i (1 <= i <= n - 1), at most one divider can be installed.
+ *
+ * Divide the corridor into non-overlapping sections, where each section has exactly two seats
+ * with any number of plants. There may be multiple ways to perform the division. Two ways are
+ * different if there is a position with a room divider installed in the first way but not in
+ * the second way.
+ *
+ * Return the number of ways to divide the corridor. Since the answer may be very large, return
+ * it modulo 109 + 7. If there is no way, return 0.
+ */
+
+/**
+ * @param {string} corridor
+ * @return {number}
+ */
+var numberOfWays = function(corridor) {
+  const MOD = 1e9 + 7;
+  let seatCount = 0;
+  let result = 1;
+  let lastPairEnd = -1;
+
+  for (let i = 0; i < corridor.length; i++) {
+    if (corridor[i] === 'S') {
+      seatCount++;
+    }
+  }
+  if (seatCount === 0 || seatCount % 2 !== 0) {
+    return 0;
+  }
+
+  seatCount = 0;
+
+  for (let i = 0; i < corridor.length; i++) {
+    if (corridor[i] === 'S') {
+      seatCount++;
+
+      if (seatCount % 2 === 0) {
+        lastPairEnd = i;
+      } else if (seatCount > 1) {
+        const plantsCount = i - lastPairEnd - 1;
+        result = (result * (plantsCount + 1)) % MOD;
+      }
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2148-count-elements-with-strictly-smaller-and-greater-elements.js b/solutions/2148-count-elements-with-strictly-smaller-and-greater-elements.js
new file mode 100644
index 00000000..194880af
--- /dev/null
+++ b/solutions/2148-count-elements-with-strictly-smaller-and-greater-elements.js
@@ -0,0 +1,25 @@
+/**
+ * 2148. Count Elements With Strictly Smaller and Greater Elements
+ * https://leetcode.com/problems/count-elements-with-strictly-smaller-and-greater-elements/
+ * Difficulty: Easy
+ *
+ * Given an integer array nums, return the number of elements that have both a strictly
+ * smaller and a strictly greater element appear in nums.
+ */
+
+/**
+* @param {number[]} nums
+* @return {number}
+*/
+var countElements = function(nums) {
+  let result = 0;
+
+  if (nums.length <= 2) return 0;
+  for (const num of nums) {
+    if (num > Math.min(...nums) && num < Math.max(...nums)) {
+      result++;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2149-rearrange-array-elements-by-sign.js b/solutions/2149-rearrange-array-elements-by-sign.js
new file mode 100644
index 00000000..7979e5ef
--- /dev/null
+++ b/solutions/2149-rearrange-array-elements-by-sign.js
@@ -0,0 +1,33 @@
+/**
+ * 2149. Rearrange Array Elements by Sign
+ * https://leetcode.com/problems/rearrange-array-elements-by-sign/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums of even length consisting of an equal number
+ * of positive and negative integers.
+ *
+ * You should return the array of nums such that the the array follows the given conditions:
+ * 1. Every consecutive pair of integers have opposite signs.
+ * 2. For all integers with the same sign, the order in which they were present in nums is
+ *    preserved.
+ * 3. The rearranged array begins with a positive integer.
+ *
+ * Return the modified array after rearranging the elements to satisfy the aforementioned
+ * conditions.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var rearrangeArray = function(nums) {
+  const positives = nums.filter(num => num > 0);
+  const negatives = nums.filter(num => num < 0);
+  const result = [];
+
+  for (let i = 0; i < positives.length; i++) {
+    result.push(positives[i], negatives[i]);
+  }
+
+  return result;
+};
diff --git a/solutions/2150-find-all-lonely-numbers-in-the-array.js b/solutions/2150-find-all-lonely-numbers-in-the-array.js
new file mode 100644
index 00000000..676badc6
--- /dev/null
+++ b/solutions/2150-find-all-lonely-numbers-in-the-array.js
@@ -0,0 +1,31 @@
+/**
+ * 2150. Find All Lonely Numbers in the Array
+ * https://leetcode.com/problems/find-all-lonely-numbers-in-the-array/
+ * Difficulty: Medium
+ *
+ * You are given an integer array nums. A number x is lonely when it appears only once, and
+ * no adjacent numbers (i.e. x + 1 and x - 1) appear in the array.
+ *
+ * Return all lonely numbers in nums. You may return the answer in any order.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var findLonely = function(nums) {
+  const map = new Map();
+
+  for (const num of nums) {
+    map.set(num, (map.get(num) || 0) + 1);
+  }
+
+  const result = [];
+  for (const [num, count] of map) {
+    if (count === 1 && !map.has(num - 1) && !map.has(num + 1)) {
+      result.push(num);
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2151-maximum-good-people-based-on-statements.js b/solutions/2151-maximum-good-people-based-on-statements.js
new file mode 100644
index 00000000..9a5d71cd
--- /dev/null
+++ b/solutions/2151-maximum-good-people-based-on-statements.js
@@ -0,0 +1,59 @@
+/**
+ * 2151. Maximum Good People Based on Statements
+ * https://leetcode.com/problems/maximum-good-people-based-on-statements/
+ * Difficulty: Hard
+ *
+ * There are two types of persons:
+ * - The good person: The person who always tells the truth.
+ * - The bad person: The person who might tell the truth and might lie.
+ *
+ * You are given a 0-indexed 2D integer array statements of size n x n that represents the
+ * statements made by n people about each other. More specifically, statements[i][j] could
+ * be one of the following:
+ * - 0 which represents a statement made by person i that person j is a bad person.
+ * - 1 which represents a statement made by person i that person j is a good person.
+ * - 2 represents that no statement is made by person i about person j.
+ *
+ * Additionally, no person ever makes a statement about themselves. Formally, we have that
+ * statements[i][i] = 2 for all 0 <= i < n.
+ *
+ * Return the maximum number of people who can be good based on the statements made by the
+ * n people.
+ */
+
+/**
+ * @param {number[][]} statements
+ * @return {number}
+ */
+var maximumGood = function(statements) {
+  const n = statements.length;
+  let result = 0;
+
+  backtrack(0, new Array(n).fill(false), 0);
+  return result;
+
+  function isValid(goodPeople) {
+    for (let i = 0; i < n; i++) {
+      if (!goodPeople[i]) continue;
+      for (let j = 0; j < n; j++) {
+        if (statements[i][j] === 0 && goodPeople[j]) return false;
+        if (statements[i][j] === 1 && !goodPeople[j]) return false;
+      }
+    }
+    return true;
+  }
+
+  function backtrack(index, goodPeople, goodCount) {
+    if (index === n) {
+      if (isValid(goodPeople)) {
+        result = Math.max(result, goodCount);
+      }
+      return;
+    }
+
+    goodPeople[index] = true;
+    backtrack(index + 1, goodPeople, goodCount + 1);
+    goodPeople[index] = false;
+    backtrack(index + 1, goodPeople, goodCount);
+  }
+};
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/2155-all-divisions-with-the-highest-score-of-a-binary-array.js b/solutions/2155-all-divisions-with-the-highest-score-of-a-binary-array.js
new file mode 100644
index 00000000..66db5b2f
--- /dev/null
+++ b/solutions/2155-all-divisions-with-the-highest-score-of-a-binary-array.js
@@ -0,0 +1,45 @@
+/**
+ * 2155. All Divisions With the Highest Score of a Binary Array
+ * https://leetcode.com/problems/all-divisions-with-the-highest-score-of-a-binary-array/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed binary array nums of length n. nums can be divided at index i
+ * (where 0 <= i <= n) into two arrays (possibly empty) numsleft and numsright:
+ * - numsleft has all the elements of nums between index 0 and i - 1 (inclusive), while numsright
+ *   has all the elements of nums between index i and n - 1 (inclusive).
+ * - If i == 0, numsleft is empty, while numsright has all the elements of nums.
+ * - If i == n, numsleft has all the elements of nums, while numsright is empty.
+ *
+ * The division score of an index i is the sum of the number of 0's in numsleft and the number
+ * of 1's in numsright.
+ *
+ * Return all distinct indices that have the highest possible division score. You may return
+ * the answer in any order.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var maxScoreIndices = function(nums) {
+  const result = [0];
+  let leftZeros = 0;
+  let rightOnes = nums.reduce((sum, num) => sum + num, 0);
+  let maxScore = rightOnes;
+
+  for (let i = 0; i < nums.length; i++) {
+    leftZeros += nums[i] === 0 ? 1 : 0;
+    rightOnes -= nums[i];
+    const score = leftZeros + rightOnes;
+
+    if (score > maxScore) {
+      maxScore = score;
+      result.length = 0;
+      result.push(i + 1);
+    } else if (score === maxScore) {
+      result.push(i + 1);
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2156-find-substring-with-given-hash-value.js b/solutions/2156-find-substring-with-given-hash-value.js
new file mode 100644
index 00000000..a43f4a10
--- /dev/null
+++ b/solutions/2156-find-substring-with-given-hash-value.js
@@ -0,0 +1,51 @@
+/**
+ * 2156. Find Substring With Given Hash Value
+ * https://leetcode.com/problems/find-substring-with-given-hash-value/
+ * Difficulty: Hard
+ *
+ * The hash of a 0-indexed string s of length k, given integers p and m, is computed using
+ * the following function:
+ * - hash(s, p, m) = (val(s[0]) * p0 + val(s[1]) * p1 + ... + val(s[k-1]) * pk-1) mod m.
+ *
+ * Where val(s[i]) represents the index of s[i] in the alphabet from val('a') = 1 to val('z') = 26.
+ *
+ * You are given a string s and the integers power, modulo, k, and hashValue. Return sub, the
+ * first substring of s of length k such that hash(sub, power, modulo) == hashValue.
+ *
+ * The test cases will be generated such that an answer always exists.
+ *
+ * A substring is a contiguous non-empty sequence of characters within a string.
+ */
+
+/**
+* @param {string} s
+* @param {number} power
+* @param {number} modulo
+* @param {number} k
+* @param {number} hashValue
+* @return {string}
+*/
+var subStrHash = function(s, power, modulo, k, hashValue) {
+  power = BigInt(power);
+  modulo = BigInt(modulo);
+  hashValue = BigInt(hashValue);
+
+  const powers = new Array(k);
+  powers[0] = 1n;
+  for (let i = 1; i < k; i++) {
+    powers[i] = (powers[i - 1] * power) % modulo;
+  }
+
+  for (let start = 0; start <= s.length - k; start++) {
+    let hash = 0n;
+    for (let i = 0; i < k; i++) {
+      const charVal = BigInt(s.charCodeAt(start + i) - 'a'.charCodeAt(0) + 1);
+      hash = (hash + charVal * powers[i]) % modulo;
+    }
+    if (hash === hashValue) {
+      return s.substring(start, start + k);
+    }
+  }
+
+  return '';
+};
diff --git a/solutions/2157-groups-of-strings.js b/solutions/2157-groups-of-strings.js
new file mode 100644
index 00000000..8af51c12
--- /dev/null
+++ b/solutions/2157-groups-of-strings.js
@@ -0,0 +1,140 @@
+/**
+ * 2157. Groups of Strings
+ * https://leetcode.com/problems/groups-of-strings/
+ * Difficulty: Hard
+ *
+ * You are given a 0-indexed array of strings words. Each string consists of lowercase English
+ * letters only. No letter occurs more than once in any string of words.
+ *
+ * Two strings s1 and s2 are said to be connected if the set of letters of s2 can be obtained
+ * from the set of letters of s1 by any one of the following operations:
+ * - Adding exactly one letter to the set of the letters of s1.
+ * - Deleting exactly one letter from the set of the letters of s1.
+ * - Replacing exactly one letter from the set of the letters of s1 with any letter, including
+ *   itself.
+ *
+ * The array words can be divided into one or more non-intersecting groups. A string belongs
+ * to a group if any one of the following is true:
+ * - It is connected to at least one other string of the group.
+ * - It is the only string present in the group.
+ *
+ * Note that the strings in words should be grouped in such a manner that a string belonging
+ * to a group cannot be connected to a string present in any other group. It can be proved
+ * that such an arrangement is always unique.
+ *
+ * Return an array ans of size 2 where:
+ * - ans[0] is the maximum number of groups words can be divided into, and
+ * - ans[1] is the size of the largest group.
+ */
+
+/**
+ * @param {string[]} words
+ * @return {number[]}
+ */
+var groupStrings = function(words) {
+  const n = words.length;
+  const masks = words.map(word => {
+    let mask = 0;
+    for (let i = 0; i < word.length; i++) {
+      mask |= (1 << (word.charCodeAt(i) - 'a'.charCodeAt(0)));
+    }
+    return mask;
+  });
+  const uf = new UnionFind(n);
+  const maskToIndex = new Map();
+  for (let i = 0; i < n; i++) {
+    if (maskToIndex.has(masks[i])) {
+      uf.union(maskToIndex.get(masks[i]), i);
+    } else {
+      maskToIndex.set(masks[i], i);
+    }
+  }
+  const processed = new Set();
+
+  for (let i = 0; i < n; i++) {
+    const mask = masks[i];
+    if (processed.has(mask)) continue;
+    processed.add(mask);
+
+    for (let bit = 0; bit < 26; bit++) {
+      if ((mask & (1 << bit)) === 0) {
+        const newMask = mask | (1 << bit);
+        if (maskToIndex.has(newMask)) {
+          uf.union(i, maskToIndex.get(newMask));
+        }
+      }
+    }
+
+    for (let bit = 0; bit < 26; bit++) {
+      if ((mask & (1 << bit)) !== 0) {
+        const newMask = mask & ~(1 << bit);
+        if (maskToIndex.has(newMask)) {
+          uf.union(i, maskToIndex.get(newMask));
+        }
+      }
+    }
+
+    for (let remove = 0; remove < 26; remove++) {
+      if ((mask & (1 << remove)) !== 0) {
+        for (let add = 0; add < 26; add++) {
+          if ((mask & (1 << add)) === 0) {
+            const newMask = (mask & ~(1 << remove)) | (1 << add);
+            if (maskToIndex.has(newMask)) {
+              uf.union(i, maskToIndex.get(newMask));
+            }
+          }
+        }
+      }
+    }
+  }
+
+  return [uf.count, uf.getMaxSize()];
+};
+
+class UnionFind {
+  constructor(n) {
+    this.parent = Array(n).fill().map((_, i) => i);
+    this.rank = Array(n).fill(0);
+    this.count = n;
+    this.sizes = Array(n).fill(1);
+  }
+
+  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) return false;
+
+    if (this.rank[rootX] < this.rank[rootY]) {
+      this.parent[rootX] = rootY;
+      this.sizes[rootY] += this.sizes[rootX];
+    } else if (this.rank[rootX] > this.rank[rootY]) {
+      this.parent[rootY] = rootX;
+      this.sizes[rootX] += this.sizes[rootY];
+    } else {
+      this.parent[rootY] = rootX;
+      this.rank[rootX]++;
+      this.sizes[rootX] += this.sizes[rootY];
+    }
+
+    this.count--;
+    return true;
+  }
+
+  getMaxSize() {
+    let maxSize = 0;
+    for (let i = 0; i < this.parent.length; i++) {
+      if (this.parent[i] === i) {
+        maxSize = Math.max(maxSize, this.sizes[i]);
+      }
+    }
+    return maxSize;
+  }
+}
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/2160-minimum-sum-of-four-digit-number-after-splitting-digits.js b/solutions/2160-minimum-sum-of-four-digit-number-after-splitting-digits.js
new file mode 100644
index 00000000..fa3b9b86
--- /dev/null
+++ b/solutions/2160-minimum-sum-of-four-digit-number-after-splitting-digits.js
@@ -0,0 +1,22 @@
+/**
+ * 2160. Minimum Sum of Four Digit Number After Splitting Digits
+ * https://leetcode.com/problems/minimum-sum-of-four-digit-number-after-splitting-digits/
+ * Difficulty: Easy
+ *
+ * You are given a positive integer num consisting of exactly four digits. Split num into two
+ * new integers new1 and new2 by using the digits found in num. Leading zeros are allowed in
+ * new1 and new2, and all the digits found in num must be used.
+ * - For example, given num = 2932, you have the following digits: two 2's, one 9 and one 3.
+ *   Some of the possible pairs [new1, new2] are [22, 93], [23, 92], [223, 9] and [2, 329].
+ *
+ * Return the minimum possible sum of new1 and new2.
+ */
+
+/**
+ * @param {number} num
+ * @return {number}
+ */
+var minimumSum = function(num) {
+  const digits = String(num).split('').map(Number).sort((a, b) => a - b);
+  return (digits[0] * 10 + digits[2]) + (digits[1] * 10 + digits[3]);
+};
diff --git a/solutions/2162-minimum-cost-to-set-cooking-time.js b/solutions/2162-minimum-cost-to-set-cooking-time.js
new file mode 100644
index 00000000..e1c51c1b
--- /dev/null
+++ b/solutions/2162-minimum-cost-to-set-cooking-time.js
@@ -0,0 +1,90 @@
+/**
+ * 2162. Minimum Cost to Set Cooking Time
+ * https://leetcode.com/problems/minimum-cost-to-set-cooking-time/
+ * Difficulty: Medium
+ *
+ * A generic microwave supports cooking times for:
+ * - at least 1 second.
+ * - at most 99 minutes and 99 seconds.
+ *
+ * To set the cooking time, you push at most four digits. The microwave normalizes what you push
+ * as four digits by prepending zeroes. It interprets the first two digits as the minutes and
+ * the last two digits as the seconds. It then adds them up as the cooking time. For example,
+ * - You push 9 5 4 (three digits). It is normalized as 0954 and interpreted as 9 minutes and
+ *   54 seconds.
+ * - You push 0 0 0 8 (four digits). It is interpreted as 0 minutes and 8 seconds.
+ * - You push 8 0 9 0. It is interpreted as 80 minutes and 90 seconds.
+ * - You push 8 1 3 0. It is interpreted as 81 minutes and 30 seconds.
+ *
+ * You are given integers startAt, moveCost, pushCost, and targetSeconds. Initially, your finger
+ * is on the digit startAt. Moving the finger above any specific digit costs moveCost units of
+ * fatigue. Pushing the digit below the finger once costs pushCost units of fatigue.
+ *
+ * There can be multiple ways to set the microwave to cook for targetSeconds seconds but you are
+ * interested in the way with the minimum cost.
+ *
+ * Return the minimum cost to set targetSeconds seconds of cooking time.
+ *
+ * Remember that one minute consists of 60 seconds.
+ */
+
+/**
+ * @param {number} startAt
+ * @param {number} moveCost
+ * @param {number} pushCost
+ * @param {number} targetSeconds
+ * @return {number}
+ */
+var minCostSetTime = function(startAt, moveCost, pushCost, targetSeconds) {
+  const minutes1 = Math.floor(targetSeconds / 60);
+  const seconds1 = targetSeconds % 60;
+  let result = Infinity;
+
+  if (minutes1 <= 99) {
+    const digits1 = getDigits(minutes1, seconds1);
+    result = Math.min(result, calculateCost(digits1));
+  }
+
+  const minutes2 = Math.floor(targetSeconds / 60) - 1;
+  const seconds2 = targetSeconds % 60 + 60;
+  if (minutes2 >= 0 && minutes2 <= 99 && seconds2 <= 99) {
+    const digits2 = getDigits(minutes2, seconds2);
+    result = Math.min(result, calculateCost(digits2));
+  }
+
+  return result;
+
+  function calculateCost(digits) {
+    let totalCost = 0;
+    let currentDigit = startAt;
+
+    for (const digit of digits) {
+      if (digit !== currentDigit) {
+        totalCost += moveCost;
+        currentDigit = digit;
+      }
+      totalCost += pushCost;
+    }
+
+    return totalCost;
+  }
+
+  function getDigits(minutes, seconds) {
+    const result = [];
+
+    if (minutes > 0) {
+      if (minutes >= 10) {
+        result.push(Math.floor(minutes / 10));
+      }
+      result.push(minutes % 10);
+    }
+
+    if (minutes > 0 || seconds >= 10) {
+      result.push(Math.floor(seconds / 10));
+    }
+
+    result.push(seconds % 10);
+
+    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/2164-sort-even-and-odd-indices-independently.js b/solutions/2164-sort-even-and-odd-indices-independently.js
new file mode 100644
index 00000000..ed9322c6
--- /dev/null
+++ b/solutions/2164-sort-even-and-odd-indices-independently.js
@@ -0,0 +1,50 @@
+/**
+ * 2164. Sort Even and Odd Indices Independently
+ * https://leetcode.com/problems/sort-even-and-odd-indices-independently/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed integer array nums. Rearrange the values of nums according to the
+ * following rules:
+ * 1. Sort the values at odd indices of nums in non-increasing order.
+ *    - For example, if nums = [4,1,2,3] before this step, it becomes [4,3,2,1] after. The values
+ *      at odd indices 1 and 3 are sorted in non-increasing order.
+ * 2. Sort the values at even indices of nums in non-decreasing order.
+ *    - For example, if nums = [4,1,2,3] before this step, it becomes [2,1,4,3] after. The values
+ *      at even indices 0 and 2 are sorted in non-decreasing order.
+ *
+ * Return the array formed after rearranging the values of nums.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var sortEvenOdd = function(nums) {
+  const evens = [];
+  const odds = [];
+
+  for (let i = 0; i < nums.length; i++) {
+    if (i % 2 === 0) {
+      evens.push(nums[i]);
+    } else {
+      odds.push(nums[i]);
+    }
+  }
+
+  evens.sort((a, b) => a - b);
+  odds.sort((a, b) => b - a);
+
+  const result = [];
+  let evenIndex = 0;
+  let oddIndex = 0;
+
+  for (let i = 0; i < nums.length; i++) {
+    if (i % 2 === 0) {
+      result.push(evens[evenIndex++]);
+    } else {
+      result.push(odds[oddIndex++]);
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2165-smallest-value-of-the-rearranged-number.js b/solutions/2165-smallest-value-of-the-rearranged-number.js
new file mode 100644
index 00000000..c3226062
--- /dev/null
+++ b/solutions/2165-smallest-value-of-the-rearranged-number.js
@@ -0,0 +1,34 @@
+/**
+ * 2165. Smallest Value of the Rearranged Number
+ * https://leetcode.com/problems/smallest-value-of-the-rearranged-number/
+ * Difficulty: Medium
+ *
+ * You are given an integer num. Rearrange the digits of num such that its value is minimized
+ * and it does not contain any leading zeros.
+ *
+ * Return the rearranged number with minimal value.
+ *
+ * Note that the sign of the number does not change after rearranging the digits.
+ */
+
+/**
+ * @param {number} num
+ * @return {number}
+ */
+var smallestNumber = function(num) {
+  const isNegative = num < 0;
+  const digits = Math.abs(num).toString().split('').map(Number);
+
+  if (isNegative) {
+    digits.sort((a, b) => b - a);
+    return -parseInt(digits.join(''), 10);
+  }
+
+  digits.sort((a, b) => a - b);
+  const firstNonZero = digits.findIndex(d => d !== 0);
+
+  if (firstNonZero === -1) return 0;
+
+  [digits[0], digits[firstNonZero]] = [digits[firstNonZero], digits[0]];
+  return parseInt(digits.join(''), 10);
+};
diff --git a/solutions/2166-design-bitset.js b/solutions/2166-design-bitset.js
new file mode 100644
index 00000000..155fe39b
--- /dev/null
+++ b/solutions/2166-design-bitset.js
@@ -0,0 +1,109 @@
+/**
+ * 2166. Design Bitset
+ * https://leetcode.com/problems/design-bitset/
+ * Difficulty: Medium
+ *
+ * A Bitset is a data structure that compactly stores bits.
+ *
+ * Implement the Bitset class:
+ * - Bitset(int size) Initializes the Bitset with size bits, all of which are 0.
+ * - void fix(int idx) Updates the value of the bit at the index idx to 1. If the value was
+ *   already 1, no change occurs.
+ * - void unfix(int idx) Updates the value of the bit at the index idx to 0. If the value
+ *   was already 0, no change occurs.
+ * - void flip() Flips the values of each bit in the Bitset. In other words, all bits with
+ *   value 0 will now have value 1 and vice versa.
+ * - boolean all() Checks if the value of each bit in the Bitset is 1. Returns true if it
+ *   satisfies the condition, false otherwise.
+ * - boolean one() Checks if there is at least one bit in the Bitset with value 1. Returns
+ *   true if it satisfies the condition, false otherwise.
+ * - int count() Returns the total number of bits in the Bitset which have value 1.
+ * - String toString() Returns the current composition of the Bitset. Note that in the
+ *   resultant string, the character at the ith index should coincide with the value at
+ *   the ith bit of the Bitset.
+ */
+
+/**
+ * @param {number} size
+ */
+var Bitset = function(size) {
+  this.bits = new Uint8Array(size);
+  this.ones = 0;
+  this.flipped = false;
+};
+
+/**
+ * @param {number} idx
+ * @return {void}
+ */
+Bitset.prototype.fix = function(idx) {
+  if (this.flipped) {
+    if (this.bits[idx] === 1) {
+      this.bits[idx] = 0;
+      this.ones++;
+    }
+  } else {
+    if (this.bits[idx] === 0) {
+      this.bits[idx] = 1;
+      this.ones++;
+    }
+  }
+};
+
+/**
+ * @param {number} idx
+ * @return {void}
+ */
+Bitset.prototype.unfix = function(idx) {
+  if (this.flipped) {
+    if (this.bits[idx] === 0) {
+      this.bits[idx] = 1;
+      this.ones--;
+    }
+  } else {
+    if (this.bits[idx] === 1) {
+      this.bits[idx] = 0;
+      this.ones--;
+    }
+  }
+};
+
+/**
+ * @return {void}
+ */
+Bitset.prototype.flip = function() {
+  this.flipped = !this.flipped;
+  this.ones = this.bits.length - this.ones;
+};
+
+/**
+ * @return {boolean}
+ */
+Bitset.prototype.all = function() {
+  return this.ones === this.bits.length;
+};
+
+/**
+ * @return {boolean}
+ */
+Bitset.prototype.one = function() {
+  return this.ones > 0;
+};
+
+/**
+ * @return {number}
+ */
+Bitset.prototype.count = function() {
+  return this.ones;
+};
+
+/**
+ * @return {string}
+ */
+Bitset.prototype.toString = function() {
+  let result = '';
+  for (let i = 0; i < this.bits.length; i++) {
+    result += this.flipped ? 1 - this.bits[i] : this.bits[i];
+  }
+  return result;
+};
diff --git a/solutions/2167-minimum-time-to-remove-all-cars-containing-illegal-goods.js b/solutions/2167-minimum-time-to-remove-all-cars-containing-illegal-goods.js
new file mode 100644
index 00000000..4877a0de
--- /dev/null
+++ b/solutions/2167-minimum-time-to-remove-all-cars-containing-illegal-goods.js
@@ -0,0 +1,37 @@
+/**
+ * 2167. Minimum Time to Remove All Cars Containing Illegal Goods
+ * https://leetcode.com/problems/minimum-time-to-remove-all-cars-containing-illegal-goods/
+ * Difficulty: Hard
+ *
+ * You are given a 0-indexed binary string s which represents a sequence of train cars. s[i] = '0'
+ * denotes that the ith car does not contain illegal goods and s[i] = '1' denotes that the ith car
+ * does contain illegal goods.
+ *
+ * As the train conductor, you would like to get rid of all the cars containing illegal goods.
+ * You can do any of the following three operations any number of times:
+ * 1. Remove a train car from the left end (i.e., remove s[0]) which takes 1 unit of time.
+ * 2. Remove a train car from the right end (i.e., remove s[s.length - 1]) which takes 1 unit
+ *    of time.
+ * 3. Remove a train car from anywhere in the sequence which takes 2 units of time.
+ *
+ * Return the minimum time to remove all the cars containing illegal goods.
+ *
+ * Note that an empty sequence of cars is considered to have no cars containing illegal goods.
+ */
+
+/**
+ * @param {string} s
+ * @return {number}
+ */
+var minimumTime = function(s) {
+  let leftCost = 0;
+  let result = s.length;
+
+  for (let i = 0; i < s.length; i++) {
+    leftCost = Math.min(leftCost + (s[i] === '1' ? 2 : 0), i + 1);
+    const rightCost = s.length - i - 1;
+    result = Math.min(result, leftCost + rightCost);
+  }
+
+  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/2169-count-operations-to-obtain-zero.js b/solutions/2169-count-operations-to-obtain-zero.js
new file mode 100644
index 00000000..428bd42a
--- /dev/null
+++ b/solutions/2169-count-operations-to-obtain-zero.js
@@ -0,0 +1,34 @@
+/**
+ * 2169. Count Operations to Obtain Zero
+ * https://leetcode.com/problems/count-operations-to-obtain-zero/
+ * Difficulty: Easy
+ *
+ * You are given two non-negative integers num1 and num2.
+ *
+ * In one operation, if num1 >= num2, you must subtract num2 from num1, otherwise subtract num1
+ * from num2.
+ * - For example, if num1 = 5 and num2 = 4, subtract num2 from num1, thus obtaining num1 = 1 and
+ *   num2 = 4. However, if num1 = 4 and num2 = 5, after one operation, num1 = 4 and num2 = 1.
+ *
+ * Return the number of operations required to make either num1 = 0 or num2 = 0.
+ */
+
+/**
+ * @param {number} num1
+ * @param {number} num2
+ * @return {number}
+ */
+var countOperations = function(num1, num2) {
+  let operations = 0;
+
+  while (num1 !== 0 && num2 !== 0) {
+    if (num1 >= num2) {
+      num1 -= num2;
+    } else {
+      num2 -= num1;
+    }
+    operations++;
+  }
+
+  return operations;
+};
diff --git a/solutions/2170-minimum-operations-to-make-the-array-alternating.js b/solutions/2170-minimum-operations-to-make-the-array-alternating.js
new file mode 100644
index 00000000..770b6d62
--- /dev/null
+++ b/solutions/2170-minimum-operations-to-make-the-array-alternating.js
@@ -0,0 +1,49 @@
+/**
+ * 2170. Minimum Operations to Make the Array Alternating
+ * https://leetcode.com/problems/minimum-operations-to-make-the-array-alternating/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed array nums consisting of n positive integers.
+ *
+ * The array nums is called alternating if:
+ * - nums[i - 2] == nums[i], where 2 <= i <= n - 1.
+ * - nums[i - 1] != nums[i], where 1 <= i <= n - 1.
+ *
+ * In one operation, you can choose an index i and change nums[i] into any positive integer.
+ *
+ * Return the minimum number of operations required to make the array alternating.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var minimumOperations = function(nums) {
+  const evenFreq = new Map();
+  const oddFreq = new Map();
+
+  if (nums.length <= 1) return 0;
+  for (let i = 0; i < nums.length; i++) {
+    if (i % 2 === 0) {
+      evenFreq.set(nums[i], (evenFreq.get(nums[i]) || 0) + 1);
+    } else {
+      oddFreq.set(nums[i], (oddFreq.get(nums[i]) || 0) + 1);
+    }
+  }
+
+  const evenTop = [...evenFreq.entries()].sort((a, b) => b[1] - a[1]).slice(0, 2);
+  const oddTop = [...oddFreq.entries()].sort((a, b) => b[1] - a[1]).slice(0, 2);
+  const evenTotal = Math.ceil(nums.length / 2);
+  const oddTotal = Math.floor(nums.length / 2);
+  let minOps = nums.length;
+
+  for (const [evenNum, evenCount] of evenTop.length ? evenTop : [[0, 0]]) {
+    for (const [oddNum, oddCount] of oddTop.length ? oddTop : [[0, 0]]) {
+      if (evenNum !== oddNum || evenNum === 0) {
+        minOps = Math.min(minOps, (evenTotal - evenCount) + (oddTotal - oddCount));
+      }
+    }
+  }
+
+  return minOps === nums.length ? Math.min(evenTotal, oddTotal) : minOps;
+};
diff --git a/solutions/2171-removing-minimum-number-of-magic-beans.js b/solutions/2171-removing-minimum-number-of-magic-beans.js
new file mode 100644
index 00000000..23fd2236
--- /dev/null
+++ b/solutions/2171-removing-minimum-number-of-magic-beans.js
@@ -0,0 +1,33 @@
+/**
+ * 2171. Removing Minimum Number of Magic Beans
+ * https://leetcode.com/problems/removing-minimum-number-of-magic-beans/
+ * Difficulty: Medium
+ *
+ * You are given an array of positive integers beans, where each integer represents the number
+ * of magic beans found in a particular magic bag.
+ *
+ * Remove any number of beans (possibly none) from each bag such that the number of beans in
+ * each remaining non-empty bag (still containing at least one bean) is equal. Once a bean
+ * has been removed from a bag, you are not allowed to return it to any of the bags.
+ *
+ * Return the minimum number of magic beans that you have to remove.
+ */
+
+/**
+ * @param {number[]} beans
+ * @return {number}
+ */
+var minimumRemoval = function(beans) {
+  const sortedBeans = beans.sort((a, b) => a - b);
+  const totalBeans = sortedBeans.reduce((sum, bean) => sum + bean, 0);
+  let result = totalBeans;
+  let remaining = totalBeans;
+
+  for (let i = 0; i < sortedBeans.length; i++) {
+    remaining -= sortedBeans[i];
+    const equalBags = sortedBeans.length - i;
+    result = Math.min(result, totalBeans - sortedBeans[i] * equalBags);
+  }
+
+  return result;
+};
diff --git a/solutions/2172-maximum-and-sum-of-array.js b/solutions/2172-maximum-and-sum-of-array.js
new file mode 100644
index 00000000..6c9020d6
--- /dev/null
+++ b/solutions/2172-maximum-and-sum-of-array.js
@@ -0,0 +1,46 @@
+/**
+ * 2172. Maximum AND Sum of Array
+ * https://leetcode.com/problems/maximum-and-sum-of-array/
+ * Difficulty: Hard
+ *
+ * You are given an integer array nums of length n and an integer numSlots such that
+ * 2 * numSlots >= n. There are numSlots slots numbered from 1 to numSlots.
+ *
+ * You have to place all n integers into the slots such that each slot contains at most
+ * two numbers. The AND sum of a given placement is the sum of the bitwise AND of every
+ * number with its respective slot number.
+ * - For example, the AND sum of placing the numbers [1, 3] into slot 1 and [4, 6] into
+ *   slot 2 is equal to (1 AND 1) + (3 AND 1) + (4 AND 2) + (6 AND 2) = 1 + 1 + 0 + 2 = 4.
+ *
+ * Return the maximum possible AND sum of nums given numSlots slots.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} numSlots
+ * @return {number}
+ */
+var maximumANDSum = function(nums, numSlots) {
+  const map = new Map();
+
+  return dp(0, new Array(numSlots).fill(0));
+
+  function dp(index, slots) {
+    if (index >= nums.length) return 0;
+
+    const key = `${index},${slots.join(',')}`;
+    if (map.has(key)) return map.get(key);
+
+    let result = 0;
+    for (let i = 0; i < numSlots; i++) {
+      if (slots[i] < 2) {
+        slots[i]++;
+        result = Math.max(result, (nums[index] & (i + 1)) + dp(index + 1, slots));
+        slots[i]--;
+      }
+    }
+
+    map.set(key, result);
+    return result;
+  }
+};
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/2176-count-equal-and-divisible-pairs-in-an-array.js b/solutions/2176-count-equal-and-divisible-pairs-in-an-array.js
new file mode 100644
index 00000000..a0adb051
--- /dev/null
+++ b/solutions/2176-count-equal-and-divisible-pairs-in-an-array.js
@@ -0,0 +1,34 @@
+/**
+ * 2176. Count Equal and Divisible Pairs in an Array
+ * https://leetcode.com/problems/count-equal-and-divisible-pairs-in-an-array/
+ * Difficulty: Easy
+ *
+ * Given a 0-indexed integer array nums of length n and an integer k, return the number of
+ * pairs (i, j) where 0 <= i < j < n, such that nums[i] == nums[j] and (i * j) is divisible by k.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var countPairs = function(nums, k) {
+  const frequencyMap = new Map();
+  let result = 0;
+
+  nums.forEach((num, index) => {
+    if (frequencyMap.has(num)) {
+      const values = frequencyMap.get(num);
+      values.forEach(prevIndex => {
+        if ((prevIndex * index) % k === 0) {
+          result++;
+        }
+      });
+      values.push(index);
+    } else {
+      frequencyMap.set(num, [index]);
+    }
+  });
+
+  return result;
+};
diff --git a/solutions/2177-find-three-consecutive-integers-that-sum-to-a-given-number.js b/solutions/2177-find-three-consecutive-integers-that-sum-to-a-given-number.js
new file mode 100644
index 00000000..f77b1221
--- /dev/null
+++ b/solutions/2177-find-three-consecutive-integers-that-sum-to-a-given-number.js
@@ -0,0 +1,19 @@
+/**
+ * 2177. Find Three Consecutive Integers That Sum to a Given Number
+ * https://leetcode.com/problems/find-three-consecutive-integers-that-sum-to-a-given-number/
+ * Difficulty: Medium
+ *
+ * Given an integer num, return three consecutive integers (as a sorted array) that sum to num.
+ * If num cannot be expressed as the sum of three consecutive integers, return an empty array.
+ */
+
+/**
+ * @param {number} num
+ * @return {number[]}
+ */
+var sumOfThree = function(num) {
+  if (num % 3 !== 0) return [];
+
+  const middle = num / 3;
+  return [middle - 1, middle, middle + 1];
+};
diff --git a/solutions/2178-maximum-split-of-positive-even-integers.js b/solutions/2178-maximum-split-of-positive-even-integers.js
new file mode 100644
index 00000000..602b2ab7
--- /dev/null
+++ b/solutions/2178-maximum-split-of-positive-even-integers.js
@@ -0,0 +1,40 @@
+/**
+ * 2178. Maximum Split of Positive Even Integers
+ * https://leetcode.com/problems/maximum-split-of-positive-even-integers/
+ * Difficulty: Medium
+ *
+ * You are given an integer finalSum. Split it into a sum of a maximum number of unique
+ * positive even integers.
+ * - For example, given finalSum = 12, the following splits are valid (unique positive even
+ *   integers summing up to finalSum): (12), (2 + 10), (2 + 4 + 6), and (4 + 8). Among them,
+ *   (2 + 4 + 6) contains the maximum number of integers. Note that finalSum cannot be split
+ *   into (2 + 2 + 4 + 4) as all the numbers should be unique.
+ *
+ * Return a list of integers that represent a valid split containing a maximum number of
+ * integers. If no valid split exists for finalSum, return an empty list. You may return
+ * the integers in any order.
+ */
+
+/**
+ * @param {number} finalSum
+ * @return {number[]}
+ */
+var maximumEvenSplit = function(finalSum) {
+  if (finalSum % 2 !== 0) return [];
+
+  const result = [];
+  let current = 2;
+  let remaining = finalSum;
+
+  while (remaining >= current) {
+    if (remaining - current <= current) {
+      result.push(remaining);
+      return result;
+    }
+    result.push(current);
+    remaining -= current;
+    current += 2;
+  }
+
+  return result;
+};
diff --git a/solutions/2180-count-integers-with-even-digit-sum.js b/solutions/2180-count-integers-with-even-digit-sum.js
new file mode 100644
index 00000000..c1a077e6
--- /dev/null
+++ b/solutions/2180-count-integers-with-even-digit-sum.js
@@ -0,0 +1,32 @@
+/**
+ * 2180. Count Integers With Even Digit Sum
+ * https://leetcode.com/problems/count-integers-with-even-digit-sum/
+ * Difficulty: Easy
+ *
+ * Given a positive integer num, return the number of positive integers less than or equal to num
+ * whose digit sums are even.
+ *
+ * The digit sum of a positive integer is the sum of all its digits.
+ */
+
+/**
+ * @param {number} num
+ * @return {number}
+ */
+var countEven = function(num) {
+  let result = 0;
+
+  for (let i = 1; i <= num; i++) {
+    let sum = 0;
+    let current = i;
+    while (current > 0) {
+      sum += current % 10;
+      current = Math.floor(current / 10);
+    }
+    if (sum % 2 === 0) {
+      result++;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2181-merge-nodes-in-between-zeros.js b/solutions/2181-merge-nodes-in-between-zeros.js
new file mode 100644
index 00000000..f5993c27
--- /dev/null
+++ b/solutions/2181-merge-nodes-in-between-zeros.js
@@ -0,0 +1,46 @@
+/**
+ * 2181. Merge Nodes in Between Zeros
+ * https://leetcode.com/problems/merge-nodes-in-between-zeros/
+ * Difficulty: Medium
+ *
+ * You are given the head of a linked list, which contains a series of integers separated
+ * by 0's. The beginning and end of the linked list will have Node.val == 0.
+ *
+ * For every two consecutive 0's, merge all the nodes lying in between them into a single
+ * node whose value is the sum of all the merged nodes. The modified list should not contain
+ * any 0's.
+ *
+ * Return the head of the modified linked 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 mergeNodes = function(head) {
+  const result = new ListNode(0);
+  let current = result;
+  let sum = 0;
+
+  head = head.next;
+
+  while (head) {
+    if (head.val === 0) {
+      current.next = new ListNode(sum);
+      current = current.next;
+      sum = 0;
+    } else {
+      sum += head.val;
+    }
+    head = head.next;
+  }
+
+  return result.next;
+};
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/2183-count-array-pairs-divisible-by-k.js b/solutions/2183-count-array-pairs-divisible-by-k.js
new file mode 100644
index 00000000..96f923c4
--- /dev/null
+++ b/solutions/2183-count-array-pairs-divisible-by-k.js
@@ -0,0 +1,39 @@
+/**
+ * 2183. Count Array Pairs Divisible by K
+ * https://leetcode.com/problems/count-array-pairs-divisible-by-k/
+ * Difficulty: Hard
+ *
+ * Given a 0-indexed integer array nums of length n and an integer k, return the number
+ * of pairs (i, j) such that:
+ * - 0 <= i < j <= n - 1 and
+ * - nums[i] * nums[j] is divisible by k.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var countPairs = function(nums, k) {
+  const map = new Map();
+  let pairs = 0;
+
+  for (const num of nums) {
+    const gcd1 = gcd(num, k);
+    for (const [gcd2, count] of map) {
+      if ((gcd1 * gcd2) % k === 0) {
+        pairs += count;
+      }
+    }
+    map.set(gcd1, (map.get(gcd1) || 0) + 1);
+  }
+
+  return pairs;
+};
+
+function gcd(a, b) {
+  while (b) {
+    [a, b] = [b, a % b];
+  }
+  return a;
+}
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/2186-minimum-number-of-steps-to-make-two-strings-anagram-ii.js b/solutions/2186-minimum-number-of-steps-to-make-two-strings-anagram-ii.js
new file mode 100644
index 00000000..2501cbd5
--- /dev/null
+++ b/solutions/2186-minimum-number-of-steps-to-make-two-strings-anagram-ii.js
@@ -0,0 +1,36 @@
+/**
+ * 2186. Minimum Number of Steps to Make Two Strings Anagram II
+ * https://leetcode.com/problems/minimum-number-of-steps-to-make-two-strings-anagram-ii/
+ * Difficulty: Medium
+ *
+ * You are given two strings s and t. In one step, you can append any character to either s or t.
+ *
+ * Return the minimum number of steps to make s and t anagrams of each other.
+ *
+ * An anagram of a string is a string that contains the same characters with a different (or the
+ * same) ordering.
+ */
+
+/**
+ * @param {string} s
+ * @param {string} t
+ * @return {number}
+ */
+var minSteps = function(s, t) {
+  const charCount = new Array(26).fill(0);
+
+  for (const char of s) {
+    charCount[char.charCodeAt(0) - 97]++;
+  }
+
+  for (const char of t) {
+    charCount[char.charCodeAt(0) - 97]--;
+  }
+
+  let result = 0;
+  for (const count of charCount) {
+    result += Math.abs(count);
+  }
+
+  return result;
+};
diff --git a/solutions/2187-minimum-time-to-complete-trips.js b/solutions/2187-minimum-time-to-complete-trips.js
new file mode 100644
index 00000000..305712f8
--- /dev/null
+++ b/solutions/2187-minimum-time-to-complete-trips.js
@@ -0,0 +1,39 @@
+/**
+ * 2187. Minimum Time to Complete Trips
+ * https://leetcode.com/problems/minimum-time-to-complete-trips/
+ * Difficulty: Medium
+ *
+ * You are given an array time where time[i] denotes the time taken by the ith bus to complete
+ * one trip.
+ *
+ * Each bus can make multiple trips successively; that is, the next trip can start immediately
+ * after completing the current trip. Also, each bus operates independently; that is, the trips
+ * of one bus do not influence the trips of any other bus.
+ *
+ * You are also given an integer totalTrips, which denotes the number of trips all buses should
+ * make in total. Return the minimum time required for all buses to complete at least totalTrips
+ * trips.
+ */
+
+/**
+ * @param {number[]} time
+ * @param {number} totalTrips
+ * @return {number}
+ */
+var minimumTime = function(time, totalTrips) {
+  let left = 1;
+  let right = Math.min(...time) * totalTrips;
+
+  while (left < right) {
+    const mid = Math.floor((left + right) / 2);
+    const trips = time.reduce((sum, t) => sum + Math.floor(mid / t), 0);
+
+    if (trips >= totalTrips) {
+      right = mid;
+    } else {
+      left = mid + 1;
+    }
+  }
+
+  return left;
+};
diff --git a/solutions/2188-minimum-time-to-finish-the-race.js b/solutions/2188-minimum-time-to-finish-the-race.js
new file mode 100644
index 00000000..fbce3d25
--- /dev/null
+++ b/solutions/2188-minimum-time-to-finish-the-race.js
@@ -0,0 +1,56 @@
+/**
+ * 2188. Minimum Time to Finish the Race
+ * https://leetcode.com/problems/minimum-time-to-finish-the-race/
+ * Difficulty: Hard
+ *
+ * You are given a 0-indexed 2D integer array tires where tires[i] = [fi, ri] indicates that
+ * the ith tire can finish its xth successive lap in fi * ri(x-1) seconds.
+ * - For example, if fi = 3 and ri = 2, then the tire would finish its 1st lap in 3 seconds,
+ *   its 2nd lap in 3 * 2 = 6 seconds, its 3rd lap in 3 * 22 = 12 seconds, etc.
+ *
+ * You are also given an integer changeTime and an integer numLaps.
+ *
+ * The race consists of numLaps laps and you may start the race with any tire. You have an
+ * unlimited supply of each tire and after every lap, you may change to any given tire (including
+ * the current tire type) if you wait changeTime seconds.
+ *
+ * Return the minimum time to finish the race.
+ */
+
+/**
+ * @param {number[][]} tires
+ * @param {number} changeTime
+ * @param {number} numLaps
+ * @return {number}
+ */
+var minimumFinishTime = function(tires, changeTime, numLaps) {
+  const minTimes = new Array(18).fill(Infinity);
+  const bestTime = new Array(numLaps + 1).fill(Infinity);
+
+  for (const [baseTime, multiplier] of tires) {
+    let currentTime = baseTime;
+    let totalTime = baseTime;
+
+    for (let lap = 1; lap <= Math.min(numLaps, 17); lap++) {
+      if (currentTime > changeTime + baseTime) break;
+      minTimes[lap] = Math.min(minTimes[lap], totalTime);
+      currentTime *= multiplier;
+      totalTime += currentTime;
+    }
+  }
+
+  bestTime[0] = 0;
+
+  for (let lap = 1; lap <= numLaps; lap++) {
+    for (let prev = 1; prev <= Math.min(lap, 17); prev++) {
+      if (minTimes[prev] !== Infinity) {
+        bestTime[lap] = Math.min(
+          bestTime[lap],
+          bestTime[lap - prev] + minTimes[prev] + (lap === prev ? 0 : changeTime)
+        );
+      }
+    }
+  }
+
+  return bestTime[numLaps];
+};
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/2190-most-frequent-number-following-key-in-an-array.js b/solutions/2190-most-frequent-number-following-key-in-an-array.js
new file mode 100644
index 00000000..b5485503
--- /dev/null
+++ b/solutions/2190-most-frequent-number-following-key-in-an-array.js
@@ -0,0 +1,43 @@
+/**
+ * 2190. Most Frequent Number Following Key In an Array
+ * https://leetcode.com/problems/most-frequent-number-following-key-in-an-array/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed integer array nums. You are also given an integer key, which is
+ * present in nums.
+ *
+ * For every unique integer target in nums, count the number of times target immediately follows
+ * an occurrence of key in nums. In other words, count the number of indices i such that:
+ * - 0 <= i <= nums.length - 2,
+ * - nums[i] == key and,
+ * - nums[i + 1] == target.
+ *
+ * Return the target with the maximum count. The test cases will be generated such that the target
+ * with maximum count is unique.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} key
+ * @return {number}
+ */
+var mostFrequent = function(nums, key) {
+  const frequency = new Map();
+  let maxCount = 0;
+  let result = 0;
+
+  for (let i = 0; i < nums.length - 1; i++) {
+    if (nums[i] === key) {
+      const target = nums[i + 1];
+      const count = (frequency.get(target) || 0) + 1;
+      frequency.set(target, count);
+
+      if (count > maxCount) {
+        maxCount = count;
+        result = target;
+      }
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2191-sort-the-jumbled-numbers.js b/solutions/2191-sort-the-jumbled-numbers.js
new file mode 100644
index 00000000..490e1d17
--- /dev/null
+++ b/solutions/2191-sort-the-jumbled-numbers.js
@@ -0,0 +1,53 @@
+/**
+ * 2191. Sort the Jumbled Numbers
+ * https://leetcode.com/problems/sort-the-jumbled-numbers/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array mapping which represents the mapping rule of a shuffled
+ * decimal system. mapping[i] = j means digit i should be mapped to digit j in this system.
+ *
+ * The mapped value of an integer is the new integer obtained by replacing each occurrence of digit
+ * i in the integer with mapping[i] for all 0 <= i <= 9.
+ *
+ * You are also given another integer array nums. Return the array nums sorted in non-decreasing
+ * order based on the mapped values of its elements.
+ *
+ * Notes:
+ * - Elements with the same mapped values should appear in the same relative order as in the input.
+ * - The elements of nums should only be sorted based on their mapped values and not be replaced by
+ *   them.
+ */
+
+/**
+ * @param {number[]} mapping
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var sortJumbled = function(mapping, nums) {
+  const mapped = nums.map((num, index) => {
+    let mappedNum = 0;
+    let temp = num;
+
+    if (temp === 0) {
+      mappedNum = mapping[0];
+    } else {
+      const digits = [];
+      while (temp > 0) {
+        digits.push(mapping[temp % 10]);
+        temp = Math.floor(temp / 10);
+      }
+      while (digits.length > 0) {
+        mappedNum = mappedNum * 10 + digits.pop();
+      }
+    }
+
+    return { original: num, mapped: mappedNum, index };
+  });
+
+  mapped.sort((a, b) => {
+    if (a.mapped === b.mapped) return a.index - b.index;
+    return a.mapped - b.mapped;
+  });
+
+  return mapped.map(item => item.original);
+};
diff --git a/solutions/2192-all-ancestors-of-a-node-in-a-directed-acyclic-graph.js b/solutions/2192-all-ancestors-of-a-node-in-a-directed-acyclic-graph.js
new file mode 100644
index 00000000..9eeb8509
--- /dev/null
+++ b/solutions/2192-all-ancestors-of-a-node-in-a-directed-acyclic-graph.js
@@ -0,0 +1,48 @@
+/**
+ * 2192. All Ancestors of a Node in a Directed Acyclic Graph
+ * https://leetcode.com/problems/all-ancestors-of-a-node-in-a-directed-acyclic-graph/
+ * Difficulty: Medium
+ *
+ * You are given a positive integer n representing the number of nodes of a Directed Acyclic
+ * Graph (DAG). The nodes are numbered from 0 to n - 1 (inclusive).
+ *
+ * You are also given a 2D integer array edges, where edges[i] = [fromi, toi] denotes that there
+ * is a unidirectional edge from fromi to toi in the graph.
+ *
+ * Return a list answer, where answer[i] is the list of ancestors of the ith node, sorted in
+ * ascending order.
+ *
+ * A node u is an ancestor of another node v if u can reach v via a set of edges.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[][]} edges
+ * @return {number[][]}
+ */
+var getAncestors = function(n, edges) {
+  const graph = Array.from({ length: n }, () => []);
+  const ancestors = Array.from({ length: n }, () => new Set());
+
+  for (const [from, to] of edges) {
+    graph[to].push(from);
+  }
+
+  for (let i = 0; i < n; i++) {
+    findAncestors(i);
+  }
+
+  return ancestors.map(set => [...set].sort((a, b) => a - b));
+
+  function findAncestors(node) {
+    if (ancestors[node].size > 0) return;
+
+    for (const parent of graph[node]) {
+      ancestors[node].add(parent);
+      findAncestors(parent);
+      for (const ancestor of ancestors[parent]) {
+        ancestors[node].add(ancestor);
+      }
+    }
+  }
+};
diff --git a/solutions/2193-minimum-number-of-moves-to-make-palindrome.js b/solutions/2193-minimum-number-of-moves-to-make-palindrome.js
new file mode 100644
index 00000000..c25800e2
--- /dev/null
+++ b/solutions/2193-minimum-number-of-moves-to-make-palindrome.js
@@ -0,0 +1,42 @@
+/**
+ * 2193. Minimum Number of Moves to Make Palindrome
+ * https://leetcode.com/problems/minimum-number-of-moves-to-make-palindrome/
+ * Difficulty: Hard
+ *
+ * You are given a string s consisting only of lowercase English letters.
+ *
+ * In one move, you can select any two adjacent characters of s and swap them.
+ *
+ * Return the minimum number of moves needed to make s a palindrome.
+ *
+ * Note that the input will be generated such that s can always be converted to a palindrome.
+ */
+
+/**
+* @param {string} s
+* @return {number}
+*/
+var minMovesToMakePalindrome = function(s) {
+  const chars = s.split('');
+  let moves = 0;
+
+  while (chars.length > 1) {
+    const matchIndex = chars.lastIndexOf(chars[0]);
+
+    if (matchIndex === 0) {
+      const middlePos = Math.floor(chars.length / 2);
+      moves += middlePos;
+      chars.splice(0, 1);
+    } else {
+      for (let i = matchIndex; i < chars.length - 1; i++) {
+        [chars[i], chars[i + 1]] = [chars[i + 1], chars[i]];
+        moves++;
+      }
+
+      chars.pop();
+      chars.shift();
+    }
+  }
+
+  return moves;
+};
diff --git a/solutions/2194-cells-in-a-range-on-an-excel-sheet.js b/solutions/2194-cells-in-a-range-on-an-excel-sheet.js
new file mode 100644
index 00000000..194c60cc
--- /dev/null
+++ b/solutions/2194-cells-in-a-range-on-an-excel-sheet.js
@@ -0,0 +1,37 @@
+/**
+ * 2194. Cells in a Range on an Excel Sheet
+ * https://leetcode.com/problems/cells-in-a-range-on-an-excel-sheet/
+ * Difficulty: Easy
+ *
+ * A cell (r, c) of an excel sheet is represented as a string "" where:
+ * -  denotes the column number c of the cell. It is represented by alphabetical letters.
+ *   - For example, the 1st column is denoted by 'A', the 2nd by 'B', the 3rd by 'C', and so on.
+ * -  is the row number r of the cell. The rth row is represented by the integer r.
+ *   - You are given a string s in the format ":", where  represents
+ *     the column c1,  represents the row r1,  represents the column c2, and 
+ *     represents the row r2, such that r1 <= r2 and c1 <= c2.
+ *
+ * Return the list of cells (x, y) such that r1 <= x <= r2 and c1 <= y <= c2. The cells should
+ * be represented as strings in the format mentioned above and be sorted in non-decreasing order
+ * first by columns and then by rows.
+ */
+
+/**
+ * @param {string} s
+ * @return {string[]}
+ */
+var cellsInRange = function(s) {
+  const result = [];
+  const startCol = s.charCodeAt(0);
+  const endCol = s.charCodeAt(3);
+  const startRow = parseInt(s[1], 10);
+  const endRow = parseInt(s[4], 10);
+
+  for (let col = startCol; col <= endCol; col++) {
+    for (let row = startRow; row <= endRow; row++) {
+      result.push(String.fromCharCode(col) + row);
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2195-append-k-integers-with-minimal-sum.js b/solutions/2195-append-k-integers-with-minimal-sum.js
new file mode 100644
index 00000000..bc873455
--- /dev/null
+++ b/solutions/2195-append-k-integers-with-minimal-sum.js
@@ -0,0 +1,40 @@
+/**
+ * 2195. Append K Integers With Minimal Sum
+ * https://leetcode.com/problems/append-k-integers-with-minimal-sum/
+ * Difficulty: Medium
+ *
+ * You are given an integer array nums and an integer k. Append k unique positive integers that do
+ * not appear in nums to nums such that the resulting total sum is minimum.
+ *
+ * Return the sum of the k integers appended to nums.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var minimalKSum = function(nums, k) {
+  const sortedUnique = [...new Set(nums)].sort((a, b) => a - b);
+  let sum = BigInt(0);
+  let current = 1;
+  let i = 0;
+
+  while (k > 0 && i < sortedUnique.length) {
+    if (current < sortedUnique[i]) {
+      const count = Math.min(k, sortedUnique[i] - current);
+      sum += (BigInt(current) + BigInt(current + count - 1)) * BigInt(count) / BigInt(2);
+      k -= count;
+      current += count;
+    } else {
+      current = sortedUnique[i] + 1;
+      i++;
+    }
+  }
+
+  if (k > 0) {
+    sum += (BigInt(current) + BigInt(current + k - 1)) * BigInt(k) / BigInt(2);
+  }
+
+  return Number(sum);
+};
diff --git a/solutions/2196-create-binary-tree-from-descriptions.js b/solutions/2196-create-binary-tree-from-descriptions.js
new file mode 100644
index 00000000..67af6416
--- /dev/null
+++ b/solutions/2196-create-binary-tree-from-descriptions.js
@@ -0,0 +1,54 @@
+/**
+ * 2196. Create Binary Tree From Descriptions
+ * https://leetcode.com/problems/create-binary-tree-from-descriptions/
+ * Difficulty: Medium
+ *
+ * You are given a 2D integer array descriptions where descriptions[i] = [parenti, childi, isLefti]
+ * indicates that parenti is the parent of childi in a binary tree of unique values. Furthermore,
+ * - If isLefti == 1, then childi is the left child of parenti.
+ * - If isLefti == 0, then childi is the right child of parenti.
+ *
+ * Construct the binary tree described by descriptions and return its root.
+ *
+ * The test cases will be generated such that the binary tree is valid.
+ */
+
+/**
+ * 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 {number[][]} descriptions
+ * @return {TreeNode}
+ */
+var createBinaryTree = function(descriptions) {
+  const nodes = new Map();
+  const children = new Set();
+
+  for (const [parent, child, isLeft] of descriptions) {
+    if (!nodes.has(parent)) {
+      nodes.set(parent, new TreeNode(parent));
+    }
+    if (!nodes.has(child)) {
+      nodes.set(child, new TreeNode(child));
+    }
+    children.add(child);
+    if (isLeft) {
+      nodes.get(parent).left = nodes.get(child);
+    } else {
+      nodes.get(parent).right = nodes.get(child);
+    }
+  }
+
+  for (const [val, node] of nodes) {
+    if (!children.has(val)) {
+      return node;
+    }
+  }
+
+  return null;
+};
diff --git a/solutions/2197-replace-non-coprime-numbers-in-array.js b/solutions/2197-replace-non-coprime-numbers-in-array.js
new file mode 100644
index 00000000..2bc8e2d5
--- /dev/null
+++ b/solutions/2197-replace-non-coprime-numbers-in-array.js
@@ -0,0 +1,48 @@
+/**
+ * 2197. Replace Non-Coprime Numbers in Array
+ * https://leetcode.com/problems/replace-non-coprime-numbers-in-array/
+ * Difficulty: Hard
+ *
+ * You are given an array of integers nums. Perform the following steps:
+ * 1. Find any two adjacent numbers in nums that are non-coprime.
+ * 2. If no such numbers are found, stop the process.
+ * 3. Otherwise, delete the two numbers and replace them with their LCM (Least Common Multiple).
+ * 4. Repeat this process as long as you keep finding two adjacent non-coprime numbers.
+ *
+ * Return the final modified array. It can be shown that replacing adjacent non-coprime numbers in
+ * any arbitrary order will lead to the same result.
+ *
+ * The test cases are generated such that the values in the final array are less than or equal to
+ * 108.
+ *
+ * Two values x and y are non-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 replaceNonCoprimes = function(nums) {
+  const result = [];
+
+  for (let num of nums) {
+    while (result.length > 0) {
+      const last = result[result.length - 1];
+      const gcdValue = gcd(last, num);
+      if (gcdValue === 1) break;
+      result.pop();
+      num = (last / gcdValue) * num;
+    }
+    result.push(num);
+  }
+
+  return result;
+};
+
+function gcd(a, b) {
+  while (b) {
+    [a, b] = [b, a % b];
+  }
+  return a;
+}
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/2200-find-all-k-distant-indices-in-an-array.js b/solutions/2200-find-all-k-distant-indices-in-an-array.js
new file mode 100644
index 00000000..5a2cd1bd
--- /dev/null
+++ b/solutions/2200-find-all-k-distant-indices-in-an-array.js
@@ -0,0 +1,31 @@
+/**
+ * 2200. Find All K-Distant Indices in an Array
+ * https://leetcode.com/problems/find-all-k-distant-indices-in-an-array/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed integer array nums and two integers key and k. A k-distant index
+ * is an index i of nums for which there exists at least one index j such that |i - j| <= k
+ * and nums[j] == key.
+ *
+ * Return a list of all k-distant indices sorted in increasing order.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} key
+ * @param {number} k
+ * @return {number[]}
+ */
+var findKDistantIndices = function(nums, key, k) {
+  const result = new Set();
+
+  for (let j = 0; j < nums.length; j++) {
+    if (nums[j] === key) {
+      for (let i = Math.max(0, j - k); i <= Math.min(nums.length - 1, j + k); i++) {
+        result.add(i);
+      }
+    }
+  }
+
+  return [...result].sort((a, b) => a - b);
+};
diff --git a/solutions/2201-count-artifacts-that-can-be-extracted.js b/solutions/2201-count-artifacts-that-can-be-extracted.js
new file mode 100644
index 00000000..cd5f5627
--- /dev/null
+++ b/solutions/2201-count-artifacts-that-can-be-extracted.js
@@ -0,0 +1,57 @@
+/**
+ * 2201. Count Artifacts That Can Be Extracted
+ * https://leetcode.com/problems/count-artifacts-that-can-be-extracted/
+ * Difficulty: Medium
+ *
+ * There is an n x n 0-indexed grid with some artifacts buried in it. You are given the integer
+ * n and a 0-indexed 2D integer array artifacts describing the positions of the rectangular
+ * artifacts where artifacts[i] = [r1i, c1i, r2i, c2i] denotes that the ith artifact is buried
+ * in the subgrid where:
+ * - (r1i, c1i) is the coordinate of the top-left cell of the ith artifact and
+ * - (r2i, c2i) is the coordinate of the bottom-right cell of the ith artifact.
+ *
+ * You will excavate some cells of the grid and remove all the mud from them. If the cell has a
+ * part of an artifact buried underneath, it will be uncovered. If all the parts of an artifact
+ * are uncovered, you can extract it.
+ *
+ * Given a 0-indexed 2D integer array dig where dig[i] = [ri, ci] indicates that you will excavate
+ * the cell (ri, ci), return the number of artifacts that you can extract.
+ *
+ * The test cases are generated such that:
+ * - No two artifacts overlap.
+ * - Each artifact only covers at most 4 cells.
+ * - The entries of dig are unique.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[][]} artifacts
+ * @param {number[][]} dig
+ * @return {number}
+ */
+var digArtifacts = function(n, artifacts, dig) {
+  const excavated = new Set();
+  let result = 0;
+
+  for (const [row, col] of dig) {
+    excavated.add(`${row},${col}`);
+  }
+
+  for (const [r1, c1, r2, c2] of artifacts) {
+    let allUncovered = true;
+
+    for (let r = r1; r <= r2; r++) {
+      for (let c = c1; c <= c2; c++) {
+        if (!excavated.has(`${r},${c}`)) {
+          allUncovered = false;
+          break;
+        }
+      }
+      if (!allUncovered) break;
+    }
+
+    if (allUncovered) result++;
+  }
+
+  return result;
+};
diff --git a/solutions/2202-maximize-the-topmost-element-after-k-moves.js b/solutions/2202-maximize-the-topmost-element-after-k-moves.js
new file mode 100644
index 00000000..8b1554b2
--- /dev/null
+++ b/solutions/2202-maximize-the-topmost-element-after-k-moves.js
@@ -0,0 +1,42 @@
+/**
+ * 2202. Maximize the Topmost Element After K Moves
+ * https://leetcode.com/problems/maximize-the-topmost-element-after-k-moves/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums representing the contents of a pile, where nums[0]
+ * is the topmost element of the pile.
+ *
+ * In one move, you can perform either of the following:
+ * - If the pile is not empty, remove the topmost element of the pile.
+ * - If there are one or more removed elements, add any one of them back onto the pile. This element
+ *   becomes the new topmost element.
+ *
+ * You are also given an integer k, which denotes the total number of moves to be made.
+ *
+ * Return the maximum value of the topmost element of the pile possible after exactly k moves. In
+ * case it is not possible to obtain a non-empty pile after k moves, return -1.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var maximumTop = function(nums, k) {
+  const n = nums.length;
+
+  if (n === 1 && k % 2 === 1) return -1;
+  if (k === 0) return nums[0];
+  if (k === 1) return n > 1 ? nums[1] : -1;
+
+  let result = 0;
+  for (let i = 0; i < Math.min(k - 1, n); i++) {
+    result = Math.max(result, nums[i]);
+  }
+
+  if (k < n) {
+    result = Math.max(result, nums[k]);
+  }
+
+  return result;
+};
diff --git a/solutions/2203-minimum-weighted-subgraph-with-the-required-paths.js b/solutions/2203-minimum-weighted-subgraph-with-the-required-paths.js
new file mode 100644
index 00000000..4ace48ff
--- /dev/null
+++ b/solutions/2203-minimum-weighted-subgraph-with-the-required-paths.js
@@ -0,0 +1,73 @@
+/**
+ * 2203. Minimum Weighted Subgraph With the Required Paths
+ * https://leetcode.com/problems/minimum-weighted-subgraph-with-the-required-paths/
+ * Difficulty: Hard
+ *
+ * You are given an integer n denoting the number of nodes of a weighted directed graph. The nodes
+ * are numbered from 0 to n - 1.
+ *
+ * You are also given a 2D integer array edges where edges[i] = [fromi, toi, weighti] denotes that
+ * there exists a directed edge from fromi to toi with weight weighti.
+ *
+ * Lastly, you are given three distinct integers src1, src2, and dest denoting three distinct nodes
+ * of the graph.
+ *
+ * Return the minimum weight of a subgraph of the graph such that it is possible to reach dest from
+ * both src1 and src2 via a set of edges of this subgraph. In case such a subgraph does not exist,
+ * return -1.
+ *
+ * A subgraph is a graph whose vertices and edges are subsets of the original graph. The weight of
+ * a subgraph is the sum of weights of its constituent edges.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[][]} edges
+ * @param {number} src1
+ * @param {number} src2
+ * @param {number} dest
+ * @return {number}
+ */
+var minimumWeight = function(n, edges, src1, src2, dest) {
+  const forwardGraph = Array.from({ length: n }, () => []);
+  const reverseGraph = Array.from({ length: n }, () => []);
+
+  for (const [from, to, weight] of edges) {
+    forwardGraph[from].push([to, weight]);
+    reverseGraph[to].push([from, weight]);
+  }
+
+  const distFromSrc1 = dijkstra(forwardGraph, src1);
+  const distFromSrc2 = dijkstra(forwardGraph, src2);
+  const distToDest = dijkstra(reverseGraph, dest);
+  let minWeight = Infinity;
+  for (let i = 0; i < n; i++) {
+    if (distFromSrc1[i] !== Infinity && distFromSrc2[i] !== Infinity
+        && distToDest[i] !== Infinity) {
+      minWeight = Math.min(minWeight, distFromSrc1[i] + distFromSrc2[i] + distToDest[i]);
+    }
+  }
+
+  return minWeight === Infinity ? -1 : minWeight;
+
+  function dijkstra(graph, start) {
+    const distances = new Array(n).fill(Infinity);
+    distances[start] = 0;
+    const pq = new PriorityQueue((a, b) => a[0] - b[0]);
+    pq.enqueue([0, start]);
+
+    while (!pq.isEmpty()) {
+      const [dist, node] = pq.dequeue();
+      if (dist > distances[node]) continue;
+
+      for (const [next, weight] of graph[node]) {
+        if (distances[next] > dist + weight) {
+          distances[next] = dist + weight;
+          pq.enqueue([distances[next], next]);
+        }
+      }
+    }
+
+    return distances;
+  }
+};
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/2207-maximize-number-of-subsequences-in-a-string.js b/solutions/2207-maximize-number-of-subsequences-in-a-string.js
new file mode 100644
index 00000000..d7ad35a6
--- /dev/null
+++ b/solutions/2207-maximize-number-of-subsequences-in-a-string.js
@@ -0,0 +1,41 @@
+/**
+ * 2207. Maximize Number of Subsequences in a String
+ * https://leetcode.com/problems/maximize-number-of-subsequences-in-a-string/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed string text and another 0-indexed string pattern of length 2, both
+ * of which consist of only lowercase English letters.
+ *
+ * You can add either pattern[0] or pattern[1] anywhere in text exactly once. Note that the
+ * character can be added even at the beginning or at the end of text.
+ *
+ * Return the maximum number of times pattern can occur as a subsequence of the modified text.
+ *
+ * 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} text
+ * @param {string} pattern
+ * @return {number}
+ */
+var maximumSubsequenceCount = function(text, pattern) {
+  const firstChar = pattern[0];
+  const secondChar = pattern[1];
+  let firstCount = 0;
+  let secondCount = 0;
+  let subsequences = 0;
+
+  for (const char of text) {
+    if (char === secondChar) {
+      subsequences += firstCount;
+      secondCount++;
+    }
+    if (char === firstChar) {
+      firstCount++;
+    }
+  }
+
+  return subsequences + Math.max(firstCount, secondCount);
+};
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/2209-minimum-white-tiles-after-covering-with-carpets.js b/solutions/2209-minimum-white-tiles-after-covering-with-carpets.js
new file mode 100644
index 00000000..08fb5fd3
--- /dev/null
+++ b/solutions/2209-minimum-white-tiles-after-covering-with-carpets.js
@@ -0,0 +1,36 @@
+/**
+ * 2209. Minimum White Tiles After Covering With Carpets
+ * https://leetcode.com/problems/minimum-white-tiles-after-covering-with-carpets/
+ * Difficulty: Hard
+ *
+ * You are given a 0-indexed binary string floor, which represents the colors of tiles on a floor:
+ * - floor[i] = '0' denotes that the ith tile of the floor is colored black.
+ * - On the other hand, floor[i] = '1' denotes that the ith tile of the floor is colored white.
+ *
+ * You are also given numCarpets and carpetLen. You have numCarpets black carpets, each of length
+ * carpetLen tiles. Cover the tiles with the given carpets such that the number of white tiles
+ * still visible is minimum. Carpets may overlap one another.
+ *
+ * Return the minimum number of white tiles still visible.
+ */
+
+/**
+ * @param {string} floor
+ * @param {number} numCarpets
+ * @param {number} carpetLen
+ * @return {number}
+ */
+var minimumWhiteTiles = function(floor, numCarpets, carpetLen) {
+  const n = floor.length;
+  const dp = Array.from({ length: n + 1 }, () => Array(numCarpets + 1).fill(0));
+
+  for (let i = 1; i <= n; i++) {
+    for (let j = 0; j <= numCarpets; j++) {
+      const skip = dp[i - 1][j] + (floor[i - 1] === '1' ? 1 : 0);
+      const cover = j > 0 ? dp[Math.max(0, i - carpetLen)][j - 1] : Infinity;
+      dp[i][j] = Math.min(skip, cover);
+    }
+  }
+
+  return dp[n][numCarpets];
+};
diff --git a/solutions/2210-count-hills-and-valleys-in-an-array.js b/solutions/2210-count-hills-and-valleys-in-an-array.js
new file mode 100644
index 00000000..388d78f5
--- /dev/null
+++ b/solutions/2210-count-hills-and-valleys-in-an-array.js
@@ -0,0 +1,38 @@
+/**
+ * 2210. Count Hills and Valleys in an Array
+ * https://leetcode.com/problems/count-hills-and-valleys-in-an-array/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed integer array nums. An index i is part of a hill in nums if the
+ * closest non-equal neighbors of i are smaller than nums[i]. Similarly, an index i is part
+ * of a valley in nums if the closest non-equal neighbors of i are larger than nums[i].
+ * Adjacent indices i and j are part of the same hill or valley if nums[i] == nums[j].
+ *
+ * Note that for an index to be part of a hill or valley, it must have a non-equal neighbor
+ * on both the left and right of the index.
+ *
+ * Return the number of hills and valleys in nums.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var countHillValley = function(nums) {
+  let count = 0;
+  let prev = nums[0];
+
+  for (let i = 1; i < nums.length - 1; i++) {
+    if (nums[i] === nums[i + 1]) continue;
+    const left = prev;
+    const right = nums[i + 1];
+
+    if ((nums[i] > left && nums[i] > right) || (nums[i] < left && nums[i] < right)) {
+      count++;
+    }
+
+    prev = nums[i];
+  }
+
+  return count;
+};
diff --git a/solutions/2211-count-collisions-on-a-road.js b/solutions/2211-count-collisions-on-a-road.js
new file mode 100644
index 00000000..acbd8920
--- /dev/null
+++ b/solutions/2211-count-collisions-on-a-road.js
@@ -0,0 +1,41 @@
+/**
+ * 2211. Count Collisions on a Road
+ * https://leetcode.com/problems/count-collisions-on-a-road/
+ * Difficulty: Medium
+ *
+ * There are n cars on an infinitely long road. The cars are numbered from 0 to n - 1 from left
+ * to right and each car is present at a unique point.
+ *
+ * You are given a 0-indexed string directions of length n. directions[i] can be either 'L', 'R',
+ * or 'S' denoting whether the ith car is moving towards the left, towards the right, or staying
+ * at its current point respectively. Each moving car has the same speed.
+ *
+ * The number of collisions can be calculated as follows:
+ * - When two cars moving in opposite directions collide with each other, the number of collisions
+ *   increases by 2.
+ * - When a moving car collides with a stationary car, the number of collisions increases by 1.
+ *
+ * After a collision, the cars involved can no longer move and will stay at the point where they
+ * collided. Other than that, cars cannot change their state or direction of motion.
+ *
+ * Return the total number of collisions that will happen on the road.
+ */
+
+/**
+ * @param {string} directions
+ * @return {number}
+ */
+var countCollisions = function(directions) {
+  let result = 0;
+  let left = 0;
+  let right = directions.length - 1;
+
+  while (left < directions.length && directions[left] === 'L') left++;
+  while (right >= 0 && directions[right] === 'R') right--;
+
+  for (let i = left; i <= right; i++) {
+    if (directions[i] !== 'S') result++;
+  }
+
+  return result;
+};
diff --git a/solutions/2212-maximum-points-in-an-archery-competition.js b/solutions/2212-maximum-points-in-an-archery-competition.js
new file mode 100644
index 00000000..2c09fc29
--- /dev/null
+++ b/solutions/2212-maximum-points-in-an-archery-competition.js
@@ -0,0 +1,60 @@
+/**
+ * 2212. Maximum Points in an Archery Competition
+ * https://leetcode.com/problems/maximum-points-in-an-archery-competition/
+ * Difficulty: Medium
+ *
+ * Alice and Bob are opponents in an archery competition. The competition has set the
+ * following rules:
+ * 1. Alice first shoots numArrows arrows and then Bob shoots numArrows arrows.
+ * 2. The points are then calculated as follows:
+ *    1. The target has integer scoring sections ranging from 0 to 11 inclusive.
+ *    2. For each section of the target with score k (in between 0 to 11), say Alice and Bob have
+ *       shot ak and bk arrows on that section respectively. If ak >= bk, then Alice takes k points.
+ *       If ak < bk, then Bob takes k points.
+ *    3. However, if ak == bk == 0, then nobody takes k points.
+ * - For example, if Alice and Bob both shot 2 arrows on the section with score 11, then Alice takes
+ *   11 points. On the other hand, if Alice shot 0 arrows on the section with score 11 and Bob shot
+ *   2 arrows on that same section, then Bob takes 11 points.
+ *
+ * You are given the integer numArrows and an integer array aliceArrows of size 12, which represents
+ * the number of arrows Alice shot on each scoring section from 0 to 11. Now, Bob wants to maximize
+ * the total number of points he can obtain.
+ *
+ * Return the array bobArrows which represents the number of arrows Bob shot on each scoring section
+ * from 0 to 11. The sum of the values in bobArrows should equal numArrows.
+ *
+ * If there are multiple ways for Bob to earn the maximum total points, return any one of them.
+ */
+
+/**
+ * @param {number} numArrows
+ * @param {number[]} aliceArrows
+ * @return {number[]}
+ */
+var maximumBobPoints = function(numArrows, aliceArrows) {
+  let maxScore = 0;
+  let bestConfig = new Array(12).fill(0);
+
+  backtrack(1, numArrows, 0, new Array(12).fill(0));
+  return bestConfig;
+
+  function backtrack(index, arrowsLeft, score, config) {
+    if (index === 12 || arrowsLeft === 0) {
+      if (score > maxScore) {
+        maxScore = score;
+        bestConfig = [...config];
+        bestConfig[0] += arrowsLeft;
+      }
+      return;
+    }
+
+    const needed = aliceArrows[index] + 1;
+    if (arrowsLeft >= needed) {
+      config[index] = needed;
+      backtrack(index + 1, arrowsLeft - needed, score + index, config);
+      config[index] = 0;
+    }
+
+    backtrack(index + 1, arrowsLeft, score, config);
+  }
+};
diff --git a/solutions/2213-longest-substring-of-one-repeating-character.js b/solutions/2213-longest-substring-of-one-repeating-character.js
new file mode 100644
index 00000000..ca5e006d
--- /dev/null
+++ b/solutions/2213-longest-substring-of-one-repeating-character.js
@@ -0,0 +1,117 @@
+/**
+ * 2213. Longest Substring of One Repeating Character
+ * https://leetcode.com/problems/longest-substring-of-one-repeating-character/
+ * Difficulty: Hard
+ *
+ * You are given a 0-indexed string s. You are also given a 0-indexed string queryCharacters of
+ * length k and a 0-indexed array of integer indices queryIndices of length k, both of which are
+ * used to describe k queries.
+ *
+ * The ith query updates the character in s at index queryIndices[i] to the character
+ * queryCharacters[i].
+ *
+ * Return an array lengths of length k where lengths[i] is the length of the longest substring of
+ * s consisting of only one repeating character after the ith query is performed.
+ */
+
+/**
+* @param {string} s
+* @param {string} queryCharacters
+* @param {number[]} queryIndices
+* @return {number[]}
+*/
+var longestRepeating = function(s, queryCharacters, queryIndices) {
+  const chars = s.split('');
+  const n = chars.length;
+  const k = queryIndices.length;
+  const result = [];
+
+  class Node {
+    constructor() {
+      this.left = 0;
+      this.right = 0;
+      this.max = 0;
+      this.total = 0;
+    }
+  }
+
+  const tree = new Array(4 * n);
+  for (let i = 0; i < 4 * n; i++) {
+    tree[i] = new Node();
+  }
+
+  function buildTree(node, start, end) {
+    if (start === end) {
+      tree[node].left = 1;
+      tree[node].right = 1;
+      tree[node].max = 1;
+      tree[node].total = 1;
+      return;
+    }
+
+    const mid = Math.floor((start + end) / 2);
+    buildTree(2 * node, start, mid);
+    buildTree(2 * node + 1, mid + 1, end);
+
+    updateNode(node, start, end);
+  }
+
+  function updateNode(node, start, end) {
+    const leftChild = 2 * node;
+    const rightChild = 2 * node + 1;
+    const mid = Math.floor((start + end) / 2);
+
+    tree[node].total = tree[leftChild].total + tree[rightChild].total;
+
+    if (tree[leftChild].total === tree[leftChild].left
+        && mid + 1 <= end && chars[mid] === chars[mid + 1]) {
+      tree[node].left = tree[leftChild].total + tree[rightChild].left;
+    } else {
+      tree[node].left = tree[leftChild].left;
+    }
+
+    if (tree[rightChild].total === tree[rightChild].right
+        && mid >= start && chars[mid] === chars[mid + 1]) {
+      tree[node].right = tree[rightChild].total + tree[leftChild].right;
+    } else {
+      tree[node].right = tree[rightChild].right;
+    }
+
+    tree[node].max = Math.max(tree[leftChild].max, tree[rightChild].max);
+
+    if (mid >= start && mid + 1 <= end && chars[mid] === chars[mid + 1]) {
+      tree[node].max = Math.max(tree[node].max,
+        tree[leftChild].right + tree[rightChild].left);
+    }
+  }
+
+  function update(node, start, end, index) {
+    if (index < start || index > end) {
+      return;
+    }
+
+    if (start === end) {
+      return;
+    }
+
+    const mid = Math.floor((start + end) / 2);
+    update(2 * node, start, mid, index);
+    update(2 * node + 1, mid + 1, end, index);
+
+    updateNode(node, start, end);
+  }
+
+  buildTree(1, 0, n - 1);
+
+  for (let q = 0; q < k; q++) {
+    const index = queryIndices[q];
+    const newChar = queryCharacters[q];
+
+    chars[index] = newChar;
+    update(1, 0, n - 1, index);
+
+    result.push(tree[1].max);
+  }
+
+  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/2216-minimum-deletions-to-make-array-beautiful.js b/solutions/2216-minimum-deletions-to-make-array-beautiful.js
new file mode 100644
index 00000000..7cb1012e
--- /dev/null
+++ b/solutions/2216-minimum-deletions-to-make-array-beautiful.js
@@ -0,0 +1,41 @@
+/**
+ * 2216. Minimum Deletions to Make Array Beautiful
+ * https://leetcode.com/problems/minimum-deletions-to-make-array-beautiful/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums. The array nums is beautiful if:
+ * - nums.length is even.
+ * - nums[i] != nums[i + 1] for all i % 2 == 0.
+ *
+ * Note that an empty array is considered beautiful.
+ *
+ * You can delete any number of elements from nums. When you delete an element, all the elements
+ * to the right of the deleted element will be shifted one unit to the left to fill the gap
+ * created and all the elements to the left of the deleted element will remain unchanged.
+ *
+ * Return the minimum number of elements to delete from nums to make it beautiful.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var minDeletion = function(nums) {
+  let result = 0;
+  let i = 0;
+
+  while (i < nums.length - 1) {
+    if (nums[i] === nums[i + 1]) {
+      result++;
+      i++;
+    } else {
+      i += 2;
+    }
+  }
+
+  if ((nums.length - result) % 2 !== 0) {
+    result++;
+  }
+
+  return result;
+};
diff --git a/solutions/2217-find-palindrome-with-fixed-length.js b/solutions/2217-find-palindrome-with-fixed-length.js
new file mode 100644
index 00000000..4e6a83aa
--- /dev/null
+++ b/solutions/2217-find-palindrome-with-fixed-length.js
@@ -0,0 +1,40 @@
+/**
+ * 2217. Find Palindrome With Fixed Length
+ * https://leetcode.com/problems/find-palindrome-with-fixed-length/
+ * Difficulty: Medium
+ *
+ * Given an integer array queries and a positive integer intLength, return an array answer where
+ * answer[i] is either the queries[i]th smallest positive palindrome of length intLength or -1
+ * if no such palindrome exists.
+ *
+ * A palindrome is a number that reads the same backwards and forwards. Palindromes cannot have
+ * leading zeros.
+ */
+
+/**
+ * @param {number[]} queries
+ * @param {number} intLength
+ * @return {number[]}
+ */
+var kthPalindrome = function(queries, intLength) {
+  const halfLength = Math.ceil(intLength / 2);
+  const maxPalindromes = Math.pow(10, halfLength - 1) * 9;
+
+  return queries.map(generatePalindrome);
+
+  function generatePalindrome(query) {
+    if (query > maxPalindromes) return -1;
+
+    let firstHalf = Math.pow(10, halfLength - 1) + query - 1;
+    let result = firstHalf;
+
+    if (intLength % 2 === 1) firstHalf = Math.floor(firstHalf / 10);
+
+    while (firstHalf > 0) {
+      result = result * 10 + (firstHalf % 10);
+      firstHalf = Math.floor(firstHalf / 10);
+    }
+
+    return result;
+  }
+};
diff --git a/solutions/2218-maximum-value-of-k-coins-from-piles.js b/solutions/2218-maximum-value-of-k-coins-from-piles.js
new file mode 100644
index 00000000..743b4b17
--- /dev/null
+++ b/solutions/2218-maximum-value-of-k-coins-from-piles.js
@@ -0,0 +1,44 @@
+/**
+ * 2218. Maximum Value of K Coins From Piles
+ * https://leetcode.com/problems/maximum-value-of-k-coins-from-piles/
+ * Difficulty: Hard
+ *
+ * There are n piles of coins on a table. Each pile consists of a positive number of coins of
+ * assorted denominations.
+ *
+ * In one move, you can choose any coin on top of any pile, remove it, and add it to your wallet.
+ *
+ * Given a list piles, where piles[i] is a list of integers denoting the composition of the ith
+ * pile from top to bottom, and a positive integer k, return the maximum total value of coins
+ * you can have in your wallet if you choose exactly k coins optimally.
+ */
+
+/**
+ * @param {number[][]} piles
+ * @param {number} k
+ * @return {number}
+ */
+var maxValueOfCoins = function(piles, k) {
+  const n = piles.length;
+  const dp = Array.from({ length: n + 1 }, () => new Array(k + 1).fill(-1));
+
+  return maximize(0, k);
+
+  function maximize(pileIndex, remainingCoins) {
+    if (pileIndex === n || remainingCoins === 0) return 0;
+    if (dp[pileIndex][remainingCoins] !== -1) return dp[pileIndex][remainingCoins];
+
+    let maxValue = maximize(pileIndex + 1, remainingCoins);
+    let currentSum = 0;
+
+    for (let i = 0; i < Math.min(piles[pileIndex].length, remainingCoins); i++) {
+      currentSum += piles[pileIndex][i];
+      maxValue = Math.max(
+        maxValue,
+        currentSum + maximize(pileIndex + 1, remainingCoins - (i + 1))
+      );
+    }
+
+    return dp[pileIndex][remainingCoins] = maxValue;
+  }
+};
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/2220-minimum-bit-flips-to-convert-number.js b/solutions/2220-minimum-bit-flips-to-convert-number.js
new file mode 100644
index 00000000..28e0a9da
--- /dev/null
+++ b/solutions/2220-minimum-bit-flips-to-convert-number.js
@@ -0,0 +1,24 @@
+/**
+ * 2220. Minimum Bit Flips to Convert Number
+ * https://leetcode.com/problems/minimum-bit-flips-to-convert-number/
+ * Difficulty: Easy
+ *
+ * A bit flip of a number x is choosing a bit in the binary representation of x and flipping it
+ * from either 0 to 1 or 1 to 0.
+ * - For example, for x = 7, the binary representation is 111 and we may choose any bit (including
+ *   any leading zeros not shown) and flip it. We can flip the first bit from the right to get 110,
+ *   flip the second bit from the right to get 101, flip the fifth bit from the right (a leading
+ *   zero) to get 10111, etc.
+ *
+ * Given two integers start and goal, return the minimum number of bit flips to convert start to
+ * goal.
+ */
+
+/**
+ * @param {number} start
+ * @param {number} goal
+ * @return {number}
+ */
+var minBitFlips = function(start, goal) {
+  return (start ^ goal).toString(2).replace(/0+/g, '').length;
+};
diff --git a/solutions/2221-find-triangular-sum-of-an-array.js b/solutions/2221-find-triangular-sum-of-an-array.js
new file mode 100644
index 00000000..3ef02fcd
--- /dev/null
+++ b/solutions/2221-find-triangular-sum-of-an-array.js
@@ -0,0 +1,34 @@
+/**
+ * 2221. Find Triangular Sum of an Array
+ * https://leetcode.com/problems/find-triangular-sum-of-an-array/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums, where nums[i] is a digit between 0 and
+ * 9 (inclusive).
+ *
+ * The triangular sum of nums is the value of the only element present in nums after the
+ * following process terminates:
+ * 1. Let nums comprise of n elements. If n == 1, end the process. Otherwise, create a new
+ *    0-indexed integer array newNums of length n - 1.
+ * 2. For each index i, where 0 <= i < n - 1, assign the value of newNums[i] as
+ *    (nums[i] + nums[i+1]) % 10, where % denotes modulo operator.
+ * 3. Replace the array nums with newNums.
+ * 4. Repeat the entire process starting from step 1.
+ *
+ * Return the triangular sum of nums.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var triangularSum = function(nums) {
+  while (nums.length > 1) {
+    const updated = [];
+    for (let i = 0; i < nums.length - 1; i++) {
+      updated.push((nums[i] + nums[i + 1]) % 10);
+    }
+    nums = updated;
+  }
+  return nums[0];
+};
diff --git a/solutions/2222-number-of-ways-to-select-buildings.js b/solutions/2222-number-of-ways-to-select-buildings.js
new file mode 100644
index 00000000..012573fc
--- /dev/null
+++ b/solutions/2222-number-of-ways-to-select-buildings.js
@@ -0,0 +1,49 @@
+/**
+ * 2222. Number of Ways to Select Buildings
+ * https://leetcode.com/problems/number-of-ways-to-select-buildings/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed binary string s which represents the types of buildings along
+ * a street where:
+ * - s[i] = '0' denotes that the ith building is an office and
+ * - s[i] = '1' denotes that the ith building is a restaurant.
+ *
+ * As a city official, you would like to select 3 buildings for random inspection. However, to
+ * ensure variety, no two consecutive buildings out of the selected buildings can be of the same
+ * type.
+ * - For example, given s = "001101", we cannot select the 1st, 3rd, and 5th buildings as that
+ *   would form "011" which is not allowed due to having two consecutive buildings of the same type.
+ *
+ * Return the number of valid ways to select 3 buildings.
+ */
+
+/**
+ * @param {string} s
+ * @return {number}
+ */
+var numberOfWays = function(s) {
+  const prefixCounts = [[0, 0]];
+  let zeros = 0;
+  let ones = 0;
+
+  for (const char of s) {
+    if (char === '0') zeros++;
+    else ones++;
+    prefixCounts.push([zeros, ones]);
+  }
+
+  let result = 0;
+  for (let i = 1; i < s.length - 1; i++) {
+    if (s[i] === '0') {
+      const leftOnes = prefixCounts[i][1];
+      const rightOnes = prefixCounts[s.length][1] - prefixCounts[i + 1][1];
+      result += leftOnes * rightOnes;
+    } else {
+      const leftZeros = prefixCounts[i][0];
+      const rightZeros = prefixCounts[s.length][0] - prefixCounts[i + 1][0];
+      result += leftZeros * rightZeros;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2223-sum-of-scores-of-built-strings.js b/solutions/2223-sum-of-scores-of-built-strings.js
new file mode 100644
index 00000000..4b5110cc
--- /dev/null
+++ b/solutions/2223-sum-of-scores-of-built-strings.js
@@ -0,0 +1,40 @@
+/**
+ * 2223. Sum of Scores of Built Strings
+ * https://leetcode.com/problems/sum-of-scores-of-built-strings/
+ * Difficulty: Hard
+ *
+ * You are building a string s of length n one character at a time, prepending each new character
+ * to the front of the string. The strings are labeled from 1 to n, where the string with length
+ * i is labeled si.
+ * - For example, for s = "abaca", s1 == "a", s2 == "ca", s3 == "aca", etc.
+ *
+ * The score of si is the length of the longest common prefix between si and sn (Note that s == sn).
+ *
+ * Given the final string s, return the sum of the score of every si.
+ */
+
+/**
+ * @param {string} s
+ * @return {number}
+ */
+var sumScores = function(s) {
+  const n = s.length;
+  const z = new Array(n).fill(0);
+  let left = 0;
+  let right = 0;
+
+  for (let i = 1; i < n; i++) {
+    if (i <= right) {
+      z[i] = Math.min(right - i + 1, z[i - left]);
+    }
+    while (i + z[i] < n && s[z[i]] === s[i + z[i]]) {
+      z[i]++;
+    }
+    if (i + z[i] - 1 > right) {
+      left = i;
+      right = i + z[i] - 1;
+    }
+  }
+
+  return z.reduce((sum, val) => sum + val, n);
+};
diff --git a/solutions/2224-minimum-number-of-operations-to-convert-time.js b/solutions/2224-minimum-number-of-operations-to-convert-time.js
new file mode 100644
index 00000000..95b7a154
--- /dev/null
+++ b/solutions/2224-minimum-number-of-operations-to-convert-time.js
@@ -0,0 +1,38 @@
+/**
+ * 2224. Minimum Number of Operations to Convert Time
+ * https://leetcode.com/problems/minimum-number-of-operations-to-convert-time/
+ * Difficulty: Easy
+ *
+ * You are given two strings current and correct representing two 24-hour times.
+ *
+ * 24-hour times are formatted as "HH:MM", where HH is between 00 and 23, and MM is between 00
+ * and 59. The earliest 24-hour time is 00:00, and the latest is 23:59.
+ *
+ * In one operation you can increase the time current by 1, 5, 15, or 60 minutes. You can perform
+ * this operation any number of times.
+ *
+ * Return the minimum number of operations needed to convert current to correct.
+ */
+
+/**
+ * @param {string} current
+ * @param {string} correct
+ * @return {number}
+ */
+var convertTime = function(current, correct) {
+  const toMinutes = time => {
+    const [hours, minutes] = time.split(':').map(Number);
+    return hours * 60 + minutes;
+  };
+
+  let diff = toMinutes(correct) - toMinutes(current);
+  const increments = [60, 15, 5, 1];
+  let result = 0;
+
+  for (const increment of increments) {
+    result += Math.floor(diff / increment);
+    diff %= increment;
+  }
+
+  return result;
+};
diff --git a/solutions/2225-find-players-with-zero-or-one-losses.js b/solutions/2225-find-players-with-zero-or-one-losses.js
new file mode 100644
index 00000000..3182523e
--- /dev/null
+++ b/solutions/2225-find-players-with-zero-or-one-losses.js
@@ -0,0 +1,44 @@
+/**
+ * 2225. Find Players With Zero or One Losses
+ * https://leetcode.com/problems/find-players-with-zero-or-one-losses/
+ * Difficulty: Medium
+ *
+ * You are given an integer array matches where matches[i] = [winneri, loseri] indicates that
+ * the player winneri defeated player loseri in a match.
+ *
+ * Return a list answer of size 2 where:
+ * - answer[0] is a list of all players that have not lost any matches.
+ * - answer[1] is a list of all players that have lost exactly one match.
+ *
+ * The values in the two lists should be returned in increasing order.
+ *
+ * Note:
+ * - You should only consider the players that have played at least one match.
+ * - The testcases will be generated such that no two matches will have the same outcome.
+ */
+
+/**
+ * @param {number[][]} matches
+ * @return {number[][]}
+ */
+var findWinners = function(matches) {
+  const lossCount = new Map();
+
+  for (const [winner, loser] of matches) {
+    lossCount.set(winner, lossCount.get(winner) || 0);
+    lossCount.set(loser, (lossCount.get(loser) || 0) + 1);
+  }
+
+  const noLosses = [];
+  const oneLoss = [];
+
+  for (const [player, losses] of lossCount) {
+    if (losses === 0) noLosses.push(player);
+    else if (losses === 1) oneLoss.push(player);
+  }
+
+  return [
+    noLosses.sort((a, b) => a - b),
+    oneLoss.sort((a, b) => a - b)
+  ];
+};
diff --git a/solutions/2227-encrypt-and-decrypt-strings.js b/solutions/2227-encrypt-and-decrypt-strings.js
new file mode 100644
index 00000000..fd773ffb
--- /dev/null
+++ b/solutions/2227-encrypt-and-decrypt-strings.js
@@ -0,0 +1,77 @@
+/**
+ * 2227. Encrypt and Decrypt Strings
+ * https://leetcode.com/problems/encrypt-and-decrypt-strings/
+ * Difficulty: Hard
+ *
+ * You are given a character array keys containing unique characters and a string array values
+ * containing strings of length 2. You are also given another string array dictionary that
+ * contains all permitted original strings after decryption. You should implement a data structure
+ * that can encrypt or decrypt a 0-indexed string.
+ *
+ * A string is encrypted with the following process:
+ * 1. For each character c in the string, we find the index i satisfying keys[i] == c in keys.
+ * 2. Replace c with values[i] in the string.
+ *
+ * Note that in case a character of the string is not present in keys, the encryption process cannot
+ * be carried out, and an empty string "" is returned.
+ *
+ * A string is decrypted with the following process:
+ * 1. For each substring s of length 2 occurring at an even index in the string, we find an i such
+ *    that values[i] == s. If there are multiple valid i, we choose any one of them. This means a
+ *    string could have multiple possible strings it can decrypt to.
+ * 2. Replace s with keys[i] in the string.
+ *
+ * Implement the Encrypter class:
+ * - Encrypter(char[] keys, String[] values, String[] dictionary) Initializes the Encrypter class
+ *   with keys, values, and dictionary.
+ * - String encrypt(String word1) Encrypts word1 with the encryption process described above and
+ *   returns the encrypted string.
+ * - int decrypt(String word2) Returns the number of possible strings word2 could decrypt to that
+ *   also appear in dictionary.
+ */
+
+/**
+ * @param {character[]} keys
+ * @param {string[]} values
+ * @param {string[]} dictionary
+ */
+var Encrypter = function(keys, values, dictionary) {
+  this.encryptMap = new Map();
+  this.validEncryptions = new Map();
+
+  for (let i = 0; i < keys.length; i++) {
+    this.encryptMap.set(keys[i], values[i]);
+  }
+
+  for (const word of dictionary) {
+    const encrypted = this.encrypt(word);
+    if (encrypted !== '') {
+      this.validEncryptions.set(encrypted, (this.validEncryptions.get(encrypted) || 0) + 1);
+    }
+  }
+};
+
+/**
+ * @param {string} word1
+ * @return {string}
+ */
+Encrypter.prototype.encrypt = function(word1) {
+  let result = '';
+
+  for (const char of word1) {
+    if (!this.encryptMap.has(char)) {
+      return '';
+    }
+    result += this.encryptMap.get(char);
+  }
+
+  return result;
+};
+
+/**
+ * @param {string} word2
+ * @return {number}
+ */
+Encrypter.prototype.decrypt = function(word2) {
+  return this.validEncryptions.get(word2) || 0;
+};
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/2232-minimize-result-by-adding-parentheses-to-expression.js b/solutions/2232-minimize-result-by-adding-parentheses-to-expression.js
new file mode 100644
index 00000000..f32f3fd9
--- /dev/null
+++ b/solutions/2232-minimize-result-by-adding-parentheses-to-expression.js
@@ -0,0 +1,50 @@
+/**
+ * 2232. Minimize Result by Adding Parentheses to Expression
+ * https://leetcode.com/problems/minimize-result-by-adding-parentheses-to-expression/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed string expression of the form "+" where 
+ * and  represent positive integers.
+ *
+ * Add a pair of parentheses to expression such that after the addition of parentheses,
+ * expression is a valid mathematical expression and evaluates to the smallest possible
+ * value. The left parenthesis must be added to the left of '+' and the right parenthesis
+ * must be added to the right of '+'.
+ *
+ * Return expression after adding a pair of parentheses such that expression evaluates to the
+ * smallest possible value. If there are multiple answers that yield the same result, return
+ * any of them.
+ *
+ * The input has been generated such that the original value of expression, and the value of
+ * expression after adding any pair of parentheses that meets the requirements fits within
+ * a signed 32-bit integer.
+ */
+
+/**
+ * @param {string} expression
+ * @return {string}
+ */
+var minimizeResult = function(expression) {
+  const plusIndex = expression.indexOf('+');
+  const left = expression.slice(0, plusIndex);
+  const right = expression.slice(plusIndex + 1);
+  let minValue = Infinity;
+  let result = '';
+
+  for (let i = 0; i < left.length; i++) {
+    for (let j = 1; j <= right.length; j++) {
+      const leftPrefix = i === 0 ? 1 : parseInt(left.slice(0, i));
+      const leftNum = parseInt(left.slice(i), 10);
+      const rightNum = parseInt(right.slice(0, j), 10);
+      const rightSuffix = j === right.length ? 1 : parseInt(right.slice(j), 10);
+      const value = leftPrefix * (leftNum + rightNum) * rightSuffix;
+
+      if (value < minValue) {
+        minValue = value;
+        result = `${left.slice(0, i)}(${left.slice(i)}+${right.slice(0, j)})${right.slice(j)}`;
+      }
+    }
+  }
+
+  return result;
+};
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/2234-maximum-total-beauty-of-the-gardens.js b/solutions/2234-maximum-total-beauty-of-the-gardens.js
new file mode 100644
index 00000000..54985527
--- /dev/null
+++ b/solutions/2234-maximum-total-beauty-of-the-gardens.js
@@ -0,0 +1,99 @@
+/**
+ * 2234. Maximum Total Beauty of the Gardens
+ * https://leetcode.com/problems/maximum-total-beauty-of-the-gardens/
+ * Difficulty: Hard
+ *
+ * Alice is a caretaker of n gardens and she wants to plant flowers to maximize the total
+ * beauty of all her gardens.
+ *
+ * You are given a 0-indexed integer array flowers of size n, where flowers[i] is the number
+ * of flowers already planted in the ith garden. Flowers that are already planted cannot be
+ * removed. You are then given another integer newFlowers, which is the maximum number of
+ * flowers that Alice can additionally plant. You are also given the integers target, full,
+ * and partial.
+ *
+ * A garden is considered complete if it has at least target flowers. The total beauty of the
+ * gardens is then determined as the sum of the following:
+ * - The number of complete gardens multiplied by full.
+ * - The minimum number of flowers in any of the incomplete gardens multiplied by partial.
+ *   If there are no incomplete gardens, then this value will be 0.
+ *
+ * Return the maximum total beauty that Alice can obtain after planting at most newFlowers flowers.
+ */
+
+/**
+ * @param {number[]} flowers
+ * @param {number} newFlowers
+ * @param {number} target
+ * @param {number} full
+ * @param {number} partial
+ * @return {number}
+ */
+var maximumBeauty = function(flowers, newFlowers, target, full, partial) {
+  const n = flowers.length;
+  flowers.sort((a, b) => b - a);
+
+  const suffixCost = Array(n + 1).fill(0);
+  let lastUniqueIndex = n - 1;
+  let minIndex = n - 2;
+
+  for (; minIndex >= 0; --minIndex) {
+    if (flowers[minIndex] >= target) break;
+
+    const flowerDiff = flowers[minIndex] - flowers[minIndex + 1];
+    const gardenCount = n - lastUniqueIndex;
+    suffixCost[minIndex] = suffixCost[minIndex + 1] + flowerDiff * gardenCount;
+
+    if (suffixCost[minIndex] > newFlowers) break;
+
+    if (flowers[minIndex] !== flowers[minIndex - 1]) {
+      lastUniqueIndex = minIndex;
+    }
+  }
+
+  ++minIndex;
+
+  const remainingFlowersForMin = newFlowers - suffixCost[minIndex];
+  const gardenCountForMin = n - minIndex;
+  let minFlowerValue = Math.min(
+    target - 1,
+    flowers[minIndex] + Math.floor(remainingFlowersForMin / gardenCountForMin)
+  );
+
+  let result = 0;
+
+  for (let i = 0; i < n; ++i) {
+    if (flowers[i] >= target) {
+      continue;
+    }
+
+    const currentBeauty = i * full + minFlowerValue * partial;
+    result = Math.max(result, currentBeauty);
+
+    const flowersNeeded = target - flowers[i];
+    if (flowersNeeded > newFlowers) break;
+
+    newFlowers -= flowersNeeded;
+    flowers[i] = target;
+
+    while (
+      minIndex <= i || newFlowers < suffixCost[minIndex]
+      || (minIndex > 0 && flowers[minIndex] === flowers[minIndex - 1])
+    ) {
+      ++minIndex;
+    }
+
+    const updatedRemaining = newFlowers - suffixCost[minIndex];
+    const updatedGardenCount = n - minIndex;
+    minFlowerValue = Math.min(
+      target - 1,
+      flowers[minIndex] + Math.floor(updatedRemaining / updatedGardenCount)
+    );
+  }
+
+  if (flowers[n - 1] >= target) {
+    result = Math.max(result, n * full);
+  }
+
+  return result;
+};
diff --git a/solutions/2236-root-equals-sum-of-children.js b/solutions/2236-root-equals-sum-of-children.js
new file mode 100644
index 00000000..fa9a3cd9
--- /dev/null
+++ b/solutions/2236-root-equals-sum-of-children.js
@@ -0,0 +1,27 @@
+/**
+ * 2236. Root Equals Sum of Children
+ * https://leetcode.com/problems/root-equals-sum-of-children/
+ * Difficulty: Easy
+ *
+ * You are given the root of a binary tree that consists of exactly 3 nodes: the root, its
+ * left child, and its right child.
+ *
+ * Return true if the value of the root is equal to the sum of the values of its two children,
+ * or false otherwise.
+ */
+
+/**
+ * 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 checkTree = function(root) {
+  return root.val === root.left.val + root.right.val;
+};
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/2239-find-closest-number-to-zero.js b/solutions/2239-find-closest-number-to-zero.js
new file mode 100644
index 00000000..56d07d8e
--- /dev/null
+++ b/solutions/2239-find-closest-number-to-zero.js
@@ -0,0 +1,27 @@
+/**
+ * 2239. Find Closest Number to Zero
+ * https://leetcode.com/problems/find-closest-number-to-zero/
+ * Difficulty: Easy
+ *
+ * Given an integer array nums of size n, return the number with the value closest to 0 in nums.
+ * If there are multiple answers, return the number with the largest value.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var findClosestNumber = function(nums) {
+  let result = nums[0];
+  let minDistance = Math.abs(nums[0]);
+
+  for (const num of nums) {
+    const distance = Math.abs(num);
+    if (distance < minDistance || (distance === minDistance && num > result)) {
+      minDistance = distance;
+      result = num;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2240-number-of-ways-to-buy-pens-and-pencils.js b/solutions/2240-number-of-ways-to-buy-pens-and-pencils.js
new file mode 100644
index 00000000..b55f1cff
--- /dev/null
+++ b/solutions/2240-number-of-ways-to-buy-pens-and-pencils.js
@@ -0,0 +1,31 @@
+/**
+ * 2240. Number of Ways to Buy Pens and Pencils
+ * https://leetcode.com/problems/number-of-ways-to-buy-pens-and-pencils/
+ * Difficulty: Medium
+ *
+ * You are given an integer total indicating the amount of money you have. You are also given
+ * two integers cost1 and cost2 indicating the price of a pen and pencil respectively. You can
+ * spend part or all of your money to buy multiple quantities (or none) of each kind of writing
+ * utensil.
+ *
+ * Return the number of distinct ways you can buy some number of pens and pencils.
+ */
+
+/**
+ * @param {number} total
+ * @param {number} cost1
+ * @param {number} cost2
+ * @return {number}
+ */
+var waysToBuyPensPencils = function(total, cost1, cost2) {
+  let result = 0;
+  const maxPens = Math.floor(total / cost1);
+
+  for (let pens = 0; pens <= maxPens; pens++) {
+    const remaining = total - pens * cost1;
+    const pencils = Math.floor(remaining / cost2);
+    result += pencils + 1;
+  }
+
+  return result;
+};
diff --git a/solutions/2241-design-an-atm-machine.js b/solutions/2241-design-an-atm-machine.js
new file mode 100644
index 00000000..4a5afa87
--- /dev/null
+++ b/solutions/2241-design-an-atm-machine.js
@@ -0,0 +1,64 @@
+/**
+ * 2241. Design an ATM Machine
+ * https://leetcode.com/problems/design-an-atm-machine/
+ * Difficulty: Medium
+ *
+ * There is an ATM machine that stores banknotes of 5 denominations: 20, 50, 100, 200, and
+ * 500 dollars. Initially the ATM is empty. The user can use the machine to deposit or
+ * withdraw any amount of money.
+ *
+ * When withdrawing, the machine prioritizes using banknotes of larger values.
+ * - For example, if you want to withdraw $300 and there are 2 $50 banknotes, 1 $100 banknote,
+ *   and 1 $200 banknote, then the machine will use the $100 and $200 banknotes.
+ * - However, if you try to withdraw $600 and there are 3 $200 banknotes and 1 $500 banknote,
+ *   then the withdraw request will be rejected because the machine will first try to use the
+ *   $500 banknote and then be unable to use banknotes to complete the remaining $100. Note
+ *   that the machine is not allowed to use the $200 banknotes instead of the $500 banknote.
+ *
+ * Implement the ATM class:
+ * - ATM() Initializes the ATM object.
+ * - void deposit(int[] banknotesCount) Deposits new banknotes in the order $20, $50, $100,
+ *   $200, and $500.
+ * - int[] withdraw(int amount) Returns an array of length 5 of the number of banknotes that
+ *   will be handed to the user in the order $20, $50, $100, $200, and $500, and update the
+ *   number of banknotes in the ATM after withdrawing. Returns [-1] if it is not possible (do
+ *   not withdraw any banknotes in this case).
+ */
+
+var ATM = function() {
+  this.denominations = [20, 50, 100, 200, 500];
+  this.notes = [0, 0, 0, 0, 0];
+};
+
+/**
+ * @param {number[]} banknotesCount
+ * @return {void}
+ */
+ATM.prototype.deposit = function(banknotesCount) {
+  for (let i = 0; i < 5; i++) {
+    this.notes[i] += banknotesCount[i];
+  }
+};
+
+/**
+ * @param {number} amount
+ * @return {number[]}
+ */
+ATM.prototype.withdraw = function(amount) {
+  const result = [0, 0, 0, 0, 0];
+  let remaining = amount;
+
+  for (let i = 4; i >= 0; i--) {
+    const count = Math.min(Math.floor(remaining / this.denominations[i]), this.notes[i]);
+    result[i] = count;
+    remaining -= count * this.denominations[i];
+  }
+
+  if (remaining !== 0) return [-1];
+
+  for (let i = 0; i < 5; i++) {
+    this.notes[i] -= result[i];
+  }
+
+  return result;
+};
diff --git a/solutions/2242-maximum-score-of-a-node-sequence.js b/solutions/2242-maximum-score-of-a-node-sequence.js
new file mode 100644
index 00000000..b64c16ce
--- /dev/null
+++ b/solutions/2242-maximum-score-of-a-node-sequence.js
@@ -0,0 +1,55 @@
+/**
+ * 2242. Maximum Score of a Node Sequence
+ * https://leetcode.com/problems/maximum-score-of-a-node-sequence/
+ * Difficulty: Hard
+ *
+ * There is an undirected graph with n nodes, numbered from 0 to n - 1.
+ *
+ * You are given a 0-indexed integer array scores of length n where scores[i] denotes the score
+ * of node i. You are also given a 2D integer array edges where edges[i] = [ai, bi] denotes that
+ * there exists an undirected edge connecting nodes ai and bi.
+ *
+ * A node sequence is valid if it meets the following conditions:
+ * - There is an edge connecting every pair of adjacent nodes in the sequence.
+ * - No node appears more than once in the sequence.
+ *
+ * The score of a node sequence is defined as the sum of the scores of the nodes in the sequence.
+ *
+ * Return the maximum score of a valid node sequence with a length of 4. If no such sequence exists,
+ * return -1.
+ */
+
+/**
+ * @param {number[]} scores
+ * @param {number[][]} edges
+ * @return {number}
+ */
+var maximumScore = function(scores, edges) {
+  const n = scores.length;
+  const graph = new Array(n).fill().map(() => []);
+
+  for (const [a, b] of edges) {
+    graph[a].push(b);
+    graph[b].push(a);
+  }
+
+  for (let i = 0; i < n; i++) {
+    graph[i].sort((a, b) => scores[b] - scores[a]);
+    if (graph[i].length > 3) {
+      graph[i] = graph[i].slice(0, 3);
+    }
+  }
+
+  let result = -1;
+  for (const [a, b] of edges) {
+    for (const c of graph[a]) {
+      if (c === b) continue;
+      for (const d of graph[b]) {
+        if (d === a || d === c) continue;
+        result = Math.max(result, scores[a] + scores[b] + scores[c] + scores[d]);
+      }
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2243-calculate-digit-sum-of-a-string.js b/solutions/2243-calculate-digit-sum-of-a-string.js
new file mode 100644
index 00000000..293438ed
--- /dev/null
+++ b/solutions/2243-calculate-digit-sum-of-a-string.js
@@ -0,0 +1,36 @@
+/**
+ * 2243. Calculate Digit Sum of a String
+ * https://leetcode.com/problems/calculate-digit-sum-of-a-string/
+ * Difficulty: Easy
+ *
+ * You are given a string s consisting of digits and an integer k.
+ *
+ * A round can be completed if the length of s is greater than k. In one round, do the following:
+ * 1. Divide s into consecutive groups of size k such that the first k characters are in the first
+ *    group, the next k characters are in the second group, and so on. Note that the size of the
+ *    last group can be smaller than k.
+ * 2. Replace each group of s with a string representing the sum of all its digits. For example,
+ *    "346" is replaced with "13" because 3 + 4 + 6 = 13.
+ * 3. Merge consecutive groups together to form a new string. If the length of the string is greater
+ *    than k, repeat from step 1.
+ *
+ * Return s after all rounds have been completed.
+ */
+
+/**
+ * @param {string} s
+ * @param {number} k
+ * @return {string}
+ */
+var digitSum = function(s, k) {
+  while (s.length > k) {
+    let next = '';
+    for (let i = 0; i < s.length; i += k) {
+      const group = s.slice(i, i + k);
+      const sum = group.split('').reduce((acc, digit) => acc + Number(digit), 0);
+      next += sum;
+    }
+    s = next;
+  }
+  return s;
+};
diff --git a/solutions/2245-maximum-trailing-zeros-in-a-cornered-path.js b/solutions/2245-maximum-trailing-zeros-in-a-cornered-path.js
new file mode 100644
index 00000000..7f18ed32
--- /dev/null
+++ b/solutions/2245-maximum-trailing-zeros-in-a-cornered-path.js
@@ -0,0 +1,112 @@
+/**
+ * 2245. Maximum Trailing Zeros in a Cornered Path
+ * https://leetcode.com/problems/maximum-trailing-zeros-in-a-cornered-path/
+ * Difficulty: Medium
+ *
+ * You are given a 2D integer array grid of size m x n, where each cell contains a positive integer.
+ *
+ * A cornered path is defined as a set of adjacent cells with at most one turn. More specifically,
+ * the path should exclusively move either horizontally or vertically up to the turn (if there is
+ * one), without returning to a previously visited cell. After the turn, the path will then move
+ * exclusively in the alternate direction: move vertically if it moved horizontally, and vice versa,
+ * also without returning to a previously visited cell.
+ *
+ * The product of a path is defined as the product of all the values in the path.
+ *
+ * Return the maximum number of trailing zeros in the product of a cornered path found in grid.
+ *
+ * Note:
+ * - Horizontal movement means moving in either the left or right direction.
+ * - Vertical movement means moving in either the up or down direction.
+ */
+
+/**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+var maxTrailingZeros = function(grid) {
+  const m = grid.length;
+  const n = grid[0].length;
+
+  function countFactors(num) {
+    let count2 = 0;
+    let count5 = 0;
+
+    while (num % 2 === 0) {
+      count2++;
+      num = Math.floor(num / 2);
+    }
+
+    while (num % 5 === 0) {
+      count5++;
+      num = Math.floor(num / 5);
+    }
+
+    return [count2, count5];
+  }
+
+  const factors = new Array(m).fill().map(() => new Array(n).fill().map(() => [0, 0]));
+  for (let i = 0; i < m; i++) {
+    for (let j = 0; j < n; j++) {
+      factors[i][j] = countFactors(grid[i][j]);
+    }
+  }
+
+  const rowPrefix = new Array(m).fill().map(() => new Array(n + 1).fill().map(() => [0, 0]));
+  for (let i = 0; i < m; i++) {
+    for (let j = 0; j < n; j++) {
+      rowPrefix[i][j + 1][0] = rowPrefix[i][j][0] + factors[i][j][0];
+      rowPrefix[i][j + 1][1] = rowPrefix[i][j][1] + factors[i][j][1];
+    }
+  }
+
+  const colPrefix = new Array(m + 1).fill().map(() => new Array(n).fill().map(() => [0, 0]));
+  for (let j = 0; j < n; j++) {
+    for (let i = 0; i < m; i++) {
+      colPrefix[i + 1][j][0] = colPrefix[i][j][0] + factors[i][j][0];
+      colPrefix[i + 1][j][1] = colPrefix[i][j][1] + factors[i][j][1];
+    }
+  }
+
+  let maxZeros = 0;
+  for (let i = 0; i < m; i++) {
+    for (let j = 0; j < n; j++) {
+      const [count2, count5] = factors[i][j];
+
+      const leftUp = [
+        rowPrefix[i][j][0] + colPrefix[i][j][0],
+        rowPrefix[i][j][1] + colPrefix[i][j][1]
+      ];
+
+      const leftDown = [
+        rowPrefix[i][j][0] + (colPrefix[m][j][0] - colPrefix[i + 1][j][0]),
+        rowPrefix[i][j][1] + (colPrefix[m][j][1] - colPrefix[i + 1][j][1])
+      ];
+
+      const rightUp = [
+        (rowPrefix[i][n][0] - rowPrefix[i][j + 1][0]) + colPrefix[i][j][0],
+        (rowPrefix[i][n][1] - rowPrefix[i][j + 1][1]) + colPrefix[i][j][1]
+      ];
+
+      const rightDown = [
+        (rowPrefix[i][n][0] - rowPrefix[i][j + 1][0])
+          + (colPrefix[m][j][0] - colPrefix[i + 1][j][0]),
+        (rowPrefix[i][n][1] - rowPrefix[i][j + 1][1])
+          + (colPrefix[m][j][1] - colPrefix[i + 1][j][1])
+      ];
+
+      const paths = [
+        [leftUp[0] + count2, leftUp[1] + count5],
+        [leftDown[0] + count2, leftDown[1] + count5],
+        [rightUp[0] + count2, rightUp[1] + count5],
+        [rightDown[0] + count2, rightDown[1] + count5]
+      ];
+
+      for (const [path2, path5] of paths) {
+        maxZeros = Math.max(maxZeros, Math.min(path2, path5));
+      }
+    }
+  }
+
+  return maxZeros;
+};
diff --git a/solutions/2246-longest-path-with-different-adjacent-characters.js b/solutions/2246-longest-path-with-different-adjacent-characters.js
new file mode 100644
index 00000000..4eb8cb53
--- /dev/null
+++ b/solutions/2246-longest-path-with-different-adjacent-characters.js
@@ -0,0 +1,54 @@
+/**
+ * 2246. Longest Path With Different Adjacent Characters
+ * https://leetcode.com/problems/longest-path-with-different-adjacent-characters/
+ * 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 node i.
+ *
+ * Return the length of the longest path in the tree such that no pair of adjacent nodes on the path
+ * have the same character assigned to them.
+ */
+
+/**
+ * @param {number[]} parent
+ * @param {string} s
+ * @return {number}
+ */
+var longestPath = function(parent, s) {
+  const n = parent.length;
+  const children = Array.from({ length: n }, () => []);
+  let result = 1;
+
+  for (let i = 1; i < n; i++) {
+    children[parent[i]].push(i);
+  }
+
+  findLongest(0);
+
+  return result;
+
+  function findLongest(node) {
+    let longest = 0;
+    let secondLongest = 0;
+
+    for (const child of children[node]) {
+      const length = findLongest(child);
+      if (s[child] !== s[node]) {
+        if (length > longest) {
+          secondLongest = longest;
+          longest = length;
+        } else if (length > secondLongest) {
+          secondLongest = length;
+        }
+      }
+    }
+
+    result = Math.max(result, longest + secondLongest + 1);
+    return longest + 1;
+  }
+};
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/2248-intersection-of-multiple-arrays.js b/solutions/2248-intersection-of-multiple-arrays.js
new file mode 100644
index 00000000..fa162656
--- /dev/null
+++ b/solutions/2248-intersection-of-multiple-arrays.js
@@ -0,0 +1,31 @@
+/**
+ * 2248. Intersection of Multiple Arrays
+ * https://leetcode.com/problems/intersection-of-multiple-arrays/
+ * Difficulty: Easy
+ *
+ * Given a 2D integer array nums where nums[i] is a non-empty array of distinct positive integers,
+ * return the list of integers that are present in each array of nums sorted in ascending order.
+ */
+
+/**
+ * @param {number[][]} nums
+ * @return {number[]}
+ */
+var intersection = function(nums) {
+  const count = new Map();
+
+  for (const array of nums) {
+    for (const num of array) {
+      count.set(num, (count.get(num) || 0) + 1);
+    }
+  }
+
+  const result = [];
+  for (const [num, freq] of count) {
+    if (freq === nums.length) {
+      result.push(num);
+    }
+  }
+
+  return result.sort((a, b) => a - b);
+};
diff --git a/solutions/2249-count-lattice-points-inside-a-circle.js b/solutions/2249-count-lattice-points-inside-a-circle.js
new file mode 100644
index 00000000..2c762806
--- /dev/null
+++ b/solutions/2249-count-lattice-points-inside-a-circle.js
@@ -0,0 +1,33 @@
+/**
+ * 2249. Count Lattice Points Inside a Circle
+ * https://leetcode.com/problems/count-lattice-points-inside-a-circle/
+ * Difficulty: Medium
+ *
+ * Given a 2D integer array circles where circles[i] = [xi, yi, ri] represents the center (xi, yi)
+ * and radius ri of the ith circle drawn on a grid, return the number of lattice points that are
+ * present inside at least one circle.
+ *
+ * Note:
+ * - A lattice point is a point with integer coordinates.
+ * - Points that lie on the circumference of a circle are also considered to be inside it.
+ */
+
+/**
+ * @param {number[][]} circles
+ * @return {number}
+ */
+var countLatticePoints = function(circles) {
+  const set = new Set();
+
+  for (const [x, y, r] of circles) {
+    for (let i = x - r; i <= x + r; i++) {
+      for (let j = y - r; j <= y + r; j++) {
+        if ((x - i) ** 2 + (y - j) ** 2 <= r ** 2) {
+          set.add(`${i},${j}`);
+        }
+      }
+    }
+  }
+
+  return set.size;
+};
diff --git a/solutions/2250-count-number-of-rectangles-containing-each-point.js b/solutions/2250-count-number-of-rectangles-containing-each-point.js
new file mode 100644
index 00000000..79ed186c
--- /dev/null
+++ b/solutions/2250-count-number-of-rectangles-containing-each-point.js
@@ -0,0 +1,62 @@
+/**
+ * 2250. Count Number of Rectangles Containing Each Point
+ * https://leetcode.com/problems/count-number-of-rectangles-containing-each-point/
+ * Difficulty: Medium
+ *
+ * You are given a 2D integer array rectangles where rectangles[i] = [li, hi] indicates that ith
+ * rectangle has a length of li and a height of hi. You are also given a 2D integer array points
+ * where points[j] = [xj, yj] is a point with coordinates (xj, yj).
+ *
+ * The ith rectangle has its bottom-left corner point at the coordinates (0, 0) and its top-right
+ * corner point at (li, hi).
+ *
+ * Return an integer array count of length points.length where count[j] is the number of rectangles
+ * that contain the jth point.
+ *
+ * The ith rectangle contains the jth point if 0 <= xj <= li and 0 <= yj <= hi. Note that points
+ * that lie on the edges of a rectangle are also considered to be contained by that rectangle.
+ */
+
+/**
+ * @param {number[][]} rectangles
+ * @param {number[][]} points
+ * @return {number[]}
+ */
+var countRectangles = function(rectangles, points) {
+  const rectByHeight = new Array(101).fill().map(() => []);
+
+  for (const [length, height] of rectangles) {
+    rectByHeight[height].push(length);
+  }
+
+  for (let h = 0; h <= 100; h++) {
+    rectByHeight[h].sort((a, b) => a - b);
+  }
+
+  const result = new Array(points.length).fill(0);
+  for (let i = 0; i < points.length; i++) {
+    const [x, y] = points[i];
+
+    for (let h = y; h <= 100; h++) {
+      const lengths = rectByHeight[h];
+
+      let left = 0;
+      let right = lengths.length - 1;
+      let insertPos = lengths.length;
+
+      while (left <= right) {
+        const mid = Math.floor((left + right) / 2);
+        if (lengths[mid] >= x) {
+          insertPos = mid;
+          right = mid - 1;
+        } else {
+          left = mid + 1;
+        }
+      }
+
+      result[i] += lengths.length - insertPos;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2251-number-of-flowers-in-full-bloom.js b/solutions/2251-number-of-flowers-in-full-bloom.js
new file mode 100644
index 00000000..c9ae393f
--- /dev/null
+++ b/solutions/2251-number-of-flowers-in-full-bloom.js
@@ -0,0 +1,43 @@
+/**
+ * 2251. Number of Flowers in Full Bloom
+ * https://leetcode.com/problems/number-of-flowers-in-full-bloom/
+ * Difficulty: Hard
+ *
+ * You are given a 0-indexed 2D integer array flowers, where flowers[i] = [starti, endi] means
+ * the ith flower will be in full bloom from starti to endi (inclusive). You are also given a
+ * 0-indexed integer array people of size n, where people[i] is the time that the ith person
+ * will arrive to see the flowers.
+ *
+ * Return an integer array answer of size n, where answer[i] is the number of flowers that are
+ * in full bloom when the ith person arrives.
+ */
+
+/**
+ * @param {number[][]} flowers
+ * @param {number[]} people
+ * @return {number[]}
+ */
+var fullBloomFlowers = function(flowers, people) {
+  const events = [];
+  for (const [start, end] of flowers) {
+    events.push([start, 1]);
+    events.push([end + 1, -1]);
+  }
+  events.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
+
+  const result = new Array(people.length).fill(0);
+  const peopleWithIndex = people.map((time, index) => [time, index]);
+  peopleWithIndex.sort((a, b) => a[0] - b[0]);
+
+  let bloomCount = 0;
+  let eventIndex = 0;
+  for (const [time, personIndex] of peopleWithIndex) {
+    while (eventIndex < events.length && events[eventIndex][0] <= time) {
+      bloomCount += events[eventIndex][1];
+      eventIndex++;
+    }
+    result[personIndex] = bloomCount;
+  }
+
+  return result;
+};
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/2255-count-prefixes-of-a-given-string.js b/solutions/2255-count-prefixes-of-a-given-string.js
new file mode 100644
index 00000000..25f3ecbf
--- /dev/null
+++ b/solutions/2255-count-prefixes-of-a-given-string.js
@@ -0,0 +1,30 @@
+/**
+ * 2255. Count Prefixes of a Given String
+ * https://leetcode.com/problems/count-prefixes-of-a-given-string/
+ * Difficulty: Easy
+ *
+ * You are given a string array words and a string s, where words[i] and s comprise only of
+ * lowercase English letters.
+ *
+ * Return the number of strings in words that are a prefix of s.
+ *
+ * A prefix of a string is a substring that occurs at the beginning of the string. A substring
+ * is a contiguous sequence of characters within a string.
+ */
+
+/**
+ * @param {string[]} words
+ * @param {string} s
+ * @return {number}
+ */
+var countPrefixes = function(words, s) {
+  let result = 0;
+
+  for (const word of words) {
+    if (word.length <= s.length && s.startsWith(word)) {
+      result++;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2256-minimum-average-difference.js b/solutions/2256-minimum-average-difference.js
new file mode 100644
index 00000000..8c7ebdde
--- /dev/null
+++ b/solutions/2256-minimum-average-difference.js
@@ -0,0 +1,46 @@
+/**
+ * 2256. Minimum Average Difference
+ * https://leetcode.com/problems/minimum-average-difference/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums of length n.
+ *
+ * The average difference of the index i is the absolute difference between the average of the
+ * first i + 1 elements of nums and the average of the last n - i - 1 elements. Both averages
+ * should be rounded down to the nearest integer.
+ *
+ * Return the index with the minimum average difference. If there are multiple such indices,
+ * return the smallest one.
+ *
+ * Note:
+ * - The absolute difference of two numbers is the absolute value of their difference.
+ * - The average of n elements is the sum of the n elements divided (integer division) by n.
+ * - The average of 0 elements is considered to be 0.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var minimumAverageDifference = function(nums) {
+  const n = nums.length;
+  let leftSum = 0;
+  let rightSum = nums.reduce((sum, num) => sum + num, 0);
+  let minDiff = Infinity;
+  let result = 0;
+
+  for (let i = 0; i < n; i++) {
+    leftSum += nums[i];
+    rightSum -= nums[i];
+    const leftAvg = Math.floor(leftSum / (i + 1));
+    const rightAvg = i === n - 1 ? 0 : Math.floor(rightSum / (n - i - 1));
+    const diff = Math.abs(leftAvg - rightAvg);
+
+    if (diff < minDiff) {
+      minDiff = diff;
+      result = i;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2257-count-unguarded-cells-in-the-grid.js b/solutions/2257-count-unguarded-cells-in-the-grid.js
new file mode 100644
index 00000000..87cbde16
--- /dev/null
+++ b/solutions/2257-count-unguarded-cells-in-the-grid.js
@@ -0,0 +1,59 @@
+/**
+ * 2257. Count Unguarded Cells in the Grid
+ * https://leetcode.com/problems/count-unguarded-cells-in-the-grid/
+ * Difficulty: Medium
+ *
+ * You are given two integers m and n representing a 0-indexed m x n grid. You are also given two
+ * 2D integer arrays guards and walls where guards[i] = [rowi, coli] and walls[j] = [rowj, colj]
+ * represent the positions of the ith guard and jth wall respectively.
+ *
+ * A guard can see every cell in the four cardinal directions (north, east, south, or west) starting
+ * from their position unless obstructed by a wall or another guard. A cell is guarded if there is
+ * at least one guard that can see it.
+ *
+ * Return the number of unoccupied cells that are not guarded.
+ */
+
+/**
+ * @param {number} m
+ * @param {number} n
+ * @param {number[][]} guards
+ * @param {number[][]} walls
+ * @return {number}
+ */
+var countUnguarded = function(m, n, guards, walls) {
+  const grid = Array.from({ length: m }, () => Array(n).fill(0));
+
+  for (const [row, col] of walls) {
+    grid[row][col] = 1;
+  }
+  for (const [row, col] of guards) {
+    grid[row][col] = 2;
+  }
+
+  for (const [row, col] of guards) {
+    for (let i = row - 1; i >= 0 && grid[i][col] !== 1 && grid[i][col] !== 2; i--) {
+      grid[i][col] = 3;
+    }
+    for (let i = row + 1; i < m && grid[i][col] !== 1 && grid[i][col] !== 2; i++) {
+      grid[i][col] = 3;
+    }
+    for (let j = col - 1; j >= 0 && grid[row][j] !== 1 && grid[row][j] !== 2; j--) {
+      grid[row][j] = 3;
+    }
+    for (let j = col + 1; j < n && grid[row][j] !== 1 && grid[row][j] !== 2; j++) {
+      grid[row][j] = 3;
+    }
+  }
+
+  let result = 0;
+  for (let i = 0; i < m; i++) {
+    for (let j = 0; j < n; j++) {
+      if (grid[i][j] === 0) {
+        result++;
+      }
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2258-escape-the-spreading-fire.js b/solutions/2258-escape-the-spreading-fire.js
new file mode 100644
index 00000000..7e26720a
--- /dev/null
+++ b/solutions/2258-escape-the-spreading-fire.js
@@ -0,0 +1,118 @@
+/**
+ * 2258. Escape the Spreading Fire
+ * https://leetcode.com/problems/escape-the-spreading-fire/
+ * Difficulty: Hard
+ *
+ * You are given a 0-indexed 2D integer array grid of size m x n which represents a field.
+ * Each cell has one of three values:
+ * - 0 represents grass,
+ * - 1 represents fire,
+ * - 2 represents a wall that you and fire cannot pass through.
+ *
+ * You are situated in the top-left cell, (0, 0), and you want to travel to the safehouse at the
+ * bottom-right cell, (m - 1, n - 1). Every minute, you may move to an adjacent grass cell. After
+ * your move, every fire cell will spread to all adjacent cells that are not walls.
+ *
+ * Return the maximum number of minutes that you can stay in your initial position before moving
+ * while still safely reaching the safehouse. If this is impossible, return -1. If you can always
+ * reach the safehouse regardless of the minutes stayed, return 109.
+ *
+ * Note that even if the fire spreads to the safehouse immediately after you have reached it, it
+ * will be counted as safely reaching the safehouse.
+ *
+ * A cell is adjacent to another cell if the former is directly north, east, south, or west of the
+ * latter (i.e., their sides are touching).
+ */
+
+/**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+var maximumMinutes = function(grid) {
+  const m = grid.length;
+  const n = grid[0].length;
+  const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]];
+  const MAX_ANSWER = 1000000000;
+
+  function isValid(x, y) {
+    return x >= 0 && x < m && y >= 0 && y < n && grid[x][y] === 0;
+  }
+
+  function calculateFireTime() {
+    const fireTime = new Array(m).fill().map(() => new Array(n).fill(Infinity));
+    const queue = [];
+
+    for (let i = 0; i < m; i++) {
+      for (let j = 0; j < n; j++) {
+        if (grid[i][j] === 1) {
+          queue.push([i, j, 0]);
+          fireTime[i][j] = 0;
+        }
+      }
+    }
+
+    while (queue.length > 0) {
+      const [x, y, time] = queue.shift();
+
+      for (const [dx, dy] of directions) {
+        const nx = x + dx;
+        const ny = y + dy;
+
+        if (isValid(nx, ny) && fireTime[nx][ny] === Infinity) {
+          fireTime[nx][ny] = time + 1;
+          queue.push([nx, ny, time + 1]);
+        }
+      }
+    }
+
+    return fireTime;
+  }
+
+  function canReachSafehouse(delay) {
+    const fireTime = calculateFireTime();
+    const visited = new Array(m).fill().map(() => new Array(n).fill(false));
+    const queue = [[0, 0, delay]];
+    visited[0][0] = true;
+
+    while (queue.length > 0) {
+      const [x, y, time] = queue.shift();
+
+      for (const [dx, dy] of directions) {
+        const nx = x + dx;
+        const ny = y + dy;
+
+        if (!isValid(nx, ny) || visited[nx][ny]) continue;
+
+        if (nx === m - 1 && ny === n - 1) {
+          if (time + 1 <= fireTime[nx][ny] || fireTime[nx][ny] === Infinity) {
+            return true;
+          }
+        }
+
+        if (time + 1 < fireTime[nx][ny]) {
+          visited[nx][ny] = true;
+          queue.push([nx, ny, time + 1]);
+        }
+      }
+    }
+
+    return false;
+  }
+
+  let left = 0;
+  let right = MAX_ANSWER;
+  let result = -1;
+
+  while (left <= right) {
+    const mid = Math.floor((left + right) / 2);
+
+    if (canReachSafehouse(mid)) {
+      result = mid;
+      left = mid + 1;
+    } else {
+      right = mid - 1;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2259-remove-digit-from-number-to-maximize-result.js b/solutions/2259-remove-digit-from-number-to-maximize-result.js
new file mode 100644
index 00000000..d9ee4397
--- /dev/null
+++ b/solutions/2259-remove-digit-from-number-to-maximize-result.js
@@ -0,0 +1,31 @@
+/**
+ * 2259. Remove Digit From Number to Maximize Result
+ * https://leetcode.com/problems/remove-digit-from-number-to-maximize-result/
+ * Difficulty: Easy
+ *
+ * You are given a string number representing a positive integer and a character digit.
+ *
+ * Return the resulting string after removing exactly one occurrence of digit from number such that
+ * the value of the resulting string in decimal form is maximized. The test cases are generated such
+ * that digit occurs at least once in number.
+ */
+
+/**
+ * @param {string} number
+ * @param {character} digit
+ * @return {string}
+ */
+var removeDigit = function(number, digit) {
+  let result = '';
+
+  for (let i = 0; i < number.length; i++) {
+    if (number[i] === digit) {
+      const candidate = number.slice(0, i) + number.slice(i + 1);
+      if (candidate > result) {
+        result = candidate;
+      }
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2260-minimum-consecutive-cards-to-pick-up.js b/solutions/2260-minimum-consecutive-cards-to-pick-up.js
new file mode 100644
index 00000000..4463e10c
--- /dev/null
+++ b/solutions/2260-minimum-consecutive-cards-to-pick-up.js
@@ -0,0 +1,29 @@
+/**
+ * 2260. Minimum Consecutive Cards to Pick Up
+ * https://leetcode.com/problems/minimum-consecutive-cards-to-pick-up/
+ * Difficulty: Medium
+ *
+ * You are given an integer array cards where cards[i] represents the value of the ith card. A pair
+ * of cards are matching if the cards have the same value.
+ *
+ * Return the minimum number of consecutive cards you have to pick up to have a pair of matching
+ * cards among the picked cards. If it is impossible to have matching cards, return -1.
+ */
+
+/**
+ * @param {number[]} cards
+ * @return {number}
+ */
+var minimumCardPickup = function(cards) {
+  const map = new Map();
+  let minLength = Infinity;
+
+  for (let i = 0; i < cards.length; i++) {
+    if (map.has(cards[i])) {
+      minLength = Math.min(minLength, i - map.get(cards[i]) + 1);
+    }
+    map.set(cards[i], i);
+  }
+
+  return minLength === Infinity ? -1 : minLength;
+};
diff --git a/solutions/2261-k-divisible-elements-subarrays.js b/solutions/2261-k-divisible-elements-subarrays.js
new file mode 100644
index 00000000..72d781d1
--- /dev/null
+++ b/solutions/2261-k-divisible-elements-subarrays.js
@@ -0,0 +1,41 @@
+/**
+ * 2261. K Divisible Elements Subarrays
+ * https://leetcode.com/problems/k-divisible-elements-subarrays/
+ * Difficulty: Medium
+ *
+ * Given an integer array nums and two integers k and p, return the number of distinct subarrays,
+ * which have at most k elements that are divisible by p.
+ *
+ * Two arrays nums1 and nums2 are said to be distinct if:
+ * - They are of different lengths, or
+ * - There exists at least one index i where nums1[i] != nums2[i].
+ *
+ * A subarray is defined as a non-empty contiguous sequence of elements in an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @param {number} p
+ * @return {number}
+ */
+var countDistinct = function(nums, k, p) {
+  const n = nums.length;
+  const seen = new Set();
+
+  for (let start = 0; start < n; start++) {
+    const subarray = [];
+    let divisibleCount = 0;
+
+    for (let end = start; end < n; end++) {
+      subarray.push(nums[end]);
+      if (nums[end] % p === 0) divisibleCount++;
+
+      if (divisibleCount <= k) {
+        seen.add(subarray.join(','));
+      }
+    }
+  }
+
+  return seen.size;
+};
diff --git a/solutions/2262-total-appeal-of-a-string.js b/solutions/2262-total-appeal-of-a-string.js
new file mode 100644
index 00000000..20c2e2c3
--- /dev/null
+++ b/solutions/2262-total-appeal-of-a-string.js
@@ -0,0 +1,31 @@
+/**
+ * 2262. Total Appeal of A String
+ * https://leetcode.com/problems/total-appeal-of-a-string/
+ * Difficulty: Hard
+ *
+ * The appeal of a string is the number of distinct characters found in the string.
+ * - For example, the appeal of "abbca" is 3 because it has 3 distinct characters:
+ *   'a', 'b', and 'c'.
+ *
+ * Given a string s, return the total appeal of all of its substrings.
+ *
+ * A substring is a contiguous sequence of characters within a string.
+ */
+
+/**
+ * @param {string} s
+ * @return {number}
+ */
+var appealSum = function(s) {
+  const n = s.length;
+  const lastSeen = new Array(26).fill(-1);
+  let result = 0;
+
+  for (let i = 0; i < n; i++) {
+    const charIndex = s.charCodeAt(i) - 97;
+    result += (i - lastSeen[charIndex]) * (n - i);
+    lastSeen[charIndex] = i;
+  }
+
+  return result;
+};
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/2264-largest-3-same-digit-number-in-string.js b/solutions/2264-largest-3-same-digit-number-in-string.js
new file mode 100644
index 00000000..ef1df3a9
--- /dev/null
+++ b/solutions/2264-largest-3-same-digit-number-in-string.js
@@ -0,0 +1,35 @@
+/**
+ * 2264. Largest 3-Same-Digit Number in String
+ * https://leetcode.com/problems/largest-3-same-digit-number-in-string/
+ * Difficulty: Easy
+ *
+ * You are given a string num representing a large integer. An integer is good if it meets
+ * the following conditions:
+ * - It is a substring of num with length 3.
+ * - It consists of only one unique digit.
+ *
+ * Return the maximum good integer as a string or an empty string "" if no such integer exists.
+ *
+ * Note:
+ * - A substring is a contiguous sequence of characters within a string.
+ * - There may be leading zeroes in num or a good integer.
+ */
+
+/**
+ * @param {string} num
+ * @return {string}
+ */
+var largestGoodInteger = function(num) {
+  let result = '';
+
+  for (let i = 0; i <= num.length - 3; i++) {
+    const substring = num.slice(i, i + 3);
+    if (substring[0] === substring[1] && substring[1] === substring[2]) {
+      if (substring > result) {
+        result = substring;
+      }
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2265-count-nodes-equal-to-average-of-subtree.js b/solutions/2265-count-nodes-equal-to-average-of-subtree.js
new file mode 100644
index 00000000..2e3f4cb5
--- /dev/null
+++ b/solutions/2265-count-nodes-equal-to-average-of-subtree.js
@@ -0,0 +1,46 @@
+/**
+ * 2265. Count Nodes Equal to Average of Subtree
+ * https://leetcode.com/problems/count-nodes-equal-to-average-of-subtree/
+ * Difficulty: Medium
+ *
+ * Given the root of a binary tree, return the number of nodes where the value of the node is
+ * equal to the average of the values in its subtree.
+ *
+ * Note:
+ * - The average of n elements is the sum of the n elements divided by n and rounded down to
+ *   the nearest integer.
+ * - A subtree of root is a tree consisting of root and 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 averageOfSubtree = function(root) {
+  let count = 0;
+  traverse(root);
+  return count;
+
+  function traverse(node) {
+    if (!node) return [0, 0];
+
+    const [leftSum, leftCount] = traverse(node.left);
+    const [rightSum, rightCount] = traverse(node.right);
+    const totalSum = leftSum + rightSum + node.val;
+    const totalCount = leftCount + rightCount + 1;
+
+    if (Math.floor(totalSum / totalCount) === node.val) {
+      count++;
+    }
+
+    return [totalSum, totalCount];
+  }
+};
diff --git a/solutions/2266-count-number-of-texts.js b/solutions/2266-count-number-of-texts.js
new file mode 100644
index 00000000..d2f9cf84
--- /dev/null
+++ b/solutions/2266-count-number-of-texts.js
@@ -0,0 +1,57 @@
+/**
+ * 2266. Count Number of Texts
+ * https://leetcode.com/problems/count-number-of-texts/
+ * Difficulty: Medium
+ *
+ * Alice is texting Bob using her phone. The mapping of digits to letters is shown in the
+ * figure below.
+ *
+ * In order to add a letter, Alice has to press the key of the corresponding digit i times,
+ * where i is the position of the letter in the key.
+ * - For example, to add the letter 's', Alice has to press '7' four times. Similarly, to
+ *   add the letter 'k', Alice has to press '5' twice.
+ * - Note that the digits '0' and '1' do not map to any letters, so Alice does not use them.
+ *
+ * However, due to an error in transmission, Bob did not receive Alice's text message but
+ * received a string of pressed keys instead.
+ * - For example, when Alice sent the message "bob", Bob received the string "2266622".
+ *
+ * Given a string pressedKeys representing the string received by Bob, return the total
+ * number of possible text messages Alice could have sent.
+ *
+ * Since the answer may be very large, return it modulo 109 + 7.
+ */
+
+/**
+ * @param {string} pressedKeys
+ * @return {number}
+ */
+var countTexts = function(pressedKeys) {
+  const mod = 1e9 + 7;
+  const maxGroup = pressedKeys.length;
+  const dp = new Array(maxGroup + 1).fill(0);
+  dp[0] = 1;
+
+  const map = new Map([
+    ['2', 3], ['3', 3], ['4', 3], ['5', 3],
+    ['6', 3], ['7', 4], ['8', 3], ['9', 4]
+  ]);
+
+  for (let i = 1; i <= maxGroup; i++) {
+    dp[i] = dp[i - 1];
+    if (i >= 2 && pressedKeys[i - 1] === pressedKeys[i - 2]) {
+      dp[i] = (dp[i] + dp[i - 2]) % mod;
+    }
+    if (i >= 3 && pressedKeys[i - 1] === pressedKeys[i - 2]
+        && pressedKeys[i - 2] === pressedKeys[i - 3]) {
+      dp[i] = (dp[i] + dp[i - 3]) % mod;
+    }
+    if (i >= 4 && pressedKeys[i - 1] === pressedKeys[i - 2]
+        && pressedKeys[i - 2] === pressedKeys[i - 3]
+        && pressedKeys[i - 3] === pressedKeys[i - 4] && map.get(pressedKeys[i - 1]) === 4) {
+      dp[i] = (dp[i] + dp[i - 4]) % mod;
+    }
+  }
+
+  return dp[maxGroup];
+};
diff --git a/solutions/2267-check-if-there-is-a-valid-parentheses-string-path.js b/solutions/2267-check-if-there-is-a-valid-parentheses-string-path.js
new file mode 100644
index 00000000..8dc163ed
--- /dev/null
+++ b/solutions/2267-check-if-there-is-a-valid-parentheses-string-path.js
@@ -0,0 +1,57 @@
+/**
+ * 2267. Check if There Is a Valid Parentheses String Path
+ * https://leetcode.com/problems/check-if-there-is-a-valid-parentheses-string-path/
+ * Difficulty: Hard
+ *
+ * A parentheses string is a non-empty string consisting only of '(' and ')'. It is valid if any of
+ * the following conditions is true:
+ * - It is ().
+ * - It can be written as AB (A concatenated with B), where A and B are valid parentheses strings.
+ * - It can be written as (A), where A is a valid parentheses string.
+ *
+ * You are given an m x n matrix of parentheses grid. A valid parentheses string path in the grid
+ * is a path satisfying all of the following conditions:
+ * - The path starts from the upper left cell (0, 0).
+ * - The path ends at the bottom-right cell (m - 1, n - 1).
+ * - The path only ever moves down or right.
+ * - The resulting parentheses string formed by the path is valid.
+ *
+ * Return true if there exists a valid parentheses string path in the grid. Otherwise, return false.
+ */
+
+/**
+* @param {character[][]} grid
+* @return {boolean}
+*/
+var hasValidPath = function(grid) {
+  const m = grid.length;
+  const n = grid[0].length;
+
+  if ((m + n - 1) % 2 !== 0) {
+    return false;
+  }
+
+  if (grid[0][0] === ')' || grid[m - 1][n - 1] === '(') {
+    return false;
+  }
+
+  const visited = new Set();
+  return dfs(0, 0, 0);
+
+  function dfs(i, j, openCount) {
+    if (i >= m || j >= n || openCount < 0) {
+      return false;
+    }
+    openCount += grid[i][j] === '(' ? 1 : -1;
+    if (i === m - 1 && j === n - 1) {
+      return openCount === 0;
+    }
+    const key = `${i},${j},${openCount}`;
+    if (visited.has(key)) {
+      return false;
+    }
+    visited.add(key);
+
+    return dfs(i + 1, j, openCount) || dfs(i, j + 1, openCount);
+  }
+};
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/2269-find-the-k-beauty-of-a-number.js b/solutions/2269-find-the-k-beauty-of-a-number.js
new file mode 100644
index 00000000..3027e4d4
--- /dev/null
+++ b/solutions/2269-find-the-k-beauty-of-a-number.js
@@ -0,0 +1,37 @@
+/**
+ * 2269. Find the K-Beauty of a Number
+ * https://leetcode.com/problems/find-the-k-beauty-of-a-number/
+ * Difficulty: Easy
+ *
+ * The k-beauty of an integer num is defined as the number of substrings of num when it is
+ * read as a string that meet the following conditions:
+ * - It has a length of k.
+ * - It is a divisor of num.
+ *
+ * Given integers num and k, return the k-beauty of num.
+ *
+ * Note:
+ * - Leading zeros are allowed.
+ * - 0 is not a divisor of any value.
+ *
+ * A substring is a contiguous sequence of characters in a string.
+ */
+
+/**
+ * @param {number} num
+ * @param {number} k
+ * @return {number}
+ */
+var divisorSubstrings = function(num, k) {
+  const numStr = num.toString();
+  let result = 0;
+
+  for (let i = 0; i <= numStr.length - k; i++) {
+    const substring = parseInt(numStr.slice(i, i + k));
+    if (substring !== 0 && num % substring === 0) {
+      result++;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2271-maximum-white-tiles-covered-by-a-carpet.js b/solutions/2271-maximum-white-tiles-covered-by-a-carpet.js
new file mode 100644
index 00000000..0af443fc
--- /dev/null
+++ b/solutions/2271-maximum-white-tiles-covered-by-a-carpet.js
@@ -0,0 +1,50 @@
+/**
+ * 2271. Maximum White Tiles Covered by a Carpet
+ * https://leetcode.com/problems/maximum-white-tiles-covered-by-a-carpet/
+ * Difficulty: Medium
+ *
+ * You are given a 2D integer array tiles where tiles[i] = [li, ri] represents that every tile
+ * j in the range li <= j <= ri is colored white.
+ *
+ * You are also given an integer carpetLen, the length of a single carpet that can be placed
+ * anywhere.
+ *
+ * Return the maximum number of white tiles that can be covered by the carpet.
+ */
+
+/**
+ * @param {number[][]} tiles
+ * @param {number} carpetLen
+ * @return {number}
+ */
+var maximumWhiteTiles = function(tiles, carpetLen) {
+  tiles.sort((a, b) => a[0] - b[0]);
+
+  let result = 0;
+  let covered = 0;
+  let j = 0;
+
+  for (let i = 0; i < tiles.length; i++) {
+    const carpetEnd = tiles[i][0] + carpetLen - 1;
+
+    while (j < tiles.length && tiles[j][0] <= carpetEnd) {
+      if (tiles[j][1] <= carpetEnd) {
+        covered += tiles[j][1] - tiles[j][0] + 1;
+        j++;
+      } else {
+        covered += carpetEnd - tiles[j][0] + 1;
+        result = Math.max(result, covered);
+        covered -= carpetEnd - tiles[j][0] + 1;
+        break;
+      }
+    }
+
+    result = Math.max(result, covered);
+
+    if (j === tiles.length) break;
+
+    covered -= tiles[i][1] - tiles[i][0] + 1;
+  }
+
+  return result;
+};
diff --git a/solutions/2272-substring-with-largest-variance.js b/solutions/2272-substring-with-largest-variance.js
new file mode 100644
index 00000000..f11361c2
--- /dev/null
+++ b/solutions/2272-substring-with-largest-variance.js
@@ -0,0 +1,84 @@
+/**
+ * 2272. Substring With Largest Variance
+ * https://leetcode.com/problems/substring-with-largest-variance/
+ * Difficulty: Hard
+ *
+ * The variance of a string is defined as the largest difference between the number of occurrences
+ * of any 2 characters present in the string. Note the two characters may or may not be the same.
+ *
+ * Given a string s consisting of lowercase English letters only, return the largest variance
+ * possible among all substrings of s.
+ *
+ * A substring is a contiguous sequence of characters within a string.
+ */
+
+/**
+ * @param {string} s
+ * @return {number}
+ */
+var largestVariance = function(s) {
+  const map = new Set(s);
+  let result = 0;
+
+  for (const charA of map) {
+    for (const charB of map) {
+      if (charA === charB) continue;
+
+      let countA = 0;
+      let countB = 0;
+      let hasA = false;
+      let hasB = false;
+
+      for (const char of s) {
+        if (char === charA) {
+          countA++;
+          hasA = true;
+        }
+        if (char === charB) {
+          countB++;
+          hasB = true;
+        }
+
+        if (hasA && hasB) {
+          result = Math.max(result, Math.abs(countA - countB));
+        }
+
+        if (countA < countB) {
+          countA = 0;
+          countB = 0;
+          hasA = false;
+          hasB = false;
+        }
+      }
+
+      countA = 0;
+      countB = 0;
+      hasA = false;
+      hasB = false;
+
+      for (let i = s.length - 1; i >= 0; i--) {
+        if (s[i] === charA) {
+          countA++;
+          hasA = true;
+        }
+        if (s[i] === charB) {
+          countB++;
+          hasB = true;
+        }
+
+        if (hasA && hasB) {
+          result = Math.max(result, Math.abs(countA - countB));
+        }
+
+        if (countA < countB) {
+          countA = 0;
+          countB = 0;
+          hasA = false;
+          hasB = false;
+        }
+      }
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2273-find-resultant-array-after-removing-anagrams.js b/solutions/2273-find-resultant-array-after-removing-anagrams.js
new file mode 100644
index 00000000..8e0ef746
--- /dev/null
+++ b/solutions/2273-find-resultant-array-after-removing-anagrams.js
@@ -0,0 +1,38 @@
+/**
+ * 2273. Find Resultant Array After Removing Anagrams
+ * https://leetcode.com/problems/find-resultant-array-after-removing-anagrams/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed string array words, where words[i] consists of lowercase
+ * English letters.
+ *
+ * In one operation, select any index i such that 0 < i < words.length and words[i - 1] and
+ * words[i] are anagrams, and delete words[i] from words. Keep performing this operation as
+ * long as you can select an index that satisfies the conditions.
+ *
+ * Return words after performing all operations. It can be shown that selecting the indices
+ * for each operation in any arbitrary order will lead to the same result.
+ *
+ * An Anagram is a word or phrase formed by rearranging the letters of a different word or
+ * phrase using all the original letters exactly once. For example, "dacb" is an anagram of
+ * "abdc".
+ */
+
+/**
+ * @param {string[]} words
+ * @return {string[]}
+ */
+var removeAnagrams = function(words) {
+  const result = [words[0]];
+
+  for (let i = 1; i < words.length; i++) {
+    const prevSorted = result[result.length - 1].split('').sort().join('');
+    const currSorted = words[i].split('').sort().join('');
+
+    if (prevSorted !== currSorted) {
+      result.push(words[i]);
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2274-maximum-consecutive-floors-without-special-floors.js b/solutions/2274-maximum-consecutive-floors-without-special-floors.js
new file mode 100644
index 00000000..6ccb00f4
--- /dev/null
+++ b/solutions/2274-maximum-consecutive-floors-without-special-floors.js
@@ -0,0 +1,31 @@
+/**
+ * 2274. Maximum Consecutive Floors Without Special Floors
+ * https://leetcode.com/problems/maximum-consecutive-floors-without-special-floors/
+ * Difficulty: Medium
+ *
+ * Alice manages a company and has rented some floors of a building as office space. Alice has
+ * decided some of these floors should be special floors, used for relaxation only.
+ *
+ * You are given two integers bottom and top, which denote that Alice has rented all the floors
+ * from bottom to top (inclusive). You are also given the integer array special, where special[i]
+ * denotes a special floor that Alice has designated for relaxation.
+ *
+ * Return the maximum number of consecutive floors without a special floor.
+ */
+
+/**
+ * @param {number} bottom
+ * @param {number} top
+ * @param {number[]} special
+ * @return {number}
+ */
+var maxConsecutive = function(bottom, top, special) {
+  special.sort((a, b) => a - b);
+  let result = Math.max(special[0] - bottom, top - special[special.length - 1]);
+
+  for (let i = 1; i < special.length; i++) {
+    result = Math.max(result, special[i] - special[i - 1] - 1);
+  }
+
+  return result;
+};
diff --git a/solutions/2275-largest-combination-with-bitwise-and-greater-than-zero.js b/solutions/2275-largest-combination-with-bitwise-and-greater-than-zero.js
new file mode 100644
index 00000000..e75f68d3
--- /dev/null
+++ b/solutions/2275-largest-combination-with-bitwise-and-greater-than-zero.js
@@ -0,0 +1,37 @@
+/**
+ * 2275. Largest Combination With Bitwise AND Greater Than Zero
+ * https://leetcode.com/problems/largest-combination-with-bitwise-and-greater-than-zero/
+ * Difficulty: Medium
+ *
+ * The bitwise AND of an array nums is the bitwise AND of all integers in nums.
+ * - For example, for nums = [1, 5, 3], the bitwise AND is equal to 1 & 5 & 3 = 1.
+ * - Also, for nums = [7], the bitwise AND is 7.
+ *
+ * You are given an array of positive integers candidates. Compute the bitwise AND for all
+ * possible combinations of elements in the candidates array.
+ *
+ * Return the size of the largest combination of candidates with a bitwise AND greater than 0.
+ */
+
+/**
+ * @param {number[]} candidates
+ * @return {number}
+ */
+var largestCombination = function(candidates) {
+  const bitCounts = new Array(32).fill(0);
+  let result = 0;
+
+  for (const num of candidates) {
+    for (let i = 0; i < 32; i++) {
+      if (num & (1 << i)) {
+        bitCounts[i]++;
+      }
+    }
+  }
+
+  for (const count of bitCounts) {
+    result = Math.max(result, count);
+  }
+
+  return result;
+};
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/2278-percentage-of-letter-in-string.js b/solutions/2278-percentage-of-letter-in-string.js
new file mode 100644
index 00000000..fb3dfdbb
--- /dev/null
+++ b/solutions/2278-percentage-of-letter-in-string.js
@@ -0,0 +1,17 @@
+/**
+ * 2278. Percentage of Letter in String
+ * https://leetcode.com/problems/percentage-of-letter-in-string/
+ * Difficulty: Easy
+ *
+ * Given a string s and a character letter, return the percentage of characters in s that equal
+ * letter rounded down to the nearest whole percent.
+ */
+
+/**
+ * @param {string} s
+ * @param {character} letter
+ * @return {number}
+ */
+var percentageLetter = function(s, letter) {
+  return Math.floor((s.split('').filter(char => char === letter).length / s.length) * 100);
+};
diff --git a/solutions/2279-maximum-bags-with-full-capacity-of-rocks.js b/solutions/2279-maximum-bags-with-full-capacity-of-rocks.js
new file mode 100644
index 00000000..77d36c1a
--- /dev/null
+++ b/solutions/2279-maximum-bags-with-full-capacity-of-rocks.js
@@ -0,0 +1,38 @@
+/**
+ * 2279. Maximum Bags With Full Capacity of Rocks
+ * https://leetcode.com/problems/maximum-bags-with-full-capacity-of-rocks/
+ * Difficulty: Medium
+ *
+ * You have n bags numbered from 0 to n - 1. You are given two 0-indexed integer arrays capacity
+ * and rocks. The ith bag can hold a maximum of capacity[i] rocks and currently contains rocks[i]
+ * rocks. You are also given an integer additionalRocks, the number of additional rocks you can
+ * place in any of the bags.
+ *
+ * Return the maximum number of bags that could have full capacity after placing the additional
+ * rocks in some bags.
+ */
+
+/**
+ * @param {number[]} capacity
+ * @param {number[]} rocks
+ * @param {number} additionalRocks
+ * @return {number}
+ */
+var maximumBags = function(capacity, rocks, additionalRocks) {
+  const remaining = capacity.map((cap, i) => cap - rocks[i]);
+  remaining.sort((a, b) => a - b);
+
+  let result = 0;
+  let rocksLeft = additionalRocks;
+
+  for (const needed of remaining) {
+    if (needed <= rocksLeft) {
+      result++;
+      rocksLeft -= needed;
+    } else {
+      break;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2280-minimum-lines-to-represent-a-line-chart.js b/solutions/2280-minimum-lines-to-represent-a-line-chart.js
new file mode 100644
index 00000000..ff401c32
--- /dev/null
+++ b/solutions/2280-minimum-lines-to-represent-a-line-chart.js
@@ -0,0 +1,38 @@
+/**
+ * 2280. Minimum Lines to Represent a Line Chart
+ * https://leetcode.com/problems/minimum-lines-to-represent-a-line-chart/
+ * Difficulty: Medium
+ *
+ * You are given a 2D integer array stockPrices where stockPrices[i] = [dayi, pricei] indicates
+ * the price of the stock on day dayi is pricei. A line chart is created from the array by
+ * plotting the points on an XY plane with the X-axis representing the day and the Y-axis
+ * representing the price and connecting adjacent points. One such example is shown below.
+ *
+ * Return the minimum number of lines needed to represent the line chart.
+ */
+
+/**
+ * @param {number[][]} stockPrices
+ * @return {number}
+ */
+var minimumLines = function(stockPrices) {
+  if (stockPrices.length <= 2) return stockPrices.length - 1;
+
+  stockPrices.sort((a, b) => a[0] - b[0]);
+
+  let lines = 1;
+  for (let i = 2; i < stockPrices.length; i++) {
+    const [x0, y0] = stockPrices[i - 2];
+    const [x1, y1] = stockPrices[i - 1];
+    const [x2, y2] = stockPrices[i];
+
+    const dx1 = BigInt(x1 - x0);
+    const dy1 = BigInt(y1 - y0);
+    const dx2 = BigInt(x2 - x1);
+    const dy2 = BigInt(y2 - y1);
+
+    if (dy1 * dx2 !== dy2 * dx1) lines++;
+  }
+
+  return lines;
+};
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/2283-check-if-number-has-equal-digit-count-and-digit-value.js b/solutions/2283-check-if-number-has-equal-digit-count-and-digit-value.js
new file mode 100644
index 00000000..ea342877
--- /dev/null
+++ b/solutions/2283-check-if-number-has-equal-digit-count-and-digit-value.js
@@ -0,0 +1,30 @@
+/**
+ * 2283. Check if Number Has Equal Digit Count and Digit Value
+ * https://leetcode.com/problems/check-if-number-has-equal-digit-count-and-digit-value/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed string num of length n consisting of digits.
+ *
+ * Return true if for every index i in the range 0 <= i < n, the digit i occurs num[i] times in num,
+ * otherwise return false.
+ */
+
+/**
+ * @param {string} num
+ * @return {boolean}
+ */
+var digitCount = function(num) {
+  const frequency = new Array(10).fill(0);
+
+  for (const digit of num) {
+    frequency[digit]++;
+  }
+
+  for (let i = 0; i < num.length; i++) {
+    if (frequency[i] !== Number(num[i])) {
+      return false;
+    }
+  }
+
+  return true;
+};
diff --git a/solutions/2284-sender-with-largest-word-count.js b/solutions/2284-sender-with-largest-word-count.js
new file mode 100644
index 00000000..d4c02260
--- /dev/null
+++ b/solutions/2284-sender-with-largest-word-count.js
@@ -0,0 +1,44 @@
+/**
+ * 2284. Sender With Largest Word Count
+ * https://leetcode.com/problems/sender-with-largest-word-count/
+ * Difficulty: Medium
+ *
+ * You have a chat log of n messages. You are given two string arrays messages and senders
+ * where messages[i] is a message sent by senders[i].
+ *
+ * A message is list of words that are separated by a single space with no leading or trailing
+ * spaces. The word count of a sender is the total number of words sent by the sender. Note
+ * that a sender may send more than one message.
+ *
+ * Return the sender with the largest word count. If there is more than one sender with the
+ * largest word count, return the one with the lexicographically largest name.
+ *
+ * Note:
+ * - Uppercase letters come before lowercase letters in lexicographical order.
+ * - "Alice" and "alice" are distinct.
+ */
+
+/**
+ * @param {string[]} messages
+ * @param {string[]} senders
+ * @return {string}
+ */
+var largestWordCount = function(messages, senders) {
+  const map = new Map();
+  let maxWords = 0;
+  let result = '';
+
+  for (let i = 0; i < messages.length; i++) {
+    const wordCount = messages[i].split(' ').length;
+    const sender = senders[i];
+    const totalWords = (map.get(sender) || 0) + wordCount;
+    map.set(sender, totalWords);
+
+    if (totalWords > maxWords || (totalWords === maxWords && sender > result)) {
+      maxWords = totalWords;
+      result = sender;
+    }
+  }
+
+  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/2287-rearrange-characters-to-make-target-string.js b/solutions/2287-rearrange-characters-to-make-target-string.js
new file mode 100644
index 00000000..310eb5a2
--- /dev/null
+++ b/solutions/2287-rearrange-characters-to-make-target-string.js
@@ -0,0 +1,38 @@
+/**
+ * 2287. Rearrange Characters to Make Target String
+ * https://leetcode.com/problems/rearrange-characters-to-make-target-string/
+ * Difficulty: Easy
+ *
+ * You are given two 0-indexed strings s and target. You can take some letters from s and
+ * rearrange them to form new strings.
+ *
+ * Return the maximum number of copies of target that can be formed by taking letters from
+ * s and rearranging them.
+ */
+
+/**
+ * @param {string} s
+ * @param {string} target
+ * @return {number}
+ */
+var rearrangeCharacters = function(s, target) {
+  const sourceFreq = new Array(26).fill(0);
+  const targetFreq = new Array(26).fill(0);
+
+  for (const char of s) {
+    sourceFreq[char.charCodeAt(0) - 97]++;
+  }
+
+  for (const char of target) {
+    targetFreq[char.charCodeAt(0) - 97]++;
+  }
+
+  let result = Infinity;
+  for (let i = 0; i < 26; i++) {
+    if (targetFreq[i] > 0) {
+      result = Math.min(result, Math.floor(sourceFreq[i] / targetFreq[i]));
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2288-apply-discount-to-prices.js b/solutions/2288-apply-discount-to-prices.js
new file mode 100644
index 00000000..4645204e
--- /dev/null
+++ b/solutions/2288-apply-discount-to-prices.js
@@ -0,0 +1,37 @@
+/**
+ * 2288. Apply Discount to Prices
+ * https://leetcode.com/problems/apply-discount-to-prices/
+ * Difficulty: Medium
+ *
+ * A sentence is a string of single-space separated words where each word can contain digits,
+ * lowercase letters, and the dollar sign '$'. A word represents a price if it is a sequence
+ * of digits preceded by a dollar sign.
+ * - For example, "$100", "$23", and "$6" represent prices while "100", "$", and "$1e5" do not.
+ *
+ * You are given a string sentence representing a sentence and an integer discount. For each
+ * word representing a price, apply a discount of discount% on the price and update the word
+ * in the sentence. All updated prices should be represented with exactly two decimal places.
+ *
+ * Return a string representing the modified sentence.
+ *
+ * Note that all prices will contain at most 10 digits.
+ */
+
+/**
+ * @param {string} sentence
+ * @param {number} discount
+ * @return {string}
+ */
+var discountPrices = function(sentence, discount) {
+  const words = sentence.split(' ');
+  const discountFactor = 1 - discount / 100;
+
+  for (let i = 0; i < words.length; i++) {
+    if (words[i].startsWith('$') && /^[0-9]+$/.test(words[i].slice(1))) {
+      const price = parseInt(words[i].slice(1)) * discountFactor;
+      words[i] = `$${price.toFixed(2)}`;
+    }
+  }
+
+  return words.join(' ');
+};
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/2293-min-max-game.js b/solutions/2293-min-max-game.js
new file mode 100644
index 00000000..b6952f9c
--- /dev/null
+++ b/solutions/2293-min-max-game.js
@@ -0,0 +1,43 @@
+/**
+ * 2293. Min Max Game
+ * https://leetcode.com/problems/min-max-game/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed integer array nums whose length is a power of 2.
+ *
+ * Apply the following algorithm on nums:
+ * 1. Let n be the length of nums. If n == 1, end the process. Otherwise, create a new 0-indexed
+ *    integer array newNums of length n / 2.
+ * 2. For every even index i where 0 <= i < n / 2, assign the value of newNums[i] as
+ *    min(nums[2 * i], nums[2 * i + 1]).
+ * 3. For every odd index i where 0 <= i < n / 2, assign the value of newNums[i] as
+ *    max(nums[2 * i], nums[2 * i + 1]).
+ * 4. Replace the array nums with newNums.
+ * 5. Repeat the entire process starting from step 1.
+ *
+ * Return the last number that remains in nums after applying the algorithm.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var minMaxGame = function(nums) {
+  let array = nums.slice();
+
+  while (array.length > 1) {
+    const newArray = new Array(array.length / 2);
+
+    for (let i = 0; i < newArray.length; i++) {
+      if (i % 2 === 0) {
+        newArray[i] = Math.min(array[2 * i], array[2 * i + 1]);
+      } else {
+        newArray[i] = Math.max(array[2 * i], array[2 * i + 1]);
+      }
+    }
+
+    array = newArray;
+  }
+
+  return array[0];
+};
diff --git a/solutions/2294-partition-array-such-that-maximum-difference-is-k.js b/solutions/2294-partition-array-such-that-maximum-difference-is-k.js
new file mode 100644
index 00000000..06cad3ae
--- /dev/null
+++ b/solutions/2294-partition-array-such-that-maximum-difference-is-k.js
@@ -0,0 +1,34 @@
+/**
+ * 2294. Partition Array Such That Maximum Difference Is K
+ * https://leetcode.com/problems/partition-array-such-that-maximum-difference-is-k/
+ * Difficulty: Medium
+ *
+ * You are given an integer array nums and an integer k. You may partition nums into one or more
+ * subsequences such that each element in nums appears in exactly one of the subsequences.
+ *
+ * Return the minimum number of subsequences needed such that the difference between the maximum
+ * and minimum values in each subsequence is at most k.
+ *
+ * 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} k
+ * @return {number}
+ */
+var partitionArray = function(nums, k) {
+  nums.sort((a, b) => a - b);
+  let result = 1;
+  let minValue = nums[0];
+
+  for (let i = 1; i < nums.length; i++) {
+    if (nums[i] - minValue > k) {
+      result++;
+      minValue = nums[i];
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2295-replace-elements-in-an-array.js b/solutions/2295-replace-elements-in-an-array.js
new file mode 100644
index 00000000..de3bbad0
--- /dev/null
+++ b/solutions/2295-replace-elements-in-an-array.js
@@ -0,0 +1,36 @@
+/**
+ * 2295. Replace Elements in an Array
+ * https://leetcode.com/problems/replace-elements-in-an-array/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed array nums that consists of n distinct positive integers.
+ * Apply m operations to this array, where in the ith operation you replace the number
+ * operations[i][0] with operations[i][1].
+ *
+ * It is guaranteed that in the ith operation:
+ * - operations[i][0] exists in nums.
+ * - operations[i][1] does not exist in nums.
+ *
+ * Return the array obtained after applying all the operations.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number[][]} operations
+ * @return {number[]}
+ */
+var arrayChange = function(nums, operations) {
+  const map = new Map();
+  for (let i = 0; i < nums.length; i++) {
+    map.set(nums[i], i);
+  }
+
+  for (const [oldVal, newVal] of operations) {
+    const index = map.get(oldVal);
+    nums[index] = newVal;
+    map.set(newVal, index);
+    map.delete(oldVal);
+  }
+
+  return nums;
+};
diff --git a/solutions/2296-design-a-text-editor.js b/solutions/2296-design-a-text-editor.js
new file mode 100644
index 00000000..6020598d
--- /dev/null
+++ b/solutions/2296-design-a-text-editor.js
@@ -0,0 +1,78 @@
+/**
+ * 2296. Design a Text Editor
+ * https://leetcode.com/problems/design-a-text-editor/
+ * Difficulty: Hard
+ *
+ * Design a text editor with a cursor that can do the following:
+ * - Add text to where the cursor is.
+ * - Delete text from where the cursor is (simulating the backspace key).
+ * - Move the cursor either left or right.
+ *
+ * When deleting text, only characters to the left of the cursor will be deleted. The cursor
+ * will also remain within the actual text and cannot be moved beyond it. More formally,
+ * we have that 0 <= cursor.position <= currentText.length always holds.
+ *
+ * Implement the TextEditor class:
+ * - TextEditor() Initializes the object with empty text.
+ * - void addText(string text) Appends text to where the cursor is. The cursor ends to the
+ *   right of text.
+ * - int deleteText(int k) Deletes k characters to the left of the cursor. Returns the number
+ *   of characters actually deleted.
+ * - string cursorLeft(int k) Moves the cursor to the left k times. Returns the last
+ *   min(10, len) characters to the left of the cursor, where len is the number of characters
+ *   to the left of the cursor.
+ * - string cursorRight(int k) Moves the cursor to the right k times. Returns the last
+ *   min(10, len) characters to the left of the cursor, where len is the number of characters
+ *   to the left of the cursor.
+ */
+
+var TextEditor = function() {
+  this.left = [];
+  this.right = [];
+};
+
+/**
+ * @param {string} text
+ * @return {void}
+ */
+TextEditor.prototype.addText = function(text) {
+  for (const char of text) {
+    this.left.push(char);
+  }
+};
+
+/**
+ * @param {number} k
+ * @return {number}
+ */
+TextEditor.prototype.deleteText = function(k) {
+  const deleteCount = Math.min(k, this.left.length);
+  for (let i = 0; i < deleteCount; i++) {
+    this.left.pop();
+  }
+  return deleteCount;
+};
+
+/**
+ * @param {number} k
+ * @return {string}
+ */
+TextEditor.prototype.cursorLeft = function(k) {
+  for (let i = 0; i < k && this.left.length; i++) {
+    this.right.push(this.left.pop());
+  }
+  const start = Math.max(0, this.left.length - 10);
+  return this.left.slice(start).join('');
+};
+
+/**
+ * @param {number} k
+ * @return {string}
+ */
+TextEditor.prototype.cursorRight = function(k) {
+  for (let i = 0; i < k && this.right.length; i++) {
+    this.left.push(this.right.pop());
+  }
+  const start = Math.max(0, this.left.length - 10);
+  return this.left.slice(start).join('');
+};
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/2299-strong-password-checker-ii.js b/solutions/2299-strong-password-checker-ii.js
new file mode 100644
index 00000000..f96fac07
--- /dev/null
+++ b/solutions/2299-strong-password-checker-ii.js
@@ -0,0 +1,43 @@
+/**
+ * 2299. Strong Password Checker II
+ * https://leetcode.com/problems/strong-password-checker-ii/
+ * Difficulty: Easy
+ *
+ * A password is said to be strong if it satisfies all the following criteria:
+ * - It has at least 8 characters.
+ * - It contains at least one lowercase letter.
+ * - It contains at least one uppercase letter.
+ * - It contains at least one digit.
+ * - It contains at least one special character. The special characters are the characters
+ *   in the following string: "!@#$%^&*()-+".
+ * - It does not contain 2 of the same character in adjacent positions (i.e., "aab" violates
+ *   this condition, but "aba" does not).
+ *
+ * Given a string password, return true if it is a strong password. Otherwise, return false.
+ */
+
+/**
+ * @param {string} password
+ * @return {boolean}
+ */
+var strongPasswordCheckerII = function(password) {
+  if (password.length < 8) return false;
+
+  let hasLower = false;
+  let hasUpper = false;
+  let hasDigit = false;
+  let hasSpecial = false;
+  const set = new Set(['!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '+']);
+
+  for (let i = 0; i < password.length; i++) {
+    if (i > 0 && password[i] === password[i - 1]) return false;
+
+    const char = password[i];
+    if (/[a-z]/.test(char)) hasLower = true;
+    else if (/[A-Z]/.test(char)) hasUpper = true;
+    else if (/\d/.test(char)) hasDigit = true;
+    else if (set.has(char)) hasSpecial = true;
+  }
+
+  return hasLower && hasUpper && hasDigit && hasSpecial;
+};
diff --git a/solutions/2301-match-substring-after-replacement.js b/solutions/2301-match-substring-after-replacement.js
new file mode 100644
index 00000000..fc7e5a91
--- /dev/null
+++ b/solutions/2301-match-substring-after-replacement.js
@@ -0,0 +1,50 @@
+/**
+ * 2301. Match Substring After Replacement
+ * https://leetcode.com/problems/match-substring-after-replacement/
+ * Difficulty: Hard
+ *
+ * You are given two strings s and sub. You are also given a 2D character array mappings where
+ * mappings[i] = [oldi, newi] indicates that you may perform the following operation any number
+ * of times:
+ * - Replace a character oldi of sub with newi.
+ *
+ * Each character in sub cannot be replaced more than once.
+ *
+ * Return true if it is possible to make sub a substring of s by replacing zero or more characters
+ * according to mappings. Otherwise, return false.
+ *
+ * A substring is a contiguous non-empty sequence of characters within a string.
+ */
+
+/**
+ * @param {string} s
+ * @param {string} sub
+ * @param {character[][]} mappings
+ * @return {boolean}
+ */
+var matchReplacement = function(s, sub, mappings) {
+  const map = new Map();
+
+  for (const [oldChar, newChar] of mappings) {
+    if (!map.has(oldChar)) {
+      map.set(oldChar, new Set());
+    }
+    map.get(oldChar).add(newChar);
+  }
+
+  const subLen = sub.length;
+  for (let i = 0; i <= s.length - subLen; i++) {
+    let isValid = true;
+    for (let j = 0; j < subLen; j++) {
+      const sChar = s[i + j];
+      const subChar = sub[j];
+      if (sChar !== subChar && (!map.has(subChar) || !map.get(subChar).has(sChar))) {
+        isValid = false;
+        break;
+      }
+    }
+    if (isValid) return true;
+  }
+
+  return false;
+};
diff --git a/solutions/2302-count-subarrays-with-score-less-than-k.js b/solutions/2302-count-subarrays-with-score-less-than-k.js
new file mode 100644
index 00000000..29aa7eda
--- /dev/null
+++ b/solutions/2302-count-subarrays-with-score-less-than-k.js
@@ -0,0 +1,35 @@
+/**
+ * 2302. Count Subarrays With Score Less Than K
+ * https://leetcode.com/problems/count-subarrays-with-score-less-than-k/
+ * Difficulty: Hard
+ *
+ * The score of an array is defined as the product of its sum and its length.
+ * - For example, the score of [1, 2, 3, 4, 5] is (1 + 2 + 3 + 4 + 5) * 5 = 75.
+ *
+ * Given a positive integer array nums and an integer k, return the number of non-empty subarrays
+ * of nums whose score is strictly less than k.
+ *
+ * A subarray is a contiguous sequence of elements within an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var countSubarrays = function(nums, k) {
+  let result = 0;
+  let currentSum = 0;
+  let left = 0;
+
+  for (let right = 0; right < nums.length; right++) {
+    currentSum += nums[right];
+    while (currentSum * (right - left + 1) >= k) {
+      currentSum -= nums[left];
+      left++;
+    }
+    result += right - left + 1;
+  }
+
+  return result;
+};
diff --git a/solutions/2303-calculate-amount-paid-in-taxes.js b/solutions/2303-calculate-amount-paid-in-taxes.js
new file mode 100644
index 00000000..6944f54b
--- /dev/null
+++ b/solutions/2303-calculate-amount-paid-in-taxes.js
@@ -0,0 +1,41 @@
+/**
+ * 2303. Calculate Amount Paid in Taxes
+ * https://leetcode.com/problems/calculate-amount-paid-in-taxes/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed 2D integer array brackets where brackets[i] = [upperi, percenti]
+ * means that the ith tax bracket has an upper bound of upperi and is taxed at a rate of percenti.
+ * The brackets are sorted by upper bound (i.e. upperi-1 < upperi for 0 < i < brackets.length).
+ *
+ * Tax is calculated as follows:
+ * - The first upper0 dollars earned are taxed at a rate of percent0.
+ * - The next upper1 - upper0 dollars earned are taxed at a rate of percent1.
+ * - The next upper2 - upper1 dollars earned are taxed at a rate of percent2.
+ * - And so on.
+ *
+ * You are given an integer income representing the amount of money you earned. Return the
+ * amount of money that you have to pay in taxes. Answers within 10-5 of the actual answer
+ * will be accepted.
+ */
+
+/**
+ * @param {number[][]} brackets
+ * @param {number} income
+ * @return {number}
+ */
+var calculateTax = function(brackets, income) {
+  let result = 0;
+  let previousUpper = 0;
+
+  for (const [upper, percent] of brackets) {
+    if (income > previousUpper) {
+      const taxable = Math.min(income, upper) - previousUpper;
+      result += taxable * (percent / 100);
+      previousUpper = upper;
+    } else {
+      break;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2304-minimum-path-cost-in-a-grid.js b/solutions/2304-minimum-path-cost-in-a-grid.js
new file mode 100644
index 00000000..eb1f10c4
--- /dev/null
+++ b/solutions/2304-minimum-path-cost-in-a-grid.js
@@ -0,0 +1,48 @@
+/**
+ * 2304. Minimum Path Cost in a Grid
+ * https://leetcode.com/problems/minimum-path-cost-in-a-grid/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed m x n integer matrix grid consisting of distinct integers from
+ * 0 to m * n - 1. You can move in this matrix from a cell to any other cell in the next row.
+ * That is, if you are in cell (x, y) such that x < m - 1, you can move to any of the cells
+ * (x + 1, 0), (x + 1, 1), ..., (x + 1, n - 1). Note that it is not possible to move from
+ * cells in the last row.
+ *
+ * Each possible move has a cost given by a 0-indexed 2D array moveCost of size (m * n) x n,
+ * where moveCost[i][j] is the cost of moving from a cell with value i to a cell in column j
+ * of the next row. The cost of moving from cells in the last row of grid can be ignored.
+ *
+ * The cost of a path in grid is the sum of all values of cells visited plus the sum of costs
+ * of all the moves made. Return the minimum cost of a path that starts from any cell in the
+ * first row and ends at any cell in the last row.
+ */
+
+/**
+ * @param {number[][]} grid
+ * @param {number[][]} moveCost
+ * @return {number}
+ */
+var minPathCost = function(grid, moveCost) {
+  const m = grid.length;
+  const n = grid[0].length;
+  const dp = Array.from({ length: m }, () => new Array(n).fill(Infinity));
+
+  for (let j = 0; j < n; j++) {
+    dp[0][j] = grid[0][j];
+  }
+
+  for (let i = 0; i < m - 1; i++) {
+    for (let j = 0; j < n; j++) {
+      const value = grid[i][j];
+      for (let k = 0; k < n; k++) {
+        dp[i + 1][k] = Math.min(
+          dp[i + 1][k],
+          dp[i][j] + grid[i + 1][k] + moveCost[value][k]
+        );
+      }
+    }
+  }
+
+  return Math.min(...dp[m - 1]);
+};
diff --git a/solutions/2305-fair-distribution-of-cookies.js b/solutions/2305-fair-distribution-of-cookies.js
new file mode 100644
index 00000000..dffcb4a4
--- /dev/null
+++ b/solutions/2305-fair-distribution-of-cookies.js
@@ -0,0 +1,46 @@
+/**
+ * 2305. Fair Distribution of Cookies
+ * https://leetcode.com/problems/fair-distribution-of-cookies/
+ * Difficulty: Medium
+ *
+ * You are given an integer array cookies, where cookies[i] denotes the number of cookies in the
+ * ith bag. You are also given an integer k that denotes the number of children to distribute
+ * all the bags of cookies to. All the cookies in the same bag must go to the same child and
+ * cannot be split up.
+ *
+ * The unfairness of a distribution is defined as the maximum total cookies obtained by a single
+ * child in the distribution.
+ *
+ * Return the minimum unfairness of all distributions.
+ */
+
+/**
+ * @param {number[]} cookies
+ * @param {number} k
+ * @return {number}
+ */
+var distributeCookies = function(cookies, k) {
+  const distribution = new Array(k).fill(0);
+  let result = Infinity;
+
+  distribute(0);
+
+  return result;
+
+  function distribute(index) {
+    if (index === cookies.length) {
+      result = Math.min(result, Math.max(...distribution));
+      return;
+    }
+
+    for (let i = 0; i < k; i++) {
+      distribution[i] += cookies[index];
+      if (distribution[i] < result) {
+        distribute(index + 1);
+      }
+      distribution[i] -= cookies[index];
+
+      if (distribution[i] === 0) break;
+    }
+  }
+};
diff --git a/solutions/2306-naming-a-company.js b/solutions/2306-naming-a-company.js
new file mode 100644
index 00000000..bef81dfe
--- /dev/null
+++ b/solutions/2306-naming-a-company.js
@@ -0,0 +1,37 @@
+/**
+ * 2306. Naming a Company
+ * https://leetcode.com/problems/naming-a-company/
+ * Difficulty: Hard
+ *
+ * You are given an array of strings ideas that represents a list of names to be used in the
+ * process of naming a company. The process of naming a company is as follows:
+ * 1. Choose 2 distinct names from ideas, call them ideaA and ideaB.
+ * 2. Swap the first letters of ideaA and ideaB with each other.
+ * 3. If both of the new names are not found in the original ideas, then the name ideaA ideaB
+ *    (the concatenation of ideaA and ideaB, separated by a space) is a valid company name.
+ * 4. Otherwise, it is not a valid name.
+ *
+ * Return the number of distinct valid names for the company.
+ */
+
+/**
+ * @param {string[]} ideas
+ * @return {number}
+ */
+var distinctNames = function(ideas) {
+  const groups = Array.from({ length: 26 }, () => new Set());
+  let result = 0;
+
+  for (const idea of ideas) {
+    groups[idea.charCodeAt(0) - 97].add(idea.slice(1));
+  }
+
+  for (let i = 0; i < 25; i++) {
+    for (let j = i + 1; j < 26; j++) {
+      const mutualCount = [...groups[i]].filter(suffix => groups[j].has(suffix)).length;
+      result += 2 * (groups[i].size - mutualCount) * (groups[j].size - mutualCount);
+    }
+  }
+
+  return result;
+};
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/2309-greatest-english-letter-in-upper-and-lower-case.js b/solutions/2309-greatest-english-letter-in-upper-and-lower-case.js
new file mode 100644
index 00000000..b86b8f8b
--- /dev/null
+++ b/solutions/2309-greatest-english-letter-in-upper-and-lower-case.js
@@ -0,0 +1,38 @@
+/**
+ * 2309. Greatest English Letter in Upper and Lower Case
+ * https://leetcode.com/problems/greatest-english-letter-in-upper-and-lower-case/
+ * Difficulty: Easy
+ *
+ * Given a string of English letters s, return the greatest English letter which occurs as both
+ * a lowercase and uppercase letter in s. The returned letter should be in uppercase. If no such
+ * letter exists, return an empty string.
+ *
+ * An English letter b is greater than another letter a if b appears after a in the English
+ * alphabet.
+ */
+
+/**
+ * @param {string} s
+ * @return {string}
+ */
+var greatestLetter = function(s) {
+  const lowerSet = new Set();
+  const upperSet = new Set();
+
+  for (const char of s) {
+    if (char >= 'a' && char <= 'z') {
+      lowerSet.add(char);
+    } else {
+      upperSet.add(char.toLowerCase());
+    }
+  }
+
+  let maxLetter = '';
+  for (const char of lowerSet) {
+    if (upperSet.has(char) && char > maxLetter) {
+      maxLetter = char;
+    }
+  }
+
+  return maxLetter.toUpperCase();
+};
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/2312-selling-pieces-of-wood.js b/solutions/2312-selling-pieces-of-wood.js
new file mode 100644
index 00000000..6edab3a0
--- /dev/null
+++ b/solutions/2312-selling-pieces-of-wood.js
@@ -0,0 +1,46 @@
+/**
+ * 2312. Selling Pieces of Wood
+ * https://leetcode.com/problems/selling-pieces-of-wood/
+ * Difficulty: Hard
+ *
+ * You are given two integers m and n that represent the height and width of a rectangular piece
+ * of wood. You are also given a 2D integer array prices, where prices[i] = [hi, wi, pricei]
+ * indicates you can sell a rectangular piece of wood of height hi and width wi for pricei dollars.
+ *
+ * To cut a piece of wood, you must make a vertical or horizontal cut across the entire height
+ * or width of the piece to split it into two smaller pieces. After cutting a piece of wood into
+ * some number of smaller pieces, you can sell pieces according to prices. You may sell multiple
+ * pieces of the same shape, and you do not have to sell all the shapes. The grain of the wood
+ * makes a difference, so you cannot rotate a piece to swap its height and width.
+ *
+ * Return the maximum money you can earn after cutting an m x n piece of wood.
+ *
+ * Note that you can cut the piece of wood as many times as you want.
+ */
+
+/**
+ * @param {number} m
+ * @param {number} n
+ * @param {number[][]} prices
+ * @return {number}
+ */
+var sellingWood = function(m, n, prices) {
+  const dp = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
+
+  for (const [h, w, price] of prices) {
+    dp[h][w] = price;
+  }
+
+  for (let i = 1; i <= m; i++) {
+    for (let j = 1; j <= n; j++) {
+      for (let k = 1; k < i; k++) {
+        dp[i][j] = Math.max(dp[i][j], dp[k][j] + dp[i - k][j]);
+      }
+      for (let k = 1; k < j; k++) {
+        dp[i][j] = Math.max(dp[i][j], dp[i][k] + dp[i][j - k]);
+      }
+    }
+  }
+
+  return dp[m][n];
+};
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/2315-count-asterisks.js b/solutions/2315-count-asterisks.js
new file mode 100644
index 00000000..650055eb
--- /dev/null
+++ b/solutions/2315-count-asterisks.js
@@ -0,0 +1,32 @@
+/**
+ * 2315. Count Asterisks
+ * https://leetcode.com/problems/count-asterisks/
+ * Difficulty: Easy
+ *
+ * You are given a string s, where every two consecutive vertical bars '|' are grouped into
+ * a pair. In other words, the 1st and 2nd '|' make a pair, the 3rd and 4th '|' make a pair,
+ * and so forth.
+ *
+ * Return the number of '*' in s, excluding the '*' between each pair of '|'.
+ *
+ * Note that each '|' will belong to exactly one pair.
+ */
+
+/**
+ * @param {string} s
+ * @return {number}
+ */
+var countAsterisks = function(s) {
+  let isInsidePair = false;
+  let result = 0;
+
+  for (const char of s) {
+    if (char === '|') {
+      isInsidePair = !isInsidePair;
+    } else if (char === '*' && !isInsidePair) {
+      result++;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2316-count-unreachable-pairs-of-nodes-in-an-undirected-graph.js b/solutions/2316-count-unreachable-pairs-of-nodes-in-an-undirected-graph.js
new file mode 100644
index 00000000..4de0c07b
--- /dev/null
+++ b/solutions/2316-count-unreachable-pairs-of-nodes-in-an-undirected-graph.js
@@ -0,0 +1,48 @@
+/**
+ * 2316. Count Unreachable Pairs of Nodes in an Undirected Graph
+ * https://leetcode.com/problems/count-unreachable-pairs-of-nodes-in-an-undirected-graph/
+ * Difficulty: Medium
+ *
+ * You are given an integer n. There is an undirected graph with n nodes, numbered from 0
+ * to n - 1. You are given a 2D integer array edges where edges[i] = [ai, bi] denotes that
+ * there exists an undirected edge connecting nodes ai and bi.
+ *
+ * Return the number of pairs of different nodes that are unreachable from each other.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[][]} edges
+ * @return {number}
+ */
+var countPairs = function(n, edges) {
+  const graph = Array.from({ length: n }, () => []);
+  for (const [a, b] of edges) {
+    graph[a].push(b);
+    graph[b].push(a);
+  }
+
+  const visited = new Array(n).fill(false);
+  let result = 0;
+
+  let totalNodes = 0;
+  for (let node = 0; node < n; node++) {
+    if (!visited[node]) {
+      const componentSize = exploreComponent(node);
+      result += totalNodes * componentSize;
+      totalNodes += componentSize;
+    }
+  }
+
+  return result;
+
+  function exploreComponent(node) {
+    if (visited[node]) return 0;
+    visited[node] = true;
+    let size = 1;
+    for (const neighbor of graph[node]) {
+      size += exploreComponent(neighbor);
+    }
+    return size;
+  }
+};
diff --git a/solutions/2317-maximum-xor-after-operations.js b/solutions/2317-maximum-xor-after-operations.js
new file mode 100644
index 00000000..7049675b
--- /dev/null
+++ b/solutions/2317-maximum-xor-after-operations.js
@@ -0,0 +1,27 @@
+/**
+ * 2317. Maximum XOR After Operations
+ * https://leetcode.com/problems/maximum-xor-after-operations/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums. In one operation, select any non-negative
+ * integer x and an index i, then update nums[i] to be equal to nums[i] AND (nums[i] XOR x).
+ *
+ * Note that AND is the bitwise AND operation and XOR is the bitwise XOR operation.
+ *
+ * Return the maximum possible bitwise XOR of all elements of nums after applying the operation
+ * any number of times.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var maximumXOR = function(nums) {
+  let maxXor = 0;
+
+  for (const num of nums) {
+    maxXor |= num;
+  }
+
+  return maxXor;
+};
diff --git a/solutions/2318-number-of-distinct-roll-sequences.js b/solutions/2318-number-of-distinct-roll-sequences.js
new file mode 100644
index 00000000..5f67f5c0
--- /dev/null
+++ b/solutions/2318-number-of-distinct-roll-sequences.js
@@ -0,0 +1,55 @@
+/**
+ * 2318. Number of Distinct Roll Sequences
+ * https://leetcode.com/problems/number-of-distinct-roll-sequences/
+ * Difficulty: Hard
+ *
+ * You are given an integer n. You roll a fair 6-sided dice n times. Determine the total number
+ * of distinct sequences of rolls possible such that the following conditions are satisfied:
+ * 1. The greatest common divisor of any adjacent values in the sequence is equal to 1.
+ * 2. There is at least a gap of 2 rolls between equal valued rolls. More formally, if the
+ *    value of the ith roll is equal to the value of the jth roll, then abs(i - j) > 2.
+ *
+ * Return the total number of distinct sequences possible. Since the answer may be very large,
+ * return it modulo 109 + 7.
+ *
+ * Two sequences are considered distinct if at least one element is different.
+ */
+
+/**
+ * @param {number} n
+ * @return {number}
+ */
+var distinctSequences = function(n) {
+  const MOD = 1e9 + 7;
+  const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
+
+  const dp = new Array(n + 1)
+    .fill()
+    .map(() => new Array(7).fill().map(() => new Array(7).fill(0)));
+
+  for (let i = 1; i <= 6; i++) {
+    dp[1][i][0] = 1;
+  }
+
+  for (let len = 2; len <= n; len++) {
+    for (let curr = 1; curr <= 6; curr++) {
+      for (let prev = 0; prev <= 6; prev++) {
+        for (let prevPrev = 0; prevPrev <= 6; prevPrev++) {
+          if (dp[len - 1][prev][prevPrev] === 0) continue;
+          if (curr === prev || curr === prevPrev) continue;
+          if (prev !== 0 && gcd(curr, prev) !== 1) continue;
+          dp[len][curr][prev] = (dp[len][curr][prev] + dp[len - 1][prev][prevPrev]) % MOD;
+        }
+      }
+    }
+  }
+
+  let result = 0;
+  for (let curr = 1; curr <= 6; curr++) {
+    for (let prev = 0; prev <= 6; prev++) {
+      result = (result + dp[n][curr][prev]) % MOD;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2319-check-if-matrix-is-x-matrix.js b/solutions/2319-check-if-matrix-is-x-matrix.js
new file mode 100644
index 00000000..ee45ca42
--- /dev/null
+++ b/solutions/2319-check-if-matrix-is-x-matrix.js
@@ -0,0 +1,32 @@
+/**
+ * 2319. Check if Matrix Is X-Matrix
+ * https://leetcode.com/problems/check-if-matrix-is-x-matrix/
+ * Difficulty: Easy
+ *
+ * A square matrix is said to be an X-Matrix if both of the following conditions hold:
+ * 1. All the elements in the diagonals of the matrix are non-zero.
+ * 2. All other elements are 0.
+ *
+ * Given a 2D integer array grid of size n x n representing a square matrix, return true if grid
+ * is an X-Matrix. Otherwise, return false.
+ */
+
+/**
+ * @param {number[][]} grid
+ * @return {boolean}
+ */
+var checkXMatrix = function(grid) {
+  const size = grid.length;
+
+  for (let row = 0; row < size; row++) {
+    for (let col = 0; col < size; col++) {
+      const isDiagonal = row === col || row + col === size - 1;
+      const isNonZero = grid[row][col] !== 0;
+
+      if (isDiagonal && !isNonZero) return false;
+      if (!isDiagonal && isNonZero) return false;
+    }
+  }
+
+  return true;
+};
diff --git a/solutions/2320-count-number-of-ways-to-place-houses.js b/solutions/2320-count-number-of-ways-to-place-houses.js
new file mode 100644
index 00000000..39c28f72
--- /dev/null
+++ b/solutions/2320-count-number-of-ways-to-place-houses.js
@@ -0,0 +1,34 @@
+/**
+ * 2320. Count Number of Ways to Place Houses
+ * https://leetcode.com/problems/count-number-of-ways-to-place-houses/
+ * Difficulty: Medium
+ *
+ * There is a street with n * 2 plots, where there are n plots on each side of the street. The plots
+ * on each side are numbered from 1 to n. On each plot, a house can be placed.
+ *
+ * Return the number of ways houses can be placed such that no two houses are adjacent to each other
+ * on the same side of the street. Since the answer may be very large, return it modulo 109 + 7.
+ *
+ * Note that if a house is placed on the ith plot on one side of the street, a house can also be
+ * placed on the ith plot on the other side of the street.
+ */
+
+/**
+ * @param {number} n
+ * @return {number}
+ */
+var countHousePlacements = function(n) {
+  const MOD = 1e9 + 7;
+  let empty = 1n;
+  let house = 1n;
+
+  for (let i = 2; i <= n; i++) {
+    const nextEmpty = (empty + house) % BigInt(MOD);
+    const nextHouse = empty;
+    empty = nextEmpty;
+    house = nextHouse;
+  }
+
+  const sideWays = (empty + house) % BigInt(MOD);
+  return Number((sideWays * sideWays) % BigInt(MOD));
+};
diff --git a/solutions/2321-maximum-score-of-spliced-array.js b/solutions/2321-maximum-score-of-spliced-array.js
new file mode 100644
index 00000000..3ecf5068
--- /dev/null
+++ b/solutions/2321-maximum-score-of-spliced-array.js
@@ -0,0 +1,52 @@
+/**
+ * 2321. Maximum Score Of Spliced Array
+ * https://leetcode.com/problems/maximum-score-of-spliced-array/
+ * Difficulty: Hard
+ *
+ * You are given two 0-indexed integer arrays nums1 and nums2, both of length n.
+ *
+ * You can choose two integers left and right where 0 <= left <= right < n and swap the subarray
+ * nums1[left...right] with the subarray nums2[left...right].
+ * - For example, if nums1 = [1,2,3,4,5] and nums2 = [11,12,13,14,15] and you choose left = 1 and
+ *   right = 2, nums1 becomes [1,12,13,4,5] and nums2 becomes [11,2,3,14,15].
+ *
+ * You may choose to apply the mentioned operation once or not do anything.
+ *
+ * The score of the arrays is the maximum of sum(nums1) and sum(nums2), where sum(arr) is the sum
+ * of all the elements in the array arr.
+ *
+ * Return the maximum possible score.
+ *
+ * A subarray is a contiguous sequence of elements within an array. arr[left...right] denotes the
+ * subarray that contains the elements of nums between indices left and right (inclusive).
+ */
+
+/**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number}
+ */
+var maximumsSplicedArray = function(nums1, nums2) {
+  const length = nums1.length;
+  let sum1 = 0;
+  let sum2 = 0;
+
+  for (let i = 0; i < length; i++) {
+    sum1 += nums1[i];
+    sum2 += nums2[i];
+  }
+
+  let maxGain1 = 0;
+  let maxGain2 = 0;
+  let currGain1 = 0;
+  let currGain2 = 0;
+
+  for (let i = 0; i < length; i++) {
+    currGain1 = Math.max(0, currGain1 + nums2[i] - nums1[i]);
+    currGain2 = Math.max(0, currGain2 + nums1[i] - nums2[i]);
+    maxGain1 = Math.max(maxGain1, currGain1);
+    maxGain2 = Math.max(maxGain2, currGain2);
+  }
+
+  return Math.max(sum1 + maxGain1, sum2 + maxGain2);
+};
diff --git a/solutions/2322-minimum-score-after-removals-on-a-tree.js b/solutions/2322-minimum-score-after-removals-on-a-tree.js
new file mode 100644
index 00000000..4b0b6cd0
--- /dev/null
+++ b/solutions/2322-minimum-score-after-removals-on-a-tree.js
@@ -0,0 +1,112 @@
+/**
+ * 2322. Minimum Score After Removals on a Tree
+ * https://leetcode.com/problems/minimum-score-after-removals-on-a-tree/
+ * Difficulty: Hard
+ *
+ * There is an undirected connected tree with n nodes labeled from 0 to n - 1 and n - 1 edges.
+ *
+ * You are given a 0-indexed integer array nums of length n where nums[i] represents the value
+ * of the ith node. You are also 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.
+ *
+ * Remove two distinct edges of the tree to form three connected components. For a pair of
+ * removed edges, the following steps are defined:
+ * 1. Get the XOR of all the values of the nodes for each of the three components respectively.
+ * 2. The difference between the largest XOR value and the smallest XOR value is the score of
+ *    the pair.
+ * 3. For example, say the three components have the node values: [4,5,7], [1,9], and [3,3,3].
+ *    The three XOR values are 4 ^ 5 ^ 7 = 6, 1 ^ 9 = 8, and 3 ^ 3 ^ 3 = 3. The largest XOR
+ *    value is 8 and the smallest XOR value is 3. The score is then 8 - 3 = 5.
+ *
+ * Return the minimum score of any possible pair of edge removals on the given tree.
+ */
+
+/**
+* @param {number[]} nums
+* @param {number[][]} edges
+* @return {number}
+*/
+var minimumScore = function(nums, edges) {
+  const n = nums.length;
+  const graph = Array.from({ length: n }, () => []);
+
+  for (const [a, b] of edges) {
+    graph[a].push(b);
+    graph[b].push(a);
+  }
+
+  const totalXor = nums.reduce((acc, num) => acc ^ num, 0);
+
+  const subtreeXor = new Array(n).fill(0);
+
+  const tin = new Array(n);
+  const tout = new Array(n);
+  let timer = 0;
+
+  function dfs(node, parent) {
+    tin[node] = timer++;
+    subtreeXor[node] = nums[node];
+
+    for (const neighbor of graph[node]) {
+      if (neighbor !== parent) {
+        dfs(neighbor, node);
+        subtreeXor[node] ^= subtreeXor[neighbor];
+      }
+    }
+
+    tout[node] = timer++;
+  }
+
+  dfs(0, -1);
+
+  function isAncestor(a, b) {
+    return tin[a] <= tin[b] && tout[a] >= tout[b];
+  }
+
+  let result = Infinity;
+  for (let i = 0; i < n - 1; i++) {
+    for (let j = i + 1; j < n - 1; j++) {
+      const edge1 = edges[i];
+      const edge2 = edges[j];
+
+      let node1;
+      if (isAncestor(edge1[0], edge1[1])) {
+        node1 = edge1[1];
+      } else {
+        node1 = edge1[0];
+      }
+      const subtree1 = subtreeXor[node1];
+
+      let node2;
+      if (isAncestor(edge2[0], edge2[1])) {
+        node2 = edge2[1];
+      } else {
+        node2 = edge2[0];
+      }
+      const subtree2 = subtreeXor[node2];
+
+      let component1;
+      let component2;
+      let component3;
+      if (isAncestor(node1, node2)) {
+        component1 = subtree2;
+        component2 = subtree1 ^ component1;
+        component3 = totalXor ^ subtree1;
+      } else if (isAncestor(node2, node1)) {
+        component1 = subtree1;
+        component2 = subtree2 ^ component1;
+        component3 = totalXor ^ subtree2;
+      } else {
+        component1 = subtree1;
+        component2 = subtree2;
+        component3 = totalXor ^ component1 ^ component2;
+      }
+
+      const maxXor = Math.max(component1, component2, component3);
+      const minXor = Math.min(component1, component2, component3);
+      result = Math.min(result, maxXor - minXor);
+    }
+  }
+
+  return result;
+};
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/2325-decode-the-message.js b/solutions/2325-decode-the-message.js
new file mode 100644
index 00000000..bde90e23
--- /dev/null
+++ b/solutions/2325-decode-the-message.js
@@ -0,0 +1,41 @@
+/**
+ * 2325. Decode the Message
+ * https://leetcode.com/problems/decode-the-message/
+ * Difficulty: Easy
+ *
+ * You are given the strings key and message, which represent a cipher key and a secret message,
+ * respectively. The steps to decode message are as follows:
+ * 1. Use the first appearance of all 26 lowercase English letters in key as the order of the
+ *    substitution table.
+ * 2. Align the substitution table with the regular English alphabet.
+ * 3. Each letter in message is then substituted using the table.
+ * 4. Spaces ' ' are transformed to themselves.
+ * 5. For example, given key = "happy boy" (actual key would have at least one instance of each
+ *    letter in the alphabet), we have the partial substitution table of ('h' -> 'a', 'a' -> 'b',
+ *    'p' -> 'c', 'y' -> 'd', 'b' -> 'e', 'o' -> 'f').
+ *
+ * Return the decoded message.
+ */
+
+/**
+ * @param {string} key
+ * @param {string} message
+ * @return {string}
+ */
+var decodeMessage = function(key, message) {
+  const substitution = new Map();
+  let alphabetIndex = 0;
+
+  for (const char of key) {
+    if (char !== ' ' && !substitution.has(char)) {
+      substitution.set(char, String.fromCharCode(97 + alphabetIndex++));
+    }
+  }
+
+  let result = '';
+  for (const char of message) {
+    result += char === ' ' ? ' ' : substitution.get(char);
+  }
+
+  return result;
+};
diff --git a/solutions/2326-spiral-matrix-iv.js b/solutions/2326-spiral-matrix-iv.js
new file mode 100644
index 00000000..1fa98050
--- /dev/null
+++ b/solutions/2326-spiral-matrix-iv.js
@@ -0,0 +1,65 @@
+/**
+ * 2326. Spiral Matrix IV
+ * https://leetcode.com/problems/spiral-matrix-iv/
+ * Difficulty: Medium
+ *
+ * You are given two integers m and n, which represent the dimensions of a matrix.
+ *
+ * You are also given the head of a linked list of integers.
+ *
+ * Generate an m x n matrix that contains the integers in the linked list presented in spiral
+ * order (clockwise), starting from the top-left of the matrix. If there are remaining empty
+ * spaces, fill them with -1.
+ *
+ * Return the generated matrix.
+ */
+
+/**
+ * Definition for singly-linked list.
+ * function ListNode(val, next) {
+ *     this.val = (val===undefined ? 0 : val)
+ *     this.next = (next===undefined ? null : next)
+ * }
+ */
+/**
+ * @param {number} m
+ * @param {number} n
+ * @param {ListNode} head
+ * @return {number[][]}
+ */
+var spiralMatrix = function(m, n, head) {
+  const matrix = new Array(m).fill().map(() => new Array(n).fill(-1));
+  let top = 0;
+  let bottom = m - 1;
+  let left = 0;
+  let right = n - 1;
+  let current = head;
+
+  while (top <= bottom && left <= right && current) {
+    for (let col = left; col <= right && current; col++) {
+      matrix[top][col] = current.val;
+      current = current.next;
+    }
+    top++;
+
+    for (let row = top; row <= bottom && current; row++) {
+      matrix[row][right] = current.val;
+      current = current.next;
+    }
+    right--;
+
+    for (let col = right; col >= left && current; col--) {
+      matrix[bottom][col] = current.val;
+      current = current.next;
+    }
+    bottom--;
+
+    for (let row = bottom; row >= top && current; row--) {
+      matrix[row][left] = current.val;
+      current = current.next;
+    }
+    left++;
+  }
+
+  return matrix;
+};
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/2328-number-of-increasing-paths-in-a-grid.js b/solutions/2328-number-of-increasing-paths-in-a-grid.js
new file mode 100644
index 00000000..f239c80c
--- /dev/null
+++ b/solutions/2328-number-of-increasing-paths-in-a-grid.js
@@ -0,0 +1,53 @@
+/**
+ * 2328. Number of Increasing Paths in a Grid
+ * https://leetcode.com/problems/number-of-increasing-paths-in-a-grid/
+ * Difficulty: Hard
+ *
+ * You are given an m x n integer matrix grid, where you can move from a cell to any adjacent
+ * cell in all 4 directions.
+ *
+ * Return the number of strictly increasing paths in the grid such that you can start from any
+ * cell and end at any cell. Since the answer may be very large, return it modulo 109 + 7.
+ *
+ * Two paths are considered different if they do not have exactly the same sequence of visited
+ * cells.
+ */
+
+/**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+var countPaths = function(grid) {
+  const MOD = 1e9 + 7;
+  const rows = grid.length;
+  const cols = grid[0].length;
+  const cache = new Array(rows).fill().map(() => new Array(cols).fill(0));
+  const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]];
+
+  function explore(row, col) {
+    if (cache[row][col]) return cache[row][col];
+
+    let paths = 1;
+    for (const [dr, dc] of directions) {
+      const newRow = row + dr;
+      const newCol = col + dc;
+      if (
+        newRow >= 0 && newRow < rows && newCol >= 0
+        && newCol < cols && grid[newRow][newCol] > grid[row][col]
+      ) {
+        paths = (paths + explore(newRow, newCol)) % MOD;
+      }
+    }
+
+    return cache[row][col] = paths;
+  }
+
+  let total = 0;
+  for (let i = 0; i < rows; i++) {
+    for (let j = 0; j < cols; j++) {
+      total = (total + explore(i, j)) % MOD;
+    }
+  }
+
+  return total;
+};
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/2331-evaluate-boolean-binary-tree.js b/solutions/2331-evaluate-boolean-binary-tree.js
new file mode 100644
index 00000000..d6f4d851
--- /dev/null
+++ b/solutions/2331-evaluate-boolean-binary-tree.js
@@ -0,0 +1,42 @@
+/**
+ * 2331. Evaluate Boolean Binary Tree
+ * https://leetcode.com/problems/evaluate-boolean-binary-tree/
+ * Difficulty: Easy
+ *
+ * You are given the root of a full binary tree with the following properties:
+ * - Leaf nodes have either the value 0 or 1, where 0 represents False and 1 represents True.
+ * - Non-leaf nodes have either the value 2 or 3, where 2 represents the boolean OR and 3 represents
+ *   the boolean AND.
+ *
+ * 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 two children and apply the boolean operation of its value with
+ *   the children's evaluations.
+ *
+ * Return the boolean result of evaluating the root node.
+ *
+ * A full binary tree is a binary tree where each node has either 0 or 2 children.
+ *
+ * A leaf node is a node that has zero 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 {boolean}
+ */
+var evaluateTree = function(root) {
+  if (!root.left && !root.right) return root.val === 1;
+
+  const leftResult = evaluateTree(root.left);
+  const rightResult = evaluateTree(root.right);
+
+  return root.val === 2 ? leftResult || rightResult : leftResult && rightResult;
+};
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/2334-subarray-with-elements-greater-than-varying-threshold.js b/solutions/2334-subarray-with-elements-greater-than-varying-threshold.js
new file mode 100644
index 00000000..789a5ff3
--- /dev/null
+++ b/solutions/2334-subarray-with-elements-greater-than-varying-threshold.js
@@ -0,0 +1,43 @@
+/**
+ * 2334. Subarray With Elements Greater Than Varying Threshold
+ * https://leetcode.com/problems/subarray-with-elements-greater-than-varying-threshold/
+ * Difficulty: Hard
+ *
+ * You are given an integer array nums and an integer threshold.
+ *
+ * Find any subarray of nums of length k such that every element in the subarray is greater
+ * than threshold / k.
+ *
+ * Return the size of any such subarray. If there is no such subarray, return -1.
+ *
+ * A subarray is a contiguous non-empty sequence of elements within an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} threshold
+ * @return {number}
+ */
+var validSubarraySize = function(nums, threshold) {
+  const n = nums.length;
+  const stack = [];
+  const nextSmaller = new Array(n).fill(n);
+  const prevSmaller = new Array(n).fill(-1);
+
+  for (let i = 0; i < n; i++) {
+    while (stack.length && nums[stack[stack.length - 1]] >= nums[i]) {
+      nextSmaller[stack.pop()] = i;
+    }
+    if (stack.length) prevSmaller[i] = stack[stack.length - 1];
+    stack.push(i);
+  }
+
+  for (let i = 0; i < n; i++) {
+    const k = nextSmaller[i] - prevSmaller[i] - 1;
+    if (k > 0 && nums[i] > threshold / k) {
+      return k;
+    }
+  }
+
+  return -1;
+};
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/2337-move-pieces-to-obtain-a-string.js b/solutions/2337-move-pieces-to-obtain-a-string.js
new file mode 100644
index 00000000..64f29a9a
--- /dev/null
+++ b/solutions/2337-move-pieces-to-obtain-a-string.js
@@ -0,0 +1,41 @@
+/**
+ * 2337. Move Pieces to Obtain a String
+ * https://leetcode.com/problems/move-pieces-to-obtain-a-string/
+ * Difficulty: Medium
+ *
+ * You are given two strings start and target, both of length n. Each string consists only of
+ * the characters 'L', 'R', and '_' where:
+ * - The characters 'L' and 'R' represent pieces, where a piece 'L' can move to the left only if
+ *   there is a blank space directly to its left, and a piece 'R' can move to the right only if
+ *   there is a blank space directly to its right.
+ * - The character '_' represents a blank space that can be occupied by any of the 'L' or 'R'
+ *   pieces.
+ *
+ * Return true if it is possible to obtain the string target by moving the pieces of the string
+ * start any number of times. Otherwise, return false.
+ */
+
+/**
+ * @param {string} start
+ * @param {string} target
+ * @return {boolean}
+ */
+var canChange = function(start, target) {
+  const pieces = [];
+  const targetPieces = [];
+
+  for (let i = 0; i < start.length; i++) {
+    if (start[i] !== '_') pieces.push([start[i], i]);
+    if (target[i] !== '_') targetPieces.push([target[i], i]);
+  }
+
+  if (pieces.length !== targetPieces.length) return false;
+
+  for (let i = 0; i < pieces.length; i++) {
+    if (pieces[i][0] !== targetPieces[i][0]) return false;
+    if (pieces[i][0] === 'L' && pieces[i][1] < targetPieces[i][1]) return false;
+    if (pieces[i][0] === 'R' && pieces[i][1] > targetPieces[i][1]) return false;
+  }
+
+  return true;
+};
diff --git a/solutions/2338-count-the-number-of-ideal-arrays.js b/solutions/2338-count-the-number-of-ideal-arrays.js
new file mode 100644
index 00000000..dab7d4bc
--- /dev/null
+++ b/solutions/2338-count-the-number-of-ideal-arrays.js
@@ -0,0 +1,73 @@
+/**
+ * 2338. Count the Number of Ideal Arrays
+ * https://leetcode.com/problems/count-the-number-of-ideal-arrays/
+ * Difficulty: Hard
+ *
+ * You are given two integers n and maxValue, which are used to describe an ideal array.
+ *
+ * A 0-indexed integer array arr of length n is considered ideal if the following conditions hold:
+ * - Every arr[i] is a value from 1 to maxValue, for 0 <= i < n.
+ * - Every arr[i] is divisible by arr[i - 1], for 0 < i < n.
+ *
+ * Return the number of distinct ideal arrays of length n. Since the answer may be very large,
+ * return it modulo 109 + 7.
+ */
+
+/**
+ * @param {number} n
+ * @param {number} maxValue
+ * @return {number}
+ */
+var idealArrays = function(n, maxValue) {
+  const MOD = 1e9 + 7;
+  const MAX_N = 10010;
+  const MAX_P = 15;
+
+  const c = Array.from({ length: MAX_N + MAX_P }, () =>
+    new Array(MAX_P + 1).fill(0)
+  );
+  const sieve = new Array(MAX_N).fill(0);
+  const ps = Array.from({ length: MAX_N }, () => []);
+
+  for (let i = 2; i < MAX_N; i++) {
+    if (sieve[i] === 0) {
+      for (let j = i; j < MAX_N; j += i) {
+        if (sieve[j] === 0) {
+          sieve[j] = i;
+        }
+      }
+    }
+  }
+
+  for (let i = 2; i < MAX_N; i++) {
+    let x = i;
+    while (x > 1) {
+      const p = sieve[x];
+      let cnt = 0;
+      while (x % p === 0) {
+        x = Math.floor(x / p);
+        cnt++;
+      }
+      ps[i].push(cnt);
+    }
+  }
+
+  c[0][0] = 1;
+  for (let i = 1; i < MAX_N + MAX_P; i++) {
+    c[i][0] = 1;
+    for (let j = 1; j <= Math.min(i, MAX_P); j++) {
+      c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % MOD;
+    }
+  }
+
+  let ans = 0n;
+  for (let x = 1; x <= maxValue; x++) {
+    let mul = 1n;
+    for (const p of ps[x]) {
+      mul = (mul * BigInt(c[n + p - 1][p])) % BigInt(MOD);
+    }
+    ans = (ans + mul) % BigInt(MOD);
+  }
+
+  return Number(ans);
+};
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/2341-maximum-number-of-pairs-in-array.js b/solutions/2341-maximum-number-of-pairs-in-array.js
new file mode 100644
index 00000000..2cdcce2c
--- /dev/null
+++ b/solutions/2341-maximum-number-of-pairs-in-array.js
@@ -0,0 +1,35 @@
+/**
+ * 2341. Maximum Number of Pairs in Array
+ * https://leetcode.com/problems/maximum-number-of-pairs-in-array/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed integer array nums. In one operation, you may do the following:
+ * - Choose two integers in nums that are equal.
+ * - Remove both integers from nums, forming a pair.
+ *
+ * The operation is done on nums as many times as possible.
+ *
+ * Return a 0-indexed integer array answer of size 2 where answer[0] is the number of pairs that
+ * are formed and answer[1] is the number of leftover integers in nums after doing the operation
+ * as many times as possible.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var numberOfPairs = function(nums) {
+  const frequency = new Map();
+  let pairs = 0;
+
+  for (const num of nums) {
+    frequency.set(num, (frequency.get(num) || 0) + 1);
+    if (frequency.get(num) === 2) {
+      pairs++;
+      frequency.set(num, 0);
+    }
+  }
+
+  const leftovers = nums.length - pairs * 2;
+  return [pairs, leftovers];
+};
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/2347-best-poker-hand.js b/solutions/2347-best-poker-hand.js
new file mode 100644
index 00000000..586dcda2
--- /dev/null
+++ b/solutions/2347-best-poker-hand.js
@@ -0,0 +1,41 @@
+/**
+ * 2347. Best Poker Hand
+ * https://leetcode.com/problems/best-poker-hand/
+ * Difficulty: Easy
+ *
+ * You are given an integer array ranks and a character array suits. You have 5 cards where the
+ * ith card has a rank of ranks[i] and a suit of suits[i].
+ *
+ * The following are the types of poker hands you can make from best to worst:
+ * 1. "Flush": Five cards of the same suit.
+ * 2. "Three of a Kind": Three cards of the same rank.
+ * 3. "Pair": Two cards of the same rank.
+ * 4. "High Card": Any single card.
+ *
+ * Return a string representing the best type of poker hand you can make with the given cards.
+ *
+ * Note that the return values are case-sensitive.
+ */
+
+/**
+ * @param {number[]} ranks
+ * @param {character[]} suits
+ * @return {string}
+ */
+var bestHand = function(ranks, suits) {
+  const suitCount = new Map();
+  const rankCount = new Map();
+
+  for (let i = 0; i < 5; i++) {
+    suitCount.set(suits[i], (suitCount.get(suits[i]) || 0) + 1);
+    rankCount.set(ranks[i], (rankCount.get(ranks[i]) || 0) + 1);
+  }
+
+  if (suitCount.size === 1) return 'Flush';
+
+  const maxRankCount = Math.max(...rankCount.values());
+  if (maxRankCount >= 3) return 'Three of a Kind';
+  if (maxRankCount === 2) return 'Pair';
+
+  return 'High Card';
+};
diff --git a/solutions/2348-number-of-zero-filled-subarrays.js b/solutions/2348-number-of-zero-filled-subarrays.js
new file mode 100644
index 00000000..fa93ec19
--- /dev/null
+++ b/solutions/2348-number-of-zero-filled-subarrays.js
@@ -0,0 +1,29 @@
+/**
+ * 2348. Number of Zero-Filled Subarrays
+ * https://leetcode.com/problems/number-of-zero-filled-subarrays/
+ * Difficulty: Medium
+ *
+ * Given an integer array nums, return the number of subarrays filled with 0.
+ *
+ * A subarray is a contiguous non-empty sequence of elements within an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var zeroFilledSubarray = function(nums) {
+  let result = 0;
+  let zeroCount = 0;
+
+  for (const num of nums) {
+    if (num === 0) {
+      zeroCount++;
+      result += zeroCount;
+    } else {
+      zeroCount = 0;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2350-shortest-impossible-sequence-of-rolls.js b/solutions/2350-shortest-impossible-sequence-of-rolls.js
new file mode 100644
index 00000000..ea27a604
--- /dev/null
+++ b/solutions/2350-shortest-impossible-sequence-of-rolls.js
@@ -0,0 +1,32 @@
+/**
+ * 2350. Shortest Impossible Sequence of Rolls
+ * https://leetcode.com/problems/shortest-impossible-sequence-of-rolls/
+ * Difficulty: Hard
+ *
+ * You are given an integer array rolls of length n and an integer k. You roll a k sided dice
+ * numbered from 1 to k, n times, where the result of the ith roll is rolls[i].
+ *
+ * Return the length of the shortest sequence of rolls so that there's no such subsequence in rolls.
+ *
+ * A sequence of rolls of length len is the result of rolling a k sided dice len times.
+ */
+
+/**
+ * @param {number[]} rolls
+ * @param {number} k
+ * @return {number}
+ */
+var shortestSequence = function(rolls, k) {
+  const set = new Set();
+  let sequences = 0;
+
+  for (const roll of rolls) {
+    set.add(roll);
+    if (set.size === k) {
+      sequences++;
+      set.clear();
+    }
+  }
+
+  return sequences + 1;
+};
diff --git a/solutions/2351-first-letter-to-appear-twice.js b/solutions/2351-first-letter-to-appear-twice.js
new file mode 100644
index 00000000..b5fff8f5
--- /dev/null
+++ b/solutions/2351-first-letter-to-appear-twice.js
@@ -0,0 +1,26 @@
+/**
+ * 2351. First Letter to Appear Twice
+ * https://leetcode.com/problems/first-letter-to-appear-twice/
+ * Difficulty: Easy
+ *
+ * Given a string s consisting of lowercase English letters, return the first letter
+ * to appear twice.
+ *
+ * Note:
+ * - A letter a appears twice before another letter b if the second occurrence of a is before
+ *   the second occurrence of b.
+ * - s will contain at least one letter that appears twice.
+ */
+
+/**
+ * @param {string} s
+ * @return {character}
+ */
+var repeatedCharacter = function(s) {
+  const set = new Set();
+
+  for (const char of s) {
+    if (set.has(char)) return char;
+    set.add(char);
+  }
+};
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/2354-number-of-excellent-pairs.js b/solutions/2354-number-of-excellent-pairs.js
new file mode 100644
index 00000000..bf60424a
--- /dev/null
+++ b/solutions/2354-number-of-excellent-pairs.js
@@ -0,0 +1,46 @@
+/**
+ * 2354. Number of Excellent Pairs
+ * https://leetcode.com/problems/number-of-excellent-pairs/
+ * Difficulty: Hard
+ *
+ * You are given a 0-indexed positive integer array nums and a positive integer k.
+ *
+ * A pair of numbers (num1, num2) is called excellent if the following conditions are satisfied:
+ * - Both the numbers num1 and num2 exist in the array nums.
+ * - The sum of the number of set bits in num1 OR num2 and num1 AND num2 is greater than or equal
+ *   to k, where OR is the bitwise OR operation and AND is the bitwise AND operation.
+ *
+ * Return the number of distinct excellent pairs.
+ *
+ * Two pairs (a, b) and (c, d) are considered distinct if either a != c or b != d. For example,
+ * (1, 2) and (2, 1) are distinct.
+ *
+ * Note that a pair (num1, num2) such that num1 == num2 can also be excellent if you have at least
+ * one occurrence of num1 in the array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var countExcellentPairs = function(nums, k) {
+  const map = new Map();
+  const set = new Set(nums);
+
+  for (const num of set) {
+    const bits = num.toString(2).split('0').join('').length;
+    map.set(bits, (map.get(bits) || 0) + 1);
+  }
+
+  let result = 0;
+  for (const [i, countI] of map) {
+    for (const [j, countJ] of map) {
+      if (i + j >= k) {
+        result += countI * countJ;
+      }
+    }
+  }
+
+  return result;
+};
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/2358-maximum-number-of-groups-entering-a-competition.js b/solutions/2358-maximum-number-of-groups-entering-a-competition.js
new file mode 100644
index 00000000..2637927b
--- /dev/null
+++ b/solutions/2358-maximum-number-of-groups-entering-a-competition.js
@@ -0,0 +1,31 @@
+/**
+ * 2358. Maximum Number of Groups Entering a Competition
+ * https://leetcode.com/problems/maximum-number-of-groups-entering-a-competition/
+ * Difficulty: Medium
+ *
+ * You are given a positive integer array grades which represents the grades of students in
+ * a university. You would like to enter all these students into a competition in ordered
+ * non-empty groups, such that the ordering meets the following conditions:
+ * - The sum of the grades of students in the ith group is less than the sum of the grades of
+ *   students in the (i + 1)th group, for all groups (except the last).
+ * - The total number of students in the ith group is less than the total number of students
+ *   in the (i + 1)th group, for all groups (except the last).
+ *
+ * Return the maximum number of groups that can be formed.
+ */
+
+/**
+ * @param {number[]} grades
+ * @return {number}
+ */
+var maximumGroups = function(grades) {
+  let result = 0;
+  let studentsUsed = 0;
+
+  while (studentsUsed + result + 1 <= grades.length) {
+    result++;
+    studentsUsed += result;
+  }
+
+  return result;
+};
diff --git a/solutions/2359-find-closest-node-to-given-two-nodes.js b/solutions/2359-find-closest-node-to-given-two-nodes.js
new file mode 100644
index 00000000..c048153f
--- /dev/null
+++ b/solutions/2359-find-closest-node-to-given-two-nodes.js
@@ -0,0 +1,63 @@
+/**
+ * 2359. Find Closest Node to Given Two Nodes
+ * https://leetcode.com/problems/find-closest-node-to-given-two-nodes/
+ * Difficulty: Medium
+ *
+ * You are given a directed graph of n nodes numbered from 0 to n - 1, where each node has at
+ * most one outgoing edge.
+ *
+ * The graph is represented with a given 0-indexed array edges of size n, indicating that there
+ * is a directed edge from node i to node edges[i]. If there is no outgoing edge from i, then
+ * edges[i] == -1.
+ *
+ * You are also given two integers node1 and node2.
+ *
+ * Return the index of the node that can be reached from both node1 and node2, such that the maximum
+ * between the distance from node1 to that node, and from node2 to that node is minimized. If there
+ * are multiple answers, return the node with the smallest index, and if no possible answer exists,
+ * return -1.
+ *
+ * Note that edges may contain cycles.
+ */
+
+/**
+ * @param {number[]} edges
+ * @param {number} node1
+ * @param {number} node2
+ * @return {number}
+ */
+var closestMeetingNode = function(edges, node1, node2) {
+  const n = edges.length;
+  const dist1 = new Array(n).fill(Infinity);
+  const dist2 = new Array(n).fill(Infinity);
+
+  computeDistances(node1, dist1);
+  computeDistances(node2, dist2);
+
+  let minDist = Infinity;
+  let result = -1;
+
+  for (let i = 0; i < n; i++) {
+    if (dist1[i] !== Infinity && dist2[i] !== Infinity) {
+      const maxDist = Math.max(dist1[i], dist2[i]);
+      if (maxDist < minDist) {
+        minDist = maxDist;
+        result = i;
+      }
+    }
+  }
+
+  return result;
+
+  function computeDistances(start, distances) {
+    let current = start;
+    let steps = 0;
+    const visited = new Set();
+
+    while (current !== -1 && !visited.has(current)) {
+      distances[current] = steps++;
+      visited.add(current);
+      current = edges[current];
+    }
+  }
+};
diff --git a/solutions/2360-longest-cycle-in-a-graph.js b/solutions/2360-longest-cycle-in-a-graph.js
new file mode 100644
index 00000000..6da96750
--- /dev/null
+++ b/solutions/2360-longest-cycle-in-a-graph.js
@@ -0,0 +1,53 @@
+/**
+ * 2360. Longest Cycle in a Graph
+ * https://leetcode.com/problems/longest-cycle-in-a-graph/
+ * Difficulty: Hard
+ *
+ * You are given a directed graph of n nodes numbered from 0 to n - 1, where each node has at
+ * most one outgoing edge.
+ *
+ * The graph is represented with a given 0-indexed array edges of size n, indicating that
+ * there is a directed edge from node i to node edges[i]. If there is no outgoing edge from
+ * node i, then edges[i] == -1.
+ *
+ * Return the length of the longest cycle in the graph. If no cycle exists, return -1.
+ *
+ * A cycle is a path that starts and ends at the same node.
+ */
+
+/**
+ * @param {number[]} edges
+ * @return {number}
+ */
+var longestCycle = function(edges) {
+  const n = edges.length;
+  const visited = new Array(n).fill(false);
+  let result = -1;
+
+  for (let i = 0; i < n; i++) {
+    if (!visited[i]) {
+      findCycle(i, 0, []);
+    }
+  }
+
+  return result;
+
+  function findCycle(node, steps, path) {
+    if (visited[node]) {
+      const cycleStart = path.indexOf(node);
+      if (cycleStart !== -1) {
+        result = Math.max(result, steps - cycleStart);
+      }
+      return;
+    }
+
+    visited[node] = true;
+    path.push(node);
+
+    if (edges[node] !== -1) {
+      findCycle(edges[node], steps + 1, path);
+    }
+
+    path.pop();
+  }
+};
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/2363-merge-similar-items.js b/solutions/2363-merge-similar-items.js
new file mode 100644
index 00000000..da16c478
--- /dev/null
+++ b/solutions/2363-merge-similar-items.js
@@ -0,0 +1,40 @@
+/**
+ * 2363. Merge Similar Items
+ * https://leetcode.com/problems/merge-similar-items/
+ * Difficulty: Easy
+ *
+ * You are given two 2D integer arrays, items1 and items2, representing two sets of items.
+ * Each array items has the following properties:
+ * - items[i] = [valuei, weighti] where valuei represents the value and weighti represents
+ *   the weight of the ith item.
+ * - The value of each item in items is unique.
+ *
+ * Return a 2D integer array ret where ret[i] = [valuei, weighti], with weighti being the sum of
+ * weights of all items with value valuei.
+ *
+ * Note: ret should be returned in ascending order by value.
+ */
+
+/**
+ * @param {number[][]} items1
+ * @param {number[][]} items2
+ * @return {number[][]}
+ */
+var mergeSimilarItems = function(items1, items2) {
+  const map = new Map();
+
+  for (const [value, weight] of items1) {
+    map.set(value, (map.get(value) || 0) + weight);
+  }
+
+  for (const [value, weight] of items2) {
+    map.set(value, (map.get(value) || 0) + weight);
+  }
+
+  const merged = [];
+  for (const [value, weight] of map) {
+    merged.push([value, weight]);
+  }
+
+  return merged.sort((a, b) => a[0] - b[0]);
+};
diff --git a/solutions/2365-task-scheduler-ii.js b/solutions/2365-task-scheduler-ii.js
new file mode 100644
index 00000000..166fdfdf
--- /dev/null
+++ b/solutions/2365-task-scheduler-ii.js
@@ -0,0 +1,41 @@
+/**
+ * 2365. Task Scheduler II
+ * https://leetcode.com/problems/task-scheduler-ii/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed array of positive integers tasks, representing tasks that need
+ * to be completed in order, where tasks[i] represents the type of the ith task.
+ *
+ * You are also given a positive integer space, which represents the minimum number of days
+ * that must pass after the completion of a task before another task of the same type can be
+ * performed.
+ *
+ * Each day, until all tasks have been completed, you must either:
+ * - Complete the next task from tasks, or
+ * - Take a break.
+ *
+ * Return the minimum number of days needed to complete all tasks.
+ */
+
+/**
+ * @param {number[]} tasks
+ * @param {number} space
+ * @return {number}
+ */
+var taskSchedulerII = function(tasks, space) {
+  const map = new Map();
+  let result = 0;
+
+  for (const task of tasks) {
+    result++;
+    if (map.has(task)) {
+      const lastDay = map.get(task);
+      if (result - lastDay <= space) {
+        result = lastDay + space + 1;
+      }
+    }
+    map.set(task, result);
+  }
+
+  return result;
+};
diff --git a/solutions/2366-minimum-replacements-to-sort-the-array.js b/solutions/2366-minimum-replacements-to-sort-the-array.js
new file mode 100644
index 00000000..422d21f6
--- /dev/null
+++ b/solutions/2366-minimum-replacements-to-sort-the-array.js
@@ -0,0 +1,33 @@
+/**
+ * 2366. Minimum Replacements to Sort the Array
+ * https://leetcode.com/problems/minimum-replacements-to-sort-the-array/
+ * Difficulty: Hard
+ *
+ * You are given a 0-indexed integer array nums. In one operation you can replace any element
+ * of the array with any two elements that sum to it.
+ * - For example, consider nums = [5,6,7]. In one operation, we can replace nums[1] with 2 and 4
+ *   and convert nums to [5,2,4,7].
+ *
+ * Return the minimum number of operations to make an array that is sorted in non-decreasing order.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var minimumReplacement = function(nums) {
+  let result = 0;
+  let prev = nums[nums.length - 1];
+
+  for (let i = nums.length - 2; i >= 0; i--) {
+    if (nums[i] > prev) {
+      const splits = Math.ceil(nums[i] / prev);
+      result += splits - 1;
+      prev = Math.floor(nums[i] / splits);
+    } else {
+      prev = nums[i];
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2367-number-of-arithmetic-triplets.js b/solutions/2367-number-of-arithmetic-triplets.js
new file mode 100644
index 00000000..21c02a86
--- /dev/null
+++ b/solutions/2367-number-of-arithmetic-triplets.js
@@ -0,0 +1,41 @@
+/**
+ * 2367. Number of Arithmetic Triplets
+ * https://leetcode.com/problems/number-of-arithmetic-triplets/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed, strictly increasing integer array nums and a positive integer diff.
+ * A triplet (i, j, k) is an arithmetic triplet if the following conditions are met:
+ * - i < j < k,
+ * - nums[j] - nums[i] == diff, and
+ * - nums[k] - nums[j] == diff.
+ *
+ * Return the number of unique arithmetic triplets.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} diff
+ * @return {number}
+ */
+var arithmeticTriplets = function(nums, diff) {
+  let result = 0;
+
+  for (let j = 1; j < nums.length - 1; j++) {
+    let i = j - 1;
+    let k = j + 1;
+
+    while (i >= 0 && nums[j] - nums[i] <= diff) {
+      if (nums[j] - nums[i] === diff) {
+        while (k < nums.length && nums[k] - nums[j] <= diff) {
+          if (nums[k] - nums[j] === diff) {
+            result++;
+          }
+          k++;
+        }
+      }
+      i--;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2368-reachable-nodes-with-restrictions.js b/solutions/2368-reachable-nodes-with-restrictions.js
new file mode 100644
index 00000000..1ecd0821
--- /dev/null
+++ b/solutions/2368-reachable-nodes-with-restrictions.js
@@ -0,0 +1,43 @@
+/**
+ * 2368. Reachable Nodes With Restrictions
+ * https://leetcode.com/problems/reachable-nodes-with-restrictions/
+ * Difficulty: Medium
+ *
+ * There is an undirected tree with n nodes labeled from 0 to n - 1 and n - 1 edges.
+ *
+ * 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 an integer
+ * array restricted which represents restricted nodes.
+ *
+ * Return the maximum number of nodes you can reach from node 0 without visiting a restricted node.
+ *
+ * Note that node 0 will not be a restricted node.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[][]} edges
+ * @param {number[]} restricted
+ * @return {number}
+ */
+var reachableNodes = function(n, edges, restricted) {
+  const graph = Array(n).fill().map(() => []);
+  const restrictedSet = new Set(restricted);
+  const visited = new Set();
+
+  for (const [u, v] of edges) {
+    graph[u].push(v);
+    graph[v].push(u);
+  }
+
+  explore(0);
+  return visited.size;
+
+  function explore(node) {
+    if (visited.has(node) || restrictedSet.has(node)) return;
+    visited.add(node);
+    for (const neighbor of graph[node]) {
+      explore(neighbor);
+    }
+  }
+};
diff --git a/solutions/2369-check-if-there-is-a-valid-partition-for-the-array.js b/solutions/2369-check-if-there-is-a-valid-partition-for-the-array.js
new file mode 100644
index 00000000..be0e9844
--- /dev/null
+++ b/solutions/2369-check-if-there-is-a-valid-partition-for-the-array.js
@@ -0,0 +1,44 @@
+/**
+ * 2369. Check if There is a Valid Partition For The Array
+ * https://leetcode.com/problems/check-if-there-is-a-valid-partition-for-the-array/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums. You have to partition the array into one or
+ * more contiguous subarrays.
+ *
+ * We call a partition of the array valid if each of the obtained subarrays satisfies one of
+ * the following conditions:
+ * 1. The subarray consists of exactly 2, equal elements. For example, the subarray [2,2] is good.
+ * 2. The subarray consists of exactly 3, equal elements. For example, the subarray [4,4,4] is good.
+ * 3. The subarray consists of exactly 3 consecutive increasing elements, that is, the difference
+ *    between adjacent elements is 1. For example, the subarray [3,4,5] is good, but the subarray
+ *    [1,3,5] is not.
+ *
+ * Return true if the array has at least one valid partition. Otherwise, return false.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {boolean}
+ */
+var validPartition = function(nums) {
+  const n = nums.length;
+  const dp = new Array(n + 1).fill(false);
+  dp[0] = true;
+
+  for (let i = 2; i <= n; i++) {
+    if (nums[i - 1] === nums[i - 2]) {
+      dp[i] = dp[i] || dp[i - 2];
+    }
+    if (i >= 3) {
+      if (nums[i - 1] === nums[i - 2] && nums[i - 2] === nums[i - 3]) {
+        dp[i] = dp[i] || dp[i - 3];
+      }
+      if (nums[i - 1] === nums[i - 2] + 1 && nums[i - 2] === nums[i - 3] + 1) {
+        dp[i] = dp[i] || dp[i - 3];
+      }
+    }
+  }
+
+  return dp[n];
+};
diff --git a/solutions/2370-longest-ideal-subsequence.js b/solutions/2370-longest-ideal-subsequence.js
new file mode 100644
index 00000000..c07e27f9
--- /dev/null
+++ b/solutions/2370-longest-ideal-subsequence.js
@@ -0,0 +1,43 @@
+/**
+ * 2370. Longest Ideal Subsequence
+ * https://leetcode.com/problems/longest-ideal-subsequence/
+ * Difficulty: Medium
+ *
+ * You are given a string s consisting of lowercase letters and an integer k. We call a string
+ * t ideal if the following conditions are satisfied:
+ * - t is a subsequence of the string s.
+ * - The absolute difference in the alphabet order of every two adjacent letters in t is less
+ *   than or equal to k.
+ *
+ * Return the length of the longest ideal string.
+ *
+ * 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.
+ *
+ * Note that the alphabet order is not cyclic. For example, the absolute difference in the
+ * alphabet order of 'a' and 'z' is 25, not 1.
+ */
+
+/**
+ * @param {string} s
+ * @param {number} k
+ * @return {number}
+ */
+var longestIdealString = function(s, k) {
+  const dp = new Array(26).fill(0);
+  let result = 0;
+
+  for (const char of s) {
+    const idx = char.charCodeAt(0) - 97;
+    let currentMax = 0;
+
+    for (let i = Math.max(0, idx - k); i <= Math.min(25, idx + k); i++) {
+      currentMax = Math.max(currentMax, dp[i]);
+    }
+
+    dp[idx] = currentMax + 1;
+    result = Math.max(result, dp[idx]);
+  }
+
+  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/2373-largest-local-values-in-a-matrix.js b/solutions/2373-largest-local-values-in-a-matrix.js
new file mode 100644
index 00000000..46a65c45
--- /dev/null
+++ b/solutions/2373-largest-local-values-in-a-matrix.js
@@ -0,0 +1,38 @@
+/**
+ * 2373. Largest Local Values in a Matrix
+ * https://leetcode.com/problems/largest-local-values-in-a-matrix/
+ * Difficulty: Easy
+ *
+ * You are given an n x n integer matrix grid.
+ *
+ * Generate an integer matrix maxLocal of size (n - 2) x (n - 2) such that:
+ * - maxLocal[i][j] is equal to the largest value of the 3 x 3 matrix in grid centered around
+ *   row i + 1 and column j + 1.
+ *
+ * In other words, we want to find the largest value in every contiguous 3 x 3 matrix in grid.
+ *
+ * Return the generated matrix.
+ */
+
+/**
+ * @param {number[][]} grid
+ * @return {number[][]}
+ */
+var largestLocal = function(grid) {
+  const n = grid.length;
+  const result = new Array(n - 2).fill().map(() => new Array(n - 2).fill(0));
+
+  for (let i = 0; i < n - 2; i++) {
+    for (let j = 0; j < n - 2; j++) {
+      let maxVal = 0;
+      for (let r = i; r < i + 3; r++) {
+        for (let c = j; c < j + 3; c++) {
+          maxVal = Math.max(maxVal, grid[r][c]);
+        }
+      }
+      result[i][j] = maxVal;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2374-node-with-highest-edge-score.js b/solutions/2374-node-with-highest-edge-score.js
new file mode 100644
index 00000000..b8597422
--- /dev/null
+++ b/solutions/2374-node-with-highest-edge-score.js
@@ -0,0 +1,39 @@
+/**
+ * 2374. Node With Highest Edge Score
+ * https://leetcode.com/problems/node-with-highest-edge-score/
+ * Difficulty: Medium
+ *
+ * You are given a directed graph with n nodes labeled from 0 to n - 1, where each node has
+ * exactly one outgoing edge.
+ *
+ * The graph is represented by a given 0-indexed integer array edges of length n, where edges[i]
+ * indicates that there is a directed edge from node i to node edges[i].
+ *
+ * The edge score of a node i is defined as the sum of the labels of all the nodes that have an
+ * edge pointing to i.
+ *
+ * Return the node with the highest edge score. If multiple nodes have the same edge score, return
+ * the node with the smallest index.
+ */
+
+/**
+ * @param {number[]} edges
+ * @return {number}
+ */
+var edgeScore = function(edges) {
+  const scores = new Array(edges.length).fill(0);
+
+  for (let i = 0; i < edges.length; i++) {
+    scores[edges[i]] += i;
+  }
+  let maxScore = 0;
+  let result = 0;
+  for (let i = 0; i < scores.length; i++) {
+    if (scores[i] > maxScore) {
+      maxScore = scores[i];
+      result = i;
+    }
+  }
+
+  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/2380-time-needed-to-rearrange-a-binary-string.js b/solutions/2380-time-needed-to-rearrange-a-binary-string.js
new file mode 100644
index 00000000..d85d2234
--- /dev/null
+++ b/solutions/2380-time-needed-to-rearrange-a-binary-string.js
@@ -0,0 +1,32 @@
+/**
+ * 2380. Time Needed to Rearrange a Binary String
+ * https://leetcode.com/problems/time-needed-to-rearrange-a-binary-string/
+ * Difficulty: Medium
+ *
+ * You are given a binary string s. In one second, all occurrences of "01" are simultaneously
+ * replaced with "10". This process repeats until no occurrences of "01" exist.
+ *
+ * Return the number of seconds needed to complete this process.
+ */
+
+/**
+ * @param {string} s
+ * @return {number}
+ */
+var secondsToRemoveOccurrences = function(s) {
+  const binary = s.split('');
+  let result = 0;
+
+  while (binary.join('').includes('01')) {
+    for (let i = 0; i < binary.length - 1; i++) {
+      if (binary[i] === '0' && binary[i + 1] === '1') {
+        binary[i] = '1';
+        binary[i + 1] = '0';
+        i++;
+      }
+    }
+    result++;
+  }
+
+  return result;
+};
diff --git a/solutions/2382-maximum-segment-sum-after-removals.js b/solutions/2382-maximum-segment-sum-after-removals.js
new file mode 100644
index 00000000..78065c5e
--- /dev/null
+++ b/solutions/2382-maximum-segment-sum-after-removals.js
@@ -0,0 +1,84 @@
+/**
+ * 2382. Maximum Segment Sum After Removals
+ * https://leetcode.com/problems/maximum-segment-sum-after-removals/
+ * Difficulty: Hard
+ *
+ * You are given two 0-indexed integer arrays nums and removeQueries, both of length n. For
+ * the ith query, the element in nums at the index removeQueries[i] is removed, splitting
+ * nums into different segments.
+ *
+ * A segment is a contiguous sequence of positive integers in nums. A segment sum is the sum
+ * of every element in a segment.
+ *
+ * Return an integer array answer, of length n, where answer[i] is the maximum segment sum after
+ * applying the ith removal.
+ *
+ * Note: The same index will not be removed more than once.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number[]} removeQueries
+ * @return {number[]}
+ */
+var maximumSegmentSum = function(nums, removeQueries) {
+  const n = nums.length;
+  const result = new Array(n);
+  const prefixSum = new Array(n + 1).fill(0);
+  const parents = new Array(n).fill(-1);
+  const sizes = new Array(n).fill(0);
+  const sums = new Array(n).fill(0);
+  let maxSum = 0;
+
+  for (let i = 0; i < n; i++) {
+    prefixSum[i + 1] = prefixSum[i] + nums[i];
+  }
+
+  for (let i = n - 1; i >= 0; i--) {
+    result[i] = maxSum;
+    const index = removeQueries[i];
+
+    parents[index] = index;
+    sizes[index] = 1;
+    sums[index] = nums[index];
+
+    if (index > 0 && parents[index - 1] !== -1) {
+      const leftRoot = findRoot(parents, index - 1);
+      const segmentSum = sums[leftRoot] + sums[index];
+
+      parents[index] = leftRoot;
+      sizes[leftRoot] += sizes[index];
+      sums[leftRoot] = segmentSum;
+    }
+
+    if (index < n - 1 && parents[index + 1] !== -1) {
+      const root = findRoot(parents, index);
+      const rightRoot = findRoot(parents, index + 1);
+
+      if (root !== rightRoot) {
+        const segmentSum = sums[root] + sums[rightRoot];
+
+        if (sizes[root] < sizes[rightRoot]) {
+          parents[root] = rightRoot;
+          sizes[rightRoot] += sizes[root];
+          sums[rightRoot] = segmentSum;
+        } else {
+          parents[rightRoot] = root;
+          sizes[root] += sizes[rightRoot];
+          sums[root] = segmentSum;
+        }
+      }
+    }
+
+    maxSum = Math.max(maxSum, sums[findRoot(parents, index)]);
+  }
+
+  return result;
+};
+
+function findRoot(parents, x) {
+  if (parents[x] !== x) {
+    parents[x] = findRoot(parents, parents[x]);
+  }
+  return parents[x];
+}
diff --git a/solutions/2383-minimum-hours-of-training-to-win-a-competition.js b/solutions/2383-minimum-hours-of-training-to-win-a-competition.js
new file mode 100644
index 00000000..0699fdcc
--- /dev/null
+++ b/solutions/2383-minimum-hours-of-training-to-win-a-competition.js
@@ -0,0 +1,55 @@
+/**
+ * 2383. Minimum Hours of Training to Win a Competition
+ * https://leetcode.com/problems/minimum-hours-of-training-to-win-a-competition/
+ * Difficulty: Easy
+ *
+ * You are entering a competition, and are given two positive integers initialEnergy and
+ * initialExperience denoting your initial energy and initial experience respectively.
+ *
+ * You are also given two 0-indexed integer arrays energy and experience, both of length n.
+ *
+ * You will face n opponents in order. The energy and experience of the ith opponent is
+ * denoted by energy[i] and experience[i] respectively. When you face an opponent, you need
+ * to have both strictly greater experience and energy to defeat them and move to the next
+ * opponent if available.
+ *
+ * Defeating the ith opponent increases your experience by experience[i], but decreases your
+ * energy by energy[i].
+ *
+ * Before starting the competition, you can train for some number of hours. After each hour
+ * of training, you can either choose to increase your initial experience by one, or increase
+ * your initial energy by one.
+ *
+ * Return the minimum number of training hours required to defeat all n opponents.
+ */
+
+/**
+ * @param {number} initialEnergy
+ * @param {number} initialExperience
+ * @param {number[]} energy
+ * @param {number[]} experience
+ * @return {number}
+ */
+var minNumberOfHours = function(initialEnergy, initialExperience, energy, experience) {
+  let energyNeeded = 0;
+  let experienceNeeded = 0;
+  let currentEnergy = initialEnergy;
+  let currentExperience = initialExperience;
+
+  for (let i = 0; i < energy.length; i++) {
+    if (currentEnergy <= energy[i]) {
+      const deficit = energy[i] - currentEnergy + 1;
+      energyNeeded += deficit;
+      currentEnergy += deficit;
+    }
+    if (currentExperience <= experience[i]) {
+      const deficit = experience[i] - currentExperience + 1;
+      experienceNeeded += deficit;
+      currentExperience += deficit;
+    }
+    currentEnergy -= energy[i];
+    currentExperience += experience[i];
+  }
+
+  return energyNeeded + experienceNeeded;
+};
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/2385-amount-of-time-for-binary-tree-to-be-infected.js b/solutions/2385-amount-of-time-for-binary-tree-to-be-infected.js
new file mode 100644
index 00000000..00bd2ddd
--- /dev/null
+++ b/solutions/2385-amount-of-time-for-binary-tree-to-be-infected.js
@@ -0,0 +1,70 @@
+/**
+ * 2385. Amount of Time for Binary Tree to Be Infected
+ * https://leetcode.com/problems/amount-of-time-for-binary-tree-to-be-infected/
+ * Difficulty: Medium
+ *
+ * You are given the root of a binary tree with unique values, and an integer start.
+ * At minute 0, an infection starts from the node with value start.
+ *
+ * Each minute, a node becomes infected if:
+ * - The node is currently uninfected.
+ * - The node is adjacent to an infected node.
+ *
+ * Return the number of minutes needed for the entire tree to be infected.
+ */
+
+/**
+ * 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} start
+ * @return {number}
+ */
+var amountOfTime = function(root, start) {
+  const graph = new Map();
+  const queue = [start];
+  const visited = new Set([start]);
+  let result = -1;
+
+  buildGraph(root, null);
+
+  while (queue.length) {
+    result++;
+    const levelSize = queue.length;
+    for (let i = 0; i < levelSize; i++) {
+      const current = queue.shift();
+      for (const neighbor of graph.get(current) || []) {
+        if (!visited.has(neighbor)) {
+          visited.add(neighbor);
+          queue.push(neighbor);
+        }
+      }
+    }
+  }
+
+  return result;
+
+  function buildGraph(node, parent) {
+    if (!node) return;
+    if (!graph.has(node.val)) graph.set(node.val, []);
+    if (parent) graph.get(node.val).push(parent.val);
+    if (node.left) {
+      graph.get(node.val).push(node.left.val);
+      graph.set(node.left.val, graph.get(node.left.val) || []);
+      graph.get(node.left.val).push(node.val);
+    }
+    if (node.right) {
+      graph.get(node.val).push(node.right.val);
+      graph.set(node.right.val, graph.get(node.right.val) || []);
+      graph.get(node.right.val).push(node.val);
+    }
+    buildGraph(node.left, node);
+    buildGraph(node.right, node);
+  }
+};
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/2389-longest-subsequence-with-limited-sum.js b/solutions/2389-longest-subsequence-with-limited-sum.js
new file mode 100644
index 00000000..a498b7c8
--- /dev/null
+++ b/solutions/2389-longest-subsequence-with-limited-sum.js
@@ -0,0 +1,43 @@
+/**
+ * 2389. Longest Subsequence With Limited Sum
+ * https://leetcode.com/problems/longest-subsequence-with-limited-sum/
+ * Difficulty: Easy
+ *
+ * You are given an integer array nums of length n, and an integer array queries of length m.
+ *
+ * Return an array answer of length m where answer[i] is the maximum size of a subsequence that
+ * you can take from nums such that the sum of its elements is less than or equal to queries[i].
+ *
+ * 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[]} queries
+ * @return {number[]}
+ */
+var answerQueries = function(nums, queries) {
+  nums.sort((a, b) => a - b);
+  const prefixSums = [0];
+  for (const num of nums) {
+    prefixSums.push(prefixSums.at(-1) + num);
+  }
+
+  const result = new Array(queries.length);
+  for (let i = 0; i < queries.length; i++) {
+    let left = 0;
+    let right = nums.length;
+    while (left < right) {
+      const mid = Math.floor((left + right + 1) / 2);
+      if (prefixSums[mid] <= queries[i]) {
+        left = mid;
+      } else {
+        right = mid - 1;
+      }
+    }
+    result[i] = left;
+  }
+
+  return result;
+};
diff --git a/solutions/2391-minimum-amount-of-time-to-collect-garbage.js b/solutions/2391-minimum-amount-of-time-to-collect-garbage.js
new file mode 100644
index 00000000..bbddfc01
--- /dev/null
+++ b/solutions/2391-minimum-amount-of-time-to-collect-garbage.js
@@ -0,0 +1,50 @@
+/**
+ * 2391. Minimum Amount of Time to Collect Garbage
+ * https://leetcode.com/problems/minimum-amount-of-time-to-collect-garbage/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed array of strings garbage where garbage[i] represents the assortment
+ * of garbage at the ith house. garbage[i] consists only of the characters 'M', 'P' and 'G'
+ * representing one unit of metal, paper and glass garbage respectively. Picking up one unit of
+ * any type of garbage takes 1 minute.
+ *
+ * You are also given a 0-indexed integer array travel where travel[i] is the number of minutes
+ * needed to go from house i to house i + 1.
+ *
+ * There are three garbage trucks in the city, each responsible for picking up one type of garbage.
+ * Each garbage truck starts at house 0 and must visit each house in order; however, they do not
+ * need to visit every house.
+ *
+ * Only one garbage truck may be used at any given moment. While one truck is driving or picking up
+ * garbage, the other two trucks cannot do anything.
+ *
+ * Return the minimum number of minutes needed to pick up all the garbage.
+ */
+
+/**
+ * @param {string[]} garbage
+ * @param {number[]} travel
+ * @return {number}
+ */
+var garbageCollection = function(garbage, travel) {
+  let result = 0;
+  const lastHouse = {'M': 0, 'P': 0, 'G': 0};
+
+  for (let i = 0; i < garbage.length; i++) {
+    result += garbage[i].length;
+    for (const type of garbage[i]) {
+      lastHouse[type] = i;
+    }
+  }
+
+  const prefixTravel = [0];
+  for (const time of travel) {
+    prefixTravel.push(prefixTravel.at(-1) + time);
+  }
+
+  Object.keys(lastHouse).forEach(type => {
+    result += prefixTravel[lastHouse[type]];
+  });
+
+  return result;
+};
diff --git a/solutions/2392-build-a-matrix-with-conditions.js b/solutions/2392-build-a-matrix-with-conditions.js
new file mode 100644
index 00000000..b55cdd0f
--- /dev/null
+++ b/solutions/2392-build-a-matrix-with-conditions.js
@@ -0,0 +1,76 @@
+/**
+ * 2392. Build a Matrix With Conditions
+ * https://leetcode.com/problems/build-a-matrix-with-conditions/
+ * Difficulty: Hard
+ *
+ * You are given a positive integer k. You are also given:
+ * - a 2D integer array rowConditions of size n where rowConditions[i] = [abovei, belowi], and
+ * - a 2D integer array colConditions of size m where colConditions[i] = [lefti, righti].
+ *
+ * The two arrays contain integers from 1 to k.
+ *
+ * You have to build a k x k matrix that contains each of the numbers from 1 to k exactly once.
+ * The remaining cells should have the value 0.
+ *
+ * The matrix should also satisfy the following conditions:
+ * - The number abovei should appear in a row that is strictly above the row at which the number
+ *   belowi appears for all i from 0 to n - 1.
+ * - The number lefti should appear in a column that is strictly left of the column at which the
+ *   number righti appears for all i from 0 to m - 1.
+ *
+ * Return any matrix that satisfies the conditions. If no answer exists, return an empty matrix.
+ */
+
+/**
+ * @param {number} k
+ * @param {number[][]} rowConditions
+ * @param {number[][]} colConditions
+ * @return {number[][]}
+ */
+var buildMatrix = function(k, rowConditions, colConditions) {
+  const rowOrder = helper(rowConditions, k);
+  if (!rowOrder.length) return [];
+
+  const colOrder = helper(colConditions, k);
+  if (!colOrder.length) return [];
+
+  const matrix = Array.from({ length: k }, () => new Array(k).fill(0));
+  const rowIndex = new Array(k + 1).fill(0);
+  const colIndex = new Array(k + 1).fill(0);
+
+  for (let i = 0; i < k; i++) {
+    rowIndex[rowOrder[i]] = i;
+    colIndex[colOrder[i]] = i;
+  }
+
+  for (let num = 1; num <= k; num++) {
+    matrix[rowIndex[num]][colIndex[num]] = num;
+  }
+
+  return matrix;
+
+  function helper(edges, size) {
+    const graph = Array.from({ length: size + 1 }, () => []);
+    const inDegree = new Array(size + 1).fill(0);
+    for (const [u, v] of edges) {
+      graph[u].push(v);
+      inDegree[v]++;
+    }
+
+    const queue = [];
+    for (let i = 1; i <= size; i++) {
+      if (inDegree[i] === 0) queue.push(i);
+    }
+
+    const order = [];
+    while (queue.length) {
+      const node = queue.shift();
+      order.push(node);
+      for (const next of graph[node]) {
+        if (--inDegree[next] === 0) queue.push(next);
+      }
+    }
+
+    return order.length === size ? order : [];
+  }
+};
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/2395-find-subarrays-with-equal-sum.js b/solutions/2395-find-subarrays-with-equal-sum.js
new file mode 100644
index 00000000..9b4ec520
--- /dev/null
+++ b/solutions/2395-find-subarrays-with-equal-sum.js
@@ -0,0 +1,28 @@
+/**
+ * 2395. Find Subarrays With Equal Sum
+ * https://leetcode.com/problems/find-subarrays-with-equal-sum/
+ * Difficulty: Easy
+ *
+ * Given a 0-indexed integer array nums, determine whether there exist two subarrays of length
+ * 2 with equal sum. Note that the two subarrays must begin at different indices.
+ *
+ * Return true if these subarrays exist, and false otherwise.
+ *
+ * A subarray is a contiguous non-empty sequence of elements within an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {boolean}
+ */
+var findSubarrays = function(nums) {
+  const set = new Set();
+
+  for (let i = 0; i < nums.length - 1; i++) {
+    const sum = nums[i] + nums[i + 1];
+    if (set.has(sum)) return true;
+    set.add(sum);
+  }
+
+  return false;
+};
diff --git a/solutions/2397-maximum-rows-covered-by-columns.js b/solutions/2397-maximum-rows-covered-by-columns.js
new file mode 100644
index 00000000..0fa68a2b
--- /dev/null
+++ b/solutions/2397-maximum-rows-covered-by-columns.js
@@ -0,0 +1,61 @@
+/**
+ * 2397. Maximum Rows Covered by Columns
+ * https://leetcode.com/problems/maximum-rows-covered-by-columns/
+ * Difficulty: Medium
+ *
+ * You are given an m x n binary matrix matrix and an integer numSelect.
+ *
+ * Your goal is to select exactly numSelect distinct columns from matrix such that you cover
+ * as many rows as possible.
+ *
+ * A row is considered covered if all the 1's in that row are also part of a column that you
+ * have selected. If a row does not have any 1s, it is also considered covered.
+ *
+ * More formally, let us consider selected = {c1, c2, ...., cnumSelect} as the set of columns
+ * selected by you. A row i is covered by selected if:
+ * - For each cell where matrix[i][j] == 1, the column j is in selected.
+ * - Or, no cell in row i has a value of 1.
+ *
+ * Return the maximum number of rows that can be covered by a set of numSelect columns.
+ */
+
+/**
+ * @param {number[][]} matrix
+ * @param {number} numSelect
+ * @return {number}
+ */
+var maximumRows = function(matrix, numSelect) {
+  const rows = matrix.length;
+  const cols = matrix[0].length;
+  let result = 0;
+
+  backtrack(0, 0, 0);
+
+  return result;
+
+  function countCovered(selected) {
+    let covered = 0;
+    for (let i = 0; i < rows; i++) {
+      let isCovered = true;
+      for (let j = 0; j < cols; j++) {
+        if (matrix[i][j] === 1 && !(selected & (1 << j))) {
+          isCovered = false;
+          break;
+        }
+      }
+      if (isCovered) covered++;
+    }
+    return covered;
+  }
+
+  function backtrack(index, selected, count) {
+    if (count === numSelect) {
+      result = Math.max(result, countCovered(selected));
+      return;
+    }
+    if (index >= cols || cols - index + count < numSelect) return;
+
+    backtrack(index + 1, selected | (1 << index), count + 1);
+    backtrack(index + 1, selected, count);
+  }
+};
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/2399-check-distances-between-same-letters.js b/solutions/2399-check-distances-between-same-letters.js
new file mode 100644
index 00000000..7f977d1e
--- /dev/null
+++ b/solutions/2399-check-distances-between-same-letters.js
@@ -0,0 +1,44 @@
+/**
+ * 2399. Check Distances Between Same Letters
+ * https://leetcode.com/problems/check-distances-between-same-letters/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed string s consisting of only lowercase English letters, where each
+ * letter in s appears exactly twice. You are also given a 0-indexed integer array distance of
+ * length 26.
+ *
+ * Each letter in the alphabet is numbered from 0 to 25 (i.e. 'a' -> 0, 'b' -> 1,
+ * 'c' -> 2, ... , 'z' -> 25).
+ *
+ * In a well-spaced string, the number of letters between the two occurrences of the ith letter
+ * is distance[i]. If the ith letter does not appear in s, then distance[i] can be ignored.
+ *
+ * Return true if s is a well-spaced string, otherwise return false.
+ */
+
+/**
+ * @param {string} s
+ * @param {number[]} distance
+ * @return {boolean}
+ */
+var checkDistances = function(s, distance) {
+  const map = new Map();
+
+  for (let i = 0; i < s.length; i++) {
+    const char = s[i];
+    if (map.has(char)) {
+      map.get(char).push(i);
+    } else {
+      map.set(char, [i]);
+    }
+  }
+
+  for (const [char, positions] of map) {
+    const letterIndex = char.charCodeAt(0) - 'a'.charCodeAt(0);
+    if (positions[1] - positions[0] - 1 !== distance[letterIndex]) {
+      return false;
+    }
+  }
+
+  return true;
+};
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/2404-most-frequent-even-element.js b/solutions/2404-most-frequent-even-element.js
new file mode 100644
index 00000000..e5fcd0c6
--- /dev/null
+++ b/solutions/2404-most-frequent-even-element.js
@@ -0,0 +1,33 @@
+/**
+ * 2404. Most Frequent Even Element
+ * https://leetcode.com/problems/most-frequent-even-element/
+ * Difficulty: Easy
+ *
+ * Given an integer array nums, return the most frequent even element.
+ *
+ * If there is a tie, return the smallest one. If there is no such element, return -1.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var mostFrequentEven = function(nums) {
+  const map = new Map();
+  let maxCount = 0;
+  let result = -1;
+
+  for (const num of nums) {
+    if (num % 2 === 0) {
+      const count = (map.get(num) || 0) + 1;
+      map.set(num, count);
+      if (count > maxCount || (count === maxCount && num < result)) {
+        maxCount = count;
+        result = num;
+      }
+    }
+  }
+
+  return result;
+};
+
diff --git a/solutions/2405-optimal-partition-of-string.js b/solutions/2405-optimal-partition-of-string.js
new file mode 100644
index 00000000..eb2849bc
--- /dev/null
+++ b/solutions/2405-optimal-partition-of-string.js
@@ -0,0 +1,31 @@
+/**
+ * 2405. Optimal Partition of String
+ * https://leetcode.com/problems/optimal-partition-of-string/
+ * Difficulty: Medium
+ *
+ * Given a string s, partition the string into one or more substrings such that the characters
+ * in each substring are unique. That is, no letter appears in a single substring more than once.
+ *
+ * Return the minimum number of substrings in such a partition.
+ *
+ * Note that each character should belong to exactly one substring in a partition.
+ */
+
+/**
+ * @param {string} s
+ * @return {number}
+ */
+var partitionString = function(s) {
+  const set = new Set();
+  let result = 1;
+
+  for (const char of s) {
+    if (set.has(char)) {
+      set.clear();
+      result++;
+    }
+    set.add(char);
+  }
+
+  return result;
+};
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/2409-count-days-spent-together.js b/solutions/2409-count-days-spent-together.js
new file mode 100644
index 00000000..1047ab0b
--- /dev/null
+++ b/solutions/2409-count-days-spent-together.js
@@ -0,0 +1,48 @@
+/**
+ * 2409. Count Days Spent Together
+ * https://leetcode.com/problems/count-days-spent-together/
+ * Difficulty: Easy
+ *
+ * Alice and Bob are traveling to Rome for separate business meetings.
+ *
+ * You are given 4 strings arriveAlice, leaveAlice, arriveBob, and leaveBob. Alice will be in
+ * the city from the dates arriveAlice to leaveAlice (inclusive), while Bob will be in the city
+ * from the dates arriveBob to leaveBob (inclusive). Each will be a 5-character string in the
+ * format "MM-DD", corresponding to the month and day of the date.
+ *
+ * Return the total number of days that Alice and Bob are in Rome together.
+ *
+ * You can assume that all dates occur in the same calendar year, which is not a leap year. Note
+ * that the number of days per month can be represented as: [31, 28, 31, 30, 31, 30, 31, 31, 30,
+ * 31, 30, 31].
+ */
+
+/**
+ * @param {string} arriveAlice
+ * @param {string} leaveAlice
+ * @param {string} arriveBob
+ * @param {string} leaveBob
+ * @return {number}
+ */
+var countDaysTogether = function(arriveAlice, leaveAlice, arriveBob, leaveBob) {
+  const daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
+
+  function toDays(date) {
+    const [month, day] = date.split('-').map(Number);
+    let totalDays = 0;
+    for (let i = 0; i < month - 1; i++) {
+      totalDays += daysInMonth[i];
+    }
+    return totalDays + day;
+  }
+
+  const aliceStart = toDays(arriveAlice);
+  const aliceEnd = toDays(leaveAlice);
+  const bobStart = toDays(arriveBob);
+  const bobEnd = toDays(leaveBob);
+
+  const overlapStart = Math.max(aliceStart, bobStart);
+  const overlapEnd = Math.min(aliceEnd, bobEnd);
+
+  return Math.max(0, overlapEnd - overlapStart + 1);
+};
diff --git a/solutions/2410-maximum-matching-of-players-with-trainers.js b/solutions/2410-maximum-matching-of-players-with-trainers.js
new file mode 100644
index 00000000..885db445
--- /dev/null
+++ b/solutions/2410-maximum-matching-of-players-with-trainers.js
@@ -0,0 +1,35 @@
+/**
+ * 2410. Maximum Matching of Players With Trainers
+ * https://leetcode.com/problems/maximum-matching-of-players-with-trainers/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array players, where players[i] represents the ability of
+ * the ith player. You are also given a 0-indexed integer array trainers, where trainers[j]
+ * represents the training capacity of the jth trainer.
+ *
+ * The ith player can match with the jth trainer if the player's ability is less than or equal
+ * to the trainer's training capacity. Additionally, the ith player can be matched with at most
+ * one trainer, and the jth trainer can be matched with at most one player.
+ *
+ * Return the maximum number of matchings between players and trainers that satisfy these
+ * conditions.
+ */
+
+/**
+ * @param {number[]} players
+ * @param {number[]} trainers
+ * @return {number}
+ */
+var matchPlayersAndTrainers = function(players, trainers) {
+  players.sort((a, b) => a - b);
+  trainers.sort((a, b) => a - b);
+
+  let result = 0;
+  for (let j = 0; result < players.length && j < trainers.length; j++) {
+    if (trainers[j] >= players[result]) {
+      result++;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2411-smallest-subarrays-with-maximum-bitwise-or.js b/solutions/2411-smallest-subarrays-with-maximum-bitwise-or.js
new file mode 100644
index 00000000..784cf5d2
--- /dev/null
+++ b/solutions/2411-smallest-subarrays-with-maximum-bitwise-or.js
@@ -0,0 +1,46 @@
+/**
+ * 2411. Smallest Subarrays With Maximum Bitwise OR
+ * https://leetcode.com/problems/smallest-subarrays-with-maximum-bitwise-or/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed array nums of length n, consisting of non-negative integers. For
+ * each index i from 0 to n - 1, you must determine the size of the minimum sized non-empty
+ * subarray of nums starting at i (inclusive) that has the maximum possible bitwise OR.
+ * - In other words, let Bij be the bitwise OR of the subarray nums[i...j]. You need to find
+ *   the smallest subarray starting at i, such that bitwise OR of this subarray is equal to
+ *   max(Bik) where i <= k <= n - 1.
+ *
+ * The bitwise OR of an array is the bitwise OR of all the numbers in it.
+ *
+ * Return an integer array answer of size n where answer[i] is the length of the minimum sized
+ * subarray starting at i with maximum bitwise OR.
+ *
+ * A subarray is a contiguous non-empty sequence of elements within an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var smallestSubarrays = function(nums) {
+  const n = nums.length;
+  const result = new Array(n).fill(1);
+  const bitPositions = new Array(32).fill(0);
+
+  for (let i = n - 1; i >= 0; i--) {
+    for (let bit = 0; bit < 32; bit++) {
+      if (nums[i] & (1 << bit)) {
+        bitPositions[bit] = i;
+      }
+    }
+
+    let maxIndex = i;
+    for (let bit = 0; bit < 32; bit++) {
+      maxIndex = Math.max(maxIndex, bitPositions[bit]);
+    }
+
+    result[i] = maxIndex - i + 1;
+  }
+
+  return result;
+};
diff --git a/solutions/2412-minimum-money-required-before-transactions.js b/solutions/2412-minimum-money-required-before-transactions.js
new file mode 100644
index 00000000..240ca6ca
--- /dev/null
+++ b/solutions/2412-minimum-money-required-before-transactions.js
@@ -0,0 +1,36 @@
+/**
+ * 2412. Minimum Money Required Before Transactions
+ * https://leetcode.com/problems/minimum-money-required-before-transactions/
+ * Difficulty: Hard
+ *
+ * You are given a 0-indexed 2D integer array transactions, where
+ * transactions[i] = [costi, cashbacki].
+ *
+ * The array describes transactions, where each transaction must be completed exactly once
+ * in some order. At any given moment, you have a certain amount of money. In order to
+ * complete transaction i, money >= costi must hold true. After performing a transaction,
+ * money becomes money - costi + cashbacki.
+ *
+ * Return the minimum amount of money required before any transaction so that all of the
+ * transactions can be completed regardless of the order of the transactions.
+ */
+
+/**
+ * @param {number[][]} transactions
+ * @return {number}
+ */
+var minimumMoney = function(transactions) {
+  let totalLoss = 0;
+  let maxCost = 0;
+
+  for (const [cost, cashback] of transactions) {
+    if (cost > cashback) {
+      totalLoss += cost - cashback;
+      maxCost = Math.max(maxCost, cashback);
+    } else {
+      maxCost = Math.max(maxCost, cost);
+    }
+  }
+
+  return totalLoss + maxCost;
+};
diff --git a/solutions/2414-length-of-the-longest-alphabetical-continuous-substring.js b/solutions/2414-length-of-the-longest-alphabetical-continuous-substring.js
new file mode 100644
index 00000000..afb44c82
--- /dev/null
+++ b/solutions/2414-length-of-the-longest-alphabetical-continuous-substring.js
@@ -0,0 +1,32 @@
+/**
+ * 2414. Length of the Longest Alphabetical Continuous Substring
+ * https://leetcode.com/problems/length-of-the-longest-alphabetical-continuous-substring/
+ * Difficulty: Medium
+ *
+ * An alphabetical continuous string is a string consisting of consecutive letters in the alphabet.
+ * In other words, it is any substring of the string "abcdefghijklmnopqrstuvwxyz".
+ * - For example, "abc" is an alphabetical continuous string, while "acb" and "za" are not.
+ *
+ * Given a string s consisting of lowercase letters only, return the length of the longest
+ * alphabetical continuous substring.
+ */
+
+/**
+ * @param {string} s
+ * @return {number}
+ */
+var longestContinuousSubstring = function(s) {
+  let result = 1;
+  let currentLength = 1;
+
+  for (let i = 1; i < s.length; i++) {
+    if (s.charCodeAt(i) - s.charCodeAt(i - 1) === 1) {
+      currentLength++;
+      result = Math.max(result, currentLength);
+    } else {
+      currentLength = 1;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2415-reverse-odd-levels-of-binary-tree.js b/solutions/2415-reverse-odd-levels-of-binary-tree.js
new file mode 100644
index 00000000..9c70383b
--- /dev/null
+++ b/solutions/2415-reverse-odd-levels-of-binary-tree.js
@@ -0,0 +1,51 @@
+/**
+ * 2415. Reverse Odd Levels of Binary Tree
+ * https://leetcode.com/problems/reverse-odd-levels-of-binary-tree/
+ * Difficulty: Medium
+ *
+ * Given the root of a perfect binary tree, reverse the node values at each odd level of the tree.
+ * - For example, suppose the node values at level 3 are [2,1,3,4,7,11,29,18], then it should
+ *   become [18,29,11,7,4,3,1,2].
+ *
+ * Return the root of the reversed tree.
+ *
+ * A binary tree is perfect if all parent nodes have two children and all leaves are on the same
+ * level.
+ *
+ * The level of a node is the number of edges along the path between it and the root 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 {TreeNode}
+ */
+var reverseOddLevels = function(root) {
+  reverseLevel([root], 0);
+  return root;
+
+  function reverseLevel(nodes, level) {
+    if (!nodes.length) return;
+
+    if (level % 2 === 1) {
+      for (let i = 0, j = nodes.length - 1; i < j; i++, j--) {
+        [nodes[i].val, nodes[j].val] = [nodes[j].val, nodes[i].val];
+      }
+    }
+
+    const nextLevel = [];
+    for (const node of nodes) {
+      if (node.left) nextLevel.push(node.left);
+      if (node.right) nextLevel.push(node.right);
+    }
+
+    reverseLevel(nextLevel, level + 1);
+  }
+};
diff --git a/solutions/2416-sum-of-prefix-scores-of-strings.js b/solutions/2416-sum-of-prefix-scores-of-strings.js
new file mode 100644
index 00000000..45d3a184
--- /dev/null
+++ b/solutions/2416-sum-of-prefix-scores-of-strings.js
@@ -0,0 +1,56 @@
+/**
+ * 2416. Sum of Prefix Scores of Strings
+ * https://leetcode.com/problems/sum-of-prefix-scores-of-strings/
+ * Difficulty: Hard
+ *
+ * You are given an array words of size n consisting of non-empty strings.
+ *
+ * We define the score of a string term as the number of strings words[i] such that term is
+ * a prefix of words[i].
+ * - For example, if words = ["a", "ab", "abc", "cab"], then the score of "ab" is 2, since
+ *   "ab" is a prefix of both "ab" and "abc".
+ *
+ * Return an array answer of size n where answer[i] is the sum of scores of every non-empty
+ * prefix of words[i].
+ *
+ * Note that a string is considered as a prefix of itself.
+ */
+
+/**
+ * @param {string[]} words
+ * @return {number[]}
+ */
+var sumPrefixScores = function(words) {
+  class TrieNode {
+    constructor() {
+      this.children = new Map();
+      this.count = 0;
+    }
+  }
+
+  const root = new TrieNode();
+
+  for (const word of words) {
+    let node = root;
+    for (const char of word) {
+      if (!node.children.has(char)) {
+        node.children.set(char, new TrieNode());
+      }
+      node = node.children.get(char);
+      node.count++;
+    }
+  }
+
+  const result = [];
+  for (const word of words) {
+    let node = root;
+    let score = 0;
+    for (const char of word) {
+      node = node.children.get(char);
+      score += node.count;
+    }
+    result.push(score);
+  }
+
+  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/2418-sort-the-people.js b/solutions/2418-sort-the-people.js
new file mode 100644
index 00000000..c0477a6a
--- /dev/null
+++ b/solutions/2418-sort-the-people.js
@@ -0,0 +1,23 @@
+/**
+ * 2418. Sort the People
+ * https://leetcode.com/problems/sort-the-people/
+ * Difficulty: Easy
+ *
+ * You are given an array of strings names, and an array heights that consists of distinct
+ * positive integers. Both arrays are of length n.
+ *
+ * For each index i, names[i] and heights[i] denote the name and height of the ith person.
+ *
+ * Return names sorted in descending order by the people's heights.
+ */
+
+/**
+ * @param {string[]} names
+ * @param {number[]} heights
+ * @return {string[]}
+ */
+var sortPeople = function(names, heights) {
+  const people = names.map((name, index) => ({name, height: heights[index]}));
+  people.sort((a, b) => b.height - a.height);
+  return people.map(person => person.name);
+};
diff --git a/solutions/2419-longest-subarray-with-maximum-bitwise-and.js b/solutions/2419-longest-subarray-with-maximum-bitwise-and.js
new file mode 100644
index 00000000..c6a26711
--- /dev/null
+++ b/solutions/2419-longest-subarray-with-maximum-bitwise-and.js
@@ -0,0 +1,38 @@
+/**
+ * 2419. Longest Subarray With Maximum Bitwise AND
+ * https://leetcode.com/problems/longest-subarray-with-maximum-bitwise-and/
+ * Difficulty: Medium
+ *
+ * You are given an integer array nums of size n.
+ *
+ * Consider a non-empty subarray from nums that has the maximum possible bitwise AND.
+ * - In other words, let k be the maximum value of the bitwise AND of any subarray of nums.
+ *   Then, only subarrays with a bitwise AND equal to k should be considered.
+ *
+ * Return the length of the longest such subarray.
+ *
+ * The bitwise AND of an array is the bitwise AND of all the numbers in it.
+ *
+ * A subarray is a contiguous sequence of elements within an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var longestSubarray = function(nums) {
+  const maxValue = Math.max(...nums);
+  let result = 0;
+  let currentLength = 0;
+
+  for (const num of nums) {
+    if (num === maxValue) {
+      currentLength++;
+      result = Math.max(result, currentLength);
+    } else {
+      currentLength = 0;
+    }
+  }
+
+  return 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/2421-number-of-good-paths.js b/solutions/2421-number-of-good-paths.js
new file mode 100644
index 00000000..c0f7d606
--- /dev/null
+++ b/solutions/2421-number-of-good-paths.js
@@ -0,0 +1,86 @@
+/**
+ * 2421. Number of Good Paths
+ * https://leetcode.com/problems/number-of-good-paths/
+ * Difficulty: Hard
+ *
+ * There is a tree (i.e. a connected, undirected graph with no cycles) consisting of n nodes
+ * numbered from 0 to n - 1 and exactly n - 1 edges.
+ *
+ * You are given a 0-indexed integer array vals of length n where vals[i] denotes the value
+ * of the ith node. You are also given a 2D integer array edges where edges[i] = [ai, bi]
+ * denotes that there exists an undirected edge connecting nodes ai and bi.
+ *
+ * A good path is a simple path that satisfies the following conditions:
+ * 1. The starting node and the ending node have the same value.
+ * 2. All nodes between the starting node and the ending node have values less than or equal
+ *    to the starting node (i.e. the starting node's value should be the maximum value along
+ *    the path).
+ *
+ * Return the number of distinct good paths.
+ *
+ * Note that a path and its reverse are counted as the same path. For example, 0 -> 1 is
+ * considered to be the same as 1 -> 0. A single node is also considered as a valid path.
+ */
+
+/**
+ * @param {number[]} vals
+ * @param {number[][]} edges
+ * @return {number}
+ */
+var numberOfGoodPaths = function(vals, edges) {
+  const n = vals.length;
+  const graph = Array.from({length: n}, () => []);
+  for (const [u, v] of edges) {
+    graph[u].push(v);
+    graph[v].push(u);
+  }
+
+  const parent = new Array(n).fill(-1);
+  const rank = new Array(n).fill(0);
+  function find(x) {
+    if (parent[x] === -1) return x;
+    return parent[x] = find(parent[x]);
+  }
+
+  function union(x, y) {
+    let px = find(x);
+    let py = find(y);
+    if (px === py) return;
+    if (rank[px] < rank[py]) [px, py] = [py, px];
+    parent[py] = px;
+    if (rank[px] === rank[py]) rank[px]++;
+  }
+
+  const valueGroups = new Map();
+  for (let i = 0; i < n; i++) {
+    if (!valueGroups.has(vals[i])) {
+      valueGroups.set(vals[i], []);
+    }
+    valueGroups.get(vals[i]).push(i);
+  }
+
+  let result = 0;
+  for (const value of [...valueGroups.keys()].sort((a, b) => a - b)) {
+    const nodes = valueGroups.get(value);
+
+    for (const node of nodes) {
+      for (const neighbor of graph[node]) {
+        if (vals[neighbor] <= value) {
+          union(node, neighbor);
+        }
+      }
+    }
+
+    const groupCount = new Map();
+    for (const node of nodes) {
+      const root = find(node);
+      groupCount.set(root, (groupCount.get(root) || 0) + 1);
+    }
+
+    for (const count of groupCount.values()) {
+      result += (count * (count + 1)) / 2;
+    }
+  }
+
+  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/2426-number-of-pairs-satisfying-inequality.js b/solutions/2426-number-of-pairs-satisfying-inequality.js
new file mode 100644
index 00000000..e24957fd
--- /dev/null
+++ b/solutions/2426-number-of-pairs-satisfying-inequality.js
@@ -0,0 +1,66 @@
+/**
+ * 2426. Number of Pairs Satisfying Inequality
+ * https://leetcode.com/problems/number-of-pairs-satisfying-inequality/
+ * Difficulty: Hard
+ *
+ * You are given two 0-indexed integer arrays nums1 and nums2, each of size n, and an
+ * integer diff. Find the number of pairs (i, j) such that:
+ * - 0 <= i < j <= n - 1 and
+ * - nums1[i] - nums1[j] <= nums2[i] - nums2[j] + diff.
+ *
+ * Return the number of pairs that satisfy the conditions.
+ */
+
+/**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @param {number} diff
+ * @return {number}
+ */
+var numberOfPairs = function(nums1, nums2, diff) {
+  const n = nums1.length;
+  const differences = new Array(n);
+  for (let i = 0; i < n; i++) {
+    differences[i] = nums1[i] - nums2[i];
+  }
+  let result = 0;
+  mergeSort(0, n);
+  return result;
+
+  function mergeSort(left, right) {
+    if (right - left <= 1) return;
+
+    const mid = Math.floor((left + right) / 2);
+    mergeSort(left, mid);
+    mergeSort(mid, right);
+
+    let i = left;
+    let j = mid;
+    while (i < mid && j < right) {
+      if (differences[i] <= differences[j] + diff) {
+        result += right - j;
+        i++;
+      } else {
+        j++;
+      }
+    }
+
+    const sorted = new Array(right - left);
+    let k = 0;
+    i = left;
+    j = mid;
+    while (i < mid && j < right) {
+      if (differences[i] <= differences[j]) {
+        sorted[k++] = differences[i++];
+      } else {
+        sorted[k++] = differences[j++];
+      }
+    }
+    while (i < mid) sorted[k++] = differences[i++];
+    while (j < right) sorted[k++] = differences[j++];
+
+    for (let p = 0; p < sorted.length; p++) {
+      differences[left + p] = sorted[p];
+    }
+  }
+};
diff --git a/solutions/2428-maximum-sum-of-an-hourglass.js b/solutions/2428-maximum-sum-of-an-hourglass.js
new file mode 100644
index 00000000..f6cb5a39
--- /dev/null
+++ b/solutions/2428-maximum-sum-of-an-hourglass.js
@@ -0,0 +1,33 @@
+/**
+ * 2428. Maximum Sum of an Hourglass
+ * https://leetcode.com/problems/maximum-sum-of-an-hourglass/
+ * Difficulty: Medium
+ *
+ * You are given an m x n integer matrix grid.
+ *
+ * We define an hourglass as a part of the matrix with the following form.
+ *
+ * Return the maximum sum of the elements of an hourglass.
+ *
+ * Note that an hourglass cannot be rotated and must be entirely contained within the matrix.
+ */
+
+/**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+var maxSum = function(grid) {
+  let result = 0;
+  const rows = grid.length;
+  const cols = grid[0].length;
+
+  for (let i = 0; i <= rows - 3; i++) {
+    for (let j = 0; j <= cols - 3; j++) {
+      const hourglassSum = grid[i][j] + grid[i][j+1] + grid[i][j+2] + grid[i+1][j+1]
+        + grid[i+2][j] + grid[i+2][j+1] + grid[i+2][j+2];
+      result = Math.max(result, hourglassSum);
+    }
+  }
+
+  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/2432-the-employee-that-worked-on-the-longest-task.js b/solutions/2432-the-employee-that-worked-on-the-longest-task.js
new file mode 100644
index 00000000..acab1a87
--- /dev/null
+++ b/solutions/2432-the-employee-that-worked-on-the-longest-task.js
@@ -0,0 +1,40 @@
+/**
+ * 2432. The Employee That Worked on the Longest Task
+ * https://leetcode.com/problems/the-employee-that-worked-on-the-longest-task/
+ * Difficulty: Easy
+ *
+ * There are n employees, each with a unique id from 0 to n - 1.
+ *
+ * You are given a 2D integer array logs where logs[i] = [idi, leaveTimei] where:
+ * - idi is the id of the employee that worked on the ith task, and
+ * - leaveTimei is the time at which the employee finished the ith task. All the values
+ *   leaveTimei are unique.
+ *
+ * Note that the ith task starts the moment right after the (i - 1)th task ends, and the 0th
+ * task starts at time 0.
+ *
+ * Return the id of the employee that worked the task with the longest time. If there is a tie
+ * between two or more employees, return the smallest id among them.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[][]} logs
+ * @return {number}
+ */
+var hardestWorker = function(n, logs) {
+  let maxDuration = 0;
+  let result = n;
+  let startTime = 0;
+
+  for (const [employeeId, endTime] of logs) {
+    const duration = endTime - startTime;
+    if (duration > maxDuration || (duration === maxDuration && employeeId < result)) {
+      maxDuration = duration;
+      result = employeeId;
+    }
+    startTime = endTime;
+  }
+
+  return result;
+};
diff --git a/solutions/2433-find-the-original-array-of-prefix-xor.js b/solutions/2433-find-the-original-array-of-prefix-xor.js
new file mode 100644
index 00000000..0f41ebeb
--- /dev/null
+++ b/solutions/2433-find-the-original-array-of-prefix-xor.js
@@ -0,0 +1,28 @@
+/**
+ * 2433. Find The Original Array of Prefix Xor
+ * https://leetcode.com/problems/find-the-original-array-of-prefix-xor/
+ * Difficulty: Medium
+ *
+ * You are given an integer array pref of size n. Find and return the array arr of size
+ * n that satisfies:
+ * - pref[i] = arr[0] ^ arr[1] ^ ... ^ arr[i].
+ *
+ * Note that ^ denotes the bitwise-xor operation.
+ *
+ * It can be proven that the answer is unique.
+ */
+
+/**
+ * @param {number[]} pref
+ * @return {number[]}
+ */
+var findArray = function(pref) {
+  const result = new Array(pref.length);
+  result[0] = pref[0];
+
+  for (let i = 1; i < pref.length; i++) {
+    result[i] = pref[i] ^ pref[i - 1];
+  }
+
+  return result;
+};
diff --git a/solutions/2434-using-a-robot-to-print-the-lexicographically-smallest-string.js b/solutions/2434-using-a-robot-to-print-the-lexicographically-smallest-string.js
new file mode 100644
index 00000000..430e0fa6
--- /dev/null
+++ b/solutions/2434-using-a-robot-to-print-the-lexicographically-smallest-string.js
@@ -0,0 +1,49 @@
+/**
+ * 2434. Using a Robot to Print the Lexicographically Smallest String
+ * https://leetcode.com/problems/using-a-robot-to-print-the-lexicographically-smallest-string/
+ * Difficulty: Medium
+ *
+ * You are given a string s and a robot that currently holds an empty string t. Apply one of the
+ * following operations until s and t are both empty:
+ * - Remove the first character of a string s and give it to the robot. The robot will append
+ *   this character to the string t.
+ * - Remove the last character of a string t and give it to the robot. The robot will write
+ *   this character on paper.
+ *
+ * Return the lexicographically smallest string that can be written on the paper.
+ */
+
+/**
+ * @param {string} s
+ * @return {string}
+ */
+var robotWithString = function(s) {
+  const charCount = Array(26).fill(0);
+  for (const char of s) {
+    charCount[char.charCodeAt(0) - 97]++;
+  }
+
+  const stack = [];
+  let minCharIndex = 0;
+  let result = '';
+
+  for (const char of s) {
+    stack.push(char);
+    charCount[char.charCodeAt(0) - 97]--;
+
+    while (minCharIndex < 26 && charCount[minCharIndex] === 0) {
+      minCharIndex++;
+    }
+
+    while (stack.length
+      && (minCharIndex === 26 || stack[stack.length - 1].charCodeAt(0) - 97 <= minCharIndex)) {
+      result += stack.pop();
+    }
+  }
+
+  while (stack.length) {
+    result += stack.pop();
+  }
+
+  return result;
+};
diff --git a/solutions/2435-paths-in-matrix-whose-sum-is-divisible-by-k.js b/solutions/2435-paths-in-matrix-whose-sum-is-divisible-by-k.js
new file mode 100644
index 00000000..741526c7
--- /dev/null
+++ b/solutions/2435-paths-in-matrix-whose-sum-is-divisible-by-k.js
@@ -0,0 +1,45 @@
+/**
+ * 2435. Paths in Matrix Whose Sum Is Divisible by K
+ * https://leetcode.com/problems/paths-in-matrix-whose-sum-is-divisible-by-k/
+ * Difficulty: Hard
+ *
+ * You are given a 0-indexed m x n integer matrix grid and an integer k. You are currently at
+ * position (0, 0) and you want to reach position (m - 1, n - 1) moving only down or right.
+ *
+ * Return the number of paths where the sum of the elements on the path is divisible by k.
+ * Since the answer may be very large, return it modulo 109 + 7.
+ */
+
+/**
+ * @param {number[][]} grid
+ * @param {number} k
+ * @return {number}
+ */
+var numberOfPaths = function(grid, k) {
+  const rows = grid.length;
+  const cols = grid[0].length;
+  const modulo = 1e9 + 7;
+  const dp = Array.from({ length: rows }, () => {
+    return Array.from({ length: cols }, () => Array(k).fill(0));
+  });
+
+  dp[0][0][grid[0][0] % k] = 1;
+
+  for (let row = 0; row < rows; row++) {
+    for (let col = 0; col < cols; col++) {
+      const currentValue = grid[row][col] % k;
+      for (let sum = 0; sum < k; sum++) {
+        if (row > 0) {
+          const prevSum = (sum - currentValue + k) % k;
+          dp[row][col][sum] = (dp[row][col][sum] + dp[row - 1][col][prevSum]) % modulo;
+        }
+        if (col > 0) {
+          const prevSum = (sum - currentValue + k) % k;
+          dp[row][col][sum] = (dp[row][col][sum] + dp[row][col - 1][prevSum]) % modulo;
+        }
+      }
+    }
+  }
+
+  return dp[rows - 1][cols - 1][0];
+};
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/2437-number-of-valid-clock-times.js b/solutions/2437-number-of-valid-clock-times.js
new file mode 100644
index 00000000..8b4d26bb
--- /dev/null
+++ b/solutions/2437-number-of-valid-clock-times.js
@@ -0,0 +1,42 @@
+/**
+ * 2437. Number of Valid Clock Times
+ * https://leetcode.com/problems/number-of-valid-clock-times/
+ * Difficulty: Easy
+ *
+ * You are given a string of length 5 called time, representing the current time on a digital
+ * clock in the format "hh:mm". The earliest possible time is "00:00" and the latest possible
+ * time is "23:59".
+ *
+ * In the string time, the digits represented by the ? symbol are unknown, and must be replaced
+ * with a digit from 0 to 9.
+ *
+ * Return an integer answer, the number of valid clock times that can be created by replacing
+ * every ? with a digit from 0 to 9.
+ */
+
+/**
+ * @param {string} time
+ * @return {number}
+ */
+var countTime = function(time) {
+  let hourChoices = 1;
+  let minuteChoices = 1;
+
+  if (time[0] === '?' && time[1] === '?') {
+    hourChoices = 24;
+  } else if (time[0] === '?') {
+    hourChoices = time[1] <= '3' ? 3 : 2;
+  } else if (time[1] === '?') {
+    hourChoices = time[0] === '2' ? 4 : 10;
+  }
+
+  if (time[3] === '?' && time[4] === '?') {
+    minuteChoices = 60;
+  } else if (time[3] === '?') {
+    minuteChoices = 6;
+  } else if (time[4] === '?') {
+    minuteChoices = 10;
+  }
+
+  return hourChoices * minuteChoices;
+};
diff --git a/solutions/2438-range-product-queries-of-powers.js b/solutions/2438-range-product-queries-of-powers.js
new file mode 100644
index 00000000..ebebead8
--- /dev/null
+++ b/solutions/2438-range-product-queries-of-powers.js
@@ -0,0 +1,45 @@
+/**
+ * 2438. Range Product Queries of Powers
+ * https://leetcode.com/problems/range-product-queries-of-powers/
+ * Difficulty: Medium
+ *
+ * Given a positive integer n, there exists a 0-indexed array called powers, composed of the
+ * minimum number of powers of 2 that sum to n. The array is sorted in non-decreasing order,
+ * and there is only one way to form the array.
+ *
+ * You are also given a 0-indexed 2D integer array queries, where queries[i] = [lefti, righti].
+ * Each queries[i] represents a query where you have to find the product of all powers[j] with
+ * lefti <= j <= righti.
+ *
+ * Return an array answers, equal in length to queries, where answers[i] is the answer to the
+ * ith query. Since the answer to the ith query may be too large, each answers[i] should be
+ * returned modulo 109 + 7.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[][]} queries
+ * @return {number[]}
+ */
+var productQueries = function(n, queries) {
+  const modulo = 1e9 + 7;
+  const powers = [];
+  while (n > 0) {
+    const power = Math.floor(Math.log2(n));
+    powers.push(1 << power);
+    n -= 1 << power;
+  }
+  powers.reverse();
+
+  const result = new Array(queries.length);
+  for (let i = 0; i < queries.length; i++) {
+    const [start, end] = queries[i];
+    let product = 1;
+    for (let j = start; j <= end; j++) {
+      product = (product * powers[j]) % modulo;
+    }
+    result[i] = product;
+  }
+
+  return result;
+};
diff --git a/solutions/2439-minimize-maximum-of-array.js b/solutions/2439-minimize-maximum-of-array.js
new file mode 100644
index 00000000..5d147f37
--- /dev/null
+++ b/solutions/2439-minimize-maximum-of-array.js
@@ -0,0 +1,53 @@
+/**
+ * 2439. Minimize Maximum of Array
+ * https://leetcode.com/problems/minimize-maximum-of-array/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed array nums comprising of n non-negative integers.
+ *
+ * In one operation, you must:
+ * - Choose an integer i such that 1 <= i < n and nums[i] > 0.
+ * - Decrease nums[i] by 1.
+ * - Increase nums[i - 1] by 1.
+ *
+ * Return the minimum possible value of the maximum integer of nums after performing
+ * any number of operations.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var minimizeArrayValue = function(nums) {
+  let left = 0;
+  let right = Math.max(...nums);
+  let result = right;
+
+  while (left <= right) {
+    const mid = Math.floor((left + right) / 2);
+    let carry = 0;
+    let valid = true;
+
+    for (let i = nums.length - 1; i >= 0; i--) {
+      const total = nums[i] + carry;
+      if (total > mid) {
+        if (i === 0) {
+          valid = false;
+          break;
+        }
+        carry = total - mid;
+      } else {
+        carry = 0;
+      }
+    }
+
+    if (valid) {
+      result = mid;
+      right = mid - 1;
+    } else {
+      left = mid + 1;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2440-create-components-with-same-value.js b/solutions/2440-create-components-with-same-value.js
new file mode 100644
index 00000000..d0a6391f
--- /dev/null
+++ b/solutions/2440-create-components-with-same-value.js
@@ -0,0 +1,64 @@
+/**
+ * 2440. Create Components With Same Value
+ * https://leetcode.com/problems/create-components-with-same-value/
+ * Difficulty: Hard
+ *
+ * There is an undirected tree with n nodes labeled from 0 to n - 1.
+ *
+ * You are given a 0-indexed integer array nums of length n where nums[i] represents the value
+ * of the ith node. You are also 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 allowed to delete some edges, splitting the tree into multiple connected components.
+ * Let the value of a component be the sum of all nums[i] for which node i is in the component.
+ *
+ * Return the maximum number of edges you can delete, such that every connected component in
+ * the tree has the same value.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number[][]} edges
+ * @return {number}
+ */
+var componentValue = function(nums, edges) {
+  const n = nums.length;
+  const graph = Array.from({ length: n }, () => []);
+  const totalSum = nums.reduce((sum, val) => sum + val, 0);
+
+  for (const [u, v] of edges) {
+    graph[u].push(v);
+    graph[v].push(u);
+  }
+
+  for (let i = n; i >= 1; i--) {
+    if (totalSum % i === 0) {
+      const target = totalSum / i;
+      const [, components] = countNodes(0, -1, target);
+      if (components === i) {
+        return i - 1;
+      }
+    }
+  }
+
+  return 0;
+
+  function countNodes(node, parent, target) {
+    let sum = nums[node];
+    let components = 0;
+
+    for (const neighbor of graph[node]) {
+      if (neighbor !== parent) {
+        const [childSum, childComponents] = countNodes(neighbor, node, target);
+        sum += childSum;
+        components += childComponents;
+      }
+    }
+
+    if (sum === target) {
+      return [0, components + 1];
+    }
+
+    return [sum, components];
+  }
+};
diff --git a/solutions/2441-largest-positive-integer-that-exists-with-its-negative.js b/solutions/2441-largest-positive-integer-that-exists-with-its-negative.js
new file mode 100644
index 00000000..e80f0ac9
--- /dev/null
+++ b/solutions/2441-largest-positive-integer-that-exists-with-its-negative.js
@@ -0,0 +1,28 @@
+/**
+ * 2441. Largest Positive Integer That Exists With Its Negative
+ * https://leetcode.com/problems/largest-positive-integer-that-exists-with-its-negative/
+ * Difficulty: Easy
+ *
+ * Given an integer array nums that does not contain any zeros, find the largest positive
+ * integer k such that -k also exists in the array.
+ *
+ * Return the positive integer k. If there is no such integer, return -1.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var findMaxK = function(nums) {
+  const set = new Set();
+  let result = -1;
+
+  for (const num of nums) {
+    if (set.has(-num)) {
+      result = Math.max(result, Math.abs(num));
+    }
+    set.add(num);
+  }
+
+  return result;
+};
diff --git a/solutions/2442-count-number-of-distinct-integers-after-reverse-operations.js b/solutions/2442-count-number-of-distinct-integers-after-reverse-operations.js
new file mode 100644
index 00000000..d1cc0abd
--- /dev/null
+++ b/solutions/2442-count-number-of-distinct-integers-after-reverse-operations.js
@@ -0,0 +1,32 @@
+/**
+ * 2442. Count Number of Distinct Integers After Reverse Operations
+ * https://leetcode.com/problems/count-number-of-distinct-integers-after-reverse-operations/
+ * Difficulty: Medium
+ *
+ * You are given an array nums consisting of positive integers.
+ *
+ * You have to take each integer in the array, reverse its digits, and add it to the end of the
+ * array. You should apply this operation to the original integers in nums.
+ *
+ * Return the number of distinct integers in the final array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var countDistinctIntegers = function(nums) {
+  const set = new Set(nums);
+
+  for (const num of nums) {
+    let reversed = 0;
+    let temp = num;
+    while (temp > 0) {
+      reversed = reversed * 10 + temp % 10;
+      temp = Math.floor(temp / 10);
+    }
+    set.add(reversed);
+  }
+
+  return set.size;
+};
diff --git a/solutions/2443-sum-of-number-and-its-reverse.js b/solutions/2443-sum-of-number-and-its-reverse.js
new file mode 100644
index 00000000..7e17944a
--- /dev/null
+++ b/solutions/2443-sum-of-number-and-its-reverse.js
@@ -0,0 +1,28 @@
+/**
+ * 2443. Sum of Number and Its Reverse
+ * https://leetcode.com/problems/sum-of-number-and-its-reverse/
+ * Difficulty: Medium
+ *
+ * Given a non-negative integer num, return true if num can be expressed as the sum of any
+ * non-negative integer and its reverse, or false otherwise.
+ */
+
+/**
+ * @param {number} num
+ * @return {boolean}
+ */
+var sumOfNumberAndReverse = function(num) {
+  for (let i = 0; i <= num; i++) {
+    let reversed = 0;
+    let temp = i;
+    while (temp > 0) {
+      reversed = reversed * 10 + temp % 10;
+      temp = Math.floor(temp / 10);
+    }
+    if (i + reversed === num) {
+      return true;
+    }
+  }
+
+  return false;
+};
diff --git a/solutions/2444-count-subarrays-with-fixed-bounds.js b/solutions/2444-count-subarrays-with-fixed-bounds.js
new file mode 100644
index 00000000..e672554c
--- /dev/null
+++ b/solutions/2444-count-subarrays-with-fixed-bounds.js
@@ -0,0 +1,39 @@
+/**
+ * 2444. Count Subarrays With Fixed Bounds
+ * https://leetcode.com/problems/count-subarrays-with-fixed-bounds/
+ * Difficulty: Hard
+ *
+ * You are given an integer array nums and two integers minK and maxK.
+ *
+ * A fixed-bound subarray of nums is a subarray that satisfies the following conditions:
+ * - The minimum value in the subarray is equal to minK.
+ * - The maximum value in the subarray is equal to maxK.
+ * - Return the number of fixed-bound subarrays.
+ *
+ * A subarray is a contiguous part of an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} minK
+ * @param {number} maxK
+ * @return {number}
+ */
+var countSubarrays = function(nums, minK, maxK) {
+  let result = 0;
+
+  for (let i = 0, minIndex = -1, maxIndex = -1, invalidIndex = -1; i < nums.length; i++) {
+    if (nums[i] < minK || nums[i] > maxK) {
+      invalidIndex = i;
+    }
+    if (nums[i] === minK) {
+      minIndex = i;
+    }
+    if (nums[i] === maxK) {
+      maxIndex = i;
+    }
+    result += Math.max(0, Math.min(minIndex, maxIndex) - invalidIndex);
+  }
+
+  return result;
+};
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/2446-determine-if-two-events-have-conflict.js b/solutions/2446-determine-if-two-events-have-conflict.js
new file mode 100644
index 00000000..3a70a834
--- /dev/null
+++ b/solutions/2446-determine-if-two-events-have-conflict.js
@@ -0,0 +1,28 @@
+/**
+ * 2446. Determine if Two Events Have Conflict
+ * https://leetcode.com/problems/determine-if-two-events-have-conflict/
+ * Difficulty: Easy
+ *
+ * You are given two arrays of strings that represent two inclusive events that happened on the
+ * same day, event1 and event2, where:
+ * - event1 = [startTime1, endTime1] and
+ * - event2 = [startTime2, endTime2].
+ *
+ * Event times are valid 24 hours format in the form of HH:MM.
+ *
+ * A conflict happens when two events have some non-empty intersection (i.e., some moment is common
+ * to both events).
+ *
+ * Return true if there is a conflict between two events. Otherwise, return false.
+ */
+
+/**
+ * @param {string[]} event1
+ * @param {string[]} event2
+ * @return {boolean}
+ */
+var haveConflict = function(event1, event2) {
+  const [start1, end1] = event1;
+  const [start2, end2] = event2;
+  return start1 <= end2 && start2 <= end1;
+};
diff --git a/solutions/2447-number-of-subarrays-with-gcd-equal-to-k.js b/solutions/2447-number-of-subarrays-with-gcd-equal-to-k.js
new file mode 100644
index 00000000..efc4339c
--- /dev/null
+++ b/solutions/2447-number-of-subarrays-with-gcd-equal-to-k.js
@@ -0,0 +1,41 @@
+/**
+ * 2447. Number of Subarrays With GCD Equal to K
+ * https://leetcode.com/problems/number-of-subarrays-with-gcd-equal-to-k/
+ * Difficulty: Medium
+ *
+ * Given an integer array nums and an integer k, return the number of subarrays of nums where
+ * the greatest common divisor of the subarray's elements is k.
+ *
+ * A subarray is a contiguous non-empty sequence of elements within an array.
+ *
+ * The greatest common divisor of an array is the largest integer that evenly divides all the
+ * array elements.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var subarrayGCD = function(nums, k) {
+  let result = 0;
+  for (let start = 0; start < nums.length; start++) {
+    let currentGCD = nums[start];
+    for (let end = start; end < nums.length; end++) {
+      currentGCD = gcd(currentGCD, nums[end]);
+      if (currentGCD === k) {
+        result++;
+      }
+    }
+  }
+
+  return result;
+
+  function gcd(a, b) {
+    while (b) {
+      a %= b;
+      [a, b] = [b, a];
+    }
+    return a;
+  }
+};
diff --git a/solutions/2448-minimum-cost-to-make-array-equal.js b/solutions/2448-minimum-cost-to-make-array-equal.js
new file mode 100644
index 00000000..1bf9d6fd
--- /dev/null
+++ b/solutions/2448-minimum-cost-to-make-array-equal.js
@@ -0,0 +1,45 @@
+/**
+ * 2448. Minimum Cost to Make Array Equal
+ * https://leetcode.com/problems/minimum-cost-to-make-array-equal/
+ * Difficulty: Hard
+ *
+ * You are given two 0-indexed arrays nums and cost consisting each of n positive integers.
+ *
+ * You can do the following operation any number of times:
+ * - Increase or decrease any element of the array nums by 1.
+ *
+ * The cost of doing one operation on the ith element is cost[i].
+ *
+ * Return the minimum total cost such that all the elements of the array nums become equal.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number[]} cost
+ * @return {number}
+ */
+var minCost = function(nums, cost) {
+  const pairs = nums.map((num, i) => [num, cost[i]]).sort((a, b) => a[0] - b[0]);
+  const n = nums.length;
+  const prefixSum = Array(n).fill(0);
+  const prefixCost = Array(n).fill(0);
+
+  prefixSum[0] = pairs[0][0] * pairs[0][1];
+  prefixCost[0] = pairs[0][1];
+
+  for (let i = 1; i < n; i++) {
+    prefixSum[i] = prefixSum[i - 1] + pairs[i][0] * pairs[i][1];
+    prefixCost[i] = prefixCost[i - 1] + pairs[i][1];
+  }
+
+  let result = Infinity;
+  for (let i = 0; i < n; i++) {
+    const target = pairs[i][0];
+    const leftCost = i > 0 ? target * prefixCost[i - 1] - prefixSum[i - 1] : 0;
+    const rightCost = i < n - 1 ? prefixSum[n - 1] - prefixSum[i]
+      - target * (prefixCost[n - 1] - prefixCost[i]) : 0;
+    result = Math.min(result, leftCost + rightCost);
+  }
+
+  return result;
+};
diff --git a/solutions/2449-minimum-number-of-operations-to-make-arrays-similar.js b/solutions/2449-minimum-number-of-operations-to-make-arrays-similar.js
new file mode 100644
index 00000000..29c2cacf
--- /dev/null
+++ b/solutions/2449-minimum-number-of-operations-to-make-arrays-similar.js
@@ -0,0 +1,44 @@
+/**
+ * 2449. Minimum Number of Operations to Make Arrays Similar
+ * https://leetcode.com/problems/minimum-number-of-operations-to-make-arrays-similar/
+ * Difficulty: Hard
+ *
+ * You are given two positive integer arrays nums and target, of the same length.
+ *
+ * In one operation, you can choose any two distinct indices i and j where 0 <= i,
+ * j < nums.length and:
+ * - set nums[i] = nums[i] + 2 and
+ * - set nums[j] = nums[j] - 2.
+ *
+ * Two arrays are considered to be similar if the frequency of each element is the same.
+ *
+ * Return the minimum number of operations required to make nums similar to target. The
+ * test cases are generated such that nums can always be similar to target.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number[]} target
+ * @return {number}
+ */
+var makeSimilar = function(nums, target) {
+  const evenNums = nums.filter(num => num % 2 === 0).sort((a, b) => a - b);
+  const oddNums = nums.filter(num => num % 2 === 1).sort((a, b) => a - b);
+  const evenTarget = target.filter(num => num % 2 === 0).sort((a, b) => a - b);
+  const oddTarget = target.filter(num => num % 2 === 1).sort((a, b) => a - b);
+
+  let result = 0;
+  for (let i = 0; i < evenNums.length; i++) {
+    if (evenNums[i] > evenTarget[i]) {
+      result += (evenNums[i] - evenTarget[i]) / 2;
+    }
+  }
+
+  for (let i = 0; i < oddNums.length; i++) {
+    if (oddNums[i] > oddTarget[i]) {
+      result += (oddNums[i] - oddTarget[i]) / 2;
+    }
+  }
+
+  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/2451-odd-string-difference.js b/solutions/2451-odd-string-difference.js
new file mode 100644
index 00000000..8556415c
--- /dev/null
+++ b/solutions/2451-odd-string-difference.js
@@ -0,0 +1,53 @@
+/**
+ * 2451. Odd String Difference
+ * https://leetcode.com/problems/odd-string-difference/
+ * Difficulty: Easy
+ *
+ * You are given an array of equal-length strings words. Assume that the length of each
+ * string is n.
+ *
+ * Each string words[i] can be converted into a difference integer array difference[i] of
+ * length n - 1 where difference[i][j] = words[i][j+1] - words[i][j] where 0 <= j <= n - 2.
+ * Note that the difference between two letters is the difference between their positions in
+ * the alphabet i.e. the position of 'a' is 0, 'b' is 1, and 'z' is 25.
+ * - For example, for the string "acb", the difference integer array is [2 - 0, 1 - 2] = [2, -1].
+ *
+ * All the strings in words have the same difference integer array, except one. You should find
+ * that string.
+ *
+ * Return the string in words that has different difference integer array.
+ */
+
+/**
+ * @param {string[]} words
+ * @return {string}
+ */
+var oddString = function(words) {
+  const map = new Map();
+  for (const word of words) {
+    const diff = getDiff(word);
+    map.set(diff, (map.get(diff) || 0) + 1);
+  }
+
+  let oddDiff;
+  for (const [diff, count] of map) {
+    if (count === 1) {
+      oddDiff = diff;
+      break;
+    }
+  }
+
+  for (const word of words) {
+    if (getDiff(word) === oddDiff) {
+      return word;
+    }
+  }
+
+  function getDiff(word) {
+    const diff = [];
+    for (let i = 1; i < word.length; i++) {
+      diff.push(word.charCodeAt(i) - word.charCodeAt(i - 1));
+    }
+    return diff.join(',');
+  }
+};
diff --git a/solutions/2452-words-within-two-edits-of-dictionary.js b/solutions/2452-words-within-two-edits-of-dictionary.js
new file mode 100644
index 00000000..237dac21
--- /dev/null
+++ b/solutions/2452-words-within-two-edits-of-dictionary.js
@@ -0,0 +1,41 @@
+/**
+ * 2452. Words Within Two Edits of Dictionary
+ * https://leetcode.com/problems/words-within-two-edits-of-dictionary/
+ * Difficulty: Medium
+ *
+ * You are given two string arrays, queries and dictionary. All words in each array comprise of
+ * lowercase English letters and have the same length.
+ *
+ * In one edit you can take a word from queries, and change any letter in it to any other letter.
+ * Find all words from queries that, after a maximum of two edits, equal some word from dictionary.
+ *
+ * Return a list of all words from queries, that match with some word from dictionary after a
+ * maximum of two edits. Return the words in the same order they appear in queries.
+ */
+
+/**
+ * @param {string[]} queries
+ * @param {string[]} dictionary
+ * @return {string[]}
+ */
+var twoEditWords = function(queries, dictionary) {
+  const result = [];
+
+  for (const query of queries) {
+    for (const word of dictionary) {
+      let edits = 0;
+      for (let i = 0; i < query.length; i++) {
+        if (query[i] !== word[i]) {
+          edits++;
+          if (edits > 2) break;
+        }
+      }
+      if (edits <= 2) {
+        result.push(query);
+        break;
+      }
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2453-destroy-sequential-targets.js b/solutions/2453-destroy-sequential-targets.js
new file mode 100644
index 00000000..d1c9f856
--- /dev/null
+++ b/solutions/2453-destroy-sequential-targets.js
@@ -0,0 +1,40 @@
+/**
+ * 2453. Destroy Sequential Targets
+ * https://leetcode.com/problems/destroy-sequential-targets/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed array nums consisting of positive integers, representing targets
+ * on a number line. You are also given an integer space.
+ *
+ * You have a machine which can destroy targets. Seeding the machine with some nums[i] allows
+ * it to destroy all targets with values that can be represented as nums[i] + c * space, where
+ * c is any non-negative integer. You want to destroy the maximum number of targets in nums.
+ *
+ * Return the minimum value of nums[i] you can seed the machine with to destroy the maximum
+ * number of targets.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} space
+ * @return {number}
+ */
+var destroyTargets = function(nums, space) {
+  const map = new Map();
+  let maxCount = 0;
+
+  for (const num of nums) {
+    const remainder = num % space;
+    map.set(remainder, (map.get(remainder) || 0) + 1);
+    maxCount = Math.max(maxCount, map.get(remainder));
+  }
+
+  let result = Infinity;
+  for (const num of nums) {
+    if (map.get(num % space) === maxCount) {
+      result = Math.min(result, num);
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2455-average-value-of-even-numbers-that-are-divisible-by-three.js b/solutions/2455-average-value-of-even-numbers-that-are-divisible-by-three.js
new file mode 100644
index 00000000..e793e8fe
--- /dev/null
+++ b/solutions/2455-average-value-of-even-numbers-that-are-divisible-by-three.js
@@ -0,0 +1,29 @@
+/**
+ * 2455. Average Value of Even Numbers That Are Divisible by Three
+ * https://leetcode.com/problems/average-value-of-even-numbers-that-are-divisible-by-three/
+ * Difficulty: Easy
+ *
+ * Given an integer array nums of positive integers, return the average value of all even integers
+ * that are divisible by 3.
+ *
+ * Note that the average of n elements is the sum of the n elements divided by n and rounded down
+ * to the nearest integer.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var averageValue = function(nums) {
+  let sum = 0;
+  let count = 0;
+
+  for (const num of nums) {
+    if (num % 2 === 0 && num % 3 === 0) {
+      sum += num;
+      count++;
+    }
+  }
+
+  return count > 0 ? Math.floor(sum / count) : 0;
+};
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/2458-height-of-binary-tree-after-subtree-removal-queries.js b/solutions/2458-height-of-binary-tree-after-subtree-removal-queries.js
new file mode 100644
index 00000000..418ee0ff
--- /dev/null
+++ b/solutions/2458-height-of-binary-tree-after-subtree-removal-queries.js
@@ -0,0 +1,68 @@
+/**
+ * 2458. Height of Binary Tree After Subtree Removal Queries
+ * https://leetcode.com/problems/height-of-binary-tree-after-subtree-removal-queries/
+ * Difficulty: Hard
+ *
+ * You are given the root of a binary tree with n nodes. Each node is assigned a unique value
+ * from 1 to n. You are also given an array queries of size m.
+ *
+ * You have to perform m independent queries on the tree where in the ith query you do the
+ * following:
+ * - Remove the subtree rooted at the node with the value queries[i] from the tree. It is
+ *   guaranteed that queries[i] will not be equal to the value of the root.
+ *
+ * Return an array answer of size m where answer[i] is the height of the tree after performing
+ * the ith query.
+ *
+ * Note:
+ * - The queries are independent, so the tree returns to its initial state after each query.
+ * - The height of a tree is the number of edges in the longest simple path from the root to
+ *   some node in the 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[]} queries
+ * @return {number[]}
+ */
+var treeQueries = function(root, queries) {
+  const heights = new Map();
+  const maxHeightWithout = new Map();
+
+  computeHeight(root);
+  computeMaxHeight(root, 0, -1);
+
+  const result = new Array(queries.length);
+  for (let i = 0; i < queries.length; i++) {
+    result[i] = maxHeightWithout.get(queries[i]);
+  }
+
+  return result;
+
+  function computeHeight(node) {
+    if (!node) return -1;
+    const leftHeight = computeHeight(node.left);
+    const rightHeight = computeHeight(node.right);
+    heights.set(node.val, Math.max(leftHeight, rightHeight) + 1);
+    return heights.get(node.val);
+  }
+
+  function computeMaxHeight(node, depth, cousinHeight) {
+    if (!node) return;
+    const leftHeight = node.left ? heights.get(node.left.val) : -1;
+    const rightHeight = node.right ? heights.get(node.right.val) : -1;
+    const maxAlternative = Math.max(cousinHeight, depth - 1);
+    maxHeightWithout.set(node.val, maxAlternative);
+
+    computeMaxHeight(node.left, depth + 1, Math.max(cousinHeight, rightHeight + depth + 1));
+    computeMaxHeight(node.right, depth + 1, Math.max(cousinHeight, leftHeight + depth + 1));
+  }
+};
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/2461-maximum-sum-of-distinct-subarrays-with-length-k.js b/solutions/2461-maximum-sum-of-distinct-subarrays-with-length-k.js
new file mode 100644
index 00000000..a1212952
--- /dev/null
+++ b/solutions/2461-maximum-sum-of-distinct-subarrays-with-length-k.js
@@ -0,0 +1,45 @@
+/**
+ * 2461. Maximum Sum of Distinct Subarrays With Length K
+ * https://leetcode.com/problems/maximum-sum-of-distinct-subarrays-with-length-k/
+ * Difficulty: Medium
+ *
+ * You are given an integer array nums and an integer k. Find the maximum subarray sum of all the
+ * subarrays of nums that meet the following conditions:
+ * - The length of the subarray is k, and
+ * - All the elements of the subarray are distinct.
+ *
+ * Return the maximum subarray sum of all the subarrays that meet the conditions. If no subarray
+ * meets the conditions, return 0.
+ *
+ * A subarray is a contiguous non-empty sequence of elements within an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var maximumSubarraySum = function(nums, k) {
+  let result = 0;
+  const seen = new Map();
+  let windowSum = 0;
+
+  for (let i = 0; i < nums.length; i++) {
+    seen.set(nums[i], (seen.get(nums[i]) || 0) + 1);
+    windowSum += nums[i];
+
+    if (i >= k - 1) {
+      if (seen.size === k) {
+        result = Math.max(result, windowSum);
+      }
+      const leftNum = nums[i - k + 1];
+      windowSum -= leftNum;
+      seen.set(leftNum, seen.get(leftNum) - 1);
+      if (seen.get(leftNum) === 0) {
+        seen.delete(leftNum);
+      }
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2463-minimum-total-distance-traveled.js b/solutions/2463-minimum-total-distance-traveled.js
new file mode 100644
index 00000000..cb71bbc0
--- /dev/null
+++ b/solutions/2463-minimum-total-distance-traveled.js
@@ -0,0 +1,71 @@
+/**
+ * 2463. Minimum Total Distance Traveled
+ * https://leetcode.com/problems/minimum-total-distance-traveled/
+ * Difficulty: Hard
+ *
+ * There are some robots and factories on the X-axis. You are given an integer array robot where
+ * robot[i] is the position of the ith robot. You are also given a 2D integer array factory where
+ * factory[j] = [positionj, limitj] indicates that positionj is the position of the jth factory
+ * and that the jth factory can repair at most limitj robots.
+ *
+ * The positions of each robot are unique. The positions of each factory are also unique. Note
+ * that a robot can be in the same position as a factory initially.
+ *
+ * All the robots are initially broken; they keep moving in one direction. The direction could be
+ * the negative or the positive direction of the X-axis. When a robot reaches a factory that did
+ * not reach its limit, the factory repairs the robot, and it stops moving.
+ *
+ * At any moment, you can set the initial direction of moving for some robot. Your target is to
+ * minimize the total distance traveled by all the robots.
+ *
+ * Return the minimum total distance traveled by all the robots. The test cases are generated
+ * such that all the robots can be repaired.
+ *
+ * Note that:
+ * - All robots move at the same speed.
+ * - If two robots move in the same direction, they will never collide.
+ * - If two robots move in opposite directions and they meet at some point, they do not collide.
+ *   They cross each other.
+ * - If a robot passes by a factory that reached its limits, it crosses it as if it does not exist.
+ * - If the robot moved from a position x to a position y, the distance it moved is |y - x|.
+ */
+
+/**
+ * @param {number[]} robot
+ * @param {number[][]} factory
+ * @return {number}
+ */
+var minimumTotalDistance = function(robot, factory) {
+  robot.sort((a, b) => a - b);
+  factory.sort((a, b) => a[0] - b[0]);
+
+  const robotCount = robot.length;
+  const factoryCount = factory.length;
+  const memo = new Array(robotCount + 1).fill(null).map(() => new Array(factoryCount + 1).fill(-1));
+
+  return calculateMinDistance(0, 0);
+
+  function calculateMinDistance(robotIndex, factoryIndex) {
+    if (robotIndex === robotCount) return 0;
+    if (factoryIndex === factoryCount) return 1e18;
+
+    if (memo[robotIndex][factoryIndex] !== -1) {
+      return memo[robotIndex][factoryIndex];
+    }
+
+    let result = calculateMinDistance(robotIndex, factoryIndex + 1);
+
+    let totalDistance = 0;
+    for (let robotsTaken = 0; robotsTaken < factory[factoryIndex][1]
+         && robotIndex + robotsTaken < robotCount; robotsTaken++) {
+      totalDistance += Math.abs(robot[robotIndex + robotsTaken] - factory[factoryIndex][0]);
+      result = Math.min(
+        result,
+        totalDistance + calculateMinDistance(robotIndex + robotsTaken + 1, factoryIndex + 1)
+      );
+    }
+
+    memo[robotIndex][factoryIndex] = result;
+    return result;
+  }
+};
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/2465-number-of-distinct-averages.js b/solutions/2465-number-of-distinct-averages.js
new file mode 100644
index 00000000..768feffd
--- /dev/null
+++ b/solutions/2465-number-of-distinct-averages.js
@@ -0,0 +1,34 @@
+/**
+ * 2465. Number of Distinct Averages
+ * https://leetcode.com/problems/number-of-distinct-averages/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed integer array nums of even length.
+ *
+ * As long as nums is not empty, you must repetitively:
+ * - Find the minimum number in nums and remove it.
+ * - Find the maximum number in nums and remove it.
+ * - Calculate the average of the two removed numbers.
+ *
+ * The average of two numbers a and b is (a + b) / 2.
+ * - For example, the average of 2 and 3 is (2 + 3) / 2 = 2.5.
+ *
+ * Return the number of distinct averages calculated using the above process.
+ *
+ * Note that when there is a tie for a minimum or maximum number, any can be removed.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var distinctAverages = function(nums) {
+  nums.sort((a, b) => a - b);
+  const averages = new Set();
+
+  for (let i = 0, j = nums.length - 1; i < j; i++, j--) {
+    averages.add((nums[i] + nums[j]) / 2);
+  }
+
+  return averages.size;
+};
diff --git a/solutions/2466-count-ways-to-build-good-strings.js b/solutions/2466-count-ways-to-build-good-strings.js
new file mode 100644
index 00000000..5bea8af2
--- /dev/null
+++ b/solutions/2466-count-ways-to-build-good-strings.js
@@ -0,0 +1,47 @@
+/**
+ * 2466. Count Ways To Build Good Strings
+ * https://leetcode.com/problems/count-ways-to-build-good-strings/
+ * Difficulty: Medium
+ *
+ * Given the integers zero, one, low, and high, we can construct a string by starting with an
+ * empty string, and then at each step perform either of the following:
+ * - Append the character '0' zero times.
+ * - Append the character '1' one times.
+ *
+ * This can be performed any number of times.
+ *
+ * A good string is a string constructed by the above process having a length between low and
+ * high (inclusive).
+ *
+ * Return the number of different good strings that can be constructed satisfying these properties.
+ * Since the answer can be large, return it modulo 109 + 7.
+ */
+
+/**
+ * @param {number} low
+ * @param {number} high
+ * @param {number} zero
+ * @param {number} one
+ * @return {number}
+ */
+var countGoodStrings = function(low, high, zero, one) {
+  const modulo = 1e9 + 7;
+  const dp = new Array(high + 1).fill(0);
+  dp[0] = 1;
+
+  for (let length = 1; length <= high; length++) {
+    if (length >= zero) {
+      dp[length] = (dp[length] + dp[length - zero]) % modulo;
+    }
+    if (length >= one) {
+      dp[length] = (dp[length] + dp[length - one]) % modulo;
+    }
+  }
+
+  let result = 0;
+  for (let length = low; length <= high; length++) {
+    result = (result + dp[length]) % modulo;
+  }
+
+  return result;
+};
diff --git a/solutions/2468-split-message-based-on-limit.js b/solutions/2468-split-message-based-on-limit.js
new file mode 100644
index 00000000..71fc5d00
--- /dev/null
+++ b/solutions/2468-split-message-based-on-limit.js
@@ -0,0 +1,52 @@
+/**
+ * 2468. Split Message Based on Limit
+ * https://leetcode.com/problems/split-message-based-on-limit/
+ * Difficulty: Hard
+ *
+ * You are given a string, message, and a positive integer, limit.
+ *
+ * You must split message into one or more parts based on limit. Each resulting part should have
+ * the suffix "", where "b" is to be replaced with the total number of parts and "a" is to
+ * be replaced with the index of the part, starting from 1 and going up to b. Additionally, the
+ * length of each resulting part (including its suffix) should be equal to limit, except for the
+ * last part whose length can be at most limit.
+ *
+ * The resulting parts should be formed such that when their suffixes are removed and they are
+ * all concatenated in order, they should be equal to message. Also, the result should contain
+ * as few parts as possible.
+ *
+ * Return the parts message would be split into as an array of strings. If it is impossible to
+ * split message as required, return an empty array.
+ */
+
+/**
+ * @param {string} message
+ * @param {number} limit
+ * @return {string[]}
+ */
+var splitMessage = function(message, limit) {
+  const n = message.length;
+  let digitSum = 0;
+
+  for (let parts = 1; parts <= n; parts++) {
+    digitSum += String(parts).length;
+    const indexLength = String(parts).length * parts;
+    const formatLength = 3 * parts;
+
+    if (limit * parts - (digitSum + indexLength + formatLength) >= n) {
+      const result = [];
+      let index = 0;
+
+      for (let i = 1; i <= parts; i++) {
+        const suffix = `<${i}/${parts}>`;
+        const chars = limit - suffix.length;
+        result.push(message.slice(index, index + chars) + suffix);
+        index += chars;
+      }
+
+      return result;
+    }
+  }
+
+  return [];
+};
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/2471-minimum-number-of-operations-to-sort-a-binary-tree-by-level.js b/solutions/2471-minimum-number-of-operations-to-sort-a-binary-tree-by-level.js
new file mode 100644
index 00000000..7d26a4c1
--- /dev/null
+++ b/solutions/2471-minimum-number-of-operations-to-sort-a-binary-tree-by-level.js
@@ -0,0 +1,66 @@
+/**
+ * 2471. Minimum Number of Operations to Sort a Binary Tree by Level
+ * https://leetcode.com/problems/minimum-number-of-operations-to-sort-a-binary-tree-by-level/
+ * Difficulty: Medium
+ *
+ * You are given the root of a binary tree with unique values.
+ *
+ * In one operation, you can choose any two nodes at the same level and swap their values.
+ *
+ * Return the minimum number of operations needed to make the values at each level sorted in a
+ * strictly increasing order.
+ *
+ * The level of a node is the number of edges along the path between it and the root 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 minimumOperations = function(root) {
+  let result = 0;
+  const queue = [root];
+  const levelValues = [];
+
+  while (queue.length) {
+    const levelSize = queue.length;
+    const values = [];
+
+    for (let i = 0; i < levelSize; i++) {
+      const node = queue.shift();
+      values.push(node.val);
+      if (node.left) queue.push(node.left);
+      if (node.right) queue.push(node.right);
+    }
+
+    levelValues.push(values);
+  }
+
+  for (const values of levelValues) {
+    const sorted = [...values].sort((a, b) => a - b);
+    const indexMap = new Map(values.map((val, i) => [val, i]));
+    let swaps = 0;
+
+    for (let i = 0; i < values.length; i++) {
+      if (values[i] !== sorted[i]) {
+        const targetIndex = indexMap.get(sorted[i]);
+        [values[i], values[targetIndex]] = [values[targetIndex], values[i]];
+        indexMap.set(values[targetIndex], targetIndex);
+        indexMap.set(values[i], i);
+        swaps++;
+      }
+    }
+
+    result += swaps;
+  }
+
+  return result;
+};
diff --git a/solutions/2472-maximum-number-of-non-overlapping-palindrome-substrings.js b/solutions/2472-maximum-number-of-non-overlapping-palindrome-substrings.js
new file mode 100644
index 00000000..6244a364
--- /dev/null
+++ b/solutions/2472-maximum-number-of-non-overlapping-palindrome-substrings.js
@@ -0,0 +1,51 @@
+/**
+ * 2472. Maximum Number of Non-overlapping Palindrome Substrings
+ * https://leetcode.com/problems/maximum-number-of-non-overlapping-palindrome-substrings/
+ * Difficulty: Hard
+ *
+ * You are given a string s and a positive integer k.
+ *
+ * Select a set of non-overlapping substrings from the string s that satisfy the following
+ * conditions:
+ * - The length of each substring is at least k.
+ * - Each substring is a palindrome.
+ *
+ * Return the maximum number of substrings in an optimal selection.
+ *
+ * A substring is a contiguous sequence of characters within a string.
+ */
+
+/**
+ * @param {string} s
+ * @param {number} k
+ * @return {number}
+ */
+var maxPalindromes = function(s, k) {
+  const n = s.length;
+  const isPal = new Array(n).fill().map(() => new Array(n).fill(false));
+  const dp = new Array(n + 1).fill(0);
+
+  for (let len = 1; len <= n; len++) {
+    for (let start = 0; start + len <= n; start++) {
+      const end = start + len - 1;
+      if (len === 1) {
+        isPal[start][end] = true;
+      } else if (len === 2) {
+        isPal[start][end] = s[start] === s[end];
+      } else {
+        isPal[start][end] = s[start] === s[end] && isPal[start + 1][end - 1];
+      }
+    }
+  }
+
+  for (let end = k; end <= n; end++) {
+    dp[end] = dp[end - 1];
+    for (let start = end - k; start >= 0; start--) {
+      if (isPal[start][end - 1]) {
+        dp[end] = Math.max(dp[end], dp[start] + 1);
+      }
+    }
+  }
+
+  return dp[n];
+};
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/2475-number-of-unequal-triplets-in-array.js b/solutions/2475-number-of-unequal-triplets-in-array.js
new file mode 100644
index 00000000..8717363b
--- /dev/null
+++ b/solutions/2475-number-of-unequal-triplets-in-array.js
@@ -0,0 +1,36 @@
+/**
+ * 2475. Number of Unequal Triplets in Array
+ * https://leetcode.com/problems/number-of-unequal-triplets-in-array/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed array of positive integers nums. Find the number of
+ * triplets (i, j, k) that meet the following conditions:
+ * - 0 <= i < j < k < nums.length
+ * - nums[i], nums[j], and nums[k] are pairwise distinct.
+ *   - In other words, nums[i] != nums[j], nums[i] != nums[k], and nums[j] != nums[k].
+ *
+ * Return the number of triplets that meet the conditions.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var unequalTriplets = function(nums) {
+  const map = new Map();
+  for (const num of nums) {
+    map.set(num, (map.get(num) || 0) + 1);
+  }
+
+  let result = 0;
+  let left = 0;
+  const total = nums.length;
+
+  for (const count of map.values()) {
+    const right = total - count - left;
+    result += left * count * right;
+    left += count;
+  }
+
+  return result;
+};
diff --git a/solutions/2476-closest-nodes-queries-in-a-binary-search-tree.js b/solutions/2476-closest-nodes-queries-in-a-binary-search-tree.js
new file mode 100644
index 00000000..8f9a487a
--- /dev/null
+++ b/solutions/2476-closest-nodes-queries-in-a-binary-search-tree.js
@@ -0,0 +1,67 @@
+/**
+ * 2476. Closest Nodes Queries in a Binary Search Tree
+ * https://leetcode.com/problems/closest-nodes-queries-in-a-binary-search-tree/
+ * Difficulty: Medium
+ *
+ * You are given the root of a binary search tree and an array queries of size n consisting of
+ * positive integers.
+ *
+ * Find a 2D array answer of size n where answer[i] = [mini, maxi]:
+ * - mini is the largest value in the tree that is smaller than or equal to queries[i]. If a such
+ *   value does not exist, add -1 instead.
+ * - maxi is the smallest value in the tree that is greater than or equal to queries[i]. If a such
+ *   value does not exist, add -1 instead.
+ *
+ * Return the array answer.
+ */
+
+/**
+ * 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[]} queries
+ * @return {number[][]}
+ */
+var closestNodes = function(root, queries) {
+  const values = [];
+
+  inorder(root);
+
+  const result = queries.map(query => {
+    let minVal = -1;
+    let maxVal = -1;
+
+    let left = 0;
+    let right = values.length - 1;
+
+    while (left <= right) {
+      const mid = Math.floor((left + right) / 2);
+      if (values[mid] === query) {
+        return [query, query];
+      } else if (values[mid] < query) {
+        minVal = values[mid];
+        left = mid + 1;
+      } else {
+        maxVal = values[mid];
+        right = mid - 1;
+      }
+    }
+
+    return [minVal, maxVal];
+  });
+
+  return result;
+
+  function inorder(node) {
+    if (!node) return;
+    inorder(node.left);
+    values.push(node.val);
+    inorder(node.right);
+  }
+};
diff --git a/solutions/2477-minimum-fuel-cost-to-report-to-the-capital.js b/solutions/2477-minimum-fuel-cost-to-report-to-the-capital.js
new file mode 100644
index 00000000..fe195062
--- /dev/null
+++ b/solutions/2477-minimum-fuel-cost-to-report-to-the-capital.js
@@ -0,0 +1,51 @@
+/**
+ * 2477. Minimum Fuel Cost to Report to the Capital
+ * https://leetcode.com/problems/minimum-fuel-cost-to-report-to-the-capital/
+ * Difficulty: Medium
+ *
+ * There is a tree (i.e., a connected, undirected graph with no cycles) structure country network
+ * consisting of n cities numbered from 0 to n - 1 and exactly n - 1 roads. The capital city is
+ * city 0. You are given a 2D integer array roads where roads[i] = [ai, bi] denotes that there
+ * exists a bidirectional road connecting cities ai and bi.
+ *
+ * There is a meeting for the representatives of each city. The meeting is in the capital city.
+ *
+ * There is a car in each city. You are given an integer seats that indicates the number of seats
+ * in each car.
+ *
+ * A representative can use the car in their city to travel or change the car and ride with another
+ * representative. The cost of traveling between two cities is one liter of fuel.
+ *
+ * Return the minimum number of liters of fuel to reach the capital city.
+ */
+
+/**
+ * @param {number[][]} roads
+ * @param {number} seats
+ * @return {number}
+ */
+var minimumFuelCost = function(roads, seats) {
+  const n = roads.length + 1;
+  const graph = Array.from({ length: n }, () => []);
+  for (const [a, b] of roads) {
+    graph[a].push(b);
+    graph[b].push(a);
+  }
+
+  let fuel = 0;
+  dfs(0, -1);
+  return fuel;
+
+  function dfs(node, parent) {
+    let representatives = 1;
+    for (const neighbor of graph[node]) {
+      if (neighbor !== parent) {
+        representatives += dfs(neighbor, node);
+      }
+    }
+    if (node !== 0) {
+      fuel += Math.ceil(representatives / seats);
+    }
+    return representatives;
+  }
+};
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/2481-minimum-cuts-to-divide-a-circle.js b/solutions/2481-minimum-cuts-to-divide-a-circle.js
new file mode 100644
index 00000000..805ed6ac
--- /dev/null
+++ b/solutions/2481-minimum-cuts-to-divide-a-circle.js
@@ -0,0 +1,24 @@
+/**
+ * 2481. Minimum Cuts to Divide a Circle
+ * https://leetcode.com/problems/minimum-cuts-to-divide-a-circle/
+ * Difficulty: Easy
+ *
+ * A valid cut in a circle can be:
+ * - A cut that is represented by a straight line that touches two points on the edge of the
+ *   circle and passes through its center, or
+ * - A cut that is represented by a straight line that touches one point on the edge of the
+ *   circle and its center.
+ *
+ * Some valid and invalid cuts are shown in the figures below.
+ *
+ * Given the integer n, return the minimum number of cuts needed to divide a circle into n
+ * equal slices.
+ */
+
+/**
+ * @param {number} n
+ * @return {number}
+ */
+var numberOfCuts = function(n) {
+  return n === 1 ? 0 : n % 2 === 0 ? n / 2 : n;
+};
diff --git a/solutions/2483-minimum-penalty-for-a-shop.js b/solutions/2483-minimum-penalty-for-a-shop.js
new file mode 100644
index 00000000..0819d961
--- /dev/null
+++ b/solutions/2483-minimum-penalty-for-a-shop.js
@@ -0,0 +1,38 @@
+/**
+ * 2483. Minimum Penalty for a Shop
+ * https://leetcode.com/problems/minimum-penalty-for-a-shop/
+ * Difficulty: Medium
+ *
+ * You are given the customer visit log of a shop represented by a 0-indexed string customers
+ * consisting only of characters 'N' and 'Y':
+ * - if the ith character is 'Y', it means that customers come at the ith hour
+ * - whereas 'N' indicates that no customers come at the ith hour.
+ *
+ * If the shop closes at the jth hour (0 <= j <= n), the penalty is calculated as follows:
+ * - For every hour when the shop is open and no customers come, the penalty increases by 1.
+ * - For every hour when the shop is closed and customers come, the penalty increases by 1.
+ *
+ * Return the earliest hour at which the shop must be closed to incur a minimum penalty.
+ *
+ * Note that if a shop closes at the jth hour, it means the shop is closed at the hour j.
+ */
+
+/**
+ * @param {string} customers
+ * @return {number}
+ */
+var bestClosingTime = function(customers) {
+  let minPenalty = 0;
+  let currentPenalty = 0;
+  let result = 0;
+
+  for (let i = 0; i < customers.length; i++) {
+    currentPenalty += customers[i] === 'Y' ? -1 : 1;
+    if (currentPenalty < minPenalty) {
+      minPenalty = currentPenalty;
+      result = i + 1;
+    }
+  }
+
+  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/2485-find-the-pivot-integer.js b/solutions/2485-find-the-pivot-integer.js
new file mode 100644
index 00000000..73a95a4a
--- /dev/null
+++ b/solutions/2485-find-the-pivot-integer.js
@@ -0,0 +1,22 @@
+/**
+ * 2485. Find the Pivot Integer
+ * https://leetcode.com/problems/find-the-pivot-integer/
+ * Difficulty: Easy
+ *
+ * Given a positive integer n, find the pivot integer x such that:
+ * - The sum of all elements between 1 and x inclusively equals the sum of all elements between
+ *   x and n inclusively.
+ *
+ * Return the pivot integer x. If no such integer exists, return -1. It is guaranteed that there
+ * will be at most one pivot index for the given input.
+ */
+
+/**
+ * @param {number} n
+ * @return {number}
+ */
+var pivotInteger = function(n) {
+  const totalSum = n * (n + 1) / 2;
+  const pivot = Math.sqrt(totalSum);
+  return Number.isInteger(pivot) && pivot <= n ? pivot : -1;
+};
diff --git a/solutions/2486-append-characters-to-string-to-make-subsequence.js b/solutions/2486-append-characters-to-string-to-make-subsequence.js
new file mode 100644
index 00000000..09bfb362
--- /dev/null
+++ b/solutions/2486-append-characters-to-string-to-make-subsequence.js
@@ -0,0 +1,32 @@
+/**
+ * 2486. Append Characters to String to Make Subsequence
+ * https://leetcode.com/problems/append-characters-to-string-to-make-subsequence/
+ * Difficulty: Medium
+ *
+ * You are given two strings s and t consisting of only lowercase English letters.
+ *
+ * Return the minimum number of characters that need to be appended to the end of s so that
+ * t becomes a subsequence of s.
+ *
+ * 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 {string} t
+ * @return {number}
+ */
+var appendCharacters = function(s, t) {
+  let sIndex = 0;
+  let tIndex = 0;
+
+  while (sIndex < s.length && tIndex < t.length) {
+    if (s[sIndex] === t[tIndex]) {
+      tIndex++;
+    }
+    sIndex++;
+  }
+
+  return t.length - tIndex;
+};
diff --git a/solutions/2487-remove-nodes-from-linked-list.js b/solutions/2487-remove-nodes-from-linked-list.js
new file mode 100644
index 00000000..b6d6cb2c
--- /dev/null
+++ b/solutions/2487-remove-nodes-from-linked-list.js
@@ -0,0 +1,44 @@
+/**
+ * 2487. Remove Nodes From Linked List
+ * https://leetcode.com/problems/remove-nodes-from-linked-list/
+ * Difficulty: Medium
+ *
+ * You are given the head of a linked list.
+ *
+ * Remove every node which has a node with a greater value anywhere to the right side of it.
+ *
+ * Return the head of the modified linked 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 removeNodes = function(head) {
+  const stack = [];
+  let current = head;
+
+  while (current) {
+    while (stack.length && stack[stack.length - 1].val < current.val) {
+      stack.pop();
+    }
+    stack.push(current);
+    current = current.next;
+  }
+
+  let result = null;
+  while (stack.length) {
+    current = stack.pop();
+    current.next = result;
+    result = current;
+  }
+
+  return result;
+};
diff --git a/solutions/2488-count-subarrays-with-median-k.js b/solutions/2488-count-subarrays-with-median-k.js
new file mode 100644
index 00000000..694d9ea9
--- /dev/null
+++ b/solutions/2488-count-subarrays-with-median-k.js
@@ -0,0 +1,43 @@
+/**
+ * 2488. Count Subarrays With Median K
+ * https://leetcode.com/problems/count-subarrays-with-median-k/
+ * Difficulty: Hard
+ *
+ * You are given an array nums of size n consisting of distinct integers from 1 to n and
+ * a positive integer k.
+ *
+ * Return the number of non-empty subarrays in nums that have a median equal to k.
+ *
+ * Note:
+ * - The median of an array is the middle element after sorting the array in ascending order.
+ *   If the array is of even length, the median is the left middle element.
+ *   - For example, the median of [2,3,1,4] is 2, and the median of [8,4,3,5,1] is 4.
+ * - A subarray is a contiguous part of an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var countSubarrays = function(nums, k) {
+  const n = nums.length;
+  const kIndex = nums.indexOf(k);
+  const balanceMap = new Map([[0, 1]]);
+  let balance = 0;
+  let result = 0;
+
+  for (let i = kIndex + 1; i < n; i++) {
+    balance += nums[i] > k ? 1 : -1;
+    balanceMap.set(balance, (balanceMap.get(balance) || 0) + 1);
+  }
+
+  balance = 0;
+  for (let i = kIndex; i >= 0; i--) {
+    balance += nums[i] > k ? -1 : nums[i] < k ? 1 : 0;
+    result += balanceMap.get(balance) || 0;
+    result += balanceMap.get(balance + 1) || 0;
+  }
+
+  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/2491-divide-players-into-teams-of-equal-skill.js b/solutions/2491-divide-players-into-teams-of-equal-skill.js
new file mode 100644
index 00000000..5f481cf0
--- /dev/null
+++ b/solutions/2491-divide-players-into-teams-of-equal-skill.js
@@ -0,0 +1,32 @@
+/**
+ * 2491. Divide Players Into Teams of Equal Skill
+ * https://leetcode.com/problems/divide-players-into-teams-of-equal-skill/
+ * Difficulty: Medium
+ *
+ * You are given a positive integer array skill of even length n where skill[i] denotes the
+ * skill of the ith player. Divide the players into n / 2 teams of size 2 such that the total
+ * skill of each team is equal.
+ *
+ * The chemistry of a team is equal to the product of the skills of the players on that team.
+ *
+ * Return the sum of the chemistry of all the teams, or return -1 if there is no way to divide
+ * the players into teams such that the total skill of each team is equal.
+ */
+
+/**
+ * @param {number[]} skill
+ * @return {number}
+ */
+var dividePlayers = function(skill) {
+  skill.sort((a, b) => a - b);
+  const n = skill.length;
+  const targetSum = skill[0] + skill[n - 1];
+  let result = 0;
+
+  for (let i = 0, j = n - 1; i < j; i++, j--) {
+    if (skill[i] + skill[j] !== targetSum) return -1;
+    result += skill[i] * skill[j];
+  }
+
+  return result;
+};
diff --git a/solutions/2492-minimum-score-of-a-path-between-two-cities.js b/solutions/2492-minimum-score-of-a-path-between-two-cities.js
new file mode 100644
index 00000000..f5cbc0f5
--- /dev/null
+++ b/solutions/2492-minimum-score-of-a-path-between-two-cities.js
@@ -0,0 +1,53 @@
+/**
+ * 2492. Minimum Score of a Path Between Two Cities
+ * https://leetcode.com/problems/minimum-score-of-a-path-between-two-cities/
+ * 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, distancei] indicates that there is a
+ * bidirectional road between cities ai and bi with a distance equal to distancei. The cities
+ * graph is not necessarily connected.
+ *
+ * The score of a path between two cities is defined as the minimum distance of a road in this
+ * path.
+ *
+ * Return the minimum possible score of a path between cities 1 and n.
+ *
+ * Note:
+ * - A path is a sequence of roads between two cities.
+ * - It is allowed for a path to contain the same road multiple times, and you can visit cities 1
+ *   and n multiple times along the path.
+ * - The test cases are generated such that there is at least one path between 1 and n.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[][]} roads
+ * @return {number}
+ */
+var minScore = function(n, roads) {
+  const graph = Array.from({ length: n + 1 }, () => []);
+  for (const [a, b, dist] of roads) {
+    graph[a].push([b, dist]);
+    graph[b].push([a, dist]);
+  }
+
+  const visited = new Set();
+  const queue = [1];
+  let result = Infinity;
+
+  while (queue.length) {
+    const city = queue.shift();
+    if (visited.has(city)) continue;
+    visited.add(city);
+
+    for (const [nextCity, dist] of graph[city]) {
+      result = Math.min(result, dist);
+      if (!visited.has(nextCity)) {
+        queue.push(nextCity);
+      }
+    }
+  }
+
+  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/2496-maximum-value-of-a-string-in-an-array.js b/solutions/2496-maximum-value-of-a-string-in-an-array.js
new file mode 100644
index 00000000..3d78d50f
--- /dev/null
+++ b/solutions/2496-maximum-value-of-a-string-in-an-array.js
@@ -0,0 +1,27 @@
+/**
+ * 2496. Maximum Value of a String in an Array
+ * https://leetcode.com/problems/maximum-value-of-a-string-in-an-array/
+ * Difficulty: Easy
+ *
+ * The value of an alphanumeric string can be defined as:
+ * - The numeric representation of the string in base 10, if it comprises of digits only.
+ * - The length of the string, otherwise.
+ *
+ * Given an array strs of alphanumeric strings, return the maximum value of any string in strs.
+ */
+
+/**
+ * @param {string[]} strs
+ * @return {number}
+ */
+var maximumValue = function(strs) {
+  let result = 0;
+
+  for (const str of strs) {
+    const isNumeric = /^[0-9]+$/.test(str);
+    const value = isNumeric ? parseInt(str) : str.length;
+    result = Math.max(result, value);
+  }
+
+  return result;
+};
diff --git a/solutions/2498-frog-jump-ii.js b/solutions/2498-frog-jump-ii.js
new file mode 100644
index 00000000..573192a9
--- /dev/null
+++ b/solutions/2498-frog-jump-ii.js
@@ -0,0 +1,33 @@
+/**
+ * 2498. Frog Jump II
+ * https://leetcode.com/problems/frog-jump-ii/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array stones sorted in strictly increasing order representing
+ * the positions of stones in a river.
+ *
+ * A frog, initially on the first stone, wants to travel to the last stone and then return to the
+ * first stone. However, it can jump to any stone at most once.
+ *
+ * The length of a jump is the absolute difference between the position of the stone the frog is
+ * currently on and the position of the stone to which the frog jumps.
+ *
+ * - More formally, if the frog is at stones[i] and is jumping to stones[j], the length of the jump
+ *   is |stones[i] - stones[j]|.
+ *
+ * The cost of a path is the maximum length of a jump among all jumps in the path.
+ *
+ * Return the minimum cost of a path for the frog.
+ */
+
+/**
+ * @param {number[]} stones
+ * @return {number}
+ */
+var maxJump = function(stones) {
+  let result = stones[1];
+  for (let i = 2; i < stones.length; i++) {
+    result = Math.max(result, stones[i] - stones[i - 2]);
+  }
+  return result;
+};
diff --git a/solutions/2499-minimum-total-cost-to-make-arrays-unequal.js b/solutions/2499-minimum-total-cost-to-make-arrays-unequal.js
new file mode 100644
index 00000000..8a8e8e9a
--- /dev/null
+++ b/solutions/2499-minimum-total-cost-to-make-arrays-unequal.js
@@ -0,0 +1,69 @@
+/**
+ * 2499. Minimum Total Cost to Make Arrays Unequal
+ * https://leetcode.com/problems/minimum-total-cost-to-make-arrays-unequal/
+ * Difficulty: Hard
+ *
+ * You are given two 0-indexed integer arrays nums1 and nums2, of equal length n.
+ *
+ * In one operation, you can swap the values of any two indices of nums1. The cost of this
+ * operation is the sum of the indices.
+ *
+ * Find the minimum total cost of performing the given operation any number of times such
+ * that nums1[i] != nums2[i] for all 0 <= i <= n - 1 after performing all the operations.
+ *
+ * Return the minimum total cost such that nums1 and nums2 satisfy the above condition.
+ * In case it is not possible, return -1.
+ */
+
+/**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number}
+ */
+var minimumTotalCost = function(nums1, nums2) {
+  const n = nums1.length;
+  const conflictIndices = [];
+  const valueCount = new Map();
+
+  for (let i = 0; i < n; i++) {
+    if (nums1[i] === nums2[i]) {
+      conflictIndices.push(i);
+      valueCount.set(nums1[i], (valueCount.get(nums1[i]) || 0) + 1);
+    }
+  }
+
+  if (conflictIndices.length === 0) return 0;
+
+  let dominantValue = -1;
+  let maxCount = 0;
+
+  for (const [value, count] of valueCount) {
+    if (count > maxCount) {
+      maxCount = count;
+      dominantValue = value;
+    }
+  }
+
+  const swapsNeeded = conflictIndices.length;
+  let helpersNeeded = Math.max(0, 2 * maxCount - swapsNeeded);
+
+  const helperIndices = [];
+  for (let i = 0; i < n && helpersNeeded > 0; i++) {
+    if (nums1[i] !== nums2[i] && nums1[i] !== dominantValue && nums2[i] !== dominantValue) {
+      helperIndices.push(i);
+      helpersNeeded--;
+    }
+  }
+
+  if (helpersNeeded > 0) return -1;
+
+  const allIndices = [...conflictIndices, ...helperIndices];
+  allIndices.sort((a, b) => a - b);
+
+  let result = 0;
+  for (let i = 0; i < allIndices.length; i++) {
+    result += allIndices[i];
+  }
+
+  return result;
+};
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/2501-longest-square-streak-in-an-array.js b/solutions/2501-longest-square-streak-in-an-array.js
new file mode 100644
index 00000000..ee667541
--- /dev/null
+++ b/solutions/2501-longest-square-streak-in-an-array.js
@@ -0,0 +1,41 @@
+/**
+ * 2501. Longest Square Streak in an Array
+ * https://leetcode.com/problems/longest-square-streak-in-an-array/
+ * Difficulty: Medium
+ *
+ * You are given an integer array nums. A subsequence of nums is called a square streak if:
+ * - The length of the subsequence is at least 2, and
+ * - after sorting the subsequence, each element (except the first element) is the square of
+ *   the previous number.
+ *
+ * Return the length of the longest square streak in nums, or return -1 if there is no square
+ * streak.
+ *
+ * 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 longestSquareStreak = function(nums) {
+  const set = new Set(nums);
+  let result = -1;
+
+  for (const num of nums) {
+    let current = num;
+    let length = 1;
+
+    while (current <= 100000 && set.has(current * current)) {
+      current *= current;
+      length++;
+    }
+
+    if (length >= 2) {
+      result = Math.max(result, length);
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2502-design-memory-allocator.js b/solutions/2502-design-memory-allocator.js
new file mode 100644
index 00000000..b09fcbb0
--- /dev/null
+++ b/solutions/2502-design-memory-allocator.js
@@ -0,0 +1,76 @@
+/**
+ * 2502. Design Memory Allocator
+ * https://leetcode.com/problems/design-memory-allocator/
+ * Difficulty: Medium
+ *
+ * You are given an integer n representing the size of a 0-indexed memory array. All memory
+ * units are initially free.
+ *
+ * You have a memory allocator with the following functionalities:
+ * 1. Allocate a block of size consecutive free memory units and assign it the id mID.
+ * 2. Free all memory units with the given id mID.
+ *
+ * Note that:
+ * - Multiple blocks can be allocated to the same mID.
+ * - You should free all the memory units with mID, even if they were allocated in different blocks.
+ *
+ * Implement the Allocator class:
+ * - Allocator(int n) Initializes an Allocator object with a memory array of size n.
+ * - int allocate(int size, int mID) Find the leftmost block of size consecutive free memory units
+ *   and allocate it with the id mID. Return the block's first index. If such a block does not
+ *   exist, return -1.
+ * - int freeMemory(int mID) Free all memory units with the id mID. Return the number of memory
+ *   units you have freed.
+ */
+
+/**
+ * @param {number} n
+ */
+var Allocator = function(n) {
+  this.memory = Array(n).fill(0);
+};
+
+/**
+ * @param {number} size
+ * @param {number} mID
+ * @return {number}
+ */
+Allocator.prototype.allocate = function(size, mID) {
+  let start = -1;
+  let count = 0;
+
+  for (let i = 0; i < this.memory.length; i++) {
+    if (this.memory[i] === 0) {
+      if (start === -1) start = i;
+      count++;
+      if (count === size) {
+        for (let j = start; j < start + size; j++) {
+          this.memory[j] = mID;
+        }
+        return start;
+      }
+    } else {
+      start = -1;
+      count = 0;
+    }
+  }
+
+  return -1;
+};
+
+/**
+ * @param {number} mID
+ * @return {number}
+ */
+Allocator.prototype.freeMemory = function(mID) {
+  let result = 0;
+
+  for (let i = 0; i < this.memory.length; i++) {
+    if (this.memory[i] === mID) {
+      this.memory[i] = 0;
+      result++;
+    }
+  }
+
+  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/2506-count-pairs-of-similar-strings.js b/solutions/2506-count-pairs-of-similar-strings.js
new file mode 100644
index 00000000..3a4d78ef
--- /dev/null
+++ b/solutions/2506-count-pairs-of-similar-strings.js
@@ -0,0 +1,36 @@
+/**
+ * 2506. Count Pairs Of Similar Strings
+ * https://leetcode.com/problems/count-pairs-of-similar-strings/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed string array words.
+ *
+ * Two strings are similar if they consist of the same characters.
+ * - For example, "abca" and "cba" are similar since both consist of characters 'a', 'b', and 'c'.
+ * - However, "abacba" and "bcfd" are not similar since they do not consist of the same characters.
+ *
+ * Return the number of pairs (i, j) such that 0 <= i < j <= word.length - 1 and the two strings
+ * words[i] and words[j] are similar.
+ */
+
+/**
+ * @param {string[]} words
+ * @return {number}
+ */
+var similarPairs = function(words) {
+  const map = new Map();
+  let result = 0;
+
+  for (const word of words) {
+    const charSet = [...new Set(word.split(''))].sort().join('');
+    map.set(charSet, (map.get(charSet) || 0) + 1);
+  }
+
+  for (const count of map.values()) {
+    if (count > 1) {
+      result += (count * (count - 1)) / 2;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2507-smallest-value-after-replacing-with-sum-of-prime-factors.js b/solutions/2507-smallest-value-after-replacing-with-sum-of-prime-factors.js
new file mode 100644
index 00000000..d77f5c3a
--- /dev/null
+++ b/solutions/2507-smallest-value-after-replacing-with-sum-of-prime-factors.js
@@ -0,0 +1,37 @@
+/**
+ * 2507. Smallest Value After Replacing With Sum of Prime Factors
+ * https://leetcode.com/problems/smallest-value-after-replacing-with-sum-of-prime-factors/
+ * Difficulty: Medium
+ *
+ * You are given a positive integer n.
+ *
+ * Continuously replace n with the sum of its prime factors.
+ * - Note that if a prime factor divides n multiple times, it should be included in the sum as many
+ *   times as it divides n.
+ *
+ * Return the smallest value n will take on.
+ */
+
+/**
+ * @param {number} n
+ * @return {number}
+ */
+var smallestValue = function(n) {
+  while (true) {
+    const next = sumPrimeFactors(n);
+    if (next === n) return n;
+    n = next;
+  }
+
+  function sumPrimeFactors(num) {
+    let sum = 0;
+    for (let i = 2; i * i <= num; i++) {
+      while (num % i === 0) {
+        sum += i;
+        num /= i;
+      }
+    }
+    if (num > 1) sum += num;
+    return sum;
+  }
+};
diff --git a/solutions/2509-cycle-length-queries-in-a-tree.js b/solutions/2509-cycle-length-queries-in-a-tree.js
new file mode 100644
index 00000000..180c2a6c
--- /dev/null
+++ b/solutions/2509-cycle-length-queries-in-a-tree.js
@@ -0,0 +1,54 @@
+/**
+ * 2509. Cycle Length Queries in a Tree
+ * https://leetcode.com/problems/cycle-length-queries-in-a-tree/
+ * Difficulty: Hard
+ *
+ * You are given an integer n. There is a complete binary tree with 2n - 1 nodes. The root of
+ * that tree is the node with the value 1, and every node with a value val in the range
+ * [1, 2n - 1 - 1] has two children where:
+ * - The left node has the value 2 * val, and
+ * - The right node has the value 2 * val + 1.
+ *
+ * You are also given a 2D integer array queries of length m, where queries[i] = [ai, bi]. For
+ * each query, solve the following problem:
+ * 1. Add an edge between the nodes with values ai and bi.
+ * 2. Find the length of the cycle in the graph.
+ * 3. Remove the added edge between nodes with values ai and bi.
+ *
+ * Note that:
+ * - A cycle is a path that starts and ends at the same node, and each edge in the path is
+ *   visited only once.
+ * - The length of a cycle is the number of edges visited in the cycle.
+ * - There could be multiple edges between two nodes in the tree after adding the edge of
+ *   the query.
+ *
+ * Return an array answer of length m where answer[i] is the answer to the ith query.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[][]} queries
+ * @return {number[]}
+ */
+var cycleLengthQueries = function(n, queries) {
+  const result = [];
+
+  for (const [a, b] of queries) {
+    let x = a;
+    let y = b;
+    let pathLength = 1;
+
+    while (x !== y) {
+      if (x > y) {
+        x = Math.floor(x / 2);
+      } else {
+        y = Math.floor(y / 2);
+      }
+      pathLength++;
+    }
+
+    result.push(pathLength);
+  }
+
+  return 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/2515-shortest-distance-to-target-string-in-a-circular-array.js b/solutions/2515-shortest-distance-to-target-string-in-a-circular-array.js
new file mode 100644
index 00000000..5c315a34
--- /dev/null
+++ b/solutions/2515-shortest-distance-to-target-string-in-a-circular-array.js
@@ -0,0 +1,37 @@
+/**
+ * 2515. Shortest Distance to Target String in a Circular Array
+ * https://leetcode.com/problems/shortest-distance-to-target-string-in-a-circular-array/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed circular string array words and a string target. A circular array
+ * means that the array's end connects to the array's beginning.
+ * - Formally, the next element of words[i] is words[(i + 1) % n] and the previous element of
+ *   words[i] is words[(i - 1 + n) % n], where n is the length of words.
+ *
+ * Starting from startIndex, you can move to either the next word or the previous word with 1
+ * step at a time.
+ *
+ * Return the shortest distance needed to reach the string target. If the string target does not
+ * exist in words, return -1.
+ */
+
+/**
+ * @param {string[]} words
+ * @param {string} target
+ * @param {number} startIndex
+ * @return {number}
+ */
+var closestTarget = function(words, target, startIndex) {
+  const n = words.length;
+  let minDistance = Infinity;
+
+  for (let i = 0; i < n; i++) {
+    if (words[i] === target) {
+      const forward = Math.abs(i - startIndex);
+      const backward = n - forward;
+      minDistance = Math.min(minDistance, forward, backward);
+    }
+  }
+
+  return minDistance === Infinity ? -1 : minDistance;
+};
diff --git a/solutions/2516-take-k-of-each-character-from-left-and-right.js b/solutions/2516-take-k-of-each-character-from-left-and-right.js
new file mode 100644
index 00000000..a37d84a9
--- /dev/null
+++ b/solutions/2516-take-k-of-each-character-from-left-and-right.js
@@ -0,0 +1,46 @@
+/**
+ * 2516. Take K of Each Character From Left and Right
+ * https://leetcode.com/problems/take-k-of-each-character-from-left-and-right/
+ * Difficulty: Medium
+ *
+ * You are given a string s consisting of the characters 'a', 'b', and 'c' and a non-negative
+ * integer k. Each minute, you may take either the leftmost character of s, or the rightmost
+ * character of s.
+ *
+ * Return the minimum number of minutes needed for you to take at least k of each character,
+ * or return -1 if it is not possible to take k of each character.
+ */
+
+/**
+ * @param {string} s
+ * @param {number} k
+ * @return {number}
+ */
+var takeCharacters = function(s, k) {
+  const n = s.length;
+  const counts = { a: 0, b: 0, c: 0 };
+
+  for (const char of s) {
+    counts[char]++;
+  }
+
+  if (counts.a < k || counts.b < k || counts.c < k) return -1;
+
+  let maxWindow = 0;
+  let left = 0;
+  const windowCounts = { a: 0, b: 0, c: 0 };
+
+  for (let right = 0; right < n; right++) {
+    windowCounts[s[right]]++;
+
+    while (windowCounts.a > counts.a - k || windowCounts.b > counts.b - k
+          || windowCounts.c > counts.c - k) {
+      windowCounts[s[left]]--;
+      left++;
+    }
+
+    maxWindow = Math.max(maxWindow, right - left + 1);
+  }
+
+  return n - maxWindow;
+};
diff --git a/solutions/2517-maximum-tastiness-of-candy-basket.js b/solutions/2517-maximum-tastiness-of-candy-basket.js
new file mode 100644
index 00000000..6ef4a383
--- /dev/null
+++ b/solutions/2517-maximum-tastiness-of-candy-basket.js
@@ -0,0 +1,47 @@
+/**
+ * 2517. Maximum Tastiness of Candy Basket
+ * https://leetcode.com/problems/maximum-tastiness-of-candy-basket/
+ * Difficulty: Medium
+ *
+ * You are given an array of positive integers price where price[i] denotes the price of the ith
+ * candy and a positive integer k.
+ *
+ * The store sells baskets of k distinct candies. The tastiness of a candy basket is the smallest
+ * absolute difference of the prices of any two candies in the basket.
+ *
+ * Return the maximum tastiness of a candy basket.
+ */
+
+/**
+ * @param {number[]} price
+ * @param {number} k
+ * @return {number}
+ */
+var maximumTastiness = function(price, k) {
+  price.sort((a, b) => a - b);
+  let left = 0;
+  let right = price[price.length - 1] - price[0];
+  let result = 0;
+
+  while (left <= right) {
+    const mid = Math.floor((left + right) / 2);
+    let count = 1;
+    let prev = price[0];
+
+    for (let i = 1; i < price.length; i++) {
+      if (price[i] - prev >= mid) {
+        count++;
+        prev = price[i];
+      }
+    }
+
+    if (count >= k) {
+      result = mid;
+      left = mid + 1;
+    } else {
+      right = mid - 1;
+    }
+  }
+
+  return result;
+};
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/2520-count-the-digits-that-divide-a-number.js b/solutions/2520-count-the-digits-that-divide-a-number.js
new file mode 100644
index 00000000..614d3add
--- /dev/null
+++ b/solutions/2520-count-the-digits-that-divide-a-number.js
@@ -0,0 +1,25 @@
+/**
+ * 2520. Count the Digits That Divide a Number
+ * https://leetcode.com/problems/count-the-digits-that-divide-a-number/
+ * Difficulty: Easy
+ *
+ * Given an integer num, return the number of digits in num that divide num.
+ *
+ * An integer val divides nums if nums % val == 0.
+ */
+
+/**
+ * @param {number} num
+ * @return {number}
+ */
+var countDigits = function(num) {
+  let result = 0;
+  let n = num;
+
+  while (n > 0) {
+    if (num % (n % 10) === 0) result++;
+    n = Math.floor(n / 10);
+  }
+
+  return result;
+};
diff --git a/solutions/2521-distinct-prime-factors-of-product-of-array.js b/solutions/2521-distinct-prime-factors-of-product-of-array.js
new file mode 100644
index 00000000..6d723c46
--- /dev/null
+++ b/solutions/2521-distinct-prime-factors-of-product-of-array.js
@@ -0,0 +1,36 @@
+/**
+ * 2521. Distinct Prime Factors of Product of Array
+ * https://leetcode.com/problems/distinct-prime-factors-of-product-of-array/
+ * Difficulty: Medium
+ *
+ * Given an array of positive integers nums, return the number of distinct prime factors in the
+ * product of the elements of nums.
+ *
+ * Note that:
+ * - A number greater than 1 is called prime if it is divisible by only 1 and itself.
+ * - An integer val1 is a factor of another integer val2 if val2 / val1 is an integer.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var distinctPrimeFactors = function(nums) {
+  const set = new Set();
+
+  for (const num of nums) {
+    factorize(num);
+  }
+
+  return set.size;
+
+  function factorize(num) {
+    for (let i = 2; i * i <= num; i++) {
+      while (num % i === 0) {
+        set.add(i);
+        num /= i;
+      }
+    }
+    if (num > 1) set.add(num);
+  }
+};
diff --git a/solutions/2522-partition-string-into-substrings-with-values-at-most-k.js b/solutions/2522-partition-string-into-substrings-with-values-at-most-k.js
new file mode 100644
index 00000000..f5777dcf
--- /dev/null
+++ b/solutions/2522-partition-string-into-substrings-with-values-at-most-k.js
@@ -0,0 +1,42 @@
+/**
+ * 2522. Partition String Into Substrings With Values at Most K
+ * https://leetcode.com/problems/partition-string-into-substrings-with-values-at-most-k/
+ * Difficulty: Medium
+ *
+ * You are given a string s consisting of digits from 1 to 9 and an integer k.
+ *
+ * A partition of a string s is called good if:
+ * - Each digit of s is part of exactly one substring.
+ * - The value of each substring is less than or equal to k.
+ *
+ * Return the minimum number of substrings in a good partition of s. If no good partition of
+ * s exists, return -1.
+ *
+ * Note that:
+ * - The value of a string is its result when interpreted as an integer. For example, the value
+ *   of "123" is 123 and the value of "1" is 1.
+ * - A substring is a contiguous sequence of characters within a string.
+ */
+
+/**
+ * @param {string} s
+ * @param {number} k
+ * @return {number}
+ */
+var minimumPartition = function(s, k) {
+  let result = 1;
+  let current = 0;
+
+  for (const digit of s) {
+    const value = current * 10 + Number(digit);
+    if (value <= k) {
+      current = value;
+    } else {
+      if (Number(digit) > k) return -1;
+      current = Number(digit);
+      result++;
+    }
+  }
+
+  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/2527-find-xor-beauty-of-array.js b/solutions/2527-find-xor-beauty-of-array.js
new file mode 100644
index 00000000..172eb3e2
--- /dev/null
+++ b/solutions/2527-find-xor-beauty-of-array.js
@@ -0,0 +1,30 @@
+/**
+ * 2527. Find Xor-Beauty of Array
+ * https://leetcode.com/problems/find-xor-beauty-of-array/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums.
+ *
+ * The effective value of three indices i, j, and k is defined as ((nums[i] | nums[j]) & nums[k]).
+ *
+ * The xor-beauty of the array is the XORing of the effective values of all the possible triplets
+ * of indices (i, j, k) where 0 <= i, j, k < n.
+ *
+ * Return the xor-beauty of nums.
+ *
+ * Note that:
+ * - val1 | val2 is bitwise OR of val1 and val2.
+ * - val1 & val2 is bitwise AND of val1 and val2.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var xorBeauty = function(nums) {
+  let result = 0;
+  for (const num of nums) {
+    result ^= num;
+  }
+  return result;
+};
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/2536-increment-submatrices-by-one.js b/solutions/2536-increment-submatrices-by-one.js
new file mode 100644
index 00000000..c5acdddd
--- /dev/null
+++ b/solutions/2536-increment-submatrices-by-one.js
@@ -0,0 +1,46 @@
+/**
+ * 2536. Increment Submatrices by One
+ * https://leetcode.com/problems/increment-submatrices-by-one/
+ * Difficulty: Medium
+ *
+ * You are given a positive integer n, indicating that we initially have an n x n 0-indexed integer
+ * matrix mat filled with zeroes.
+ *
+ * You are also given a 2D integer array query. For each query[i] = [row1i, col1i, row2i, col2i],
+ * you should do the following operation:
+ * - Add 1 to every element in the submatrix with the top left corner (row1i, col1i) and the bottom
+ *   right corner (row2i, col2i). That is, add 1 to mat[x][y] for all row1i <= x <= row2i and
+ *   col1i <= y <= col2i.
+ *
+ * Return the matrix mat after performing every query.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[][]} queries
+ * @return {number[][]}
+ */
+var rangeAddQueries = function(n, queries) {
+  const matrix = new Array(n).fill().map(() => new Array(n).fill(0));
+
+  for (const [row1, col1, row2, col2] of queries) {
+    matrix[row1][col1]++;
+    if (row2 + 1 < n) matrix[row2 + 1][col1]--;
+    if (col2 + 1 < n) matrix[row1][col2 + 1]--;
+    if (row2 + 1 < n && col2 + 1 < n) matrix[row2 + 1][col2 + 1]++;
+  }
+
+  for (let i = 0; i < n; i++) {
+    for (let j = 1; j < n; j++) {
+      matrix[i][j] += matrix[i][j - 1];
+    }
+  }
+
+  for (let i = 1; i < n; i++) {
+    for (let j = 0; j < n; j++) {
+      matrix[i][j] += matrix[i - 1][j];
+    }
+  }
+
+  return matrix;
+};
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/2540-minimum-common-value.js b/solutions/2540-minimum-common-value.js
new file mode 100644
index 00000000..32b8dea1
--- /dev/null
+++ b/solutions/2540-minimum-common-value.js
@@ -0,0 +1,29 @@
+/**
+ * 2540. Minimum Common Value
+ * https://leetcode.com/problems/minimum-common-value/
+ * Difficulty: Easy
+ *
+ * Given two integer arrays nums1 and nums2, sorted in non-decreasing order, return the minimum
+ * integer common to both arrays. If there is no common integer amongst nums1 and nums2, return -1.
+ *
+ * Note that an integer is said to be common to nums1 and nums2 if both arrays have at least one
+ * occurrence of that integer.
+ */
+
+/**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number}
+ */
+var getCommon = function(nums1, nums2) {
+  let i = 0;
+  let j = 0;
+
+  while (i < nums1.length && j < nums2.length) {
+    if (nums1[i] === nums2[j]) return nums1[i];
+    if (nums1[i] < nums2[j]) i++;
+    else j++;
+  }
+
+  return -1;
+};
diff --git a/solutions/2543-check-if-point-is-reachable.js b/solutions/2543-check-if-point-is-reachable.js
new file mode 100644
index 00000000..31d51902
--- /dev/null
+++ b/solutions/2543-check-if-point-is-reachable.js
@@ -0,0 +1,40 @@
+/**
+ * 2543. Check if Point Is Reachable
+ * https://leetcode.com/problems/check-if-point-is-reachable/
+ * Difficulty: Hard
+ *
+ * There exists an infinitely large grid. You are currently at point (1, 1), and you need
+ * to reach the point (targetX, targetY) using a finite number of steps.
+ *
+ * In one step, you can move from point (x, y) to any one of the following points:
+ * - (x, y - x)
+ * - (x - y, y)
+ * - (2 * x, y)
+ * - (x, 2 * y)
+ *
+ * Given two integers targetX and targetY representing the X-coordinate and Y-coordinate of
+ * your final position, return true if you can reach the point from (1, 1) using some number
+ * of steps, and false otherwise.
+ */
+
+/**
+ * @param {number} targetX
+ * @param {number} targetY
+ * @return {boolean}
+ */
+var isReachable = function(targetX, targetY) {
+  let g = gcd(targetX, targetY);
+  while (g % 2 === 0) {
+    g /= 2;
+  }
+
+  return g === 1;
+};
+
+function gcd(a, b) {
+  while (b) {
+    a %= b;
+    [a, b] = [b, a];
+  }
+  return a;
+}
diff --git a/solutions/2544-alternating-digit-sum.js b/solutions/2544-alternating-digit-sum.js
new file mode 100644
index 00000000..49aa7939
--- /dev/null
+++ b/solutions/2544-alternating-digit-sum.js
@@ -0,0 +1,29 @@
+/**
+ * 2544. Alternating Digit Sum
+ * https://leetcode.com/problems/alternating-digit-sum/
+ * Difficulty: Easy
+ *
+ * You are given a positive integer n. Each digit of n has a sign according to the following rules:
+ * - The most significant digit is assigned a positive sign.
+ * - Each other digit has an opposite sign to its adjacent digits.
+ *
+ * Return the sum of all digits with their corresponding sign.
+ */
+
+/**
+ * @param {number} n
+ * @return {number}
+ */
+var alternateDigitSum = function(n) {
+  let sum = 0;
+  let isPositive = true;
+
+  while (n > 0) {
+    const digit = n % 10;
+    sum += isPositive ? digit : -digit;
+    isPositive = !isPositive;
+    n = Math.floor(n / 10);
+  }
+
+  return isPositive ? -sum : sum;
+};
diff --git a/solutions/2545-sort-the-students-by-their-kth-score.js b/solutions/2545-sort-the-students-by-their-kth-score.js
new file mode 100644
index 00000000..55464ba9
--- /dev/null
+++ b/solutions/2545-sort-the-students-by-their-kth-score.js
@@ -0,0 +1,23 @@
+/**
+ * 2545. Sort the Students by Their Kth Score
+ * https://leetcode.com/problems/sort-the-students-by-their-kth-score/
+ * Difficulty: Medium
+ *
+ * There is a class with m students and n exams. You are given a 0-indexed m x n integer matrix
+ * score, where each row represents one student and score[i][j] denotes the score the ith student
+ * got in the jth exam. The matrix score contains distinct integers only.
+ *
+ * You are also given an integer k. Sort the students (i.e., the rows of the matrix) by their
+ * scores in the kth (0-indexed) exam from the highest to the lowest.
+ *
+ * Return the matrix after sorting it.
+ */
+
+/**
+ * @param {number[][]} score
+ * @param {number} k
+ * @return {number[][]}
+ */
+var sortTheStudents = function(score, k) {
+  return score.sort((studentA, studentB) => studentB[k] - studentA[k]);
+};
diff --git a/solutions/2546-apply-bitwise-operations-to-make-strings-equal.js b/solutions/2546-apply-bitwise-operations-to-make-strings-equal.js
new file mode 100644
index 00000000..e3b401a5
--- /dev/null
+++ b/solutions/2546-apply-bitwise-operations-to-make-strings-equal.js
@@ -0,0 +1,25 @@
+/**
+ * 2546. Apply Bitwise Operations to Make Strings Equal
+ * https://leetcode.com/problems/apply-bitwise-operations-to-make-strings-equal/
+ * Difficulty: Medium
+ *
+ * You are given two 0-indexed binary strings s and target of the same length n. You can do the
+ * following operation on s any number of times:
+ * - Choose two different indices i and j where 0 <= i, j < n.
+ * - Simultaneously, replace s[i] with (s[i] OR s[j]) and s[j] with (s[i] XOR s[j]).
+ *
+ * For example, if s = "0110", you can choose i = 0 and j = 2, then simultaneously replace s[0]
+ * with (s[0] OR s[2] = 0 OR 1 = 1), and s[2] with (s[0] XOR s[2] = 0 XOR 1 = 1), so we will
+ * have s = "1110".
+ *
+ * Return true if you can make the string s equal to target, or false otherwise.
+ */
+
+/**
+ * @param {string} s
+ * @param {string} target
+ * @return {boolean}
+ */
+var makeStringsEqual = function(s, target) {
+  return (s.includes('1') === target.includes('1'));
+};
diff --git a/solutions/2547-minimum-cost-to-split-an-array.js b/solutions/2547-minimum-cost-to-split-an-array.js
new file mode 100644
index 00000000..04732298
--- /dev/null
+++ b/solutions/2547-minimum-cost-to-split-an-array.js
@@ -0,0 +1,48 @@
+/**
+ * 2547. Minimum Cost to Split an Array
+ * https://leetcode.com/problems/minimum-cost-to-split-an-array/
+ * Difficulty: Hard
+ *
+ * You are given an integer array nums and an integer k.
+ *
+ * Split the array into some number of non-empty subarrays. The cost of a split is the sum of
+ * the importance value of each subarray in the split.
+ *
+ * Let trimmed(subarray) be the version of the subarray where all numbers which appear only
+ * once are removed.
+ * - For example, trimmed([3,1,2,4,3,4]) = [3,4,3,4].
+ *
+ * The importance value of a subarray is k + trimmed(subarray).length.
+ * - For example, if a subarray is [1,2,3,3,3,4,4], then trimmed([1,2,3,3,3,4,4]) = [3,3,3,4,4].
+ *   The importance value of this subarray will be k + 5.
+ *
+ * Return the minimum possible cost of a split of nums.
+ *
+ * A subarray is a contiguous non-empty sequence of elements within an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var minCost = function(nums, k) {
+  const n = nums.length;
+  const dp = new Array(n + 1).fill(Infinity);
+  dp[0] = 0;
+
+  for (let end = 1; end <= n; end++) {
+    const freq = new Map();
+    let trimLen = 0;
+    for (let start = end - 1; start >= 0; start--) {
+      const num = nums[start];
+      const count = (freq.get(num) || 0) + 1;
+      freq.set(num, count);
+      if (count === 1) trimLen++;
+      if (count === 2) trimLen--;
+      dp[end] = Math.min(dp[end], dp[start] + k + (end - start - trimLen));
+    }
+  }
+
+  return dp[n];
+};
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/2549-count-distinct-numbers-on-board.js b/solutions/2549-count-distinct-numbers-on-board.js
new file mode 100644
index 00000000..861cd59d
--- /dev/null
+++ b/solutions/2549-count-distinct-numbers-on-board.js
@@ -0,0 +1,24 @@
+/**
+ * 2549. Count Distinct Numbers on Board
+ * https://leetcode.com/problems/count-distinct-numbers-on-board/
+ * Difficulty: Easy
+ *
+ * You are given a positive integer n, that is initially placed on a board. Every day, for
+ * 109 days, you perform the following procedure:
+ * - For each number x present on the board, find all numbers 1 <= i <= n such that x % i == 1.
+ * - Then, place those numbers on the board.
+ *
+ * Return the number of distinct integers present on the board after 109 days have elapsed.
+ *
+ * Note:
+ * - Once a number is placed on the board, it will remain on it until the end.
+ * - % stands for the modulo operation. For example, 14 % 3 is 2.
+ */
+
+/**
+ * @param {number} n
+ * @return {number}
+ */
+var distinctIntegers = function(n) {
+  return n === 1 ? 1 : n - 1;
+};
diff --git a/solutions/2553-separate-the-digits-in-an-array.js b/solutions/2553-separate-the-digits-in-an-array.js
new file mode 100644
index 00000000..1255dfb6
--- /dev/null
+++ b/solutions/2553-separate-the-digits-in-an-array.js
@@ -0,0 +1,19 @@
+/**
+ * 2553. Separate the Digits in an Array
+ * https://leetcode.com/problems/separate-the-digits-in-an-array/
+ * Difficulty: Easy
+ *
+ * Given an array of positive integers nums, return an array answer that consists of the digits
+ * of each integer in nums after separating them in the same order they appear in nums.
+ *
+ * To separate the digits of an integer is to get all the digits it has in the same order.
+ * - For example, for the integer 10921, the separation of its digits is [1,0,9,2,1].
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var separateDigits = function(nums) {
+  return nums.flatMap(num => String(num).split('').map(Number));
+};
diff --git a/solutions/2554-maximum-number-of-integers-to-choose-from-a-range-i.js b/solutions/2554-maximum-number-of-integers-to-choose-from-a-range-i.js
new file mode 100644
index 00000000..bb160607
--- /dev/null
+++ b/solutions/2554-maximum-number-of-integers-to-choose-from-a-range-i.js
@@ -0,0 +1,35 @@
+/**
+ * 2554. Maximum Number of Integers to Choose From a Range I
+ * https://leetcode.com/problems/maximum-number-of-integers-to-choose-from-a-range-i/
+ * 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 set = new Set(banned);
+  let result = 0;
+  let currentSum = 0;
+
+  for (let num = 1; num <= n; num++) {
+    if (!set.has(num) && currentSum + num <= maxSum) {
+      result++;
+      currentSum += num;
+    }
+  }
+
+  return result;
+};
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/2562-find-the-array-concatenation-value.js b/solutions/2562-find-the-array-concatenation-value.js
new file mode 100644
index 00000000..b35decfc
--- /dev/null
+++ b/solutions/2562-find-the-array-concatenation-value.js
@@ -0,0 +1,42 @@
+/**
+ * 2562. Find the Array Concatenation Value
+ * https://leetcode.com/problems/find-the-array-concatenation-value/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed integer array nums.
+ *
+ * The concatenation of two numbers is the number formed by concatenating their numerals.
+ * - For example, the concatenation of 15, 49 is 1549.
+ *
+ * The concatenation value of nums is initially equal to 0. Perform this operation until nums
+ * becomes empty:
+ * - If nums has a size greater than one, add the value of the concatenation of the first and
+ *   the last element to the concatenation value of nums, and remove those two elements from
+ *   nums. For example, if the nums was [1, 2, 4, 5, 6], add 16 to the concatenation value.
+ * - If only one element exists in nums, add its value to the concatenation value of nums,
+ *   then remove it.
+ *
+ * Return the concatenation value of nums.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var findTheArrayConcVal = function(nums) {
+  let result = 0;
+  let left = 0;
+  let right = nums.length - 1;
+
+  while (left <= right) {
+    if (left === right) {
+      result += nums[left];
+    } else {
+      result += Number(`${nums[left]}${nums[right]}`);
+    }
+    left++;
+    right--;
+  }
+
+  return result;
+};
diff --git a/solutions/2563-count-the-number-of-fair-pairs.js b/solutions/2563-count-the-number-of-fair-pairs.js
new file mode 100644
index 00000000..bcacc7b3
--- /dev/null
+++ b/solutions/2563-count-the-number-of-fair-pairs.js
@@ -0,0 +1,56 @@
+/**
+ * 2563. Count the Number of Fair Pairs
+ * https://leetcode.com/problems/count-the-number-of-fair-pairs/
+ * Difficulty: Medium
+ *
+ * Given a 0-indexed integer array nums of size n and two integers lower and upper, return the
+ * number of fair pairs.
+ *
+ * A pair (i, j) is fair if:
+ * - 0 <= i < j < n, and
+ * - lower <= nums[i] + nums[j] <= upper
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} lower
+ * @param {number} upper
+ * @return {number}
+ */
+var countFairPairs = function(nums, lower, upper) {
+  let result = 0;
+
+  nums.sort((a, b) => a - b);
+
+  for (let i = 0; i < nums.length - 1; i++) {
+    const minTarget = lower - nums[i];
+    const maxTarget = upper - nums[i];
+
+    const first = findFirstValidIndex(i + 1, minTarget);
+    const last = findFirstValidIndex(i + 1, maxTarget + 1) - 1;
+
+    if (first <= last) {
+      result += last - first + 1;
+    }
+  }
+
+  return result;
+
+  function findFirstValidIndex(start, target) {
+    let left = start;
+    let right = nums.length - 1;
+    let index = nums.length;
+
+    while (left <= right) {
+      const mid = Math.floor((left + right) / 2);
+      if (nums[mid] >= target) {
+        index = mid;
+        right = mid - 1;
+      } else {
+        left = mid + 1;
+      }
+    }
+
+    return index;
+  }
+};
diff --git a/solutions/2566-maximum-difference-by-remapping-a-digit.js b/solutions/2566-maximum-difference-by-remapping-a-digit.js
new file mode 100644
index 00000000..55898513
--- /dev/null
+++ b/solutions/2566-maximum-difference-by-remapping-a-digit.js
@@ -0,0 +1,40 @@
+/**
+ * 2566. Maximum Difference by Remapping a Digit
+ * https://leetcode.com/problems/maximum-difference-by-remapping-a-digit/
+ * Difficulty: Easy
+ *
+ * You are given an integer num. You know that Bob will sneakily remap one of the 10 possible
+ * digits (0 to 9) to another digit.
+ *
+ * Return the difference between the maximum and minimum values Bob can make by remapping
+ * exactly one digit in num.
+ *
+ * Notes:
+ * - When Bob remaps a digit d1 to another digit d2, Bob replaces all occurrences of d1 in
+ *   num with d2.
+ * - Bob can remap a digit to itself, in which case num does not change.
+ * - Bob can remap different digits for obtaining minimum and maximum values respectively.
+ * - The resulting number after remapping can contain leading zeroes.
+ */
+
+/**
+ * @param {number} num
+ * @return {number}
+ */
+var minMaxDifference = function(num) {
+  const digits = String(num).split('');
+  let maxNum = num;
+  let minNum = num;
+
+  for (let i = 0; i < 10; i++) {
+    const digit = String(i);
+    if (digits.includes(digit)) {
+      const maxCandidate = Number(digits.join('').replaceAll(digit, '9'));
+      const minCandidate = Number(digits.join('').replaceAll(digit, '0'));
+      maxNum = Math.max(maxNum, maxCandidate);
+      minNum = Math.min(minNum, minCandidate);
+    }
+  }
+
+  return maxNum - minNum;
+};
diff --git a/solutions/2567-minimum-score-by-changing-two-elements.js b/solutions/2567-minimum-score-by-changing-two-elements.js
new file mode 100644
index 00000000..a5f5d1c5
--- /dev/null
+++ b/solutions/2567-minimum-score-by-changing-two-elements.js
@@ -0,0 +1,26 @@
+/**
+ * 2567. Minimum Score by Changing Two Elements
+ * https://leetcode.com/problems/minimum-score-by-changing-two-elements/
+ * Difficulty: Medium
+ *
+ * You are given an integer array nums.
+ * - The low score of nums is the minimum absolute difference between any two integers.
+ * - The high score of nums is the maximum absolute difference between any two integers.
+ * - The score of nums is the sum of the high and low scores.
+ *
+ * Return the minimum score after changing two elements of nums.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var minimizeSum = function(nums) {
+  const sorted = nums.sort((a, b) => a - b);
+
+  return Math.min(
+    sorted[sorted.length - 2] - sorted[1],
+    sorted[sorted.length - 1] - sorted[2],
+    sorted[sorted.length - 3] - sorted[0]
+  );
+};
diff --git a/solutions/2568-minimum-impossible-or.js b/solutions/2568-minimum-impossible-or.js
new file mode 100644
index 00000000..6cb1df58
--- /dev/null
+++ b/solutions/2568-minimum-impossible-or.js
@@ -0,0 +1,30 @@
+/**
+ * 2568. Minimum Impossible OR
+ * https://leetcode.com/problems/minimum-impossible-or/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums.
+ *
+ * We say that an integer x is expressible from nums if there exist some integers
+ * 0 <= index1 < index2 < ... < indexk < nums.length for which
+ * nums[index1] | nums[index2] | ... | nums[indexk] = x. In other words, an
+ * integer is expressible if it can be written as the bitwise OR of some subsequence
+ * of nums.
+ *
+ * Return the minimum positive non-zero integer that is not expressible from nums.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var minImpossibleOR = function(nums) {
+  const set = new Set(nums);
+  let result = 1;
+
+  while (set.has(result)) {
+    result <<= 1;
+  }
+
+  return result;
+};
diff --git a/solutions/2571-minimum-operations-to-reduce-an-integer-to-0.js b/solutions/2571-minimum-operations-to-reduce-an-integer-to-0.js
new file mode 100644
index 00000000..0ee9bb23
--- /dev/null
+++ b/solutions/2571-minimum-operations-to-reduce-an-integer-to-0.js
@@ -0,0 +1,34 @@
+/**
+ * 2571. Minimum Operations to Reduce an Integer to 0
+ * https://leetcode.com/problems/minimum-operations-to-reduce-an-integer-to-0/
+ * Difficulty: Medium
+ *
+ * You are given a positive integer n, you can do the following operation any number of times:
+ * - Add or subtract a power of 2 from n.
+ *
+ * Return the minimum number of operations to make n equal to 0.
+ *
+ * A number x is power of 2 if x == 2i where i >= 0.
+ */
+
+/**
+ * @param {number} n
+ * @return {number}
+ */
+var minOperations = function(n) {
+  let result = 0;
+
+  while (n > 0) {
+    if ((n & 1) === 0) {
+      n >>= 1;
+    } else if ((n & 3) === 3) {
+      n += 1;
+      result++;
+    } else {
+      n -= 1;
+      result++;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2574-left-and-right-sum-differences.js b/solutions/2574-left-and-right-sum-differences.js
new file mode 100644
index 00000000..e3292140
--- /dev/null
+++ b/solutions/2574-left-and-right-sum-differences.js
@@ -0,0 +1,34 @@
+/**
+ * 2574. Left and Right Sum Differences
+ * https://leetcode.com/problems/left-and-right-sum-differences/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed integer array nums of size n.
+ *
+ * Define two arrays leftSum and rightSum where:
+ * - leftSum[i] is the sum of elements to the left of the index i in the array nums.
+ *   If there is no such element, leftSum[i] = 0.
+ * - rightSum[i] is the sum of elements to the right of the index i in the array nums.
+ *   If there is no such element, rightSum[i] = 0.
+ *
+ * Return an integer array answer of size n where answer[i] = |leftSum[i] - rightSum[i]|.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var leftRightDifference = function(nums) {
+  const n = nums.length;
+  const result = new Array(n).fill(0);
+  let leftSum = 0;
+  let rightSum = nums.reduce((sum, num) => sum + num, 0);
+
+  for (let i = 0; i < n; i++) {
+    rightSum -= nums[i];
+    result[i] = Math.abs(leftSum - rightSum);
+    leftSum += nums[i];
+  }
+
+  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/2578-split-with-minimum-sum.js b/solutions/2578-split-with-minimum-sum.js
new file mode 100644
index 00000000..3d81e46c
--- /dev/null
+++ b/solutions/2578-split-with-minimum-sum.js
@@ -0,0 +1,38 @@
+/**
+ * 2578. Split With Minimum Sum
+ * https://leetcode.com/problems/split-with-minimum-sum/
+ * Difficulty: Easy
+ *
+ * Given a positive integer num, split it into two non-negative integers num1 and num2 such that:
+ * - The concatenation of num1 and num2 is a permutation of num.
+ *   - In other words, the sum of the number of occurrences of each digit in num1 and num2 is equal
+ *     to the number of occurrences of that digit in num.
+ * - num1 and num2 can contain leading zeros.
+ *
+ * Return the minimum possible sum of num1 and num2.
+ *
+ * Notes:
+ * - It is guaranteed that num does not contain any leading zeros.
+ * - The order of occurrence of the digits in num1 and num2 may differ from the order of occurrence
+ *   of num.
+ */
+
+/**
+ * @param {number} num
+ * @return {number}
+ */
+var splitNum = function(num) {
+  const digits = String(num).split('').sort((a, b) => a - b);
+  let num1 = '';
+  let num2 = '';
+
+  for (let i = 0; i < digits.length; i++) {
+    if (i % 2 === 0) {
+      num1 += digits[i];
+    } else {
+      num2 += digits[i];
+    }
+  }
+
+  return Number(num1) + Number(num2);
+};
diff --git a/solutions/2581-count-number-of-possible-root-nodes.js b/solutions/2581-count-number-of-possible-root-nodes.js
new file mode 100644
index 00000000..4d879928
--- /dev/null
+++ b/solutions/2581-count-number-of-possible-root-nodes.js
@@ -0,0 +1,78 @@
+/**
+ * 2581. Count Number of Possible Root Nodes
+ * https://leetcode.com/problems/count-number-of-possible-root-nodes/
+ * Difficulty: Hard
+ *
+ * Alice has an undirected tree with n nodes labeled from 0 to n - 1. The tree is represented as 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.
+ *
+ * Alice wants Bob to find the root of the tree. She allows Bob to make several guesses about her
+ * tree. In one guess, he does the following:
+ * - Chooses two distinct integers u and v such that there exists an edge [u, v] in the tree.
+ * - He tells Alice that u is the parent of v in the tree.
+ *
+ * Bob's guesses are represented by a 2D integer array guesses where guesses[j] = [uj, vj] indicates
+ * Bob guessed uj to be the parent of vj.
+ *
+ * Alice being lazy, does not reply to each of Bob's guesses, but just says that at least k of his
+ * guesses are true.
+ *
+ * Given the 2D integer arrays edges, guesses and the integer k, return the number of possible
+ * nodes that can be the root of Alice's tree. If there is no such tree, return 0.
+ */
+
+/**
+ * @param {number[][]} edges
+ * @param {number[][]} guesses
+ * @param {number} k
+ * @return {number}
+ */
+var rootCount = function(edges, guesses, k) {
+  const n = edges.length + 1;
+  const adj = Array.from({ length: n }, () => new Set());
+  const set = new Set();
+
+  for (const [u, v] of edges) {
+    adj[u].add(v);
+    adj[v].add(u);
+  }
+
+  for (const [u, v] of guesses) {
+    set.add(u * n + v);
+  }
+
+  const rootCorrect = dfs(0, -1);
+  let result = rootCorrect >= k ? 1 : 0;
+
+  for (const neighbor of adj[0]) {
+    helper(neighbor, 0, rootCorrect);
+  }
+
+  return result;
+
+  function helper(node, parent, parentCorrect) {
+    let count = parentCorrect;
+    if (set.has(parent * n + node)) count--;
+    if (set.has(node * n + parent)) count++;
+
+    if (count >= k) result++;
+
+    for (const neighbor of adj[node]) {
+      if (neighbor !== parent) {
+        helper(neighbor, node, count);
+      }
+    }
+  }
+
+  function dfs(node, parent) {
+    let count = 0;
+    for (const neighbor of adj[node]) {
+      if (neighbor !== parent) {
+        if (set.has(node * n + neighbor)) count++;
+        count += dfs(neighbor, node);
+      }
+    }
+    return count;
+  }
+};
diff --git a/solutions/2582-pass-the-pillow.js b/solutions/2582-pass-the-pillow.js
new file mode 100644
index 00000000..6f1a17a9
--- /dev/null
+++ b/solutions/2582-pass-the-pillow.js
@@ -0,0 +1,25 @@
+/**
+ * 2582. Pass the Pillow
+ * https://leetcode.com/problems/pass-the-pillow/
+ * Difficulty: Easy
+ *
+ * There are n people standing in a line labeled from 1 to n. The first person in the line is
+ * holding a pillow initially. Every second, the person holding the pillow passes it to the
+ * next person standing in the line. Once the pillow reaches the end of the line, the direction
+ * changes, and people continue passing the pillow in the opposite direction.
+ * - For example, once the pillow reaches the nth person they pass it to the n - 1th person,
+ *   then to the n - 2th person and so on.
+ *
+ * Given the two positive integers n and time, return the index of the person holding the pillow
+ * after time seconds.
+ */
+
+/**
+ * @param {number} n
+ * @param {number} time
+ * @return {number}
+ */
+var passThePillow = function(n, time) {
+  const position = time % (2 * (n - 1));
+  return position < n ? position + 1 : 2 * n - position - 1;
+};
diff --git a/solutions/2583-kth-largest-sum-in-a-binary-tree.js b/solutions/2583-kth-largest-sum-in-a-binary-tree.js
new file mode 100644
index 00000000..b8759f23
--- /dev/null
+++ b/solutions/2583-kth-largest-sum-in-a-binary-tree.js
@@ -0,0 +1,50 @@
+/**
+ * 2583. Kth Largest Sum in a Binary Tree
+ * https://leetcode.com/problems/kth-largest-sum-in-a-binary-tree/
+ * Difficulty: Medium
+ *
+ * You are given the root of a binary tree and a positive integer k.
+ *
+ * The level sum in the tree is the sum of the values of the nodes that are on the same level.
+ *
+ * Return the kth largest level sum in the tree (not necessarily distinct). If there are fewer
+ * than k levels in the tree, return -1.
+ *
+ * Note that two nodes are on the same level if they have the same distance from the root.
+ */
+
+/**
+ * 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 kthLargestLevelSum = function(root, k) {
+  const levelSums = [];
+  const queue = [root];
+
+  while (queue.length) {
+    let levelSize = queue.length;
+    let levelSum = 0;
+
+    while (levelSize--) {
+      const node = queue.shift();
+      levelSum += node.val;
+      if (node.left) queue.push(node.left);
+      if (node.right) queue.push(node.right);
+    }
+
+    levelSums.push(levelSum);
+  }
+
+  if (levelSums.length < k) return -1;
+
+  return levelSums.sort((a, b) => b - a)[k - 1];
+};
diff --git a/solutions/2585-number-of-ways-to-earn-points.js b/solutions/2585-number-of-ways-to-earn-points.js
new file mode 100644
index 00000000..a88d5050
--- /dev/null
+++ b/solutions/2585-number-of-ways-to-earn-points.js
@@ -0,0 +1,37 @@
+/**
+ * 2585. Number of Ways to Earn Points
+ * https://leetcode.com/problems/number-of-ways-to-earn-points/
+ * Difficulty: Hard
+ *
+ * There is a test that has n types of questions. You are given an integer target and a 0-indexed
+ * 2D integer array types where types[i] = [counti, marksi] indicates that there are counti
+ * questions of the ith type, and each one of them is worth marksi points.
+ *
+ * Return the number of ways you can earn exactly target points in the exam. Since the answer may
+ * be too large, return it modulo 109 + 7.
+ *
+ * Note that questions of the same type are indistinguishable.
+ * - For example, if there are 3 questions of the same type, then solving the 1st and 2nd questions
+ *   is the same as solving the 1st and 3rd questions, or the 2nd and 3rd questions.
+ */
+
+/**
+ * @param {number} target
+ * @param {number[][]} types
+ * @return {number}
+ */
+var waysToReachTarget = function(target, types) {
+  const MOD = 1e9 + 7;
+  const dp = new Array(target + 1).fill(0);
+  dp[0] = 1;
+
+  for (const [count, marks] of types) {
+    for (let points = target; points >= 0; points--) {
+      for (let k = 1; k <= count && points >= k * marks; k++) {
+        dp[points] = (dp[points] + dp[points - k * marks]) % MOD;
+      }
+    }
+  }
+
+  return dp[target];
+};
diff --git a/solutions/2586-count-the-number-of-vowel-strings-in-range.js b/solutions/2586-count-the-number-of-vowel-strings-in-range.js
new file mode 100644
index 00000000..feff0ca4
--- /dev/null
+++ b/solutions/2586-count-the-number-of-vowel-strings-in-range.js
@@ -0,0 +1,32 @@
+/**
+ * 2586. Count the Number of Vowel Strings in Range
+ * https://leetcode.com/problems/count-the-number-of-vowel-strings-in-range/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed array of string words and two integers left and right.
+ *
+ * A string is called a vowel string if it starts with a vowel character and ends with
+ * a vowel character where vowel characters are 'a', 'e', 'i', 'o', and 'u'.
+ *
+ * Return the number of vowel strings words[i] where i belongs to the inclusive range [left, right].
+ */
+
+/**
+ * @param {string[]} words
+ * @param {number} left
+ * @param {number} right
+ * @return {number}
+ */
+var vowelStrings = function(words, left, right) {
+  const vowels = new Set(['a', 'e', 'i', 'o', 'u']);
+  let result = 0;
+
+  for (let i = left; i <= right; i++) {
+    const word = words[i];
+    if (vowels.has(word[0]) && vowels.has(word[word.length - 1])) {
+      result++;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2587-rearrange-array-to-maximize-prefix-score.js b/solutions/2587-rearrange-array-to-maximize-prefix-score.js
new file mode 100644
index 00000000..585a0d04
--- /dev/null
+++ b/solutions/2587-rearrange-array-to-maximize-prefix-score.js
@@ -0,0 +1,32 @@
+/**
+ * 2587. Rearrange Array to Maximize Prefix Score
+ * https://leetcode.com/problems/rearrange-array-to-maximize-prefix-score/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums. You can rearrange the elements of nums to any
+ * order (including the given order).
+ *
+ * Let prefix be the array containing the prefix sums of nums after rearranging it. In other words,
+ * prefix[i] is the sum of the elements from 0 to i in nums after rearranging it. The score of nums
+ * is the number of positive integers in the array prefix.
+ *
+ * Return the maximum score you can achieve.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var maxScore = function(nums) {
+  const sorted = nums.sort((a, b) => b - a);
+  let prefixSum = 0;
+  let result = 0;
+
+  for (const num of sorted) {
+    prefixSum += num;
+    if (prefixSum > 0) result++;
+    else break;
+  }
+
+  return result;
+};
diff --git a/solutions/2588-count-the-number-of-beautiful-subarrays.js b/solutions/2588-count-the-number-of-beautiful-subarrays.js
new file mode 100644
index 00000000..122bc329
--- /dev/null
+++ b/solutions/2588-count-the-number-of-beautiful-subarrays.js
@@ -0,0 +1,36 @@
+/**
+ * 2588. Count the Number of Beautiful Subarrays
+ * https://leetcode.com/problems/count-the-number-of-beautiful-subarrays/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums. In one operation, you can:
+ * - Choose two different indices i and j such that 0 <= i, j < nums.length.
+ * - Choose a non-negative integer k such that the kth bit (0-indexed) in the binary representation
+ *   of nums[i] and nums[j] is 1.
+ * - Subtract 2k from nums[i] and nums[j].
+ *
+ * A subarray is beautiful if it is possible to make all of its elements equal to 0 after applying
+ * the above operation any number of times.
+ *
+ * Return the number of beautiful subarrays in the array nums.
+ *
+ * A subarray is a contiguous non-empty sequence of elements within an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var beautifulSubarrays = function(nums) {
+  let result = 0;
+  const prefixXOR = new Map([[0, 1]]);
+  let currentXOR = 0;
+
+  for (const num of nums) {
+    currentXOR ^= num;
+    result += prefixXOR.get(currentXOR) || 0;
+    prefixXOR.set(currentXOR, (prefixXOR.get(currentXOR) || 0) + 1);
+  }
+
+  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/2592-maximize-greatness-of-an-array.js b/solutions/2592-maximize-greatness-of-an-array.js
new file mode 100644
index 00000000..07b1edea
--- /dev/null
+++ b/solutions/2592-maximize-greatness-of-an-array.js
@@ -0,0 +1,36 @@
+/**
+ * 2592. Maximize Greatness of an Array
+ * https://leetcode.com/problems/maximize-greatness-of-an-array/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums. You are allowed to permute nums into a new
+ * array perm of your choosing.
+ *
+ * We define the greatness of nums be the number of indices 0 <= i < nums.length for which
+ * perm[i] > nums[i].
+ *
+ * Return the maximum possible greatness you can achieve after permuting nums.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var maximizeGreatness = function(nums) {
+  nums.sort((a, b) => a - b);
+  let result = 0;
+  let i = 0;
+  let j = 1;
+
+  while (j < nums.length) {
+    if (nums[j] > nums[i]) {
+      result++;
+      i++;
+      j++;
+    } else {
+      j++;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2595-number-of-even-and-odd-bits.js b/solutions/2595-number-of-even-and-odd-bits.js
new file mode 100644
index 00000000..e4508491
--- /dev/null
+++ b/solutions/2595-number-of-even-and-odd-bits.js
@@ -0,0 +1,36 @@
+/**
+ * 2595. Number of Even and Odd Bits
+ * https://leetcode.com/problems/number-of-even-and-odd-bits/
+ * Difficulty: Easy
+ *
+ * You are given a positive integer n.
+ *
+ * Let even denote the number of even indices in the binary representation of n with value 1.
+ *
+ * Let odd denote the number of odd indices in the binary representation of n with value 1.
+ *
+ * Note that bits are indexed from right to left in the binary representation of a number.
+ *
+ * Return the array [even, odd].
+ */
+
+/**
+ * @param {number} n
+ * @return {number[]}
+ */
+var evenOddBit = function(n) {
+  let evenCount = 0;
+  let oddCount = 0;
+  let index = 0;
+
+  while (n > 0) {
+    if (n & 1) {
+      if (index % 2 === 0) evenCount++;
+      else oddCount++;
+    }
+    n >>= 1;
+    index++;
+  }
+
+  return [evenCount, oddCount];
+};
diff --git a/solutions/2596-check-knight-tour-configuration.js b/solutions/2596-check-knight-tour-configuration.js
new file mode 100644
index 00000000..d75bc66a
--- /dev/null
+++ b/solutions/2596-check-knight-tour-configuration.js
@@ -0,0 +1,52 @@
+/**
+ * 2596. Check Knight Tour Configuration
+ * https://leetcode.com/problems/check-knight-tour-configuration/
+ * Difficulty: Medium
+ *
+ * There is a knight on an n x n chessboard. In a valid configuration, the knight starts at the
+ * top-left cell of the board and visits every cell on the board exactly once.
+ *
+ * You are given an n x n integer matrix grid consisting of distinct integers from the range
+ * [0, n * n - 1] where grid[row][col] indicates that the cell (row, col) is the grid[row][col]th
+ * cell that the knight visited. The moves are 0-indexed.
+ *
+ * Return true if grid represents a valid configuration of the knight's movements or false
+ * otherwise.
+ *
+ * Note that a valid knight move consists of moving two squares vertically and one square
+ * horizontally, or two squares horizontally and one square vertically. The figure below
+ * illustrates all the possible eight moves of a knight from some cell.
+ */
+
+/**
+ * @param {number[][]} grid
+ * @return {boolean}
+ */
+var checkValidGrid = function(grid) {
+  const n = grid.length;
+  const moves = [[-2, -1], [-2, 1], [-1, -2], [-1, 2], [1, -2], [1, 2], [2, -1], [2, 1]];
+
+  if (grid[0][0] !== 0) return false;
+
+  const isValidMove = (fromRow, fromCol, toRow, toCol) => {
+    for (const [dr, dc] of moves) {
+      if (fromRow + dr === toRow && fromCol + dc === toCol) return true;
+    }
+    return false;
+  };
+
+  const positions = new Array(n * n).fill(0).map(() => [0, 0]);
+  for (let row = 0; row < n; row++) {
+    for (let col = 0; col < n; col++) {
+      positions[grid[row][col]] = [row, col];
+    }
+  }
+
+  for (let i = 1; i < n * n; i++) {
+    const [prevRow, prevCol] = positions[i - 1];
+    const [currRow, currCol] = positions[i];
+    if (!isValidMove(prevRow, prevCol, currRow, currCol)) return false;
+  }
+
+  return true;
+};
diff --git a/solutions/2597-the-number-of-beautiful-subsets.js b/solutions/2597-the-number-of-beautiful-subsets.js
new file mode 100644
index 00000000..9f72486d
--- /dev/null
+++ b/solutions/2597-the-number-of-beautiful-subsets.js
@@ -0,0 +1,42 @@
+/**
+ * 2597. The Number of Beautiful Subsets
+ * https://leetcode.com/problems/the-number-of-beautiful-subsets/
+ * Difficulty: Medium
+ *
+ * You are given an array nums of positive integers and a positive integer k.
+ *
+ * A subset of nums is beautiful if it does not contain two integers with an absolute difference
+ * equal to k.
+ *
+ * Return the number of non-empty beautiful subsets of the array nums.
+ *
+ * A subset of nums is an array that can be obtained by deleting some (possibly none) elements
+ * from nums. Two subsets are different if and only if the chosen indices to delete are different.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var beautifulSubsets = function(nums, k) {
+  const n = nums.length;
+  let count = 0;
+  backtrack(0, []);
+  return count;
+
+  function backtrack(index, selected) {
+    if (index === n) {
+      if (selected.length > 0) count++;
+      return;
+    }
+
+    const isValid = selected.every(num => Math.abs(num - nums[index]) !== k);
+
+    backtrack(index + 1, selected);
+
+    if (isValid) {
+      backtrack(index + 1, [...selected, nums[index]]);
+    }
+  }
+};
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/2600-k-items-with-the-maximum-sum.js b/solutions/2600-k-items-with-the-maximum-sum.js
new file mode 100644
index 00000000..c6952fe3
--- /dev/null
+++ b/solutions/2600-k-items-with-the-maximum-sum.js
@@ -0,0 +1,38 @@
+/**
+ * 2600. K Items With the Maximum Sum
+ * https://leetcode.com/problems/k-items-with-the-maximum-sum/
+ * Difficulty: Easy
+ *
+ * There is a bag that consists of items, each item has a number 1, 0, or -1 written on it.
+ *
+ * You are given four non-negative integers numOnes, numZeros, numNegOnes, and k.
+ *
+ * The bag initially contains:
+ * - numOnes items with 1s written on them.
+ * - numZeroes items with 0s written on them.
+ * - numNegOnes items with -1s written on them.
+ *
+ * We want to pick exactly k items among the available items. Return the maximum possible sum
+ * of numbers written on the items.
+ */
+
+/**
+ * @param {number} numOnes
+ * @param {number} numZeros
+ * @param {number} numNegOnes
+ * @param {number} k
+ * @return {number}
+ */
+var kItemsWithMaximumSum = function(numOnes, numZeros, numNegOnes, k) {
+  let result = 0;
+
+  if (k <= numOnes) {
+    result = k;
+  } else if (k <= numOnes + numZeros) {
+    result = numOnes;
+  } else {
+    result = numOnes - (k - numOnes - numZeros);
+  }
+
+  return result;
+};
diff --git a/solutions/2601-prime-subtraction-operation.js b/solutions/2601-prime-subtraction-operation.js
new file mode 100644
index 00000000..c9fbc184
--- /dev/null
+++ b/solutions/2601-prime-subtraction-operation.js
@@ -0,0 +1,62 @@
+/**
+ * 2601. Prime Subtraction Operation
+ * https://leetcode.com/problems/prime-subtraction-operation/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums of length n.
+ *
+ * You can perform the following operation as many times as you want:
+ * - Pick an index i that you haven’t picked before, and pick a prime p strictly less than
+ *   nums[i], then subtract p from nums[i].
+ *
+ * Return true if you can make nums a strictly increasing array using the above operation
+ * and false otherwise.
+ *
+ * A strictly increasing array is an array whose each element is strictly greater than its
+ * preceding element.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {boolean}
+ */
+var primeSubOperation = function(nums) {
+  const primes = generatePrimes(1000);
+  const adjusted = [...nums];
+  let prev = 0;
+
+  for (let i = 0; i < adjusted.length; i++) {
+    const curr = adjusted[i];
+    let maxPrime = 0;
+
+    for (const prime of primes) {
+      if (prime >= curr) break;
+      if (curr - prime > prev && (i === adjusted.length - 1 || curr - prime < adjusted[i + 1])) {
+        maxPrime = prime;
+      }
+    }
+
+    adjusted[i] -= maxPrime;
+    if (adjusted[i] <= prev) return false;
+    prev = adjusted[i];
+  }
+
+  return true;
+
+  function generatePrimes(limit) {
+    const group = new Array(limit + 1).fill(true);
+    const primes = [];
+    group[0] = group[1] = false;
+
+    for (let i = 2; i <= limit; i++) {
+      if (group[i]) {
+        primes.push(i);
+        for (let j = i * i; j <= limit; j += i) {
+          group[j] = false;
+        }
+      }
+    }
+
+    return primes;
+  }
+};
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/2605-form-smallest-number-from-two-digit-arrays.js b/solutions/2605-form-smallest-number-from-two-digit-arrays.js
new file mode 100644
index 00000000..4892b564
--- /dev/null
+++ b/solutions/2605-form-smallest-number-from-two-digit-arrays.js
@@ -0,0 +1,31 @@
+/**
+ * 2605. Form Smallest Number From Two Digit Arrays
+ * https://leetcode.com/problems/form-smallest-number-from-two-digit-arrays/
+ * Difficulty: Easy
+ *
+ * Given two arrays of unique digits nums1 and nums2, return the smallest number that contains
+ * at least one digit from each array.
+ */
+
+/**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number}
+ */
+var minNumber = function(nums1, nums2) {
+  const set1 = new Set(nums1);
+  const set2 = new Set(nums2);
+  const min1 = Math.min(...nums1);
+  const min2 = Math.min(...nums2);
+  let smallestCommon = 10;
+
+  for (const digit of set1) {
+    if (set2.has(digit) && digit < smallestCommon) {
+      smallestCommon = digit;
+    }
+  }
+
+  if (smallestCommon !== 10) return smallestCommon;
+
+  return min1 < min2 ? min1 * 10 + min2 : min2 * 10 + min1;
+};
diff --git a/solutions/2606-find-the-substring-with-maximum-cost.js b/solutions/2606-find-the-substring-with-maximum-cost.js
new file mode 100644
index 00000000..0a4572c5
--- /dev/null
+++ b/solutions/2606-find-the-substring-with-maximum-cost.js
@@ -0,0 +1,42 @@
+/**
+ * 2606. Find the Substring With Maximum Cost
+ * https://leetcode.com/problems/find-the-substring-with-maximum-cost/
+ * Difficulty: Medium
+ *
+ * You are given a string s, a string chars of distinct characters and an integer array vals of
+ * the same length as chars.
+ *
+ * The cost of the substring is the sum of the values of each character in the substring. The
+ * cost of an empty string is considered 0.
+ *
+ * The value of the character is defined in the following way:
+ * - If the character is not in the string chars, then its value is its corresponding position
+ *   (1-indexed) in the alphabet.
+ *   - For example, the value of 'a' is 1, the value of 'b' is 2, and so on. The value of 'z' is 26.
+ * - Otherwise, assuming i is the index where the character occurs in the string chars, then its
+ *   value is vals[i].
+ *
+ * Return the maximum cost among all substrings of the string s.
+ */
+
+/**
+ * @param {string} s
+ * @param {string} chars
+ * @param {number[]} vals
+ * @return {number}
+ */
+var maximumCostSubstring = function(s, chars, vals) {
+  const charValues = new Array(26).fill().map((_, i) => i + 1);
+  for (let i = 0; i < chars.length; i++) {
+    charValues[chars.charCodeAt(i) - 97] = vals[i];
+  }
+
+  let result = 0;
+  let currentCost = 0;
+  for (const char of s) {
+    currentCost = Math.max(0, currentCost + charValues[char.charCodeAt(0) - 97]);
+    result = Math.max(result, currentCost);
+  }
+
+  return result;
+};
diff --git a/solutions/2609-find-the-longest-balanced-substring-of-a-binary-string.js b/solutions/2609-find-the-longest-balanced-substring-of-a-binary-string.js
new file mode 100644
index 00000000..3884e54e
--- /dev/null
+++ b/solutions/2609-find-the-longest-balanced-substring-of-a-binary-string.js
@@ -0,0 +1,45 @@
+/**
+ * 2609. Find the Longest Balanced Substring of a Binary String
+ * https://leetcode.com/problems/find-the-longest-balanced-substring-of-a-binary-string/
+ * Difficulty: Easy
+ *
+ * You are given a binary string s consisting only of zeroes and ones.
+ *
+ * A substring of s is considered balanced if all zeroes are before ones and the number of zeroes
+ * is equal to the number of ones inside the substring. Notice that the empty substring is
+ * considered a balanced substring.
+ *
+ * Return the length of the longest balanced substring of s.
+ *
+ * A substring is a contiguous sequence of characters within a string.
+ */
+
+/**
+ * @param {string} s
+ * @return {number}
+ */
+var findTheLongestBalancedSubstring = function(s) {
+  let result = 0;
+  let zeros = 0;
+  let ones = 0;
+
+  for (let i = 0; i < s.length; i++) {
+    if (s[i] === '0') {
+      if (ones > 0) {
+        zeros = 0;
+        ones = 0;
+      }
+      zeros++;
+    } else {
+      if (zeros >= ones + 1) {
+        ones++;
+        result = Math.max(result, 2 * ones);
+      } else {
+        zeros = 0;
+        ones = 0;
+      }
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2610-convert-an-array-into-a-2d-array-with-conditions.js b/solutions/2610-convert-an-array-into-a-2d-array-with-conditions.js
new file mode 100644
index 00000000..7c584818
--- /dev/null
+++ b/solutions/2610-convert-an-array-into-a-2d-array-with-conditions.js
@@ -0,0 +1,42 @@
+/**
+ * 2610. Convert an Array Into a 2D Array With Conditions
+ * https://leetcode.com/problems/convert-an-array-into-a-2d-array-with-conditions/
+ * Difficulty: Medium
+ *
+ * You are given an integer array nums. You need to create a 2D array from nums satisfying
+ * the following conditions:
+ * - The 2D array should contain only the elements of the array nums.
+ * - Each row in the 2D array contains distinct integers.
+ * - The number of rows in the 2D array should be minimal.
+ *
+ * Return the resulting array. If there are multiple answers, return any of them.
+ *
+ * Note that the 2D array can have a different number of elements on each row.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[][]}
+ */
+var findMatrix = function(nums) {
+  const frequency = new Map();
+  for (const num of nums) {
+    frequency.set(num, (frequency.get(num) || 0) + 1);
+  }
+
+  const result = [];
+  while (frequency.size) {
+    const row = [];
+    for (const [num, count] of frequency) {
+      row.push(num);
+      if (count === 1) {
+        frequency.delete(num);
+      } else {
+        frequency.set(num, count - 1);
+      }
+    }
+    result.push(row);
+  }
+
+  return result;
+};
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/2615-sum-of-distances.js b/solutions/2615-sum-of-distances.js
new file mode 100644
index 00000000..470c10cf
--- /dev/null
+++ b/solutions/2615-sum-of-distances.js
@@ -0,0 +1,44 @@
+/**
+ * 2615. Sum of Distances
+ * https://leetcode.com/problems/sum-of-distances/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums. There exists an array arr of length nums.length,
+ * where arr[i] is the sum of |i - j| over all j such that nums[j] == nums[i] and j != i. If there
+ * is no such j, set arr[i] to be 0.
+ *
+ * Return the array arr.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var distance = function(nums) {
+  const valueIndices = new Map();
+  const result = new Array(nums.length).fill(0);
+
+  for (let i = 0; i < nums.length; i++) {
+    if (!valueIndices.has(nums[i])) {
+      valueIndices.set(nums[i], []);
+    }
+    valueIndices.get(nums[i]).push(i);
+  }
+
+  for (const indices of valueIndices.values()) {
+    let prefixSum = 0;
+    for (let i = 1; i < indices.length; i++) {
+      prefixSum += indices[i] - indices[0];
+    }
+
+    result[indices[0]] = prefixSum;
+
+    for (let i = 1; i < indices.length; i++) {
+      const diff = indices[i] - indices[i - 1];
+      prefixSum += diff * (i - (indices.length - i));
+      result[indices[i]] = prefixSum;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2616-minimize-the-maximum-difference-of-pairs.js b/solutions/2616-minimize-the-maximum-difference-of-pairs.js
new file mode 100644
index 00000000..691f2e60
--- /dev/null
+++ b/solutions/2616-minimize-the-maximum-difference-of-pairs.js
@@ -0,0 +1,53 @@
+/**
+ * 2616. Minimize the Maximum Difference of Pairs
+ * https://leetcode.com/problems/minimize-the-maximum-difference-of-pairs/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums and an integer p. Find p pairs of indices
+ * of nums such that the maximum difference amongst all the pairs is minimized. Also, ensure
+ * no index appears more than once amongst the p pairs.
+ *
+ * Note that for a pair of elements at the index i and j, the difference of this pair is
+ * |nums[i] - nums[j]|, where |x| represents the absolute value of x.
+ *
+ * Return the minimum maximum difference among all p pairs. We define the maximum of an empty
+ * set to be zero.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} p
+ * @return {number}
+ */
+var minimizeMax = function(nums, p) {
+  nums.sort((a, b) => a - b);
+  const n = nums.length;
+
+  let left = 0;
+  let right = nums[n - 1] - nums[0];
+  let result = 0;
+
+  while (left <= right) {
+    const mid = Math.floor((left + right) / 2);
+    if (canFormPairs(mid)) {
+      result = mid;
+      right = mid - 1;
+    } else {
+      left = mid + 1;
+    }
+  }
+
+  return result;
+
+  function canFormPairs(maxDiff) {
+    let pairs = 0;
+    for (let i = 0; i < n - 1 && pairs < p; i += 2) {
+      if (nums[i + 1] - nums[i] <= maxDiff) {
+        pairs++;
+      } else {
+        i--;
+      }
+    }
+    return pairs >= p;
+  }
+};
diff --git a/solutions/2624-snail-traversal.js b/solutions/2624-snail-traversal.js
new file mode 100644
index 00000000..2ff26d6d
--- /dev/null
+++ b/solutions/2624-snail-traversal.js
@@ -0,0 +1,46 @@
+/**
+ * 2624. Snail Traversal
+ * https://leetcode.com/problems/snail-traversal/
+ * Difficulty: Medium
+ *
+ * Write code that enhances all arrays such that you can call the snail(rowsCount,
+ * colsCount) method that transforms the 1D array into a 2D array organised in the
+ * pattern known as snail traversal order. Invalid input values should output an
+ * empty array. If rowsCount * colsCount !== nums.length, the input is considered invalid.
+ *
+ * Snail traversal order starts at the top left cell with the first value of the
+ * current array. It then moves through the entire first column from top to bottom,
+ * followed by moving to the next column on the right and traversing it from bottom
+ * to top. This pattern continues, alternating the direction of traversal with each
+ * column, until the entire current array is covered. For example, when given the
+ * input array [19, 10, 3, 7, 9, 8, 5, 2, 1, 17, 16, 14, 12, 18, 6, 13, 11, 20, 4, 15]
+ * with rowsCount = 5 and colsCount = 4, the desired output matrix is shown below.
+ * Note that iterating the matrix following the arrows corresponds to the order
+ * of numbers in the original array.
+ */
+
+/**
+ * @param {number} rowsCount
+ * @param {number} colsCount
+ * @return {Array>}
+ */
+Array.prototype.snail = function(rowsCount, colsCount) {
+  if (rowsCount * colsCount !== this.length) return [];
+
+  const result = Array.from({ length: rowsCount }, () => []);
+  let index = 0;
+
+  for (let col = 0; col < colsCount; col++) {
+    if (col % 2 === 0) {
+      for (let row = 0; row < rowsCount; row++) {
+        result[row][col] = this[index++];
+      }
+    } else {
+      for (let row = rowsCount - 1; row >= 0; row--) {
+        result[row][col] = this[index++];
+      }
+    }
+  }
+
+  return result;
+}
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/2639-find-the-width-of-columns-of-a-grid.js b/solutions/2639-find-the-width-of-columns-of-a-grid.js
new file mode 100644
index 00000000..e544bc23
--- /dev/null
+++ b/solutions/2639-find-the-width-of-columns-of-a-grid.js
@@ -0,0 +1,34 @@
+/**
+ * 2639. Find the Width of Columns of a Grid
+ * https://leetcode.com/problems/find-the-width-of-columns-of-a-grid/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed m x n integer matrix grid. The width of a column is the
+ * maximum length of its integers.
+ * - For example, if grid = [[-10], [3], [12]], the width of the only column is 3
+ *   since -10 is of length 3.
+ *
+ * Return an integer array ans of size n where ans[i] is the width of the ith column.
+ *
+ * The length of an integer x with len digits is equal to len if x is non-negative, and
+ * len + 1 otherwise.
+ */
+
+/**
+ * @param {number[][]} grid
+ * @return {number[]}
+ */
+var findColumnWidth = function(grid) {
+  const rows = grid.length;
+  const cols = grid[0].length;
+  const result = new Array(cols).fill(0);
+
+  for (let col = 0; col < cols; col++) {
+    for (let row = 0; row < rows; row++) {
+      const num = grid[row][col];
+      result[col] = Math.max(result[col], String(num).length);
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2640-find-the-score-of-all-prefixes-of-an-array.js b/solutions/2640-find-the-score-of-all-prefixes-of-an-array.js
new file mode 100644
index 00000000..9ec56b99
--- /dev/null
+++ b/solutions/2640-find-the-score-of-all-prefixes-of-an-array.js
@@ -0,0 +1,32 @@
+/**
+ * 2640. Find the Score of All Prefixes of an Array
+ * https://leetcode.com/problems/find-the-score-of-all-prefixes-of-an-array/
+ * Difficulty: Medium
+ *
+ * We define the conversion array conver of an array arr as follows:
+ * - conver[i] = arr[i] + max(arr[0..i]) where max(arr[0..i]) is the maximum value of
+ *   arr[j] over 0 <= j <= i.
+ *
+ * We also define the score of an array arr as the sum of the values of the conversion array of arr.
+ *
+ * Given a 0-indexed integer array nums of length n, return an array ans of length n where ans[i]
+ * is the score of the prefix nums[0..i].
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var findPrefixScore = function(nums) {
+  const result = new Array(nums.length);
+  let maxSoFar = 0;
+  let total = 0;
+
+  for (let i = 0; i < nums.length; i++) {
+    maxSoFar = Math.max(maxSoFar, nums[i]);
+    total += nums[i] + maxSoFar;
+    result[i] = total;
+  }
+
+  return result;
+};
diff --git a/solutions/2641-cousins-in-binary-tree-ii.js b/solutions/2641-cousins-in-binary-tree-ii.js
new file mode 100644
index 00000000..07faea41
--- /dev/null
+++ b/solutions/2641-cousins-in-binary-tree-ii.js
@@ -0,0 +1,53 @@
+/**
+ * 2641. Cousins in Binary Tree II
+ * https://leetcode.com/problems/cousins-in-binary-tree-ii/
+ * Difficulty: Medium
+ *
+ * Given the root of a binary tree, replace the value of each node in the tree with the
+ * sum of all its cousins' values.
+ *
+ * Two nodes of a binary tree are cousins if they have the same depth with different parents.
+ *
+ * Return the root of the modified tree.
+ *
+ * Note that the depth of a node is the number of edges in the path from the root node to it.
+ */
+
+/**
+ * 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 replaceValueInTree = function(root) {
+  const levelSums = [];
+
+  collectSums(root, 0);
+  replaceValues(root, 0, 0);
+
+  return root;
+
+  function collectSums(node, depth) {
+    if (!node) return;
+    if (levelSums.length <= depth) levelSums.push(0);
+    levelSums[depth] += node.val;
+    collectSums(node.left, depth + 1);
+    collectSums(node.right, depth + 1);
+  }
+
+  function replaceValues(node, depth, siblingSum) {
+    if (!node) return;
+    node.val = levelSums[depth] - node.val - siblingSum;
+
+    const leftVal = node.left ? node.left.val : 0;
+    const rightVal = node.right ? node.right.val : 0;
+    replaceValues(node.left, depth + 1, rightVal);
+    replaceValues(node.right, depth + 1, leftVal);
+  }
+};
diff --git a/solutions/2643-row-with-maximum-ones.js b/solutions/2643-row-with-maximum-ones.js
new file mode 100644
index 00000000..aaa37e79
--- /dev/null
+++ b/solutions/2643-row-with-maximum-ones.js
@@ -0,0 +1,32 @@
+/**
+ * 2643. Row With Maximum Ones
+ * https://leetcode.com/problems/row-with-maximum-ones/
+ * Difficulty: Easy
+ *
+ * Given a m x n binary matrix mat, find the 0-indexed position of the row that contains
+ * the maximum count of ones, and the number of ones in that row.
+ *
+ * In case there are multiple rows that have the maximum count of ones, the row with the
+ * smallest row number should be selected.
+ *
+ * Return an array containing the index of the row, and the number of ones in it.
+ */
+
+/**
+ * @param {number[][]} mat
+ * @return {number[]}
+ */
+var rowAndMaximumOnes = function(mat) {
+  let maxOnes = 0;
+  let maxRow = 0;
+
+  for (let row = 0; row < mat.length; row++) {
+    const ones = mat[row].reduce((sum, val) => sum + val, 0);
+    if (ones > maxOnes) {
+      maxOnes = ones;
+      maxRow = row;
+    }
+  }
+
+  return [maxRow, maxOnes];
+};
diff --git a/solutions/2644-find-the-maximum-divisibility-score.js b/solutions/2644-find-the-maximum-divisibility-score.js
new file mode 100644
index 00000000..ac5c2e02
--- /dev/null
+++ b/solutions/2644-find-the-maximum-divisibility-score.js
@@ -0,0 +1,38 @@
+/**
+ * 2644. Find the Maximum Divisibility Score
+ * https://leetcode.com/problems/find-the-maximum-divisibility-score/
+ * Difficulty: Easy
+ *
+ * You are given two integer arrays nums and divisors.
+ *
+ * The divisibility score of divisors[i] is the number of indices j such that nums[j] is
+ * divisible by divisors[i].
+ *
+ * Return the integer divisors[i] with the maximum divisibility score. If multiple integers
+ * have the maximum score, return the smallest one.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number[]} divisors
+ * @return {number}
+ */
+var maxDivScore = function(nums, divisors) {
+  let maxScore = 0;
+  let result = divisors[0];
+
+  for (const divisor of divisors) {
+    let score = 0;
+    for (const num of nums) {
+      if (num % divisor === 0) {
+        score++;
+      }
+    }
+    if (score > maxScore || (score === maxScore && divisor < result)) {
+      maxScore = score;
+      result = divisor;
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2645-minimum-additions-to-make-valid-string.js b/solutions/2645-minimum-additions-to-make-valid-string.js
new file mode 100644
index 00000000..fd6bec83
--- /dev/null
+++ b/solutions/2645-minimum-additions-to-make-valid-string.js
@@ -0,0 +1,49 @@
+/**
+ * 2645. Minimum Additions to Make Valid String
+ * https://leetcode.com/problems/minimum-additions-to-make-valid-string/
+ * Difficulty: Medium
+ *
+ * Given a string word to which you can insert letters "a", "b" or "c" anywhere and any number
+ * of times, return the minimum number of letters that must be inserted so that word becomes valid.
+ *
+ * A string is called valid if it can be formed by concatenating the string "abc" several times.
+ */
+
+/**
+ * @param {string} word
+ * @return {number}
+ */
+var addMinimum = function(word) {
+  let result = 0;
+  let index = 0;
+
+  while (index < word.length) {
+    if (word[index] === 'a') {
+      if (word[index + 1] === 'b' && word[index + 2] === 'c') {
+        index += 3;
+      } else if (word[index + 1] === 'b') {
+        result += 1;
+        index += 2;
+      } else if (word[index + 1] === 'c') {
+        result += 1;
+        index += 2;
+      } else {
+        result += 2;
+        index += 1;
+      }
+    } else if (word[index] === 'b') {
+      if (word[index + 1] === 'c') {
+        result += 1;
+        index += 2;
+      } else {
+        result += 2;
+        index += 1;
+      }
+    } else {
+      result += 2;
+      index += 1;
+    }
+  }
+
+  return result;
+};
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/2651-calculate-delayed-arrival-time.js b/solutions/2651-calculate-delayed-arrival-time.js
new file mode 100644
index 00000000..09571897
--- /dev/null
+++ b/solutions/2651-calculate-delayed-arrival-time.js
@@ -0,0 +1,21 @@
+/**
+ * 2651. Calculate Delayed Arrival Time
+ * https://leetcode.com/problems/calculate-delayed-arrival-time/
+ * Difficulty: Easy
+ *
+ * You are given a positive integer arrivalTime denoting the arrival time of a train in
+ * hours, and another positive integer delayedTime denoting the amount of delay in hours.
+ *
+ * Return the time when the train will arrive at the station.
+ *
+ * Note that the time in this problem is in 24-hours format.
+ */
+
+/**
+ * @param {number} arrivalTime
+ * @param {number} delayedTime
+ * @return {number}
+ */
+var findDelayedArrivalTime = function(arrivalTime, delayedTime) {
+  return (arrivalTime + delayedTime) % 24;
+};
diff --git a/solutions/2652-sum-multiples.js b/solutions/2652-sum-multiples.js
new file mode 100644
index 00000000..340dbd2a
--- /dev/null
+++ b/solutions/2652-sum-multiples.js
@@ -0,0 +1,25 @@
+/**
+ * 2652. Sum Multiples
+ * https://leetcode.com/problems/sum-multiples/
+ * Difficulty: Easy
+ *
+ * Given a positive integer n, find the sum of all integers in the range [1, n] inclusive
+ * that are divisible by 3, 5, or 7.
+ *
+ * Return an integer denoting the sum of all numbers in the given range satisfying the constraint.
+ */
+
+/**
+ * @param {number} n
+ * @return {number}
+ */
+var sumOfMultiples = function(n) {
+  return sumDivisibleBy(3) + sumDivisibleBy(5) + sumDivisibleBy(7)
+    - sumDivisibleBy(15) - sumDivisibleBy(21) - sumDivisibleBy(35)
+    + sumDivisibleBy(105);
+
+  function sumDivisibleBy(divisor) {
+    const count = Math.floor(n / divisor);
+    return divisor * count * (count + 1) / 2;
+  }
+};
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/2656-maximum-sum-with-exactly-k-elements.js b/solutions/2656-maximum-sum-with-exactly-k-elements.js
new file mode 100644
index 00000000..fdac61de
--- /dev/null
+++ b/solutions/2656-maximum-sum-with-exactly-k-elements.js
@@ -0,0 +1,23 @@
+/**
+ * 2656. Maximum Sum With Exactly K Elements
+ * https://leetcode.com/problems/maximum-sum-with-exactly-k-elements/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed integer array nums and an integer k. Your task is to perform
+ * the following operation exactly k times in order to maximize your score:
+ * 1. Select an element m from nums.
+ * 2. Remove the selected element m from the array.
+ * 3. Add a new element with a value of m + 1 to the array.
+ * 4. Increase your score by m.
+ *
+ * Return the maximum score you can achieve after performing the operation exactly k times.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var maximizeSum = function(nums, k) {
+  return k * Math.max(...nums) + k * (k - 1) / 2;
+};
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/2670-find-the-distinct-difference-array.js b/solutions/2670-find-the-distinct-difference-array.js
new file mode 100644
index 00000000..fc3ddaea
--- /dev/null
+++ b/solutions/2670-find-the-distinct-difference-array.js
@@ -0,0 +1,46 @@
+/**
+ * 2670. Find the Distinct Difference Array
+ * https://leetcode.com/problems/find-the-distinct-difference-array/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed array nums of length n.
+ *
+ * The distinct difference array of nums is an array diff of length n such that diff[i] is
+ * equal to the number of distinct elements in the suffix nums[i + 1, ..., n - 1] subtracted
+ * from the number of distinct elements in the prefix nums[0, ..., i].
+ *
+ * Return the distinct difference array of nums.
+ *
+ * Note that nums[i, ..., j] denotes the subarray of nums starting at index i and ending at
+ * index j inclusive. Particularly, if i > j then nums[i, ..., j] denotes an empty subarray.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number[]}
+ */
+var distinctDifferenceArray = function(nums) {
+  const n = nums.length;
+  const result = new Array(n);
+  const prefixSet = new Set();
+  const suffixCount = new Map();
+
+  for (const num of nums) {
+    suffixCount.set(num, (suffixCount.get(num) || 0) + 1);
+  }
+
+  let suffixDistinct = suffixCount.size;
+
+  for (let i = 0; i < n; i++) {
+    prefixSet.add(nums[i]);
+    const count = suffixCount.get(nums[i]);
+    suffixCount.set(nums[i], count - 1);
+    if (count === 1) {
+      suffixCount.delete(nums[i]);
+      suffixDistinct--;
+    }
+    result[i] = prefixSet.size - suffixDistinct;
+  }
+
+  return result;
+};
diff --git a/solutions/2672-number-of-adjacent-elements-with-the-same-color.js b/solutions/2672-number-of-adjacent-elements-with-the-same-color.js
new file mode 100644
index 00000000..257d4270
--- /dev/null
+++ b/solutions/2672-number-of-adjacent-elements-with-the-same-color.js
@@ -0,0 +1,44 @@
+/**
+ * 2672. Number of Adjacent Elements With the Same Color
+ * https://leetcode.com/problems/number-of-adjacent-elements-with-the-same-color/
+ * Difficulty: Medium
+ *
+ * You are given an integer n representing an array colors of length n where all elements
+ * are set to 0's meaning uncolored. You are also given a 2D integer array queries where
+ * queries[i] = [indexi, colori]. For the ith query:
+ * - Set colors[indexi] to colori.
+ * - Count the number of adjacent pairs in colors which have the same color (regardless of colori).
+ *
+ * Return an array answer of the same length as queries where answer[i] is the answer to the ith
+ * query.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[][]} queries
+ * @return {number[]}
+ */
+var colorTheArray = function(n, queries) {
+  const colors = new Array(n).fill(0);
+  const result = new Array(queries.length).fill(0);
+  let sameColorPairs = 0;
+
+  for (let i = 0; i < queries.length; i++) {
+    const [index, color] = queries[i];
+    const prevColor = colors[index];
+
+    if (prevColor !== 0) {
+      if (index > 0 && colors[index - 1] === prevColor) sameColorPairs--;
+      if (index < n - 1 && colors[index + 1] === prevColor) sameColorPairs--;
+    }
+
+    colors[index] = color;
+
+    if (index > 0 && colors[index - 1] === color) sameColorPairs++;
+    if (index < n - 1 && colors[index + 1] === color) sameColorPairs++;
+
+    result[i] = sameColorPairs;
+  }
+
+  return result;
+};
diff --git a/solutions/2673-make-costs-of-paths-equal-in-a-binary-tree.js b/solutions/2673-make-costs-of-paths-equal-in-a-binary-tree.js
new file mode 100644
index 00000000..7d60cdb5
--- /dev/null
+++ b/solutions/2673-make-costs-of-paths-equal-in-a-binary-tree.js
@@ -0,0 +1,41 @@
+/**
+ * 2673. Make Costs of Paths Equal in a Binary Tree
+ * https://leetcode.com/problems/make-costs-of-paths-equal-in-a-binary-tree/
+ * Difficulty: Medium
+ *
+ * You are given an integer n representing the number of nodes in a perfect binary tree consisting
+ * of nodes numbered from 1 to n. The root of the tree is node 1 and each node i in the tree has
+ * two children where the left child is the node 2 * i and the right child is 2 * i + 1.
+ *
+ * Each node in the tree also has a cost represented by a given 0-indexed integer array cost of
+ * size n where cost[i] is the cost of node i + 1. You are allowed to increment the cost of any
+ * node by 1 any number of times.
+ *
+ * Return the minimum number of increments you need to make the cost of paths from the root to
+ * each leaf node equal.
+ *
+ * Note:
+ * - A perfect binary tree is a tree where each node, except the leaf nodes, has exactly 2 children.
+ * - The cost of a path is the sum of costs of nodes in the path.
+ */
+
+/**
+ * @param {number} n
+ * @param {number[]} cost
+ * @return {number}
+ */
+var minIncrements = function(n, cost) {
+  let result = 0;
+
+  for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {
+    const left = 2 * i + 1;
+    const right = 2 * i + 2;
+    if (left < n && right < n) {
+      const maxChildCost = Math.max(cost[left], cost[right]);
+      result += maxChildCost - cost[left] + maxChildCost - cost[right];
+      cost[i] += maxChildCost;
+    }
+  }
+
+  return result;
+};
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/2678-number-of-senior-citizens.js b/solutions/2678-number-of-senior-citizens.js
new file mode 100644
index 00000000..7c599c9f
--- /dev/null
+++ b/solutions/2678-number-of-senior-citizens.js
@@ -0,0 +1,30 @@
+/**
+ * 2678. Number of Senior Citizens
+ * https://leetcode.com/problems/number-of-senior-citizens/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed array of strings details. Each element of details provides
+ * information about a given passenger compressed into a string of length 15. The system
+ * is such that:
+ * - The first ten characters consist of the phone number of passengers.
+ * - The next character denotes the gender of the person.
+ * - The following two characters are used to indicate the age of the person.
+ * - The last two characters determine the seat allotted to that person.
+ *
+ * Return the number of passengers who are strictly more than 60 years old.
+ */
+
+/**
+ * @param {string[]} details
+ * @return {number}
+ */
+var countSeniors = function(details) {
+  let result = 0;
+
+  for (const detail of details) {
+    const age = parseInt(detail.slice(11, 13));
+    if (age > 60) result++;
+  }
+
+  return result;
+};
diff --git a/solutions/2680-maximum-or.js b/solutions/2680-maximum-or.js
new file mode 100644
index 00000000..fb53a9c9
--- /dev/null
+++ b/solutions/2680-maximum-or.js
@@ -0,0 +1,41 @@
+/**
+ * 2680. Maximum OR
+ * https://leetcode.com/problems/maximum-or/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums of length n and an integer k. In an operation,
+ * you can choose an element and multiply it by 2.
+ *
+ * Return the maximum possible value of nums[0] | nums[1] | ... | nums[n - 1] that can be obtained
+ * after applying the operation on nums at most k times.
+ *
+ * Note that a | b denotes the bitwise or between two integers a and b.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var maximumOr = function(nums, k) {
+  const n = nums.length;
+  const prefixOr = new Array(n + 1).fill(0n);
+  const suffixOr = new Array(n + 1).fill(0n);
+
+  for (let i = 0; i < n; i++) {
+    prefixOr[i + 1] = prefixOr[i] | BigInt(nums[i]);
+  }
+
+  for (let i = n - 1; i >= 0; i--) {
+    suffixOr[i] = suffixOr[i + 1] | BigInt(nums[i]);
+  }
+
+  let maxOr = 0n;
+  for (let i = 0; i < n; i++) {
+    maxOr = maxOr > (prefixOr[i] | (BigInt(nums[i]) << BigInt(k)) | suffixOr[i + 1])
+      ? maxOr
+      : (prefixOr[i] | (BigInt(nums[i]) << BigInt(k)) | suffixOr[i + 1]);
+  }
+
+  return Number(maxOr);
+};
diff --git a/solutions/2682-find-the-losers-of-the-circular-game.js b/solutions/2682-find-the-losers-of-the-circular-game.js
new file mode 100644
index 00000000..8536fa0b
--- /dev/null
+++ b/solutions/2682-find-the-losers-of-the-circular-game.js
@@ -0,0 +1,56 @@
+/**
+ * 2682. Find the Losers of the Circular Game
+ * https://leetcode.com/problems/find-the-losers-of-the-circular-game/
+ * Difficulty: Easy
+ *
+ * There are n friends that are playing a game. The friends are sitting in a circle and are numbered
+ * from 1 to n in clockwise order. More formally, moving clockwise from the ith friend brings you to
+ * the (i+1)th friend for 1 <= i < n, and moving clockwise from the nth friend brings you to the 1st
+ * friend.
+ *
+ * The rules of the game are as follows:
+ *
+ * 1st friend receives the ball.
+ * - After that, 1st friend passes it to the friend who is k steps away from them in the clockwise
+ *   direction.
+ * - After that, the friend who receives the ball should pass it to the friend who is 2 * k steps
+ *   away from them in the clockwise direction.
+ * - After that, the friend who receives the ball should pass it to the friend who is 3 * k steps
+ *   away from them in the clockwise direction, and so on and so forth.
+ *
+ * In other words, on the ith turn, the friend holding the ball should pass it to the friend who
+ * is i * k steps away from them in the clockwise direction.
+ *
+ * The game is finished when some friend receives the ball for the second time.
+ *
+ * The losers of the game are friends who did not receive the ball in the entire game.
+ *
+ * Given the number of friends, n, and an integer k, return the array answer, which contains the
+ * losers of the game in the ascending order.
+ */
+
+/**
+ * @param {number} n
+ * @param {number} k
+ * @return {number[]}
+ */
+var circularGameLosers = function(n, k) {
+  const visited = new Set();
+  let current = 0;
+  let step = 1;
+
+  while (!visited.has(current)) {
+    visited.add(current);
+    current = (current + step * k) % n;
+    step++;
+  }
+
+  const result = [];
+  for (let i = 0; i < n; i++) {
+    if (!visited.has(i)) {
+      result.push(i + 1);
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2684-maximum-number-of-moves-in-a-grid.js b/solutions/2684-maximum-number-of-moves-in-a-grid.js
new file mode 100644
index 00000000..65b4464f
--- /dev/null
+++ b/solutions/2684-maximum-number-of-moves-in-a-grid.js
@@ -0,0 +1,53 @@
+/**
+ * 2684. Maximum Number of Moves in a Grid
+ * https://leetcode.com/problems/maximum-number-of-moves-in-a-grid/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed m x n matrix grid consisting of positive integers.
+ *
+ * You can start at any cell in the first column of the matrix, and traverse the grid in the
+ * following way:
+ * - From a cell (row, col), you can move to any of the cells: (row - 1, col + 1), (row, col + 1)
+ *   and (row + 1, col + 1) such that the value of the cell you move to, should be strictly bigger
+ *   than the value of the current cell.
+ *
+ * Return the maximum number of moves that you can perform.
+ */
+
+/**
+ * @param {number[][]} grid
+ * @return {number}
+ */
+var maxMoves = function(grid) {
+  const rows = grid.length;
+  const cols = grid[0].length;
+  const memo = Array.from({ length: rows }, () => new Array(cols).fill(-1));
+
+  let result = 0;
+  for (let row = 0; row < rows; row++) {
+    result = Math.max(result, explore(row, 0));
+  }
+
+  return result;
+
+  function explore(row, col) {
+    if (col === cols - 1) return 0;
+    if (memo[row][col] !== -1) return memo[row][col];
+
+    let maxSteps = 0;
+    const current = grid[row][col];
+
+    if (row > 0 && col + 1 < cols && grid[row - 1][col + 1] > current) {
+      maxSteps = Math.max(maxSteps, 1 + explore(row - 1, col + 1));
+    }
+    if (col + 1 < cols && grid[row][col + 1] > current) {
+      maxSteps = Math.max(maxSteps, 1 + explore(row, col + 1));
+    }
+    if (row + 1 < rows && col + 1 < cols && grid[row + 1][col + 1] > current) {
+      maxSteps = Math.max(maxSteps, 1 + explore(row + 1, col + 1));
+    }
+
+    memo[row][col] = maxSteps;
+    return maxSteps;
+  }
+};
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/2696-minimum-string-length-after-removing-substrings.js b/solutions/2696-minimum-string-length-after-removing-substrings.js
new file mode 100644
index 00000000..de51fb8f
--- /dev/null
+++ b/solutions/2696-minimum-string-length-after-removing-substrings.js
@@ -0,0 +1,34 @@
+/**
+ * 2696. Minimum String Length After Removing Substrings
+ * https://leetcode.com/problems/minimum-string-length-after-removing-substrings/
+ * Difficulty: Easy
+ *
+ * You are given a string s consisting only of uppercase English letters.
+ *
+ * You can apply some operations to this string where, in one operation, you can remove any
+ * occurrence of one of the substrings "AB" or "CD" from s.
+ *
+ * Return the minimum possible length of the resulting string that you can obtain.
+ *
+ * Note that the string concatenates after removing the substring and could produce new "AB"
+ * or "CD" substrings.
+ */
+
+/**
+ * @param {string} s
+ * @return {number}
+ */
+var minLength = function(s) {
+  const stack = [];
+
+  for (const char of s) {
+    if (stack.length && ((stack[stack.length - 1] === 'A' && char === 'B')
+        || (stack[stack.length - 1] === 'C' && char === 'D'))) {
+      stack.pop();
+    } else {
+      stack.push(char);
+    }
+  }
+
+  return stack.length;
+};
diff --git a/solutions/2697-lexicographically-smallest-palindrome.js b/solutions/2697-lexicographically-smallest-palindrome.js
new file mode 100644
index 00000000..2489eb32
--- /dev/null
+++ b/solutions/2697-lexicographically-smallest-palindrome.js
@@ -0,0 +1,39 @@
+/**
+ * 2697. Lexicographically Smallest Palindrome
+ * https://leetcode.com/problems/lexicographically-smallest-palindrome/
+ * Difficulty: Easy
+ *
+ * You are given a string s consisting of lowercase English letters, and you are allowed to
+ * perform operations on it. In one operation, you can replace a character in s with another
+ * lowercase English letter.
+ *
+ * Your task is to make s a palindrome with the minimum number of operations possible. If there
+ * are multiple palindromes that can be made using the minimum number of operations, make the
+ * lexicographically smallest one.
+ *
+ * A string a is lexicographically smaller than a string b (of the same length) 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.
+ *
+ * Return the resulting palindrome string.
+ */
+
+/**
+ * @param {string} s
+ * @return {string}
+ */
+var makeSmallestPalindrome = function(s) {
+  const chars = s.split('');
+  let left = 0;
+  let right = s.length - 1;
+
+  while (left < right) {
+    if (chars[left] !== chars[right]) {
+      chars[left] = chars[right] = chars[left] < chars[right] ? chars[left] : chars[right];
+    }
+    left++;
+    right--;
+  }
+
+  return chars.join('');
+};
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/2706-buy-two-chocolates.js b/solutions/2706-buy-two-chocolates.js
new file mode 100644
index 00000000..8c77f0e5
--- /dev/null
+++ b/solutions/2706-buy-two-chocolates.js
@@ -0,0 +1,28 @@
+/**
+ * 2706. Buy Two Chocolates
+ * https://leetcode.com/problems/buy-two-chocolates/
+ * Difficulty: Easy
+ *
+ * You are given an integer array prices representing the prices of various chocolates in
+ * a store. You are also given a single integer money, which represents your initial amount
+ * of money.
+ *
+ * You must buy exactly two chocolates in such a way that you still have some non-negative
+ * leftover money. You would like to minimize the sum of the prices of the two chocolates
+ * you buy.
+ *
+ * Return the amount of money you will have leftover after buying the two chocolates. If
+ * there is no way for you to buy two chocolates without ending up in debt, return money.
+ * Note that the leftover must be non-negative.
+ */
+
+/**
+ * @param {number[]} prices
+ * @param {number} money
+ * @return {number}
+ */
+var buyChoco = function(prices, money) {
+  prices.sort((a, b) => a - b);
+  const minCost = prices[0] + prices[1];
+  return minCost <= money ? money - minCost : money;
+};
diff --git a/solutions/2707-extra-characters-in-a-string.js b/solutions/2707-extra-characters-in-a-string.js
new file mode 100644
index 00000000..2d335169
--- /dev/null
+++ b/solutions/2707-extra-characters-in-a-string.js
@@ -0,0 +1,35 @@
+/**
+ * 2707. Extra Characters in a String
+ * https://leetcode.com/problems/extra-characters-in-a-string/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed string s and a dictionary of words dictionary. You have to break
+ * s into one or more non-overlapping substrings such that each substring is present in
+ * dictionary. There may be some extra characters in s which are not present in any of the
+ * substrings.
+ *
+ * Return the minimum number of extra characters left over if you break up s optimally.
+ */
+
+/**
+ * @param {string} s
+ * @param {string[]} dictionary
+ * @return {number}
+ */
+var minExtraChar = function(s, dictionary) {
+  const n = s.length;
+  const dp = new Array(n + 1).fill(Infinity);
+  dp[0] = 0;
+  const dictSet = new Set(dictionary);
+
+  for (let i = 1; i <= n; i++) {
+    dp[i] = dp[i - 1] + 1;
+    for (let j = 0; j < i; j++) {
+      if (dictSet.has(s.slice(j, i))) {
+        dp[i] = Math.min(dp[i], dp[j]);
+      }
+    }
+  }
+
+  return dp[n];
+};
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/2799-count-complete-subarrays-in-an-array.js b/solutions/2799-count-complete-subarrays-in-an-array.js
new file mode 100644
index 00000000..1ba19bb5
--- /dev/null
+++ b/solutions/2799-count-complete-subarrays-in-an-array.js
@@ -0,0 +1,42 @@
+/**
+ * 2799. Count Complete Subarrays in an Array
+ * https://leetcode.com/problems/count-complete-subarrays-in-an-array/
+ * Difficulty: Medium
+ *
+ * You are given an array nums consisting of positive integers.
+ *
+ * We call a subarray of an array complete if the following condition is satisfied:
+ * - The number of distinct elements in the subarray is equal to the number of distinct
+ *   elements in the whole array.
+ *
+ * Return the number of complete subarrays.
+ *
+ * A subarray is a contiguous non-empty part of an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {number}
+ */
+var countCompleteSubarrays = function(nums) {
+  const totalDistinct = new Set(nums).size;
+  const frequency = new Map();
+  let completeCount = 0;
+  let left = 0;
+
+  for (let right = 0; right < nums.length; right++) {
+    frequency.set(nums[right], (frequency.get(nums[right]) || 0) + 1);
+
+    while (frequency.size === totalDistinct) {
+      completeCount += nums.length - right;
+      const leftNum = nums[left];
+      frequency.set(leftNum, frequency.get(leftNum) - 1);
+      if (frequency.get(leftNum) === 0) {
+        frequency.delete(leftNum);
+      }
+      left++;
+    }
+  }
+
+  return completeCount;
+};
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/2845-count-of-interesting-subarrays.js b/solutions/2845-count-of-interesting-subarrays.js
new file mode 100644
index 00000000..841f4b24
--- /dev/null
+++ b/solutions/2845-count-of-interesting-subarrays.js
@@ -0,0 +1,37 @@
+/**
+ * 2845. Count of Interesting Subarrays
+ * https://leetcode.com/problems/count-of-interesting-subarrays/
+ * Difficulty: Medium
+ *
+ * You are given a 0-indexed integer array nums, an integer modulo, and an integer k.
+ *
+ * Your task is to find the count of subarrays that are interesting.
+ *
+ * A subarray nums[l..r] is interesting if the following condition holds:
+ * - Let cnt be the number of indices i in the range [l, r] such that nums[i] % modulo == k.
+ *   Then, cnt % modulo == k.
+ *
+ * Return an integer denoting the count of interesting subarrays.
+ *
+ * Note: A subarray is a contiguous non-empty sequence of elements within an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} modulo
+ * @param {number} k
+ * @return {number}
+ */
+var countInterestingSubarrays = function(nums, modulo, k) {
+  const prefixCounts = new Map([[0, 1]]);
+  let currentSum = 0;
+  let result = 0;
+
+  for (const num of nums) {
+    currentSum = (currentSum + (num % modulo === k ? 1 : 0)) % modulo;
+    result += prefixCounts.get((currentSum - k + modulo) % modulo) || 0;
+    prefixCounts.set(currentSum, (prefixCounts.get(currentSum) || 0) + 1);
+  }
+
+  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/2894-divisible-and-non-divisible-sums-difference.js b/solutions/2894-divisible-and-non-divisible-sums-difference.js
new file mode 100644
index 00000000..31f068ec
--- /dev/null
+++ b/solutions/2894-divisible-and-non-divisible-sums-difference.js
@@ -0,0 +1,33 @@
+/**
+ * 2894. Divisible and Non-divisible Sums Difference
+ * https://leetcode.com/problems/divisible-and-non-divisible-sums-difference/
+ * Difficulty: Easy
+ *
+ * You are given positive integers n and m.
+ *
+ * Define two integers as follows:
+ * - num1: The sum of all integers in the range [1, n] (both inclusive) that are not divisible by m.
+ * - num2: The sum of all integers in the range [1, n] (both inclusive) that are divisible by m.
+ *
+ * Return the integer num1 - num2.
+ */
+
+/**
+ * @param {number} n
+ * @param {number} m
+ * @return {number}
+ */
+var differenceOfSums = function(n, m) {
+  let nonDivisibleSum = 0;
+  let divisibleSum = 0;
+
+  for (let i = 1; i <= n; i++) {
+    if (i % m === 0) {
+      divisibleSum += i;
+    } else {
+      nonDivisibleSum += i;
+    }
+  }
+
+  return nonDivisibleSum - divisibleSum;
+};
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/2900-longest-unequal-adjacent-groups-subsequence-i.js b/solutions/2900-longest-unequal-adjacent-groups-subsequence-i.js
new file mode 100644
index 00000000..b4df7c52
--- /dev/null
+++ b/solutions/2900-longest-unequal-adjacent-groups-subsequence-i.js
@@ -0,0 +1,40 @@
+/**
+ * 2900. Longest Unequal Adjacent Groups Subsequence I
+ * https://leetcode.com/problems/longest-unequal-adjacent-groups-subsequence-i/
+ * Difficulty: Easy
+ *
+ * You are given a string array words and a binary array groups both of length n, where words[i]
+ * is associated with groups[i].
+ *
+ * Your task is to select the longest alternating subsequence from words. A subsequence of words
+ * is alternating if for any two consecutive strings in the sequence, their corresponding elements
+ * in the binary array groups differ. Essentially, you are to choose strings such that adjacent
+ * elements have non-matching corresponding bits in the groups array.
+ *
+ * Formally, you need to find the longest subsequence of an array of indices [0, 1, ..., n - 1]
+ * denoted as [i0, i1, ..., ik-1], such that groups[ij] != groups[ij+1] for each 0 <= j < k - 1
+ * and then find the words corresponding to these indices.
+ *
+ * Return the selected subsequence. If there are multiple answers, return any of them.
+ *
+ * Note: The elements in words are distinct.
+ */
+
+/**
+ * @param {string[]} words
+ * @param {number[]} groups
+ * @return {string[]}
+ */
+var getLongestSubsequence = function(words, groups) {
+  const result = [words[0]];
+  let lastGroup = groups[0];
+
+  for (let i = 1; i < words.length; i++) {
+    if (groups[i] !== lastGroup) {
+      result.push(words[i]);
+      lastGroup = groups[i];
+    }
+  }
+
+  return result;
+};
diff --git a/solutions/2901-longest-unequal-adjacent-groups-subsequence-ii.js b/solutions/2901-longest-unequal-adjacent-groups-subsequence-ii.js
new file mode 100644
index 00000000..1a290423
--- /dev/null
+++ b/solutions/2901-longest-unequal-adjacent-groups-subsequence-ii.js
@@ -0,0 +1,68 @@
+/**
+ * 2901. Longest Unequal Adjacent Groups Subsequence II
+ * https://leetcode.com/problems/longest-unequal-adjacent-groups-subsequence-ii/
+ * Difficulty: Medium
+ *
+ * You are given a string array words, and an array groups, both arrays having length n.
+ *
+ * The hamming distance between two strings of equal length is the number of positions at which the
+ * corresponding characters are different.
+ *
+ * You need to select the longest subsequence from an array of indices [0, 1, ..., n - 1], such
+ * that for the subsequence denoted as [i0, i1, ..., ik-1] having length k, the following holds:
+ * - For adjacent indices in the subsequence, their corresponding groups are unequal, i.e.,
+ *   groups[ij] != groups[ij+1], for each j where 0 < j + 1 < k.
+ * - words[ij] and words[ij+1] are equal in length, and the hamming distance between them is 1,
+ *   where 0 < j + 1 < k, for all indices in the subsequence.
+ *
+ * Return a string array containing the words corresponding to the indices (in order) in the
+ * selected subsequence. If there are multiple answers, return any of them.
+ *
+ * Note: strings in words may be unequal in length.
+ */
+
+/**
+ * @param {string[]} words
+ * @param {number[]} groups
+ * @return {string[]}
+ */
+var getWordsInLongestSubsequence = function(words, groups) {
+  const n = words.length;
+  const dp = new Array(n).fill(1);
+  const prev = new Array(n).fill(-1);
+  let maxLen = 1;
+  let lastIndex = 0;
+
+  for (let i = 1; i < n; i++) {
+    for (let j = 0; j < i; j++) {
+      if (groups[i] !== groups[j] && helper(words[i], words[j])) {
+        if (dp[j] + 1 > dp[i]) {
+          dp[i] = dp[j] + 1;
+          prev[i] = j;
+        }
+      }
+    }
+    if (dp[i] > maxLen) {
+      maxLen = dp[i];
+      lastIndex = i;
+    }
+  }
+
+  const result = [];
+  while (lastIndex !== -1) {
+    result.push(words[lastIndex]);
+    lastIndex = prev[lastIndex];
+  }
+
+  return result.reverse();
+
+  function helper(s1, s2) {
+    if (s1.length !== s2.length) return false;
+    let diff = 0;
+    for (let i = 0; i < s1.length; i++) {
+      if (s1[i] !== s2[i]) diff++;
+      if (diff > 1) return false;
+    }
+    return diff === 1;
+  }
+};
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/2918-minimum-equal-sum-of-two-arrays-after-replacing-zeros.js b/solutions/2918-minimum-equal-sum-of-two-arrays-after-replacing-zeros.js
new file mode 100644
index 00000000..15ea4af7
--- /dev/null
+++ b/solutions/2918-minimum-equal-sum-of-two-arrays-after-replacing-zeros.js
@@ -0,0 +1,40 @@
+/**
+ * 2918. Minimum Equal Sum of Two Arrays After Replacing Zeros
+ * https://leetcode.com/problems/minimum-equal-sum-of-two-arrays-after-replacing-zeros/
+ * Difficulty: Medium
+ *
+ * You are given two arrays nums1 and nums2 consisting of positive integers.
+ *
+ * You have to replace all the 0's in both arrays with strictly positive integers such that the
+ * sum of elements of both arrays becomes equal.
+ *
+ * Return the minimum equal sum you can obtain, or -1 if it is impossible.
+ */
+
+/**
+ * @param {number[]} nums1
+ * @param {number[]} nums2
+ * @return {number}
+ */
+var minSum = function(nums1, nums2) {
+  let sum1 = 0;
+  let zeros1 = 0;
+  for (const num of nums1) {
+    sum1 += num;
+    if (num === 0) zeros1++;
+  }
+
+  let sum2 = 0;
+  let zeros2 = 0;
+  for (const num of nums2) {
+    sum2 += num;
+    if (num === 0) zeros2++;
+  }
+
+  const minSum1 = sum1 + zeros1;
+  const minSum2 = sum2 + zeros2;
+
+  if (minSum1 > sum2 && zeros2 === 0 || minSum2 > sum1 && zeros1 === 0) return -1;
+
+  return Math.max(minSum1, minSum2);
+};
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/2942-find-words-containing-character.js b/solutions/2942-find-words-containing-character.js
new file mode 100644
index 00000000..9fadea6b
--- /dev/null
+++ b/solutions/2942-find-words-containing-character.js
@@ -0,0 +1,28 @@
+/**
+ * 2942. Find Words Containing Character
+ * https://leetcode.com/problems/find-words-containing-character/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed array of strings words and a character x.
+ *
+ * Return an array of indices representing the words that contain the character x.
+ *
+ * Note that the returned array may be in any order.
+ */
+
+/**
+ * @param {string[]} words
+ * @param {character} x
+ * @return {number[]}
+ */
+var findWordsContaining = function(words, x) {
+  const result = [];
+
+  for (let i = 0; i < words.length; i++) {
+    if (words[i].includes(x)) {
+      result.push(i);
+    }
+  }
+
+  return result;
+};
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/2962-count-subarrays-where-max-element-appears-at-least-k-times.js b/solutions/2962-count-subarrays-where-max-element-appears-at-least-k-times.js
new file mode 100644
index 00000000..1a67fad9
--- /dev/null
+++ b/solutions/2962-count-subarrays-where-max-element-appears-at-least-k-times.js
@@ -0,0 +1,35 @@
+/**
+ * 2962. Count Subarrays Where Max Element Appears at Least K Times
+ * https://leetcode.com/problems/count-subarrays-where-max-element-appears-at-least-k-times/
+ * Difficulty: Medium
+ *
+ * You are given an integer array nums and a positive integer k.
+ *
+ * Return the number of subarrays where the maximum element of nums appears at least k times in
+ * that subarray.
+ *
+ * A subarray is a contiguous sequence of elements within an array.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @return {number}
+ */
+var countSubarrays = function(nums, k) {
+  const maxNum = Math.max(...nums);
+  let maxCount = 0;
+  let left = 0;
+  let result = 0;
+
+  for (let right = 0; right < nums.length; right++) {
+    if (nums[right] === maxNum) maxCount++;
+    while (maxCount >= k) {
+      result += nums.length - right;
+      if (nums[left] === maxNum) maxCount--;
+      left++;
+    }
+  }
+
+  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/3024-type-of-triangle.js b/solutions/3024-type-of-triangle.js
new file mode 100644
index 00000000..0a62411d
--- /dev/null
+++ b/solutions/3024-type-of-triangle.js
@@ -0,0 +1,27 @@
+/**
+ * 3024. Type of Triangle
+ * https://leetcode.com/problems/type-of-triangle/
+ * Difficulty: Easy
+ *
+ * You are given a 0-indexed integer array nums of size 3 which can form the sides of a triangle.
+ * - A triangle is called equilateral if it has all sides of equal length.
+ * - A triangle is called isosceles if it has exactly two sides of equal length.
+ * - A triangle is called scalene if all its sides are of different lengths.
+ *
+ * Return a string representing the type of triangle that can be formed or "none" if it cannot
+ * form a triangle.
+ */
+
+/**
+ * @param {number[]} nums
+ * @return {string}
+ */
+var triangleType = function(nums) {
+  const [sideA, sideB, sideC] = nums.sort((a, b) => a - b);
+
+  if (sideA + sideB <= sideC) return 'none';
+  if (sideA === sideB && sideB === sideC) return 'equilateral';
+  if (sideA === sideB || sideB === sideC) return 'isosceles';
+
+  return 'scalene';
+};
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/3068-find-the-maximum-sum-of-node-values.js b/solutions/3068-find-the-maximum-sum-of-node-values.js
new file mode 100644
index 00000000..27666217
--- /dev/null
+++ b/solutions/3068-find-the-maximum-sum-of-node-values.js
@@ -0,0 +1,52 @@
+/**
+ * 3068. Find the Maximum Sum of Node Values
+ * https://leetcode.com/problems/find-the-maximum-sum-of-node-values/
+ * Difficulty: Hard
+ *
+ * There exists an undirected tree with n nodes numbered 0 to n - 1. You are given a 0-indexed
+ * 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. You are also given a positive integer k, and a
+ * 0-indexed array of non-negative integers nums of length n, where nums[i] represents the
+ * value of the node numbered i.
+ *
+ * Alice wants the sum of values of tree nodes to be maximum, for which Alice can perform the
+ * following operation any number of times (including zero) on the tree:
+ * - Choose any edge [u, v] connecting the nodes u and v, and update their values as follows:
+ *   - nums[u] = nums[u] XOR k
+ *   - nums[v] = nums[v] XOR k
+ *
+ * Return the maximum possible sum of the values Alice can achieve by performing the operation
+ * any number of times.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number} k
+ * @param {number[][]} edges
+ * @return {number}
+ */
+var maximumValueSum = function(nums, k, edges) {
+  let totalSum = 0;
+  let minChange = Infinity;
+  let changeCount = 0;
+
+  for (const num of nums) {
+    const xored = num ^ k;
+    const change = xored - num;
+
+    if (change > 0) {
+      totalSum += xored;
+      changeCount++;
+    } else {
+      totalSum += num;
+    }
+
+    minChange = Math.min(minChange, Math.abs(change));
+  }
+
+  if (changeCount % 2 === 0) {
+    return totalSum;
+  }
+
+  return totalSum - minChange;
+};
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/3178-find-the-child-who-has-the-ball-after-k-seconds.js b/solutions/3178-find-the-child-who-has-the-ball-after-k-seconds.js
new file mode 100644
index 00000000..cdbd5d88
--- /dev/null
+++ b/solutions/3178-find-the-child-who-has-the-ball-after-k-seconds.js
@@ -0,0 +1,25 @@
+/**
+ * 3178. Find the Child Who Has the Ball After K Seconds
+ * https://leetcode.com/problems/find-the-child-who-has-the-ball-after-k-seconds/
+ * Difficulty: Easy
+ *
+ * You are given two positive integers n and k. There are n children numbered from 0 to n - 1
+ * standing in a queue in order from left to right.
+ *
+ * Initially, child 0 holds a ball and the direction of passing the ball is towards the right
+ * direction. After each second, the child holding the ball passes it to the child next to
+ * them. Once the ball reaches either end of the line, i.e. child 0 or child n - 1, the direction
+ * of passing is reversed.
+ *
+ * Return the number of the child who receives the ball after k seconds.
+ */
+
+/**
+ * @param {number} n
+ * @param {number} k
+ * @return {number}
+ */
+var numberOfChild = function(n, k) {
+  const position = k % (2 * (n - 1));
+  return position < n ? position : 2 * n - position - 2;
+};
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/3335-total-characters-in-string-after-transformations-i.js b/solutions/3335-total-characters-in-string-after-transformations-i.js
new file mode 100644
index 00000000..e62e76ea
--- /dev/null
+++ b/solutions/3335-total-characters-in-string-after-transformations-i.js
@@ -0,0 +1,47 @@
+/**
+ * 3335. Total Characters in String After Transformations I
+ * https://leetcode.com/problems/total-characters-in-string-after-transformations-i/
+ * Difficulty: Medium
+ *
+ * You are given a string s and an integer t, representing the number of transformations to
+ * perform. In one transformation, every character in s is replaced according to the following
+ * rules:
+ * - If the character is 'z', replace it with the string "ab".
+ * - Otherwise, replace it with the next character in the alphabet. For example, 'a' is replaced
+ *   with 'b', 'b' is replaced with 'c', and so on.
+ *
+ * Return the length of the resulting string after exactly t transformations.
+ *
+ * Since the answer may be very large, return it modulo 109 + 7.
+ */
+
+/**
+ * @param {string} s
+ * @param {number} t
+ * @return {number}
+ */
+var lengthAfterTransformations = function(s, t) {
+  const MOD = 1e9 + 7;
+  const freq = new Array(26).fill(0);
+
+  for (const char of s) {
+    freq[char.charCodeAt(0) - 97]++;
+  }
+
+  for (let i = 0; i < t; i++) {
+    const newFreq = new Array(26).fill(0);
+    for (let j = 0; j < 25; j++) {
+      newFreq[j + 1] = freq[j];
+    }
+    newFreq[0] = (newFreq[0] + freq[25]) % MOD;
+    newFreq[1] = (newFreq[1] + freq[25]) % MOD;
+    freq.splice(0, 26, ...newFreq);
+  }
+
+  let result = 0;
+  for (const count of freq) {
+    result = (result + count) % MOD;
+  }
+
+  return result;
+};
diff --git a/solutions/3337-total-characters-in-string-after-transformations-ii.js b/solutions/3337-total-characters-in-string-after-transformations-ii.js
new file mode 100644
index 00000000..91d4d6aa
--- /dev/null
+++ b/solutions/3337-total-characters-in-string-after-transformations-ii.js
@@ -0,0 +1,78 @@
+/**
+ * 3337. Total Characters in String After Transformations II
+ * https://leetcode.com/problems/total-characters-in-string-after-transformations-ii/
+ * Difficulty: Hard
+ *
+ * You are given a string s consisting of lowercase English letters, an integer t representing
+ * the number of transformations to perform, and an array nums of size 26. In one transformation,
+ * every character in s is replaced according to the following rules:
+ * - Replace s[i] with the next nums[s[i] - 'a'] consecutive characters in the alphabet. For
+ *   example, if s[i] = 'a' and nums[0] = 3, the character 'a' transforms into the next 3
+ *   consecutive characters ahead of it, which results in "bcd".
+ * - The transformation wraps around the alphabet if it exceeds 'z'. For example, if s[i] = 'y'
+ *   and nums[24] = 3, the character 'y' transforms into the next 3 consecutive characters ahead
+ *   of it, which results in "zab".
+ *
+ * Return the length of the resulting string after exactly t transformations.
+ *
+ * Since the answer may be very large, return it modulo 109 + 7.
+ */
+
+/**
+ * @param {string} s
+ * @param {number} t
+ * @param {number[]} nums
+ * @return {number}
+ */
+var lengthAfterTransformations = function(s, t, nums) {
+  const MOD = 1000000007n;
+  const freq = new Array(26).fill(0n);
+
+  for (const char of s) {
+    freq[char.charCodeAt(0) - 97]++;
+  }
+
+  const matrix = new Array(26).fill().map(() => new Array(26).fill(0n));
+  for (let i = 0; i < 26; i++) {
+    for (let j = 0; j < nums[i]; j++) {
+      matrix[(i + j + 1) % 26][i] = 1n;
+    }
+  }
+
+  const finalMatrix = matrixPower(matrix, t);
+  let total = 0n;
+
+  for (let i = 0; i < 26; i++) {
+    let sum = 0n;
+    for (let j = 0; j < 26; j++) {
+      sum = (sum + finalMatrix[i][j] * freq[j]) % MOD;
+    }
+    total = (total + sum) % MOD;
+  }
+
+  return Number(total);
+
+  function matrixMultiply(a, b) {
+    const result = new Array(26).fill().map(() => new Array(26).fill(0n));
+    for (let i = 0; i < 26; i++) {
+      for (let j = 0; j < 26; j++) {
+        for (let k = 0; k < 26; k++) {
+          result[i][j] = (result[i][j] + a[i][k] * b[k][j]) % MOD;
+        }
+      }
+    }
+    return result;
+  }
+
+  function matrixPower(mat, power) {
+    let result = new Array(26).fill().map(() => new Array(26).fill(0n));
+    for (let i = 0; i < 26; i++) result[i][i] = 1n;
+
+    while (power > 0) {
+      if (power & 1) result = matrixMultiply(result, mat);
+      mat = matrixMultiply(mat, mat);
+      power >>= 1;
+    }
+    return result;
+  }
+};
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/3341-find-minimum-time-to-reach-last-room-i.js b/solutions/3341-find-minimum-time-to-reach-last-room-i.js
new file mode 100644
index 00000000..fae5957b
--- /dev/null
+++ b/solutions/3341-find-minimum-time-to-reach-last-room-i.js
@@ -0,0 +1,55 @@
+/**
+ * 3341. Find Minimum Time to Reach Last Room I
+ * https://leetcode.com/problems/find-minimum-time-to-reach-last-room-i/
+ * Difficulty: Medium
+ *
+ * There is a dungeon with n x m rooms arranged as a grid.
+ *
+ * You are given a 2D array moveTime of size n x m, where moveTime[i][j] represents the minimum
+ * time in seconds when you can start moving to that room. You start from the room (0, 0) at
+ * time t = 0 and can move to an adjacent room. Moving between adjacent rooms takes exactly
+ * one second.
+ *
+ * Return the minimum time to reach the room (n - 1, m - 1).
+ *
+ * Two rooms are adjacent if they share a common wall, either horizontally or vertically.
+ */
+
+/**
+ * @param {number[][]} moveTime
+ * @return {number}
+ */
+var minTimeToReach = function(moveTime) {
+  const rows = moveTime.length;
+  const cols = moveTime[0].length;
+  const distances = Array.from({ length: rows }, () => new Array(cols).fill(Infinity));
+  const pq = new PriorityQueue((a, b) => a[0] - b[0]);
+  pq.enqueue([0, 0, 0]);
+  const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]];
+
+  distances[0][0] = 0;
+
+  while (!pq.isEmpty()) {
+    const [time, row, col] = pq.dequeue();
+
+    if (row === rows - 1 && col === cols - 1) return time;
+
+    if (time > distances[row][col]) continue;
+
+    for (const [dr, dc] of directions) {
+      const newRow = row + dr;
+      const newCol = col + dc;
+
+      if (newRow < 0 || newRow >= rows || newCol < 0 || newCol >= cols) continue;
+
+      const newTime = Math.max(time, moveTime[newRow][newCol]) + 1;
+
+      if (newTime < distances[newRow][newCol]) {
+        distances[newRow][newCol] = newTime;
+        pq.enqueue([newTime, newRow, newCol]);
+      }
+    }
+  }
+
+  return distances[rows - 1][cols - 1];
+};
diff --git a/solutions/3342-find-minimum-time-to-reach-last-room-ii.js b/solutions/3342-find-minimum-time-to-reach-last-room-ii.js
new file mode 100644
index 00000000..24c9fc5a
--- /dev/null
+++ b/solutions/3342-find-minimum-time-to-reach-last-room-ii.js
@@ -0,0 +1,57 @@
+/**
+ * 3342. Find Minimum Time to Reach Last Room II
+ * https://leetcode.com/problems/find-minimum-time-to-reach-last-room-ii/
+ * Difficulty: Medium
+ *
+ * There is a dungeon with n x m rooms arranged as a grid.
+ *
+ * You are given a 2D array moveTime of size n x m, where moveTime[i][j] represents the minimum
+ * time in seconds when you can start moving to that room. You start from the room (0, 0) at
+ * time t = 0 and can move to an adjacent room. Moving between adjacent rooms takes one
+ * second for one move and two seconds for the next, alternating between the two.
+ *
+ * Return the minimum time to reach the room (n - 1, m - 1).
+ *
+ * Two rooms are adjacent if they share a common wall, either horizontally or vertically.
+ */
+
+/**
+ * @param {number[][]} moveTime
+ * @return {number}
+ */
+var minTimeToReach = function(moveTime) {
+  const rows = moveTime.length;
+  const cols = moveTime[0].length;
+  const distances = Array.from({ length: rows }, () => new Array(cols).fill(Infinity));
+  const pq = new PriorityQueue((a, b) => a[0] - b[0]);
+  pq.enqueue([0, 0, 0, 0]);
+  const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]];
+
+  distances[0][0] = 0;
+
+  while (!pq.isEmpty()) {
+    const [time, row, col, moveCount] = pq.dequeue();
+
+    if (row === rows - 1 && col === cols - 1) return time;
+
+    if (time > distances[row][col]) continue;
+
+    for (const [dr, dc] of directions) {
+      const newRow = row + dr;
+      const newCol = col + dc;
+
+      if (newRow < 0 || newRow >= rows || newCol < 0 || newCol >= cols) continue;
+
+      const moveCost = moveCount % 2 === 0 ? 1 : 2;
+      const startTime = Math.max(time, moveTime[newRow][newCol]);
+      const newTime = startTime + moveCost;
+
+      if (newTime < distances[newRow][newCol]) {
+        distances[newRow][newCol] = newTime;
+        pq.enqueue([newTime, newRow, newCol, moveCount + 1]);
+      }
+    }
+  }
+
+  return distances[rows - 1][cols - 1];
+};
diff --git a/solutions/3343-count-number-of-balanced-permutations.js b/solutions/3343-count-number-of-balanced-permutations.js
new file mode 100644
index 00000000..0e27eae1
--- /dev/null
+++ b/solutions/3343-count-number-of-balanced-permutations.js
@@ -0,0 +1,70 @@
+/**
+ * 3343. Count Number of Balanced Permutations
+ * https://leetcode.com/problems/count-number-of-balanced-permutations/
+ * Difficulty: Hard
+ *
+ * You are given a string num. A string of digits is called balanced if the sum of the digits
+ * at even indices is equal to the sum of the digits at odd indices.
+ *
+ * Return the number of distinct permutations of num that are balanced.
+ *
+ * Since the answer may be very large, return it modulo 109 + 7.
+ *
+ * A permutation is a rearrangement of all the characters of a string.
+ */
+
+/**
+ * @param {string} num
+ * @return {number}
+ */
+var countBalancedPermutations = function(num) {
+  const MOD = 1e9 + 7;
+  const n = num.length;
+  const digitCounts = new Array(10).fill(0);
+  let totalSum = 0;
+
+  for (const char of num) {
+    const digit = parseInt(char);
+    digitCounts[digit]++;
+    totalSum += digit;
+  }
+
+  if (totalSum % 2) return 0;
+
+  const memo = new Map();
+
+  function combination(n, r) {
+    if (r > n) return 0;
+    if (r === 0 || r === n) return 1;
+    if (r > n - r) r = n - r;
+
+    let result = 1n;
+    for (let i = 0; i < r; i++) {
+      result = result * BigInt(n - i) / BigInt(i + 1);
+    }
+    return Number(result % BigInt(MOD));
+  }
+
+  function exploreDigits(digit, oddSlots, evenSlots, targetBalance) {
+    if (oddSlots === 0 && evenSlots === 0 && targetBalance === 0) return 1;
+    if (digit < 0 || oddSlots < 0 || evenSlots < 0 || targetBalance < 0) return 0;
+
+    const key = `${digit},${oddSlots},${evenSlots},${targetBalance}`;
+    if (memo.has(key)) return memo.get(key);
+
+    let result = 0;
+    for (let oddCount = 0; oddCount <= digitCounts[digit]; oddCount++) {
+      const evenCount = digitCounts[digit] - oddCount;
+      const ways = (BigInt(combination(oddSlots, oddCount))
+        * BigInt(combination(evenSlots, evenCount))) % BigInt(MOD);
+      const next = BigInt(exploreDigits(digit - 1, oddSlots - oddCount,
+        evenSlots - evenCount, targetBalance - digit * oddCount));
+      result = (result + Number((ways * next) % BigInt(MOD))) % MOD;
+    }
+
+    memo.set(key, result);
+    return result;
+  }
+
+  return exploreDigits(9, n - Math.floor(n / 2), Math.floor(n / 2), totalSum / 2);
+};
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/3355-zero-array-transformation-i.js b/solutions/3355-zero-array-transformation-i.js
new file mode 100644
index 00000000..21b9bc13
--- /dev/null
+++ b/solutions/3355-zero-array-transformation-i.js
@@ -0,0 +1,43 @@
+/**
+ * 3355. Zero Array Transformation I
+ * https://leetcode.com/problems/zero-array-transformation-i/
+ * Difficulty: Medium
+ *
+ * You are given an integer array nums of length n and a 2D array queries, where
+ * queries[i] = [li, ri].
+ *
+ * For each queries[i]:
+ * - Select a subset of indices within the range [li, ri] in nums.
+ * - Decrement the values at the selected indices by 1.
+ *
+ * A Zero Array is an array where all elements are equal to 0.
+ *
+ * Return true if it is possible to transform nums into a Zero Array after processing all the
+ * queries sequentially, otherwise return false.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number[][]} queries
+ * @return {boolean}
+ */
+var isZeroArray = function(nums, queries) {
+  const maxDecrements = new Array(nums.length).fill(0);
+
+  for (const [left, right] of queries) {
+    maxDecrements[left]++;
+    if (right + 1 < nums.length) {
+      maxDecrements[right + 1]--;
+    }
+  }
+
+  let currentDecrements = 0;
+  for (let i = 0; i < nums.length; i++) {
+    currentDecrements += maxDecrements[i];
+    if (nums[i] > currentDecrements) {
+      return false;
+    }
+  }
+
+  return true;
+};
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/3362-zero-array-transformation-iii.js b/solutions/3362-zero-array-transformation-iii.js
new file mode 100644
index 00000000..f6d979bb
--- /dev/null
+++ b/solutions/3362-zero-array-transformation-iii.js
@@ -0,0 +1,53 @@
+/**
+ * 3362. Zero Array Transformation III
+ * https://leetcode.com/problems/zero-array-transformation-iii/
+ * Difficulty: Medium
+ *
+ * You are given an integer array nums of length n and a 2D array queries where
+ * queries[i] = [li, ri].
+ *
+ * Each queries[i] represents the following action on nums:
+ * - Decrement the value at each index in the range [li, ri] in nums by at most 1.
+ * - The amount by which the value is decremented can be chosen independently for each index.
+ *
+ * A Zero Array is an array with all its elements equal to 0.
+ *
+ * Return the maximum number of elements that can be removed from queries, such that nums can
+ * still be converted to a zero array using the remaining queries. If it is not possible to
+ * convert nums to a zero array, return -1.
+ */
+
+/**
+ * @param {number[]} nums
+ * @param {number[][]} queries
+ * @return {number}
+ */
+var maxRemoval = function(nums, queries) {
+  queries.sort((a, b) => a[0] - b[0]);
+  const endIndexHeap = new MaxPriorityQueue();
+  const expiredQueries = new Array(nums.length + 1).fill(0);
+  let operationCount = 0;
+  let queryIndex = 0;
+
+  for (let numIndex = 0; numIndex < nums.length; numIndex++) {
+    operationCount -= expiredQueries[numIndex];
+
+    while (queryIndex < queries.length && queries[queryIndex][0] === numIndex) {
+      endIndexHeap.push(queries[queryIndex][1]);
+      queryIndex++;
+    }
+
+    while (
+      operationCount < nums[numIndex] && !endIndexHeap.isEmpty() && endIndexHeap.front() >= numIndex
+    ) {
+      operationCount++;
+      expiredQueries[endIndexHeap.pop() + 1]++;
+    }
+
+    if (operationCount < nums[numIndex]) {
+      return -1;
+    }
+  }
+
+  return endIndexHeap.size();
+};
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/3372-maximize-the-number-of-target-nodes-after-connecting-trees-i.js b/solutions/3372-maximize-the-number-of-target-nodes-after-connecting-trees-i.js
new file mode 100644
index 00000000..c4ce5f98
--- /dev/null
+++ b/solutions/3372-maximize-the-number-of-target-nodes-after-connecting-trees-i.js
@@ -0,0 +1,87 @@
+/**
+ * 3372. Maximize the Number of Target Nodes After Connecting Trees I
+ * https://leetcode.com/problems/maximize-the-number-of-target-nodes-after-connecting-trees-i/
+ * Difficulty: Medium
+ *
+ * There exist two undirected trees with n and m nodes, with distinct labels in ranges [0, n - 1]
+ * and [0, m - 1], respectively.
+ *
+ * You are given two 2D integer arrays edges1 and edges2 of lengths n - 1 and m - 1, respectively,
+ * where edges1[i] = [ai, bi] indicates that there is an edge between nodes ai and bi in the first
+ * tree and edges2[i] = [ui, vi] indicates that there is an edge between nodes ui and vi in the
+ * second tree. You are also given an integer k.
+ *
+ * Node u is target to node v if the number of edges on the path from u to v is less than or equal
+ * to k. Note that a node is always target to itself.
+ *
+ * Return an array of n integers answer, where answer[i] is the maximum possible number of nodes
+ * target to node i of the first tree if you have to connect one node from the first tree to
+ * another node in the second tree.
+ *
+ * Note that queries are independent from each other. That is, for every query you will remove
+ * the added edge before proceeding to the next query.
+ */
+
+/**
+ * @param {number[][]} edges1
+ * @param {number[][]} edges2
+ * @param {number} k
+ * @return {number[]}
+ */
+var maxTargetNodes = function(edges1, edges2, k) {
+  const graph1 = buildGraph(edges1);
+  const graph2 = buildGraph(edges2);
+  const n = edges1.length + 1;
+  const m = edges2.length + 1;
+
+  let tree2Max = 0;
+  if (k > 0) {
+    tree2Max = Math.max(...Array.from({ length: m }, (_, i) =>
+      countReachable(graph2, i, k - 1)
+    ));
+  }
+
+  const result = [];
+  for (let i = 0; i < n; i++) {
+    const tree1Count = countReachable(graph1, i, k);
+    result.push(tree1Count + tree2Max);
+  }
+
+  return result;
+
+  function buildGraph(edges) {
+    const graph = {};
+    for (const [u, v] of edges) {
+      if (!graph[u]) graph[u] = [];
+      if (!graph[v]) graph[v] = [];
+      graph[u].push(v);
+      graph[v].push(u);
+    }
+    return graph;
+  }
+
+  function countReachable(graph, start, maxDist) {
+    const queue = [start];
+    const visited = new Set([start]);
+    let count = 1;
+    let dist = 0;
+
+    while (queue.length > 0 && dist < maxDist) {
+      const size = queue.length;
+      dist++;
+      for (let i = 0; i < size; i++) {
+        const node = queue.shift();
+        if (graph[node]) {
+          for (const neighbor of graph[node]) {
+            if (!visited.has(neighbor)) {
+              visited.add(neighbor);
+              queue.push(neighbor);
+              count++;
+            }
+          }
+        }
+      }
+    }
+    return count;
+  }
+};
diff --git a/solutions/3373-maximize-the-number-of-target-nodes-after-connecting-trees-ii.js b/solutions/3373-maximize-the-number-of-target-nodes-after-connecting-trees-ii.js
new file mode 100644
index 00000000..8ac956f1
--- /dev/null
+++ b/solutions/3373-maximize-the-number-of-target-nodes-after-connecting-trees-ii.js
@@ -0,0 +1,79 @@
+/**
+ * 3373. Maximize the Number of Target Nodes After Connecting Trees II
+ * https://leetcode.com/problems/maximize-the-number-of-target-nodes-after-connecting-trees-ii/
+ * Difficulty: Hard
+ *
+ * There exist two undirected trees with n and m nodes, labeled from [0, n - 1] and [0, m - 1],
+ * respectively.
+ *
+ * You are given two 2D integer arrays edges1 and edges2 of lengths n - 1 and m - 1, respectively,
+ * where edges1[i] = [ai, bi] indicates that there is an edge between nodes ai and bi in the first
+ * tree and edges2[i] = [ui, vi] indicates that there is an edge between nodes ui and vi in the
+ * second tree.
+ *
+ * Node u is target to node v if the number of edges on the path from u to v is even. Note that
+ * a node is always target to itself.
+ *
+ * Return an array of n integers answer, where answer[i] is the maximum possible number of nodes
+ * that are target to node i of the first tree if you had to connect one node from the first tree
+ * to another node in the second tree.
+ *
+ * Note that queries are independent from each other. That is, for every query you will remove the
+ * added edge before proceeding to the next query.
+ */
+
+/**
+ * @param {number[][]} edges1
+ * @param {number[][]} edges2
+ * @return {number[]}
+ */
+var maxTargetNodes = function(edges1, edges2) {
+  const graph1 = buildGraph(edges1);
+  const graph2 = buildGraph(edges2);
+  const n = graph1.length;
+  const { color: color1 } = getBipartiteGroups(graph1);
+  const { maxGroup: maxGroup2 } = getBipartiteGroups(graph2);
+  const group0Count = color1.filter(c => c === 0).length;
+  const group1Count = n - group0Count;
+  const result = new Array(n);
+
+  for (let i = 0; i < n; i++) {
+    result[i] = (color1[i] === 0 ? group0Count : group1Count) + maxGroup2;
+  }
+
+  return result;
+
+  function buildGraph(edges) {
+    const n = edges.length + 1;
+    const graph = Array.from({ length: n }, () => []);
+    for (const [u, v] of edges) {
+      graph[u].push(v);
+      graph[v].push(u);
+    }
+    return graph;
+  }
+
+  function getBipartiteGroups(graph) {
+    const n = graph.length;
+    const color = new Array(n).fill(-1);
+    const groups = [0, 0];
+
+    for (let i = 0; i < n; i++) {
+      if (color[i] === -1) {
+        dfs(i, 0);
+      }
+    }
+
+    return { color, maxGroup: Math.max(groups[0], groups[1]) };
+
+    function dfs(node, c) {
+      color[node] = c;
+      groups[c]++;
+      for (const neighbor of graph[node]) {
+        if (color[neighbor] === -1) {
+          dfs(neighbor, 1 - c);
+        }
+      }
+    }
+  }
+};
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;
+};