diff --git a/README.md b/README.md index bb07c5c9..9978339f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# 1,709 LeetCode solutions in JavaScript +# 1,980 LeetCode solutions in JavaScript [https://leetcodejavascript.com](https://leetcodejavascript.com) @@ -1571,55 +1571,313 @@ 2045|[Second Minimum Time to Reach Destination](./solutions/2045-second-minimum-time-to-reach-destination.js)|Hard| 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| 2053|[Kth Distinct String in an Array](./solutions/2053-kth-distinct-string-in-an-array.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| +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| +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| +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| +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| 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| +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| 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| +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| +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| 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| +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| 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| +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| +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| +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| 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| +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| +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| +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| 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| +2183|[Count Array Pairs Divisible by K](./solutions/2183-count-array-pairs-divisible-by-k.js)|Hard| 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| +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| +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| 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| +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| 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| +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| +2232|[Minimize Result by Adding Parentheses to Expression](./solutions/2232-minimize-result-by-adding-parentheses-to-expression.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| +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| +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| +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| +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| +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| +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| +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| +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| +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| +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| +2309|[Greatest English Letter in Upper and Lower Case](./solutions/2309-greatest-english-letter-in-upper-and-lower-case.js)|Easy| +2312|[Selling Pieces of Wood](./solutions/2312-selling-pieces-of-wood.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| +2325|[Decode the Message](./solutions/2325-decode-the-message.js)|Easy| +2326|[Spiral Matrix IV](./solutions/2326-spiral-matrix-iv.js)|Medium| +2328|[Number of Increasing Paths in a Grid](./solutions/2328-number-of-increasing-paths-in-a-grid.js)|Hard| +2331|[Evaluate Boolean Binary Tree](./solutions/2331-evaluate-boolean-binary-tree.js)|Easy| +2334|[Subarray With Elements Greater Than Varying Threshold](./solutions/2334-subarray-with-elements-greater-than-varying-threshold.js)|Hard| 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| +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| +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| +2354|[Number of Excellent Pairs](./solutions/2354-number-of-excellent-pairs.js)|Hard| +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| +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| +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| 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| +2385|[Amount of Time for Binary Tree to Be Infected](./solutions/2385-amount-of-time-for-binary-tree-to-be-infected.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| +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| +2399|[Check Distances Between Same Letters](./solutions/2399-check-distances-between-same-letters.js)|Easy| 2401|[Longest Nice Subarray](./solutions/2401-longest-nice-subarray.js)|Medium| +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| +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| +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| +2421|[Number of Good Paths](./solutions/2421-number-of-good-paths.js)|Hard| 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| +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| +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| +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| +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| +2458|[Height of Binary Tree After Subtree Removal Queries](./solutions/2458-height-of-binary-tree-after-subtree-removal-queries.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| +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| +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| +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| +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| +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| 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| 2493|[Divide Nodes Into the Maximum Number of Groups](./solutions/2493-divide-nodes-into-the-maximum-number-of-groups.js)|Hard| 2503|[Maximum Number of Points From Grid Queries](./solutions/2503-maximum-number-of-points-from-grid-queries.js)|Hard| 2523|[Closest Prime Numbers in Range](./solutions/2523-closest-prime-numbers-in-range.js)|Medium| @@ -1634,6 +1892,7 @@ 2570|[Merge Two 2D Arrays by Summing Values](./solutions/2570-merge-two-2d-arrays-by-summing-values.js)|Easy| 2579|[Count Total Number of Colored Cells](./solutions/2579-count-total-number-of-colored-cells.js)|Medium| 2594|[Minimum Time to Repair Cars](./solutions/2594-minimum-time-to-repair-cars.js)|Medium| +2615|[Sum of Distances](./solutions/2615-sum-of-distances.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| @@ -1684,12 +1943,18 @@ 2845|[Count of Interesting Subarrays](./solutions/2845-count-of-interesting-subarrays.js)|Medium| 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| +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| +2918|[Minimum Equal Sum of Two Arrays After Replacing Zeros](./solutions/2918-minimum-equal-sum-of-two-arrays-after-replacing-zeros.js)|Medium| +2942|[Find Words Containing Character](./solutions/2942-find-words-containing-character.js)|Easy| 2948|[Make Lexicographically Smallest Array by Swapping Elements](./solutions/2948-make-lexicographically-smallest-array-by-swapping-elements.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| 2965|[Find Missing and Repeated Values](./solutions/2965-find-missing-and-repeated-values.js)|Easy| 2999|[Count the Number of Powerful Integers](./solutions/2999-count-the-number-of-powerful-integers.js)|Hard| +3024|[Type of Triangle](./solutions/3024-type-of-triangle.js)|Easy| 3042|[Count Prefix and Suffix Pairs I](./solutions/3042-count-prefix-and-suffix-pairs-i.js)|Easy| 3066|[Minimum Operations to Exceed Threshold Value II](./solutions/3066-minimum-operations-to-exceed-threshold-value-ii.js)|Medium| +3068|[Find the Maximum Sum of Node Values](./solutions/3068-find-the-maximum-sum-of-node-values.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| 3110|[Score of a String](./solutions/3110-score-of-a-string.js)|Easy| @@ -1702,8 +1967,14 @@ 3223|[Minimum Length of String After Operations](./solutions/3223-minimum-length-of-string-after-operations.js)|Medium| 3272|[Find the Count of Good Integers](./solutions/3272-find-the-count-of-good-integers.js)|Hard| 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| +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| +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| +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| +3362|[Zero Array Transformation III](./solutions/3362-zero-array-transformation-iii.js)|Medium| 3375|[Minimum Operations to Make Array Values Equal to K](./solutions/3375-minimum-operations-to-make-array-values-equal-to-k.js)|Easy| 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| 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/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/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/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/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/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/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/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/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/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/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/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, anddenotes 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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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(); +};