目录
二分法通用模板:
//查找数字
int binary_search(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while(left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if(nums[mid] == target) {
// 直接返回
return mid;
}
}
// 直接返回
return -1;
}
//查找左边界
int left_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
// 别返回,锁定左侧边界
right = mid - 1;
}
}
// 最后要检查 left 越界的情况
if (left >= nums.length || nums[left] != target)
return -1;
return left;
}
//查找右边界
int right_bound(int[] nums, int target) {
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if (nums[mid] == target) {
// 别返回,锁定右侧边界
left = mid + 1;
}
}
// 最后要检查 right 越界的情况
if (right < 0 || nums[right] != target)
return -1;
return right;
}
33. 搜索旋转排序数组
此题和剑指offer第6题本质上是一样的。
我的第一思路其实是:
class Solution:
def search(self, nums: List[int], target: int) -> int:
for k,v in enumerate(nums):
if v == target:
return k
return -1
但是这个题好像想考的是二分法,于是二分法的代码为:
class Solution:
def search(self, nums: List[int], target: int) -> int:
if len(nums) <= 0:
return -1
left = 0
right = len(nums) - 1
while left < right:
mid = (right - left) // 2 + left
if nums[mid] == target:
return mid
# 如果中间的值大于最左边的值,说明左边有序
if nums[mid] > nums[left]:
if nums[left] <= target <= nums[mid]:
right = mid
else:
# 这里 +1,因为上面是 <= 符号
left = mid + 1
# 否则右边有序
else:
# 注意:这里必须是 mid+1,因为根据我们的比较方式,mid属于左边的序列
if nums[mid+1] <= target <= nums[right]:
left = mid + 1
else:
right = mid
return left if nums[left] == target else -1
但是,我们可以看一下运行时间于内存的对比:
第一行是二分法的,第二行是最直接的字典,竟然比二分法耗时少。。。。。
34. 在排序数组中查找元素的第一个和最后一个位置
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
return [self.left_bound(nums,target), self.right_bound(nums,target)]
def right_bound(self, nums, target):
if len(nums) == 0:
return -1
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
left = mid + 1
elif nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
if right >= 0 and nums[right] == target: return right # 注意
else: return -1
def left_bound(self, nums, target):
if len(nums) == 0:
return -1
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] == target:
right = mid - 1
elif nums[mid] < target:
left = mid + 1
elif nums[mid] > target:
right = mid - 1
if left <= len(nums)-1 and nums[left] == target: return left # 注意
else: return -1
704. 二分查找
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0, right = nums.size() - 1;
while(left <= right) {
int mid = left + (right - left) / 2;
if (nums[mid] < target) {
left = mid + 1;
} else if (nums[mid] > target) {
right = mid - 1;
} else if(nums[mid] == target) {
// 直接返回
return mid;
}
}
// 直接返回
return -1;
}
};