...

/

Solution: Peak Element

Solution: Peak Element

This review discusses the solution of the Peak Element Challenge in detail.

Solution #1

One simple way to solve this problem is:

Press + to interact
class PeakElement {
public static int findPeak(int[] array) {
//calculating array length
int len = array.length;
if (len == 0) {
return -1;
}
if (len == 1) {
return array[0];
}
if (array[0] >= array[1]) {
return array[0];
}
//traversing array
for (int i = 1; i < len - 1; i++) {
//if current value is greater than previous and the next value return it
if ((array[i] >= array[i - 1]) & (array[i] >= array[i + 1])) {
return array[i];
}
}
if (array[len - 1] >= array[len - 2]) {
return array[len - 1];
}
return -1;
}
/* Driver program to test above functions */
public static void main(String args[]) {
int[] array = { 7, 11, 22, 13, 4, 0 };
System.out.println("Peak element is: " + findPeak(array));
int[] array1 = {0,3,100,2,-1,0};
System.out.println("Peak element is: " + findPeak(array1));
}
}

In the code above, we:

  1. Start from the beginning and compare each element with its neighbors.
  2. Return the peak element wherever it is found in the array.

There must always be one peak element in an array with distinct elements but it’s possible that the array is sorted in ascending order just like this:

In this case, the peak element is at the end of the array.

Time complexity

The implementation of this solution is left for your own understanding. It gives us a worst-case time complexity of O(n)O(n).

Can we do better?


"Solution #2: Divide and conquer (efficient)

Using divide and conquer, we can speed up the whole process. Have a look at the solution given below:

Press + to interact
class PeakElement {
// This function is based on the recursive binary search algorithm returning the index of the peak element in the given array
public static int findPeakRecursive(int low, int high, int size, int array[]) {
// Just as in binary search, we will first find the middle element
int middle = low + (high - low) / 2;
// If neighbors of the middle element exist, compare them with the element
if ((middle == size - 1 || array[middle + 1] <= array[middle]) &&
(middle == 0 || array[middle - 1] <= array[middle]))
return middle;
// If the left neighbor of the middle element is greater, The peak element must be in the left subarray
else if (array[middle - 1] > array[middle] && middle > 0)
return findPeakRecursive(low, (middle - 1), size, array);
// If the right neighbor of the middle element is greater, The peak element must be in the right subarray
else
return findPeakRecursive((middle + 1), high, size, array);
}
// Wrapper to call the recursive findPeakRecursive()
public static int findPeak(int arr[]) {
int n = arr.length;
return findPeakRecursive(0, n - 1, n, arr);
}
/* Driver program to test above functions */
public static void main(String args[]) {
// A 2D array to store integer input arrays
int[][] inputs = { {7, 11, 22, 13, 4, 0} , {13, 27, 54, 11, 99, 1} ,{0, 1, 2, 3, 4, 5} , {10, 9, 8, 7, 6}};
int peak = 0; // variable to store the peak value for each input array
for (int i = 0; i < inputs.length; i++) {
peak = findPeak(inputs[i]);
if (i == 2)
System.out.println("Input Array: " + Arrays.toString(inputs[i]) + " ----> Peak = \"" + inputs[i][peak] + "\"\t\t (Ascending Order - Peak = Last Element)\n");
else if (i == 3)
System.out.println("Input Array: " + Arrays.toString(inputs[i]) + " ----> Peak = \"" + inputs[i][peak] + "\"\t\t(Descending Order - Peak = First Element)\n");
else
System.out.println("Input Array: " + Arrays.toString(inputs[i]) + " ----> Peak = \"" + inputs[i][peak] + "\"\n");
}
}
}

Explanation

  • Line 37: The driver calls the findPeak(int[]array) function.

  • Line 27: A helper function findPeakRecursive(int high, int low, int size, int[]arr) is called to get the peak value.

  • Line 7: The function starts with calculating the middle index of the array.

  • ...