我被给定了一个整数数组,需要找到其中的峰值元素。 如果一个数组元素不小于它的相邻元素,则该元素为峰值元素。 对于边缘元素,只考虑一个相邻元素。
例如:
对于输入数组{10, 20, 15, 2, 23, 90, 67}
,
有两个峰值元素:20和90。我需要返回任意一个峰值元素。
我尝试的解决方法是线性扫描数组并找到峰值元素。该方法的最坏时间复杂度为O(n)。
我们能否在最坏时间复杂度优于O(n)的情况下找到峰值元素?
是的,你可以使用类似二分查找的思想在O(log n)时间复杂度内完成。指向向量的中间元素并检查其相邻元素。如果它比两个相邻元素都大,则返回该元素,它就是峰值。如果右侧元素更大,则在数组的右侧递归查找峰值。如果左侧元素更大,则在数组的左侧递归查找峰值。
是的,可以使用分治算法以更好的时间复杂度找到它。
以下链接将对您有所帮助。 http://courses.csail.mit.edu/6.006/spring11/lectures/lec02.pdf
// A divide and conquer solution to find a peak element element
#include <stdio.h>
// A binary search based function that returns index of a peak element
int findPeakUtil(int arr[], int low, int high, int n)
{
// Fin index of middle element
int mid = low + (high - low)/2; /* (low + high)/2 */
// Compare middle element with its neighbours (if neighbours exist)
if ((mid == 0 || arr[mid-1] <= arr[mid]) &&
(mid == n-1 || arr[mid+1] <= arr[mid]))
return mid;
// If middle element is not peak and its left neighbor is greater than it
// then left half must have a peak element
else if (mid > 0 && arr[mid-1] > arr[mid])
return findPeakUtil(arr, low, (mid -1), n);
// If middle element is not peak and its right neighbor is greater than it
// then right half must have a peak element
else return findPeakUtil(arr, (mid + 1), high, n);
}
// A wrapper over recursive function findPeakUtil()
int findPeak(int arr[], int n)
{
return findPeakUtil(arr, 0, n-1, n);
}
/* Driver program to check above functions */
int main()
{
int arr[] = {1, 3, 20, 4, 1, 0};
int n = sizeof(arr)/sizeof(arr[0]);
printf("Index of a peak point is %d", findPeak(arr, n));
return 0;
}
我曾在MIT 6.006 OCW课程中使用过这个工具,您也可以去看看。