二分法(LeetCode34)
二分法(LeetCode34)
二分法强烈建议看看LC34。
二分法(折半查找),时间复杂度O(logN)
关于中间的取法 mid = l + (r - l) / 2;
最好不要使用 mid = (r + l) / 2; 原因是当 l 和 r比较大的时候会超出int所能存储的值
LC34 要找到最左边的目标值以及最右边的目标值的位置。
可以相应的转换为找到target最左边的值,以及target+1最右边的值。
代码可以写为:
class Solution {
public int[] searchRange(int[] nums, int target) {
int n = nums.length;
if(n == 0) return new int[]{-1, -1};
int first = findFirst(nums, target);
if(first == n || nums[first] != target) return new int[]{-1, -1};
int last = findFirst(nums, target + 1) - 1;
return new int[]{first, Math.max(first, last)};
}
int findFirst(int[] nums, int target) {
int l = 0;
int r = nums.length;
while(l < r) {
int mid = l + (r - l) / 2;
if(nums[mid] >= target) {
r = mid;
} else {
l = mid +1;
}
}
return l;
}
}
当然也可以分别找到最左边和最右边的值
class Solution { public int[] searchRange(int[] nums, int target) { int n = nums.length; if(n == 0) return new int[]{-1, -1}; int l = 0; int r = n -1; int left = 0; int right = 0; //寻找最左边的target值 while(l <= r && l < n && r >= 0) { int mid = l + (r - l) / 2; if(nums[mid] >= target) { r = mid -1; } else { l = mid + 1; } } if(l >= n|| nums[l] != target) return new int[]{-1, -1}; left = l; l = 0; r = n - 1; //寻找最右边的target值 while(l <= r && l < n && r >= 0){ int mid = l + (r - l) / 2; if(nums[mid] <= target) { l = mid +1; } else { r = mid -1; } } right = r; return new int[]{left, right}; } }
二分法最最最困难的是边界问题的考虑,所以大家对二分法的题目要有足够的耐心!

浙公网安备 33010602011771号