Skip to content
26 changes: 26 additions & 0 deletions 0401-0500/0457_circular_array_loop.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# @param {Integer[]} nums
# @return {Boolean}
def circular_array_loop(nums)
sign = lambda { |num| num > 0 ? 1 : -1 }
next_index = lambda { |i| i >= 0 ? (i % nums.size) : ((nums.size - (-i % nums.size)) % nums.size) }

(0...nums.size).any? do |i|
sign_i = sign.call(nums[i])
slow = i
fast = i
loop do
slow = next_index.call(slow + nums[slow])
break false if sign.call(nums[slow]) != sign_i

break false unless 2.times do
_fast = next_index.call(fast + nums[fast])
break false if _fast == fast

fast = _fast
break false if sign.call(nums[fast]) != sign_i
end

break true if fast == slow
end
end
end
49 changes: 49 additions & 0 deletions 0701-0800/0726_number_of_atoms.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# @param {String} formula
# @return {String}
def count_of_atoms(formula)
stack = []
i = 0
while i < formula.length
c = formula[i]
if (c >= "A" && c <= "Z") || c == ")"
curr_element = "#{c}"
while i + 1 < formula.length && formula[i+1] >= "a" && formula[i+1] <= "z"
curr_element << formula[i+1]
i += 1
end

curr_count = 0
while i + 1 < formula.length && formula[i+1] >= "0" && formula[i+1] <= "9"
curr_count = curr_count * 10 + formula[i+1].to_i
i += 1
end
curr_count = 1 if curr_count < 1

if c == ")"
sub_formula = []
until stack.empty? || stack[-1][0] == "("
element, count = stack.pop
sub_formula << [element, count * curr_count]
end

stack.pop
stack += sub_formula
elsif c >= "A" && c <= "Z"
stack << [curr_element, curr_count]
end
elsif c == "("
stack << [c, 0]
end

i += 1
end

counter = Hash.new {|h, k| h[k] = 0 }
stack.each do |element, count|
counter[element] += count
end

counter.entries.sort_by(&:first).map do |element, count|
"#{element}#{count > 1 ? count : ''}"
end.join
end
42 changes: 42 additions & 0 deletions 1101-1200/1110_delete_nodes_and_return_forest.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Definition for a binary tree node.
# class TreeNode
# attr_accessor :val, :left, :right
# def initialize(val = 0, left = nil, right = nil)
# @val = val
# @left = left
# @right = right
# end
# end
# @param {TreeNode} root
# @param {Integer[]} to_delete
# @return {TreeNode[]}
def del_nodes(root, to_delete)
to_delete = to_delete.map { |d| [d, true] }.to_h
forest = dfs(root, to_delete)
forest << root unless to_delete.has_key?(root.val)
forest
end

def dfs(node, to_delete)
return [] if node.nil?

trees = []

left = node.left
if to_delete.has_key?(left&.val)
node.left = nil
elsif to_delete.has_key?(node.val)
trees << left if left
end
trees += dfs(left, to_delete)

right = node.right
if to_delete.has_key?(right&.val)
node.right = nil
elsif to_delete.has_key?(node.val)
trees << right if right
end
trees += dfs(right, to_delete)

trees
end
16 changes: 12 additions & 4 deletions 1301-1400/1380_lucky_numbers_in_a_matrix.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,23 @@ def lucky_numbers (matrix)
end
end

lucky_nums = []
min_rows.each_with_index do |col_index, row_index|
lucky_nums << matrix[row_index][col_index] if max_cols[col_index] == row_index
# we can prove that there's only one lucky number
# given the input matrix contains only distinct numbers
# now let suppose [i,j] is the lucky number
# we assume that there's another lucky number [u,v]
# so we have: m[u][v] is the min of the row u => m[u][v] < m[u][j] < m[i][j]
# we also have: m[u][v] is the max of the col v => m[u][v] > m[i][v] > m[i][j]
# => m[u][v] < m[i][j] && m[u][v] > m[i][j] ==> wrong
# so either there's no [u,v] or [u,v] is [i,j],
# but the matrix contains only distinct numbers, so there's only one luck number.
return [matrix[row_index][col_index]] if max_cols[col_index] == row_index
end

