【Leetcode】二分法求解问题
目录
- 704.二分查找
- 35.搜索插入位置
- 代码
- 思路
- 34.在排序数组中查找元素第一个和最后一个的位置
- 代码
- 思路:
- 二分法必须用于以排好序的数组。
704.二分查找
如果对二分法没有了解,可以先看这个题
35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n) 的算法。
示例1:
输入: nums = [1,3,5,6], target = 5
输出: 2
示例2:
输入: nums = [1,3,5,6], target = 2
输出: 1
示例3:
输入: nums = [1,3,5,6], target = 7
输出: 4
提示:
- 1 <= nums.length <= 104
- 104 <= nums[i] <= 104
- nums 为 无重复元素 的 升序 排列数组
- 104 <= target <= 104
代码
int searchInsert(int* nums, int numsSize, int target){
int left = 0, right = numsSize-1;
while(left <= right)
{
int mid = left+((right-left)>>1);
if(nums[mid] > target)
{
right = mid - 1;
}
else if(nums[mid] < target)
{
left = mid + 1;
}
else
{
return mid;
}
}
return right+1;
//return left;
}
思路
- 当数组中有target时,直接使用正常的二分查找即可。
- 当数组中没有target时,需要输出插入的位置,此时插入的位置只可能是0、5或是1~4。
- 当插入位置为0时,到数第二步应指向该位置
下一步right指向的下标为-1,返回right+1或left即可。 - 当插入的位置为5时,到数第二步指向的位置应该为
下一步left应该指向下标为5的位置,此时返回right+1或left即可。 - 当插入的位置为其它时,到数第二步指向的位置应该是
下一步left指向下标为2的位置,此时跳出循环,返回left或right+1即可
34.在排序数组中查找元素第一个和最后一个的位置
给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。
如果数组中不存在目标值 target,返回 [-1, -1]。
你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。
示例1:
输入:nums = [5,7,7,8,8,10], target = 8
输出:[3,4]
示例2:
输入:nums = [5,7,7,8,8,10], target = 6
输出:[-1,-1]
示例3:
输入:nums = [], target = 0
输出:[-1,-1]
提示:
- 0 <= nums.length <= 105
- 109 <= nums[i] <= 109
- nums 是一个非递减数组
- 109 <= target <= 109
代码
int* searchRange(int* nums, int numsSize, int target, int* returnSize){
int left =0,right = numsSize-1;
*returnSize = 2;
int* arr = (int*)malloc(2*sizeof(int));
while(left<=right)
{
int center = left + ((right - left) >> 1);//防止溢出,与(left + right)/2;同意
if(nums[center] == target)
{
int left = center - 1;
int right = center + 1;
while(left >= 0 && nums[left] == target)//确定所求数字在数组中最左边的下标
{
left--;
}
while(right <= numsSize-1 && nums[right] == target)//确定所求数字在数组中最右边的下标
{
right++;
}
arr[0] = left + 1;
arr[1] = right - 1;
return arr;
}
else if(nums[center] > target)
{
right = center - 1;
}
else
{
left = center + 1;
}
}
arr[0] = -1;
arr[1] = -1;
return arr;
}
思路:
- 使用常规的二分法查找数组中是否有目标值
- 有:使用left和right变量,将找到的目标值的下标将改下标的左右值分别赋给left和right,进行向左和向右的遍历,直到找到与target不相同的值。