Skip to content
25 changes: 25 additions & 0 deletions 0201-0300/0224_basic_calculator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# @param {String} s
# @return {Integer}
def calculate(s, i = 0, j = s.length-1)
sum = 0
curr = 0
curr_sign = 1 # 1 for +, -1 for -
signs_stack = [1]
while i <= j
if s[i] >= "0" && s[i] <= "9"
curr = curr * 10 + s[i].to_i
elsif s[i] == "+" || s[i] == "-"
sum += curr_sign * curr
curr = 0
# -(-(x)) == +x
curr_sign = (s[i] == "+" ? 1 : -1) * signs_stack[-1]
elsif s[i] == "("
signs_stack.push(curr_sign.dup)
elsif s[i] == ")"
signs_stack.pop
end
i += 1
end

sum += curr_sign * curr
end
46 changes: 46 additions & 0 deletions 0301-0400/0386_lexicographical_numbers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# @param {Integer} n
# @return {Integer[]}
def lexical_order(n)
trie = Trie.new
(1..n).each { |num| trie.add(num) }
trie.lexicographical
end

class Trie
class Node
attr_accessor :children, :num

def initialize
@children = Array.new(10)
@num = nil
end
end

def initialize
@root = Node.new
end

def add(num)
node = @root
digits = num.digits.reverse
until digits.empty?
d = digits.shift
node.children[d] = Node.new if node.children[d].nil?
node = node.children[d]
end
node.num = num
end

def lexicographical(node = @root)
nums = []
return nums if node.nil?

nums << node.num if node.num

(0..9).each { |i|
nums += lexicographical(node.children[i])
}

nums
end
end
12 changes: 12 additions & 0 deletions 0501-0600/0507_perfect_number.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# @param {Integer} num
# @return {Boolean}
def check_perfect_number(num)
return false if num == 1

sum = 1
(2..Math.sqrt(num)).each { |i|
sum += i + num/i if num % i == 0
}

sum == num
end
48 changes: 48 additions & 0 deletions 0901-1000/0912_sort_an_array.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#
# You must solve the problem without using any built-in functions
#

#
# Quick Sort
#
Expand Down Expand Up @@ -45,3 +49,47 @@ def sort_array(nums)

sorted
end


#
# Merge Sort
#
def sort_array(nums)
merge_sort(nums)
end

def merge_sort(arr, left = 0, right = arr.length-1)
return arr if left == right

mid = (left + right)/2
left_sorted = merge_sort(arr[left..mid])
right_sorted = merge_sort(arr[mid+1..right])
merge(left_sorted, right_sorted)
end

def merge(left, right)
arr = []

i = j = 0
while i < left.length && j < right.length
if left[i] <= right[j]
arr << left[i]
i += 1
else
arr << right[j]
j += 1
end
end

while i < left.length
arr << left[i]
i += 1
end

while j < right.length
arr << right[j]
j += 1
end

arr
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# @param {Integer} n
# @param {Integer[][]} edges
# @param {Integer} distance_threshold
# @return {Integer}
def find_the_city(n, edges, distance_threshold)
shortest_dist = floy_warshall(n, edges)

min = Float::INFINITY
min_index = nil
(0...n).each { |i|
count = 0
(0...n).each { |j|
count += 1 if shortest_dist[i][j] <= distance_threshold
}

if min >= count
min = count
min_index = i
end
}

min_index
end

# https://en.wikipedia.org/wiki/Floyd–Warshall_algorithm
def floy_warshall(n, edges)
dist = Array.new(n) { Array.new(n, Float::INFINITY) }

edges.each { |u, v, w|
dist[u][v] = w
dist[v][u] = w
}

(0...n).each { |u|
dist[u][u] = 0
}

(0...n).each { |k|
(0...n).each { |i|
(0...n).each { |j|
dist[i][j] = [dist[i][j], dist[i][k] + dist[k][j]].min
}
}
}

dist
end
9 changes: 9 additions & 0 deletions 1601-1700/1636_sort_array_by_increasing_frequency.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# @param {Integer[]} nums
# @return {Integer[]}
def frequency_sort(nums)
nums.tally.entries.sort { |(num1, count1), (num2, count2)|
count1 == count2 ? (num2 <=> num1) : (count1 <=> count2)
}.map { |num, count|
Array.new(count, num)
}.flatten
end
11 changes: 11 additions & 0 deletions 1801-1900/1884_egg_drop_with_2_eggs_and_n_floors.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# @param {Integer} n
# @return {Integer}
def two_egg_drop(n)
# jump search multiple levels
# set the first optimal block size is x
# then we have: x + (x-1) + ... + 1 = n
# => x(x+1)/2 = n
# => x**2 + x -2n = 0
# => x = (-1 + Math.sqrt(1 + 8n))/2
((-1 + Math.sqrt(1 + 8*n))/2).ceil
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# @param {Integer} needed_apples
# @return {Integer}
def minimum_perimeter(needed_apples)
# for each radius r, the additional number of apples is r*r*12
# so sum of apples inside a square with a side length L (r = L/2, perimeter = L*4 = r*8):
# = (1**2 + 2**2 + ... + r**2) * 12
# = (r*(r+1)*(2*r+1)/6) * 12
formular_apples_count = lambda { |r| r*(r+1)*(2*r+1)*2 }

