diff --git a/ruby/100-Same-Tree.rb b/ruby/100-Same-Tree.rb new file mode 100644 index 000000000..5168d6d83 --- /dev/null +++ b/ruby/100-Same-Tree.rb @@ -0,0 +1,11 @@ +def is_same_tree(p, q) + if p.nil? && q.nil? + true + elsif p && q + (p.val == q.val) && + is_same_tree(p.left, q.left) && + is_same_tree(p.right, q.right) + else + false + end +end diff --git a/ruby/104-Maximum-Depth-of-Binary-Tree.rb b/ruby/104-Maximum-Depth-of-Binary-Tree.rb new file mode 100644 index 000000000..816fd42c6 --- /dev/null +++ b/ruby/104-Maximum-Depth-of-Binary-Tree.rb @@ -0,0 +1,8 @@ +def max_depth(root) + return 0 if root.nil? + return 1 if root.left.nil? && root.right.nil? + + left = 1 + max_depth(root.left) + right = 1 + max_depth(root.right) + left > right ? left : right +end diff --git a/ruby/1046-Last-Stone-Weight.rb b/ruby/1046-Last-Stone-Weight.rb new file mode 100644 index 000000000..d919c8b53 --- /dev/null +++ b/ruby/1046-Last-Stone-Weight.rb @@ -0,0 +1,15 @@ +require 'rubygems' +require 'algorithms' +include Containers + +def last_stone_weight(stones) + heap = MaxHeap.new + stones.each { |stone| heap << stone } + until heap.size <= 1 + stone1 = heap.pop + stone2 = heap.pop + heap << (stone1 - stone2).abs if stone1 != stone2 + end + last = heap.pop + last.nil? ? 0 : last +end diff --git a/ruby/11-Container-With-Most-Water.rb b/ruby/11-Container-With-Most-Water.rb new file mode 100644 index 000000000..9f9b80157 --- /dev/null +++ b/ruby/11-Container-With-Most-Water.rb @@ -0,0 +1,17 @@ +def max_area(height) + idx_start = 0 + idx_end = height.length - 1 + max_water = 0 + while idx_start < idx_end + challenger = (height[idx_start] > height[idx_end] ? height[idx_end] : height[idx_start]) + challenger *= (idx_end - idx_start) + max_water = challenger if challenger > max_water + + if height[idx_start] > height[idx_end] + idx_end -= 1 + else + idx_start += 1 + end + end + max_water +end diff --git a/ruby/110-Balanced-Binary-Tree.rb b/ruby/110-Balanced-Binary-Tree.rb new file mode 100644 index 000000000..e64366129 --- /dev/null +++ b/ruby/110-Balanced-Binary-Tree.rb @@ -0,0 +1,15 @@ +def is_balanced(root) + $balance = true + balanced?(root) + $balance +end + +def balanced?(root) + return -1 if root.nil? + + left_height = 1 + balanced?(root.left) + right_height = 1 + balanced?(root.right) + $balance = false if (left_height - right_height).abs > 1 + + left_height > right_height ? left_height : right_height +end diff --git a/ruby/121-Best-Time-To-Buy-and-Sell-Stock.rb b/ruby/121-Best-Time-To-Buy-and-Sell-Stock.rb new file mode 100644 index 000000000..7adc19223 --- /dev/null +++ b/ruby/121-Best-Time-To-Buy-and-Sell-Stock.rb @@ -0,0 +1,10 @@ +def max_profit(prices) + max_profit = 0 + min = prices.first + prices.each do |price| + min = price if price < min + profit = price - min + max_profit = profit if profit > max_profit + end + max_profit +end diff --git a/ruby/125-Valid-Palindrome.rb b/ruby/125-Valid-Palindrome.rb new file mode 100644 index 000000000..b174cbd91 --- /dev/null +++ b/ruby/125-Valid-Palindrome.rb @@ -0,0 +1,35 @@ +def is_palindrome(s) + str = s.downcase.chars.select { |char| /[a-zA-Z0-9]/.match?(char) }.join + idx_start = 0 + idx_end = str.length - 1 + while idx_start < idx_end + return false if str[idx_start] != str[idx_end] + + idx_start += 1 + idx_end -= 1 + end + true +end + +def is_palindrome(s) + idx_start = 0 + idx_end = s.length - 1 + while idx_start < idx_end + if !/[a-zA-Z0-9]/.match?(s[idx_start]) + idx_start += 1 + elsif !/[a-zA-Z0-9]/.match?(s[idx_end]) + idx_end -= 1 + else + return false if s[idx_start].downcase != s[idx_end].downcase + + idx_start += 1 + idx_end -= 1 + end + end + true +end + +def is_palindrome(s) + str = s.downcase.chars.select { |char| /[a-zA-Z0-9]/.match?(char) } + str == str.reverse +end diff --git a/ruby/141-Linked-List-Cycle.rb b/ruby/141-Linked-List-Cycle.rb new file mode 100644 index 000000000..b2f3e07bf --- /dev/null +++ b/ruby/141-Linked-List-Cycle.rb @@ -0,0 +1,31 @@ +def hasCycle(head) + return false if head.nil? + return false if head.next.nil? + + dict = {} + while head + return true if dict.key?(head) + + dict[head] = true + head = head.next + end + false +end + +# Tortoise and Hare solution +def hasCycle(head) + return false if head.nil? + return false if head.next.nil? + + fast = head + while head && fast + fast = fast.next + return false if fast.nil? + + fast = fast.next + head = head.next + + return true if head == fast + end + false +end diff --git a/ruby/15-3Sum.rb b/ruby/15-3Sum.rb new file mode 100644 index 000000000..d963c4727 --- /dev/null +++ b/ruby/15-3Sum.rb @@ -0,0 +1,23 @@ +def three_sum(nums) + sums = [] + nums.sort! # This is to get rid of duplicate solutions + nums.each_with_index do |num, idx| + next if idx.positive? && num == nums[idx - 1] + + left = idx + 1 + right = nums.length - 1 + while left < right + case num + nums[left] + nums[right] <=> 0 + when 1 + right -= 1 + when 0 + sums << [num, nums[left], nums[right]] + left += 1 + left += 1 while nums[left] == nums[left - 1] && left < right + when -1 + left += 1 + end + end + end + sums +end diff --git a/ruby/155-Min-Stack.rb b/ruby/155-Min-Stack.rb new file mode 100644 index 000000000..9f62c9560 --- /dev/null +++ b/ruby/155-Min-Stack.rb @@ -0,0 +1,33 @@ +class MinStack + def initialize + @stack = [] + end + + def push(val) + min = if @stack.empty? + val + else + val < @stack.last[1] ? val : @stack.last[1] + end + + @stack << [val, min] + nil + end + + def pop + @stack.pop + nil + end + + def top + return nil if @stack.empty? + + @stack.last[0] + end + + def get_min + return nil if @stack.empty? + + @stack.last[1] + end +end diff --git a/ruby/167-Two-Sum-II.rb b/ruby/167-Two-Sum-II.rb new file mode 100644 index 000000000..70573005c --- /dev/null +++ b/ruby/167-Two-Sum-II.rb @@ -0,0 +1,15 @@ +def two_sum(numbers, target) + idx_start = 0 + idx_end = numbers.length - 1 + while idx_start < idx_end + case numbers[idx_start] + numbers[idx_end] <=> target + when 1 + idx_end -= 1 + when 0 + return [idx_start + 1, idx_end + 1] + when -1 + idx_start += 1 + end + end + nil +end diff --git a/ruby/20-Valid-Parentheses.rb b/ruby/20-Valid-Parentheses.rb new file mode 100644 index 000000000..ce364ea32 --- /dev/null +++ b/ruby/20-Valid-Parentheses.rb @@ -0,0 +1,17 @@ +def is_valid(s) + paren = [] + match = { + '{' => '}', + '(' => ')', + '[' => ']' + } + s.each_char do |char| + if match.key?(char) + paren << char + else + return false if paren.empty? + return false if match[paren.pop] != char + end + end + paren.empty? +end diff --git a/ruby/206-Reverse-Linked-List.rb b/ruby/206-Reverse-Linked-List.rb new file mode 100644 index 000000000..148c5e5a2 --- /dev/null +++ b/ruby/206-Reverse-Linked-List.rb @@ -0,0 +1,28 @@ +def reverse_list(head) + next_node = nil + prev_node = nil + loop do + next_node = head.next + head.next = prev_node + prev_node = head + if next_node.nil? + return head + else + head = next_node + end + end +end + +# Recursive +def reverse_list(head) + return head if head.nil? + + new_head = head + if head.next + new_head = reverse_list(head.next) + head.next.next = head + end + + head.next = nil + new_head +end diff --git a/ruby/21-Merge-Two-Sorted-Lists.rb b/ruby/21-Merge-Two-Sorted-Lists.rb new file mode 100644 index 000000000..27aad4d12 --- /dev/null +++ b/ruby/21-Merge-Two-Sorted-Lists.rb @@ -0,0 +1,22 @@ +def merge_two_lists(list1, list2) + return nil if list1.nil? && list2.nil? + + dummy = ListNode.new + beginning = dummy + while list1 && list2 + if list1.val > list2.val + dummy.next = list2 + list2 = list2.next + else + dummy.next = list1 + list1 = list1.next + end + dummy = dummy.next + end + if list1 + dummy.next = list1 + elsif list2 + dummy.next = list2 + end + beginning.next +end diff --git a/ruby/226-Invert-Binary-Tree.rb b/ruby/226-Invert-Binary-Tree.rb new file mode 100644 index 000000000..e4e39ae7b --- /dev/null +++ b/ruby/226-Invert-Binary-Tree.rb @@ -0,0 +1,9 @@ +def invert_tree(root) + return root if root.nil? + return root if root.left.nil? && root.right.nil? + + root.left, root.right = root.right, root.left + invert_tree(root.left) + invert_tree(root.right) + root +end diff --git a/ruby/235-Lowest-Common-Ancestor-of-a-Binary-Search-Tree.rb b/ruby/235-Lowest-Common-Ancestor-of-a-Binary-Search-Tree.rb new file mode 100644 index 000000000..b082d83a7 --- /dev/null +++ b/ruby/235-Lowest-Common-Ancestor-of-a-Binary-Search-Tree.rb @@ -0,0 +1,10 @@ +def lowest_common_ancestor(root, p, q) + return root if root.val == p.val || root.val == q.val + return root if root.val.between?(p.val, q.val) || root.val.between?(q.val, p.val) + + if root.val > p.val + lowest_common_ancestor(root.left, p, q) + else + lowest_common_ancestor(root.right, p, q) + end +end diff --git a/ruby/3-Longest-Substring-Without-Repeating-Characters.rb b/ruby/3-Longest-Substring-Without-Repeating-Characters.rb new file mode 100644 index 000000000..49b0ebf11 --- /dev/null +++ b/ruby/3-Longest-Substring-Without-Repeating-Characters.rb @@ -0,0 +1,19 @@ +def length_of_longest_substring(s) + return 1 if s.length == 1 + return 0 if s.length.zero? + + window = [] + appear = {} + max = 0 + s.each_char do |c| + if appear.key?(c) + while appear.key?(c) + appear.delete(window.shift) + end + end + window << c + appear[c] = c + max = window.length if window.length > max + end + max +end diff --git a/ruby/42-Trapping-Rain-Water.rb b/ruby/42-Trapping-Rain-Water.rb new file mode 100644 index 000000000..6d88f4e2c --- /dev/null +++ b/ruby/42-Trapping-Rain-Water.rb @@ -0,0 +1,49 @@ +def trap(height) + max_left = [] + max_right = [] + + max = 0 + height.each do |line| + max_left << max + max = line if line > max + end + + max = 0 + (height.length - 1).downto(0).each do |idx| + max_right.unshift(max) + max = height[idx] if height[idx] > max + end + + total_water = 0 + height.each_with_index do |line, idx| + min = max_left[idx] > max_right[idx] ? max_right[idx] : max_left[idx] + water = min - line + next if water < 1 + + total_water += water + end + total_water +end + +# 0(1) space +def trap(height) + max_water = 0 + max_left = height.first + max_right = height.last + left = 0 + right = height.length - 1 + + while left < right + if max_left > max_right + right -= 1 + water = max_right - height[right] + max_right = height[right] if height[right] > max_right + else + left += 1 + water = max_left - height[left] + max_left = height[left] if height[left] > max_left + end + max_water += water unless water < 1 + end + max_water +end diff --git a/ruby/424-Longest-Repeating-Character-Replacement.rb b/ruby/424-Longest-Repeating-Character-Replacement.rb new file mode 100644 index 000000000..e806f24fa --- /dev/null +++ b/ruby/424-Longest-Repeating-Character-Replacement.rb @@ -0,0 +1,30 @@ +def character_replacement(s, k) + return 0 if s.length.zero? + return 1 if s.length == 1 + + max = 0 + window = [] + dict = Hash.new(0) + left = 0 + right = left + while true + break if s[right].nil? + + char = s[right] + window << char + dict[char] += 1 + until window.length - highest_freq(dict) <= k + dict[window.shift] -= 1 + left += 1 + end + max = window.length if window.length > max + right += 1 + end + max +end + +def highest_freq(dict) + max = 0 + dict.each { |_k, v| max = v if v > max } + max +end diff --git a/ruby/543-Diameter-of-Binary-Tree.rb b/ruby/543-Diameter-of-Binary-Tree.rb new file mode 100644 index 000000000..7833ce5a6 --- /dev/null +++ b/ruby/543-Diameter-of-Binary-Tree.rb @@ -0,0 +1,16 @@ +def diameter_of_binary_tree(root) + $max = 0 + max_height = diameter(root) + $max > max_height ? $max : max_height +end + +def diameter(root) + return -1 if root.nil? + + left = 1 + diameter(root.left) + right = 1 + diameter(root.right) + diameter = left + right + $max = diameter if diameter > $max + + left > right ? left : right +end diff --git a/ruby/572-Subtree-of-Another-Tree.rb b/ruby/572-Subtree-of-Another-Tree.rb new file mode 100644 index 000000000..1ccd9112f --- /dev/null +++ b/ruby/572-Subtree-of-Another-Tree.rb @@ -0,0 +1,24 @@ +def is_subtree(root, sub_root) + return true if root.nil? && sub_root.nil? + return true if sub_root.nil? + return false if root.nil? + + if same_tree?(root, sub_root) + true + else + is_subtree(root.left, sub_root) || + is_subtree(root.right, sub_root) + end +end + +def same_tree?(p, q) + if p.nil? && q.nil? + true + elsif p && q + (p.val == q.val) && + same_tree?(p.left, q.left) && + same_tree?(p.right, q.right) + else + false + end +end diff --git a/ruby/703-Kth-Largest-Element-in-a-Stream.rb b/ruby/703-Kth-Largest-Element-in-a-Stream.rb new file mode 100644 index 000000000..78a5ca624 --- /dev/null +++ b/ruby/703-Kth-Largest-Element-in-a-Stream.rb @@ -0,0 +1,16 @@ +require 'rb_heap' + +class KthLargest + def initialize(k, nums) + @k = k + @heap = Heap.new + nums.each { |num| @heap << num } + @heap.pop until @heap.size <= @k + end + + def add(val) + @heap << val + @heap.pop until @heap.size <= @k + @heap.peak + end +end