Skip to content

Find peak element #54

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions DIRECTORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,8 @@
* Binary Search
* Big Words
* [Big Words](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/search/binary_search/big_words/big_words.py)
* Find Peak Element
* [Test Find Peak Element](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/search/binary_search/find_peak_element/test_find_peak_element.py)
* First Boundary
* [Test First Boundary](https://github.com/BrianLusina/PythonSnips/blob/master/puzzles/search/binary_search/first_boundary/test_first_boundary.py)
* First Occurrence
Expand Down
29 changes: 29 additions & 0 deletions puzzles/search/binary_search/find_peak_element/README.md
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 puzzles/search/binary_search/find_peak_element/__init__.py
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
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()
9 changes: 3 additions & 6 deletions puzzles/search/binary_search/peak_of_mountain/README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
# The Peak of a Mountain Array

A mountain array is defined as an array that

has at least 3 elements
has an element with the largest value called "peak", with index k. The array elements strictly increase from the first
element to A[k], and then strictly decreases from A[k + 1] to the last element of the array. Thus creating a "mountain"
of numbers.
A mountain array is defined as an array that has at least 3 elements has an element with the largest value called "
peak", with index k. The array elements strictly increase from the first element to A[k], and then strictly decreases
from A[k + 1] to the last element of the array. Thus creating a "mountain" of numbers.
That is, given A[0]<...<A[k-1]<A[k]>A[k+1]>...>A[n-1], we need to find the index k. Note that the peak element is
neither the first nor the last element of the array.

Expand Down