Skip to content

Commit

Permalink
Find in Mountain Array
Browse files Browse the repository at this point in the history
  • Loading branch information
hikjik committed Oct 12, 2023
1 parent 256d926 commit abd8937
Show file tree
Hide file tree
Showing 5 changed files with 100 additions and 11 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ add_task(find-critical-and-pseudo-critical-edges-in-minimum-spanning-tree)
add_task(find-duplicate-subtrees)
add_task(find-eventual-safe-states)
add_task(find-first-and-last-position-of-element-in-sorted-array)
add_task(find-in-mountain-array)
add_task(find-k-closest-elements)
add_task(find-k-pairs-with-smallest-sums)
add_task(find-latest-group-of-size-m)
Expand Down
1 change: 1 addition & 0 deletions solutions/find-in-mountain-array/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
add_catch(test_find_in_mountain_array test.cpp)
63 changes: 63 additions & 0 deletions solutions/find-in-mountain-array/solution.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#pragma once

#include <functional>
#include <vector>

class MountainArray {
public:
MountainArray(std::vector<int> arr) : arr_(arr), cnt_(0) {}

int get(int index) {
++cnt_;
return arr_[index];
}

int length() const { return arr_.size(); }

int count() const { return cnt_; }

private:
std::vector<int> arr_;
int cnt_;
};

class Solution {
public:
static int findInMountainArray(int target, MountainArray &arr) {
const auto peak = peakIndexInMountainArray(arr);

const auto left = binarySearch(0, peak, target, std::less<int>(), arr);
if (arr.get(left) == target) {
return left;
}

const auto right = binarySearch(peak + 1, arr.length() - 1, target,
std::greater<int>(), arr);
if (arr.get(right) == target) {
return right;
}

return -1;
}

private:
template <typename Comparator>
static int binarySearch(int left, int right, int target, Comparator comp,
MountainArray &arr) {
while (left < right) {
const auto middle = left + (right - left) / 2;
comp(arr.get(middle), target) ? left = middle + 1 : right = middle;
}
return left;
}

static int peakIndexInMountainArray(MountainArray &arr) {
auto left = 0, right = arr.length() - 1;
while (left < right) {
const auto middle = left + (right - left) / 2;
arr.get(middle) < arr.get(middle + 1) ? left = middle + 1
: right = middle;
}
return left;
}
};
31 changes: 31 additions & 0 deletions solutions/find-in-mountain-array/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <catch.hpp>

#include <solution.hpp>

TEST_CASE("Simple") {
struct TestCase {
std::vector<int> secret;
int target;
int expected;
};

std::vector<TestCase> test_cases{
{
.secret{1, 2, 3, 4, 5, 3, 1},
.target = 3,
.expected = 2,
},
{
.secret{0, 1, 2, 4, 2, 1},
.target = 3,
.expected = -1,
},
};

for (const auto &[secret, target, expected] : test_cases) {
auto array = MountainArray(secret);
const auto actual = Solution::findInMountainArray(target, array);
REQUIRE(expected == actual);
REQUIRE(array.count() <= 100);
}
}
15 changes: 4 additions & 11 deletions solutions/peak-index-in-a-mountain-array/solution.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,11 @@
class Solution {
public:
static int peakIndexInMountainArray(const std::vector<int> &arr) {
int left = 0;
int right = arr.size() - 1;
int left = 0, right = arr.size() - 1;
while (left < right) {
const int middle = left + (right - left) / 2;
if (arr[middle - 1] < arr[middle] && arr[middle] > arr[middle + 1]) {
return middle;
} else if (arr[middle - 1] < arr[middle]) {
left = middle + 1;
} else {
right = middle;
}
const auto middle = left + (right - left) / 2;
arr[middle] < arr[middle + 1] ? left = middle + 1 : right = middle;
}
return left;
}
};
};

0 comments on commit abd8937

Please sign in to comment.