🌰单峰序列题目描述
晴问算法
题目描述:
单峰序列是指,在这个序列中存在一个位置,满足这个位置的左侧(含该位置)是严格递增的、右侧(含该位置)是严格递减的,这个位置被称作峰顶位置。现在给定一个单峰序列,求峰顶位置的下标。
注:使用二分法实现。
输入描述:
第一行为一个正整数𝑛(1≤𝑛≤105),表示序列的长度;
第二行按顺序给出单峰序列的𝑛个元素(1≤每个元素≤106)。假设序列的下标从0开始。
数据保证不是单调序列,一定有峰顶。
思路2
把该题转化为寻找峰顶后一个元素,也就是该序列中第一个小于前一个元素的下标(前续解),再减1即为最终解。
对于二分查找闭区间[left, right]:
若nums[mid-1] > nums[mid] ,说明mid有可能是前续解(固定思路,先思考满足什么条件有可能是解,反推出nums[mid-1] > nums[mid]),因为它小于前一个元素,但还需要往左检查是否还有满足条件的元素,因此让rigth = mid;
若nums[mid -1] < nums[mid], 说明前续解在mid右侧,因为它还在严格递增的前半序列中,因此让left = mid + 1;
题目说严格递增与严格递减,因此不存在重复的元素,不需要考虑等于的情况,直接else即可;
当left == right时,就找到了前续解,结束循环,所以进入循环条件是left < right。
由于数据保证序列不是单调序列,所以最终解峰顶一定不是序列中的第一个和最后一个元素,所以最终解峰顶可能取值为[1, n-1], 因此前续解所有可能取值为[2, n], 所以查找区间初值为【2, n】。
最终解为left -1 or right -1;
//返回该序列中第一个小于前一个元素的下标(前续解)
int binarySearch(){int left = 2, right = n, mid;while(left < right){mid = (left + right) / 2;if(nums[mid-1] > nums[mid])right = mid;elseleft = mid + 1;}return left ; // or right;
}
printf("%d\n", binarySearch() - 1);
思路1
对于二分查找闭区间[left, right]:
若nums[mid-1] < nums[mid] && nums[mid] > nums[mid+1],说明mid是峰顶;
若nums[mid-1] < nums[mid], 峰顶有可能是mid,也可能在mid右侧,,则让left = mid;
若nums[mid] > nums[mid + 1],峰顶有可能是mid,也可能在mid左侧,,则让right = mid;
由于数据保证序列不是单调序列,所以峰顶(解)一定不会是第一个和最后一个,因此mid-1, mid+1一定合法,不需要检查索引合法了,且因此峰顶(解)的所有可能取值为[1, n-1], 所以查找区间初值为【1, n-1】,当然多一个0也可以【0, n-1】
且题目说严格递增与严格递减,因此不存在重复的元素,不需要考虑等于的情况。
最终返回mid即可;
int left = 0, right = n-1, mid;while(1){mid = (left + right) / 2;if(nums[mid-1] < nums[mid] && nums[mid] > nums[mid+1])break;if(nums[mid-1] < nums[mid])left = mid;if(nums[mid] > nums[mid+1])right = mid;}