forked from ProAlgos/ProAlgos-Cpp
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathternary_search.cpp
More file actions
104 lines (89 loc) · 2.85 KB
/
ternary_search.cpp
File metadata and controls
104 lines (89 loc) · 2.85 KB
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/*
Ternary search
--------------
A searching algorithm that finds the position of a maximum(minimum) value
within an unimodal array.
Time complexity
---------------
O(log(N)), where N is the number of elements in the array.
Space complexity
----------------
O(1).
*/
#include <iostream>
#include <vector>
using namespace std;
enum Pattern {
ASCEND_THEN_DESCEND,
DESCEND_THEN_ASCEND
};
/*
ternary_search
-------------
If the values first ascend and then descend, this function finds the position
of the maximum value. Otherwise, if they first descend and then ascend, it
finds the position of the minimum value.
*/
template <typename T>
size_t ternary_search(const vector<T>& values, const Pattern& pattern) {
// left and right are the edges of the interval of search
size_t left = 0;
size_t right = values.size() - 1;
bool changed = true;
size_t mid1, mid2;
while (right - left > 1 and changed) { // if the interval is not shrinking,
// its size already equals O(1)
changed = false;
mid1 = left + (right - left) / 3;
mid2 = right - (right - left) / 3;
if ((pattern and values[mid1] < values[mid2])
or (!pattern and values[mid1] > values[mid2])) {
changed |= (right != mid2);
right = mid2;
}
else {
changed |= (left != mid1);
left = mid1;
}
}
T min_value = values[left];
T max_value = values[left];
size_t min_index = left;
size_t max_index = left;
for (size_t index = left + 1; index <= right; index++) {
if (min_value > values[index]) {
min_value = values[index];
min_index = index;
}
if (max_value < values[index]) {
max_value = values[index];
max_index = index;
}
}
return pattern == ASCEND_THEN_DESCEND ? max_index : min_index;
}
#ifndef TERNARY_SEARCH_TEST
int main() {
int size;
cout << "Enter the input size : ";
cin >> size;
vector <int> input_values(size); //supposedly unimodal array
cout << "Enter " << size << " values:\n";
for (int& value: input_values)
cin >> value;
string answer;
cout << "\nDo the values first ascend then descend?"
<< "If otherwise, enter \"no\".\n"
<< "[Y]es / [n]o : ";
getline(cin, answer);
Pattern pattern = ASCEND_THEN_DESCEND; // answer is "yes" by default
if (answer[0] == 'n' or answer[0] == 'N') // user answers "no"
pattern = Pattern::DESCEND_THEN_ASCEND;
int index = ternary_search(input_values, pattern);
if (pattern == ASCEND_THEN_DESCEND)
cout << "Maximum value has position " << index << "\n";
else
cout << "Minimum value has position " << index << "\n";
return 0;
}
#endif