二分查找算法
二分查找
给定一个 n
个元素有序的(升序)
整型数组 nums
和一个目标值 target
,写一个函数搜索 nums
中的 target
,如果目标值存在返回下标,否则返回 -1
示例
1 2 3
| 输入: nums = [-1,0,3,5,9,12], target = 9 输出: 4 解释: 9 出现在 nums 中并且下标为 4
|
1 2 3
| 输入: nums = [-1,0,3,5,9,12], target = 2 输出: -1 解释: 2 不存在 nums 中因此返回 -1
|
解题
点击展开代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| public int search(int[] nums, int target) { int left = 0; int right = nums.length - 1; while (left <= right) { int middle = left + ((right - left) / 2); if (nums[middle] > target) { right = middle - 1; } else if (nums[middle] < target) { left = middle + 1; } else { return middle; } } return -1; }
|
第一个错误的版本
你是产品经理,目前正在带领一个团队开发新的产品。不幸的是,你的产品的最新版本没有通过质量检测。由于每个版本都是基于之前的版本开发的,所以错误的版本之后的所有版本都是错的。
假设你有 n
个版本 [1, 2, ..., n]
,你想找出导致之后所有版本出错的第一个错误的版本。
你可以通过调用 bool isBadVersion(version)
接口来判断版本号 version
是否在单元测试中出错。实现一个函数来查找第一个错误的版本。你应该尽量减少对调用 API 的次数。
示例
1 2 3 4 5 6 7
| 输入:n = 5, bad = 4 输出:4 解释: 调用 isBadVersion(3) -> false 调用 isBadVersion(5) -> true 调用 isBadVersion(4) -> true 所以,4 是第一个错误的版本。
|
提示
1
| 1 <= bad <= n <= 231 - 1
|
解题
点击展开代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public int firstBadVersion(int n) { int left = 1, right = n; while (left < right) { int mid = left + (right - left) / 2; if (isBadVersion(mid)) { right = mid; } else { left = mid + 1; } } return left; }
|
搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n)
的算法。
示例
1 2 3 4 5 6 7 8
| 输入: nums = [1,3,5,6], target = 5 输出: 2
输入: nums = [1,3,5,6], target = 2 输出: 1
输入: nums = [1,3,5,6], target = 7 输出: 4
|
提示
- 1 <=
nums.length
<= 104
- -104 <=
nums[i]
<= 104
- nums 为
无重复元素
的 升序
排列数组
- -104 <=
target
<= 104
解题
解法一
时间复杂度:O(n)
空间复杂度:O(1)
点击展开代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public int searchInsertOne(int[] nums, int target) { for (int i = 0; i < nums.length; i++) { if (nums[i] >= target) { return i; } } return nums.length; }
|
解法二
时间复杂度:O(logn)
时间复杂度:O(1)
点击展开代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public static int searchInsertTwo(int[] nums, int target) { int left = 0; int right = nums.length - 1; while (left <= right) { int middle = left + ((right - left) / 2); if (nums[middle] > target) { right = middle - 1; } else if (nums[middle] < target) { left = middle + 1; } else { return middle; } } return right + 1; }
|
相关文章
双指针