├── 1.two-sum.rb ├── 10.regular-expression-matching.rb ├── 1005.maximize-sum-of-array-after-k-negations.rb ├── 101.symmetric-tree.rb ├── 1012.complement-of-base-10-integer.rb ├── 1013.pairs-of-songs-with-total-durations-divisible-by-60.rb ├── 1014.capacity-to-ship-packages-within-d-days.rb ├── 102.binary-tree-level-order-traversal.rb ├── 1021.remove-outermost-parentheses.rb ├── 1022.sum-of-root-to-leaf-binary-numbers.rb ├── 1023.camelcase-matching.rb ├── 1024.video-stitching.rb ├── 1025.divisor-game.rb ├── 1026.maximum-difference-between-node-and-ancestor.rb ├── 1027.longest-arithmetic-sequence.rb ├── 1028.recover-a-tree-from-preorder-traversal.rb ├── 1029.two-city-scheduling.rb ├── 103.binary-tree-zigzag-level-order-traversal.rb ├── 1030.matrix-cells-in-distance-order.rb ├── 1031.maximum-sum-of-two-non-overlapping-subarrays.rb ├── 1032.stream-of-characters.rb ├── 1033.moving-stones-until-consecutive.rb ├── 1034.coloring-a-border.rb ├── 1035.uncrossed-lines.rb ├── 1037.valid-boomerang.rb ├── 1038.binary-search-tree-to-greater-sum-tree.rb ├── 1039.minimum-score-triangulation-of-polygon.rb ├── 104.maximum-depth-of-binary-tree.rb ├── 1041.robot-bounded-in-circle.rb ├── 1042.flower-planting-with-no-adjacent.rb ├── 1043.partition-array-for-maximum-sum.rb ├── 105.construct-binary-tree-from-preorder-and-inorder-traversal.rb ├── 106.construct-binary-tree-from-inorder-and-postorder-traversal.rb ├── 108.convert-sorted-array-to-binary-search-tree.rb ├── 11.container-with-most-water.rb ├── 110.balanced-binary-tree.rb ├── 111.minimum-depth-of-binary-tree.rb ├── 112.path-sum.rb ├── 113.path-sum-ii.rb ├── 116.populating-next-right-pointers-in-each-node.rb ├── 118.pascals-triangle.rb ├── 119.pascals-triangle-ii.rb ├── 121.best-time-to-buy-and-sell-stock.rb ├── 122.best-time-to-buy-and-sell-stock-ii.rb ├── 123.best-time-to-buy-and-sell-stock-iii.rb ├── 124.binary-tree-maximum-path-sum.rb ├── 125.valid-palindrome.rb ├── 126.word-ladder-ii.rb ├── 127.word-ladder.rb ├── 128.longest-consecutive-sequence.rb ├── 13.roman-to-integer.rb ├── 130.surrounded-regions.rb ├── 131.palindrome-partitioning.rb ├── 134.gas-station.rb ├── 136.single-number.rb ├── 138.copy-list-with-random-pointer.rb ├── 139.word-break.rb ├── 14.longest-common-prefix.rb ├── 140.word-break-ii.rb ├── 141.linked-list-cycle.rb ├── 144.binary-tree-preorder-traversal.rb ├── 146.lru-cache.rb ├── 148.sort-list.rb ├── 149.max-points-on-a-line.rb ├── 15.3sum.rb ├── 150.evaluate-reverse-polish-notation.rb ├── 151.reverse-words-in-a-string.rb ├── 152.maximum-product-subarray.rb ├── 155.min-stack.rb ├── 157.read-n-characters-given-read4.rb ├── 16.3sum-closest.rb ├── 160.intersection-of-two-linked-lists.rb ├── 162.find-peak-element.rb ├── 163.missing-ranges.rb ├── 166.fraction-to-recurring-decimal.rb ├── 167.two-sum-ii-input-array-is-sorted.rb ├── 169.majority-element.rb ├── 17.letter-combinations-of-a-phone-number.rb ├── 171.excel-sheet-column-number.rb ├── 172.factorial-trailing-zeroes.rb ├── 186.reverse-words-in-a-string-ii.rb ├── 189.rotate-array.rb ├── 19.remove-nth-node-from-end-of-list.rb ├── 191.number-of-1-bits.rb ├── 198.house-robber.rb ├── 199.binary-tree-right-side-view.rb ├── 2.add-two-numbers.rb ├── 20.valid-parentheses.rb ├── 200.number-of-islands.rb ├── 202.happy-number.rb ├── 203.remove-linked-list-elements.rb ├── 204.count-primes.rb ├── 206.reverse-linked-list.rb ├── 207.course-schedule.rb ├── 208.implement-trie-prefix-tree.rb ├── 209.minimum-size-subarray-sum.rb ├── 21.merge-two-sorted-lists.rb ├── 210.course-schedule-ii.rb ├── 212.word-search-ii.rb ├── 213.house-robber-ii.rb ├── 215.kth-largest-element-in-an-array.rb ├── 216.combination-sum-iii.rb ├── 218.the-skyline-problem.rb ├── 22.generate-parentheses.rb ├── 226.invert-binary-tree.rb ├── 228.summary-ranges.rb ├── 23.merge-k-sorted-lists.rb ├── 230.kth-smallest-element-in-a-bst.rb ├── 234.palindrome-linked-list.rb ├── 235.lowest-common-ancestor-of-a-binary-search-tree.rb ├── 236.lowest-common-ancestor-of-a-binary-tree.rb ├── 237.delete-node-in-a-linked-list.rb ├── 238.product-of-array-except-self.rb ├── 239.sliding-window-maximum.rb ├── 240.search-a-2d-matrix-ii.rb ├── 242.valid-anagram.rb ├── 243.shortest-word-distance.rb ├── 25.reverse-nodes-in-k-group.rb ├── 252.meeting-rooms.rb ├── 253.meeting-rooms-ii.rb ├── 256.paint-house.rb ├── 26.remove-duplicates-from-sorted-array.rb ├── 266.palindrome-permutation.rb ├── 269.alien-dictionary.rb ├── 276.paint-fence.rb ├── 28.implement-strstr.rb ├── 280.wiggle-sort.rb ├── 285.inorder-successor-in-bst.rb ├── 29.divide-two-integers.rb ├── 292.nim-game.rb ├── 295.find-median-from-data-stream.rb ├── 297.serialize-and-deserialize-binary-tree.rb ├── 3.longest-substring-without-repeating-characters.rb ├── 300.longest-increasing-subsequence.rb ├── 303.range-sum-query-immutable.rb ├── 307.range-sum-query-mutable.rb ├── 31.next-permutation.rb ├── 315.count-of-smaller-numbers-after-self.rb ├── 32.longest-valid-parentheses.rb ├── 322.coin-change.rb ├── 327.count-of-range-sum.rb ├── 33.search-in-rotated-sorted-array.rb ├── 336.palindrome-pairs.rb ├── 337.house-robber-iii.rb ├── 339.nested-list-weight-sum.rb ├── 34.find-first-and-last-position-of-element-in-sorted-array.rb ├── 344.reverse-string.rb ├── 346.moving-average-from-data-stream.rb ├── 347.top-k-frequent-elements.rb ├── 35.search-insert-position.rb ├── 36.valid-sudoku.rb ├── 371.sum-of-two-integers.rb ├── 378.kth-smallest-element-in-a-sorted-matrix.rb ├── 380.insert-delete-getrandom-o1.rb ├── 381.insert-delete-getrandom-o1-duplicates-allowed.rb ├── 384.shuffle-an-array.rb ├── 387.first-unique-character-in-a-string.rb ├── 388.longest-absolute-file-path.rb ├── 39.combination-sum.rb ├── 4.median-of-two-sorted-arrays.rb ├── 40.combination-sum-ii.rb ├── 409.longest-palindrome.rb ├── 41.first-missing-positive.rb ├── 416.partition-equal-subset-sum.rb ├── 42.trapping-rain-water.rb ├── 437.path-sum-iii.rb ├── 44.wildcard-matching.rb ├── 442.find-all-duplicates-in-an-array.rb ├── 445.add-two-numbers-ii.rb ├── 449.serialize-and-deserialize-bst.rb ├── 45.jump-game-ii.rb ├── 450.delete-node-in-a-bst.rb ├── 451.sort-characters-by-frequency.rb ├── 46.permutations.rb ├── 460.lfu-cache.rb ├── 461.hamming-distance.rb ├── 47.permutations-ii.rb ├── 48.rotate-image.rb ├── 49.group-anagrams.rb ├── 493.reverse-pairs.rb ├── 5.longest-palindromic-substring.rb ├── 50.powx-n.rb ├── 509.fibonacci-number.rb ├── 51.n-queens.rb ├── 515.find-largest-value-in-each-tree-row.rb ├── 516.longest-palindromic-subsequence.rb ├── 518.coin-change-2.rb ├── 52.n-queens-ii.rb ├── 523.continuous-subarray-sum.rb ├── 53.maximum-subarray.rb ├── 535.encode-and-decode-tinyurl.rb ├── 54.spiral-matrix.rb ├── 548.split-array-with-equal-sum.rb ├── 55.jump-game.rb ├── 56.merge-intervals.rb ├── 560.subarray-sum-equals-k.rb ├── 57.insert-interval.rb ├── 572.subtree-of-another-tree.rb ├── 587.erect-the-fence.rb ├── 59.spiral-matrix-ii.rb ├── 6.zigzag-conversion.rb ├── 61.rotate-list.rb ├── 617.merge-two-binary-trees.rb ├── 62.unique-paths.rb ├── 63.unique-paths-ii.rb ├── 66.plus-one.rb ├── 661.image-smoother.rb ├── 666.path-sum-iv.rb ├── 673.number-of-longest-increasing-subsequence.rb ├── 674.longest-continuous-increasing-subsequence.rb ├── 678.valid-parenthesis-string.rb ├── 69.sqrtx.rb ├── 694.number-of-distinct-islands.rb ├── 695.max-area-of-island.rb ├── 7.reverse-integer.rb ├── 70.climbing-stairs.rb ├── 701.insert-into-a-binary-search-tree.rb ├── 704.binary-search.rb ├── 706.design-hashmap.rb ├── 718.maximum-length-of-repeated-subarray.rb ├── 719.find-k-th-smallest-pair-distance.rb ├── 72.edit-distance.rb ├── 73.set-matrix-zeroes.rb ├── 733.flood-fill.rb ├── 74.search-a-2d-matrix.rb ├── 743.network-delay-time.rb ├── 75.sort-colors.rb ├── 76.minimum-window-substring.rb ├── 765.couples-holding-hands.rb ├── 78.subsets.rb ├── 783.minimum-distance-between-bst-nodes.rb ├── 787.cheapest-flights-within-k-stops.rb ├── 79.word-search.rb ├── 790.domino-and-tromino-tiling.rb ├── 8.string-to-integer-atoi.rb ├── 80.remove-duplicates-from-sorted-array-ii.rb ├── 81.search-in-rotated-sorted-array-ii.rb ├── 812.largest-triangle-area.rb ├── 836.rectangle-overlap.rb ├── 84.largest-rectangle-in-histogram.rb ├── 862.shortest-subarray-with-sum-at-least-k.rb ├── 863.all-nodes-distance-k-in-binary-tree.rb ├── 876.middle-of-the-linked-list.rb ├── 88.merge-sorted-array.rb ├── 89.gray-code.rb ├── 9.palindrome-number.rb ├── 91.decode-ways.rb ├── 938.range-sum-of-bst.rb ├── 94.binary-tree-inorder-traversal.rb ├── 947.most-stones-removed-with-same-row-or-column.rb ├── 958.check-completeness-of-a-binary-tree.rb ├── 973.k-closest-points-to-origin.rb ├── 98.validate-binary-search-tree.rb ├── 980.unique-paths-iii.rb ├── 99.recover-binary-search-tree.rb ├── README.org ├── data-structures ├── fenwick-tree.rb ├── heap.rb ├── segment-tree.rb ├── sparse-table.rb ├── treap.rb └── union-find.rb ├── imgs ├── meme0.jpg ├── meme1.jpg └── meme2.jpg └── other ├── build-array-from-count-of-bigger-numbers-before-self.rb ├── distance-between-2-nodes-in-BST.rb ├── fair-work-load.rb ├── generic-cow-protests.rb ├── longest-subarray-sum-equals-s.rb ├── longest-subsequence-of-balanced-parentheses.rb ├── lowest-common-territory-of-places.rb ├── merge-two-intervals.rb ├── minimum-flip-to-sorted-string.rb ├── swap-lex-order.rb └── villagers-and-defenders.rb /1.two-sum.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=1 lang=ruby 4 | # 5 | # [1] Two Sum 6 | # 7 | # https://leetcode.com/problems/two-sum/description/ 8 | # 9 | # Given an array of integers, return indices of the two numbers such 10 | # that they add up to a specific target. 11 | # 12 | # You may assume that each input would have exactly one solution, and 13 | # you may not use the same element twice. 14 | # 15 | # Example: 16 | # 17 | # Given nums = [2, 7, 11, 15], target = 9, 18 | # Because nums[0] + nums[1] = 2 + 7 = 9, 19 | # return [0, 1]. 20 | 21 | 22 | # @param {Integer[]} nums 23 | # @param {Integer} target 24 | # @return {Integer[]} 25 | def two_sum(nums, target) 26 | hash = {} 27 | nums.each_with_index { |x, i| 28 | return [hash[target-x], i] if hash.has_key?(target-x) 29 | hash[x] = i 30 | } 31 | end 32 | -------------------------------------------------------------------------------- /101.symmetric-tree.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=101 lang=ruby 4 | # 5 | # [101] Symmetric Tree 6 | # 7 | # https://leetcode.com/problems/symmetric-tree/description/ 8 | # 9 | # Given a binary tree, check whether it is a mirror of itself (ie, symmetric 10 | # around its center). 11 | # 12 | # For example, this binary tree [1,2,2,3,4,4,3] is symmetric: 13 | # 14 | # ⁠ 1 15 | # ⁠ / \ 16 | # ⁠ 2 2 17 | # ⁠/ \ / \ 18 | # 3 4 4 3 19 | # 20 | # But the following [1,2,2,null,3,null,3] is not: 21 | # 22 | # ⁠ 1 23 | # ⁠ / \ 24 | # ⁠ 2 2 25 | # ⁠ \ \ 26 | # ⁠ 3 3 27 | # 28 | # Note: 29 | # 30 | # Bonus points if you could solve it both recursively and iteratively. 31 | # 32 | # Definition for a binary tree node. 33 | # class TreeNode 34 | # attr_accessor :val, :left, :right 35 | # def initialize(val) 36 | # @val = val 37 | # @left, @right = nil, nil 38 | # end 39 | # end 40 | 41 | 42 | # Recursive. 43 | 44 | # @param {TreeNode} root 45 | # @return {Boolean} 46 | def is_symmetric(root) 47 | return true if root.nil? 48 | helper(root.left, root.right) 49 | end 50 | 51 | def helper(a, b) 52 | return true if a.nil? && b.nil? 53 | return false if a.nil? || b.nil? 54 | a.val == b.val && helper(a.left, b.right) && helper(a.right, b.left) 55 | end 56 | 57 | 58 | # Iterative. 59 | 60 | def is_symmetric_a(root) 61 | q = [root.right, root.left] 62 | while !q.empty? 63 | t1 = q.pop 64 | t2 = q.pop 65 | next if t1.nil? && t2.nil? 66 | return false if t1.nil? || t2.nil? || t1.val != t2.val 67 | q.unshift t1.left 68 | q.unshift t2.right 69 | q.unshift t1.right 70 | q.unshift t2.left 71 | end 72 | true 73 | end 74 | -------------------------------------------------------------------------------- /1012.complement-of-base-10-integer.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=1012 lang=ruby 4 | # 5 | # [1012] Complement of Base 10 Integer 6 | # 7 | # https://leetcode.com/problems/complement-of-base-10-integer/description/ 8 | # 9 | # Every non-negative integer N has a binary representation. For 10 | # example, 5 can be represented as "101" in binary, 11 as "1011" in 11 | # binary, and so on.Note that except for N = 0, there are no leading 12 | # zeroes in any binary representation. 13 | # 14 | # The complement of a binary representation is the number in binary 15 | # you get when changing every 1 to a 0 and 0 to a 1. For example, the 16 | # complement of "101" in binary is "010" in binary. 17 | # 18 | # For a given number N in base-10, return the complement of it's 19 | # binary representation as a base-10 integer. 20 | # 21 | # Example 1: 22 | # 23 | # Input: 5 24 | # Output: 2 25 | # Explanation: 5 is "101" in binary, with complement "010" in binary, 26 | # which is 2 in base-10. 27 | # 28 | # Example 2: 29 | # 30 | # Input: 7 31 | # Output: 0 32 | # Explanation: 7 is "111" in binary, with complement "000" in binary, 33 | # which is 0 in base-10. 34 | # 35 | # Example 3: 36 | # 37 | # Input: 10 38 | # Output: 5 39 | # Explanation: 10 is "1010" in binary, with complement "0101" in 40 | # binary, which is 5 in base-10. 41 | # 42 | # Note: 43 | # 44 | # 0 <= N < 10^9 45 | 46 | 47 | # Ruby... 48 | 49 | # @param {Integer} n 50 | # @return {Integer} 51 | def bitwise_complement_a(n) 52 | return 1 if n == 0 53 | s = "" 54 | n.bit_length.times do |i| 55 | s.prepend n[i] == 1 ? '0' : '1' 56 | end 57 | s.to_i(2) 58 | end 59 | 60 | 61 | # Or, use Math: 62 | # 63 | # 1. n ^ complement(n) = 11...11 64 | # 2. complement(n) = 11...11 ^ n 65 | 66 | def bitwise_complement(n) 67 | return 1 if n == 0 68 | n ^ (1< 60 38 | # 20%60=(20+60)%60=(20+60+60)%60=(20+...)%60=20 39 | # 40%60=(40+60)%60=(40+60+60)%60=(40+...)%60=40 40 | # x%60=(x+60)%60=(x+60+60)%60=(x+...)%60 41 | # y%60=(y+60)%60=(y+60+60)%60=(y+...)%60 42 | # we want (x+y)%60==0, then x%60+y%60==60, ehmmm, it's two sum problem... 43 | # the only exception is when x%60=0, then we also want y%60=0 44 | 45 | # @param {Integer[]} time 46 | # @return {Integer} 47 | def num_pairs_divisible_by60(time) 48 | h, count = Hash.new(0), 0 49 | time.each do |t| 50 | x = 60-t%60 51 | count += h[x == 60 ? 0 : x] 52 | h[t%60] += 1 53 | end 54 | count 55 | end 56 | -------------------------------------------------------------------------------- /102.binary-tree-level-order-traversal.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=102 lang=ruby 4 | # 5 | # [102] Binary Tree Level Order Traversal 6 | # 7 | # https://leetcode.com/problems/binary-tree-level-order-traversal/description/ 8 | # 9 | # Given a binary tree, return the level order traversal of its nodes' 10 | # values. (ie, from left to right, level by level). 11 | # 12 | # For example: 13 | # Given binary tree [3,9,20,null,null,15,7], 14 | # 15 | # ⁠ 3 16 | # ⁠ / \ 17 | # ⁠ 9 20 18 | # ⁠ / \ 19 | # ⁠ 15 7 20 | # 21 | # return its level order traversal as: 22 | # 23 | # [ 24 | # ⁠ [3], 25 | # ⁠ [9,20], 26 | # ⁠ [15,7] 27 | # ] 28 | # 29 | # Definition for a binary tree node. 30 | # class TreeNode 31 | # attr_accessor :val, :left, :right 32 | # def initialize(val) 33 | # @val = val 34 | # @left, @right = nil, nil 35 | # end 36 | # end 37 | 38 | 39 | # The key is how to process one level at a time: only process queue's 40 | # size at a time. 41 | 42 | # @param {TreeNode} root 43 | # @return {Integer[][]} 44 | def level_order(root) 45 | return [] if root.nil? 46 | result = [] 47 | queue = [root] 48 | until queue.empty? 49 | sub = [] 50 | queue.size.times do 51 | x = queue.shift 52 | sub << x.val 53 | queue << x.left unless x.left.nil? 54 | queue << x.right unless x.right.nil? 55 | end 56 | result << sub 57 | end 58 | result 59 | end 60 | -------------------------------------------------------------------------------- /1022.sum-of-root-to-leaf-binary-numbers.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=5017 lang=ruby 4 | # 5 | # [5017] Sum of Root To Leaf Binary Numbers 6 | # 7 | # https://leetcode.com/problems/sum-of-root-to-leaf-binary-numbers/description/ 8 | # 9 | # Given a binary tree, each node has value 0 or 1. Each root-to-leaf 10 | # path represents a binary number starting with the most significant 11 | # bit. For example, if the path is 0 -> 1 -> 1 -> 0 -> 1, then this 12 | # could represent 01101 in binary, which is 13. 13 | # 14 | # For all leaves in the tree, consider the numbers represented by the 15 | # path from the root to that leaf. 16 | # 17 | # Return the sum of these numbers modulo 10^9 + 7. 18 | # 19 | # Example 1: 20 | # 21 | # Input: [1,0,1,0,1,0,1] 22 | # Output: 22 23 | # Explanation: (100) + (101) + (110) + (111) = 4 + 5 + 6 + 7 = 22 24 | # 25 | # Note: 26 | # 27 | # The number of nodes in the tree is between 1 and 1000. 28 | # node.val is 0 or 1. 29 | # 30 | # Definition for a binary tree node. 31 | # class TreeNode 32 | # attr_accessor :val, :left, :right 33 | # def initialize(val) 34 | # @val = val 35 | # @left, @right = nil, nil 36 | # end 37 | # end 38 | 39 | 40 | # DFS... 41 | 42 | # @param {TreeNode} root 43 | # @return {Integer} 44 | def sum_root_to_leaf(root, v=0) 45 | return 0 if root.nil? 46 | v = v*2 + root.val 47 | return v if root.left.nil? && root.right.nil? 48 | (sum_root_to_leaf(root.left, v) + sum_root_to_leaf(root.right, v)) % (10**9 + 7) 49 | end 50 | -------------------------------------------------------------------------------- /1025.divisor-game.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=1025 lang=ruby 4 | # 5 | # [1025] Divisor Game 6 | # 7 | # https://leetcode.com/problems/divisor-game/description/ 8 | # 9 | # Alice and Bob take turns playing a game, with Alice starting first. 10 | # 11 | # Initially, there is a number N on the chalkboard. On each player's 12 | # turn, that player makes a move consisting of: 13 | # 14 | # Choosing any x with 0 < x < N and N % x == 0. 15 | # Replacing the number N on the chalkboard with N - x. 16 | # 17 | # Also, if a player cannot make a move, they lose the game. 18 | # 19 | # Return True if and only if Alice wins the game, assuming both 20 | # players play optimally. 21 | # 22 | # Example 1: 23 | # 24 | # Input: 2 25 | # Output: true 26 | # Explanation: Alice chooses 1, and Bob has no more moves. 27 | # 28 | # Example 2: 29 | # 30 | # Input: 3 31 | # Output: false 32 | # Explanation: Alice chooses 1, Bob chooses 1, and Alice has no more 33 | # moves. 34 | # 35 | # Note: 36 | # 37 | # 1 <= N <= 1000 38 | 39 | 40 | # @param {Integer} n 41 | # @return {Boolean} 42 | def divisor_game(n) 43 | n.even? 44 | end 45 | -------------------------------------------------------------------------------- /1029.two-city-scheduling.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=1029 lang=ruby 4 | # 5 | # [1029] Two City Scheduling 6 | # 7 | # https://leetcode.com/problems/two-city-scheduling/description/ 8 | # 9 | # There are 2N people a company is planning to interview. The cost of 10 | # flying the i-th person to city A is costs[i][0], and the cost of 11 | # flying the i-th person to city B is costs[i][1]. 12 | # 13 | # Return the minimum cost to fly every person to a city such that 14 | # exactly N people arrive in each city. 15 | # 16 | # Example 1: 17 | # 18 | # Input: [[10,20],[30,200],[400,50],[30,20]] 19 | # Output: 110 20 | # Explanation: 21 | # The first person goes to city A for a cost of 10. 22 | # The second person goes to city A for a cost of 30. 23 | # The third person goes to city B for a cost of 50. 24 | # The fourth person goes to city B for a cost of 20. 25 | # 26 | # The total minimum cost is 10 + 30 + 50 + 20 = 110 to have half the people 27 | # interviewing in each city. 28 | # 29 | # Note: 30 | # 31 | # 1 <= costs.length <= 100 32 | # It is guaranteed that costs.length is even. 33 | # 1 <= costs[i][0], costs[i][1] <= 1000 34 | 35 | 36 | # Cost of flying the i-th person to A instead of B: 37 | # d[i] = costs[i][0]-costs[i][1]. 38 | # if d[i] < 0, then we've saved -d[i] money. 39 | # if d[i] > 0, then we've spent d[i] more money. 40 | # we want to save the most amount for A then spend the rest for B. 41 | # So sort by d[i], the first half is for A, the last half is for B. 42 | 43 | # @param {Integer[][]} costs 44 | # @return {Integer} 45 | def two_city_sched_cost(costs) 46 | x = cost.sort_by { |(a, b)| a-b } 47 | m = costs.size/2-1 48 | x[0..m].sum { |a, _| a } + x[m+1..-1].sum { |_, b| b } 49 | end 50 | -------------------------------------------------------------------------------- /103.binary-tree-zigzag-level-order-traversal.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=103 lang=ruby 4 | # 5 | # [103] Binary Tree Zigzag Level Order Traversal 6 | # 7 | # https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/description/ 8 | # 9 | # Given a binary tree, return the zigzag level order traversal of its 10 | # nodes' values. (ie, from left to right, then right to left for the 11 | # next level and alternate between). 12 | # 13 | # For example: 14 | # Given binary tree [3,9,20,null,null,15,7], 15 | # ⁠ 3 16 | # ⁠ / \ 17 | # ⁠ 9 20 18 | # ⁠ / \ 19 | # ⁠ 15 7 20 | # return its zigzag level order traversal as: 21 | # [ 22 | # ⁠ [3], 23 | # ⁠ [20,9], 24 | # ⁠ [15,7] 25 | # ] 26 | # 27 | # Definition for a binary tree node. 28 | # class TreeNode 29 | # attr_accessor :val, :left, :right 30 | # def initialize(val) 31 | # @val = val 32 | # @left, @right = nil, nil 33 | # end 34 | # end 35 | 36 | 37 | # Same old level order traversal. 38 | 39 | # @param {TreeNode} root 40 | # @return {Integer[][]} 41 | def zigzag_level_order(root) 42 | return [] if root.nil? 43 | q, flip, ans = [root], false, [] 44 | while !q.empty? 45 | sub = [] 46 | m = flip ? :unshift : :<< 47 | q.size.times do 48 | x = q.shift 49 | sub.send(m, x.val) 50 | q << x.left if x.left 51 | q << x.right if x.right 52 | end 53 | flip = !flip 54 | ans << sub 55 | end 56 | ans 57 | end 58 | -------------------------------------------------------------------------------- /1035.uncrossed-lines.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=1035 lang=ruby 4 | # 5 | # [1035] Uncrossed Lines 6 | # 7 | # https://leetcode.com/problems/uncrossed-lines/description/ 8 | # 9 | # We write the integers of A and B (in the order they are given) on 10 | # two separate horizontal lines. 11 | # 12 | # Now, we may draw a straight line connecting two numbers A[i] and 13 | # B[j] as long as A[i] == B[j], and the line we draw does not 14 | # intersect any other connecting (non-horizontal) line. 15 | # 16 | # Return the maximum number of connecting lines we can draw in this way. 17 | # 18 | # Example 1: 19 | # 20 | # Input: A = [1,4,2], B = [1,2,4] 21 | # Output: 2 22 | # Explanation: We can draw 2 uncrossed lines as in the diagram. 23 | # We cannot draw 3 uncrossed lines, because the line from A[1]=4 to B[2]=4 will 24 | # intersect the line from A[2]=2 to B[1]=2. 25 | # 26 | # Example 2: 27 | # 28 | # Input: A = [2,5,1,2,5], B = [10,5,2,1,5,2] 29 | # Output: 3 30 | # 31 | # Example 3: 32 | # 33 | # Input: A = [1,3,7,1,7,5], B = [1,9,2,5,1] 34 | # Output: 2 35 | # 36 | # Note: 37 | # 38 | # 1 <= A.length <= 500 39 | # 1 <= B.length <= 500 40 | # 1 <= A[i], B[i] <= 2000 41 | 42 | 43 | # DP. 44 | 45 | # @param {Integer[]} a 46 | # @param {Integer[]} b 47 | # @return {Integer} 48 | def max_uncrossed_lines(a, b) 49 | m, n = a.size, b.size 50 | d = Array.new(m+1) { Array.new(n+1, 0) } 51 | (m-1).downto(0).each do |i| 52 | (n-1).downto(0).each do |j| 53 | if a[i] == b[j] 54 | d[i][j] = d[i+1][j+1] + 1 55 | else 56 | d[i][j] = [d[i][j+1], d[i+1][j]].max 57 | end 58 | end 59 | end 60 | d[0][0] 61 | end 62 | -------------------------------------------------------------------------------- /1037.valid-boomerang.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=1037 lang=ruby 4 | # 5 | # [1037] Valid Boomerang 6 | # 7 | # https://leetcode.com/problems/valid-boomerang/description/ 8 | # 9 | # A boomerang is a set of 3 points that are all distinct and not in a 10 | # straight line. 11 | # 12 | # Given a list of three points in the plane, return whether these 13 | # points are a boomerang. 14 | # 15 | # Example 1: 16 | # 17 | # Input: [[1,1],[2,3],[3,2]] 18 | # Output: true 19 | # 20 | # Example 2: 21 | # 22 | # Input: [[1,1],[2,2],[3,3]] 23 | # Output: false 24 | # 25 | # Note: 26 | # 27 | # points.length == 3 28 | # points[i].length == 2 29 | # 0 <= points[i][j] <= 100 30 | 31 | 32 | # The area of the triangle formed by these points should not be 0. 33 | # See: https://math.stackexchange.com/a/1414021 34 | 35 | # @param {Integer[][]} points 36 | # @return {Boolean} 37 | def is_boomerang(points) 38 | x1, y1 = points[0] 39 | x2, y2 = points[1] 40 | x3, y3 = points[2] 41 | (x2-x1)*(y3-y1) - (x3-x1)*(y2-y1) != 0 42 | end 43 | -------------------------------------------------------------------------------- /1038.binary-search-tree-to-greater-sum-tree.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=1038 lang=ruby 4 | # 5 | # [1038] Binary Search Tree to Greater Sum Tree 6 | # 7 | # https://leetcode.com/problems/binary-search-tree-to-greater-sum-tree/description/ 8 | # 9 | # Given the root of a binary search tree with distinct values, modify 10 | # it so that every node has a new value equal to the sum of the values 11 | # of the original tree that are greater than or equal to node.val. 12 | # 13 | # Example 1: 14 | # 15 | # Input: [4,1,6,0,2,5,7,null,null,null,3,null,null,null,8] 16 | # Output: [30,36,21,36,35,26,15,null,null,null,33,null,null,null,8] 17 | # 18 | # Note: 19 | # 20 | # The number of nodes in the tree is between 1 and 100. 21 | # Each node will have value between 0 and 100. 22 | # The given tree is a binary search tree. 23 | # 24 | # Definition for a binary tree node. 25 | # class TreeNode 26 | # attr_accessor :val, :left, :right 27 | # def initialize(val) 28 | # @val = val 29 | # @left, @right = nil, nil 30 | # end 31 | # end 32 | 33 | 34 | # Inorder traversal. 35 | 36 | # @param {TreeNode} root 37 | # @return {TreeNode} 38 | def bst_to_gst(root, sum=[0]) 39 | return if root.nil? 40 | bst_to_gst(root.right, sum) 41 | sum[0] += root.val 42 | root.val = sum[0] 43 | bst_to_gst(root.left, sum) 44 | root 45 | end 46 | -------------------------------------------------------------------------------- /1043.partition-array-for-maximum-sum.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=1043 lang=ruby 4 | # 5 | # [1043] Partition Array for Maximum Sum 6 | # 7 | # https://leetcode.com/problems/partition-array-for-maximum-sum/description/ 8 | # 9 | # Given an integer array A, you partition the array into (contiguous) 10 | # subarrays of length at most K. After partitioning, each subarray has 11 | # their values changed to become the maximum value of that subarray. 12 | # 13 | # Return the largest sum of the given array after partitioning. 14 | # 15 | # Example 1: 16 | # 17 | # Input: A = [1,15,7,9,2,5,10], K = 3 18 | # Output: 84 19 | # Explanation: A becomes [15,15,15,9,10,10,10] 20 | # 21 | # Note: 22 | # 23 | # 1 <= K <= A.length <= 500 24 | # 0 <= A[i] <= 10^6 25 | 26 | 27 | # DP. d[i]: answer for a[i..-1]. 28 | 29 | # @param {Integer[]} a 30 | # @param {Integer} k 31 | # @return {Integer} 32 | def max_sum_after_partitioning(a, k) 33 | n = a.size 34 | d = Array.new(n+1, 0) 35 | (n-1).downto(0) do |i| 36 | max = 0 37 | k.times do |j| 38 | break if i+j+1 > n 39 | max = [max, a[i+j]].max 40 | d[i] = [d[i], max*(j+1)+d[i+j+1]].max 41 | end 42 | end 43 | d[0] 44 | end 45 | -------------------------------------------------------------------------------- /11.container-with-most-water.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=11 lang=ruby 4 | # 5 | # [11] Container With Most Water 6 | # 7 | # https://leetcode.com/problems/container-with-most-water/description/ 8 | # 9 | # Given n non-negative integers a1, a2, ..., an, where each 10 | # represents a point at coordinate (i, ai). n vertical lines are drawn 11 | # such that the two endpoints of line i is at (i, ai) and (i, 0). Find 12 | # two lines, which together with x-axis forms a container, such that 13 | # the container contains the most water. 14 | # 15 | # Note: You may not slant the container and n is at least 2. 16 | # 17 | # The above vertical lines are represented by array 18 | # [1,8,6,2,5,4,8,3,7]. In this case, the max area of water (blue 19 | # section) the container can contain is 49. 20 | # 21 | # Example: 22 | # 23 | # Input: [1,8,6,2,5,4,8,3,7] 24 | # Output: 49 25 | 26 | 27 | # Given i and j, it contains v = [h[i], h[j]].min * (j-i), so you can 28 | # see that in order to make v bigger, we need to change the smaller 29 | # one of h[i] and h[j], changing the bigger one doesn't help at all. 30 | 31 | # @param {Integer[]} height 32 | # @return {Integer} 33 | def max_area(height) 34 | i, j, max = 0, height.length-1, 0 35 | while i < j 36 | v = height.values_at(i,j).min * (j - i) 37 | max = [max, v].max 38 | if height[i] < height[j] 39 | i += 1 40 | else 41 | j -= 1 42 | end 43 | end 44 | max 45 | end 46 | -------------------------------------------------------------------------------- /111.minimum-depth-of-binary-tree.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=111 lang=ruby 4 | # 5 | # [111] Minimum Depth of Binary Tree 6 | # 7 | # https://leetcode.com/problems/minimum-depth-of-binary-tree/description/ 8 | # 9 | # Given a binary tree, find its minimum depth. 10 | # 11 | # The minimum depth is the number of nodes along the shortest path 12 | # from the root node down to the nearest leaf node. 13 | # 14 | # Note: A leaf is a node with no children. 15 | # 16 | # Example: 17 | # 18 | # Given binary tree [3,9,20,null,null,15,7], 19 | # 20 | # ⁠ 3 21 | # ⁠ / \ 22 | # ⁠ 9 20 23 | # ⁠ / \ 24 | # ⁠ 15 7 25 | # 26 | # return its minimum depth = 2. 27 | # 28 | # Definition for a binary tree node. 29 | # class TreeNode 30 | # attr_accessor :val, :left, :right 31 | # def initialize(val) 32 | # @val = val 33 | # @left, @right = nil, nil 34 | # end 35 | # end 36 | 37 | 38 | # See problem 110, it's the same idea. 39 | 40 | # @param {TreeNode} root 41 | # @return {Integer} 42 | def min_depth(root) 43 | return 0 if root.nil? 44 | return 1 + min_depth(root.left) if root.right.nil? 45 | return 1 + min_depth(root.right) if root.left.nil? 46 | 1 + [min_depth(root.left), min_depth(root.right)].min 47 | end 48 | -------------------------------------------------------------------------------- /112.path-sum.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=112 lang=ruby 4 | # 5 | # [112] Path Sum 6 | # 7 | # https://leetcode.com/problems/path-sum/description/ 8 | # 9 | # Given a binary tree and a sum, determine if the tree has a 10 | # root-to-leaf path such that adding up all the values along the path 11 | # equals the given sum. 12 | # 13 | # Note: A leaf is a node with no children. 14 | # 15 | # Example: 16 | # 17 | # Given the below binary tree and sum = 22, 18 | # 19 | # ⁠ 5 20 | # ⁠ / \ 21 | # ⁠ 4 8 22 | # ⁠ / / \ 23 | # ⁠ 11 13 4 24 | # ⁠/ \ \ 25 | # 7 2 1 26 | # 27 | # return true, as there exist a root-to-leaf path 5->4->11->2 which 28 | # sum is 22. 29 | # 30 | # Definition for a binary tree node. 31 | # class TreeNode 32 | # attr_accessor :val, :left, :right 33 | # def initialize(val) 34 | # @val = val 35 | # @left, @right = nil, nil 36 | # end 37 | # end 38 | 39 | 40 | # DFS... 41 | 42 | # @param {TreeNode} root 43 | # @param {Integer} sum 44 | # @return {Boolean} 45 | def has_path_sum(root, sum, x=0) 46 | return false if root.nil? 47 | x += root.val 48 | return true if root.left.nil? && root.right.nil? && x == sum 49 | has_path_sum(root.left, sum, x) || has_path_sum(root.right, sum, x) 50 | end 51 | -------------------------------------------------------------------------------- /113.path-sum-ii.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=113 lang=ruby 4 | # 5 | # [113] Path Sum II 6 | # 7 | # https://leetcode.com/problems/path-sum-ii/description/ 8 | # 9 | # Given a binary tree and a sum, find all root-to-leaf paths where 10 | # each path's sum equals the given sum. 11 | # 12 | # Note: A leaf is a node with no children. 13 | # 14 | # Example: 15 | # 16 | # Given the below binary tree and sum = 22, 17 | # 18 | # ⁠ 5 19 | # ⁠ / \ 20 | # ⁠ 4 8 21 | # ⁠ / / \ 22 | # ⁠ 11 13 4 23 | # ⁠/ \ / \ 24 | # 7 2 5 1 25 | # 26 | # Return: 27 | # 28 | # [ 29 | # ⁠ [5,4,11,2], 30 | # ⁠ [5,8,4,5] 31 | # ] 32 | # 33 | # Definition for a binary tree node. 34 | # class TreeNode 35 | # attr_accessor :val, :left, :right 36 | # def initialize(val) 37 | # @val = val 38 | # @left, @right = nil, nil 39 | # end 40 | # end 41 | 42 | 43 | # DFS+Backtracking... 44 | 45 | # @param {TreeNode} root 46 | # @param {Integer} sum 47 | # @return {Integer[][]} 48 | def path_sum(root, sum, x=0, path=[], paths=[]) 49 | return [] if root.nil? 50 | x += root.val 51 | path += [root.val] 52 | paths << path.dup if root.left.nil? && root.right.nil? && x == sum 53 | path_sum(root.left, sum, x, path, paths) 54 | path_sum(root.right, sum, x, path, paths) 55 | paths 56 | end 57 | -------------------------------------------------------------------------------- /116.populating-next-right-pointers-in-each-node.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=116 lang=ruby 4 | # 5 | # [116] Populating Next Right Pointers in Each Node 6 | # 7 | # https://leetcode.com/problems/populating-next-right-pointers-in-each-node/description/ 8 | # 9 | # You are given a perfect binary tree where all leaves are on the same 10 | # level, and every parent has two children. The binary tree has the 11 | # following definition: 12 | # 13 | # class TreeNode 14 | # attr_accessor :val, :left, :right, :next 15 | # def initialize(val) 16 | # @val = val 17 | # @left, @right = nil, nil, nil 18 | # end 19 | # end 20 | # 21 | # Populate each next pointer to point to its next right node. If there 22 | # is no next right node, the next pointer should be set to NULL. 23 | # 24 | # Initially, all next pointers are set to NULL. 25 | 26 | def connect(root) 27 | return if root.nil? 28 | if root.left 29 | root.left.next = root.right 30 | root.right.next = root.next.left if root.next 31 | end 32 | connect(root.left) 33 | connect(root.right) 34 | root 35 | end 36 | -------------------------------------------------------------------------------- /118.pascals-triangle.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=118 lang=ruby 4 | # 5 | # [118] Pascal's Triangle 6 | # 7 | # https://leetcode.com/problems/pascals-triangle/description/ 8 | # 9 | # Given a non-negative integer numRows, generate the first numRows of 10 | # Pascal's triangle. 11 | # 12 | # In Pascal's triangle, each number is the sum of the two numbers 13 | # directly above it. 14 | # 15 | # Example: 16 | # 17 | # Input: 5 18 | # Output: 19 | # [ 20 | # ⁠ [1], 21 | # ⁠ [1,1], 22 | # ⁠ [1,2,1], 23 | # ⁠ [1,3,3,1], 24 | # ⁠[1,4,6,4,1] 25 | # ] 26 | 27 | 28 | # Recursive. 29 | 30 | # @param {Integer} num_rows 31 | # @return {Integer[][]} 32 | def generate(num_rows, x=[[1]], k=1) 33 | return [] if num_rows.zero? 34 | return x if k == num_rows 35 | k += 1 36 | prev = x[-1] 37 | cur = (1..k-2).map { |i| prev[i-1]+prev[i] } 38 | cur.unshift 1 39 | cur << 1 40 | x << cur 41 | generate(num_rows, x, k) 42 | end 43 | 44 | 45 | # Iterative. 46 | 47 | def generate(num_rows) 48 | return [] if num_rows.zero? 49 | ans = [[1]] 50 | (1..num_rows-1).each do |i| 51 | prev = ans[-1] 52 | cur = (1..i-1).map { |i| prev[i-1]+prev[i] } 53 | cur.unshift 1 54 | cur << 1 55 | ans << cur 56 | end 57 | ans 58 | end 59 | -------------------------------------------------------------------------------- /119.pascals-triangle-ii.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=119 lang=ruby 4 | # 5 | # [119] Pascal's Triangle II 6 | # 7 | # https://leetcode.com/problems/pascals-triangle-ii/description/ 8 | # 9 | # Given a non-negative index k where k ≤ 33, return the kth index row 10 | # of the Pascal's triangle. 11 | # 12 | # Note that the row index starts from 0. 13 | # 14 | # In Pascal's triangle, each number is the sum of the two numbers 15 | # directly above it. 16 | # 17 | # Example: 18 | # 19 | # Input: 3 20 | # Output: [1,3,3,1] 21 | # 22 | # Follow up: 23 | # 24 | # Could you optimize your algorithm to use only O(k) extra space? 25 | 26 | 27 | # @param {Integer} row_index 28 | # @return {Integer[]} 29 | def get_row(row_index, x=[1], k=0) 30 | return x if k == row_index 31 | k += 1 32 | cur = (1..k-1).map { |i| x[i-1]+x[i] } 33 | cur.unshift 1 34 | cur << 1 35 | get_row(row_index, cur, k) 36 | end 37 | 38 | 39 | # O(k) space. 40 | 41 | def get_row(row_index) 42 | x = Array.new(row_index+1, 0).tap { |h| h[0] = 1 } 43 | (1..row_index).each do |i| 44 | i.downto(1).each do |j| 45 | x[j] += x[j-1] 46 | end 47 | end 48 | x 49 | end 50 | -------------------------------------------------------------------------------- /124.binary-tree-maximum-path-sum.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=124 lang=ruby 4 | # 5 | # [124] Binary Tree Maximum Path Sum 6 | # 7 | # https://leetcode.com/problems/binary-tree-maximum-path-sum/description/ 8 | # 9 | # Given a non-empty binary tree, find the maximum path sum. 10 | # 11 | # For this problem, a path is defined as any sequence of nodes from 12 | # some starting node to any node in the tree along the parent-child 13 | # connections. The path must contain at least one node and does not 14 | # need to go through the root. 15 | # 16 | # Example 1: 17 | # 18 | # Input: [1,2,3] 19 | # ⁠ 1 20 | # ⁠ / \ 21 | # ⁠ 2 3 22 | # Output: 6 23 | # 24 | # Example 2: 25 | # 26 | # Input: [-10,9,20,null,null,15,7] 27 | # -10 28 | # / \ 29 | # 9 20 30 | # / \ 31 | #15 7 32 | # 33 | # Output: 42 34 | # 35 | # Definition for a binary tree node. 36 | # class TreeNode 37 | # attr_accessor :val, :left, :right 38 | # def initialize(val) 39 | # @val = val 40 | # @left, @right = nil, nil 41 | # end 42 | # end 43 | 44 | 45 | # @param {TreeNode} root 46 | # @return {Integer} 47 | def max_path_sum(root) 48 | [-Float::INFINITY].tap { |ans| helper(root, ans) }[0] 49 | end 50 | 51 | def helper(root, ans) 52 | return 0 if root.nil? 53 | l = [helper(root.left, ans), 0].max 54 | r = [helper(root.right, ans), 0].max 55 | ans[0] = [ans[0], root.val+l+r].max 56 | [root.val+l, root.val+r].max 57 | end 58 | -------------------------------------------------------------------------------- /125.valid-palindrome.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=125 lang=ruby 4 | # 5 | # [125] Valid Palindrome 6 | # 7 | # https://leetcode.com/problems/valid-palindrome/description/ 8 | # 9 | # Given a string, determine if it is a palindrome, considering only 10 | # alphanumeric characters and ignoring cases. 11 | # 12 | # Note: For the purpose of this problem, we define empty string as 13 | # valid palindrome. 14 | # 15 | # Example 1: 16 | # 17 | # Input: "A man, a plan, a canal: Panama" 18 | # Output: true 19 | # 20 | # Example 2: 21 | # 22 | # Input: "race a car" 23 | # Output: false 24 | 25 | 26 | # @param {String} s 27 | # @return {Boolean} 28 | def is_palindrome(s) 29 | pl?(s.downcase.gsub(/[^a-z0-9]+/, "")) 30 | end 31 | 32 | def pl?(s) 33 | i, j = 0, s.size-1 34 | while i < j 35 | return false if s[i] != s[j] 36 | i += 1 37 | j -= 1 38 | end 39 | true 40 | end 41 | -------------------------------------------------------------------------------- /131.palindrome-partitioning.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=131 lang=ruby 4 | # 5 | # [131] Palindrome Partitioning 6 | # 7 | # https://leetcode.com/problems/palindrome-partitioning/description/ 8 | # 9 | # Given a string s, partition s such that every substring of the 10 | # partition is a palindrome. 11 | # 12 | # Return all possible palindrome partitioning of s. 13 | # 14 | # Example: 15 | # 16 | # Input: "aab" 17 | # Output: 18 | # [ 19 | # ⁠ ["aa","b"], 20 | # ⁠ ["a","a","b"] 21 | # ] 22 | 23 | 24 | # DFS. 25 | 26 | # @param {String} s 27 | # @return {String[][]} 28 | def partition(s) 29 | dfs(s, 0) 30 | end 31 | 32 | def dfs(s, k, path=[], paths=[]) 33 | return if k > s.size 34 | if k == s.size 35 | paths << path.dup 36 | else 37 | (k..s.size-1).each do |i| 38 | next if !pl?(s[k..i]) 39 | path << s[k..i] 40 | dfs(s, i+1, path, paths) 41 | path.pop 42 | end 43 | end 44 | paths 45 | end 46 | 47 | def pl?(s) 48 | i, j = 0, s.size-1 49 | while i < j 50 | return false if s[i] != s[j] 51 | i += 1 52 | j -= 1 53 | end 54 | true 55 | end 56 | 57 | 58 | # Recursive. 59 | 60 | def partition(s, k=0) 61 | return [[]] if k == s.size 62 | (k..s.size-1).flat_map do |i| 63 | pl?(s[k..i]) ? partition(s, i+1).map { |r| [s[k..i]]+r } : [] 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /136.single-number.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=136 lang=ruby 4 | # 5 | # [136] Single Number 6 | # 7 | # https://leetcode.com/problems/single-number/description/ 8 | # 9 | # Given a non-empty array of integers, every element appears twice 10 | # except for one. Find that single one. 11 | # 12 | # Note: 13 | # 14 | # Your algorithm should have a linear runtime complexity. Could you 15 | # implement it without using extra memory? 16 | # 17 | # Example 1: 18 | # 19 | # Input: [2,2,1] 20 | # Output: 1 21 | # 22 | # Example 2: 23 | # 24 | # Input: [4,1,2,1,2] 25 | # Output: 4 26 | 27 | 28 | # @param {Integer[]} nums 29 | # @return {Integer} 30 | def single_number_a(nums) 31 | s = Set.new 32 | nums.each do |n| 33 | if s.include?(n) 34 | s.delete(n) 35 | else 36 | s << n 37 | end 38 | end 39 | s.first 40 | end 41 | 42 | 43 | # The second method is brilliant, it uses the XOR operator(^). 44 | # 45 | # 1. a ^ 0 = 0 ^ a = a 46 | # 2. a ^ a = 0 47 | # 3. a ^ b ^ a = a ^ a ^ b = 0 ^ b = b 48 | # 49 | # So just reduce the list by XOR. 50 | 51 | def single_number(nums) 52 | nums.reduce(&:^) 53 | end 54 | -------------------------------------------------------------------------------- /138.copy-list-with-random-pointer.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=138 lang=ruby 4 | # 5 | # [138] Copy List with Random Pointer 6 | # 7 | # https://leetcode.com/problems/copy-list-with-random-pointer/description/ 8 | # 9 | # A linked list is given such that each node contains an additional 10 | # random pointer which could point to any node in the list or null. 11 | # 12 | # Return a deep copy of the list. 13 | # 14 | # Definition for singly-linked list. 15 | # class Node 16 | # attr_accessor :val, :next, :random 17 | # def initialize(val) 18 | # @val = val 19 | # @next, @random = nil, nil 20 | # end 21 | # end 22 | 23 | 24 | # O(n) space using Hash. 25 | 26 | def copy_random_list(head) 27 | return if head.nil? 28 | cur, h = head, {} 29 | while cur 30 | h[cur] = Node.new(cur.val) 31 | cur = cur.next 32 | end 33 | cur = head 34 | while cur 35 | h[cur].random = h[cur.random] if cur.random 36 | h[cur].next = h[cur.next] if cur.next 37 | cur = cur.next 38 | end 39 | h[head] 40 | end 41 | -------------------------------------------------------------------------------- /14.longest-common-prefix.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=14 lang=ruby 4 | # 5 | # [14] Longest Common Prefix 6 | # 7 | # https://leetcode.com/problems/longest-common-prefix/description/ 8 | # 9 | # Write a function to find the longest common prefix string amongst an 10 | # array of strings. 11 | # 12 | # If there is no common prefix, return an empty string "". 13 | # 14 | # Example 1: 15 | # 16 | # Input: ["flower","flow","flight"] 17 | # Output: "fl" 18 | # 19 | # Example 2: 20 | # 21 | # Input: ["dog","racecar","car"] 22 | # Output: "" 23 | # Explanation: There is no common prefix among the input strings. 24 | # 25 | # Note: 26 | # 27 | # All given inputs are in lowercase letters a-z. 28 | 29 | 30 | # Reduce: (lcp(lcp(lcp(s1, s2), s3), s4)... 31 | 32 | # @param {String[]} strs 33 | # @return {String} 34 | def longest_common_prefix(strs) 35 | f, *strs = strs 36 | strs.reduce(f) do |r, s| 37 | return "" if r == "" 38 | j = 0 39 | m = [r.size, s.size].min 40 | j += 1 while j < m && r[j] == s[j] 41 | j == 0 ? "" : s[0..j-1] 42 | end 43 | end 44 | 45 | 46 | # Divide and Conquer. 47 | 48 | def longest_common_prefix(strs, lo=0, hi=strs.size-1) 49 | return "" if strs.empty? 50 | return strs[lo] if lo == hi 51 | m = (lo+hi)/2 52 | lcp(longest_common_prefix(strs, lo, m), longest_common_prefix(strs, m+1, hi)) 53 | end 54 | 55 | def lcp(s1, s2) 56 | m = [s1.size, s2.size].min 57 | j = 0 58 | j += 1 while j < m && s1[j] == s2[j] 59 | j == 0 ? "" : s[0..j-1] 60 | end 61 | -------------------------------------------------------------------------------- /141.linked-list-cycle.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=141 lang=ruby 4 | # 5 | # [141] Linked List Cycle 6 | # 7 | # https://leetcode.com/problems/linked-list-cycle/description/ 8 | # 9 | # Given a linked list, determine if it has a cycle in it. 10 | # 11 | # Definition for singly-linked list. 12 | # class ListNode 13 | # attr_accessor :val, :next 14 | # def initialize(val) 15 | # @val = val 16 | # @next = nil 17 | # end 18 | # end 19 | 20 | def hasCycle(head) 21 | return false if head.nil? || head.next.nil? 22 | slow, fast = head, head.next 23 | while !fast.nil? && !fast.next.nil? 24 | return true if fast == slow 25 | slow, fast = slow.next, fast.next.next 26 | end 27 | false 28 | end 29 | -------------------------------------------------------------------------------- /144.binary-tree-preorder-traversal.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=144 lang=ruby 4 | # 5 | # [144] Binary Tree Preorder Traversal 6 | # 7 | # https://leetcode.com/problems/binary-tree-preorder-traversal/description/ 8 | # 9 | # Given a binary tree, return the preorder traversal of its nodes' values. 10 | # 11 | # Example: 12 | # 13 | # Input: [1,null,2,3] 14 | # ⁠ 1 15 | # ⁠ \ 16 | # ⁠ 2 17 | # ⁠ / 18 | # ⁠ 3 19 | # Output: [1,2,3] 20 | # 21 | # Follow up: Recursive solution is trivial, could you do it iteratively? 22 | # 23 | # Definition for a binary tree node. 24 | # class TreeNode 25 | # attr_accessor :val, :left, :right 26 | # def initialize(val) 27 | # @val = val 28 | # @left, @right = nil, nil 29 | # end 30 | # end 31 | 32 | 33 | # Recursive. 34 | 35 | # @param {TreeNode} root 36 | # @return {Integer[]} 37 | def preorder_traversal(root, ans=[]) 38 | return [] if root.nil? 39 | ans << root.val 40 | preorder_traversal(root.left, ans) 41 | preorder_traversal(root.right, ans) 42 | ans 43 | end 44 | 45 | 46 | # Iterative. 47 | 48 | def preorder_traversal_a(root) 49 | return [] if root.nil? 50 | stack, ans = [root], [] 51 | while !stack.empty? 52 | x = stack.pop 53 | ans << x.val 54 | stack << x.right if !x.right.nil? 55 | stack << x.left if !x.left.nil? 56 | end 57 | ans 58 | end 59 | -------------------------------------------------------------------------------- /148.sort-list.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=148 lang=ruby 4 | # 5 | # [148] Sort List 6 | # 7 | # https://leetcode.com/problems/sort-list/description/ 8 | # 9 | # Sort a linked list in O(n log n) time using constant space complexity. 10 | # 11 | # Example 1: 12 | # 13 | # Input: 4->2->1->3 14 | # Output: 1->2->3->4 15 | # 16 | # Example 2: 17 | # 18 | # Input: -1->5->3->4->0 19 | # Output: -1->0->3->4->5 20 | # 21 | # Definition for singly-linked list. 22 | # class ListNode 23 | # attr_accessor :val, :next 24 | # def initialize(val) 25 | # @val = val 26 | # @next = nil 27 | # end 28 | # end 29 | 30 | 31 | # Recursive. 32 | 33 | # @param {ListNode} head 34 | # @return {ListNode} 35 | def sort_list(head) 36 | return head if head.nil? || head.next.nil? 37 | l1, l2 = split_list(head) 38 | merge_two_lists(sort_list(l1), sort_list(l2)) 39 | end 40 | 41 | def split_list(head) 42 | slow, fast = head, head.next 43 | while !fast.nil? && !fast.next.nil? 44 | slow, fast = slow.next, fast.next.next 45 | end 46 | m, slow.next = slow.next, nil 47 | [head, m] 48 | end 49 | 50 | def merge_two_lists(l1, l2) 51 | return l1 if l2.nil? 52 | return l2 if l1.nil? 53 | if l1 < l2 54 | l1.next = merge_two_lists(l1.next, l2) 55 | l1 56 | else 57 | l2.next = merge_two_lists(l1, l2.next) 58 | l2 59 | end 60 | end 61 | 62 | 63 | # TODO 64 | # O(1) space. 65 | -------------------------------------------------------------------------------- /150.evaluate-reverse-polish-notation.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=150 lang=ruby 4 | # 5 | # [150] Evaluate Reverse Polish Notation 6 | # 7 | # https://leetcode.com/problems/evaluate-reverse-polish-notation/description/ 8 | # 9 | # Evaluate the value of an arithmetic expression in Reverse Polish Notation. 10 | # 11 | # Valid operators are +, -, *, /. Each operand may be an integer or 12 | # another expression. 13 | # 14 | # Note: 15 | # 16 | # Division between two integers should truncate toward zero. The given 17 | # RPN expression is always valid. That means the expression would 18 | # always evaluate to a result and there won't be any divide by zero 19 | # operation. 20 | # 21 | # Example 1: 22 | # 23 | # Input: ["2", "1", "+", "3", "*"] 24 | # Output: 9 25 | # Explanation: ((2 + 1) * 3) = 9 26 | # 27 | # Example 2: 28 | # 29 | # Input: ["4", "13", "5", "/", "+"] 30 | # Output: 6 31 | # Explanation: (4 + (13 / 5)) = 6 32 | # 33 | # Example 3: 34 | # 35 | # Input: ["10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"] 36 | # Output: 22 37 | # Explanation: 38 | # ⁠ ((10 * (6 / ((9 + 3) * -11))) + 17) + 5 39 | # = ((10 * (6 / (12 * -11))) + 17) + 5 40 | # = ((10 * (6 / -132)) + 17) + 5 41 | # = ((10 * 0) + 17) + 5 42 | # = (0 + 17) + 5 43 | # = 17 + 5 44 | # = 22 45 | 46 | 47 | # Stack. 48 | 49 | # @param {String[]} tokens 50 | # @return {Integer} 51 | def eval_rpn(tokens) 52 | q = [] 53 | ops = Set['+', '-', '*', '/'] 54 | tokens.each do |t| 55 | if ops.include?(t) 56 | r = q.pop 57 | l = q.pop 58 | a = l.send(t, r) 59 | q << t == '/' ? a.truncate : a 60 | else 61 | q << t.to_f 62 | end 63 | end 64 | q[0] 65 | end 66 | -------------------------------------------------------------------------------- /151.reverse-words-in-a-string.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=151 lang=ruby 4 | # 5 | # [151] Reverse Words in a String 6 | # 7 | # https://leetcode.com/problems/reverse-words-in-a-string/description/ 8 | # 9 | # Given an input string, reverse the string word by word. 10 | # 11 | # Example 1: 12 | # 13 | # Input: "the sky is blue" 14 | # Output: "blue is sky the" 15 | # 16 | # Example 2: 17 | # 18 | # 19 | # Input: " hello world! " 20 | # Output: "world! hello" 21 | # Explanation: Your reversed string should not contain leading or 22 | # trailing spaces. 23 | # 24 | # Example 3: 25 | # 26 | # Input: "a good example" 27 | # Output: "example good a" 28 | # Explanation: You need to reduce multiple spaces between two words to 29 | # a single space in the reversed string. 30 | # 31 | # Note: 32 | # 33 | # A word is defined as a sequence of non-space characters. Input 34 | # string may contain leading or trailing spaces. However, your 35 | # reversed string should not contain leading or trailing spaces. You 36 | # need to reduce multiple spaces between two words to a single space 37 | # in the reversed string. 38 | 39 | 40 | # @param {String} s 41 | # @return {String} 42 | def reverse_words(s) 43 | s.split.reverse.join(' ') 44 | end 45 | -------------------------------------------------------------------------------- /152.maximum-product-subarray.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=152 lang=ruby 4 | # 5 | # [152] Maximum Product Subarray 6 | # 7 | # https://leetcode.com/problems/maximum-product-subarray/description/ 8 | # 9 | # Given an integer array nums, find the contiguous subarray within an array 10 | # (containing at least one number) which has the largest product. 11 | # 12 | # Example 1: 13 | # 14 | # Input: [2,3,-2,4] 15 | # Output: 6 16 | # Explanation: [2,3] has the largest product 6. 17 | # 18 | # Example 2: 19 | # 20 | # Input: [-2,0,-1] 21 | # Output: 0 22 | # Explanation: The result cannot be 2, because [-2,-1] is not a subarray. 23 | 24 | 25 | # DP. 26 | 27 | # @param {Integer[]} nums 28 | # @return {Integer} 29 | def max_product(nums) 30 | n, ans = nums.size, -Float::INFINITY 31 | d = Array.new(n+1).tap { |d| d[n] = [1, 1] } 32 | (n-1).downto(0).each do |i| 33 | min, max = (d[i+1].map { |s| s * nums[i] } + [nums[i]]).minmax 34 | if max < 0 35 | d[i] = [min, min] 36 | elsif min > 0 37 | d[i] = [max, max] 38 | else 39 | d[i] = [min, max] 40 | end 41 | ans = [ans, d[i][1]].max 42 | end 43 | ans 44 | end 45 | -------------------------------------------------------------------------------- /155.min-stack.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=155 lang=ruby 4 | # 5 | # [155] Min Stack 6 | # 7 | # https://leetcode.com/problems/min-stack/description/ 8 | # 9 | # Design a stack that supports push, pop, top, and retrieving the 10 | # minimum element in constant time. 11 | # 12 | # push(x) -- Push element x onto stack. 13 | # pop() -- Removes the element on top of the stack. 14 | # top() -- Get the top element. 15 | # getMin() -- Retrieve the minimum element in the stack. 16 | # 17 | # Example: 18 | # 19 | # MinStack minStack = new MinStack(); 20 | # minStack.push(-2); 21 | # minStack.push(0); 22 | # minStack.push(-3); 23 | # minStack.getMin(); --> Returns -3. 24 | # minStack.pop(); 25 | # minStack.top(); --> Returns 0. 26 | # minStack.getMin(); --> Returns -2. 27 | 28 | 29 | # Stack: [[num, current_min]]. 30 | 31 | class MinStack 32 | 33 | def initialize 34 | @h = [] 35 | end 36 | 37 | def push(x) 38 | if @h.empty? 39 | @h << [x, x] 40 | else 41 | @h << [x, [@h[-1][1], x].min] 42 | end 43 | end 44 | 45 | def pop 46 | @h.pop 47 | end 48 | 49 | def top 50 | @h[-1][0] 51 | end 52 | 53 | def get_min 54 | @h[-1][1] 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /157.read-n-characters-given-read4.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=157 lang=ruby 4 | # 5 | # [157] Read N Characters Given Read4 6 | # 7 | # https://leetcode.com/problems/read-n-characters-given-read4/description/ 8 | # 9 | # The API: int read4(char *buf) reads 4 characters at a time from a file. 10 | # 11 | # The return value is the actual number of characters read. For 12 | # example, it returns 3 if there is only 3 characters left in the file. 13 | # 14 | # By using the read4 API, implement the function int read(char *buf, int n) 15 | # that reads n characters from the file. 16 | # 17 | # Note: The read function will only be called once for each test case. 18 | 19 | 20 | def read(buf, n) 21 | x, eof, count = [], false, 0 22 | while n > 0 && !eof 23 | c = read4(x) 24 | eof = true if c < 4 25 | x[0..c].each do |i| 26 | buf << i 27 | count += 1 28 | break if count == n 29 | end 30 | end 31 | count 32 | end 33 | -------------------------------------------------------------------------------- /16.3sum-closest.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=16 lang=ruby 4 | # 5 | # [16] 3Sum Closest 6 | # 7 | # https://leetcode.com/problems/3sum-closest/description/ 8 | # 9 | # Given an array nums of n integers and an integer target, find three 10 | # integers in nums such that the sum is closest to target. Return the 11 | # sum of the three integers. You may assume that each input would have 12 | # exactly one solution. 13 | # 14 | # Example: 15 | # 16 | # Given array nums = [-1, 2, 1, -4], and target = 1. 17 | # 18 | # The sum that is closest to the target is 2. (-1 + 2 + 1 = 2). 19 | 20 | 21 | # See problem 15. 22 | 23 | # @param {Integer[]} nums 24 | # @param {Integer} target 25 | # @return {Integer} 26 | def three_sum_closest(nums, target) 27 | nums.sort! 28 | n, min = nums.size, Float::INFINITY 29 | (0...n).each do |i| 30 | j = i+1 31 | k = n-1 32 | while j < k 33 | diff = nums[i] + nums[j] + nums[k] - target 34 | if diff < 0 35 | j += 1 36 | elsif diff > 0 37 | k -= 1 38 | else 39 | return diff + target 40 | end 41 | min = diff if diff.abs < min.abs 42 | end 43 | end 44 | min + target 45 | end 46 | -------------------------------------------------------------------------------- /160.intersection-of-two-linked-lists.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=160 lang=ruby 4 | # 5 | # [160] Intersection of Two Linked Lists 6 | # 7 | # https://leetcode.com/problems/intersection-of-two-linked-lists/description/ 8 | # 9 | # Write a program to find the node at which the intersection of two 10 | # singly linked lists begins. 11 | # 12 | # Definition for singly-linked list. 13 | # class ListNode 14 | # attr_accessor :val, :next 15 | # def initialize(val) 16 | # @val = val 17 | # @next = nil 18 | # end 19 | # end 20 | 21 | 22 | # O(m+n) space. 23 | def get_intersection_node(headA, headB) 24 | h = Set.new 25 | while !headA.nil? 26 | h << headA 27 | headA = headA.next 28 | end 29 | while !headB.nil? 30 | return headB if h.include?(headB) 31 | headB = headB.next 32 | end 33 | end 34 | 35 | 36 | # O(1) space. 37 | 38 | def get_intersection_node(headA, headB) 39 | return if headA.nil? || headB.nil? 40 | a, b= headA, headB 41 | while a != b 42 | a = a.next 43 | b = b.next 44 | return if a.nil? && b.nil? 45 | a = headB if a.nil? 46 | b = headA if b.nil? 47 | end 48 | a 49 | end 50 | -------------------------------------------------------------------------------- /162.find-peak-element.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=162 lang=ruby 4 | # 5 | # [162] Find Peak Element 6 | # 7 | # https://leetcode.com/problems/find-peak-element/description/ 8 | # 9 | # A peak element is an element that is greater than its neighbors. 10 | # 11 | # Given an input array nums, where nums[i] ≠ nums[i+1], find a peak 12 | # element and return its index. 13 | # 14 | # The array may contain multiple peaks, in that case return the index 15 | # to any one of the peaks is fine. 16 | # 17 | # You may imagine that nums[-1] = nums[n] = -∞. 18 | # 19 | # Example 1: 20 | # 21 | # Input: nums = [1,2,3,1] 22 | # Output: 2 23 | # Explanation: 3 is a peak element and your function should return the 24 | # index number 2. 25 | # 26 | # Example 2: 27 | # 28 | # Input: nums = [1,2,1,3,5,6,4] 29 | # Output: 1 or 5 30 | # Explanation: Your function can return either index number 1 where 31 | # the peak element is 2, or index number 5 where the peak element is 6. 32 | # 33 | # Note: Your solution should be in logarithmic complexity. 34 | 35 | 36 | # See https://courses.csail.mit.edu/6.006/spring11/lectures/lec02.pdf 37 | 38 | # @param {Integer[]} nums 39 | # @return {Integer} 40 | def find_peak_element(nums, lo=0, hi=nums.size-1) 41 | m = (lo + hi) / 2 42 | if m > 0 && nums[m] < nums[m-1] 43 | find_peak_element(nums, lo, m-1) 44 | elsif m < nums.size-1 && nums[m] < nums[m+1] 45 | find_peak_element(nums, m+1, hi) 46 | else 47 | m 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /163.missing-ranges.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=163 lang=ruby 4 | # 5 | # [163] Missing Ranges 6 | # 7 | # https://leetcode.com/problems/missing-ranges/description/ 8 | # 9 | # Given a sorted integer array where the range of elements are in the 10 | # inclusive range [lower, upper], return its missing ranges. 11 | # 12 | # For example, given [0, 1, 3, 50, 75], lower = 0 and upper = 99, 13 | # return ["2", "4->49", "51->74", "76->99"]. 14 | 15 | def find_missing_ranges(nums, lower, upper) 16 | return [] if nums.empty? || upper < nums[0] || lower > nums[-1] 17 | ans = [] 18 | nums.each_with_index do |n, i| 19 | break if n > upper 20 | if lower < n 21 | ans << range_str(lower, [n-1, upper].min) 22 | lower = nums[i]+1 23 | elsif lower == n 24 | lower += 1 25 | end 26 | end 27 | ans << range_str(lower, upper) if lower <= upper 28 | ans 29 | end 30 | 31 | def range_str(a, b) 32 | a == b ? a.to_s : "#{a}->#{b}" 33 | end 34 | -------------------------------------------------------------------------------- /166.fraction-to-recurring-decimal.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=166 lang=ruby 4 | # 5 | # [166] Fraction to Recurring Decimal 6 | # 7 | # https://leetcode.com/problems/fraction-to-recurring-decimal/description/ 8 | # 9 | # Given two integers representing the numerator and denominator of a 10 | # fraction, return the fraction in string format. 11 | # 12 | # If the fractional part is repeating, enclose the repeating part in 13 | # parentheses. 14 | # 15 | # Example 1: 16 | # 17 | # Input: numerator = 1, denominator = 2 18 | # Output: "0.5" 19 | # 20 | # Example 2: 21 | # 22 | # Input: numerator = 2, denominator = 1 23 | # Output: "2" 24 | # 25 | # Example 3: 26 | # 27 | # Input: numerator = 2, denominator = 3 28 | # Output: "0.(6)" 29 | 30 | 31 | # 0. Determine the sign. 32 | # 1. n is divisible by d, return sign+"n/d" 33 | # 2. Otherwise do division till we meet a known remainder. 34 | 35 | # @param {Integer} numerator 36 | # @param {Integer} denominator 37 | # @return {String} 38 | def fraction_to_decimal(n, d) 39 | return "0" if n.zero? 40 | ans = (n<0) ^ (d<0) ? "-" : "" 41 | n, d = n.abs, d.abs 42 | a, b = n.divmod(d) 43 | return "#{ans}#{a}" if b.zero? 44 | ans << "#{a}." 45 | h = {} 46 | while !b.zero? 47 | if h.has_key?(b) 48 | ans.insert(h[b], "(") 49 | ans << ")" 50 | break 51 | end 52 | h[b] = ans.size 53 | a, b = (b*10).divmod(d) 54 | ans << a.to_s 55 | end 56 | ans 57 | end 58 | -------------------------------------------------------------------------------- /167.two-sum-ii-input-array-is-sorted.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=167 lang=ruby 4 | # 5 | # [167] Two Sum II - Input array is sorted 6 | # 7 | # https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/description/ 8 | # 9 | # Given an array of integers that is already sorted in ascending 10 | # order, find two numbers such that they add up to a specific target 11 | # number. 12 | # 13 | # The function twoSum should return indices of the two numbers such 14 | # that they add up to the target, where index1 must be less than 15 | # index2. 16 | # 17 | # Note: 18 | # 19 | # Your returned answers (both index1 and index2) are not zero-based. 20 | # You may assume that each input would have exactly one solution and 21 | # you may not use the same element twice. 22 | # 23 | # Example: 24 | # 25 | # Input: numbers = [2,7,11,15], target = 9 26 | # Output: [1,2] 27 | # Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2. 28 | 29 | 30 | # @param {Integer[]} numbers 31 | # @param {Integer} target 32 | # @return {Integer[]} 33 | def two_sum(numbers, target) 34 | i, j = 0, numbers.size-1 35 | while i < j 36 | sum = numbers[i] + numbers[j] 37 | cmp = sum <=> target 38 | case cmp 39 | when 1 40 | j -= 1 41 | when -1 42 | i += 1 43 | else 44 | return [i+1, j+1] 45 | end 46 | end 47 | end 48 | -------------------------------------------------------------------------------- /169.majority-element.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=169 lang=ruby 4 | # 5 | # [169] Majority Element 6 | # 7 | # https://leetcode.com/problems/majority-element/description/ 8 | # 9 | # Given an array of size n, find the majority element. The majority 10 | # element is the element that appears more than ⌊ n/2 ⌋ times. 11 | # 12 | # You may assume that the array is non-empty and the majority element 13 | # always exist in the array. 14 | # 15 | # Example 1: 16 | # 17 | # Input: [3,2,3] 18 | # Output: 3 19 | # 20 | # Example 2: 21 | # 22 | # Input: [2,2,1,1,1,2,2] 23 | # Output: 2 24 | 25 | 26 | # Using Hash. 27 | 28 | # @param {Integer[]} nums 29 | # @return {Integer} 30 | def majority_element_a(nums) 31 | freq, max_f, max_n = Hash.new(0), 0 32 | nums.each do |n| 33 | freq[n] += 1 34 | max_f, max_n = freq[n], n if freq[n] > max_f 35 | end 36 | max_n 37 | end 38 | 39 | 40 | # Using Boyer-Moore majority vote algorithm, see: 41 | # 42 | # https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_majority_vote_algorithm 43 | # 44 | # However even when the input sequence has no majority, the algorithm 45 | # will report one of the sequence elements as its result, but that's 46 | # not a problem since this problem guarantee to have one. 47 | 48 | def majority_element(nums) 49 | i, m = 0 50 | nums.each do |x| 51 | if i == 0 52 | m = x 53 | i = 1 54 | elsif m == x 55 | i += 1 56 | else 57 | i -= 1 58 | end 59 | end 60 | m 61 | end 62 | -------------------------------------------------------------------------------- /17.letter-combinations-of-a-phone-number.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=17 lang=ruby 4 | # 5 | # [17] Letter Combinations of a Phone Number 6 | # 7 | # https://leetcode.com/problems/letter-combinations-of-a-phone-number/description/ 8 | # 9 | # Given a string containing digits from 2-9 inclusive, return all 10 | # possible letter combinations that the number could represent. 11 | # 12 | # A mapping of digit to letters (just like on the telephone buttons) 13 | # is given below. Note that 1 does not map to any letters. 14 | # 15 | # Example: 16 | # 17 | # Input: "23" 18 | # Output: ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. 19 | # 20 | # Note: 21 | # 22 | # Although the above answer is in lexicographical order, your answer 23 | # could be in any order you want. 24 | 25 | 26 | # DFS. 27 | 28 | # @param {String} digits 29 | # @return {String[]} 30 | def letter_combinations(digits) 31 | map = { "2" => ["a", "b", "c"], 32 | "3" => ["d", "e", "f"], 33 | "4" => ["g", "h", "i"], 34 | "5" => ["j", "k", "l"], 35 | "6" => ["m", "n", "o"], 36 | "7" => ["p", "q", "r", "s"], 37 | "8" => ["t", "u", "v"], 38 | "9" => ["w", "x", "y", "z"] } 39 | dfs(digits, map) 40 | end 41 | 42 | def dfs(digits, map, k=0, path="", paths=[]) 43 | if k == digits.size 44 | paths << path.dup 45 | else 46 | map[digits[k]].each do |c| 47 | dfs(digits, map, k+1, path+c, paths) 48 | end 49 | end 50 | paths 51 | end 52 | -------------------------------------------------------------------------------- /171.excel-sheet-column-number.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=171 lang=ruby 4 | # 5 | # [171] Excel Sheet Column Number 6 | # 7 | # https://leetcode.com/problems/excel-sheet-column-number/description/ 8 | # 9 | # Given a column title as appear in an Excel sheet, return its 10 | # corresponding column number. 11 | # 12 | # For example: 13 | # 14 | # ⁠ A -> 1 15 | # ⁠ B -> 2 16 | # ⁠ C -> 3 17 | # ⁠ ... 18 | # ⁠ Z -> 26 19 | # ⁠ AA -> 27 20 | # ⁠ AB -> 28 21 | # ⁠ ... 22 | # 23 | # Example 1: 24 | # 25 | # Input: "A" 26 | # Output: 1 27 | # 28 | # Example 2: 29 | # 30 | # Input: "AB" 31 | # Output: 28 32 | # 33 | # Example 3: 34 | # 35 | # Input: "ZY" 36 | # Output: 701 37 | 38 | 39 | # @param {String} s 40 | # @return {Integer} 41 | def title_to_number(s) 42 | sum = 0 43 | s.each_char do |c| 44 | o = c.ord-64 45 | sum = 26 * sum + o 46 | end 47 | sum 48 | end 49 | -------------------------------------------------------------------------------- /172.factorial-trailing-zeroes.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=172 lang=ruby 4 | # 5 | # [172] Factorial Trailing Zeroes 6 | # 7 | # https://leetcode.com/problems/factorial-trailing-zeroes/description/ 8 | # 9 | # Given an integer n, return the number of trailing zeroes in n!. 10 | # 11 | # Example 1: 12 | # 13 | # Input: 3 14 | # Output: 0 15 | # Explanation: 3! = 6, no trailing zero. 16 | # 17 | # Example 2: 18 | # 19 | # Input: 5 20 | # Output: 1 21 | # Explanation: 5! = 120, one trailing zero. 22 | # 23 | # Note: Your solution should be in logarithmic time complexity. 24 | 25 | 26 | # trailing zeroes come from 2*5=10,2*5*5,... 27 | # Count the number of 5,5*5,... 28 | 29 | # @param {Integer} n 30 | # @return {Integer} 31 | def trailing_zeroes(n) 32 | i, ans = 5, 0 33 | while n/i > 0 34 | ans += n/i 35 | i *= 5 36 | end 37 | ans 38 | end 39 | -------------------------------------------------------------------------------- /186.reverse-words-in-a-string-ii.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=186 lang=ruby 4 | # 5 | # [186] Reverse Words in a String II 6 | # 7 | # https://leetcode.com/problems/reverse-words-in-a-string-ii/description/ 8 | # 9 | # Given an input string, reverse the string word by word. A word is 10 | # defined as a sequence of non-space characters. The input string does 11 | # not contain leading or trailing spaces and the words are always 12 | # separated by a single space. 13 | # 14 | # For example, 15 | # Given s = "the sky is blue", 16 | # return "blue is sky the". 17 | # 18 | # Could you do it in-place without allocating extra space? 19 | 20 | 21 | # See problem 189. 22 | 23 | # 1. Reverse the whole string. 24 | # 2. Reverse each word. 25 | 26 | def reverse_words(s) 27 | s.reverse! 28 | i = 0 29 | while i < s.size 30 | if s[i] == ' ' 31 | i += 1 32 | else 33 | j = i 34 | i += 1 while i < s.size && s[i] != ' ' 35 | reverse(s, j, i-1) 36 | end 37 | end 38 | s 39 | end 40 | 41 | def swap(nums, i, j) 42 | nums[i], nums[j] = nums[j], nums[i] 43 | end 44 | 45 | def reverse(nums, i, j) 46 | until i > j 47 | swap(nums, i, j) 48 | i += 1 49 | j -= 1 50 | end 51 | end 52 | -------------------------------------------------------------------------------- /189.rotate-array.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=189 lang=ruby 4 | # 5 | # [189] Rotate Array 6 | # 7 | # https://leetcode.com/problems/rotate-array/description/ 8 | # 9 | # Given an array, rotate the array to the right by k steps, where k is 10 | # non-negative. 11 | # 12 | # Example 1: 13 | # 14 | # Input: [1,2,3,4,5,6,7] and k = 3 15 | # Output: [5,6,7,1,2,3,4] 16 | # Explanation: 17 | # rotate 1 steps to the right: [7,1,2,3,4,5,6] 18 | # rotate 2 steps to the right: [6,7,1,2,3,4,5] 19 | # rotate 3 steps to the right: [5,6,7,1,2,3,4] 20 | # 21 | # Example 2: 22 | # 23 | # Input: [-1,-100,3,99] and k = 2 24 | # Output: [3,99,-1,-100] 25 | # Explanation: 26 | # rotate 1 steps to the right: [99,-1,-100,3] 27 | # rotate 2 steps to the right: [3,99,-1,-100] 28 | # 29 | # Note: 30 | # 31 | # Try to come up as many solutions as you can, there are at least 3 different 32 | # ways to solve this problem. 33 | # Could you do it in-place with O(1) extra space? 34 | 35 | 36 | # @param {Integer[]} nums 37 | # @param {Integer} k 38 | # @return {Void} Do not return anything, modify nums in-place instead. 39 | def rotate_a(nums, k) 40 | nums.rotate!(k) 41 | end 42 | 43 | 44 | def rotate_b(nums, k) 45 | x, n = nums.dup, nums.size 46 | (0..n-1).each do |i| 47 | nums[(i+k)%n] = x[i] 48 | end 49 | end 50 | 51 | 52 | def rotate(nums, k) 53 | k %= nums.length 54 | reverse(nums, 0, nums.size-1) 55 | reverse(nums, 0, k-1) 56 | reverse(nums, k, nums.size-1) 57 | end 58 | 59 | def swap(nums, i, j) 60 | nums[i], nums[j] = nums[j], nums[i] 61 | end 62 | 63 | def reverse(nums, i, j) 64 | until i > j 65 | swap(nums, i, j) 66 | i += 1 67 | j -= 1 68 | end 69 | end 70 | -------------------------------------------------------------------------------- /19.remove-nth-node-from-end-of-list.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=19 lang=ruby 4 | # 5 | # [19] Remove Nth Node From End of List 6 | # 7 | # https://leetcode.com/problems/remove-nth-node-from-end-of-list/description/ 8 | # 9 | # Given a linked list, remove the n-th node from the end of list and 10 | # return its head. 11 | # 12 | # Example: 13 | # 14 | # Given linked list: 1->2->3->4->5, and n = 2. 15 | # 16 | # After removing the second node from the end, the linked list becomes 17 | # 1->2->3->5. 18 | # 19 | # Note: 20 | # 21 | # Given n will always be valid. 22 | # 23 | # Follow up: 24 | # 25 | # Could you do this in one pass? 26 | # 27 | # Definition for singly-linked list. 28 | # class ListNode 29 | # attr_accessor :val, :next 30 | # def initialize(val) 31 | # @val = val 32 | # @next = nil 33 | # end 34 | # end 35 | 36 | 37 | # Two pointers: fast and slow, fast is n steps faster than slow. 38 | # The only edge case is to delete the first element. 39 | 40 | # @param {ListNode} head 41 | # @param {Integer} n 42 | # @return {ListNode} 43 | def remove_nth_from_end(head, n) 44 | fast = slow = head 45 | n.times { fast = fast.next } 46 | return head.next if fast.nil? 47 | slow, fast = slow.next, fast.next while !fast.next.nil? 48 | slow.next = slow.next.next 49 | head 50 | end 51 | -------------------------------------------------------------------------------- /191.number-of-1-bits.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=191 lang=ruby 4 | # 5 | # [191] Number of 1 Bits 6 | # 7 | # https://leetcode.com/problems/number-of-1-bits/description/ 8 | # 9 | # Write a function that takes an unsigned integer and return the 10 | # number of '1' bits it has (also known as the Hamming weight). 11 | # 12 | # Example 1: 13 | # 14 | # Input: 00000000000000000000000000001011 15 | # Output: 3 16 | # Explanation: The input binary string 17 | # 00000000000000000000000000001011 has a total of three '1' bits. 18 | # 19 | # Example 2: 20 | # 21 | # Input: 00000000000000000000000010000000 22 | # Output: 1 23 | # Explanation: The input binary string 24 | # 00000000000000000000000010000000 has a total of one '1' bit. 25 | # 26 | # Example 3: 27 | # 28 | # Input: 11111111111111111111111111111101 29 | # Output: 31 30 | # Explanation: The input binary string 11111111111111111111111111111101 has a 31 | # total of thirty one '1' bits. 32 | # 33 | # Note: 34 | # 35 | # Note that in some languages such as Java, there is no unsigned 36 | # integer type. In this case, the input will be given as signed 37 | # integer type and should not affect your implementation, as the 38 | # internal binary representation of the integer is the same whether it 39 | # is signed or unsigned. In Java, the compiler represents the signed 40 | # integers using 2's complement notation. Therefore, in Example 41 | # 3 above the input represents the signed integer -3. 42 | # 43 | # Follow up: 44 | # 45 | # If this function is called many times, how would you optimize it? 46 | 47 | 48 | # See Fenwick Tree for the idea behind (n & -n). 49 | 50 | # @param {Integer} n, a positive integer 51 | # @return {Integer} 52 | def hamming_weight(n) 53 | count = 0 54 | while n > 0 55 | n -= (n & -n) 56 | count += 1 57 | end 58 | count 59 | end 60 | -------------------------------------------------------------------------------- /199.binary-tree-right-side-view.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=199 lang=ruby 4 | # 5 | # [199] Binary Tree Right Side View 6 | # 7 | # https://leetcode.com/problems/binary-tree-right-side-view/description/ 8 | # 9 | # Given a binary tree, imagine yourself standing on the right side of it, 10 | # return the values of the nodes you can see ordered from top to bottom. 11 | # 12 | # Example: 13 | # 14 | # Input: [1,2,3,null,5,null,4] 15 | # Output: [1, 3, 4] 16 | # Explanation: 17 | # ⁠ 1 <--- 18 | # ⁠/ \ 19 | # 2 3 <--- 20 | # ⁠\ \ 21 | # ⁠ 5 4 <--- 22 | # 23 | # Definition for a binary tree node. 24 | # class TreeNode 25 | # attr_accessor :val, :left, :right 26 | # def initialize(val) 27 | # @val = val 28 | # @left, @right = nil, nil 29 | # end 30 | # end 31 | 32 | 33 | # Level order traversal. 34 | 35 | # @param {TreeNode} root 36 | # @return {Integer[]} 37 | def right_side_view(root) 38 | return [] if root.nil? 39 | q, ans = [root], [] 40 | while !q.empty? 41 | ans << q[-1].val 42 | q.size.times do 43 | x = q.shift 44 | q << x.left if !x.left.nil? 45 | q << x.right if !x.right.nil? 46 | end 47 | end 48 | ans 49 | end 50 | -------------------------------------------------------------------------------- /2.add-two-numbers.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=2 lang=ruby 4 | # 5 | # [2] Add Two Numbers 6 | # 7 | # https://leetcode.com/problems/add-two-numbers/description/ 8 | # 9 | # You are given two non-empty linked lists representing two 10 | # non-negative integers. The digits are stored in reverse order and 11 | # each of their nodes contain a single digit. Add the two numbers and 12 | # return it as a linked list. 13 | # 14 | # You may assume the two numbers do not contain any leading zero, 15 | # except the number 0 itself. 16 | # 17 | # Example: 18 | # 19 | # Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) 20 | # Output: 7 -> 0 -> 8 21 | # Explanation: 342 + 465 = 807. 22 | # 23 | # Definition for singly-linked list. 24 | # class ListNode 25 | # attr_accessor :val, :next 26 | # def initialize(val) 27 | # @val = val 28 | # @next = nil 29 | # end 30 | # end 31 | 32 | 33 | # @param {ListNode} l1 34 | # @param {ListNode} l2 35 | # @return {ListNode} 36 | def add_two_numbers(l1, l2) 37 | curr, carry = ListNode.new(nil), 0 38 | ans = curr 39 | while !l1.nil? || !l2.nil? || !carry.zero? 40 | sum = carry + l1&.val.to_i + l2&.val.to_i 41 | carry = sum / 10 42 | curr.next = ListNode.new(sum % 10) 43 | curr = curr.next 44 | l1 = l1.next if !l1.nil? 45 | l2 = l2.next if !l2.nil? 46 | end 47 | ans.next 48 | end 49 | -------------------------------------------------------------------------------- /20.valid-parentheses.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=20 lang=ruby 4 | # 5 | # [20] Valid Parentheses 6 | # 7 | # https://leetcode.com/problems/valid-parentheses/description/ 8 | # 9 | # Given a string containing just the characters '(', ')', '{', '}', 10 | # '[' and ']', determine if the input string is valid. 11 | # 12 | # An input string is valid if: 13 | # 14 | # Open brackets must be closed by the same type of brackets. 15 | # Open brackets must be closed in the correct order. 16 | # 17 | # Note that an empty string is also considered valid. 18 | # 19 | # Example 1: 20 | # 21 | # Input: "()" 22 | # Output: true 23 | # 24 | # Example 2: 25 | # 26 | # Input: "()[]{}" 27 | # Output: true 28 | # 29 | # Example 3: 30 | # 31 | # Input: "(]" 32 | # Output: false 33 | # 34 | # Example 4: 35 | # 36 | # Input: "([)]" 37 | # Output: false 38 | # 39 | # Example 5: 40 | # 41 | # Input: "{[]}" 42 | # Output: true 43 | 44 | 45 | 46 | # @param {String} s 47 | # @return {Boolean} 48 | def is_valid(s) 49 | st = [] 50 | s.chars.each do |c| 51 | t = st[-1] 52 | if c == ']' && t == '[' || 53 | c == '}' && t == '{' || 54 | c == ')' && t == '(' 55 | st.pop 56 | else 57 | st << c 58 | end 59 | end 60 | st.empty? 61 | end 62 | -------------------------------------------------------------------------------- /202.happy-number.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=202 lang=ruby 4 | # 5 | # [202] Happy Number 6 | # 7 | # https://leetcode.com/problems/happy-number/description/ 8 | # 9 | # Write an algorithm to determine if a number is "happy". 10 | # 11 | # A happy number is a number defined by the following process: Starting with 12 | # any positive integer, replace the number by the sum of the squares of its 13 | # digits, and repeat the process until the number equals 1 (where it will 14 | # stay), or it loops endlessly in a cycle which does not include 1. Those 15 | # numbers for which this process ends in 1 are happy numbers. 16 | # 17 | # Example: 18 | # 19 | # Input: 19 20 | # Output: true 21 | # Explanation: 22 | # 12 + 92 = 82 23 | # 82 + 22 = 68 24 | # 62 + 82 = 100 25 | # 12 + 02 + 02 = 1 26 | 27 | 28 | # Using Hash. 29 | 30 | # @param {Integer} n 31 | # @return {Boolean} 32 | def is_happy(n) 33 | h = Set.new 34 | x = f(n) 35 | while x != 1 36 | puts x 37 | return false if h.include?(x) 38 | h << x 39 | x = f(x) 40 | end 41 | true 42 | end 43 | 44 | def f(n) 45 | n.digits.reduce(0) { |s, x| s += x*x } 46 | end 47 | 48 | 49 | # Floyd Cycle detection algorithm. 50 | # 51 | # See: https://en.wikipedia.org/wiki/Cycle_detection 52 | 53 | def is_happy(n) 54 | t = f(n) 55 | h = f(f(n)) 56 | while t != h 57 | t = f(t) 58 | h = f(f(h)) 59 | end 60 | return t == 1 61 | end 62 | 63 | def f(n) 64 | n.digits.reduce(0) { |s, x| s += x*x } 65 | end 66 | -------------------------------------------------------------------------------- /203.remove-linked-list-elements.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=203 lang=ruby 4 | # 5 | # [203] Remove Linked List Elements 6 | # 7 | # https://leetcode.com/problems/remove-linked-list-elements/description/ 8 | # 9 | # Remove all elements from a linked list of integers that have value val. 10 | # 11 | # Example: 12 | # 13 | # Input: 1->2->6->3->4->5->6, val = 6 14 | # Output: 1->2->3->4->5 15 | # 16 | # Definition for singly-linked list. 17 | # class ListNode 18 | # attr_accessor :val, :next 19 | # def initialize(val) 20 | # @val = val 21 | # @next = nil 22 | # end 23 | # end 24 | 25 | 26 | # Recursive. 27 | 28 | # @param {ListNode} head 29 | # @param {Integer} val 30 | # @return {ListNode} 31 | def remove_elements_a(head, val) 32 | return if head.nil? 33 | if head.val == val 34 | head = remove_elements(head.next, val) 35 | else 36 | head.next = remove_elements(head.next, val) 37 | end 38 | head 39 | end 40 | 41 | 42 | # Iterative. 43 | 44 | def remove_elements(head, val) 45 | head = head.next while !head.nil? && head.val == val 46 | cur = head 47 | while !cur.nil? && !cur.next.nil? 48 | if cur.next.val == val 49 | cur.next = cur.next.next 50 | else 51 | cur = cur.next 52 | end 53 | end 54 | head 55 | end 56 | -------------------------------------------------------------------------------- /204.count-primes.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=204 lang=ruby 4 | # 5 | # [204] Count Primes 6 | # 7 | # https://leetcode.com/problems/count-primes/description/ 8 | # 9 | # Count the number of prime numbers less than a non-negative number, n. 10 | # 11 | # Example: 12 | # 13 | # Input: 10 14 | # Output: 4 15 | # Explanation: There are 4 prime numbers less than 10, they are 2, 3, 5, 7. 16 | 17 | 18 | # @param {Integer} n 19 | # @return {Integer} 20 | def count_primes(n) 21 | primes = Array.new(n, true) 22 | (2...Math.sqrt(n)).each do |i| 23 | next if !primes[i] 24 | (i*i..n-1).step(i).each do |j| 25 | primes[j] = false 26 | end 27 | end 28 | primes[2..(n-1)]&.count(true) || 0 29 | end 30 | 31 | 32 | # Ruby 33 | 34 | require 'prime' 35 | 36 | def count_primes(n) 37 | Prime.each(n-1).count 38 | end 39 | -------------------------------------------------------------------------------- /206.reverse-linked-list.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=206 lang=ruby 4 | # 5 | # [206] Reverse Linked List 6 | # 7 | # https://leetcode.com/problems/reverse-linked-list/description/ 8 | # 9 | # Reverse a singly linked list. 10 | # 11 | # Example: 12 | # 13 | # Input: 1->2->3->4->5->NULL 14 | # Output: 5->4->3->2->1->NULL 15 | # 16 | # Follow up: 17 | # 18 | # A linked list can be reversed either iteratively or recursively. 19 | # Could you implement both? 20 | # 21 | # Definition for singly-linked list. 22 | # class ListNode 23 | # attr_accessor :val, :next 24 | # def initialize(val) 25 | # @val = val 26 | # @next = nil 27 | # end 28 | # end 29 | 30 | 31 | # Recursive. 32 | 33 | # @param {ListNode} head 34 | # @return {ListNode} 35 | def reverse_list(head) 36 | return head if head.nil? || head.next.nil? 37 | p = reverse_list(head.next) 38 | head.next.next = head 39 | head.next = nil 40 | p 41 | end 42 | 43 | 44 | # Iterative. 45 | 46 | def reverse_list(head) 47 | cur, rev = head, nil 48 | while !cur.nil? 49 | rev, rev.next, cur = cur, rev, cur.next 50 | end 51 | rev 52 | end 53 | -------------------------------------------------------------------------------- /208.implement-trie-prefix-tree.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=208 lang=ruby 4 | # 5 | # [208] Implement Trie (Prefix Tree) 6 | # 7 | # https://leetcode.com/problems/implement-trie-prefix-tree/description/ 8 | # 9 | # Implement a trie with insert, search, and startsWith methods. 10 | # 11 | # Example: 12 | # 13 | # Trie trie = new Trie(); 14 | # 15 | # trie.insert("apple"); 16 | # trie.search("apple"); // returns true 17 | # trie.search("app"); // returns false 18 | # trie.startsWith("app"); // returns true 19 | # trie.insert("app"); 20 | # trie.search("app"); // returns true 21 | # 22 | # Note: 23 | # 24 | # You may assume that all inputs are consist of lowercase letters a-z. 25 | # All inputs are guaranteed to be non-empty strings. 26 | 27 | 28 | class Trie 29 | 30 | def initialize 31 | @root = Node.new 32 | end 33 | 34 | def insert(word, x=@root, k=0) 35 | x = Node.new if x.nil? 36 | if k == word.size 37 | x.val = true 38 | return x 39 | end 40 | c = ord(word[k]) 41 | x.next[c] = insert(word, x.next[c], k+1) 42 | x 43 | end 44 | 45 | def search(word, x=@root, k=0) 46 | return false if x.nil? 47 | return !x.val.nil? if k == word.size 48 | c = ord(word[k]) 49 | search(word, x.next[c], k+1) 50 | end 51 | 52 | def starts_with(prefix, x=@root, k=0) 53 | return false if x.nil? 54 | return true if k == prefix.size 55 | c = ord(prefix[k]) 56 | starts_with(prefix, x.next[c], k+1) 57 | end 58 | 59 | private 60 | 61 | def ord(s) 62 | s.ord - 'a'.ord 63 | end 64 | 65 | class Node 66 | attr_accessor :val, :next 67 | def initialize 68 | @val, @next = nil, Array.new(26) 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /209.minimum-size-subarray-sum.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=209 lang=ruby 4 | # 5 | # [209] Minimum Size Subarray Sum 6 | # 7 | # https://leetcode.com/problems/minimum-size-subarray-sum/description/ 8 | # 9 | # Given an array of n positive integers and a positive integer s, find the 10 | # minimal length of a contiguous subarray of which the sum ≥ s. If there isn't 11 | # one, return 0 instead. 12 | # 13 | # Example: 14 | # 15 | # Input: s = 7, nums = [2,3,1,2,4,3] 16 | # Output: 2 17 | # Explanation: the subarray [4,3] has the minimal length under the 18 | # problem constraint. 19 | # 20 | # Follow up: 21 | # 22 | # If you have figured out the O(n) solution, try coding another solution of 23 | # which the time complexity is O(n log n). 24 | 25 | 26 | # Two Pointers: 27 | # 28 | # 1. window(i, j) is the sum from num[i] to nums[j]. 29 | # 2. If window(i, j) >= s, then update minimum count, move i 30 | # forward, reconsider the new window(i+1, j). 31 | # 3. If window(i, j) < s, then the window is too small, we need more 32 | # number, move j forward. 33 | # 4. Instead of caculating window(i, j) for every i and j, we can 34 | # use the technique from prefix sum to calculate window(i, j). 35 | 36 | # @param {Integer} s 37 | # @param {Integer[]} nums 38 | # @return {Integer} 39 | def min_sub_array_len(s, nums) 40 | i = j = 0 41 | sum, min = 0, Float::INFINITY 42 | while j < nums.size 43 | sum += nums[j] # consider nums[j] 44 | return 1 if i == j && nums[i] >= s 45 | if sum < s 46 | j += 1 47 | else 48 | min = [min, j-i+1].min 49 | sum -= nums[i] # exclude nums[i] 50 | sum -= nums[j] # reconsider nums[j] for the next loop 51 | i += 1 52 | end 53 | end 54 | min == Float::INFINITY ? 0 : min 55 | end 56 | -------------------------------------------------------------------------------- /21.merge-two-sorted-lists.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=21 lang=ruby 4 | # 5 | # [21] Merge Two Sorted Lists 6 | # 7 | # https://leetcode.com/problems/merge-two-sorted-lists/description/ 8 | # 9 | # Merge two sorted linked lists and return it as a new list. The new list 10 | # should be made by splicing together the nodes of the first two lists. 11 | # 12 | # Example: 13 | # 14 | # Input: 1->2->4, 1->3->4 15 | # Output: 1->1->2->3->4->4 16 | # 17 | # Definition for singly-linked list. 18 | # class ListNode 19 | # attr_accessor :val, :next 20 | # def initialize(val) 21 | # @val = val 22 | # @next = nil 23 | # end 24 | # end 25 | 26 | 27 | # Recursive. 28 | 29 | # @param {ListNode} l1 30 | # @param {ListNode} l2 31 | # @return {ListNode} 32 | def merge_two_lists(l1, l2) 33 | return l2 if l1.nil? 34 | return l1 if l2.nil? 35 | if l1.val <= l2.val 36 | l1.next = merge_two_lists(l1.next, l2) 37 | l1 38 | else 39 | l2.next = merge_two_lists(l1, l2.next) 40 | l2 41 | end 42 | end 43 | 44 | 45 | # Iterative. 46 | 47 | def merge_two_lists(l1, l2) 48 | ans = cur = ListNode.new(nil) 49 | while !l1.nil? && !l2.nil? 50 | if l1.val <= l2.val 51 | cur.next, l1 = l1, l1.next 52 | else 53 | cur.next, l2 = l2, l2.next 54 | end 55 | cur = cur.next 56 | end 57 | cur.next = l1 || l2 58 | ans.next 59 | end 60 | -------------------------------------------------------------------------------- /213.house-robber-ii.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=213 lang=ruby 4 | # 5 | # [213] House Robber II 6 | # 7 | # https://leetcode.com/problems/house-robber-ii/description/ 8 | # 9 | # You are a professional robber planning to rob houses along a street. 10 | # Each house has a certain amount of money stashed. All houses at this 11 | # place are arranged in a circle. That means the first house is the 12 | # neighbor of the last one. Meanwhile, adjacent houses have security 13 | # system connected and it will automatically contact the police if two 14 | # adjacent houses were broken into on the same night. 15 | # 16 | # Given a list of non-negative integers representing the amount of 17 | # money of each house, determine the maximum amount of money you can 18 | # rob tonight without alerting the police. 19 | # 20 | # Example 1: 21 | # 22 | # Input: [2,3,2] 23 | # Output: 3 24 | # Explanation: You cannot rob house 1 (money = 2) and then rob house 3 25 | # (money = 2), because they are adjacent houses. 26 | # 27 | # Example 2: 28 | # 29 | # Input: [1,2,3,1] 30 | # Output: 4 31 | # Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 32 | # 3). Total amount you can rob = 1 + 3 = 4. 33 | 34 | 35 | # @param {Integer[]} nums 36 | # @return {Integer} 37 | def rob(nums) 38 | return 0 if nums.empty? 39 | return nums[0] if nums.size == 1 40 | [sub_rob(nums[1..-1]), sub_rob(nums[0..-2])].max 41 | end 42 | 43 | def sub_rob(nums) 44 | d2 = d1 = 0 45 | nums.each do |n| 46 | d1, d2 = [d2+n, d1].max, d1 47 | end 48 | d1 49 | end 50 | -------------------------------------------------------------------------------- /216.combination-sum-iii.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=216 lang=ruby 4 | # 5 | # [216] Combination Sum III 6 | # 7 | # https://leetcode.com/problems/combination-sum-iii/description/ 8 | # 9 | # Find all possible combinations of k numbers that add up to a number 10 | # n, given that only numbers from 1 to 9 can be used and each 11 | # combination should be a unique set of numbers. 12 | # 13 | # Note: 14 | # 15 | # All numbers will be positive integers. 16 | # The solution set must not contain duplicate combinations. 17 | # 18 | # Example 1: 19 | # 20 | # Input: k = 3, n = 7 21 | # Output: [[1,2,4]] 22 | # 23 | # Example 2: 24 | # 25 | # Input: k = 3, n = 9 26 | # Output: [[1,2,6], [1,3,5], [2,3,4]] 27 | 28 | 29 | # DFS+Backtracking. 30 | 31 | # @param {Integer} k 32 | # @param {Integer} n 33 | # @return {Integer[][]} 34 | def combination_sum3(k, n, a=(1..9).to_a, i=0, sum=0, path=[], paths=[]) 35 | return if path.size > k || sum > n 36 | if sum == n && path.size == k 37 | paths << path.dup 38 | else 39 | (i..8).each do |j| 40 | path << a[j] 41 | combination_sum3(k, n, a, j+1, sum+a[j], path, paths) 42 | path.pop 43 | end 44 | end 45 | paths 46 | end 47 | -------------------------------------------------------------------------------- /22.generate-parentheses.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=22 lang=ruby 4 | # 5 | # [22] Generate Parentheses 6 | # 7 | # https://leetcode.com/problems/generate-parentheses/description/ 8 | # 9 | # Given n pairs of parentheses, write a function to generate all 10 | # combinations of well-formed parentheses. 11 | # 12 | # For example, given n = 3, a solution set is: 13 | # [ 14 | # ⁠ "((()))", 15 | # ⁠ "(()())", 16 | # ⁠ "(())()", 17 | # ⁠ "()(())", 18 | # ⁠ "()()()" 19 | # ] 20 | 21 | 22 | # DFS. 23 | # 24 | # See: https://stackoverflow.com/a/23414519 25 | 26 | # @param {Integer} n 27 | # @return {String[]} 28 | def generate_parenthesis(n) 29 | dfs(n, n) 30 | end 31 | 32 | def dfs(o, c, s="", paths=[]) 33 | return if o > c || c < 0 || o < 0 34 | if o == 0 35 | paths << "#{s}#{')'*c}" 36 | else 37 | dfs(o-1, c, s+"(", paths) 38 | dfs(o, c-1, s+")", paths) 39 | end 40 | paths 41 | end 42 | -------------------------------------------------------------------------------- /226.invert-binary-tree.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=226 lang=ruby 4 | # 5 | # [226] Invert Binary Tree 6 | # 7 | # https://leetcode.com/problems/invert-binary-tree/description/ 8 | # 9 | # Invert a binary tree. 10 | # 11 | # Example: 12 | # 13 | # Input: 14 | # 15 | # ⁠ 4 16 | # ⁠ / \ 17 | # ⁠ 2 7 18 | # ⁠/ \ / \ 19 | # 1 3 6 9 20 | # 21 | # Output: 22 | # 23 | # ⁠ 4 24 | # ⁠ / \ 25 | # ⁠ 7 2 26 | # ⁠/ \ / \ 27 | # 9 6 3 1 28 | # 29 | # Trivia: 30 | # This problem was inspired by this original tweet by Max Howell: 31 | # 32 | # Google: 90% of our engineers use the software you wrote (Homebrew), but you 33 | # can’t invert a binary tree on a whiteboard so f*** off. 34 | # 35 | # Definition for a binary tree node. 36 | # class TreeNode 37 | # attr_accessor :val, :left, :right 38 | # def initialize(val) 39 | # @val = val 40 | # @left, @right = nil, nil 41 | # end 42 | # end 43 | 44 | # @param {TreeNode} root 45 | # @return {TreeNode} 46 | def invert_tree(root) 47 | return if root.nil? 48 | root.left, root.right = root.right, root.left 49 | invert_tree(root.left) 50 | invert_tree(root.right) 51 | root 52 | end 53 | -------------------------------------------------------------------------------- /228.summary-ranges.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=228 lang=ruby 4 | # 5 | # [228] Summary Ranges 6 | # 7 | # https://leetcode.com/problems/summary-ranges/description/ 8 | # 9 | # Given a sorted integer array without duplicates, return the summary 10 | # of its ranges. 11 | # 12 | # Example 1: 13 | # 14 | # Input: [0,1,2,4,5,7] 15 | # Output: ["0->2","4->5","7"] 16 | # Explanation: 0,1,2 form a continuous range; 4,5 form a continuous range. 17 | # 18 | # Example 2: 19 | # 20 | # Input: [0,2,3,4,6,8,9] 21 | # Output: ["0","2->4","6","8->9"] 22 | # Explanation: 2,3,4 form a continuous range; 8,9 form a continuous range. 23 | 24 | 25 | # @param {Integer[]} nums 26 | # @return {String[]} 27 | def summary_ranges(nums, r=[]) 28 | return [] if nums.empty? 29 | i = 0 30 | i += 1 while i+1 < nums.size && nums[i+1] == nums[i]+1 31 | i == 0 ? r << "#{nums[0]}" : r << "#{nums[0]}->#{nums[i]}" 32 | summary_ranges(nums[i+1..-1], r) 33 | r 34 | end 35 | -------------------------------------------------------------------------------- /23.merge-k-sorted-lists.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=23 lang=ruby 4 | # 5 | # [23] Merge k Sorted Lists 6 | # 7 | # https://leetcode.com/problems/merge-k-sorted-lists/description/ 8 | # 9 | # Merge k sorted linked lists and return it as one sorted list. 10 | # Analyze and describe its complexity. 11 | # 12 | # Example: 13 | # 14 | # Input: 15 | # [ 16 | # 1->4->5, 17 | # 1->3->4, 18 | # 2->6 19 | # ] 20 | # Output: 1->1->2->3->4->4->5->6 21 | # 22 | # Definition for singly-linked list. 23 | # class ListNode 24 | # attr_accessor :val, :next 25 | # def initialize(val) 26 | # @val = val 27 | # @next = nil 28 | # end 29 | # end 30 | 31 | 32 | # Divide and Conquer. See https://www.coursera.org/learn/algorithms-divide-conquer. 33 | # 34 | # The method to analyse the time complexity is the same as merge sort. 35 | # 36 | # 1. Initailly there are k lists at level 1, we merge every 2 lists, now there 37 | # are k/2 lists at level 2. Same goes on: k/4, ..., logk. 38 | # 2. At each level, the work being done is time proportional to the 39 | # size of all numbers N (n1+n2+n3+...+nk). 40 | # 3. The total time complexity would be 41 | # work_at_each_level*number_of_levels: N*logk 42 | 43 | # @param {ListNode[]} lists 44 | # @return {ListNode} 45 | def merge_k_lists(lists) 46 | return [] if lists.empty? 47 | while lists.size != 1 48 | lists = lists.each_slice(2).map do |a, b| 49 | merge_two_lists(a, b) 50 | end 51 | end 52 | lists[0] 53 | end 54 | 55 | def merge_two_lists(l1, l2) 56 | return l2 if l1.nil? 57 | return l1 if l2.nil? 58 | if l1.val <= l2.val 59 | l1.next = merge_two_lists(l1.next, l2) 60 | l1 61 | else 62 | l2.next = merge_two_lists(l1, l2.next) 63 | l2 64 | end 65 | end 66 | -------------------------------------------------------------------------------- /234.palindrome-linked-list.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=234 lang=ruby 4 | # 5 | # [234] Palindrome Linked List 6 | # 7 | # https://leetcode.com/problems/palindrome-linked-list/description/ 8 | # 9 | # Given a singly linked list, determine if it is a palindrome. 10 | # 11 | # Example 1: 12 | # 13 | # Input: 1->2 14 | # Output: false 15 | # 16 | # Example 2: 17 | # 18 | # Input: 1->2->2->1 19 | # Output: true 20 | # 21 | # Follow up: 22 | # Could you do it in O(n) time and O(1) space? 23 | # 24 | # Definition for singly-linked list. 25 | # class ListNode 26 | # attr_accessor :val, :next 27 | # def initialize(val) 28 | # @val = val 29 | # @next = nil 30 | # end 31 | # end 32 | 33 | 34 | # 1. Find the middle, see proble 876. 35 | # 2. Reverse the first half while finding the middle. 36 | # 3. Compare the frist half and the second half. 37 | 38 | # @param {ListNode} head 39 | # @return {Boolean} 40 | def is_palindrome(head) 41 | rev = nil 42 | slow = fast = head 43 | while !fast.nil? && !fast.next.nil? 44 | fast = fast.next.next 45 | rev, rev.next, slow = slow, rev, slow.next 46 | end 47 | slow = slow.next if !fast.nil? 48 | while !rev.nil? && rev.val == slow.val 49 | slow, rev = slow.next, rev.next 50 | end 51 | rev.nil? 52 | end 53 | -------------------------------------------------------------------------------- /235.lowest-common-ancestor-of-a-binary-search-tree.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=235 lang=ruby 4 | # 5 | # [235] Lowest Common Ancestor of a Binary Search Tree 6 | # 7 | # https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/description/ 8 | # 9 | # Given a binary search tree (BST), find the lowest common ancestor 10 | # (LCA) of two given nodes in the BST. 11 | # 12 | # According to the definition of LCA on Wikipedia: “The lowest common 13 | # ancestor is defined between two nodes p and q as the lowest node in 14 | # T that has both p and q as descendants (where we allow a node to be 15 | # a descendant of itself).” 16 | # 17 | # Given binary search tree: root = [6,2,8,0,4,7,9,null,null,3,5] 18 | # 19 | # Example 1: 20 | # 21 | # Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8 22 | # Output: 6 23 | # Explanation: The LCA of nodes 2 and 8 is 6. 24 | # 25 | # Example 2: 26 | # 27 | # Input: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 4 28 | # Output: 2 29 | # Explanation: The LCA of nodes 2 and 4 is 2, since a node can be a 30 | # descendant of itself according to the LCA definition. 31 | # 32 | # Note: 33 | # 34 | # All of the nodes' values will be unique. p and q are different and 35 | # both values will exist in the BST. 36 | # 37 | # Definition for a binary tree node. 38 | # class TreeNode 39 | # attr_accessor :val, :left, :right 40 | # def initialize(val) 41 | # @val = val 42 | # @left, @right = nil, nil 43 | # end 44 | # end 45 | 46 | 47 | # @param {TreeNode} root 48 | # @param {TreeNode} p 49 | # @param {TreeNode} q 50 | # @return {TreeNode} 51 | def lowest_common_ancestor(root, p, q) 52 | p, q = q, p if p.val > q.val 53 | if root.val < p.val 54 | lowest_common_ancestor(root.right, p, q) 55 | elsif root.val > q.val 56 | lowest_common_ancestor(root.left, p, q) 57 | else 58 | root 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /237.delete-node-in-a-linked-list.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=237 lang=ruby 4 | # 5 | # [237] Delete Node in a Linked List 6 | # 7 | # https://leetcode.com/problems/delete-node-in-a-linked-list/description/ 8 | # 9 | # Write a function to delete a node (except the tail) in a singly 10 | # linked list, given only access to that node. 11 | # 12 | # Given linked list -- head = [4,5,1,9], which looks like following: 13 | # 14 | # Example 1: 15 | # 16 | # Input: head = [4,5,1,9], node = 5 17 | # Output: [4,1,9] 18 | # Explanation: You are given the second node with value 5, the linked list 19 | # should become 4 -> 1 -> 9 after calling your function. 20 | # 21 | # Example 2: 22 | # 23 | # Input: head = [4,5,1,9], node = 1 24 | # Output: [4,5,9] 25 | # Explanation: You are given the third node with value 1, the linked list 26 | # should become 4 -> 5 -> 9 after calling your function. 27 | # 28 | # Note: 29 | # 30 | # The linked list will have at least two elements. 31 | # All of the nodes' values will be unique. 32 | # The given node will not be the tail and it will always be a valid node of the 33 | # linked list. 34 | # Do not return anything from your function. 35 | # 36 | # 37 | # 38 | # Definition for singly-linked list. 39 | # class ListNode 40 | # attr_accessor :val, :next 41 | # def initialize(val) 42 | # @val = val 43 | # @next = nil 44 | # end 45 | # end 46 | 47 | 48 | # Very interesting question, seems like you can 'delete' a node in 49 | # O(n) time if it's not at the tail. 50 | 51 | # @param {ListNode} node 52 | # @return {Void} Do not return anything, modify node in-place instead. 53 | def delete_node(node) 54 | node.val, node.next = node.next.val, node.next.next 55 | end 56 | -------------------------------------------------------------------------------- /238.product-of-array-except-self.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=238 lang=ruby 4 | # 5 | # [238] Product of Array Except Self 6 | # 7 | # https://leetcode.com/problems/product-of-array-except-self/description/ 8 | # 9 | # Given an array nums of n integers where n > 1, return an array 10 | # output such that output[i] is equal to the product of all the 11 | # elements of nums except nums[i]. 12 | # 13 | # Example: 14 | # 15 | # Input: [1,2,3,4] 16 | # Output: [24,12,8,6] 17 | # 18 | # Note: Please solve it without division and in O(n). 19 | # 20 | # Follow up: 21 | # Could you solve it with constant space complexity? (The output array does not 22 | # count as extra space for the purpose of space complexity analysis.) 23 | 24 | 25 | # See problem 42, same idea: two passes, left to right, right to left. 26 | 27 | # @param {Integer[]} nums 28 | # @return {Integer[]} 29 | def product_except_self(nums) 30 | l = nums.reduce([1]) { |h, n| h << h[-1]*n } 31 | r = nums.reverse_each.reduce([1]) { |h, n| h.unshift(h[0]*n) } 32 | nums.size.times.map do |i| 33 | l[i] * r[i+1] 34 | end 35 | end 36 | 37 | 38 | # The second pass is unnecessary. 39 | 40 | def product_except_self(nums) 41 | l = nums.reduce([1]) { |h, n| h << h[-1]*n } 42 | t, ans = 1, [] 43 | (nums.size-1).downto(0) do |i| 44 | ans.unshift(l[i] * t) 45 | t *= nums[i] 46 | end 47 | ans 48 | end 49 | -------------------------------------------------------------------------------- /240.search-a-2d-matrix-ii.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=240 lang=ruby 4 | # 5 | # [240] Search a 2D Matrix II 6 | # 7 | # https://leetcode.com/problems/search-a-2d-matrix-ii/description/ 8 | # 9 | # Write an efficient algorithm that searches for a value in an m x n 10 | # matrix. This matrix has the following properties: 11 | # 12 | # Integers in each row are sorted in ascending from left to right. 13 | # Integers in each column are sorted in ascending from top to bottom. 14 | # 15 | # Example: 16 | # 17 | # Consider the following matrix: 18 | # 19 | # [ 20 | # ⁠ [1, 4, 7, 11, 15], 21 | # ⁠ [2, 5, 8, 12, 19], 22 | # ⁠ [3, 6, 9, 16, 22], 23 | # ⁠ [10, 13, 14, 17, 24], 24 | # ⁠ [18, 21, 23, 26, 30] 25 | # ] 26 | # 27 | # Given target = 5, return true. 28 | # 29 | # Given target = 20, return false. 30 | 31 | 32 | # The key point is to check the top right corner. 33 | 34 | # @param {Integer[][]} matrix 35 | # @param {Integer} target 36 | # @return {Boolean} 37 | def search_matrix(matrix, target) 38 | k = -1 39 | matrix.each do |s| 40 | k -= 1 while s[k] && target < s[k] 41 | return true if s[k] == target 42 | end 43 | false 44 | end 45 | -------------------------------------------------------------------------------- /242.valid-anagram.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=242 lang=ruby 4 | # 5 | # [242] Valid Anagram 6 | # 7 | # https://leetcode.com/problems/valid-anagram/description/ 8 | # 9 | # Given two strings s and t, write a function to determine if t is an 10 | # anagram of s. 11 | # 12 | # Example 1: 13 | # 14 | # Input: s = "anagram", t = "nagaram" 15 | # Output: true 16 | # 17 | # Example 2: 18 | # 19 | # Input: s = "rat", t = "car" 20 | # Output: false 21 | # 22 | # Note: 23 | # You may assume the string contains only lowercase alphabets. 24 | # 25 | # Follow up: 26 | # What if the inputs contain unicode characters? How would you adapt your 27 | # solution to such case? 28 | 29 | 30 | # @param {String} s 31 | # @param {String} t 32 | # @return {Boolean} 33 | def is_anagram(s, t) 34 | return false if s.size != t.size 35 | s.chars.sort == t.chars.sort 36 | end 37 | 38 | 39 | def is_anagram(s, t) 40 | return false if s.size != t.size 41 | !(0..s.size-1).reduce({}) do |h, i| 42 | h[s[i]] += 1 43 | h[t[i]] -= 1 44 | h 45 | end.any? { |_, v| v != 0 } 46 | end 47 | -------------------------------------------------------------------------------- /243.shortest-word-distance.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=243 lang=ruby 4 | # 5 | # [243] Shortest Word Distance 6 | # 7 | # https://leetcode.com/problems/shortest-word-distance/description/ 8 | # 9 | # Given a list of words and two words word1 and word2, return the 10 | # shortest distance between these two words in the list. 11 | # 12 | # For example, 13 | # Assume that words = ["practice", "makes", "perfect", "coding", "makes"]. 14 | # Given word1 = “coding”, word2 = “practice”, return 3. 15 | # Given word1 = "makes", word2 = "coding", return 1. 16 | 17 | 18 | # This question is so fxxking stupid, what's the point of an O(n) 19 | # solution when there are n queries with the same input and the time 20 | # complexity'd be O(n^2). You should preprocess the words and answer 21 | # each query in O(f(w1)+f(w2)) time where f is the time word occurs. 22 | 23 | def shortest_distance(words, word1, word2) 24 | p = q = -1 25 | min = Float::INFINITY 26 | words.each_with_index do |w, i| 27 | if word1 == w 28 | p = i 29 | elsif word2 == w 30 | q = i 31 | end 32 | if p >= 0 && q >= 0 33 | min = [min, (p-q).abs].min 34 | end 35 | end 36 | min 37 | end 38 | -------------------------------------------------------------------------------- /25.reverse-nodes-in-k-group.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=25 lang=ruby 4 | # 5 | # [25] Reverse Nodes in k-Group 6 | # 7 | # https://leetcode.com/problems/reverse-nodes-in-k-group/description/ 8 | # 9 | # Given a linked list, reverse the nodes of a linked list k at a time 10 | # and return its modified list. 11 | # 12 | # k is a positive integer and is less than or equal to the length of 13 | # the linked list. If the number of nodes is not a multiple of k then 14 | # left-out nodes in the end should remain as it is. 15 | # 16 | # Example: 17 | # 18 | # Given this linked list: 1->2->3->4->5 19 | # For k = 2, you should return: 2->1->4->3->5 20 | # For k = 3, you should return: 3->2->1->4->5 21 | # 22 | # Note: 23 | # 24 | # Only constant extra memory is allowed. 25 | # You may not alter the values in the list's nodes, only nodes itself 26 | # may be changed. 27 | # 28 | # Definition for singly-linked list. 29 | # class ListNode 30 | # attr_accessor :val, :next 31 | # def initialize(val) 32 | # @val = val 33 | # @next = nil 34 | # end 35 | # end 36 | 37 | 38 | # @param {ListNode} head 39 | # @param {Integer} k 40 | # @return {ListNode} 41 | def reverse_k_group(head, k) 42 | return if head.nil? 43 | return head if k == 1 44 | head, tail, cur = reverse_first_k(head, k) 45 | tail.next = reverse_k_group(cur, k) 46 | head 47 | end 48 | 49 | def reverse_first_k(l, k) 50 | cur, tail, rev = l, l, nil 51 | k.times do |i| 52 | return reverse_first_k(rev, i) if cur.nil? 53 | rev, rev.next, cur = cur, rev, cur.next 54 | end 55 | [rev, tail, cur] 56 | end 57 | -------------------------------------------------------------------------------- /252.meeting-rooms.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=252 lang=ruby 4 | # 5 | # [252] Meeting Rooms 6 | # 7 | # https://leetcode.com/problems/meeting-rooms/description/ 8 | # 9 | # Given an array of meeting time intervals consisting of start and end 10 | # times [[s1,e1],[s2,e2],...] (si < ei), determine if a person could 11 | # attend all meetings. 12 | # 13 | # Example: 14 | # 15 | # Given [[0, 30],[5, 10],[15, 20]], return false. 16 | # 17 | # Definition for an interval. 18 | # class Interval 19 | # attr_accessor :start, :end 20 | # def initialize(s=0, e=0) 21 | # @start = s 22 | # @end = e 23 | # end 24 | # end 25 | 26 | def can_attend_mettings(intervals) 27 | intervals.sort_by { |x| [x.start, x.end] } 28 | intervals[0].tap do |r| 29 | (1...intervals.size).each do |i| 30 | return false if intervals[i].start < r.end 31 | r.end = [r.end, intervals[i].end].max 32 | end 33 | end 34 | true 35 | end 36 | -------------------------------------------------------------------------------- /253.meeting-rooms-ii.rb: -------------------------------------------------------------------------------- 1 | # Given an array of meeting time intervals consisting of start and end 2 | # times [[s1,e1],[s2,e2],...] (si < ei), find the minimum number of 3 | # conference rooms required. 4 | # 5 | # Example: 6 | # 7 | # Given [[0, 30],[5, 10],[15, 20]], 8 | # 9 | # return 2. 10 | # 11 | # Definition for an interval. 12 | # class Interval 13 | # attr_accessor :start, :end 14 | # def initialize(s=0, e=0) 15 | # @start = s 16 | # @end = e 17 | # end 18 | # end 19 | 20 | 21 | # If you put all intervals on a 1d line, then the rooms we need at any 22 | # given point x would be the same as the number of intersections if we 23 | # draw a vertical line at point x. Using this idea, we can do simple 24 | # line-sweep from left to right and keep record of the maximum number 25 | # of intersections. To calculate the intersections, we don't have to 26 | # iterate through all integers, we just need to consider all the start 27 | # points and end points. 28 | 29 | def min_meeting_rooms(intervals) 30 | s, e = [], [] 31 | intervals.each do |i| 32 | s << i.start 33 | e << i.end 34 | end 35 | s.sort! 36 | e.sort! 37 | i = j = 0 38 | x = ans = 0 39 | while i < intervals.size 40 | if s[i] < e[j] 41 | x += 1 42 | ans = [ans, x].max 43 | i += 1 44 | else 45 | x -= 1 46 | j += 1 47 | end 48 | end 49 | ans 50 | end 51 | 52 | 53 | require './data-structures/treap' 54 | 55 | def min_meeting_rooms_bst(intervals) 56 | st = Treap.new 57 | intervals.each do |i| 58 | st[i.start] = :start 59 | st[i.end] = :end 60 | end 61 | ans = 0 62 | st.each_val.reduce(0) do |c, i| 63 | if i == :start 64 | c += 1 65 | ans = [ans, c].max 66 | else 67 | c -= 1 68 | end 69 | end 70 | ans 71 | end 72 | -------------------------------------------------------------------------------- /256.paint-house.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=256 lang=ruby 4 | # 5 | # [256] Paint House 6 | # 7 | # https://leetcode.com/problems/paint-house/description/ 8 | # 9 | # There are a row of n houses, each house can be painted with one of 10 | # the three colors: red, blue or green. The cost of painting each 11 | # house with a certain color is different. You have to paint all the 12 | # houses such that no two adjacent houses have the same color. 13 | 14 | # The cost of painting each house with a certain color is represented 15 | # by a n x 3 cost matrix. For example, costs[0][0] is the cost of 16 | # painting house 0 with color red; costs[1][2] is the cost of painting 17 | # house 1 with color green, and so on... Find the minimum cost to 18 | # paint all houses. 19 | # 20 | # Note: 21 | # All costs are positive integers. 22 | # 23 | # Example: 24 | # 25 | # Input: [[17,2,17],[16,16,5],[14,3,19]] 26 | # Output: 10 27 | 28 | 29 | # DP 30 | 31 | def min_cost(costs) 32 | return 0 if costs.nil? || costs.empty? 33 | dp = Array.new(costs.size) { Array.new(3, 0) } 34 | dp[0] = costs[0] 35 | (1..costs.size-1).each do |i| 36 | dp[i][0] = [dp[i-1][1], dp[i-1][2]].min + costs[i][0] 37 | dp[i][1] = [dp[i-1][0], dp[i-1][2]].min + costs[i][1] 38 | dp[i][2] = [dp[i-1][0], dp[i-1][1]].min + costs[i][2] 39 | end 40 | dp[costs.size-1].min 41 | end 42 | -------------------------------------------------------------------------------- /266.palindrome-permutation.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=266 lang=ruby 4 | # 5 | # [266] Palindrome Permutation 6 | # 7 | # https://leetcode.com/problems/palindrome-permutation/description/ 8 | # 9 | # Given a string, determine if a permutation of the string could form a palindrome. 10 | # 11 | # For example, "code" -> False, "aab" -> True, "carerac" -> True. 12 | 13 | def can_permute_palindrome(s) 14 | t, n = Set.new, 0 15 | s.chars.each do |c| 16 | if t.include?(c) 17 | n -= 1 18 | t.delete(c) 19 | else 20 | n += 1 21 | t << c 22 | end 23 | end 24 | n <= 1 25 | end 26 | -------------------------------------------------------------------------------- /276.paint-fence.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=276 lang=ruby 4 | # 5 | # [276] Paint Fence 6 | # 7 | # https://leetcode.com/problems/paint-fence/description/ 8 | # 9 | # There is a fence with n posts, each post can be painted with one of 10 | # the k colors. You have to paint all the posts such that no more than 11 | # two adjacent fence posts have the same color. 12 | # 13 | # Return the total number of ways you can paint the fence. 14 | # 15 | # Note: n and k are non-negative integers. 16 | 17 | 18 | # DP. 19 | # 0. dp[i]: the answer up to the ith post. 20 | # 1. i and i-1 have the same color, then dp[i] is dp[i-2]*(k-1). 21 | # (i-2 and i have different color) 22 | # 2. i and i-1 have different color, then dp[i] is dp[i-1]*(k-1). 23 | # 3. Combine these two we have dp[i] = (k-1) * (dp[i-1]+dp[i-2]) 24 | 25 | def num_ways_a(n, k) 26 | dp = [0, k, k*k] 27 | (3..n).each do |i| 28 | dp[i] = (k-1) * (dp[i-1]+dp[i-2]) 29 | end 30 | dp[n] 31 | end 32 | 33 | 34 | # Above method always use the last two elements in dp array, so to 35 | # save space we can use variables to store them. 36 | 37 | def num_ways(n, k) 38 | return 0 if n == 0 39 | d1, d2, d3 = k, k*k 40 | return d1 if n == 1 41 | return d2 if n == 2 42 | (3..n).each do 43 | d3 = (k-1) * (d1+d2) 44 | d1 = d2 45 | d2 = d3 46 | end 47 | d3 48 | end 49 | -------------------------------------------------------------------------------- /28.implement-strstr.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=28 lang=ruby 4 | # 5 | # [28] Implement strStr() 6 | # 7 | # https://leetcode.com/problems/implement-strstr/description/ 8 | # 9 | # Implement strStr(). 10 | # 11 | # Return the index of the first occurrence of needle in haystack, or 12 | # -1 if needle is not part of haystack. 13 | # 14 | # Example 1: 15 | # 16 | # Input: haystack = "hello", needle = "ll" 17 | # Output: 2 18 | # 19 | # Example 2: 20 | # 21 | # Input: haystack = "aaaaa", needle = "bba" 22 | # Output: -1 23 | # 24 | # Clarification: 25 | # 26 | # What should we return when needle is an empty string? This is a 27 | # great question to ask during an interview. 28 | # 29 | # For the purpose of this problem, we will return 0 when needle is an empty 30 | # string. This is consistent to C's strstr() and Java's indexOf(). 31 | 32 | 33 | # Ruby. 34 | 35 | # @param {String} haystack 36 | # @param {String} needle 37 | # @return {Integer} 38 | def str_str(haystack, needle) 39 | needle.empty? ? 0 : haystack.index(needle) || -1 40 | end 41 | 42 | 43 | # Brute Force. 44 | 45 | def str_str(haystack, needle) 46 | return 0 if needle.empty? 47 | return -1 if needle.length > haystack.length 48 | m, n = haystack.size, needle.size 49 | (0..m-n).each do |i| 50 | j, k = i, 0 51 | while j < m && 52 | k < n && 53 | haystack[j] == needle[k] 54 | j += 1 55 | k += 1 56 | end 57 | return i if k == n 58 | end 59 | -1 60 | end 61 | 62 | 63 | # TODO 64 | # - KMP. 65 | # - Rabin-Karp. 66 | # - Boyer-Moore. 67 | -------------------------------------------------------------------------------- /280.wiggle-sort.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=280 lang=ruby 4 | # 5 | # [280] Wiggle Sort 6 | # 7 | # https://leetcode.com/problems/wiggle-sort/description/ 8 | # 9 | # Given an unsorted array nums, reorder it in-place such that nums[0] 10 | # <= nums[1] >= nums[2] <= nums[3].... 11 | # 12 | # For example, given nums = [3, 5, 2, 1, 6, 4], one possible answer is 13 | # [1, 6, 2, 5, 3, 4]. 14 | 15 | 16 | def wiggle_sort(nums) 17 | i, j = 0, 1 18 | while j < nums.size 19 | if i.even? 20 | if nums[i] > nums[j] 21 | swap(nums, i, j) 22 | end 23 | else 24 | if nums[i] < nums[j] 25 | swap(nums, i, j) 26 | end 27 | end 28 | i += 1 29 | j += 1 30 | end 31 | nums 32 | end 33 | 34 | def swap(nums, i, j) 35 | nums[i], nums[j] = nums[j], nums[i] 36 | end 37 | -------------------------------------------------------------------------------- /285.inorder-successor-in-bst.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=285 lang=ruby 4 | # 5 | # [285] Inorder Successor in BST 6 | # 7 | # https://leetcode.com/problems/inorder-successor-in-bst/description/ 8 | # 9 | # Given a binary search tree and a node in it, find the in-order 10 | # successor of that node in the BST. 11 | # 12 | # Note: If the given node has no in-order successor in the tree, 13 | # return null. 14 | 15 | 16 | # See 'ceil' method in data-structures/treap.rb, it's the same except 17 | # it doesn't return itself. 18 | 19 | def inorder_successor(root, p) 20 | return if root.nil? || p.nil? 21 | if p.val >= root.val 22 | inorder_successor(root.right, p) 23 | else 24 | inorder_successor(root.left, p) || root 25 | end 26 | end 27 | -------------------------------------------------------------------------------- /29.divide-two-integers.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=29 lang=ruby 4 | # 5 | # [29] Divide Two Integers 6 | # 7 | # https://leetcode.com/problems/divide-two-integers/description/ 8 | # 9 | # Given two integers dividend and divisor, divide two integers without 10 | # using multiplication, division and mod operator. 11 | # 12 | # Return the quotient after dividing dividend by divisor. 13 | # 14 | # The integer division should truncate toward zero. 15 | # 16 | # Example 1: 17 | # 18 | # Input: dividend = 10, divisor = 3 19 | # Output: 3 20 | # 21 | # Example 2: 22 | # 23 | # Input: dividend = 7, divisor = -3 24 | # Output: -2 25 | # 26 | # Note: 27 | # 28 | # Both dividend and divisor will be 32-bit signed integers. 29 | # The divisor will never be 0. 30 | # Assume we are dealing with an environment which could only store integers 31 | # within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of 32 | # this problem, assume that your function returns 231 − 1 when the division 33 | # result overflows. 34 | 35 | 36 | # Binary Search. 37 | 38 | # @param {Integer} dividend 39 | # @param {Integer} divisor 40 | # @return {Integer} 41 | def divide(dividend, divisor) 42 | if divisor == 1 43 | x = dividend 44 | elsif divisor == -1 45 | x = -dividend 46 | else 47 | d, b = dividend.abs, divisor.abs 48 | x = (0..d).bsearch { |x| (x+1)*b > d } 49 | x = (dividend > 0 && divisor < 0) || (dividend < 0 && divisor > 0) ? -x : x 50 | end 51 | x < -2**31 || x > 2**31-1 ? 2**31-1 : x 52 | end 53 | -------------------------------------------------------------------------------- /292.nim-game.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=292 lang=ruby 4 | # 5 | # [292] Nim Game 6 | # 7 | # https://leetcode.com/problems/nim-game/description/ 8 | # 9 | # You are playing the following Nim Game with your friend: There is a 10 | # heap of stones on the table, each time one of you take turns to 11 | # remove 1 to 3 stones. The one who removes the last stone will be the 12 | # winner. You will take the first turn to remove the stones. 13 | # 14 | # Both of you are very clever and have optimal strategies for the 15 | # game. Write a function to determine whether you can win the game 16 | # given the number of stones in the heap. 17 | # 18 | # Example: 19 | # 20 | # Input: 4 21 | # Output: false 22 | # Explanation: If there are 4 stones in the heap, then you will never 23 | # win the game; No matter 1, 2, or 3 stones you remove, the last stone 24 | # will always be removed by your friend. 25 | 26 | 27 | # @param {Integer} n 28 | # @return {Boolean} 29 | def can_win_nim(n) 30 | (n % 4) != 0 31 | end 32 | -------------------------------------------------------------------------------- /3.longest-substring-without-repeating-characters.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=3 lang=ruby 4 | # 5 | # [3] Longest Substring Without Repeating Characters 6 | # 7 | # https://leetcode.com/problems/longest-substring-without-repeating-characters/description/ 8 | # 9 | # Given a string, find the length of the longest substring without 10 | # repeating characters. 11 | # 12 | # Example 1: 13 | # 14 | # Input: "abcabcbb" 15 | # Output: 3 16 | # Explanation: The answer is "abc", with the length of 3. 17 | # 18 | # Example 2: 19 | # 20 | # Input: "bbbbb" 21 | # Output: 1 22 | # Explanation: The answer is "b", with the length of 1. 23 | # 24 | # Example 3: 25 | # 26 | # Input: "pwwkew" 27 | # Output: 3 28 | # Explanation: The answer is "wke", with the length of 3. ⁠ Note that 29 | # the answer must be a substring, "pwke" is a subsequence and not a 30 | # substring. 31 | 32 | 33 | # The key is to keep a sliding window of substring without repeating 34 | # characters. Example: 35 | # 36 | # given "abcab" 37 | # a b c a b | "a" | 1 | { a: 0 } 38 | # / \ 39 | #i j 40 | # a b c a b | "ab" | 2 | { a: 0, b: 1 } 41 | # | | 42 | # j i 43 | # a b c a b | "abc" | 3 | { a: 0, b: 1, c: 2 } 44 | # | | 45 | # j i 46 | # a b c a b | "bac" | 3 | { a: 3, b: 1, c: 2 } 47 | # | | 48 | # j i 49 | # a b c a b | "cab" | 3 | { a: 3, b: 4, c: 2 } 50 | # | | 51 | # j i 52 | # 53 | # max: 3 54 | 55 | # @param {String} s 56 | # @return {Integer} 57 | def length_of_longest_substring(s) 58 | result = 0 59 | hash = {} 60 | j = 0 61 | for i in 0...s.length 62 | if hash.has_key?(s[i]) 63 | j = [hash[s[i]]+1, j].max 64 | end 65 | result = [i-j+1, result].max 66 | hash[s[i]] = i 67 | end 68 | result 69 | end 70 | -------------------------------------------------------------------------------- /303.range-sum-query-immutable.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=303 lang=ruby 4 | # 5 | # [303] Range Sum Query - Immutable 6 | # 7 | # https://leetcode.com/problems/range-sum-query-immutable/description/ 8 | # 9 | # Given an integer array nums, find the sum of the elements between 10 | # indices i and j (i ≤ j), inclusive. 11 | # 12 | # Example: 13 | # 14 | # Given nums = [-2, 0, 3, -5, 2, -1] 15 | # 16 | # sumRange(0, 2) -> 1 17 | # sumRange(2, 5) -> -1 18 | # sumRange(0, 5) -> -3 19 | # 20 | # Note: 21 | # 22 | # You may assume that the array does not change. 23 | # There are many calls to sumRange function. 24 | 25 | 26 | # table[i]: the current acumulate sum of [0, i). 27 | # so that: range(i, j) = sum[0, j+1) - sum[0, i) 28 | 29 | class NumArray 30 | 31 | def initialize(nums) 32 | @table = Array.new(nums.count + 1) 33 | @table[0] = 0 34 | nums.each_with_index do |n, i| 35 | @table[i+1] = @table[i] + n 36 | end 37 | end 38 | 39 | def sum_range(i, j) 40 | return @table[j + 1] - @table[i] 41 | end 42 | end 43 | -------------------------------------------------------------------------------- /31.next-permutation.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=31 lang=ruby 4 | # 5 | # [31] Next Permutation 6 | # 7 | # https://leetcode.com/problems/next-permutation/description/ 8 | # 9 | # Implement next permutation, which rearranges numbers into the 10 | # lexicographically next greater permutation of numbers. 11 | # 12 | # If such arrangement is not possible, it must rearrange it as the 13 | # lowest possible order (ie, sorted in ascending order). 14 | # 15 | # The replacement must be in-place and use only constant extra memory. 16 | # 17 | # Here are some examples. Inputs are in the left-hand column and its 18 | # corresponding outputs are in the right-hand column. 19 | # 20 | # 1,2,3 → 1,3,2 21 | # 3,2,1 → 1,2,3 22 | # 1,1,5 → 1,5,1 23 | 24 | 25 | # See https://en.wikipedia.org/wiki/Permutation#Generation_in_lexicographic_order 26 | 27 | # @param {Integer[]} nums 28 | # @return {Void} Do not return anything, modify nums in-place instead. 29 | def next_permutation(nums) 30 | n, k, l = nums.size 31 | (n-2).downto(0).each do |i| 32 | k = i and break if nums[i] < nums[i+1] 33 | end 34 | nums.sort! and return if k.nil? 35 | (n-1).downto(k+1).each do |i| 36 | l = i and break if nums[i] > nums[k] 37 | end 38 | swap(nums, k, l) 39 | reverse(nums, k+1, n-1) 40 | end 41 | 42 | def swap(nums, i, j) 43 | nums[i], nums[j] = nums[j], nums[i] 44 | end 45 | 46 | def reverse(nums, i, j) 47 | until i > j 48 | swap(nums, i, j) 49 | i += 1 50 | j -= 1 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /32.longest-valid-parentheses.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=32 lang=ruby 4 | # 5 | # [32] Longest Valid Parentheses 6 | # 7 | # https://leetcode.com/problems/longest-valid-parentheses/description/ 8 | # 9 | # Given a string containing just the characters '(' and ')', find the 10 | # length of the longest valid (well-formed) parentheses substring. 11 | # 12 | # Example 1: 13 | # 14 | # Input: "(()" 15 | # Output: 2 16 | # Explanation: The longest valid parentheses substring is "()" 17 | # 18 | # Example 2: 19 | # 20 | # Input: ")()())" 21 | # Output: 4 22 | # Explanation: The longest valid parentheses substring is "()()" 23 | 24 | 25 | # dp[i]: the longest valid substring ending at s[i]. 26 | # 27 | # We have dp.size = s.size+1 and dp[-1]=0 so that we don't have to 28 | # check i-2 > 0. 29 | 30 | # @param {String} s 31 | # @return {Integer} 32 | def longest_valid_parentheses(s) 33 | dp, ans = Array.new(s.size+1, 0), 0 34 | (1...s.size).each do |i| 35 | next if s[i] == '(' 36 | if s[i-1] == '(' 37 | dp[i] = dp[i-2] + 2 38 | elsif i-dp[i-1] > 0 && s[i-dp[i-1]-1] == '(' 39 | dp[i] = dp[i-dp[i-1]-2] + dp[i-1] + 2 40 | end 41 | ans = [ans, dp[i]].max 42 | end 43 | ans 44 | end 45 | 46 | 47 | # Another variation of this problem: 48 | # 49 | # See: other/longest-subsequence-of-balanced-parentheses.rb 50 | -------------------------------------------------------------------------------- /33.search-in-rotated-sorted-array.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=33 lang=ruby 4 | # 5 | # [33] Search in Rotated Sorted Array 6 | # 7 | # https://leetcode.com/problems/search-in-rotated-sorted-array/description/ 8 | # 9 | # Suppose an array sorted in ascending order is rotated at some pivot 10 | # unknown to you beforehand. 11 | # 12 | # (i.e., [0,1,2,4,5,6,7] might become [4,5,6,7,0,1,2]). 13 | # 14 | # You are given a target value to search. If found in the array return 15 | # its index, otherwise return -1. 16 | # 17 | # You may assume no duplicate exists in the array. 18 | # 19 | # Your algorithm's runtime complexity must be in the order of O(log n). 20 | # 21 | # Example 1: 22 | # 23 | # Input: nums = [4,5,6,7,0,1,2], target = 0 24 | # Output: 4 25 | # 26 | # Example 2: 27 | # 28 | # Input: nums = [4,5,6,7,0,1,2], target = 3 29 | # Output: -1 30 | 31 | 32 | # Here are all the possible search condition: 33 | # 34 | # [4,5,6,7,0,1,2] 35 | # mid >= left 36 | # - x=left then go left 37 | # - else got right 38 | # [5,6,0,1,2,3,4] 39 | # mid < left 40 | # - x>mid && x<=right then go right 41 | # - else go left 42 | 43 | # @param {Integer[]} nums 44 | # @param {Integer} target 45 | # @return {Integer} 46 | def search(nums, target) 47 | i, j = 0, nums.length-1 48 | while i <= j 49 | mid = (i + j) / 2 50 | if nums[mid] == target 51 | return mid 52 | elsif nums[mid] >= nums[i] 53 | if target < nums[mid] && target >= nums[i] 54 | j = mid - 1 55 | else 56 | i = mid + 1 57 | end 58 | else 59 | if target <= nums[j] && target > nums[mid] 60 | i = mid + 1 61 | else 62 | j = mid - 1 63 | end 64 | end 65 | end 66 | -1 67 | end 68 | 69 | -------------------------------------------------------------------------------- /339.nested-list-weight-sum.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=339 lang=ruby 4 | # 5 | # [339] Nested List Weight Sum 6 | # 7 | # https://leetcode.com/problems/nested-list-weight-sum/description/ 8 | # 9 | # Given a nested list of integers, return the sum of all integers in 10 | # the list weighted by their depth. 11 | # 12 | # Each element is either an integer, or a list -- whose elements may 13 | # also be integers or other lists. 14 | # 15 | # Example 1: 16 | # Given the list [[1,1],2,[1,1]], return 10. 17 | # (four 1's at depth 2, one 2 at depth 1) 18 | # 19 | # Example 2: 20 | # Given the list [1,[4,[6]]], return 27. 21 | # (one 1 at depth 1, one 4 at depth 2, and one 6 at depth 3; 1 + 4*2 + 6*3 = 27) 22 | 23 | def depth_sum(list, d=1) 24 | list.reduce(0) do |s, n| 25 | if n.is_a? Array 26 | s += depth_sum(n, d+1) 27 | else 28 | s += n * d 29 | end 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /34.find-first-and-last-position-of-element-in-sorted-array.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=34 lang=ruby 4 | # 5 | # [34] Find First and Last Position of Element in Sorted Array 6 | # 7 | # https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/description/ 8 | # 9 | # Given an array of integers nums sorted in ascending order, find the 10 | # starting and ending position of a given target value. 11 | # 12 | # Your algorithm's runtime complexity must be in the order of O(log n). 13 | # 14 | # If the target is not found in the array, return [-1, -1]. 15 | # 16 | # Example 1: 17 | # 18 | # Input: nums = [5,7,7,8,8,10], target = 8 19 | # Output: [3,4] 20 | # 21 | # Example 2: 22 | # 23 | # Input: nums = [5,7,7,8,8,10], target = 6 24 | # Output: [-1,-1] 25 | 26 | 27 | # Binary Search. 28 | 29 | # @param {Integer[]} nums 30 | # @param {Integer} target 31 | # @return {Integer[]} 32 | def search_range(nums, target) 33 | i = nums.bsearch_index { |x| x >= target } 34 | return [-1, -1] if i.nil? || nums[i] != target 35 | j = i 36 | j += 1 while nums[j] == target 37 | [i, j-1] 38 | end 39 | -------------------------------------------------------------------------------- /344.reverse-string.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=344 lang=ruby 4 | # 5 | # [344] Reverse String 6 | # 7 | # https://leetcode.com/problems/reverse-string/description/ 8 | # 9 | # Write a function that reverses a string. The input string is given 10 | # as an array of characters char[]. 11 | # 12 | # Do not allocate extra space for another array, you must do this by 13 | # modifying the input array in-place with O(1) extra memory. 14 | # 15 | # You may assume all the characters consist of printable ascii characters. 16 | # 17 | # Example 1: 18 | # 19 | # Input: ["h","e","l","l","o"] 20 | # Output: ["o","l","l","e","h"] 21 | # 22 | # Example 2: 23 | # 24 | # Input: ["H","a","n","n","a","h"] 25 | # Output: ["h","a","n","n","a","H"] 26 | 27 | 28 | # @param {Character[]} s 29 | # @return {Void} Do not return anything, modify s in-place instead. 30 | def reverse_string(s) 31 | i, j = 0, s.length-1 32 | until i > j 33 | s[i], s[j] = s[j], s[i] 34 | i += 1 35 | j -= 1 36 | end 37 | s 38 | end 39 | -------------------------------------------------------------------------------- /346.moving-average-from-data-stream.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=346 lang=ruby 4 | # 5 | # [346] Moving Average from Data Stream 6 | # 7 | # https://leetcode.com/problems/moving-average-from-data-stream/description/ 8 | # 9 | # Given a stream of integers and a window size, calculate the moving average of all integers in the sliding window. 10 | # 11 | # For example, 12 | # MovingAverage m = new MovingAverage(3); 13 | # m.next(1) = 1 14 | # m.next(10) = (1 + 10) / 2 15 | # m.next(3) = (1 + 10 + 3) / 3 16 | # m.next(5) = (10 + 3 + 5) / 3 17 | 18 | class MovingAverage 19 | 20 | def initialize(size) 21 | @q, @size, @sum = [], size, 0 22 | end 23 | 24 | def next(val) 25 | if @q.size == @size 26 | @sum -= @q.pop 27 | end 28 | @q.unshift(val) 29 | @sum += val 30 | @sum.fdiv(@q.size) 31 | end 32 | end 33 | -------------------------------------------------------------------------------- /35.search-insert-position.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=35 lang=ruby 4 | # 5 | # [35] Search Insert Position 6 | # 7 | # https://leetcode.com/problems/search-insert-position/description/ 8 | # 9 | # Given a sorted array and a target value, return the index if the 10 | # target is found. If not, return the index where it would be if it 11 | # were inserted in order. 12 | # 13 | # You may assume no duplicates in the array. 14 | # 15 | # Example 1: 16 | # 17 | # Input: [1,3,5,6], 5 18 | # Output: 2 19 | # 20 | # Example 2: 21 | # 22 | # Input: [1,3,5,6], 2 23 | # Output: 1 24 | # 25 | # Example 3: 26 | # 27 | # Input: [1,3,5,6], 7 28 | # Output: 4 29 | # 30 | # Example 4: 31 | # 32 | # Input: [1,3,5,6], 0 33 | # Output: 0 34 | 35 | 36 | # Binary Search. 37 | 38 | # @param {Integer[]} nums 39 | # @param {Integer} target 40 | # @return {Integer} 41 | def search_insert(nums, target) 42 | nums.bsearch_index { |x| x >= target } || nums.size 43 | end 44 | -------------------------------------------------------------------------------- /371.sum-of-two-integers.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=371 lang=ruby 4 | # 5 | # [371] Sum of Two Integers 6 | # 7 | # https://leetcode.com/problems/sum-of-two-integers/description/ 8 | # 9 | # Calculate the sum of two integers a and b, but you are not allowed 10 | # to use the operator + and -. 11 | # 12 | # Example 1: 13 | # 14 | # Input: a = 1, b = 2 15 | # Output: 3 16 | # 17 | # Example 2: 18 | # 19 | # Input: a = -2, b = 3 20 | # Output: 1 21 | 22 | 23 | # See: https://www.youtube.com/watch?v=qq64FrA2UXQ 24 | 25 | # @param {Integer} a 26 | # @param {Integer} b 27 | # @return {Integer} 28 | def get_sum(a, b) 29 | a = [a].pack('l').unpack('l').first 30 | b = [b].pack('l').unpack('l').first 31 | get_sum_32bit(a, b) 32 | end 33 | 34 | def get_sum_32bit(a, b) 35 | return a if b.zero? 36 | return b if a.zero? 37 | get_sum(a^b, (a&b)<<1) 38 | end 39 | -------------------------------------------------------------------------------- /378.kth-smallest-element-in-a-sorted-matrix.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=378 lang=ruby 4 | # 5 | # [378] Kth Smallest Element in a Sorted Matrix 6 | # 7 | # https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/description/ 8 | # 9 | # Given a n x n matrix where each of the rows and columns are sorted 10 | # in ascending order, find the kth smallest element in the matrix. 11 | # 12 | # Note that it is the kth smallest element in the sorted order, not the kth 13 | # distinct element. 14 | # 15 | # Example: 16 | # 17 | # matrix = [ 18 | # ⁠ [ 1, 5, 9], 19 | # ⁠ [10, 11, 13], 20 | # ⁠ [12, 13, 15] 21 | # ], 22 | # k = 8, 23 | # 24 | # return 13. 25 | # 26 | # Note: You may assume k is always valid, 1 ≤ k ≤ n2. 27 | 28 | 29 | # The first thing that hit my mind, just flatten and sort it... 30 | # Time complexity: O(n+(n^2)*log(n^2)). 31 | 32 | # @param {Integer[][]} matrix 33 | # @param {Integer} k 34 | # @return {Integer} 35 | def kth_smallest_a(matrix, k) 36 | matrix.flatten.sort[k-1] 37 | end 38 | 39 | 40 | # Binary search, given: 41 | # matrix = [ 42 | # ⁠ [ 1, 5, 9], 43 | # ⁠ [10, 11, 13], 44 | # ⁠ [12, 13, 15] 45 | # ], 46 | # 1. k=8, mid=(1+15)/2=8, for each row find the index of the first element that is larger than mid. 47 | # 2. Sum up all the indices, 2+0+0 < k, which mean mid is too big, go 'left' side. 48 | # 3. If it equals k, it means that we have k numbers that smaller or equal than that number, 49 | # which is exactly what we want -- the kth smallest number. 50 | # 51 | # Time complexity: O(n*log(n)*log(max-min)) 52 | 53 | def kth_smallest(matrix, k) 54 | lo, hi = matrix[0][0], matrix[-1][-1] 55 | (lo..hi).bsearch do |m| 56 | matrix.map do |x| 57 | (0..x.length).bsearch { |i| i == x.length || x[i] > m } 58 | end.sum >= k 59 | end 60 | end 61 | -------------------------------------------------------------------------------- /384.shuffle-an-array.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=384 lang=ruby 4 | # 5 | # [384] Shuffle an Array 6 | # 7 | # https://leetcode.com/problems/shuffle-an-array/description/ 8 | # 9 | # Shuffle a set of numbers without duplicates. 10 | # 11 | # Example: 12 | # 13 | # // Init an array with set 1, 2, and 3. 14 | # int[] nums = {1,2,3}; 15 | # Solution solution = new Solution(nums); 16 | # 17 | # // Shuffle the array [1,2,3] and return its result. Any permutation of 18 | # [1,2,3] must equally likely to be returned. 19 | # solution.shuffle(); 20 | # 21 | # // Resets the array back to its original configuration [1,2,3]. 22 | # solution.reset(); 23 | # 24 | # // Returns the random shuffling of array [1,2,3]. 25 | # solution.shuffle(); 26 | 27 | 28 | class Solution 29 | 30 | def initialize(nums) 31 | @size = nums.size 32 | @nums = nums 33 | @orig = nums.dup 34 | end 35 | 36 | def reset 37 | @nums = @orig 38 | @orig = @orig.dup 39 | end 40 | 41 | def shuffle 42 | @size.times do |i| 43 | swap(i, rand(i..@size-1)) 44 | end 45 | @nums 46 | end 47 | 48 | private 49 | 50 | def swap(i, j) 51 | @nums[i], @nums[j] = @nums[j], @nums[i] 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /387.first-unique-character-in-a-string.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=387 lang=ruby 4 | # 5 | # [387] First Unique Character in a String 6 | # 7 | # https://leetcode.com/problems/first-unique-character-in-a-string/description/ 8 | # 9 | # Given a string, find the first non-repeating character in it and 10 | # return it's index. If it doesn't exist, return -1. 11 | # 12 | # Examples: 13 | # 14 | # s = "leetcode" 15 | # return 0. 16 | # 17 | # s = "loveleetcode", 18 | # return 2. 19 | # 20 | # Note: You may assume the string contain only lowercase letters. 21 | 22 | 23 | # One-liner. 24 | 25 | # @param {String} s 26 | # @return {Integer} 27 | def first_uniq_char(s) 28 | s.chars.each_with_index.reduce(Hash.new { |h, k| h[k] = [0, 0] }) { |h, (c, i)| h[c][0] += 1; h[c][1] = i; h }.each { |c, (f, i)| return i if f == 1 } 29 | -1 30 | end 31 | 32 | 33 | def first_uniq_char(s) 34 | h = s.chars.reduce(Hash.new(0)) { |h, c| h[c] += 1; h } 35 | s.chars.each_with_index do |c, i| 36 | return i if h[c] == 1 37 | end 38 | -1 39 | end 40 | -------------------------------------------------------------------------------- /39.combination-sum.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=39 lang=ruby 4 | # 5 | # [39] Combination Sum 6 | # 7 | # https://leetcode.com/problems/combination-sum/description/ 8 | # 9 | # Given a set of candidate numbers (candidates) (without duplicates) 10 | # and a target number (target), find all unique combinations in 11 | # candidates where the candidate numbers sums to target. 12 | # 13 | # The same repeated number may be chosen from candidates unlimited 14 | # number of times. 15 | # 16 | # Note: 17 | # 18 | # All numbers (including target) will be positive integers. The 19 | # solution set must not contain duplicate combinations. 20 | # 21 | # Example 1: 22 | # 23 | # Input: candidates = [2,3,6,7], target = 7, 24 | # A solution set is: 25 | # [ 26 | # ⁠ [7], 27 | # ⁠ [2,2,3] 28 | # ] 29 | # 30 | # Example 2: 31 | # 32 | # Input: candidates = [2,3,5], target = 8, 33 | # A solution set is: 34 | # [ 35 | # [2,2,2,2], 36 | # [2,3,3], 37 | # [3,5] 38 | # ] 39 | 40 | 41 | # DFS+Backtracking. 42 | # 43 | # 1. why (k..n-1)? Cuz we don't want to reuse item: Given, 44 | # a=[2,3,5],target=8, if we aleady found 3+5==8, we don't want to 45 | # consider 5+3. 46 | # 2. why recurring on the same i? Cuz we want to reuse the same item. 47 | 48 | # @param {Integer[]} candidates 49 | # @param {Integer} target 50 | # @return {Integer[][]} 51 | def combination_sum(candidates, target, k=0, sum=0, path=[], paths=[]) 52 | return [] if candidates.empty? 53 | return if sum > target 54 | if sum == target 55 | paths << path.dup 56 | else 57 | (k..candidates.size-1).each do |i| 58 | x = candidates[i] 59 | path << x 60 | combination_sum(candidates, target, i, sum+x, path, paths) 61 | path.pop 62 | end 63 | end 64 | paths 65 | end 66 | -------------------------------------------------------------------------------- /40.combination-sum-ii.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=40 lang=ruby 4 | # 5 | # [40] Combination Sum II 6 | # 7 | # https://leetcode.com/problems/combination-sum-ii/description/ 8 | # 9 | # Given a collection of candidate numbers (candidates) and a target 10 | # number (target), find all unique combinations in candidates where 11 | # the candidate numbers sums to target. 12 | # 13 | # Each number in candidates may only be used once in the combination. 14 | # 15 | # Note: 16 | # 17 | # All numbers (including target) will be positive integers. 18 | # The solution set must not contain duplicate combinations. 19 | # 20 | # Example 1: 21 | # 22 | # Input: candidates = [10,1,2,7,6,1,5], target = 8, 23 | # A solution set is: 24 | # [ 25 | # ⁠ [1, 7], 26 | # ⁠ [1, 2, 5], 27 | # ⁠ [2, 6], 28 | # ⁠ [1, 1, 6] 29 | # ] 30 | # 31 | # Example 2: 32 | # 33 | # Input: candidates = [2,5,2,1,2], target = 5, 34 | # A solution set is: 35 | # [ 36 | # [1,2,2], 37 | # [5] 38 | # ] 39 | 40 | 41 | # DFS+Backtracking. 42 | 43 | # @param {Integer[]} candidates 44 | # @param {Integer} target 45 | # @return {Integer[][]} 46 | def combination_sum2(candidates, target) 47 | dfs(candidates.sort, target) 48 | end 49 | 50 | def dfs(a, target, k=0, sum=0, path=[], paths=[]) 51 | return [] if a.empty? 52 | return if sum > target 53 | if sum == target 54 | paths << path.dup 55 | else 56 | (k..a.size-1).each do |i| 57 | next if i > k && a[i] == a[i-1] 58 | path << a[i] 59 | dfs(a, target, i+1, sum+a[i], path, paths) 60 | path.pop 61 | end 62 | end 63 | paths 64 | end 65 | -------------------------------------------------------------------------------- /409.longest-palindrome.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=409 lang=ruby 4 | # 5 | # [409] Longest Palindrome 6 | # 7 | # https://leetcode.com/problems/longest-palindrome/description/ 8 | # 9 | # Given a string which consists of lowercase or uppercase letters, find the 10 | # length of the longest palindromes that can be built with those letters. 11 | # 12 | # This is case sensitive, for example "Aa" is not considered a palindrome here. 13 | # 14 | # Note: Assume the length of given string will not exceed 1,010. 15 | # 16 | # Example: 17 | # 18 | # Input: 19 | # "abccccdd" 20 | # Output: 21 | # 7 22 | # Explanation: 23 | # One longest palindrome that can be built is "dccaccd", whose length is 7. 24 | 25 | 26 | # @param {String} s 27 | # @return {Integer} 28 | def longest_palindrome(s) 29 | t, ans = Set.new, 0 30 | s.chars.each do |c| 31 | if t.include?(c) 32 | t.delete(c) 33 | ans += 2 34 | else 35 | t << c 36 | end 37 | end 38 | ans == s.length ? ans : ans+1 39 | end 40 | -------------------------------------------------------------------------------- /41.first-missing-positive.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=41 lang=ruby 4 | # 5 | # [41] First Missing Positive 6 | # 7 | # https://leetcode.com/problems/first-missing-positive/description/ 8 | # 9 | # Given an unsorted integer array, find the smallest missing positive integer. 10 | # 11 | # Example 1: 12 | # 13 | # Input: [1,2,0] 14 | # Output: 3 15 | # 16 | # Example 2: 17 | # 18 | # Input: [3,4,-1,1] 19 | # Output: 2 20 | # 21 | # Example 3: 22 | # 23 | # Input: [7,8,9,11,12] 24 | # Output: 1 25 | # 26 | # Note: 27 | # 28 | # Your algorithm should run in O(n) time and uses constant extra space. 29 | 30 | 31 | # O(n) space. 32 | 33 | # @param {Integer[]} nums 34 | # @return {Integer} 35 | def first_missing_positive(nums) 36 | s = nums.size 37 | xs = Array.new(s+1) 38 | nums.each do |n| 39 | xs[n] = n if n > 0 && n <= s 40 | end 41 | (1..s).each do |i| 42 | return i if xs[i].nil? 43 | end 44 | xs.size 45 | end 46 | 47 | 48 | # O(1) space. 49 | 50 | def first_missing_positive(nums) 51 | s = nums.size 52 | (0..s-1).each do |i| 53 | while nums[i] > 0 && nums[i] <= s && nums[nums[i]-1] != nums[i] 54 | nums[nums[i]-1], nums[i] = nums[i], nums[nums[i]-1] 55 | end 56 | end 57 | (0..s-1).each do |i| 58 | return i+1 if nums[i] != i+1 59 | end 60 | s+1 61 | end 62 | -------------------------------------------------------------------------------- /416.partition-equal-subset-sum.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=416 lang=ruby 4 | # 5 | # [416] Partition Equal Subset Sum 6 | # 7 | # https://leetcode.com/problems/partition-equal-subset-sum/description/ 8 | # 9 | # Given a non-empty array containing only positive integers, find if 10 | # the array can be partitioned into two subsets such that the sum of 11 | # elements in both subsets is equal. 12 | # 13 | # Note: 14 | # 15 | # Each of the array element will not exceed 100. 16 | # The array size will not exceed 200. 17 | # 18 | # Example 1: 19 | # 20 | # Input: [1, 5, 11, 5] 21 | # Output: true 22 | # Explanation: The array can be partitioned as [1, 5, 5] and [11]. 23 | # 24 | # Example 2: 25 | # 26 | # Input: [1, 2, 3, 5] 27 | # Output: false 28 | # Explanation: The array cannot be partitioned into equal sum subsets. 29 | 30 | 31 | # DFS+Memo. 32 | 33 | # @param {Integer[]} nums 34 | # @return {Boolean} 35 | def can_partition(nums) 36 | t, r = nums.sum.divmod(2) 37 | return false if !r.zero? 38 | dfs(nums, t) 39 | end 40 | 41 | def dfs(nums, target, k=0, sum=0, memo={}) 42 | return memo[sum] if memo.has_key?(sum) 43 | if sum > target 44 | memo[sum] = false 45 | elsif sum == target 46 | memo[sum] = true 47 | else 48 | (k..nums.size-1).each do |i| 49 | if dfs(nums, target, i+1, sum+nums[i], memo) 50 | memo[sum] = true 51 | return true 52 | end 53 | end 54 | memo[sum] = false 55 | end 56 | memo[sum] 57 | end 58 | 59 | 60 | # DP. 61 | 62 | def can_partition(nums) 63 | t, r = nums.sum.divmod(2) 64 | return false if !r.zero? 65 | d = Array.new(nums.size+1) { Array.new(t+1, false) } 66 | d[0][0] = true 67 | (1..nums.size).each do |i| 68 | (0..t).each do |j| 69 | d[i][j] = d[i-1][j] 70 | d[i][j] ||= d[i][j-nums[i-1]] if nums[i-1] <= j 71 | end 72 | end 73 | d[nums.size][t] 74 | end 75 | -------------------------------------------------------------------------------- /442.find-all-duplicates-in-an-array.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=442 lang=ruby 4 | # 5 | # [442] Find All Duplicates in an Array 6 | # 7 | # https://leetcode.com/problems/find-all-duplicates-in-an-array/description/ 8 | # 9 | # Given an array of integers, 1 ≤ a[i] ≤ n (n = size of array), some 10 | # elements appear twice and others appear once. 11 | # 12 | # Find all the elements that appear twice in this array. 13 | # 14 | # Could you do it without extra space and in O(n) runtime? 15 | # 16 | # Example: 17 | # 18 | # Input: 19 | # [4,3,2,7,8,2,3,1] 20 | # 21 | # Output: 22 | # [2,3] 23 | 24 | 25 | # Hash. 26 | 27 | # @param {Integer[]} nums 28 | # @return {Integer[]} 29 | def find_duplicates(nums) 30 | freq = nums.reduce(Hash.new(0)) { |h, n| h[n] += 1; h } 31 | freq.select { |k, v| v >= 2 }.keys 32 | end 33 | 34 | 35 | # O(1) 36 | 37 | def find_duplicates(nums) 38 | ans = [] 39 | nums.each do |n| 40 | if nums[n.abs-1] < 0 41 | ans << n.abs 42 | else 43 | nums[n.abs-1] *= -1 44 | end 45 | end 46 | ans 47 | end 48 | -------------------------------------------------------------------------------- /451.sort-characters-by-frequency.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=451 lang=ruby 4 | # 5 | # [451] Sort Characters By Frequency 6 | # 7 | # https://leetcode.com/problems/sort-characters-by-frequency/description/ 8 | # 9 | # Given a string, sort it in decreasing order based on the frequency 10 | # of characters. 11 | # 12 | # Example 1: 13 | # 14 | # Input: 15 | # "tree" 16 | # Output: 17 | # "eert" 18 | # Explanation: 19 | # 'e' appears twice while 'r' and 't' both appear once. So 'e' must 20 | # appear before both 'r' and 't'. Therefore "eetr" is also a valid 21 | # answer. 22 | # 23 | # Example 2: 24 | # 25 | # Input: 26 | # "cccaaa" 27 | # Output: 28 | # "cccaaa" 29 | # Explanation: 30 | # Both 'c' and 'a' appear three times, so "aaaccc" is also a valid 31 | # answer. Note that "cacaca" is incorrect, as the same characters must 32 | # be together. 33 | # 34 | # Example 3: 35 | # 36 | # Input: 37 | # "Aabb" 38 | # Output: 39 | # "bbAa" 40 | # Explanation: 41 | # "bbaA" is also a valid answer, but "Aabb" is incorrect. Note that 42 | # 'A' and 'a' are treated as two different characters. 43 | 44 | 45 | # Bucket sort. 46 | 47 | # @param {String} s 48 | # @return {String} 49 | def frequency_sort(s) 50 | freq = s.chars.reduce(Hash.new(0)) { |h, k| h[k] += 1; h } 51 | buckets = Array.new(s.size+1) {[]} 52 | freq.each { |n, c| buckets[c] << n } 53 | ans = "" 54 | buckets.each_with_index do |a, i| 55 | a.each do |c| 56 | ans << c*i 57 | end 58 | end 59 | ans.reverse 60 | end 61 | -------------------------------------------------------------------------------- /461.hamming-distance.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=461 lang=ruby 4 | # 5 | # [461] Hamming Distance 6 | # 7 | # https://leetcode.com/problems/hamming-distance/description/ 8 | # 9 | # The Hamming distance between two integers is the number of positions 10 | # at which the corresponding bits are different. 11 | # 12 | # Given two integers x and y, calculate the Hamming distance. 13 | # 14 | # Note: 15 | # 0 ≤ x, y < 231. 16 | # 17 | # Example: 18 | # 19 | # Input: x = 1, y = 4 20 | # Output: 2 21 | # Explanation: 22 | # 1 (0 0 0 1) 23 | # 4 (0 1 0 0) 24 | # ⁠ ↑ ↑ 25 | # 26 | # The above arrows point to positions where the corresponding bits are 27 | # different. 28 | 29 | 30 | # See Fenwick Tree for the idea behind (n & -n). 31 | 32 | # @param {Integer} x 33 | # @param {Integer} y 34 | # @return {Integer} 35 | def hamming_distance(x, y) 36 | n, count = x ^ y, 0 37 | while n > 0 38 | n -= (n & -n) 39 | count += 1 40 | end 41 | count 42 | end 43 | -------------------------------------------------------------------------------- /47.permutations-ii.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=47 lang=ruby 4 | # 5 | # [47] Permutations II 6 | # 7 | # https://leetcode.com/problems/permutations-ii/description/ 8 | # 9 | # Given a collection of numbers that might contain duplicates, return 10 | # all possible unique permutations. 11 | # 12 | # Example: 13 | # 14 | # Input: [1,1,2] 15 | # Output: 16 | # [ 17 | # ⁠ [1,1,2], 18 | # ⁠ [1,2,1], 19 | # ⁠ [2,1,1] 20 | # ] 21 | 22 | 23 | # See problem 46. The idea is not to fix the number we've already fixed. 24 | # 25 | # See https://en.wikipedia.org/wiki/Permutation#Permutations_of_multisets 26 | # 27 | # Example: given "xxy" 28 | # 29 | # - x followed by all permutations of x and y (xy and yx) 30 | # - do not fix the second x in position 0 31 | # - y followed by all permutations of x and x (xx) 32 | 33 | # @param {Integer[]} nums 34 | # @return {Integer[][]} 35 | def permute_unique(nums, k=0, ans=[]) 36 | ans << nums.dup and return if k == nums.size 37 | seen = Set.new 38 | (k...nums.size).each do |i| 39 | next if seen.include?(nums[i]) 40 | seen << nums[i] 41 | swap(nums, k, i) 42 | permute_unique(nums, k+1, ans) 43 | swap(nums, k, i) 44 | end 45 | ans 46 | end 47 | 48 | def swap(nums, i, j) 49 | nums[i], nums[j] = nums[j], nums[i] 50 | end 51 | 52 | 53 | # DFS+Backtracking. 54 | 55 | def permute_unique(nums, seen=Set.new, path=[], paths=[]) 56 | if path.size == nums.size 57 | paths << path.dup 58 | else 59 | same_level = Set.new 60 | (0..nums.size-1).each do |i| 61 | next if seen.include?(i) || same_level.include?(nums[i]) 62 | seen << i 63 | same_level << nums[i] 64 | path << nums[i] 65 | permute_unique(nums, seen, path, paths) 66 | path.pop 67 | seen.delete(i) 68 | end 69 | end 70 | paths 71 | end 72 | -------------------------------------------------------------------------------- /48.rotate-image.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=48 lang=ruby 4 | # 5 | # [48] Rotate Image 6 | # 7 | # https://leetcode.com/problems/rotate-image/description/ 8 | # 9 | # You are given an n x n 2D matrix representing an image. 10 | # 11 | # Rotate the image by 90 degrees (clockwise). 12 | # 13 | # Note: 14 | # 15 | # You have to rotate the image in-place, which means you have to 16 | # modify the input 2D matrix directly. DO NOT allocate another 2D 17 | # matrix and do the rotation. 18 | # 19 | # Example 1: 20 | # 21 | # Given input matrix = 22 | # [ 23 | # ⁠ [1,2,3], 24 | # ⁠ [4,5,6], 25 | # ⁠ [7,8,9] 26 | # ], 27 | # rotate the input matrix in-place such that it becomes: 28 | # [ 29 | # ⁠ [7,4,1], 30 | # ⁠ [8,5,2], 31 | # ⁠ [9,6,3] 32 | # ] 33 | # 34 | # Example 2: 35 | # 36 | # Given input matrix = 37 | # [ 38 | # ⁠ [ 5, 1, 9,11], 39 | # ⁠ [ 2, 4, 8,10], 40 | # ⁠ [13, 3, 6, 7], 41 | # ⁠ [15,14,12,16] 42 | # ], 43 | # rotate the input matrix in-place such that it becomes: 44 | # [ 45 | # ⁠ [15,13, 2, 5], 46 | # ⁠ [14, 3, 4, 1], 47 | # ⁠ [12, 6, 8, 9], 48 | # ⁠ [16, 7,10,11] 49 | # ] 50 | 51 | 52 | # @param {Integer[][]} matrix 53 | # @return {Void} Do not return anything, modify matrix in-place instead. 54 | def rotate_a(a) 55 | n = a.size 56 | (0...n/2).each do |i| 57 | (i...n-1-i).each do |j| 58 | a[i][j], a[j][n-1-i], a[n-1-i][n-1-j], a[n-1-j][i] = a[n-1-j][i], a[i][j], a[j][n-1-i], a[n-1-i][n-1-j] 59 | end 60 | end 61 | end 62 | 63 | 64 | # 1. Reverse: a[i][j] = a[n-1-i][j]. 65 | # 2. Symmetry: a[n-1-i][j] = a[j][n-1-i]. 66 | 67 | def rotate(a) 68 | n = a.size 69 | a.reverse! 70 | (0...n).each do |i| 71 | (i+1...n).each do |j| 72 | a[i][j], a[j][i] = a[j][i], a[i][j] 73 | end 74 | end 75 | end 76 | -------------------------------------------------------------------------------- /49.group-anagrams.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=49 lang=ruby 4 | # 5 | # [49] Group Anagrams 6 | # 7 | # https://leetcode.com/problems/group-anagrams/description/ 8 | # 9 | # Given an array of strings, group anagrams together. 10 | # 11 | # Example: 12 | # 13 | # Input: ["eat", "tea", "tan", "ate", "nat", "bat"], 14 | # Output: 15 | # [ 16 | # ⁠ ["ate","eat","tea"], 17 | # ⁠ ["nat","tan"], 18 | # ⁠ ["bat"] 19 | # ] 20 | # 21 | # Note: 22 | # 23 | # All inputs will be in lowercase. 24 | # The order of your output does not matter. 25 | 26 | 27 | # Ruby can use mutable object as hash key. 28 | 29 | # @param {String[]} strs 30 | # @return {String[][]} 31 | def group_anagrams_a(strs) 32 | strs.map { |x| [x, x.chars.reduce(Hash.new(0)) { |h, c| h[c] += 1; h }] } 33 | .group_by(&:last).map { |k, vs| vs.map { |v| v.first } } 34 | end 35 | 36 | 37 | # Or use sorted string as identifier. 38 | 39 | def group_anagrams(strs) 40 | strs.group_by { |s| s.chars.sort }.values 41 | end 42 | -------------------------------------------------------------------------------- /5.longest-palindromic-substring.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=5 lang=ruby 4 | # 5 | # [5] Longest Palindromic Substring 6 | # 7 | # https://leetcode.com/problems/longest-palindromic-substring/description/ 8 | # 9 | # Given a string s, find the longest palindromic substring in s. You 10 | # may assume that the maximum length of s is 1000. 11 | # 12 | # Example 1: 13 | # 14 | # Input: "babad" 15 | # Output: "bab" 16 | # Note: "aba" is also a valid answer. 17 | # 18 | # Example 2: 19 | # 20 | # Input: "cbbd" 21 | # Output: "bb" 22 | 23 | 24 | # "cacbbcb": find all segment with the same character. 25 | # "c" "a" "c" "bb" "c" "b" expand each segment: 26 | # "c" "cac" "c" "cbbc" "bcb" "b" 27 | # we have cbbc as longest palindrome. 28 | 29 | # @param {String} s 30 | # @return {String} 31 | def longest_palindrome(s) 32 | longest = "" 33 | i = 0 34 | while i < s.length 35 | j = i + 1 36 | j += 1 while s[j] == s[i] 37 | found = expand(s, i, j-1) 38 | longest = found if found.length >= longest.length 39 | i = j 40 | end 41 | longest 42 | end 43 | 44 | def expand(s, l, r) 45 | while l >= 0 && r < s.length && s[l] == s[r] 46 | l -= 1 47 | r += 1 48 | end 49 | s[(l+1)..(r-1)] 50 | end 51 | -------------------------------------------------------------------------------- /50.powx-n.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=50 lang=ruby 4 | # 5 | # [50] Pow(x, n) 6 | # 7 | # https://leetcode.com/problems/powx-n/description/ 8 | # 9 | # Implement pow(x, n), which calculates x raised to the power n (xn). 10 | # 11 | # Example 1: 12 | # 13 | # Input: 2.00000, 10 14 | # Output: 1024.00000 15 | # 16 | # Example 2: 17 | # 18 | # Input: 2.10000, 3 19 | # Output: 9.26100 20 | # 21 | # Example 3: 22 | # 23 | # Input: 2.00000, -2 24 | # Output: 0.25000 25 | # Explanation: 2-2 = 1/22 = 1/4 = 0.25 26 | # 27 | # Note: 28 | # 29 | # -100.0 < x < 100.0 30 | # n is a 32-bit signed integer, within the range [−231, 231 − 1] 31 | 32 | 33 | # @param {Float} x 34 | # @param {Integer} n 35 | # @return {Float} 36 | def my_pow(x, n) 37 | return 1 if n == 0 38 | return 1.fdiv(my_pow(x, -n)) if n < 0 39 | helper(x, n) 40 | end 41 | 42 | def helper(x, n) 43 | return x if n == 1 44 | m = helper(x, n/2) 45 | n.odd? ? m*m*x : m*m 46 | end 47 | -------------------------------------------------------------------------------- /509.fibonacci-number.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=509 lang=ruby 4 | # 5 | # [509] Fibonacci Number 6 | # 7 | # https://leetcode.com/problems/fibonacci-number/description/ 8 | # 9 | # The Fibonacci numbers, commonly denoted F(n) form a sequence, called 10 | # the Fibonacci sequence, such that each number is the sum of the two 11 | # preceding ones, starting from 0 and 1. That is, 12 | # 13 | # F(0) = 0, F(1) = 1 14 | # F(N) = F(N - 1) + F(N - 2), for N > 1. 15 | # 16 | # Given N, calculate F(N). 17 | # 18 | # Example 1: 19 | # 20 | # Input: 2 21 | # Output: 1 22 | # Explanation: F(2) = F(1) + F(0) = 1 + 0 = 1. 23 | # 24 | # Example 2: 25 | # 26 | # Input: 3 27 | # Output: 2 28 | # Explanation: F(3) = F(2) + F(1) = 1 + 1 = 2. 29 | # 30 | # Example 3: 31 | # 32 | # Input: 4 33 | # Output: 3 34 | # Explanation: F(4) = F(3) + F(2) = 2 + 1 = 3. 35 | # 36 | # Note: 37 | # 38 | # 0 ≤ N ≤ 30. 39 | 40 | 41 | # Ruby magic. 42 | 43 | # @param {Integer} n 44 | # @return {Integer} 45 | def fib(n) 46 | Hash.new { |h, k| h[k] = h[k-1] + h[k-2] }.merge({0=>0, 1=>1})[n] 47 | end 48 | 49 | 50 | # O(1) space. 51 | 52 | def fib_a(n) 53 | d2, d1 = 0, 1 54 | n.times do 55 | d2, d1 = d1, d2+d1 56 | end 57 | d2 58 | end 59 | -------------------------------------------------------------------------------- /515.find-largest-value-in-each-tree-row.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=515 lang=ruby 4 | # 5 | # [515] Find Largest Value in Each Tree Row 6 | # 7 | # https://leetcode.com/problems/find-largest-value-in-each-tree-row/description/ 8 | # 9 | # You need to find the largest value in each row of a binary tree. 10 | # 11 | # Example: 12 | # 13 | # Input: 14 | # ⁠ 1 15 | # ⁠ / \ 16 | # ⁠ 3 2 17 | # ⁠ / \ \ 18 | # ⁠ 5 3 9 19 | # Output: [1, 3, 9] 20 | # 21 | # Definition for a binary tree node. 22 | # class TreeNode 23 | # attr_accessor :val, :left, :right 24 | # def initialize(val) 25 | # @val = val 26 | # @left, @right = nil, nil 27 | # end 28 | # end 29 | 30 | 31 | # See problem 102. 32 | 33 | # @param {TreeNode} root 34 | # @return {Integer[]} 35 | def largest_values(root) 36 | return [] if root.nil? 37 | q, ans = [root], [] 38 | while !q.empty? 39 | max = -Float::INFINITY 40 | q.size.times do 41 | x = q.shift 42 | max = [max, x.val].max 43 | q << x.left unless x.left.nil? 44 | q << x.right unless x.right.nil? 45 | end 46 | ans << max 47 | end 48 | ans 49 | end 50 | -------------------------------------------------------------------------------- /516.longest-palindromic-subsequence.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=516 lang=ruby 4 | # 5 | # [516] Longest Palindromic Subsequence 6 | # 7 | # https://leetcode.com/problems/longest-palindromic-subsequence/description/ 8 | # 9 | # Given a string s, find the longest palindromic subsequence's length 10 | # in s. You may assume that the maximum length of s is 1000. 11 | # 12 | # Example 1: 13 | # Input: "bbbab" 14 | # Output: 4 15 | # One possible longest palindromic subsequence is "bbbb". 16 | # 17 | # Example 2: 18 | # Input: "cbbd" 19 | # Output: 2 20 | # One possible longest palindromic subsequence is "bb". 21 | 22 | 23 | # DP. 24 | # 25 | # 1. dp[i][j]: the length of longest palindrome in s[i..j]. 26 | # 2. dp[i][i] is 1. 27 | # 3. dp[0][s.size-1] is the answer. 28 | 29 | # @param {String} s 30 | # @return {Integer} 31 | def longest_palindrome_subseq(s) 32 | n = s.size 33 | dp = Array.new(n) { Array.new(n, 0) } 34 | (1..n).each do |l| 35 | (0..n-l).each do |i| 36 | j = i+l-1 37 | if i == j 38 | dp[i][j] = 1 39 | elsif s[i] == s[j] 40 | dp[i][j] = dp[i+1][j-1] + 2 41 | else 42 | dp[i][j] = [dp[i+1][j], dp[i][j-1]].max 43 | end 44 | end 45 | end 46 | dp[0][n-1] 47 | end 48 | -------------------------------------------------------------------------------- /52.n-queens-ii.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=52 lang=ruby 4 | # 5 | # [52] N-Queens II 6 | # 7 | # https://leetcode.com/problems/n-queens-ii/description/ 8 | # 9 | # The n-queens puzzle is the problem of placing n queens on an n×n 10 | # chessboard such that no two queens attack each other. 11 | # 12 | # Given an integer n, return the number of distinct solutions to the 13 | # n-queens puzzle. 14 | # 15 | # Example: 16 | # 17 | # Input: 4 18 | # Output: 2 19 | # Explanation: There are two distinct solutions to the 4-queens puzzle as shown 20 | # below. 21 | # [ 22 | # [".Q..", // Solution 1 23 | # "...Q", 24 | # "Q...", 25 | # "..Q."], 26 | # 27 | # ["..Q.", // Solution 2 28 | # "Q...", 29 | # "...Q", 30 | # ".Q.."] 31 | # ] 32 | 33 | 34 | # WTF leetcode, it's the same as problem 51... 35 | 36 | # @param {Integer} n 37 | # @return {Integer} 38 | def total_n_queens(n) 39 | permute((0...n).to_a) 40 | end 41 | 42 | def permute(a, k=0, ans=[0], diags=Set.new) 43 | n = a.size 44 | if k == n 45 | ans[0] += 1 46 | return 47 | end 48 | (k...n).each do |i| 49 | next if !valid_move(a, k, i, diags) # k: row, a[i]: column 50 | swap(a, k, i) 51 | make_move(a, k, diags) 52 | permute(a, k+1, ans, diags) 53 | undo_move(a, k, diags) 54 | swap(a, k, i) 55 | end 56 | ans[0] 57 | end 58 | 59 | def swap(a, i, j) 60 | a[i], a[j] = a[j], a[i] 61 | end 62 | 63 | def make_move(a, k, diags) 64 | diags << a[k]+k << a[k]-k-a.size-1 65 | end 66 | 67 | def undo_move(a, k, diags) 68 | diags.delete(a[k]+k) 69 | diags.delete(a[k]-k-a.size-1) 70 | end 71 | 72 | def valid_move(a, k, i, diags) 73 | !diags.include?(a[i]-k-a.size-1) && !diags.include?(a[i]+k) 74 | end 75 | -------------------------------------------------------------------------------- /535.encode-and-decode-tinyurl.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=535 lang=ruby 4 | # 5 | # [535] Encode and Decode TinyURL 6 | # 7 | # https://leetcode.com/problems/encode-and-decode-tinyurl/description/ 8 | # 9 | # Note: This is a companion problem to the System Design problem: 10 | # Design TinyURL. 11 | # 12 | # TinyURL is a URL shortening service where you enter a URL such as 13 | # https://leetcode.com/problems/design-tinyurl and it returns a short 14 | # URL such as http://tinyurl.com/4e9iAk. 15 | # 16 | # Design the encode and decode methods for the TinyURL service. There 17 | # is no restriction on how your encode/decode algorithm should work. 18 | # You just need to ensure that a URL can be encoded to a tiny URL and 19 | # the tiny URL can be decoded to the original URL. 20 | 21 | 22 | @h = {} 23 | @codes = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 24 | 25 | def rand_key 26 | "".tap do |r| 27 | 6.times do 28 | r << @codes[rand(@codes.size)] 29 | end 30 | end 31 | end 32 | 33 | # Encodes a URL to a shortened URL. 34 | # 35 | # @param {string} longUrl 36 | # @return {string} 37 | def encode(longUrl) 38 | key = rand_key 39 | key = rand_key while @h.has_key?(key) 40 | @h[key] = longUrl 41 | "http://tinyurl.com/#{key}" 42 | end 43 | 44 | # Decodes a shortened URL to its original URL. 45 | # 46 | # @param {string} shortUrl 47 | # @return {string} 48 | def decode(shortUrl) 49 | @h[shortUrl.gsub("http://tinyurl.com/", "")] 50 | end 51 | -------------------------------------------------------------------------------- /54.spiral-matrix.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=54 lang=ruby 4 | # 5 | # [54] Spiral Matrix 6 | # 7 | # https://leetcode.com/problems/spiral-matrix/description/ 8 | # 9 | # Given a matrix of m x n elements (m rows, n columns), return all 10 | # elements of the matrix in spiral order. 11 | # 12 | # Example 1: 13 | # 14 | # Input: 15 | # [ 16 | # ⁠[ 1, 2, 3 ], 17 | # ⁠[ 4, 5, 6 ], 18 | # ⁠[ 7, 8, 9 ] 19 | # ] 20 | # Output: [1,2,3,6,9,8,7,4,5] 21 | # 22 | # Example 2: 23 | # 24 | # Input: 25 | # [ 26 | # ⁠ [1, 2, 3, 4], 27 | # ⁠ [5, 6, 7, 8], 28 | # ⁠ [9,10,11,12] 29 | # ] 30 | # Output: [1,2,3,4,8,12,11,10,9,5,6,7] 31 | 32 | 33 | # for loop practice... 34 | 35 | # @param {Integer[][]} matrix 36 | # @return {Integer[]} 37 | def spiral_order(matrix) 38 | return [] if matrix.empty? 39 | helper(matrix) 40 | end 41 | 42 | def helper(matrix, si=0, sj=0, ei=matrix.size-1, ej=matrix[0].size-1, ans=[]) 43 | return if si > ei 44 | return if sj > ej 45 | (sj..ej).each { |x| ans << matrix[si][x] } 46 | (si+1..ei).each { |x| ans << matrix[x][ej] } 47 | (sj..ej-1).reverse_each { |x| ans << matrix[ei][x] } if ei != si 48 | (si+1..ei-1).reverse_each { |x| ans << matrix[x][sj] } if ej != sj 49 | helper(matrix, si+1, sj+1, ei-1, ej-1, ans) 50 | ans 51 | end 52 | -------------------------------------------------------------------------------- /548.split-array-with-equal-sum.rb: -------------------------------------------------------------------------------- 1 | # Given an array with n integers, you need to find if there are 2 | # triplets (i, j, k) which satisfies following conditions: 3 | # 4 | # 0 < i, i + 1 < j, j + 1 < k < n - 1, sum of subarrays (0, i - 1), (i 5 | # + 1, j - 1), (j + 1, k - 1) and (k + 1, n - 1) should be equal. 6 | # where we define that subarray (L, R) represents a slice of the 7 | # original array starting from the element indexed L to the element 8 | # indexed R. 9 | # 10 | # Example: 11 | # 12 | # Input: [1,2,1,2,1,2,1] 13 | # Output: True 14 | # Explanation: 15 | # i = 1, j = 3, k = 5. 16 | # sum(0, i - 1) = sum(0, 0) = 1 17 | # sum(i + 1, j - 1) = sum(2, 2) = 1 18 | # sum(j + 1, k - 1) = sum(4, 4) = 1 19 | # sum(k + 1, n - 1) = sum(6, 6) = 1 20 | 21 | 22 | # 0,i-1, i, i+1,j-1, j, j+1,k-1, k, k+1,n-1 23 | 24 | def split_array(nums) 25 | n = nums.size 26 | return false if n < 7 27 | sum = nums.inject([]) { |a, n| a << (a[-1]||0)+n } << 0 28 | range_sum = ->(i, j) { sum[j] - sum[i-1] } 29 | (3..n-4).each do |j| 30 | st = Set.new 31 | (1..j-2).each do |i| 32 | st << range_sum[0, i-1] if range_sum[0, i-1] == range_sum[i+1, j-1] 33 | end 34 | (j+2..n-2).each do |k| 35 | return true if range_sum[k+1, n-1] == range_sum[j+1, k-1] && 36 | st.include?(range_sum[j+1, k-1]) 37 | end 38 | end 39 | false 40 | end 41 | -------------------------------------------------------------------------------- /560.subarray-sum-equals-k.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=560 lang=ruby 4 | # 5 | # [560] Subarray Sum Equals K 6 | # 7 | # https://leetcode.com/problems/subarray-sum-equals-k/description/ 8 | # 9 | # Given an array of integers and an integer k, you need to find the 10 | # total number of continuous subarrays whose sum equals to k. 11 | # 12 | # Example 1: 13 | # 14 | # Input:nums = [1,1,1], k = 2 15 | # Output: 2 16 | # 17 | # Note: The length of the array is in range [1, 20,000]. The range of 18 | # numbers in the array is [-1000, 1000] and the range of the integer k 19 | # is [-1e7, 1e7]. 20 | 21 | 22 | # Hash+Prefix Sum 23 | # 24 | # 1. s is the prefix sum array, s[i]=nums[0]+...+nums[i-1]. 25 | # 2. Range sum from i to j: nums[i]+...nums[j]=s[j]-s[i-1]. 26 | # 3. So we want s[j]-s[i-1]==k, for all 0<=i<=j<=n-1. in other 27 | # words, we want s[j]-k=s[i-1], so we scan nums from left to 28 | # right, at each index j, we check how many s[j]-k exists before 29 | # j, and use hash to check it with efficiency ({ s[j]: count }). 30 | 31 | # @param {Integer[]} nums 32 | # @param {Integer} k 33 | # @return {Integer} 34 | def subarray_sum(nums, k) 35 | h = Hash.new(0) 36 | h[0] = 1 37 | sum, count = 0, 0 38 | nums.each do |n| 39 | sum += n 40 | count += h[sum-k] 41 | h[sum] += 1 42 | end 43 | count 44 | end 45 | -------------------------------------------------------------------------------- /57.insert-interval.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=57 lang=ruby 4 | # 5 | # [57] Insert Interval 6 | # 7 | # https://leetcode.com/problems/insert-interval/description/ 8 | # 9 | # Given a set of non-overlapping intervals, insert a new interval into 10 | # the intervals (merge if necessary). 11 | # 12 | # You may assume that the intervals were initially sorted according to 13 | # their start times. 14 | # 15 | # Example 1: 16 | # 17 | # Input: intervals = [[1,3],[6,9]], newInterval = [2,5] 18 | # Output: [[1,5],[6,9]] 19 | # 20 | # Example 2: 21 | # 22 | # Input: intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8] 23 | # Output: [[1,2],[3,10],[12,16]] 24 | # Explanation: Because the new interval [4,8] overlaps with [3,5],[6,7],[8,10]. 25 | # 26 | # Definition for an interval. 27 | # class Interval 28 | # attr_accessor :start, :end 29 | # def initialize(s=0, e=0) 30 | # @start = s 31 | # @end = e 32 | # end 33 | # end 34 | 35 | 36 | # 1. Find first interval x that x.end >= new_interval.start, meaning 37 | # that x overlaps with new_interval. 38 | # 2. Find first interval y that y.start > new_interval.end, meaning 39 | # that the y doesn't overlap with new_interval and previous interval 40 | # could overlap with y if it exists. 41 | # 3. Intervals between x and y-1 are the overlapping intervals. 42 | 43 | # @param {Interval[]} intervals 44 | # @param {Interval} new_interval 45 | # @return {Interval[]} 46 | def insert(intervals, new_interval) 47 | n = intervals.size 48 | i = intervals.bsearch_index { |x| x.end >= new_interval.start } || n 49 | j = intervals.bsearch_index { |x| x.start > new_interval.end } || n 50 | new_interval.start = [new_interval.start, intervals[i].start].min if i < n 51 | new_interval.end = [new_interval.end, intervals[j-1].end].max if j > 0 52 | intervals[0...i] + [new_interval] + intervals[j..-1] 53 | end 54 | -------------------------------------------------------------------------------- /572.subtree-of-another-tree.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=572 lang=ruby 4 | # 5 | # [572] Subtree of Another Tree 6 | # 7 | # https://leetcode.com/problems/subtree-of-another-tree/description/ 8 | # 9 | # Given two non-empty binary trees s and t, check whether tree t has 10 | # exactly the same structure and node values with a subtree of s. A 11 | # subtree of s is a tree consists of a node in s and all of this 12 | # node's descendants. The tree s could also be considered as a subtree 13 | # of itself. 14 | # 15 | # Example 1: 16 | # 17 | # Given tree s: 18 | # ⁠ 3 19 | # ⁠ / \ 20 | # ⁠ 4 5 21 | # ⁠ / \ 22 | # ⁠1 2 23 | # Given tree t: 24 | # ⁠ 4 25 | # ⁠ / \ 26 | # ⁠1 2 27 | # Return true, because t has the same structure and node values with a 28 | # subtree of s. 29 | # 30 | # Example 2: 31 | # 32 | # Given tree s: 33 | # ⁠ 3 34 | # ⁠ / \ 35 | # ⁠ 4 5 36 | # ⁠ / \ 37 | # ⁠1 2 38 | # ⁠ / 39 | # ⁠ 0 40 | # Given tree t: 41 | # ⁠ 4 42 | # ⁠ / \ 43 | # ⁠1 2 44 | # Return false. 45 | # 46 | # Definition for a binary tree node. 47 | # class TreeNode 48 | # attr_accessor :val, :left, :right 49 | # def initialize(val) 50 | # @val = val 51 | # @left, @right = nil, nil 52 | # end 53 | # end 54 | 55 | 56 | # @param {TreeNode} s 57 | # @param {TreeNode} t 58 | # @return {Boolean} 59 | def is_subtree(s, t) 60 | return false if s.nil? 61 | same_tree(s, t) || is_subtree(s.left, t) || is_subtree(s.right, t) 62 | end 63 | 64 | def same_tree(s, t) 65 | return true if s.nil? && t.nil? 66 | return false if s.nil? || t.nil? || s.val != t.val 67 | same_tree(s.left, t.left) && same_tree(s.right, t.right) 68 | end 69 | -------------------------------------------------------------------------------- /59.spiral-matrix-ii.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=59 lang=ruby 4 | # 5 | # [59] Spiral Matrix II 6 | # 7 | # https://leetcode.com/problems/spiral-matrix-ii/description/ 8 | # 9 | # Given a positive integer n, generate a square matrix filled with 10 | # elements from 1 to n2 in spiral order. 11 | # 12 | # Example: 13 | # 14 | # Input: 3 15 | # Output: 16 | # [ 17 | # ⁠[ 1, 2, 3 ], 18 | # ⁠[ 8, 9, 4 ], 19 | # ⁠[ 7, 6, 5 ] 20 | # ] 21 | 22 | 23 | # for loop practice... 24 | 25 | # @param {Integer} n 26 | # @return {Integer[][]} 27 | def generate_matrix(n) 28 | Array.new(n) { Array.new(n) }.tap { |r| helper(0, n-1, r) } 29 | end 30 | 31 | def helper(s, e, ans, x=1) 32 | return if s > e 33 | if s == e 34 | ans[s][e] = x 35 | return 36 | end 37 | (s..e).each { |j| ans[s][j] = x; x += 1 } 38 | (s+1..e).each { |i| ans[i][e] = x; x += 1 } 39 | (s..e-1).reverse_each { |j| ans[e][j] = x; x += 1 } 40 | (s+1..e-1).reverse_each { |i| ans[i][s] = x; x += 1 } 41 | helper(s+1, e-1, ans, x) 42 | end 43 | -------------------------------------------------------------------------------- /6.zigzag-conversion.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=6 lang=ruby 4 | # 5 | # [6] ZigZag Conversion 6 | # 7 | # https://leetcode.com/problems/zigzag-conversion/description/ 8 | # 9 | # The string "PAYPALISHIRING" is written in a zigzag pattern on a 10 | # given number of rows like this: (you may want to display this 11 | # pattern in a fixed font for better legibility) 12 | # 13 | # P A H N 14 | # A P L S I I G 15 | # Y I R 16 | # 17 | # And then read line by line: "PAHNAPLSIIGYIR" 18 | # 19 | # Write the code that will take a string and make this conversion 20 | # given a number of rows: 21 | # 22 | # string convert(string s, int numRows); 23 | # 24 | # Example 1: 25 | # # 0, 4, 8, 12, 1, 3, 5, 7, 9, 11, 13, 2, 6, 10 26 | # Input: s = "PAYPALISHIRING", numRows = 3 27 | # Output: "PAHNAPLSIIGYIR" 28 | # 29 | # 30 | # Example 2: 31 | # (4 - 1 - 0) * 2 = 6 32 | # (4 - 1 - 1) * 2 = 4 1 * 2 = 2 33 | # (4 - 1 - 2) * 2 = 2 2 * 2 = 4 34 | # (4 - 1 - 3) * 2 = 0 3 * 2 = 6 35 | # # 0, 6, 12, 1, 5, 7, 11, 13, 2, 4, 8, 10, 3, 9 36 | # Input: s = "PAYPALISHIRING", numRows = 4 37 | # Output: "PINALSIGYAHRPI" 38 | # Explanation: 39 | # 40 | # P I N 41 | # A L S I G 42 | # Y A H R 43 | # P I 44 | 45 | 46 | # @param {String} s 47 | # @param {Integer} num_rows 48 | # @return {String} 49 | def convert(s, num_rows) 50 | return s if num_rows == 1 51 | indices = [] 52 | for i in 0...num_rows 53 | m, n = (num_rows - 1 - i) * 2, i * 2 54 | j = i 55 | indices << j 56 | while j < s.length 57 | unless m.zero? 58 | j += m 59 | indices << j if j < s.length 60 | end 61 | unless n.zero? 62 | j += n 63 | indices << j if j < s.length 64 | end 65 | end 66 | end 67 | s.chars.values_at(*indices).join 68 | end 69 | -------------------------------------------------------------------------------- /61.rotate-list.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=61 lang=ruby 4 | # 5 | # [61] Rotate List 6 | # 7 | # https://leetcode.com/problems/rotate-list/description/ 8 | # 9 | # Given a linked list, rotate the list to the right by k places, where 10 | # k is non-negative. 11 | # 12 | # Example 1: 13 | # 14 | # Input: 1->2->3->4->5->NULL, k = 2 15 | # Output: 4->5->1->2->3->NULL 16 | # Explanation: 17 | # rotate 1 steps to the right: 5->1->2->3->4->NULL 18 | # rotate 2 steps to the right: 4->5->1->2->3->NULL 19 | # 20 | # Example 2: 21 | # 22 | # Input: 0->1->2->NULL, k = 4 23 | # Output: 2->0->1->NULL 24 | # Explanation: 25 | # rotate 1 steps to the right: 2->0->1->NULL 26 | # rotate 2 steps to the right: 1->2->0->NULL 27 | # rotate 3 steps to the right: 0->1->2->NULL 28 | # rotate 4 steps to the right: 2->0->1->NULL 29 | 30 | 31 | # Definition for singly-linked list. 32 | # class ListNode 33 | # attr_accessor :val, :next 34 | # def initialize(val) 35 | # @val = val 36 | # @next = nil 37 | # end 38 | # end 39 | 40 | 41 | # @param {ListNode} head 42 | # @param {Integer} k 43 | # @return {ListNode} 44 | def rotate_right(head, k) 45 | return if head.nil? 46 | tail, size = head, 1 47 | while !tail.next.nil? 48 | size += 1 49 | tail = tail.next 50 | end 51 | k %= size 52 | return head if k == 0 53 | tail.next = head 54 | front = head 55 | (size-k-1).times do 56 | front = front.next 57 | end 58 | head = front.next 59 | front.next = nil 60 | head 61 | end 62 | -------------------------------------------------------------------------------- /617.merge-two-binary-trees.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=617 lang=ruby 4 | # 5 | # [617] Merge Two Binary Trees 6 | # 7 | # https://leetcode.com/problems/merge-two-binary-trees/description/ 8 | # 9 | # Given two binary trees and imagine that when you put one of them to 10 | # cover the other, some nodes of the two trees are overlapped while 11 | # the others are not. 12 | # 13 | # You need to merge them into a new binary tree. The merge rule is 14 | # that if two nodes overlap, then sum node values up as the new value 15 | # of the merged node. Otherwise, the NOT null node will be used as the 16 | # node of new tree. 17 | # 18 | # Example 1: 19 | # 20 | # Input: 21 | # Tree 1 Tree 2 22 | # ⁠ 1 2 23 | # ⁠ / \ / \ 24 | # ⁠ 3 2 1 3 25 | # ⁠ / \ \ 26 | # ⁠ 5 4 7 27 | # Output: 28 | # Merged tree: 29 | # 3 30 | # / \ 31 | # 4 5 32 | # / \ \ 33 | # 5 4 7 34 | # 35 | # Note: The merging process must start from the root nodes of both trees. 36 | # 37 | # Definition for a binary tree node. 38 | # class TreeNode 39 | # attr_accessor :val, :left, :right 40 | # def initialize(val) 41 | # @val = val 42 | # @left, @right = nil, nil 43 | # end 44 | # end 45 | 46 | 47 | # @param {TreeNode} t1 48 | # @param {TreeNode} t2 49 | # @return {TreeNode} 50 | def merge_trees(t1, t2) 51 | return t1 if t2.nil? 52 | return t2 if t1.nil? 53 | x = TreeNode.new(t1.val+t2.val) 54 | x.left = merge_trees(t1.left, t2.left) 55 | x.right = merge_trees(t1.right, t2.right) 56 | x 57 | end 58 | -------------------------------------------------------------------------------- /62.unique-paths.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=62 lang=ruby 4 | # 5 | # [62] Unique Paths 6 | # 7 | # https://leetcode.com/problems/unique-paths/description/ 8 | # 9 | # A robot is located at the top-left corner of a m x n grid (marked 10 | # 'Start' in the diagram below). 11 | # 12 | # The robot can only move either down or right at any point in time. 13 | # The robot is trying to reach the bottom-right corner of the grid 14 | # (marked 'Finish' in the diagram below). 15 | # 16 | # How many possible unique paths are there? 17 | # 18 | # Above is a 7 x 3 grid. How many possible unique paths are there? 19 | # 20 | # Note: m and n will be at most 100. 21 | # 22 | # Example 1: 23 | # 24 | # Input: m = 3, n = 2 25 | # Output: 3 26 | # Explanation: 27 | # From the top-left corner, there are a total of 3 ways to reach the 28 | # bottom-right corner: 29 | # 1. Right -> Right -> Down 30 | # 2. Right -> Down -> Right 31 | # 3. Down -> Right -> Right 32 | # 33 | # Example 2: 34 | # 35 | # Input: m = 7, n = 3 36 | # Output: 28 37 | 38 | 39 | # Recursive version. 40 | 41 | # @param {Integer} m 42 | # @param {Integer} n 43 | # @return {Integer} 44 | def unique_paths_a(m, n) 45 | return 1 if m == 1 || n == 1 46 | unique_paths(m, n-1) + unique_paths(m-1, n) 47 | end 48 | 49 | 50 | # DP version. 51 | 52 | def unique_paths(m, n) 53 | dp = Array.new(m+1) { Array.new(n+1, 0) } 54 | (1..m).each do |i| 55 | (1..n).each do |j| 56 | if i == 1 || j == 1 57 | dp[i][j] = 1 58 | else 59 | dp[i][j] = dp[i][j-1] + dp[i-1][j] 60 | end 61 | end 62 | end 63 | dp[m][n] 64 | end 65 | -------------------------------------------------------------------------------- /66.plus-one.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=66 lang=ruby 4 | # 5 | # [66] Plus One 6 | # 7 | # https://leetcode.com/problems/plus-one/description/ 8 | # 9 | # Given a non-empty array of digits representing a non-negative 10 | # integer, plus one to the integer. 11 | # 12 | # The digits are stored such that the most significant digit is at the head of 13 | # the list, and each element in the array contain a single digit. 14 | # 15 | # You may assume the integer does not contain any leading zero, except 16 | # the number 0 itself. 17 | # 18 | # Example 1: 19 | # 20 | # Input: [1,2,3] 21 | # Output: [1,2,4] 22 | # Explanation: The array represents the integer 123. 23 | # 24 | # Example 2: 25 | # 26 | # Input: [4,3,2,1] 27 | # Output: [4,3,2,2] 28 | # Explanation: The array represents the integer 4321. 29 | 30 | 31 | # Ruby... 32 | 33 | # @param {Integer[]} digits 34 | # @return {Integer[]} 35 | def plus_one(digits) 36 | digits.join.to_i.succ.to_s.chars.map(&:to_i) 37 | end 38 | 39 | 40 | # Or waste your time and wirte this. 41 | def plus_one_a(digits) 42 | (digits.size-1).downto(0) do |i| 43 | if digits[i] < 9 44 | digits[i] += 1 45 | return digits 46 | end 47 | digits[i] = 0 48 | end 49 | digits.unshift 1 50 | end 51 | -------------------------------------------------------------------------------- /661.image-smoother.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=661 lang=ruby 4 | # 5 | # [661] Image Smoother 6 | # 7 | # https://leetcode.com/problems/image-smoother/description/ 8 | # 9 | # Given a 2D integer matrix M representing the gray scale of an image, you need 10 | # to design a smoother to make the gray scale of each cell becomes the average 11 | # gray scale (rounding down) of all the 8 surrounding cells and itself. If a 12 | # cell has less than 8 surrounding cells, then use as many as you can. 13 | # 14 | # Example 1: 15 | # 16 | # Input: 17 | # [[1,1,1], 18 | # ⁠[1,0,1], 19 | # ⁠[1,1,1]] 20 | # Output: 21 | # [[0, 0, 0], 22 | # ⁠[0, 0, 0], 23 | # ⁠[0, 0, 0]] 24 | # Explanation: 25 | # For the point (0,0), (0,2), (2,0), (2,2): floor(3/4) = floor(0.75) = 0 26 | # For the point (0,1), (1,0), (1,2), (2,1): floor(5/6) = floor(0.83333333) = 0 27 | # For the point (1,1): floor(8/9) = floor(0.88888889) = 0 28 | # 29 | # Note: 30 | # 31 | # The value in the given matrix is in the range of [0, 255]. 32 | # The length and width of the given matrix are in the range of [1, 150]. 33 | 34 | 35 | # @param {Integer[][]} m 36 | # @return {Integer[][]} 37 | def image_smoother(m) 38 | w, h = m[0].size, m.size 39 | ans = Array.new(h) { Array.new(w, 0) } 40 | (0..h-1).each do |i| 41 | (0..w-1).each do |j| 42 | c, sum = 0, 0 43 | [i-1, i, i+1].each do |x| 44 | [j-1, j, j+1].each do |y| 45 | if x >=0 && x < h && y >= 0 && y < w 46 | c += 1 47 | sum += m[x][y] 48 | end 49 | end 50 | end 51 | ans[i][j] = sum / c 52 | end 53 | end 54 | ans 55 | end 56 | -------------------------------------------------------------------------------- /666.path-sum-iv.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # If the depth of a tree is smaller than 5, then this tree can be 4 | # represented by a list of three-digits integers. 5 | # 6 | # For each integer in this list: 7 | # 1. The hundreds digit represents the depth D of this node, 1 <= D <= 4. 8 | # 2. The tens digit represents the position P of this node in the level it belongs to, 1 <= P <= 8. The position is the same as that in a full binary tree. 9 | # 3. The units digit represents the value V of this node, 0 <= V <= 9. 10 | # 11 | # Given a list of ascending three-digits integers representing a 12 | # binary with the depth smaller than 5. You need to return the sum of 13 | # all paths from the root towards the leaves. 14 | # 15 | # Example 1: 16 | # 17 | # Input: [113, 215, 221] 18 | # Output: 12 19 | # Explanation: 20 | # The tree that the list represents is: 21 | # 3 22 | # / \ 23 | # 5 1 24 | # 25 | # The path sum is (3 + 5) + (3 + 1) = 12. 26 | # 27 | # Example 2: 28 | # 29 | # Input: [113, 221] 30 | # Output: 4 31 | # Explanation: 32 | # The tree that the list represents is: 33 | # 3 34 | # \ 35 | # 1 36 | # 37 | # The path sum is (3 + 1) = 4. 38 | 39 | 40 | # For node 'DPV', its left child is a = (D+1)*10+2*P-1, its right 41 | # child is a+1, knowing its left and right child we can use normal dfs 42 | # to solve it, the only question is how to check if a node exists, we 43 | # can use a hash { 'DP':'V' } to do that. 44 | 45 | def path_sum(nums) 46 | dfs(nums[0]/10, nums.inject({}) { |h, n| h[n/10]=n%10; h }) 47 | end 48 | 49 | def dfs(root, h, x=0) 50 | return 0 if h[root].nil? 51 | left = (root/10+1)*10 + 2*(root%10)-1 52 | right = left+1 53 | x += h[root] 54 | return x if h[left].nil? && h[right].nil? 55 | dfs(left, h, x) + dfs(right, h, x) 56 | end 57 | -------------------------------------------------------------------------------- /673.number-of-longest-increasing-subsequence.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=673 lang=ruby 4 | # 5 | # [673] Number of Longest Increasing Subsequence 6 | # 7 | # https://leetcode.com/problems/number-of-longest-increasing-subsequence/description/ 8 | # 9 | # Given an unsorted array of integers, find the number of longest 10 | # increasing subsequence. 11 | # 12 | # Example 1: 13 | # 14 | # Input: [1,3,5,4,7] 15 | # Output: 2 16 | # Explanation: The two longest increasing subsequence are [1, 3, 4, 7] 17 | # and [1, 3, 5, 7]. 18 | # 19 | # Example 2: 20 | # 21 | # Input: [2,2,2,2,2] 22 | # Output: 5 23 | # Explanation: The length of longest continuous increasing subsequence is 1, 24 | # and there are 5 subsequences' length is 1, so output 5. 25 | # 26 | # Note: 27 | # 28 | # Length of the given array will be not exceed 2000 and the answer is 29 | # guaranteed to be fit in 32-bit signed int. 30 | 31 | 32 | # O(n^2). 33 | 34 | # @param {Integer[]} nums 35 | # @return {Integer} 36 | def find_number_of_lis(nums) 37 | return 0 if nums.empty? 38 | n = nums.size 39 | d, count = Array.new(n, 1), Array.new(n, 1) 40 | (1..n-1).each do |i| 41 | (0..i-1).each do |j| 42 | if nums[j] < nums[i] && d[i] < d[j]+1 43 | d[i] = d[j]+1 44 | count[i] = count[j] 45 | elsif d[j]+1 == d[i] 46 | count[i] += count[j] 47 | end 48 | end 49 | end 50 | longest = d.max 51 | sum = 0 52 | count.each_with_index do |c, i| 53 | sum += c if d[i] == longest 54 | end 55 | sum 56 | end 57 | -------------------------------------------------------------------------------- /674.longest-continuous-increasing-subsequence.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=674 lang=ruby 4 | # 5 | # [674] Longest Continuous Increasing Subsequence 6 | # 7 | # https://leetcode.com/problems/longest-continuous-increasing-subsequence/description/ 8 | # 9 | # Given an unsorted array of integers, find the length of longest 10 | # continuous increasing subsequence (subarray). 11 | # 12 | # Example 1: 13 | # 14 | # Input: [1,3,5,4,7] 15 | # Output: 3 16 | # Explanation: The longest continuous increasing subsequence is 17 | # [1,3,5], its length is 3. Even though [1,3,5,7] is also an 18 | # increasing subsequence, it's not a continuous one where 5 and 7 are 19 | # separated by 4. 20 | # 21 | # Example 2: 22 | # 23 | # Input: [2,2,2,2,2] 24 | # Output: 1 25 | # Explanation: The longest continuous increasing subsequence is [2], 26 | # its length is 1. 27 | # 28 | # Note: Length of the array will not exceed 10,000. 29 | 30 | 31 | # @param {Integer[]} nums 32 | # @return {Integer} 33 | def find_length_of_lcis(nums) 34 | return 0 if nums.empty? 35 | i = j = 0 36 | ans = 1 37 | while j < nums.size 38 | if j == nums.size-1 || nums[j] >= nums[j+1] 39 | ans = [ans, j-i+1].max 40 | i = j = j+1 41 | else 42 | j += 1 43 | end 44 | end 45 | ans 46 | end 47 | -------------------------------------------------------------------------------- /69.sqrtx.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=69 lang=ruby 4 | # 5 | # [69] Sqrt(x) 6 | # 7 | # https://leetcode.com/problems/sqrtx/description/ 8 | # 9 | # Implement int sqrt(int x). 10 | # 11 | # Compute and return the square root of x, where x is guaranteed to be 12 | # a non-negative integer. 13 | # 14 | # Since the return type is an integer, the decimal digits are truncated and 15 | # only the integer part of the result is returned. 16 | # 17 | # Example 1: 18 | # 19 | # Input: 4 20 | # Output: 2 21 | # 22 | # Example 2: 23 | # 24 | # Input: 8 25 | # Output: 2 26 | # Explanation: The square root of 8 is 2.82842..., and since 27 | # the decimal part is truncated, 2 is returned. 28 | 29 | 30 | # Binary Search. 31 | 32 | # @param {Integer} x 33 | # @return {Integer} 34 | def my_sqrt_a(x) 35 | (0..x).bsearch { |i| (i+1)**2 > x } 36 | end 37 | 38 | 39 | # Newton's method. See https://youtu.be/eCaXlAaN2uE?list=PLUl4u3cNGP61Oq3tWYp6V_F-5jb5L2iHb&t=1452 40 | # 41 | # 0. Given f(x)=x**2-a, we want to find x that f(x) == 0. 42 | # 1. f(x2)-f(x1)=(x2-x1)*f'(x1) 43 | # 2. we want f(x2)==0: f(x1)/f'(x1)=(x2-x1) => x2=x1-f(x1)/f'(x1) => x2=x1-(x1**2-a)/(2*x1) 44 | # => x2=(x1+(a/x1))/2 45 | 46 | def my_sqrt(x) 47 | n = x 48 | n = (n+x/n)/2 while n*n > x 49 | n 50 | end 51 | -------------------------------------------------------------------------------- /7.reverse-integer.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=7 lang=ruby 4 | # 5 | # [7] Reverse Integer 6 | # 7 | # https://leetcode.com/problems/reverse-integer/description/ 8 | # 9 | # Given a 32-bit signed integer, reverse digits of an integer. 10 | # 11 | # Example 1: 12 | # 13 | # Input: 123 14 | # Output: 321 15 | # 16 | # Example 2: 17 | # 18 | # Input: -123 19 | # Output: -321 20 | # 21 | # Example 3: 22 | # 23 | # Input: 120 24 | # Output: 21 25 | # 26 | # Note: 27 | # Assume we are dealing with an environment which could only store integers 28 | # within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of 29 | # this problem, assume that your function returns 0 when the reversed integer 30 | # overflows. 31 | 32 | 33 | # Ruby. 34 | 35 | # @param {Integer} x 36 | # @return {Integer} 37 | def reverse(x) 38 | r = x.abs.digits.reverse.join.to_i 39 | r = x < 0 ? -r : r 40 | return 0 if r < -(2**31) || r > (2**31)-1 41 | r 42 | end 43 | -------------------------------------------------------------------------------- /70.climbing-stairs.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=70 lang=ruby 4 | # 5 | # [70] Climbing Stairs 6 | # 7 | # https://leetcode.com/problems/climbing-stairs/description/ 8 | # 9 | # You are climbing a stair case. It takes n steps to reach to the top. 10 | # 11 | # Each time you can either climb 1 or 2 steps. In how many distinct 12 | # ways can you climb to the top? 13 | # 14 | # Note: Given n will be a positive integer. 15 | # 16 | # Example 1: 17 | # 18 | # Input: 2 19 | # Output: 2 20 | # Explanation: There are two ways to climb to the top. 21 | # 1. 1 step + 1 step 22 | # 2. 2 steps 23 | # 24 | # Example 2: 25 | # 26 | # Input: 3 27 | # Output: 3 28 | # Explanation: There are three ways to climb to the top. 29 | # 1. 1 step + 1 step + 1 step 30 | # 2. 1 step + 2 steps 31 | # 3. 2 steps + 1 step 32 | 33 | 34 | # @param {Integer} n 35 | # @return {Integer} 36 | def climb_stairs(n) 37 | Hash.new { |h, k| h[k] = h[k-1] + h[k-2] }.merge({1=>1, 2=>2})[n] 38 | end 39 | -------------------------------------------------------------------------------- /701.insert-into-a-binary-search-tree.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=701 lang=ruby 4 | # 5 | # [701] Insert into a Binary Search Tree 6 | # 7 | # https://leetcode.com/problems/insert-into-a-binary-search-tree/description/ 8 | # 9 | # Given the root node of a binary search tree (BST) and a value to be 10 | # inserted into the tree, insert the value into the BST. Return the 11 | # root node of the BST after the insertion. It is guaranteed that the 12 | # new value does not exist in the original BST. 13 | # 14 | # Note that there may exist multiple valid ways for the insertion, as 15 | # long as the tree remains a BST after insertion. You can return any 16 | # of them. 17 | # 18 | # For example, 19 | # 20 | # Given the tree: 21 | # ⁠ 4 22 | # ⁠ / \ 23 | # ⁠ 2 7 24 | # ⁠ / \ 25 | # ⁠ 1 3 26 | # And the value to insert: 5 27 | # 28 | # You can return this binary search tree: 29 | # 30 | # ⁠ 4 31 | # ⁠ / \ 32 | # ⁠ 2 7 33 | # ⁠ / \ / 34 | # ⁠ 1 3 5 35 | # 36 | # This tree is also valid: 37 | # 38 | # ⁠ 5 39 | # ⁠ / \ 40 | # ⁠ 2 7 41 | # ⁠ / \ 42 | # ⁠ 1 3 43 | # ⁠ \ 44 | # ⁠ 4 45 | # 46 | # Definition for a binary tree node. 47 | # class TreeNode 48 | # attr_accessor :val, :left, :right 49 | # def initialize(val) 50 | # @val = val 51 | # @left, @right = nil, nil 52 | # end 53 | # end 54 | 55 | # @param {TreeNode} root 56 | # @param {Integer} val 57 | # @return {TreeNode} 58 | def insert_into_bst(root, val) 59 | return TreeNode.new(val) if root.nil? 60 | cmp = val <=> root.val 61 | if cmp < 0 62 | root.left = insert_into_bst(root.left, val) 63 | elsif cmp > 0 64 | root.right = insert_into_bst(root.right, val) 65 | else 66 | root.val = val 67 | end 68 | root 69 | end 70 | -------------------------------------------------------------------------------- /704.binary-search.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=704 lang=ruby 4 | # 5 | # [704] Binary Search 6 | # 7 | # https://leetcode.com/problems/binary-search/description/ 8 | # 9 | # Given a sorted (in ascending order) integer array nums of n elements 10 | # and a target value, write a function to search target in nums. If 11 | # target exists, then return its index, otherwise return -1. 12 | # 13 | # Example 1: 14 | # 15 | # Input: nums = [-1,0,3,5,9,12], target = 9 16 | # Output: 4 17 | # Explanation: 9 exists in nums and its index is 4 18 | # 19 | # Example 2: 20 | # 21 | # Input: nums = [-1,0,3,5,9,12], target = 2 22 | # Output: -1 23 | # Explanation: 2 does not exist in nums so return -1 24 | # 25 | # Note: 26 | # 27 | # You may assume that all elements in nums are unique. 28 | # n will be in the range [1, 10000]. 29 | # The value of each element in nums will be in the range [-9999, 9999]. 30 | 31 | 32 | # Ruby. 33 | 34 | # @param {Integer[]} nums 35 | # @param {Integer} target 36 | # @return {Integer} 37 | def search(nums, target) 38 | nums.bsearch_index { |x| x >= target } || -1 39 | end 40 | 41 | 42 | # Or this. 43 | 44 | def search(nums, target) 45 | lo, hi = 0, nums.size-1 46 | while lo < hi 47 | m = lo+(hi-lo)/2 48 | if nums[m] >= target 49 | hi = m 50 | else 51 | lo = m+1 52 | end 53 | end 54 | nums[lo] == target ? lo : -1 55 | end 56 | -------------------------------------------------------------------------------- /718.maximum-length-of-repeated-subarray.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=718 lang=ruby 4 | # 5 | # [718] Maximum Length of Repeated Subarray 6 | # 7 | # https://leetcode.com/problems/maximum-length-of-repeated-subarray/description/ 8 | # 9 | # Given two integer arrays A and B, return the maximum length of an 10 | # subarray that appears in both arrays. 11 | # 12 | # Example 1: 13 | # 14 | # Input: 15 | # A: [1,2,3,2,1] 16 | # B: [3,2,1,4,7] 17 | # Output: 3 18 | # Explanation: 19 | # The repeated subarray with maximum length is [3, 2, 1]. 20 | # 21 | # Note: 22 | # 23 | # 1 <= len(A), len(B) <= 1000 24 | # 0 <= A[i], B[i] < 100 25 | 26 | 27 | # DP. O(n^2). 28 | 29 | # @param {Integer[]} a 30 | # @param {Integer[]} b 31 | # @return {Integer} 32 | def find_length(a, b) 33 | m, n = a.size, b.size 34 | d, ans = Array.new(a.size+1) { Array.new(b.size+1, 0) }, 0 35 | (m-1).downto(0) do |i| 36 | (n-1).downto(0) do |j| 37 | d[i][j] = d[i+1][j+1]+1 if a[i] == b[j] 38 | ans = [ans, d[i][j]].max 39 | end 40 | end 41 | ans 42 | end 43 | 44 | 45 | # TODO O(n*log(n))? 46 | -------------------------------------------------------------------------------- /75.sort-colors.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=75 lang=ruby 4 | # 5 | # [75] Sort Colors 6 | # 7 | # https://leetcode.com/problems/sort-colors/description/ 8 | # 9 | # Given an array with n objects colored red, white or blue, sort them 10 | # in-place so that objects of the same color are adjacent, with the 11 | # colors in the order red, white and blue. 12 | # 13 | # Here, we will use the integers 0, 1, and 2 to represent the color 14 | # red, white, and blue respectively. 15 | # 16 | # Note: You are not suppose to use the library's sort function for this 17 | # problem. 18 | # 19 | # Example: 20 | # 21 | # Input: [2,0,2,1,1,0] 22 | # Output: [0,0,1,1,2,2] 23 | # 24 | # Follow up: 25 | # 26 | # A rather straight forward solution is a two-pass algorithm using counting 27 | # sort. 28 | # First, iterate the array counting number of 0's, 1's, and 2's, then overwrite 29 | # array with total number of 0's, then 1's and followed by 2's. 30 | # Could you come up with a one-pass algorithm using only constant space? 31 | 32 | 33 | # Three way partitioning from quick sort. See problem 215. 34 | 35 | # @param {Integer[]} nums 36 | # @return {Void} Do not return anything, modify nums in-place instead. 37 | def sort_colors(nums) 38 | three_way_partition(nums) 39 | end 40 | 41 | def three_way_partition(nums, lo=0, hi=nums.size-1) 42 | lt, gt, k = lo, hi, lo 43 | while k <= gt 44 | cmp = nums[k] <=> 1 45 | case cmp 46 | when -1 47 | swap(nums, lt, k) 48 | lt += 1 49 | k += 1 50 | when 1 51 | swap(nums, gt, k) 52 | gt -= 1 53 | when 0 54 | k += 1 55 | end 56 | end 57 | end 58 | 59 | def swap(nums, i, j) 60 | nums[i], nums[j] = nums[j], nums[i] 61 | end 62 | -------------------------------------------------------------------------------- /78.subsets.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=78 lang=ruby 4 | # 5 | # [78] Subsets 6 | # 7 | # https://leetcode.com/problems/subsets/description/ 8 | # 9 | # Given a set of distinct integers, nums, return all possible subsets 10 | # (the power set). 11 | # 12 | # Note: The solution set must not contain duplicate subsets. 13 | # 14 | # Example: 15 | # 16 | # Input: nums = [1,2,3] 17 | # Output: 18 | # [ 19 | # ⁠ [3], 20 | # [1], 21 | # [2], 22 | # [1,2,3], 23 | # [1,3], 24 | # [2,3], 25 | # [1,2], 26 | # [] 27 | # ] 28 | 29 | 30 | # Recursive function P either removes the first character from its 31 | # argument, or does not. Here + means set union, . means concatenation 32 | # and λ is the empty set 33 | 34 | # P[3] => [] + [3] 35 | # P[2,3] => P[3] + 2.p[3] => [] + [3] + [2] + [2,3] 36 | # P[1,2,3] => P[2,3] + 1.P[2,3] => [] + [3] + [2] + [2,3] + [1] + [1,3] + [1,2] + [1,2,3] 37 | 38 | # @param {Integer[]} nums 39 | # @return {Integer[][]} 40 | def subsets(nums, pos = 0) 41 | return [[], [nums[pos]]] if pos == nums.length-1 42 | sub = subsets(nums, pos+1) 43 | sub + sub.map { |c| c + [nums[pos]] } 44 | end 45 | 46 | 47 | # DFS+Backtracking. 48 | 49 | def subsets(nums, k=0, path=[], paths=[[]]) 50 | return [] if nums.empty? 51 | return if k == nums.size 52 | (k..nums.size-1).each do |i| 53 | path << nums[i] 54 | paths << path.dup 55 | subsets(nums, i+1, path, paths) 56 | path.pop 57 | end 58 | paths 59 | end 60 | -------------------------------------------------------------------------------- /783.minimum-distance-between-bst-nodes.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=783 lang=ruby 4 | # 5 | # [783] Minimum Distance Between BST Nodes 6 | # 7 | # https://leetcode.com/problems/minimum-distance-between-bst-nodes/description/ 8 | # 9 | # Given a Binary Search Tree (BST) with the root node root, return the 10 | # minimum difference between the values of any two different nodes in 11 | # the tree. 12 | # 13 | # Example : 14 | # 15 | # Input: root = [4,2,6,1,3,null,null] 16 | # Output: 1 17 | # Explanation: 18 | # Note that root is a TreeNode object, not an array. 19 | # 20 | # The given tree [4,2,6,1,3,null,null] is represented by the following 21 | # diagram: 22 | # 23 | # ⁠ 4 24 | # ⁠ / \ 25 | # ⁠ 2 6 26 | # ⁠ / \ 27 | # ⁠ 1 3 28 | # 29 | # while the minimum difference in this tree is 1, it occurs between node 1 and 30 | # node 2, also between node 3 and node 2. 31 | # 32 | # Note: 33 | # 34 | # The size of the BST will be between 2 and 100. 35 | # The BST is always valid, each node's value is an integer, and each node's 36 | # value is different. 37 | # 38 | # Definition for a binary tree node. 39 | # class TreeNode 40 | # attr_accessor :val, :left, :right 41 | # def initialize(val) 42 | # @val = val 43 | # @left, @right = nil, nil 44 | # end 45 | # end 46 | 47 | 48 | # The core idea is inorder traversal: 49 | # 50 | # 1. Inorder traversal a bst result in an ordered list. 51 | # 2. Keep record of the previous visited node. 52 | # 3. Update mininal distance if current node.val-previous is smaller. 53 | 54 | # @param {TreeNode} root 55 | # @return {Integer} 56 | def min_diff_in_bst(root, prev=[], min=[Float::INFINITY]) 57 | return if root.nil? 58 | min_diff_in_bst(root.left, prev, min) 59 | min[0] = [min[0], root.val-prev[0]].min if prev[0] 60 | prev[0] = root.val 61 | min_diff_in_bst(root.right, prev, min) 62 | min[0] 63 | end 64 | -------------------------------------------------------------------------------- /79.word-search.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=79 lang=ruby 4 | # 5 | # [79] Word Search 6 | # 7 | # https://leetcode.com/problems/word-search/description/ 8 | # 9 | # Given a 2D board and a word, find if the word exists in the grid. 10 | # 11 | # The word can be constructed from letters of sequentially adjacent 12 | # cell, where "adjacent" cells are those horizontally or vertically 13 | # neighboring. The same letter cell may not be used more than once. 14 | # 15 | # Example: 16 | # 17 | # board = 18 | # [ 19 | # ⁠ ['A','B','C','E'], 20 | # ⁠ ['S','F','C','S'], 21 | # ⁠ ['A','D','E','E'] 22 | # ] 23 | # 24 | # Given word = "ABCCED", return true. 25 | # Given word = "SEE", return true. 26 | # Given word = "ABCB", return false. 27 | 28 | 29 | # When I use Array.new(board.size) { Array.new(board[0].size, false) } 30 | # as a default parameter, the runtime bumps up to 4000ms, WTF RUBY, not cool. 31 | 32 | # DFS+Backtracking. 33 | 34 | # @param {Character[][]} board 35 | # @param {String} word 36 | # @return {Boolean} 37 | def exist(board, word) 38 | board.each_with_index do |b, i| 39 | b.each_with_index do |c, j| 40 | return true if dfs(board, word, i, j, 0) 41 | end 42 | end 43 | false 44 | end 45 | 46 | def dfs(g, word, i, j, k) 47 | return true if k == word.size 48 | return false if i < 0 || i > g.size-1 || 49 | j < 0 || j > g[0].size-1 || 50 | g[i][j] != word[k] 51 | g[i][j], x = "*", g[i][j] 52 | ans = dfs(g, word, i-1, j, k+1) || 53 | dfs(g, word, i+1, j, k+1) || 54 | dfs(g, word, i, j-1, k+1) || 55 | dfs(g, word, i, j+1, k+1) 56 | g[i][j] = x 57 | ans 58 | end 59 | -------------------------------------------------------------------------------- /81.search-in-rotated-sorted-array-ii.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=81 lang=ruby 4 | # 5 | # [81] Search in Rotated Sorted Array II 6 | # 7 | # https://leetcode.com/problems/search-in-rotated-sorted-array-ii/description/ 8 | # 9 | # Suppose an array sorted in ascending order is rotated at some pivot 10 | # unknown to you beforehand. 11 | # 12 | # (i.e., [0,0,1,2,2,5,6] might become [2,5,6,0,0,1,2]). 13 | # 14 | # You are given a target value to search. If found in the array return 15 | # true, otherwise return false. 16 | # 17 | # Example 1: 18 | # 19 | # Input: nums = [2,5,6,0,0,1,2], target = 0 20 | # Output: true 21 | # 22 | # Example 2: 23 | # 24 | # Input: nums = [2,5,6,0,0,1,2], target = 3 25 | # Output: false 26 | # 27 | # Follow up: 28 | # 29 | # This is a follow up problem to Search in Rotated Sorted Array, where nums may 30 | # contain duplicates. 31 | # Would this affect the run-time complexity? How and why? 32 | 33 | 34 | # See problem 33. 35 | 36 | # @param {Integer[]} nums 37 | # @param {Integer} target 38 | # @return {Boolean} 39 | def search(nums, target) 40 | i, j = 0, nums.length-1 41 | while i <= j 42 | mid = (i + j) / 2 43 | if nums[mid] == target 44 | return true 45 | elsif nums[i] == nums[j] && nums[i] == nums[mid] 46 | i += 1 47 | j -= 1 48 | elsif nums[mid] >= nums[i] 49 | if target < nums[mid] && target >= nums[i] 50 | j = mid - 1 51 | else 52 | i = mid + 1 53 | end 54 | else 55 | if target <= nums[j] && target > nums[mid] 56 | i = mid + 1 57 | else 58 | j = mid - 1 59 | end 60 | end 61 | end 62 | false 63 | end 64 | -------------------------------------------------------------------------------- /812.largest-triangle-area.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=812 lang=ruby 4 | # 5 | # [812] Largest Triangle Area 6 | # 7 | # https://leetcode.com/problems/largest-triangle-area/description/ 8 | # 9 | # You have a list of points in the plane. Return the area of the 10 | # largest triangle that can be formed by any 3 of the points. 11 | # 12 | # Example: 13 | # Input: points = [[0,0],[0,1],[1,0],[0,2],[2,0]] 14 | # Output: 2 15 | # Explanation: 16 | # The five points are show in the figure below. The red triangle is the 17 | # largest. 18 | # 19 | # Notes: 20 | # 21 | # 3 <= points.length <= 50. 22 | # No points will be duplicated. 23 | # -50 <= points[i][j] <= 50. 24 | # Answers withinw10^-6 of the true value will be accepted as correct. 25 | 26 | 27 | # I use Convex Hull algorithm here to reduce the number of points 28 | # being considered. Brute Force all points also seems to be working. 29 | 30 | # @param {Integer[][]} points 31 | # @return {Float} 32 | def largest_triangle_area(points) 33 | x0, y0 = points.min_by { |(x, y)| [y, x] } 34 | p1, p2, *ps = points.sort_by { |(x, y)| [Math.atan2(y-y0, x-x0), x] } 35 | h = [p1, p2].tap do |q| 36 | ps.each do |p| 37 | q.pop while q.size > 1 && !ccw?(q[-2], q[-1], p) 38 | q << p 39 | end 40 | end 41 | n, ans = h.size, -Float::INFINITY 42 | (0..n-1).each do |i| 43 | (i+1..n-1).each do |j| 44 | (j+1..n-1).each do |k| 45 | ans = [ans, area(h[i], h[j], h[k])].max 46 | end 47 | end 48 | end 49 | ans 50 | end 51 | 52 | def vproduct((x1, y1), (x2, y2), (x3, y3)) 53 | (x2-x1)*(y3-y1) - (x3-x1)*(y2-y1) 54 | end 55 | 56 | def ccw?(a, b, c) 57 | vproduct(a, b, c) > 0 58 | end 59 | 60 | def area(a, b, c) 61 | vproduct(a, b, c).fdiv(2) 62 | end 63 | -------------------------------------------------------------------------------- /836.rectangle-overlap.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=836 lang=ruby 4 | # 5 | # [836] Rectangle Overlap 6 | # 7 | # https://leetcode.com/problems/rectangle-overlap/description/ 8 | # 9 | # A rectangle is represented as a list [x1, y1, x2, y2], where (x1, 10 | # y1) are the coordinates of its bottom-left corner, and (x2, y2) are 11 | # the coordinates of its top-right corner. 12 | # 13 | # Two rectangles overlap if the area of their intersection is 14 | # positive. To be clear, two rectangles that only touch at the corner 15 | # or edges do not overlap. 16 | # 17 | # Given two (axis-aligned) rectangles, return whether they overlap. 18 | # 19 | # Example 1: 20 | # 21 | # Input: rec1 = [0,0,2,2], rec2 = [1,1,3,3] 22 | # Output: true 23 | # 24 | # Example 2: 25 | # 26 | # Input: rec1 = [0,0,1,1], rec2 = [1,0,2,1] 27 | # Output: false 28 | # 29 | # Notes: 30 | # 31 | # Both rectangles rec1 and rec2 are lists of 4 integers. 32 | # All coordinates in rectangles will be between -10^9 and 10^9. 33 | 34 | 35 | # @param {Integer[]} rec1 36 | # @param {Integer[]} rec2 37 | # @return {Boolean} 38 | def is_rectangle_overlap(rec1, rec2) 39 | lx1, rx1 = rec1[0], rec1[2] 40 | lx2, rx2 = rec2[0], rec2[2] 41 | x_overlap = lx2 < rx1 && lx1 < rx2 42 | ly1, ry1 = rec1[1], rec1[3] 43 | ly2, ry2 = rec2[1], rec2[3] 44 | y_overlap = ly2 < ry1 && ly1 < ry2 45 | x_overlap && y_overlap 46 | end 47 | -------------------------------------------------------------------------------- /876.middle-of-the-linked-list.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=876 lang=ruby 4 | # 5 | # [876] Middle of the Linked List 6 | # 7 | # https://leetcode.com/problems/middle-of-the-linked-list/description/ 8 | # 9 | # Given a non-empty, singly linked list with head node head, return a 10 | # middle node of linked list. 11 | # 12 | # If there are two middle nodes, return the second middle node. 13 | # 14 | # Example 1: 15 | # 16 | # Input: [1,2,3,4,5] 17 | # Output: Node 3 from this list (Serialization: [3,4,5]) 18 | # The returned node has value 3. (The judge's serialization of this 19 | # node is [3,4,5]). Note that we returned a ListNode object ans, such 20 | # that: ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, and 21 | # ans.next.next.next = NULL. 22 | # 23 | # Example 2: 24 | # 25 | # Input: [1,2,3,4,5,6] 26 | # Output: Node 4 from this list (Serialization: [4,5,6]) 27 | # Since the list has two middle nodes with values 3 and 4, we return 28 | # the second one. 29 | # 30 | # Note: 31 | # 32 | # The number of nodes in the given list will be between 1 and 100. 33 | # 34 | # Definition for singly-linked list. 35 | # class ListNode 36 | # attr_accessor :val, :next 37 | # def initialize(val) 38 | # @val = val 39 | # @next = nil 40 | # end 41 | # end 42 | 43 | 44 | # @param {ListNode} head 45 | # @return {ListNode} 46 | def middle_node(head) 47 | slow = fast = head 48 | while !fast.nil? && !fast.next.nil? 49 | fast = fast.next.next 50 | slow = slow.next 51 | end 52 | slow 53 | end 54 | -------------------------------------------------------------------------------- /88.merge-sorted-array.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=88 lang=ruby 4 | # 5 | # [88] Merge Sorted Array 6 | # 7 | # https://leetcode.com/problems/merge-sorted-array/description/ 8 | # 9 | # Given two sorted integer arrays nums1 and nums2, merge nums2 into 10 | # nums1 as one sorted array. 11 | # 12 | # Note: 13 | # 14 | # The number of elements initialized in nums1 and nums2 are m and n 15 | # respectively. You may assume that nums1 has enough space (size that 16 | # is greater or equal to m + n) to hold additional elements from 17 | # nums2. 18 | # 19 | # Example: 20 | # 21 | # Input: 22 | # nums1 = [1,2,3,0,0,0], m = 3 23 | # nums2 = [2,5,6], n = 3 24 | # Output: [1,2,2,3,5,6] 25 | 26 | 27 | # @param {Integer[]} nums1 28 | # @param {Integer} m 29 | # @param {Integer[]} nums2 30 | # @param {Integer} n 31 | # @return {Void} Do not return anything, modify nums1 in-place instead. 32 | def merge(nums1, m, nums2, n) 33 | i, j, k = m-1, n-1, m+n-1 34 | until i < 0 || j < 0 35 | if nums1[i] > nums2[j] 36 | nums1[k] = nums1[i] 37 | i -= 1 38 | else 39 | nums1[k] = nums2[j] 40 | j -= 1 41 | end 42 | k -= 1 43 | end 44 | until j < 0 45 | nums1[k] = nums2[j] 46 | k -= 1 47 | j -= 1 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /89.gray-code.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=89 lang=ruby 4 | # 5 | # [89] Gray Code 6 | # 7 | # https://leetcode.com/problems/gray-code/description/ 8 | # 9 | # The gray code is a binary numeral system where two successive values 10 | # differ in only one bit. 11 | # 12 | # Given a non-negative integer n representing the total number of bits 13 | # in the code, print the sequence of gray code. A gray code sequence 14 | # must begin with 0. 15 | # 16 | # Example 1: 17 | # 18 | # Input: 2 19 | # Output: [0,1,3,2] 20 | # Explanation: 21 | # 00 - 0 22 | # 01 - 1 23 | # 11 - 3 24 | # 10 - 2 25 | # 26 | # For a given n, a gray code sequence may not be uniquely defined. 27 | # For example, [0,2,3,1] is also a valid gray code sequence. 28 | # 29 | # 00 - 0 30 | # 10 - 2 31 | # 11 - 3 32 | # 01 - 1 33 | # 34 | # Example 2: 35 | # 36 | # Input: 0 37 | # Output: [0] 38 | # Explanation: We define the gray code sequence to begin with 0. A 39 | # gray code sequence of n has size = 2n, which for n = 0 the size is 40 | # 20 = 1. Therefore, for n = 0 the gray code sequence is [0]. 41 | 42 | 43 | # My idea is to flip the right subtree for all search path, so that 44 | # left and right subtree are 'closer'. You can draw it out like this: 45 | # 46 | # "" 47 | # / \ 48 | # 0 1 49 | # / \ / \ 50 | # 0 1 1 0 51 | # 52 | # Surprisingly it works, but WHY? I don't know how to prove it. 53 | 54 | # @param {Integer} n 55 | # @return {Integer[]} 56 | def gray_code(n) 57 | dfs(n, 0, 0) 58 | end 59 | 60 | def dfs(n, k, v, ans=[], flip=false) 61 | if k == n 62 | ans << v 63 | else 64 | if flip 65 | dfs(n, k+1, v*2+1, ans, false) 66 | dfs(n, k+1, v*2, ans, true) 67 | else 68 | dfs(n, k+1, v*2, ans, false) 69 | dfs(n, k+1, v*2+1, ans, true) 70 | end 71 | end 72 | ans 73 | end 74 | -------------------------------------------------------------------------------- /9.palindrome-number.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=9 lang=ruby 4 | # 5 | # [9] Palindrome Number 6 | # 7 | # https://leetcode.com/problems/palindrome-number/description/ 8 | # 9 | # Determine whether an integer is a palindrome. An integer is a 10 | # palindrome when it reads the same backward as forward. 11 | # 12 | # Example 1: 13 | # 14 | # Input: 121 15 | # Output: true 16 | # 17 | # Example 2: 18 | # 19 | # Input: -121 20 | # Output: false 21 | # Explanation: From left to right, it reads -121. From right to left, it 22 | # becomes 121-. Therefore it is not a palindrome. 23 | # 24 | # Example 3: 25 | # 26 | # Input: 10 27 | # Output: false 28 | # Explanation: Reads 01 from right to left. Therefore it is not a palindrome. 29 | # 30 | # Follow up: 31 | # 32 | # Coud you solve it without converting the integer to a string? 33 | 34 | 35 | # @param {Integer} x 36 | # @return {Boolean} 37 | def is_palindrome(x) 38 | return false if x < 0 || (x != 0 && x % 10 == 0) 39 | n = 0 40 | while x > n 41 | n = n*10 + x%10 42 | x = x/10 43 | end 44 | n == x || x == n/10 45 | end 46 | -------------------------------------------------------------------------------- /91.decode-ways.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=91 lang=ruby 4 | # 5 | # [91] Decode Ways 6 | # 7 | # https://leetcode.com/problems/decode-ways/description/ 8 | # 9 | # A message containing letters from A-Z is being encoded to numbers 10 | # using the following mapping: 11 | # 12 | # 'A' -> 1 13 | # 'B' -> 2 14 | # ... 15 | # 'Z' -> 26 16 | # 17 | # Given a non-empty string containing only digits, determine the total 18 | # number of ways to decode it. 19 | # 20 | # Example 1: 21 | # 22 | # Input: "12" 23 | # Output: 2 24 | # Explanation: It could be decoded as "AB" (1 2) or "L" (12). 25 | # 26 | # Example 2: 27 | # 28 | # Input: "226" 29 | # Output: 3 30 | # Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 31 | # 6). 32 | 33 | 34 | # A classic DP problem, after solving problem 35 | # 10-regular-expression-matching, this seems like child's play... 36 | # 37 | # Two tricky parts tho: 38 | # 1. There are 0 ways to decode a string started with 0. 39 | # 2. No need to check whether first two letters are bigger than 9, 40 | # we've already taken care of that in step 1. 41 | 42 | # @param {String} s 43 | # @return {Integer} 44 | def num_decodings(s) 45 | dp = [] 46 | dp[s.length] = 1 47 | (s.length-1).downto(0).each do |i| 48 | if s[i] == "0" 49 | dp[i] = 0 50 | else 51 | dp[i] = dp[i+1] + (i < s.length-1 && s[i,2].to_i <= 26 ? dp[i+2] : 0) 52 | end 53 | end 54 | dp[0] 55 | end 56 | -------------------------------------------------------------------------------- /938.range-sum-of-bst.rb: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # @lc app=leetcode id=938 lang=ruby 4 | # 5 | # [938] Range Sum of BST 6 | # 7 | # https://leetcode.com/problems/range-sum-of-bst/description/ 8 | # 9 | # Given the root node of a binary search tree, return the sum of 10 | # values of all nodes with value between L and R (inclusive). 11 | # 12 | # The binary search tree is guaranteed to have unique values. 13 | # 14 | # Example 1: 15 | # 16 | # Input: root = [10,5,15,3,7,null,18], L = 7, R = 15 17 | # Output: 32 18 | # 19 | # Example 2: 20 | # 21 | # Input: root = [10,5,15,3,7,13,18,1,null,6], L = 6, R = 10 22 | # Output: 23 23 | # 24 | # Note: 25 | # 26 | # The number of nodes in the tree is at most 10000. 27 | # The final answer is guaranteed to be less than 2^31. 28 | # 29 | # Definition for a binary tree node. 30 | # class TreeNode 31 | # attr_accessor :val, :left, :right 32 | # def initialize(val) 33 | # @val = val 34 | # @left, @right = nil, nil 35 | # end 36 | # end 37 | 38 | 39 | # @param {TreeNode} root 40 | # @param {Integer} l 41 | # @param {Integer} r 42 | # @return {Integer} 43 | def range_sum_bst(root, l, r, sum = 0) 44 | return 0 if root.nil? 45 | return range_sum_bst(root.right, l, r, sum) if root.val < l 46 | return range_sum_bst(root.left, l, r, sum) if root.val > r 47 | range_sum_bst(root.left, l, r, sum) + root.val + range_sum_bst(root.right, l, r, sum) 48 | end 49 | -------------------------------------------------------------------------------- /data-structures/union-find.rb: -------------------------------------------------------------------------------- 1 | # Union Find (weighed quick-union with path compression) 2 | # 3 | # See Algoritms Part 1 from Princeton University: 4 | # https://www.coursera.org/learn/algorithms-part1/lecture/ZgecU/quick-union 5 | 6 | class UF 7 | def initialize(size) 8 | @arr = Array.new(size, &:itself) 9 | @weight = Array.new(size, 1) 10 | end 11 | 12 | def connected?(p, q) 13 | root(p) == root(q) 14 | end 15 | 16 | def root(p) 17 | until p == @arr[p] 18 | @arr[p] = @arr[@arr[p]] 19 | p = @arr[p] 20 | end 21 | p 22 | end 23 | 24 | def union(p, q) 25 | i, j = root(p), root(q) 26 | return if i == j 27 | if @weight[i] < @weight[j] 28 | @arr[i] = j 29 | @weight[j] += @weight[i] 30 | else 31 | @arr[j] = i 32 | @weight[i] += @weight[j] 33 | end 34 | end 35 | 36 | def max_size 37 | @weight.max 38 | end 39 | end 40 | 41 | 42 | # Test 43 | require 'test/unit' 44 | 45 | class SimpleTest < Test::Unit::TestCase 46 | def test_union_find 47 | uf = UF.new(10) 48 | assert !uf.connected?(0, 6) 49 | uf.union(0, 6) 50 | assert uf.connected?(0, 6) 51 | uf.union(1, 2) 52 | uf.union(1, 0) 53 | uf.union(6, 7) 54 | assert_equal uf.root(2), uf.root(7) 55 | end 56 | end 57 | -------------------------------------------------------------------------------- /imgs/meme0.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ACEMerlin/leetcode-ruby/c985981715d076b0f1467f425d3fc044e53583b5/imgs/meme0.jpg -------------------------------------------------------------------------------- /imgs/meme1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ACEMerlin/leetcode-ruby/c985981715d076b0f1467f425d3fc044e53583b5/imgs/meme1.jpg -------------------------------------------------------------------------------- /imgs/meme2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ACEMerlin/leetcode-ruby/c985981715d076b0f1467f425d3fc044e53583b5/imgs/meme2.jpg -------------------------------------------------------------------------------- /other/build-array-from-count-of-bigger-numbers-before-self.rb: -------------------------------------------------------------------------------- 1 | # You are given an integer array 'counts' of size n. The counts array 2 | # has the property where counts[i] is the number of bigger elements to 3 | # the left of nums[i], the range of nums is 1..n, build the original 4 | # nums array. 5 | # 6 | # Example: 7 | # 8 | # Input: [0,1,2,1,0] 9 | # Output: [4,2,1,3,5] 10 | 11 | 12 | def build_array(data) 13 | n = data.size 14 | x = Array.new(n) { |i| i+1 } 15 | result = [] 16 | (n-1).downto(0) do |i| 17 | k = -data[i]-1 18 | result[i] = x[k] 19 | x.delete_at(k) 20 | end 21 | result 22 | end 23 | 24 | def build_array(data) 25 | n = data.size 26 | x = Array.new(n) { |i| i+1 } 27 | result = [] 28 | (n-1).downto(0) do |i| 29 | k, count = -1, 0 30 | while true 31 | if x[k] != 0 32 | count += 1 33 | break if count > data[i] 34 | end 35 | k -= 1 36 | end 37 | result[i] = x[k] 38 | x[k] = 0 39 | end 40 | result 41 | end 42 | -------------------------------------------------------------------------------- /other/distance-between-2-nodes-in-BST.rb: -------------------------------------------------------------------------------- 1 | # Find the distance between two nodes in BST. 2 | # 3 | # Example: 4 | # 5 | # Given tree: 6 | # 5 7 | # / \ 8 | # 1 7 9 | # / \ / \ 10 | # 0 3 6 8 11 | # / \ 12 | # 2 4 13 | # 14 | # The distance between 1 and 8 is 3: 1->5->7->8 15 | # The distance between 0 and 2 is 3: 0->1->3->2 16 | # 17 | # Definition for a binary tree node. 18 | # class TreeNode 19 | # attr_accessor :val, :left, :right 20 | # def initialize(val) 21 | # @val = val 22 | # @left, @right = nil, nil 23 | # end 24 | # end 25 | 26 | 27 | # 1. get depth of p 28 | # 2. get depth of q 29 | # 3. get LCA of p and q 30 | # 4. dist(p,q) = depth(p) + depth(q) - 2 * dist(lca(p,q)) 31 | 32 | def distance_in_bst(root, p, q) 33 | p, q = q, p if p > q 34 | depth(root, p) + depth(root, q) - 2 * depth(root, lca(root, p, q)) 35 | end 36 | 37 | def depth(root, p, d=0) 38 | return if root.nil? 39 | cmp = p <=> root.val 40 | if cmp < 0 41 | depth(root.left, p, d+1) 42 | elsif cmp > 0 43 | depth(root.right, p, d+1) 44 | else 45 | d 46 | end 47 | end 48 | 49 | def lca(root, p, q) 50 | if root.val < p 51 | lca(root.right, p, q) 52 | elsif root.val > q 53 | lca(root.left, p, q) 54 | else 55 | root.val 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /other/fair-work-load.rb: -------------------------------------------------------------------------------- 1 | # Topcoder: 2 | # 3 | # https://community.topcoder.com/stat?c=problem_statement&pm=1901&rd=4650 4 | 5 | 6 | def fair_work_load(folders, workers) 7 | lo, hi = folders.max, folders.sum 8 | (lo..hi).bsearch do |load| 9 | worker_needed_with_load(folders, load) <= workers 10 | end 11 | end 12 | 13 | def worker_needed_with_load(folders, load) 14 | need, cur_load = 1, 0 15 | folders.each do |f| 16 | cur_load += f 17 | if cur_load > load 18 | need += 1 19 | cur_load = f 20 | end 21 | end 22 | need 23 | end 24 | 25 | 26 | # Test 27 | require 'test/unit' 28 | 29 | class SimpleTest < Test::Unit::TestCase 30 | def test_simple 31 | assert_equal fair_work_load([10, 20, 30, 40, 50, 60, 70, 80, 90], 3), 170 32 | assert_equal fair_work_load([10, 20, 30, 40, 50, 60, 70, 80, 90], 5), 110 33 | assert_equal fair_work_load([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1000], 2), 1000 34 | end 35 | end 36 | -------------------------------------------------------------------------------- /other/longest-subarray-sum-equals-s.rb: -------------------------------------------------------------------------------- 1 | # Codefight: https://app.codesignal.com/interview-practice/task/izLStwkDr5sMS9CEm/ 2 | 3 | def findLongestSubarrayBySum(s, arr) 4 | h, sum = {0=>-1}, 0 5 | max, ans = 0, [-1] 6 | arr.each_with_index do |n, i| 7 | sum += n 8 | if h.has_key?(sum-s) 9 | length = i-h[sum-s] 10 | if length > max 11 | max = length 12 | ans = [h[sum-s]+2, i+1] 13 | end 14 | end 15 | h[sum] = i if !h.has_key?(sum) 16 | end 17 | ans 18 | end 19 | -------------------------------------------------------------------------------- /other/longest-subsequence-of-balanced-parentheses.rb: -------------------------------------------------------------------------------- 1 | # Seraja and Brackets 2 | # 3 | # http://codeforces.com/contest/380/problem/C 4 | # https://www.spoj.com/problems/BRCKTS 5 | 6 | require '../data-structures/segment-tree' 7 | 8 | class ParenTree < SegmentTree 9 | 10 | def leaf(c) 11 | { 12 | ans: 0, 13 | o: c == '(' ? 1 : 0, 14 | c: c == ')' ? 1 : 0 15 | } 16 | end 17 | 18 | def combine(left, right) 19 | t = [left[:o], right[:c]].min 20 | { 21 | ans: left[:ans] + right[:ans] + 2*t, 22 | o: left[:o] + right[:o] - t, 23 | c: left[:c] + right[:c] - t 24 | } 25 | end 26 | end 27 | 28 | 29 | # Test 30 | require 'test/unit' 31 | 32 | class SimpleTest < Test::Unit::TestCase 33 | def test_parens 34 | t = ParenTree.new("())(())(())(") 35 | assert_equal t.query(0, 0)[:ans], 0 36 | assert_equal t.query(1, 2)[:ans], 0 37 | assert_equal t.query(0, 1)[:ans], 2 38 | assert_equal t.query(0, 11)[:ans], 10 39 | assert_equal t.query(7, 11)[:ans], 4 40 | assert_equal t.query(4, 10)[:ans], 6 41 | assert_equal t.query(1, 9)[:ans], 6 42 | end 43 | end 44 | -------------------------------------------------------------------------------- /other/lowest-common-territory-of-places.rb: -------------------------------------------------------------------------------- 1 | # Find the lowest common territory that holds the given two places. 2 | # First column of each row is enclosing region, and following columns 3 | # are all the regions within that row. 4 | # 5 | # Example: 6 | # 7 | # data = [ 8 | # ['America', 'NA', 'SA'], 9 | # ['NA', 'MXC', 'USA', 'CAN'], 10 | # ['SA', 'Argentina', 'Brazil', 'Chile'], 11 | # ['MXC', 'Oaxaca', 'Puebla'], 12 | # ['USA', 'CA', 'WY', 'NY'], 13 | # ['CAN', 'ON', 'QU', 'SAS']] 14 | # 15 | # lca(data, "CA", "Puebla") => "NA" 16 | # lca(data, "WY", "NY") => "USA" 17 | 18 | 19 | def build_parents(data) 20 | data.inject({}) do |h, d| 21 | (1...d.length).each { |i| h[d[i]] = d[0] }; h 22 | end 23 | end 24 | 25 | def lca(data, p, q) 26 | parents = build_parents(data) 27 | ancestors = Set.new 28 | until p.nil? 29 | ancestors << p 30 | p = parents[p] 31 | end 32 | q = parents[q] until q.nil? || ancestors.include?(q) 33 | q 34 | end 35 | -------------------------------------------------------------------------------- /other/merge-two-intervals.rb: -------------------------------------------------------------------------------- 1 | # Merge two sorted (ascending) lists of interval and return it as a 2 | # new sorted list. The new sorted list should be made by splicing 3 | # together the intervals of the two lists and sorted in ascending 4 | # order. 5 | # 6 | # Example: 7 | # 8 | # Input: list1 = [[1,2],[3,4]] and list2 = [[2,3],[5,6]] 9 | # Output: [[1,4],[5,6]] 10 | 11 | 12 | # We just need to pick the smaller one of l1 and l2. 13 | # 1. When run out of l2 then just use l1. 14 | # 2. When run out of l1 then just use l2. 15 | # 3. When still have l1 and l2 left, we use the smaller one of them. 16 | 17 | def merge_two_intervals(l1, l2) 18 | return l2 if l1.empty? 19 | return l1 if l2.empty? 20 | i, j = 0, 0 21 | [].tap do |r| 22 | while i < l1.length || j < l2.length 23 | if j == l2.length || (i < l1.length && l1[i].start < l2[j].start) 24 | k = l1[i] 25 | i += 1 26 | elsif i == l1.length || (j < l2.length && l1[i].start >= l2[j].start) 27 | k = l2[j] 28 | j += 1 29 | end 30 | if r.empty? || r[-1].end < k.start 31 | r << k 32 | else 33 | r[-1].end = [r[-1].end, k.end].max 34 | end 35 | end 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /other/minimum-flip-to-sorted-string.rb: -------------------------------------------------------------------------------- 1 | # Given string contains only 'a' and 'b', their are 2 ops you can do: 2 | # 3 | # 1. flip a to b at certain index. 4 | # 2. flip b to a at certain index. 5 | # 6 | # Find minimum ops you can do after which the string is sorted 7 | # (a...ab...b), return the sorted string. 8 | 9 | 10 | # Given "ababbab" 11 | # 1. From right to left count the number of 'a's up to given point. 12 | # there is a dummy node 0 at the end. 13 | # [3, 2, 2, 1, 1, 1, 0, 0] 14 | # 2. From left to right count the number of 'b's up to given point. 15 | # there is a dummy node 0 at the start. 16 | # [0, 0, 1, 1, 2, 3, 3, 4] 17 | # 3. For each character, check how many 'b's are there to the left, 18 | # and how many 'a's to the right, sum it together, update the minimum 19 | # if it's smaller, keep record of the current index, after iteration, 20 | # rebuild the string using the index. 21 | 22 | def abstring(str) 23 | min, sep = Float::INFINITY 24 | count = 0 25 | bs = (0...str.length).reduce([0]) do |b, i| 26 | count += 1 if str[i] == 'b' 27 | b << count 28 | end 29 | count = 0 30 | as = (str.length-1).downto(0).reduce([0]) do |a, i| 31 | count += 1 if str[i] == 'a' 32 | a.unshift(count) 33 | end 34 | (0..str.length).each do |i| 35 | flips = as[i] + bs[i] 36 | if flips <= min 37 | min = flips 38 | sep = i 39 | end 40 | end 41 | 'a'*sep + 'b'*(str.size-sep) 42 | end 43 | -------------------------------------------------------------------------------- /other/swap-lex-order.rb: -------------------------------------------------------------------------------- 1 | # Codefight: https://app.codesignal.com/interview-practice/task/5vXzdE9yzjsoMZ9sk 2 | 3 | eval <<-Ruby 4 | class UF 5 | 6 | attr_accessor :arr 7 | 8 | def initialize(size) 9 | @arr = Array.new(size, &:itself) 10 | @weight = Array.new(size, 1) 11 | end 12 | 13 | def union(i, j) 14 | p, q = root(i), root(j) 15 | return if p == q 16 | if @weight[p] <= @weight[q] 17 | @arr[p] = q 18 | @weight[q] += @weight[p] 19 | else 20 | @arr[q] = p 21 | @weight[p] += @weight[q] 22 | end 23 | end 24 | 25 | def connected?(i, j) 26 | root(i) == root(j) 27 | end 28 | 29 | def root(i) 30 | while @arr[i] != i 31 | @arr[i] = @arr[@arr[i]] 32 | i = @arr[i] 33 | end 34 | i 35 | end 36 | end 37 | Ruby 38 | 39 | def swapLexOrder(str, pairs) 40 | uf = UF.new(str.size) 41 | pairs.each do |(i, j)| 42 | uf.union(i-1, j-1) 43 | end 44 | uf.arr 45 | .map { |i| uf.root(i) } 46 | .each_with_index 47 | .reduce(Hash.new { |h, k| h[k] = [] }) { |h, (n, i)| h[n] << [i, str[i]]; h} 48 | .values 49 | .each { |xs| 50 | next if xs.size == 1 51 | order = xs.sort_by(&:last).reverse 52 | xs.each_with_index { |(i, _), j| str[i] = order[j][1] } 53 | } 54 | str 55 | end 56 | -------------------------------------------------------------------------------- /other/villagers-and-defenders.rb: -------------------------------------------------------------------------------- 1 | # There is a village with two kinds of people- villagers (represented 2 | # by 0) and defenders (represented by 1). When enemy attacks the 3 | # defenders stand in front as shown below: 4 | # 5 | # 110000 6 | # 100000 7 | # 111000 8 | # 110000 9 | # 10 | # The enemy will attack in that row which is most vulnerable (i.e. has 11 | # the least number of defenders. Write a program to find the row where 12 | # the enemy will attack. 13 | 14 | # O(m+n) 15 | 16 | def attack(grid) 17 | j, ans = grid[0].size-1, 0 18 | grid.each_with_index do |n, i| 19 | next if n[j] == 1 20 | j -= 1 while n[j] == 0 21 | ans = i 22 | end 23 | ans 24 | end 25 | --------------------------------------------------------------------------------