二分法

发布时间 2024-01-07 17:23:52作者: lulixiu

本周练习内容
题目来自于力扣(掌握二分法)
题目链接

https://leetcode.cn/problems/binary-search/

代码如下
#include <stdio.h>

int search(int* nums, int numsSize, int target) {
int left = 0;
   int right = numsSize - 1;

 while (left <= right) {//左闭右闭,合法的区间
int mid = left + (right - left) / 2;
if (nums[mid] == target)	return mid;
else if (nums[mid] < target)	left = mid + 1;
else right = mid - 1;
}
 /*  int right=numsSize;
 while (left < right) {//左闭右开,合法的区间
 int mid= left + (right - left) / 2;
 if (nums[mid] == target)	return mid;
 else if (nums[mid] < target)	left = mid + 1;
 else right = mid ;
 }*/

return -1;
}

int main() {
int nums[] = { -1,0,3,5,9,12 };
int target;
int numsSize = sizeof(nums) / sizeof(nums[0]);
scanf_s("%d", &target);
int result = search(nums, numsSize, target);

if (result != -1) {
printf("%d\n", result);
}
else {
printf("-1\n");
}

return 0;
}

https://leetcode.cn/problems/search-insert-position/

自己写的

int search(int* nums, int numsSize, int target) {
   int left=0;
   int right=numsSize-1;
   
   while(left<=right){
int mid=left+(right-left)/2;
   	if(nums[mid]==target)	return mid;
   	else if(nums[mid]<target)	left=mid+1;
   	else right=mid-1;
   }
   
   for(int i=0;i<numsSize+1;i++){
   	if(target<nums[i]){
   		return i;
   		break;
	   }
   }
   
   return numsSize;
}

官方解法

class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
int n = nums.size();
int l=0,r=n-1;
while(l<=r){
int mid=l+(r-l)/2;
if(nums[mid]<target)
l=mid+1;
else r=mid-1;
}
return l;
}
};

最简写法

int searchInsert(int* nums, int numsSize, int target) {
for (int i=0;i<numsSize;i++){
if (nums[i]>=target)
return i;
}
return numsSize;
}

https://leetcode.cn/problems/find-first-and-last-position-of-element-in-sorted-array/

官方题解

int searchBoundary(int* nums, int numsSize, int target, bool   isLeft){
int left = 0, right = numsSize - 1, ans = numsSize;

while (left <= right) {

    int mid = (left + right) / 2;
    if (nums[mid] > target || (isLeft && nums[mid] >= target)) {
//取左区间:找右边界的时候nums[mid] > target需要抛弃,找左边界的时候nums[mid] >= target需要抛弃
    right = mid - 1;
    ans = mid;//右边界:最右一个大于target的位置;左边界:最左一个等于target的位置;
    } else 
		{ 
//取右区间:找右边界的时候nums[mid] <= target需要抛弃,找左边界的时候nums[mid] < target需要抛弃
    left = mid + 1;
    }

}

return ans;
}

int* searchRange(int* nums, int numsSize, int target, int* returnSize){
    int * ret = malloc(sizeof(int) * 2);
    memset(ret, -1, sizeof(ret));//设置内存块的函数,ptr 是指向要设置的内存的指针,value 是要设置的值,num 是要设置的字节数
   
	 *returnSize = 2;
    int l = searchBoundary(nums, numsSize, target, true), r = searchBoundary(nums, numsSize, target, false) - 1;

    if(l != numsSize && nums[l] == target)//返回边界值有效
    ret[0] = l, ret[1] = r;
    return ret;
}

最快解法

int findleftbound(int* nums,int numsSize,int target){
int left=0,right=numsSize-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{
    right=mid-1;
    }
}
if(left<0 || left>=numsSize){
return -1;
}

return nums[left]==target?left:-1;
}

int findrightbound(int* nums,int numsSize,int target){
int left=0,right=numsSize-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{
    left=mid+1;
    }
}
if(right<0 || right>=numsSize){
return -1;
}
return nums[right]==target?right:-1;
}

int* searchRange(int* nums, int numsSize, int target, int* returnSize){
int* res=(int*)malloc(sizeof(int)*2);

int left=0,right=numsSize-1;
int mid=left+(right-left)/2;

res[0]=findleftbound(nums,numsSize,target);
res[1]=findrightbound(nums,numsSize,target);
*returnSize=2;
return res;
}

https://leetcode.cn/problems/sqrtx/

也是用到了二分查找的思想

int mySqrt(int x) {
int l = 0, r = x, ans = -1;

while (l <= r) {
    int mid = l + (r - l) / 2;
    if ((long long)mid * mid <= x) {
    ans = mid;
    l = mid + 1;
    } else {
    r = mid - 1;
    }
}

return ans;
}

https://leetcode.cn/problems/valid-perfect-square/

妙解:4=1+3 9=1+3+5 16=1+3+5+7以此类推,模仿它可以使用一个while循环,不断减去一个从1开始不断增大的奇数,若最终减成了0,说明是完全平方数,否则,不是。

bool isPerfectSquare(int num) 
{
int num1 = 1;
	while(num > 0) 
    {
	 num -= num1;
	 num1 += 2;
    }
	return num == 0;
}

基于二分查找

bool isPerfectSquare(int num) {
int left = 0, right = num;
while (left <= right) {
    int mid = (right - left) / 2 + left;
    long square = (long) mid * mid;
    if (square < num) {
    left = mid + 1;
    } else if (square > num) {
    right = mid - 1;
    } else {
    return true;
    }
}
    return false;
}

务必把二分法框架背住!注意区分区间!左闭右闭 还是左闭右开.然后自己上网搜索一下二分法变型!