├── .gitignore ├── .rubocop.yml ├── 3sum └── solution.rb ├── 3sum_closest └── solution.rb ├── 4sum └── solution.rb ├── LICENSE ├── README.md ├── add_binary └── solution.rb ├── add_two_numbers └── solution.rb ├── anagrams └── solution.rb ├── balanced_binary_tree └── solution.rb ├── best_time_to_buy_and_sell_stock └── solution.rb ├── best_time_to_buy_and_sell_stock_ii └── solution.rb ├── best_time_to_buy_and_sell_stock_iii └── solution.rb ├── binary_tree_inorder_traversal └── solution.rb ├── binary_tree_level_order_traversal └── solution.rb ├── binary_tree_level_order_traversal_ii └── solution.rb ├── binary_tree_postorder_traversal └── solution.rb ├── binary_tree_preorder_traversal └── solution.rb ├── binary_tree_zigzag_level_order_traversal └── solution.rb ├── climbing_stairs └── solution.rb ├── combination_sum └── solution.rb ├── combination_sum_ii └── solution.rb ├── combinations └── solution.rb ├── find_minimum_in_rotated_sorted_array └── solution.rb ├── implement_strstr └── solution.rb ├── makedir.sh ├── permutations └── solution.rb ├── search_a_2d_matrix └── solution.rb ├── search_in_rotated_sorted_array └── solution.rb ├── search_in_rotated_sorted_array_ii └── solution.rb ├── subsets └── solution.rb └── summary_ranges └── solution.rb /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *.gem 4 | *.rbc 5 | /.config 6 | /coverage/ 7 | /InstalledFiles 8 | /pkg/ 9 | /spec/reports/ 10 | /test/tmp/ 11 | /test/version_tmp/ 12 | /tmp/ 13 | 14 | ## Specific to RubyMotion: 15 | .dat* 16 | .repl_history 17 | build/ 18 | 19 | ## Documentation cache and generated files: 20 | /.yardoc/ 21 | /_yardoc/ 22 | /doc/ 23 | /rdoc/ 24 | 25 | ## Environment normalisation: 26 | /.bundle/ 27 | /vendor/bundle 28 | /lib/bundler/man/ 29 | 30 | # for a library or gem, you might want to ignore these files since the code is 31 | # intended to run in multiple environments; otherwise, check them in: 32 | # Gemfile.lock 33 | # .ruby-version 34 | # .ruby-gemset 35 | 36 | # unless supporting rvm < 1.11.0 or doing something fancy, ignore this: 37 | .rvmrc 38 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | Style/Documentation: 2 | Description: 'Document classes and non-namespace modules.' 3 | Enabled: false 4 | 5 | Metrics/PerceivedComplexity: 6 | Description: >- 7 | A complexity metric geared towards measuring complexity for a 8 | human reader. 9 | Enabled: false 10 | 11 | Metrics/CyclomaticComplexity: 12 | Description: >- 13 | A complexity metric that is strongly correlated to the number 14 | of test cases needed to validate a method. 15 | Enabled: false 16 | 17 | Metrics/MethodLength: 18 | Description: 'Avoid methods longer than 10 lines of code.' 19 | StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#short-methods' 20 | Enabled: false 21 | 22 | Metrics/AbcSize: 23 | Description: >- 24 | A calculated magnitude based on number of assignments, 25 | branches, and conditions. 26 | Enabled: false 27 | 28 | Style/PredicateName: 29 | # Predicate name prefices. 30 | NamePrefix: 31 | - is_ 32 | - has_ 33 | - have_ 34 | # Predicate name prefices that should be removed. 35 | NamePrefixBlacklist: 36 | - is_ 37 | - has_ 38 | - have_ 39 | Enabled: false 40 | -------------------------------------------------------------------------------- /3sum/solution.rb: -------------------------------------------------------------------------------- 1 | def three_sum(num) 2 | num.sort! 3 | res = [] 4 | (0..num.length - 3).each do |i| 5 | next unless i == 0 || i > 0 && num[i - 1] != num[i] 6 | left = i + 1 7 | right = num.length - 1 8 | while left < right 9 | s = num[i] + num[left] + num[right] 10 | if s == 0 11 | res.push([num[i], num[left], num[right]]) 12 | left += 1 13 | right -= 1 14 | left += 1 while left < right && num[left] == num[left - 1] 15 | right += 1 while right > left && num[right] == num[right + 1] 16 | elsif s < 0 17 | left += 1 18 | else 19 | right -= 1 20 | end 21 | end 22 | end 23 | res 24 | end 25 | 26 | p num 27 | p three_sum([-1, -3, 0, 1, 3, 5, 2]) 28 | -------------------------------------------------------------------------------- /3sum_closest/solution.rb: -------------------------------------------------------------------------------- 1 | def three_sum_closet(num, target) 2 | num.sort! 3 | n = num.length 4 | res = num[0] + num[1] + num[2] 5 | (0..n - 3).each do |i| 6 | l = i + 1 7 | r = n - 1 8 | while l < r 9 | s = num[i] + num[l] + num[r] 10 | res = s if (s - target).abs < (res - target).abs 11 | if s == target 12 | return s 13 | elsif s < target 14 | l += 1 15 | else 16 | r -= 1 17 | end 18 | end 19 | end 20 | res 21 | end 22 | 23 | num = [-4, 2, 4, 6, 11] 24 | target = 14 25 | res = three_sum_closet(num, target) 26 | puts res 27 | -------------------------------------------------------------------------------- /4sum/solution.rb: -------------------------------------------------------------------------------- 1 | def four_sum(num, target) 2 | n = num.length 3 | num.sort! 4 | res = [] 5 | (0..n - 4).each do |a| 6 | next if a > 0 && num[a - 1] == num[a] 7 | (a + 1..n - 2).each do |b| 8 | next if b > a + 1 && num[b - 1] == num[b] 9 | c = b + 1 10 | d = n - 1 11 | while c < d 12 | s = num[a] + num[b] + num[c] + num[d] 13 | if s == target 14 | res.push([num[a], num[b], num[c], num[d]]) 15 | c += 1 16 | d -= 1 17 | c += 1 while c < d && num[c] == num[c - 1] 18 | d -= 1 while c < d && num[d] == num[d + 1] 19 | elsif s < target 20 | c += 1 21 | else 22 | d -= 1 23 | end 24 | end 25 | end 26 | end 27 | res 28 | end 29 | 30 | res = four_sum([-2, -1, 2, 5, 5, 7, 8], 12) 31 | p res 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Shichao An 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | leetcode-ruby 2 | ============= 3 | 4 | LeetCode problems in Ruby translated from leetcode-python 5 | -------------------------------------------------------------------------------- /add_binary/solution.rb: -------------------------------------------------------------------------------- 1 | # @param {String} a 2 | # @param {String} b 3 | # @return {String} 4 | def add_binary(a, b) 5 | res = [] 6 | b, a = a, b if a.length < b.length 7 | n = a.length 8 | m = b.length 9 | c = 0 10 | r = 0 11 | (0..n - 1).each do |k| 12 | i = n - 1 - k 13 | if k < m 14 | j = m - 1 - k 15 | r = (a[i].to_i + b[j].to_i + c) % 2 16 | c = (a[i].to_i + b[j].to_i + c) / 2 17 | else 18 | r = (a[i].to_i + c) % 2 19 | c = (a[i].to_i + c) / 2 20 | end 21 | res.insert(0, r) 22 | end 23 | res.insert(0, c) if c == 1 24 | res.join 25 | end 26 | 27 | p add_binary('110', '11') 28 | p add_binary('11', '11') 29 | p add_binary('101', '10') 30 | -------------------------------------------------------------------------------- /add_two_numbers/solution.rb: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode 3 | # attr_accessor :val, :next 4 | # def initialize(val) 5 | # @val = val 6 | # @next = nil 7 | # end 8 | # end 9 | 10 | # @param {ListNode} l1 11 | # @param {ListNode} l2 12 | # @return {ListNode} 13 | def add_two_numbers(l1, l2) 14 | carry = 0 15 | res = nil 16 | res_end = nil 17 | while !l1.nil? || !l2.nil? || carry == 1 18 | temp = 0 19 | unless l1.nil? 20 | temp += l1.val 21 | l1 = l1.next 22 | end 23 | unless l2.nil? 24 | temp += l2.val 25 | l2 = l2.next 26 | end 27 | temp += carry 28 | digit = temp % 10 29 | carry = temp / 10 30 | if res.nil? 31 | res = ListNode.new(digit) 32 | res_end = res 33 | else 34 | res_end.next = ListNode.new(digit) 35 | res_end = res_end.next 36 | end 37 | end 38 | res 39 | end 40 | -------------------------------------------------------------------------------- /anagrams/solution.rb: -------------------------------------------------------------------------------- 1 | def anagrams(strs) 2 | d = {} 3 | res = [] 4 | strs.each do |s| 5 | key = make_key(s) 6 | if d.key?(key) 7 | d[key].push(s) 8 | else 9 | d[key] = [s] 10 | end 11 | end 12 | d.each_key do |key| 13 | res.concat(d[key]) if d[key].length > 1 14 | end 15 | res 16 | end 17 | 18 | def make_key(s) 19 | d = {} 20 | res = [] 21 | s.each_char do |c| 22 | if d.key?(c) 23 | d[c] += 1 24 | else 25 | d[c] = 1 26 | end 27 | end 28 | ('a'..'z').each do |c| 29 | if d.key?(c) 30 | res.push(c) 31 | res.push(d[c]) 32 | end 33 | end 34 | res.join 35 | end 36 | 37 | strs = %w(abc pcd cba ssd psd cdp) 38 | p anagrams(strs) 39 | -------------------------------------------------------------------------------- /balanced_binary_tree/solution.rb: -------------------------------------------------------------------------------- 1 | def is_balanced(root) 2 | if root.nil? 3 | return true 4 | else 5 | if is_balanced(root.left) && is_balanced(root.right) 6 | return (depth(root.left) - depth(root.right)) <= 1 7 | else 8 | return false 9 | end 10 | end 11 | end 12 | 13 | def depth(root) 14 | if root.nil? 15 | return -1 16 | else 17 | [depth(root.left), depth(root.right)].max + 1 18 | end 19 | end 20 | 21 | class TreeNode 22 | attr_accessor :val, :left, :right 23 | def initialize(val, left, right) 24 | @val = val 25 | @left = left 26 | @right = right 27 | end 28 | end 29 | 30 | a = TreeNode.new(3, nil, nil) 31 | b = TreeNode.new(2, nil, nil) 32 | root = TreeNode.new(1, a, b) 33 | 34 | puts is_balanced(root) 35 | -------------------------------------------------------------------------------- /best_time_to_buy_and_sell_stock/solution.rb: -------------------------------------------------------------------------------- 1 | # @param {Integer[]} prices 2 | # @return {Integer} 3 | def max_profit(prices) 4 | return 0 if prices.empty? 5 | max_profit = 0 6 | min_price = prices[0] 7 | prices.each do |p| 8 | max_profit = [max_profit, p - min_price].max 9 | min_price = [min_price, p].min 10 | end 11 | max_profit 12 | end 13 | -------------------------------------------------------------------------------- /best_time_to_buy_and_sell_stock_ii/solution.rb: -------------------------------------------------------------------------------- 1 | # @param {Integer[]} prices 2 | # @return {Integer} 3 | def max_profit(prices) 4 | return 0 if prices.empty? 5 | max_profit = 0 6 | (1..prices.length - 1).each do |i| 7 | max_profit += prices[i] - prices[i - 1] if prices[i] > prices[i - 1] 8 | end 9 | max_profit 10 | end 11 | -------------------------------------------------------------------------------- /best_time_to_buy_and_sell_stock_iii/solution.rb: -------------------------------------------------------------------------------- 1 | # @param {Integer[]} prices 2 | # @return {Integer} 3 | def max_profit(prices) 4 | return 0 if prices.empty? 5 | n = prices.length 6 | m1 = (1..n).collect { 0 } 7 | m2 = (1..n).collect { 0 } 8 | max_profit1 = 0 9 | min_price1 = prices[0] 10 | max_profit2 = 0 11 | max_price2 = prices[-1] 12 | (0..n - 1).each do |i| 13 | max_profit1 = [max_profit1, prices[i] - min_price1].max 14 | m1[i] = max_profit1 15 | min_price1 = [min_price1, prices[i]].min 16 | end 17 | (0..n - 1).each do |i| 18 | max_profit2 = [max_profit2, max_price2 - prices[n - 1 - i]].max 19 | m2[n - 1 - i] = max_profit2 20 | max_price2 = [max_price2, prices[n - 1 - i]].max 21 | end 22 | max_profit = 0 23 | (0..n - 1).each do |i| 24 | max_profit = [max_profit, m1[i] + m2[i]].max 25 | end 26 | max_profit 27 | end 28 | -------------------------------------------------------------------------------- /binary_tree_inorder_traversal/solution.rb: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node 2 | # class TreeNode 3 | # attr_accessor :val, :left, :right 4 | # def initialize(val) 5 | # @val = val 6 | # @left, @right = nil, nil 7 | # end 8 | # end 9 | 10 | # @param {TreeNode} root 11 | # @return {Integer[]} 12 | def inorder_traversal(root) 13 | path = [] 14 | return path if root.nil? 15 | stack = [] 16 | while !stack.empty? || !root.nil? 17 | if !root.nil? 18 | stack.push(root) 19 | root = root.left 20 | else 21 | root = stack.pop 22 | path.push(root.val) 23 | root = root.right 24 | end 25 | end 26 | path 27 | end 28 | -------------------------------------------------------------------------------- /binary_tree_level_order_traversal/solution.rb: -------------------------------------------------------------------------------- 1 | def level_order(root) 2 | res = [] 3 | return res if root.nil? 4 | queue = [] 5 | level = [] 6 | queue.push(root) 7 | queue.push(nil) 8 | until queue.empty? 9 | root = queue.shift 10 | if root.nil? 11 | res.push(Array.new(level)) 12 | level = [] 13 | queue.push(nil) unless queue.empty? 14 | else 15 | level.push(root.val) 16 | queue.push(root.left) unless root.left.nil? 17 | queue.push(root.right) unless root.right.nil? 18 | end 19 | end 20 | res 21 | end 22 | -------------------------------------------------------------------------------- /binary_tree_level_order_traversal_ii/solution.rb: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode 3 | # attr_accessor :val, :left, :right 4 | # def initialize(val) 5 | # @val = val 6 | # @left, @right = nil, nil 7 | # end 8 | # end 9 | 10 | # @param {TreeNode} root 11 | # @return {Integer[][]} 12 | def level_order_bottom(root) 13 | res = [] 14 | return res if root.nil? 15 | queue = [] 16 | level = [] 17 | queue.push(root) 18 | queue.push(nil) 19 | until queue.empty? 20 | root = queue.shift 21 | if root.nil? 22 | res.push(Array.new(level)) 23 | level = [] 24 | queue.push(nil) unless queue.empty? 25 | else 26 | level.push(root.val) 27 | queue.push(root.left) unless root.left.nil? 28 | queue.push(root.right) unless root.right.nil? 29 | end 30 | end 31 | res.reverse! 32 | end 33 | -------------------------------------------------------------------------------- /binary_tree_postorder_traversal/solution.rb: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode 3 | # attr_accessor :val, :left, :right 4 | # def initialize(val) 5 | # @val = val 6 | # @left, @right = nil, nil 7 | # end 8 | # end 9 | 10 | # @param {TreeNode} root 11 | # @return {Integer[]} 12 | def postorder_traversal(root) 13 | res = [] 14 | return res if root.nil? 15 | stack = [] 16 | stack.push(root) 17 | until stack.empty? 18 | root = stack.pop 19 | res.push(root.val) 20 | stack.push(root.left) unless root.left.nil? 21 | stack.push(root.right) unless root.right.nil? 22 | end 23 | res.reverse! 24 | end 25 | -------------------------------------------------------------------------------- /binary_tree_preorder_traversal/solution.rb: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode 3 | # attr_accessor :val, :left, :right 4 | # def initialize(val) 5 | # @val = val 6 | # @left, @right = nil, nil 7 | # end 8 | # end 9 | 10 | # @param {TreeNode} root 11 | # @return {Integer[]} 12 | def preorder_traversal(root) 13 | res = [] 14 | return res if root.nil? 15 | stack = [] 16 | stack.push(root) 17 | until stack.empty? 18 | root = stack.pop 19 | res.push(root.val) 20 | stack.push(root.right) unless root.right.nil? 21 | stack.push(root.left) unless root.left.nil? 22 | end 23 | res 24 | end 25 | -------------------------------------------------------------------------------- /binary_tree_zigzag_level_order_traversal/solution.rb: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode 3 | # attr_accessor :val, :left, :right 4 | # def initialize(val) 5 | # @val = val 6 | # @left, @right = nil, nil 7 | # end 8 | # end 9 | 10 | # @param {TreeNode} root 11 | # @return {Integer[][]} 12 | def zigzag_level_order(root) 13 | res = [] 14 | return res if root.nil? 15 | queue = [] 16 | level = [] 17 | rev = false 18 | queue.push(root) 19 | queue.push(nil) 20 | until queue.empty? 21 | root = queue.shift 22 | if root.nil? 23 | queue.push(nil) unless queue.empty? 24 | res.push(Array.new(level)) 25 | level = [] 26 | rev = !rev 27 | else 28 | if rev == false 29 | level.push(root.val) 30 | else 31 | level.unshift(root.val) 32 | end 33 | queue.push(root.left) unless root.left.nil? 34 | queue.push(root.right) unless root.right.nil? 35 | end 36 | end 37 | res 38 | end 39 | -------------------------------------------------------------------------------- /climbing_stairs/solution.rb: -------------------------------------------------------------------------------- 1 | # @param {Integer} n 2 | # @return {Integer} 3 | def climb_stairs(n) 4 | t = Array.new(n + 1, 0) 5 | climb_stairs_helper(n, t) 6 | end 7 | 8 | def climb_stairs_helper(n, t) 9 | return t[n] if t[n] > 0 10 | if n == 0 || n == 1 11 | t[n] = 1 12 | else 13 | t[n] = climb_stairs_helper(n - 1, t) + climb_stairs_helper(n - 2, t) 14 | end 15 | t[n] 16 | end 17 | -------------------------------------------------------------------------------- /combination_sum/solution.rb: -------------------------------------------------------------------------------- 1 | # @param {Integer[]} candidates 2 | # @param {Integer} target 3 | # @return {Integer[][]} 4 | def combination_sum(candidates, target) 5 | candidates.sort! 6 | cand = [] 7 | res = [] 8 | combination_sum_helper(candidates, cand, target, res) 9 | res 10 | end 11 | 12 | def combination_sum_helper(candidates, cand, target, res) 13 | if target < 0 14 | return 15 | elsif target == 0 16 | res.push(Array.new(cand)) 17 | else 18 | candidates.each_with_index do |c, i| 19 | cand.push(c) 20 | combination_sum_helper(candidates[i..-1], cand, target - c, res) 21 | cand.pop 22 | end 23 | end 24 | end 25 | 26 | target = 7 27 | candidates = [2, 3, 6, 7] 28 | 29 | p combination_sum(candidates, target) 30 | -------------------------------------------------------------------------------- /combination_sum_ii/solution.rb: -------------------------------------------------------------------------------- 1 | # @param {Integer[]} candidates 2 | # @param {Integer} target 3 | # @return {Integer[][]} 4 | def combination_sum2(candidates, target) 5 | candidates.sort! 6 | cand = [] 7 | res = [] 8 | combination_sum_helper(candidates, cand, target, res) 9 | res 10 | end 11 | 12 | def combination_sum_helper(candidates, cand, target, res) 13 | if target < 0 14 | return 15 | elsif target == 0 16 | res.push(Array.new(cand)) 17 | else 18 | prev = nil 19 | candidates.each_with_index do |c, i| 20 | if i == 0 21 | prev = c 22 | elsif prev == c 23 | next 24 | else 25 | prev = c 26 | end 27 | cand.push(c) 28 | combination_sum_helper(candidates[i + 1..-1], cand, target - c, res) 29 | cand.pop 30 | end 31 | end 32 | end 33 | 34 | target = 7 35 | candidates = [2, 2, 3, 6, 5, 7] 36 | 37 | p combination_sum2(candidates, target) 38 | -------------------------------------------------------------------------------- /combinations/solution.rb: -------------------------------------------------------------------------------- 1 | # @param {Integer} n 2 | # @param {Integer} k 3 | # @return {Integer[][]} 4 | def combine(n, k) 5 | a = (1..n).to_a 6 | combine_helper(a, k) 7 | end 8 | 9 | def combine_helper(a, k) 10 | return [[]] if k == 0 11 | res = [] 12 | a.each_with_index do |e, i| 13 | rest_comb = combine_helper(a[i + 1..-1], k - 1) 14 | rest_comb.each do |comb| 15 | comb.unshift(e) 16 | end 17 | res += rest_comb 18 | end 19 | res 20 | end 21 | 22 | p combine(1, 1) 23 | p combine(4, 2) 24 | -------------------------------------------------------------------------------- /find_minimum_in_rotated_sorted_array/solution.rb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shichao-an/leetcode-ruby/056cb98f27bd4a8ce82c1591bb5b2319b1ff097e/find_minimum_in_rotated_sorted_array/solution.rb -------------------------------------------------------------------------------- /implement_strstr/solution.rb: -------------------------------------------------------------------------------- 1 | # @param {String} haystack 2 | # @param {String} needle 3 | # @return {Integer} 4 | def str_str(haystack, needle) 5 | n = haystack.length 6 | m = needle.length 7 | (0..n - m).each do |i| 8 | matched = true 9 | for j in (0..m - 1) 10 | if haystack[i + j] != needle[j] 11 | matched = false 12 | break 13 | end 14 | end 15 | return i if matched 16 | end 17 | -1 18 | end 19 | 20 | p str_str('abcdabcdefg', 'bcd') 21 | p str_str('', 'a') 22 | -------------------------------------------------------------------------------- /makedir.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | USAGE="./makedir.sh title [...]" 4 | 5 | [ "$#" -eq 0 ] && { 6 | echo "$USAGE" 7 | exit 1 8 | } 9 | 10 | SCRIPTDIR=$(dirname "$0") 11 | NEWDIR="$SCRIPTDIR/$(echo "$@" | tr 'A-Z ' 'a-z_' | tr -d "'")" 12 | 13 | [ -d "$NEWDIR" ] && { 14 | echo "This directory already exists" 15 | exit 1 16 | } 17 | 18 | echo "Creating new directory $NEWDIR ..." 19 | mkdir "$NEWDIR" 20 | touch "$NEWDIR/solution.rb" 21 | -------------------------------------------------------------------------------- /permutations/solution.rb: -------------------------------------------------------------------------------- 1 | # @param {Integer[]} nums 2 | # @return {Integer[][]} 3 | def permute(nums) 4 | if nums.empty? 5 | return [[]] 6 | else 7 | res = [] 8 | nums.each_with_index do |e, i| 9 | rest = nums[0, i] + nums[i + 1..-1] 10 | rest_perms = permute(rest) 11 | rest_perms.each do |perm| 12 | perm.push(e) 13 | end 14 | res += rest_perms 15 | end 16 | res 17 | end 18 | end 19 | 20 | p permute([1, 2, 3]) 21 | -------------------------------------------------------------------------------- /search_a_2d_matrix/solution.rb: -------------------------------------------------------------------------------- 1 | # Write an efficient algorithm that searches for a value in an m x n matrix. 2 | # This matrix has the following properties: 3 | # 4 | # Integers in each row are sorted from left to right. 5 | # The first integer of each row is greater than the last integer of the previous 6 | # row. 7 | # For example, 8 | # 9 | # Consider the following matrix: 10 | # 11 | # [ 12 | # [1, 3, 5, 7], 13 | # [10, 11, 16, 20], 14 | # [23, 30, 34, 50] 15 | # ] 16 | # Given target = 3, return true. 17 | 18 | # @param {Integer[][]} matrix 19 | # @param {Integer} target 20 | # @return {Boolean} 21 | def search_matrix(matrix, target) 22 | row_left = 0 23 | row_right = matrix.length - 1 24 | while row_left <= row_right 25 | row_mid = row_left + (row_right - row_left) / 2 26 | row = matrix[row_mid] 27 | if target >= row[0] && target <= row[-1] 28 | left = 0 29 | right = row.length - 1 30 | while left <= right 31 | mid = left + (right - left) / 2 32 | if target == row[mid] 33 | return true 34 | elsif target < row[mid] 35 | right = mid - 1 36 | else 37 | left = mid + 1 38 | end 39 | end 40 | return false 41 | elsif target < row[0] 42 | row_right = row_mid - 1 43 | else 44 | row_left = row_mid + 1 45 | end 46 | end 47 | false 48 | end 49 | 50 | p search_matrix([[1]], 2) 51 | p search_matrix([[1,3]], 2) 52 | -------------------------------------------------------------------------------- /search_in_rotated_sorted_array/solution.rb: -------------------------------------------------------------------------------- 1 | # Suppose a sorted array is rotated at some pivot unknown to you beforehand. 2 | # 3 | # (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). 4 | # 5 | # You are given a target value to search. If found in the array return its 6 | # index, otherwise return -1. 7 | # 8 | # You may assume no duplicate exists in the array. 9 | 10 | # @param {Integer[]} nums 11 | # @param {Integer} target 12 | # @return {Integer} 13 | def search(nums, target) 14 | n = nums.length 15 | left = 0 16 | right = n - 1 17 | while left <= right 18 | mid = left + (right - left) / 2 19 | if target == nums[mid] 20 | return mid 21 | # If left side is sorted 22 | elsif nums[mid] >= nums[-1] 23 | # Search the left side if target is within that range 24 | if nums[left] <= target && target < nums[mid] 25 | right = mid - 1 26 | else 27 | left = mid + 1 28 | end 29 | # If right side is sorted 30 | else 31 | # Search the right side if target is within that range 32 | if nums[mid] < target && target <= nums[right] 33 | left = mid + 1 34 | else 35 | right = mid - 1 36 | end 37 | end 38 | end 39 | -1 40 | end 41 | 42 | a1 = [4, 5, 6, 7, 0, 1, 2] 43 | p search(a1, 0) 44 | p search(a1, 5) 45 | p search(a1, 2) 46 | -------------------------------------------------------------------------------- /search_in_rotated_sorted_array_ii/solution.rb: -------------------------------------------------------------------------------- 1 | # Suppose a sorted array is rotated at some pivot unknown to you beforehand. 2 | # 3 | # (i.e., 0 1 2 4 5 6 7 might become 4 5 6 7 0 1 2). 4 | # 5 | # Follow up for "Search in Rotated Sorted Array": 6 | # 7 | # What if duplicates are allowed? 8 | # 9 | # Would this affect the run-time complexity? How and why? 10 | # 11 | # Write a function to determine if a given target is in the array. 12 | 13 | # @param {Integer[]} nums 14 | # @param {Integer} target 15 | # @return {Boolean} 16 | def search(nums, target) 17 | n = nums.length 18 | left = 0 19 | right = n - 1 20 | while left <= right 21 | mid = left + (right - left) / 2 22 | if target == nums[mid] 23 | return true 24 | # Left side is sorted 25 | elsif nums[mid] > nums[right] 26 | if nums[left] <= target && target < nums[mid] 27 | right = mid - 1 28 | else 29 | left = mid + 1 30 | end 31 | # Right side sorted 32 | elsif nums[mid] < nums[right] 33 | if nums[mid] < target && target <= nums[right] 34 | left = mid + 1 35 | else 36 | right = mid - 1 37 | end 38 | else 39 | right -= 1 40 | end 41 | end 42 | false 43 | end 44 | 45 | p search([1], 0) 46 | a1 = [4, 5, 6, 7, 0, 1, 2] 47 | p search(a1, 0) 48 | -------------------------------------------------------------------------------- /subsets/solution.rb: -------------------------------------------------------------------------------- 1 | # @param {Integer[]} nums 2 | # @return {Integer[][]} 3 | def subsets(nums) 4 | nums.sort! 5 | subsets_helper(nums) 6 | end 7 | 8 | def subsets_helper(nums) 9 | if nums.empty? 10 | return [[]] 11 | else 12 | res = [[]] 13 | nums.each_with_index do |e, i| 14 | rest_subsets = subsets_helper(nums[i + 1..-1]) 15 | rest_subsets.each do |subset| 16 | subset.insert(0, e) 17 | end 18 | res += rest_subsets 19 | end 20 | end 21 | res 22 | end 23 | 24 | p subsets([3, 2, 1]) 25 | -------------------------------------------------------------------------------- /summary_ranges/solution.rb: -------------------------------------------------------------------------------- 1 | # Given a sorted integer array without duplicates, return the summary of its 2 | # ranges. 3 | # 4 | # For example, given [0,1,2,4,5,7], return ["0->2","4->5","7"]. 5 | 6 | # @param {Integer[]} nums 7 | # @return {String[]} 8 | def summary_ranges(nums) 9 | res = [] 10 | n = nums.length 11 | left = -1 12 | right = -1 13 | nums.each_with_index do |e, i| 14 | if i == 0 15 | left = 0 16 | right = 0 17 | else 18 | if e != nums[i - 1] + 1 19 | r = make_range(left, right, nums) 20 | res.push(r) 21 | left = i 22 | end 23 | right = i 24 | end 25 | if i == n - 1 26 | right = i 27 | r = make_range(left, right, nums) 28 | res.push(r) 29 | end 30 | end 31 | res 32 | end 33 | 34 | def make_range(left, right, nums) 35 | if right > left 36 | return "#{nums[left]}->#{nums[right]}" 37 | elsif right == left 38 | return "#{nums[left]}" 39 | end 40 | end 41 | 42 | a1 = [0, 1, 2, 4, 5, 7] 43 | a2 = [0, 5, 9] 44 | p summary_ranges(a1) 45 | p summary_ranges(a2) 46 | --------------------------------------------------------------------------------