forked from gcallah/algorithms
-
Notifications
You must be signed in to change notification settings - Fork 0
/
find_max_subarray.rb
70 lines (65 loc) · 2.12 KB
/
find_max_subarray.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
module DivideAndConquer
class << self
# Internal: Computes the sum of the left, right halves and their index where max is reached
#
# ARGS:
# arr - Array where the sub-array has to be found
# low - Index of the first element in arr
# mid - Index of the middle element in arr
# high - Index of the last element in arr
#
# Return: Array (Triplet)
#
# Examples
# find_max_crossing_subarray([-2, -3, 4, -1, -2, 1, 5, -3], 0, 3, 7)
# => [2, 6, 7]
def find_max_crossing_subarray(arr, low, mid, high)
sum = max_left = 0
left_sum = -Float::INFINITY
max_left = 0
(low..mid).reverse_each do |i|
sum += arr[i]
if sum > left_sum
left_sum = sum
max_left = i
end
end
sum = max_right = 0
right_sum = -Float::INFINITY
(mid+1..high).each do |j|
sum += arr[j]
if sum > right_sum
right_sum = sum
max_right = j
end
end
[max_left, max_right, left_sum+right_sum]
end
# Internal: Computes the maximum sub array which returns maximum sum over a range
# Recursive strategy
#
# ARGS:
# arr - Array where the sub-array has to be found
# low - Index of the first element in arr
# high - Index of the last element in arr
#
# Return: Array (Triplet)
#
# Examples
# find_max_subarray([-2, -3, 4, -1, -2, 1, 5, -3], 0, 7)
# find_max_subarray([-2, -3, 4, -1, -2, 1, 5, -3])
# => [2, 6, 7]
def find_max_subarray(arr, low=0, high=arr.length-1)
low ||= 0
high ||= arr.length-1
return [low, high, arr[low]] if low == high
mid = (low+high)/2
left_subarray = find_max_subarray(arr, low, mid)
right_subarray = find_max_subarray(arr, mid+1, high)
cross_subarray = find_max_crossing_subarray(arr, low, mid, high)
return left_subarray if left_subarray[2] > right_subarray[2] && left_subarray[2] > cross_subarray[2]
return right_subarray if right_subarray[2] > left_subarray[2] && right_subarray[2] > cross_subarray[2]
return cross_subarray
end
end
end