lucky_nums
[]
end

# better
# more ruby style
def lucky_numbers (input)
input.transpose.map { |col| col.max } & input.map { |row| row.min }
end
32 changes: 32 additions & 0 deletions 1401-1500/1483_kth_ancestor_of_a_tree_node.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
class TreeAncestor
def initialize(n, parent)
# the max-height of the Binary-Lifting
# or the max-len of the bit representation of n count from the left-most significant
# ex: 156: "10011100" => 8
@max_height = Math.log(n, 2).ceil

@dp = Hash.new { |ancestor, node| ancestor[node] = Hash.new }

(0...n).each do |node|
@dp[node][0] = parent[node] # lift node(2^0=1) == this node's parent
end

(1..@max_height).each do |h|
(0...n).each do |node|
# the lift_node(2^h) = the lift_node(2^(h-1)) (if existed) lift up h-1
@dp[node][h] = @dp[node][h-1] == -1 ? -1 : (@dp[@dp[node][h-1]][h-1] || -1)
end
end
end

def get_kth_ancestor(node, k)
(0..@max_height).each do |i|
# only lift if the bit is 1
# ex: 156: "10011100" => will only lift at indexes: 2,3,4, and 7
node = @dp[node][i] unless (k & (1 << i)).zero?
break if node == -1
end
node
end
end

37 changes: 37 additions & 0 deletions 1501-1600/1530_number_of_good_leaf_nodes_pairs.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Definition for a binary tree node.
# class TreeNode
# attr_accessor :val, :left, :right
# def initialize(val = 0, left = nil, right = nil)
# @val = val
# @left = left
# @right = right
# end
# end
# @param {TreeNode} root
# @param {Integer} distance
# @return {Integer}
def count_pairs(root, distance)
count = 0
dfs = lambda { |node, dist|
return [0] if node.left.nil? && node.right.nil?

l = node.left ? dfs.call(node.left, dist) : []
r = node.right ? dfs.call(node.right, dist) : []
l = l.map { |d| d + 1 }
r = r.map { |d| d + 1 }

if !l.empty? && !r.empty?
l.each { |dl|
r.each { |dr|
count += 1 if dl + dr <= dist
}
}
end

(l + r).reject { |d| d >= dist }
}

dfs.call(root, distance)

count
end
17 changes: 17 additions & 0 deletions 1601-1700/1605_find_valid_matrix_given_row_and_column_sums.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# @param {Integer[]} row_sum
# @param {Integer[]} col_sum
# @return {Integer[][]}
def restore_matrix(row_sum, col_sum)
row_size = row_sum.size
col_size = col_sum.size
matrix = Array.new(row_size) { Array.new(col_size) }
(0...row_size).each { |r|
(0...col_size).each { |c|
matrix[r][c] = [row_sum[r], col_sum[c]].min
row_sum[r] -= matrix[r][c]
col_sum[c] -= matrix[r][c]
}
}

matrix
end
22 changes: 22 additions & 0 deletions 2001-2100/2063_vowels_of_all_substrings.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# @param {String} word
# @return {Integer}
def count_vowels(word)
vowels = 'aeiou'.freeze
vowels_count = 0
# assume we track all vowel indexes [i1, i2, .., in]
# ex: xxaxxxuxixxexxoxxa....
# [ 2 6 .............]
# for each new char c in word at index (in)
# all new subsets will be collected by sub array from c to every previous chars (vowel or not)
# if c is a vowel then we will have (in + 1) + ... + (i1 + 1) vowels
# if c is not a vowel then we will have (in-1 + 1) + ... + (i1 + 1) vowels
sum_vowel_indexes = 0
(0...word.size).each { |i|
if (vowels.include?(word[i]))
sum_vowel_indexes += i + 1
end
vowels_count += sum_vowel_indexes
}

vowels_count
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Definition for a binary tree node.
# class TreeNode
# attr_accessor :val, :left, :right
# def initialize(val = 0, left = nil, right = nil)
# @val = val
# @left = left
# @right = right
# end
# end
# @param {TreeNode} root
# @param {Integer} start_value
# @param {Integer} dest_value
# @return {String}
def get_directions(root, start_value, dest_value)
return "" if start_value == dest_value

start_path = dfs(root, start_value, "L") || dfs(root, start_value, "R")
dest_path = dfs(root, dest_value, "L") || dfs(root, dest_value, "R")
lca = nil
while !start_path.empty? && !dest_path.empty? && start_path[-1][0].val == dest_path[-1][0].val
start_path.pop
lca = dest_path.pop
end

start_path.map { |node, step| "U" }
.concat([lca[1]])
.concat(dest_path.reverse.map { |node, step| step })
.join
end

def dfs(node, target_val, step)
return if node.nil?
return [[node, nil]] if node.val == target_val

next_node = step == "L" ? node.left : node.right

l = dfs(next_node, target_val, "L")
return l << [node, step] if l

r = dfs(next_node, target_val, "R")
return r << [node, step] if r

nil
end
28 changes: 28 additions & 0 deletions 2101-2200/2196_create_binary_tree_from_descriptions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Definition for a binary tree node.
# class TreeNode
# attr_accessor :val, :left, :right
# def initialize(val = 0, left = nil, right = nil)
# @val = val
# @left = left
# @right = right
# end
# end
# @param {Integer[][]} descriptions
# @return {TreeNode}
def create_binary_tree(descriptions)
nodes = {}
descriptions.each do |parent_val, child_val, is_left|
child_node = nodes.dig(child_val, :tree_node) || TreeNode.new(child_val)
parent_node = nodes.dig(parent_val, :tree_node) || TreeNode.new(parent_val)
if is_left == 1
parent_node.left = child_node
else
parent_node.right = child_node
end

nodes[parent_val] = {tree_node: parent_node, is_child: nodes[parent_val]&.fetch(:is_child)}
nodes[child_val] = {tree_node: child_node, is_child: true}
end

nodes.values.find { |node| !node[:is_child] }.fetch(:tree_node)
end
22 changes: 22 additions & 0 deletions 2201-2300/2256_minimum_average_difference.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# @param {Integer[]} nums
# @return {Integer}
def minimum_average_difference(nums)
prefix_sums = [nums.first]
(1...nums.length).each { |i|
prefix_sums << (prefix_sums[-1] + nums[i])
}

min_index = prefix_sums.length
min_ave_diff = Float::INFINITY
(0...prefix_sums.length).map { |i|
l = prefix_sums[i]/(i+1)
r = prefix_sums.length-i-1 > 0 ? (prefix_sums[-1] - prefix_sums[i])/(prefix_sums.length-i-1) : 0
ave_diff = (l - r).abs
if min_ave_diff > ave_diff
min_index = i
min_ave_diff = ave_diff
end
}

min_index
end
40 changes: 40 additions & 0 deletions 2601-2700/2641_cousins_in_binary_tree_ii.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Definition for a binary tree node.
# class TreeNode
# attr_accessor :val, :left, :right
# def initialize(val = 0, left = nil, right = nil)
# @val = val
# @left = left
# @right = right
# end
# end
# @param {TreeNode} root
# @return {TreeNode}
def replace_value_in_tree(root)
level = [root]
until level.empty?
children = []
sum = 0
level.each { |node|
if node.left
children << node.left
sum += node.left.val
end

if node.right
children << node.right
sum += node.right.val
end
}

level.each { |node|
cousins_sum = sum - ((node.left&.val || 0) + (node.right&.val || 0))
node.left&.val = cousins_sum
node.right&.val = cousins_sum
}

level = children
end

root.val = 0
root
end
Loading