Use algorithm from Kamil:

Excluding sorting, this is O(n) which should be much faster and
much simpler and easier to understand.
This commit is contained in:
Lin Jen-Shin 2016-08-30 23:02:39 +08:00
parent 031b162392
commit bd78e6af29
1 changed files with 9 additions and 28 deletions

View File

@ -37,41 +37,22 @@ module Gitlab
if segments.empty?
segments
else
segments[1..-1].inject([segments.first]) do |current, target|
left, result = insert_segment(current, target)
segments.drop(1).inject([segments.first]) do |result, current|
merged = try_merge_segment(result.last, current)
if left # left is the latest one
result << left
else
if merged
result[-1] = merged
result
else
result << current
end
end
end
end
def insert_segment(segments, init)
segments.inject([init, []]) do |target_result, member|
target, result = target_result
if target.nil? # done
result << member
[nil, result]
elsif merged = try_merge_segment(target, member) # overlapped
[merged, result] # merge and keep finding the hole
elsif target.last < member.first # found the hole
result << target << member
[nil, result]
else
result << member
target_result
end
end
end
def try_merge_segment(target, member)
if target.first <= member.last && target.last >= member.first
Segment.new([target.first, member.first].min,
[target.last, member.last].max)
def try_merge_segment(previous, current)
if current.first <= previous.last
Segment.new(previous.first, [previous.last, current.last].max)
end
end