This repository has been archived by the owner on Feb 6, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
/
maximum_subarray.hpp
80 lines (67 loc) · 2.25 KB
/
maximum_subarray.hpp
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
71
72
73
74
75
76
77
78
79
80
// Andrew Naplavkov
#ifndef STEP_MAXIMUM_SUBARRAY_HPP
#define STEP_MAXIMUM_SUBARRAY_HPP
#include <iterator>
#include <utility>
namespace step::maximum_subarray {
namespace detail {
template <class T, class ForwardIt>
struct weighted_range {
T weight;
ForwardIt first;
ForwardIt last;
};
template <class T, class ForwardIt>
auto make_weighted_range(ForwardIt it)
{
return weighted_range<T, ForwardIt>{*it, it, std::next(it)};
}
} // namespace detail
/// Kadane's algorithm.
/// Find the bounds of the contiguous subrange which has the largest sum.
/// Time complexity O(N), space complexity O(1), where:
/// N = std::distance(first, last).
/// @return a pair of iterators defining the wanted subarray.
/// @see https://en.wikipedia.org/wiki/Maximum_subarray_problem
template <class ForwardIt, class BinaryOp, class Compare>
std::pair<ForwardIt, ForwardIt> find(ForwardIt first,
ForwardIt last,
BinaryOp op,
Compare cmp)
{
using weight_t = decltype(op(*first, *first));
if (first == last)
return {first, last};
auto rng = detail::make_weighted_range<weight_t>(first);
auto result = rng;
while (rng.last != last) {
rng.weight = op(std::move(rng.weight), *rng.last);
if (cmp(*rng.last, rng.weight))
++rng.last;
else
rng = detail::make_weighted_range<weight_t>(rng.last);
if (cmp(result.weight, rng.weight))
result = rng;
}
return {result.first, result.last};
}
template <class ForwardIt>
auto find(ForwardIt first, ForwardIt last)
{
return maximum_subarray::find(first, last, std::plus{}, std::less{});
}
template <class ForwardRng, class BinaryOp, class Compare>
auto find(const ForwardRng& rng, BinaryOp&& op, Compare&& cmp)
{
return maximum_subarray::find(std::begin(rng),
std::end(rng),
std::forward<BinaryOp>(op),
std::forward<Compare>(cmp));
}
template <class ForwardRng>
auto find(const ForwardRng& rng)
{
return maximum_subarray::find(std::begin(rng), std::end(rng));
}
} // namespace step::maximum_subarray
#endif // STEP_MAXIMUM_SUBARRAY_HPP