-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy path1095-Find_in_Mountain_Array.cpp
More file actions
216 lines (190 loc) · 5.34 KB
/
1095-Find_in_Mountain_Array.cpp
File metadata and controls
216 lines (190 loc) · 5.34 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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
/*******************************************************************************
* 1095-Find_in_Mountain_Array.cpp
* Billy.Ljm
* 12 October 2023
*
* =======
* Problem
* =======
* https://leetcode.com/problems/find-in-mountain-array/
*
* (This problem is an interactive problem.)
*
* You may recall that an array arr is a mountain array if and only if:
* - arr.length >= 3
* - There exists some i with 0 < i < arr.length - 1 such that:
* > arr[0] < arr[1] < ... < arr[i - 1] < arr[i]
* > arr[i] > arr[i + 1] > ... > arr[arr.length - 1]
*
* Given a mountain array mountainArr, return the minimum index such that
* mountainArr.get(index) == target. If such an index does not exist, return -1.
*
* You cannot access the mountain array directly. You may only access the array
* using a MountainArray interface:
* - MountainArray.get(k) returns the element of the array at index k (0-indexed).
* - MountainArray.length() returns the length of the array.
*
* Submissions making more than 100 calls to MountainArray.get will be judged
* Wrong Answer. Also, any solutions that attempt to circumvent the judge will
* result in disqualification.
*
* ===========
* My Approach
* ===========
* We will use binary search 3 times; first to find the peak of the mountain
* array, and then to find the target in the two slopes. To find the peak, we
* have to find the gradient by querying two adjacent elements; and to find the
* target we just have to query one element as usual. Additionally, we can cache
* the queries to avoid querying the same index multiple times across the
* independent binary searches.
*
* This has a time complexity of O(log n), and space complexity of O(n), where n
* is the length of the mountain array.
******************************************************************************/
#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
using namespace std;
/**
* << operator for vectors
*/
template <typename T>
std::ostream& operator<<(std::ostream& os, const std::vector<T>& v) {
os << "[";
for (const auto elem : v) {
os << elem << ",";
}
if (v.size() > 0) os << "\b";
os << "]";
return os;
}
/**
* MountainArray's API interface
*/
class MountainArray {
private:
vector<int> array;
public:
// default constructor
MountainArray() {
this->array = vector<int>();
}
// constructor for mountain array
MountainArray(vector<int> vals) {
srand(time(NULL));
vector<int> tmp;
// sort values
sort(vals.begin(), vals.end());
// init both slopes
this->array.push_back(vals[0]);
tmp.push_back(vals[1]);
// populate rest of slopes randomly
for (int i = 2; i < vals.size(); i++) {
if (rand() % 2 == 0) {
if (this->array.back() != vals[i]) this->array.push_back(vals[i]);
else tmp.push_back(vals[i]);
}
else {
if (tmp.back() != vals[i]) tmp.push_back(vals[i]);
else this->array.push_back(vals[i]);
}
}
// concatenate into mountain
reverse(tmp.begin(), tmp.end());
this->array.insert(this->array.end(), tmp.begin(), tmp.end());
}
// get element of array
int get(int index) {
return this->array[index];
}
// get lenght of array
int length() {
return array.size();
}
// get whole vector (for printing)
vector<int> vec() {
return this->array;
}
};
/**
* Solution
*/
class Solution {
private:
vector<int> cache;
MountainArray* mountainArr;
public:
// default constructor
Solution() {
this->cache = vector<int>();
this->mountainArr = nullptr;
}
// cache get calls
int getElem(int idx) {
if (this->cache[idx] < 0) this->cache[idx] = this->mountainArr->get(idx);
return this->cache[idx];
}
// main function
int findInMountainArray(int target, MountainArray& mountainArr) {
int lenn = mountainArr.length();
int start, end, mid; // binary search
int peak; // index of peak of mountain array
// fill atrributes
this->cache = vector<int>(lenn, -1);
this->mountainArr = &mountainArr;
// find peak of mountain array
start = 0;
end = lenn - 1;
while (end > start + 1) {
mid = (end + start) / 2;
if (getElem(mid + 1) > getElem(mid)) start = mid;
else end = mid;
}
peak = getElem(start) > getElem(end) ? start : end;
// search slope with smaller indices first
start = 0;
end = peak;
while (end > start + 1) {
mid = (end + start) / 2;
if (target > getElem(mid)) start = mid;
else end = mid;
}
if (getElem(start) == target) return start;
else if (getElem(end) == target) return end;
// search other slope
start = peak;
end = lenn - 1;
while (end > start + 1) {
mid = (end + start) / 2;
if (target > getElem(mid)) end = mid;
else start = mid;
}
if (getElem(start) == target) return start;
else if (getElem(end) == target) return end;
// target not found
return -1;
}
};
/**
* Test cases
*/
int main(void) {
Solution sol;
int target;
vector<int> array;
MountainArray mountainArr;
// test case 1
target = 3;
array = { 1,2,3,4,5,3,1 };
mountainArr = MountainArray(array);
std::cout << "findInMountainArray(" << target << "," << mountainArr.vec() << ") = ";
std::cout << sol.findInMountainArray(target, mountainArr) << std::endl;
// test case 2
target = 3;
array = { 0,1,2,4,2,1 };
mountainArr = MountainArray(array);
std::cout << "findInMountainArray(" << target << "," << mountainArr.vec() << ") = ";
std::cout << sol.findInMountainArray(target, mountainArr) << std::endl;
return 0;
}