Today I will talk about an extremely basic algorithm that I and most of you who are starting to learn about algorithmic programming have done. That is the Peak Finding algorithm.
1. Introduction to the algorithm
In an array, a number is said to be a "peak" if and only if its adjacent elements are less than or equal to the element in question. Imagine that there is a mountain range like this
The red arrows above point to the peaks of a mountain range, because those points are higher than the neighboring points around it (the points on the mountainside).
To be more intuitive in programming, let's take an example with the following array:
Considering the array of symbols above, the element at position 3 is called a peak if and only if and . The 9th element is called a peak if and only if .
Notice that:
- In an array, there will always be at least one peak.
- This problem of ours will be to find one peak, not all the peaks.
2. Finding peak in 1-dimensional array
Suppose we have a 1-dimensional array of elements, find a peak of that array.
2.1. Linear Traversing
Idea: Iterate through each element of the array and check if the element under consideration satisfies the property of being a peak.
Algorithm analysis: Each element being browsed will have conditional statements to check if the element is a peak, these conditional statements take constant time . In the worst case, we'll have to go through all elements of the array to find the peak. Therefore, the worst case of the algorithm will have a time complexity of .
2.2. Binary Search
Idea: In this way, we will always look at the middle of the traversed array and decide which half of the array to traverse to find the peak.
Algorithm:
- Look at the location .
- If , we look at the left half (the elements of the array under consideration to find the peak.
- If , we look at the right half (the elements of the array under consideration to find the peak.
- If both conditions are not satisfied, we return the position element is a peak.
To explain this, I have a drawing to make it more intuitive
The red arrow points to the current position. Suppose we are standing on a position in the mountains, so that we can climb to the top, we will always look to the side that we see its position higher than where we are standing, and that is also the algorithm to solve for this problem.
Algorithm analysis: Using divide and conquer, we have the following expression
Time complexity for comparative conditionals , base case here is . From that, .
Python Code
import math
ini_arr = [10, 20, 15, 2, 23, 90, 67]
def peak_finding(arr):
length = len(arr)
middle = math.floor(length / 2)
if length == 1:
return arr[0]
if length == 2:
return arr[0] if (arr[0] >= arr[1]) else arr[1]
if arr[middle] < arr[middle - 1]:
return peak_finding(arr[:middle])
elif arr[middle] < arr[middle + 1]:
return peak_finding(arr[middle + 1:])
else:
return arr[middle]
print(peak_finding(ini_arr))
Output
20
3. Finding peak in 2-dimensional array
Suppose we have a 2-dimensional array represented as a matrix of m rows and n columns
An element is considered to be a peak if and only if it is greater than or equal to all adjacent elements vertically and horizontally.
3.1. Direct traversal
Idea: Iterate through each element of the array and check if the element under consideration satisfies the property of being a peak.
Algorithm analysis: the worst case of the algorithm will have a time complexity of .
3.2. Greedy Ascent Algorithm
Idea: We start at a random point. With the point under consideration, we compare it with 4 adjacent points vertically and horizontally, if any value is greater than the point under consideration, we will consider the next point to be that point.
Algorithm analysis: At first glance, the algorithm seems to be more efficient, but its worst case is still when we have to traverse most of the elements.
3.3. Jamming Binary Search Algorithm
Idea: We rely on Binary Search as applied to the 1-dimensional array above.
Algorithm:
- Select the column in the middle . Find the maximum value of that column. Assume that value is at position .
- Compare elements at positions .
- We choose the left-part submatrix if , choose the right-part submatrix if to consider the next step.
- Otherwise, we return the value is a peak.
Algorithm analysis: The base case here will be that we only have a single column, find the maximum value of that column. From this, we have the following expression
With . Therefore, .
Python Code
import numpy as np
import math
ini_matrix = np.array([[14, 13, 12, 6], [15, 9, 11, 7], [
16, 17, 19, 92], [17, 18, 17, 12]])
def peak_finding_2d(matrix):
(rows, cols) = matrix.shape
j = math.floor(cols / 2)
i_in_max = np.argmax(matrix[:, j])
if cols == 1:
return matrix[i_in_max, j]
if cols == 2:
peak_1 = np.amax(matrix[:, 0])
peak_2 = np.amax(matrix[:, 1])
return peak_1 if peak_1 >= peak_2 else peak_2
if matrix[i_in_max, j] < matrix[i_in_max, j-1]:
return peak_finding_2d(matrix[:, :j])
elif matrix[i_in_max, j] < matrix[i_in_max, j+1]:
return peak_finding_2d(matrix[:, (j+1):])
else:
return matrix[i_in_max, j]
print(peak_finding_2d(ini_matrix))
Output
92