解法一:暴力求解
int findPeakElement(int* nums, int numsLen ) {// write code herefor (int i = 1; i < numsLen - 1; i++) {if ((nums[i] > nums[i - 1]) && (nums[i] > nums[i+1])) {return i;}}if (nums[numsLen - 1] > nums[numsLen - 2]) {return numsLen - 1;}return 0;
}
题中明确说明:nums[-1] = nums[n] = −∞,所以要特别注意 nums[0] 和 nums[numsLen - 1]
直接遍历数组从 1 到 numsLen-2,要注意边界的问题,当nums[0] > nums[1]时,返回0
当 nums[numsLen - 1](最后一个元素) > nums[numsLen - 2](倒数第二个元素)时,返回numsLen - 1 。
解法二:二分思想
中间比右边大,认为从右往左半边递增,则把 right 不断向左靠拢 right=mid ,注意不能是 mid-1 ,因为这个位置有可能就是峰值点。 直到遇到中间比右边小了,意味着数据开始递降了,则 left 向右偏移, left=mid+1 ; 而一旦 mid+1 位置大于了 right ,意味着刚好这个 mid+1 位置,是一个左半边-右往左递降,右半边-右往左递增的点,就是一个峰值点。
示例:
int arr[] = {3, 5, 4, 4, 3, 2, 1} , 这个数组中两边边界都是非峰值点 int left = 0, right = 6;
left=0,right=6,mid=3: arr[3]=4 > arr[4]=3, 则right = mid = 3; //从右往左是递增的
left=0,right=3,mid=1: arr[1]=5 > arr[2]=4, 则right = mid = 1; //从右往左是递增的
left=0,right=1,mid=0: arr[0]=3 < arr[1]=5, 则left = mid + 1 = 1; //从右往左开始递降了 left > right 退出循环, 返回left,也就是1号下标位置。
int findPeakElement(int* nums, int numsLen ) {//边界情况处理,1个元素前后都是负无穷 以及 0号位置大于1号位置,-1位置负无穷的情况if (numsLen == 1 || nums[0] > nums[1])return 0; //末尾位置数据大于上一个位置数据,而nums[numsLen]负无穷的情况if (nums[numsLen - 1] > nums[numsLen - 2])return numsLen - 1;int left = 0, right = numsLen - 1, mid = 0;while (left < right) {mid = left + (right - left) / 2;//中间比右边小,意味着右边肯定有个峰值if (nums[mid] < nums[mid + 1]) {left = mid + 1;}//否则在左边包括当前位置肯定有个峰值else {right = mid;}}return left;
}