low = 0
high = needed_apples
while low < high
m = (low + high)/2
apples_count = formular_apples_count.call(m)

return m * 8 if apples_count == needed_apples

if apples_count > needed_apples
high = m
else
low = m + 1
end
end

low * 8
end
9 changes: 9 additions & 0 deletions 2001-2100/2022_convert_1d_array_into_2d_array.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# @param {Integer[]} original
# @param {Integer} m
# @param {Integer} n
# @return {Integer[][]}
def construct2_d_array(original, m, n)
return [] if original.size != m * n

original.each_slice(n).to_a
end
36 changes: 36 additions & 0 deletions 2101-2200/2176_count_equal_and_divisible_pairs_in_an_array.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# brute force
# @param {Integer[]} nums
# @param {Integer} k
# @return {Integer}
def count_pairs(nums, k)
count = 0
(0...nums.size).each { |i|
(i+1...nums.size).each { |j|
count += 1 if nums[i] == nums[j] && (i * j) % k == 0
}
}

count
end

# optimal
def count_pairs(nums, k)
num_indexes = Hash.new { |h, k| h[k] = [] }
nums.each_with_index { |num, i|
num_indexes[num] << i
}

count = 0
num_indexes.values.each { |indexes|
gcds = Array.new(k+1, 0)
indexes.each { |index|
gcd_i = index.gcd(k)
gcds.each_with_index { |c, gcd_j|
count += c if (gcd_i * gcd_j) % k == 0
}
gcds[gcd_i] += 1
}
}

count
end
12 changes: 12 additions & 0 deletions 2101-2200/2191_sort_the_jumbled_numbers.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# @param {Integer[]} mapping
# @param {Integer[]} nums
# @return {Integer[]}
def sort_jumbled(mapping, nums)
mapped = mapping.map.with_index { |m, i| [i, m] }.to_h

nums.map { |num|
[num, num.digits.reverse.map { |d| mapped[d] }.join.to_i]
}
.sort_by(&:last)
.map(&:first)
end
57 changes: 57 additions & 0 deletions 2301-2400/2392_build_a_matrix_with_conditions.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# @param {Integer} k
# @param {Integer[][]} row_conditions
# @param {Integer[][]} col_conditions
# @return {Integer[][]}
def build_matrix(k, row_conditions, col_conditions)
matrix = Array.new(k) { Array.new(k, 0) }

row_order = topological_sort(k, adj_matrix(row_conditions))
return [] if row_order.empty?

col_order = topological_sort(k, adj_matrix(col_conditions))
return [] if col_order.empty?

col_order_map = col_order.map.with_index { |c, i| [c, i] }.to_h
row_order.each_with_index { |r, i|
matrix[i][col_order_map[r]] = r
}

matrix
end

def adj_matrix(edges)
adj = Hash.new { |h, k| h[k] = [] }
edges.each { |u, v|
adj[u] << v
}

adj
end

def topological_sort(n, adj)
# Kahn algorithm
indegrees = Array.new(n+1) { 0 }
adj.values.each { |a|
a.each { |v|
indegrees[v] += 1
}
}

order = []
queue = (1..n).select { |i| indegrees[i].zero? }
until queue.empty?
u = queue.pop
order.push(u)
adj[u].each { |v|
indegrees[v] -= 1
if indegrees[v].zero?
queue.push(v)
end
}
end

# detect cycle
return [] if order.size != n

order
end
6 changes: 6 additions & 0 deletions 2401-2500/2418_sort_the_people.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# @param {String[]} names
# @param {Integer[]} heights
# @return {String[]}
def sort_people(names, heights)
names.zip(heights).sort_by(&:last).map(&:first).reverse
end
16 changes: 16 additions & 0 deletions 2801-2900/2860_happy_students.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# @param {Integer[]} nums
# @return {Integer}
def count_ways(nums)
nums.sort!

# if the happy of the first student > 0
# the teacher can choice no one
count = nums.first > 0 ? 1 : 0

(0...nums.size-1).each { |i|
count += 1 if nums[i] < i + 1 && nums[i+1] > i + 1
}

# add 1 because the teacher always can select all students
count + 1
end
Loading