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:
parent
031b162392
commit
bd78e6af29
|
@ -37,41 +37,22 @@ module Gitlab
|
||||||
if segments.empty?
|
if segments.empty?
|
||||||
segments
|
segments
|
||||||
else
|
else
|
||||||
segments[1..-1].inject([segments.first]) do |current, target|
|
segments.drop(1).inject([segments.first]) do |result, current|
|
||||||
left, result = insert_segment(current, target)
|
merged = try_merge_segment(result.last, current)
|
||||||
|
|
||||||
if left # left is the latest one
|
if merged
|
||||||
result << left
|
result[-1] = merged
|
||||||
else
|
|
||||||
result
|
result
|
||||||
|
else
|
||||||
|
result << current
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def insert_segment(segments, init)
|
def try_merge_segment(previous, current)
|
||||||
segments.inject([init, []]) do |target_result, member|
|
if current.first <= previous.last
|
||||||
target, result = target_result
|
Segment.new(previous.first, [previous.last, current.last].max)
|
||||||
|
|
||||||
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)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue