-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(binary search): find peak element
- Loading branch information
1 parent
032aaa9
commit 0d70833
Showing
4 changed files
with
147 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
# Find Peak Element | ||
|
||
A peak element is an element that is strictly greater than its neighbors. | ||
|
||
Given a 0-indexed integer array nums, find a peak element, and return its index. If the array contains multiple peaks, | ||
return the index to any of the peaks. | ||
|
||
You may imagine that nums[-1] = nums[n] = -∞. In other words, an element is always considered to be strictly greater | ||
than a neighbor that is outside the array. | ||
|
||
You must write an algorithm that runs in O(log n) time. | ||
|
||
```plain | ||
Example 1: | ||
Input: nums = [1,2,3,1] | ||
Output: 2 | ||
Explanation: 3 is a peak element and your function should return the index number 2. | ||
Example 2: | ||
Input: nums = [1,2,1,3,5,6,4] | ||
Output: 5 | ||
Explanation: Your function can return either index number 1 where the peak element is 2, or index number 5 where the peak element is 6. | ||
``` | ||
|
||
## Topics | ||
|
||
- Array | ||
- Binary Search |
43 changes: 43 additions & 0 deletions
43
puzzles/search/binary_search/find_peak_element/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
from typing import List | ||
|
||
|
||
def find_peak_element(nums: List[int]) -> int: | ||
"""Finds a peak element's index in the provided list of integers | ||
Algorithm: | ||
- Initializes left as the start index of the list and right as the end index of the list (len(nums)- 1). | ||
- Perform binary search until left becomes equal to right. | ||
- Calculate the middle index mid using the formula mid = left + (right - left) // 2. or mid = (left + right) >> 1 | ||
- Compare nums[mid] with nums[mid + 1] to determine if the peak is on the left side or the right side of mid. | ||
- If nums[mid] is greater than nums[mid + 1], move the right index to mid, indicating that the peak is on the | ||
left side. | ||
- Otherwise, move the left index to mid + 1, indicating that the peak is on the right side. | ||
- Repeat steps 3-4 until left becomes equal to right. | ||
- Return the value of peak_index, which represents the index of the peak element. | ||
Complexity: | ||
- Time complexity O(log n): Where n is the number of elements in the nums vector. | ||
- Space Complexity O(1): Since it uses a constant amount of extra space. | ||
Args: | ||
nums (List): list of integers | ||
Returns: | ||
int: index of a peak element(i.e. element that is greater than its adjacent neighbours) | ||
""" | ||
left = 0 | ||
right = len(nums) - 1 | ||
peak_index = -1 | ||
|
||
while left <= right: | ||
mid = (left + right) >> 1 | ||
|
||
# check that the potential peak element is within bounds or is greater than both its neighbours | ||
potential_peak = nums[mid] | ||
if mid == len(nums) - 1 or potential_peak > nums[mid + 1]: | ||
peak_index = mid | ||
right = mid - 1 | ||
else: | ||
left = mid + 1 | ||
|
||
return peak_index |
72 changes: 72 additions & 0 deletions
72
puzzles/search/binary_search/find_peak_element/test_find_peak_element.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import unittest | ||
from . import find_peak_element | ||
|
||
|
||
class FindPeakElementTestCase(unittest.TestCase): | ||
def test_1(self): | ||
"""should return 2 for nums = [1,2,3,1]""" | ||
nums = [1, 2, 3, 1] | ||
expected = 2 | ||
actual = find_peak_element(nums) | ||
self.assertEqual(expected, actual) | ||
|
||
def test_2(self): | ||
"""should return either 5 or 1 for nums = [1,2,1,3,5,6,4]""" | ||
nums = [1, 2, 1, 3, 5, 6, 4] | ||
expected_5 = 5 | ||
expected_1 = 1 | ||
actual = find_peak_element(nums) | ||
self.assertIn(actual, [expected_1, expected_5]) | ||
|
||
def test_3(self): | ||
"""should return either 5 or 1 for nums = [1,2,1,3,5,6,4]""" | ||
nums = [0, 1, 2, 3, 2, 1, 0] | ||
expected = 3 | ||
actual = find_peak_element(nums) | ||
self.assertEqual(actual, expected) | ||
|
||
def test_4(self): | ||
"""should return 1 from 0 10 3 2 1 0""" | ||
nums = [0, 10, 3, 2, 1, 0] | ||
expected = 1 | ||
actual = find_peak_element(nums) | ||
self.assertEqual(expected, actual) | ||
|
||
def test_5(self): | ||
"""should return 1 from 0 10 0""" | ||
nums = [0, 10, 0] | ||
expected = 1 | ||
actual = find_peak_element(nums) | ||
self.assertEqual(expected, actual) | ||
|
||
def test_6(self): | ||
"""should return 16 from 0 1 2 12 22 32 42 52 62 72 82 92 102 112 122 132 133 132 111 0""" | ||
nums = [0, 1, 2, 12, 22, 32, 42, 52, 62, 72, 82, 92, 102, 112, 122, 132, 133, 132, 111, 0] | ||
expected = 16 | ||
actual = find_peak_element(nums) | ||
self.assertEqual(expected, actual) | ||
|
||
def test_7(self): | ||
"""should return 1 from 0, 10, 5, 2""" | ||
nums = [0, 10, 5, 2] | ||
expected = 1 | ||
actual = find_peak_element(nums) | ||
self.assertEqual(expected, actual) | ||
|
||
def test_8(self): | ||
"""should return 1 from 0, 2, 1, 0""" | ||
nums = [0, 2, 1, 0] | ||
expected = 1 | ||
actual = find_peak_element(nums) | ||
self.assertEqual(expected, actual) | ||
|
||
def test_9(self): | ||
"""should return 1 from 0, 1, 0""" | ||
nums = [0, 1, 0] | ||
expected = 1 | ||
actual = find_peak_element(nums) | ||
self.assertEqual(expected, actual) | ||
|
||
|
||
if __name__ == '__main__': | ||
unittest.main() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters