Skip to content

Commit 02b2c55

Browse files
Merge pull request #6 from theforestvn88/july
July
2 parents 17883ed + b3a2d51 commit 02b2c55

10 files changed

+386
-0
lines changed

0101-0200/0163_missing_ranges.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# @param {Integer[]} nums
2+
# @param {Integer} lower
3+
# @param {Integer} upper
4+
# @return {Integer[][]}
5+
def missing_ranges(nums, lower, upper)
6+
return [[lower, upper]] if nums.empty?
7+
8+
ans = []
9+
10+
if nums[0] > lower
11+
ans << [lower, nums[0]-1]
12+
end
13+
14+
nums.each_cons(2) { |a, b|
15+
if a < b-1
16+
ans << [a+1, b-1]
17+
end
18+
}
19+
20+
if nums[-1] < upper
21+
ans << [nums[-1]+1, upper]
22+
end
23+
24+
ans
25+
end
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# @param {Integer[][]} books
2+
# @param {Integer} shelf_width
3+
# @return {Integer}
4+
def min_height_shelves(books, shelf_width)
5+
# defining dp[i] as the min height for placing i books (IN ORDER)
6+
dp = Array.new(books.size + 1, Float::INFINITY)
7+
dp[0] = 0
8+
(0...books.size).each { |i|
9+
# for the next i-th book
10+
w, h = books[i]
11+
# we can:
12+
# place it on another level
13+
dp[i+1] = dp[i] + h
14+
# collect books [j..i-1] and place them at the same level, 0 <= j < i
15+
(i-1).downto(0) { |j|
16+
w += books[j][0]
17+
# Note that we need to place books IN ORDER
18+
# so we cannot place the i-th book at the same level of books [j..i-2] which above the (i-1)th book
19+
# therefor, if the width of books [j..i] is out of the shelf width, we stop
20+
break if w > shelf_width
21+
22+
h = [h, books[j][1]].max
23+
dp[i+1] = [dp[i+1], dp[j] + h].min
24+
}
25+
}
26+
27+
dp[books.size]
28+
end
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# @param {Integer[]} rating
2+
# @return {Integer}
3+
def num_teams(rating)
4+
max = rating.max
5+
count = 0
6+
7+
# for each k, there're teams formed by rating[k], previous rating[j] <= rating[k] - 1, and previous ratings[i] < rating[j]
8+
# ........ rating[k]-1 rating[k]
9+
# [i] j k
10+
counter = BinaryIndexedTree.new(max)
11+
accumulate = BinaryIndexedTree.new(max)
12+
(0...rating.size).each { |k|
13+
rate = rating[k]
14+
count += accumulate.range_sum(rate-1)
15+
accumulate.update(rate, counter.range_sum(rate-1))
16+
counter.update(rate, 1)
17+
}
18+
19+
# same as above, but in reverse direction
20+
counter = BinaryIndexedTree.new(max)
21+
accumulate = BinaryIndexedTree.new(max)
22+
(rating.size-1).downto(0) { |k|
23+
rate = rating[k]
24+
count += accumulate.range_sum(rate-1)
25+
accumulate.update(rate, counter.range_sum(rate-1))
26+
counter.update(rate, 1)
27+
}
28+
29+
count
30+
end
31+
32+
class BinaryIndexedTree
33+
attr_reader :counter
34+
35+
def initialize(size)
36+
@size = size
37+
@counter = Array.new(size+1, 0)
38+
end
39+
40+
def update(index, val)
41+
i = index + 1
42+
while i <= @size
43+
@counter[i] += val
44+
i += i & (-i)
45+
end
46+
end
47+
48+
def range_sum(index)
49+
sum = 0
50+
i = index + 1
51+
while i > 0
52+
sum += @counter[i]
53+
i -= i & (-i)
54+
end
55+
sum
56+
end
57+
end
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# @param {Integer} n
2+
# @param {Integer} start
3+
# @return {Integer}
4+
def xor_operation(n, start)
5+
n.times.reduce(0) { |acc, i| acc ^= (start + 2*i) }
6+
end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# @param {Integer[]} arr
2+
# @param {Integer} m
3+
# @param {Integer} k
4+
# @return {Boolean}
5+
def contains_pattern(arr, m, k)
6+
(0..arr.length-m).each { |i|
7+
pattern = arr[i...i+m]
8+
return true if (k-1).times.all? { |j|
9+
pattern == arr[(i + (j+1)*m)...(i + (j+2)*m)]
10+
}
11+
}
12+
false
13+
end
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# @param {String} s
2+
# @return {Integer}
3+
def minimum_deletions(s)
4+
# at the index i
5+
# ...........(a|b)...
6+
# [ balanced ]
7+
# assume that [0..i-1] is balanced by removing some 'a'/'b'
8+
# there're 3 ways to make [0..i] is also balanced:
9+
# - [1] if 'a' at i then:
10+
# + [1.1] we remove some 'a'/'b' same as [0..i-1] above and remove the 'a' at i
11+
# + [1.2] remove all 'b', let 'a' only
12+
# - [2] if 'b' at i, we remove some 'a'/'b' same as [0..i-1] above, and keep 'b' at i
13+
#
14+
15+
ans = 0 # number of removing some 'a'/'b' so far
16+
b_count = 0 # number of prefix 'b' so far
17+
s.each_char { |c|
18+
if c == 'b'
19+
b_count += 1
20+
# case [2], keep b, the ans so far is still optimal
21+
else
22+
# min of case [1.1] and case [1.2]
23+
ans = [ans + 1, b_count].min
24+
end
25+
}
26+
ans
27+
end
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# @param {Integer[][]} is_water
2+
# @return {Integer[][]}
3+
def highest_peak(is_water)
4+
r = is_water.size
5+
c = is_water[0].size
6+
result = Array.new(r) { Array.new(c, Float::INFINITY) }
7+
8+
queue = []
9+
(0...r).each { |i|
10+
(0...c).each { |j|
11+
if is_water[i][j] == 1
12+
result[i][j] = 0
13+
queue << [i, j]
14+
end
15+
}
16+
}
17+
18+
directions = [[-1, 0], [1, 0], [0, -1], [0, 1]]
19+
until queue.empty?
20+
i, j = queue.shift
21+
directions.each { |dr, dc|
22+
_i = i + dr
23+
_j = j + dc
24+
next if _i < 0 || _i >= r || _j < 0 || _j >= c
25+
26+
queue << [_i, _j] if result[_i][_j] == Float::INFINITY
27+
result[_i][_j] = [result[_i][_j], result[i][j] + 1].min
28+
}
29+
end
30+
31+
result
32+
end
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# @param {Integer} n
2+
# @param {Integer[][]} edges
3+
# @param {Integer} time
4+
# @param {Integer} change
5+
# @return {Integer}
6+
def second_minimum(n, edges, time, change)
7+
adj = Hash.new { |h, k| h[k] = [] }
8+
edges.each { |u, v|
9+
adj[u] << v
10+
adj[v] << u
11+
}
12+
13+
costs = Array.new(n+1) { [nil, nil] }
14+
queue = MinHeap.new
15+
queue.add([0, 1])
16+
until queue.empty?
17+
t, u = queue.extract_min
18+
wait = (t/change).odd? ? change - (t % change) : 0
19+
next_t = t + wait + time
20+
21+
adj[u].each { |v|
22+
next if costs[v][1] # already reached 2 times, no need to process
23+
24+
if costs[v][0].nil? # reach the first time
25+
costs[v][0] = next_t
26+
else # reach the second time
27+
costs[v][1] = next_t if costs[v][1].nil? && costs[v][0] < next_t
28+
end
29+
30+
return costs[v][1] if v == n && costs[v][1]
31+
32+
queue.add([next_t, v])
33+
}
34+
end
35+
end
36+
37+
class MinHeap
38+
def initialize
39+
@items = []
40+
end
41+
42+
def add(x)
43+
@items.push(x)
44+
swim_up(@items.size-1)
45+
end
46+
47+
def extract_min
48+
return if empty?
49+
50+
swap(0, @items.size-1)
51+
min = @items.pop()
52+
sink_down(0)
53+
min
54+
end
55+
56+
def empty?
57+
@items.empty?
58+
end
59+
60+
private
61+
62+
def swap(i, j)
63+
temp = @items[i]
64+
@items[i] = @items[j]
65+
@items[j] = temp
66+
end
67+
68+
def sink_down(i)
69+
return if (l = 2*i + 1) >= @items.size
70+
r = l + 1
71+
72+
min = (@items[l] <=> @items[r] || 0) <= 0 ? l : r
73+
if (@items[min] <=> @items[i]) < 0
74+
swap(min, i)
75+
sink_down(min)
76+
end
77+
end
78+
79+
def swim_up(i)
80+
return if (p = (i-1)/2) < 0
81+
if (@items[i] <=> @items[p]) < 0
82+
swap(i, p)
83+
swim_up(p)
84+
end
85+
end
86+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# @param {Integer[]} nums
2+
# @return {Integer[]}
3+
def distinct_difference_array(nums)
4+
prefix_diff = []
5+
prefix_appear = Hash.new(false)
6+
(0...nums.size).each { |i|
7+
prefix_appear[nums[i]] = true
8+
prefix_diff[i] = prefix_appear.size
9+
}
10+
11+
suffix_diff = []
12+
suffix_appear = Hash.new(false)
13+
(nums.size-1).downto(0).map { |i|
14+
suffix_diff[i] = suffix_appear.size
15+
suffix_appear[nums[i]] = true
16+
}
17+
18+
(0...nums.size).map { |i| prefix_diff[i] - suffix_diff[i] }
19+
end
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# @param {Integer} n
2+
# @param {Integer[][]} edges
3+
# @return {Boolean[]}
4+
def find_answer(n, edges)
5+
adj = Hash.new { |h, k| h[k] = [] }
6+
edges.each { |u, v, w|
7+
adj[u] << [v, w]
8+
adj[v] << [u, w]
9+
}
10+
11+
min_cost_from_source = dijkstra(adj, n, 0)
12+
min_cost_from_target = dijkstra(adj, n, n-1)
13+
14+
edges.map { |u, v, w|
15+
min_cost_from_source[n-1] < Float::INFINITY &&
16+
(min_cost_from_source[u] + w + min_cost_from_target[v] == min_cost_from_source[n-1] ||
17+
min_cost_from_source[v] + w + min_cost_from_target[u] == min_cost_from_source[n-1])
18+
}
19+
end
20+
21+
# https://en.wikipedia.org/wiki/Dijkstra's_algorithm
22+
def dijkstra(graph, n, source)
23+
dist = Array.new(n, Float::INFINITY)
24+
dist[source] = 0
25+
26+
queue = MinHeap.new
27+
queue.add([0, source])
28+
until queue.empty?
29+
cost, v = queue.extract_min
30+
next if cost > dist[v]
31+
32+
graph[v].each { |u, w|
33+
alt = dist[v] + w
34+
if dist[u] > alt
35+
dist[u] = alt
36+
queue.add([alt, u])
37+
end
38+
}
39+
end
40+
41+
dist
42+
end
43+
44+
class MinHeap
45+
def initialize
46+
@items = []
47+
end
48+
49+
def add(x)
50+
@items.push(x)
51+
swim_up(@items.size-1)
52+
end
53+
54+
def extract_min
55+
return if empty?
56+
57+
swap(0, @items.size-1)
58+
min = @items.pop()
59+
sink_down(0)
60+
min
61+
end
62+
63+
def empty?
64+
@items.empty?
65+
end
66+
67+
private
68+
69+
def swap(i, j)
70+
temp = @items[i]
71+
@items[i] = @items[j]
72+
@items[j] = temp
73+
end
74+
75+
def sink_down(i)
76+
return if (l = 2*i + 1) >= @items.size
77+
r = l + 1
78+
79+
min = (@items[l] <=> @items[r] || 0) <= 0 ? l : r
80+
if (@items[min] <=> @items[i]) < 0
81+
swap(min, i)
82+
sink_down(min)
83+
end
84+
end
85+
86+
def swim_up(i)
87+
return if (p = (i-1)/2) < 0
88+
if (@items[i] <=> @items[p]) < 0
89+
swap(i, p)
90+
swim_up(p)
91+
end
92+
end
93+
end

0 commit comments

Comments
 (0)