二分查找题解
- 核心词:有序。
一、704 二分查找 简单
-
标志词
- 有序数组
-
解法
- 将 left = 0, right = nums.length - 1,使用
[]区间 - 找到中间值,与 target 比较
- target =
nums[mid]=> return; - target <
nums[mid]=> 往左半部分找 => right = mid - 1 nums[mid]< target => 往右半部分找 => left = mid + 1
- target =
- 重复步骤 2
- 直至找到 left > right 为止 => 循环结束条件
- 若 left = right,还存在一个值可以与 target 比较
- 将 left = 0, right = nums.length - 1,使用
-
var search = function (nums, target) { let left = 0, right = nums.length - 1; while (left <= right) { const mid = left + ((right - left) >> 1); if (target === nums[mid]) return mid; else if (target < nums[mid]) right = mid - 1; else left = mid + 1; } return -1; };
二、35 搜索插入位置 简单
- 标志词:
- 排序数组
- 解法
- 仍然使用
[]区间: left = 0, right = nums.length - 1 - 找到中间值,与 target 比较
- target =
nums[mid]=> return; - target <
nums[mid]=> 往左半部分找 => right = mid - 1 nums[mid]< target => 往右半部分找 => left = mid + 1
- target =
- 重复步骤 2
- 直至找到 left > right 为止 => 循环结束条件
- 此时
nums[right]< target <nums[left]=> 插入操作,所以应取代 nums[left] => return left
- 此时
- 仍然使用
- 代码
/** * @param {number[]} nums * @param {number} target * @returns {number} */ var searchInsert = function (nums, target) { let left = 0, right = nums.length - 1; while (left <= right) { const mid = left + ((right - left) >> 1); if (target === nums[mid]) return mid; else if (target < nums[mid]) right = mid - 1; else left = mid + 1; } return left; };
三、33 搜索旋转排序数组 中等
- 解法
- 使用
[]区间: left = 0, right = nums.length - 1 - 找到中间值,判断哪边是有序区间
- target =
nums[left/mid/right]=> return left/mid/right; - if
nums[left]<nums[mid],左边为有序区间 (无需考虑 left = mid 情况,若这种情况,在 上一步中已经比较过,必定找不到)nums[left]< target <nums[mid]=> target 在有序区间内 => right = mid - 1- => target 在无序区间 => left = mid + 1
- 右边为有序区间
nums[left]< target <nums[mid]=> target 在有序区间内 => left = mid + 1- => target 在无序区间 => right = mid - 1
- target =
- 使用
- 代码
/** * @param {number[]} nums * @param {number} target * @returns {number} */ var search = function (nums, target) { let left = 0, right = nums.length - 1; while (left <= right) { const mid = left + ((right - left) >> 1); if (target === nums[left]) return left; if (target === nums[mid]) return mid; if (target === nums[right]) return right; if (nums[left] < nums[mid]) { if (nums[left] < target && target < nums[mid]) right = mid - 1; else left = mid + 1; } else { if (nums[mid] < target && target < nums[right]) left = mid + 1; else right = mid - 1; } } return -1; };
四、69 x 的平方根 简单
- 解法
i * i=> i 的平方,与 x 比较即可
- 代码
/** * @param {number} x * @return {number} */ var mySqrt = function (x) { let i = 0; while (i * i <= x) { i++; } return i - 1; };
五、74 搜索二维矩阵 中等
- 解法
- 使用
[]区间: left = 0, right = matrix.length - 1; - 找到中间的数组,先比较首尾元素
- 若与第一个或最后一个相等,直接返回 true
arr[start] < target < arr[end]=> 对该数组进行二分查找target < arr[start]=> right = mid - 1target > arr[end]=> left = mid + 1
- 重复步骤 2
- 使用
- 代码
/** * @param {number[][]} matrix * @param {number} target * @return {boolean} */ var searchMatrix = function (matrix, target) { let left = 0, right = matrix.length - 1; while (left <= right) { const mid = left + ((right - left) >> 1); const arr = matrix[mid]; let start = 0, end = arr.length - 1; if (target === arr[start]) return true; else if (target === arr[end]) return true; else if (target < arr[start]) right = mid - 1; else if (target > arr[end]) left = mid + 1; else { while (start <= end) { const mid = start + ((end - start) >> 1); if (target === arr[mid]) return true; else if (target < arr[mid]) end = mid - 1; else start = mid + 1; } break; } } return false; };
六、240 搜索二维矩阵 Ⅱ 中等
- 解法
- 以左下角
matrix[m-1][0]为起始点,与 target 进行大小比较(x = m - 1, y = 0)matrix[x][y]= target => return truematrix[x][y]> target => target 一定在matrix[m-1][0]的上面 => x--- 左下已经在上一次的比较中被排除
matrix[x][y]< target => target 一定在matrix[m-1][0]的右边 => y++- 左下已经在上一次的比较中被排除
- 重复步骤 1
- 以左下角
- 核心:选好起始点
- 代码
/** * @param {number[][]} matrix * @param {number} target * @return {boolean} */ var searchMatrix = function (matrix, target) { let m = matrix.length, n = matrix[0].length; let x = m - 1, y = 0; while (x >= 0 && y < n) { if (matrix[x][y] === target) return true; else if (matrix[x][y] < target) y++; else x--; } return false; };