diff --git a/CMakeLists.txt b/CMakeLists.txt index 3c7a999b..3f438198 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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) diff --git a/solutions/find-in-mountain-array/CMakeLists.txt b/solutions/find-in-mountain-array/CMakeLists.txt new file mode 100644 index 00000000..ba2465e0 --- /dev/null +++ b/solutions/find-in-mountain-array/CMakeLists.txt @@ -0,0 +1 @@ +add_catch(test_find_in_mountain_array test.cpp) diff --git a/solutions/find-in-mountain-array/solution.hpp b/solutions/find-in-mountain-array/solution.hpp new file mode 100644 index 00000000..cdd910bb --- /dev/null +++ b/solutions/find-in-mountain-array/solution.hpp @@ -0,0 +1,63 @@ +#pragma once + +#include +#include + +class MountainArray { +public: + MountainArray(std::vector 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 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(), arr); + if (arr.get(left) == target) { + return left; + } + + const auto right = binarySearch(peak + 1, arr.length() - 1, target, + std::greater(), arr); + if (arr.get(right) == target) { + return right; + } + + return -1; + } + +private: + template + 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; + } +}; diff --git a/solutions/find-in-mountain-array/test.cpp b/solutions/find-in-mountain-array/test.cpp new file mode 100644 index 00000000..cd717371 --- /dev/null +++ b/solutions/find-in-mountain-array/test.cpp @@ -0,0 +1,31 @@ +#include + +#include + +TEST_CASE("Simple") { + struct TestCase { + std::vector secret; + int target; + int expected; + }; + + std::vector 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); + } +} diff --git a/solutions/peak-index-in-a-mountain-array/solution.hpp b/solutions/peak-index-in-a-mountain-array/solution.hpp index a683bfd2..cefe77d7 100644 --- a/solutions/peak-index-in-a-mountain-array/solution.hpp +++ b/solutions/peak-index-in-a-mountain-array/solution.hpp @@ -5,18 +5,11 @@ class Solution { public: static int peakIndexInMountainArray(const std::vector &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; } -}; \ No newline at end of file +};