模板二
使用的是 左闭右开
初始条件:left = 0;right = length
终止: left === right
向左查找的话: right = mid
向右查找: left = mid + 1
278. 第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n 个版本 [1, 2, ..., n],你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version) 接口来判断版本号 version 是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
示例 1:
输入:n = 5, bad = 4 输出:4 解释: 调用 isBadVersion(3) -> false 调用 isBadVersion(5) -> true 调用 isBadVersion(4) -> true 所以,4 是第一个错误的版本。 示例 2:
输入:n = 1, bad = 1 输出:1
提示:
1 <= bad <= n <= 231 - 1
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/fi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
/**
* Definition for isBadVersion()
*
* @param {integer} version number
* @return {boolean} whether the version is bad
* isBadVersion = function(version) {
* ...
* };
*/
/**
* @param {function} isBadVersion()
* @return {function}
*/
var solution = function(isBadVersion) {
// 这道题目是说判断版本号是否出错
// 然后可以通过调用接口 isBadVersion() 判断之后是否有出错
// 如果之后有出错的话,就往前移动,如果没有出错就往后面移动
// 是用 左闭合 右开 [)
// 所以最后会多出一个元素
/**
* @param {integer} n Total versions
* @return {integer} The first bad version
*/
return function(n) {
if(n == 1) return 1
var min = 1
var max = n
// 如果比较小的数小于大的数就继续
while(min < max){
var mid = min + parseInt((max - min) / 2)
if(isBadVersion(max) == false) {
return max
}
// 如果是没有错的话
if(isBadVersion(mid) == false && isBadVersion(mid + 1) == true){
return mid + 1
}
// 如果是正确的话,就要往前移动
if(isBadVersion(mid) == true){
max = mid
}else{
min = mid + 1
}
}
// 剩余一个元素需要对其进行处理
if(isBadVersion(min) == true){
return min
}
};
};
162. 寻找峰值
这道题题目的话,我总是找不到什么时候进行向左查找和向右查找
最后看到有人发了一种解法就是利用上坡和下坡,
通过中间值和中间值的下一个值来进行判断,
如果中间值大于下一值的时候,这时候是下坡,要进行向左查找,因为峰峰值在左边
反之亦然。
峰值元素是指其值严格大于左右相邻值的元素。
给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞ 。
你必须实现时间复杂度为 O(log n) 的算法来解决此问题。
示例 1:
输入:nums = [1,2,3,1] 输出:2 解释:3 是峰值元素,你的函数应该返回其索引 2。 示例 2:
输入:nums = [1,2,1,3,5,6,4] 输出:1 或 5 解释:你的函数可以返回索引 1,其峰值元素为 2; 或者返回索引 5, 其峰值元素为 6。
提示:
1 <= nums.length <= 1000 -231 <= nums[i] <= 231 - 1 对于所有有效的 i 都有 nums[i] != nums[i + 1]
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/fi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
/**
* @param {number[]} nums
* @return {number}
*/
var findPeakElement = function(nums) {
// 寻找峰值,跟上一道题目差不多,也是可以使用
// 左闭右开的方法来进行
// 这里比较难的地方就是如果最开始的比较大的话,就比较难办
// 可以使用滑坡法
// 如果初始位置小于最后位置的大小就让
// 又明白,最后的时候左端点等于右端点
// 通过判断中间的点与中间下一个点的关系来进行判断
var left = 0
var right = nums.length - 1
while(left < right){
var mid = left + parseInt((right - left) / 2)
// 下坡,右边进行移动
if(nums[mid] > nums[mid + 1]){
right = mid
}
// 上坡,左边右移
else{
left = mid + 1
}
}
return left
};
153. 寻找旋转排序数组中的最小值
找到移动的条件就是判断中间的值与两边值的关系,
因为是进行旋转数组,所以具有唯一性,也就是中间的值一定会大于最右边的值或者小于最右边的值
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到: 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2] 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7] 注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。
给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
示例 1:
输入:nums = [3,4,5,1,2] 输出:1 解释:原数组为 [1,2,3,4,5] ,旋转 3 次得到输入数组。 示例 2:
输入:nums = [4,5,6,7,0,1,2] 输出:0 解释:原数组为 [0,1,2,4,5,6,7] ,旋转 4 次得到输入数组。 示例 3:
输入:nums = [11,13,15,17] 输出:11 解释:原数组为 [11,13,15,17] ,旋转 4 次得到输入数组。
提示:
n == nums.length 1 <= n <= 5000 -5000 <= nums[i] <= 5000 nums 中的所有整数 互不相同 nums 原来是一个升序排序的数组,并进行了 1 至 n 次旋转
来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/fi… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
/**
* @param {number[]} nums
* @return {number}
*/
var findMin = function(nums) {
// 这道题目也是跟刚才那道题目是一样的就是找到峰值换成最小值
var left = 0
var right = nums.length - 1
if(nums[left] < nums[right]) return nums[left]
while(left < right){
var mid = left + parseInt((right - left) / 2)
// 如果中间值小于最右边的值的时候,就朝着左边查找
if(nums[mid] < nums[right]){
right = mid
}else{
left = mid + 1
}
}
return nums[left]
};
\