代码实现
第一种(左闭右闭)
int search(int* nums, int numsSize, int target) {
int left = 0;
int right = numsSize - 1;
int middle;
while(left <= right){
middle = (left + right) / 2;
if(target < nums[middle])
right = middle - 1;
else if(target >nums[middle] )
left = middle + 1;
else
return middle;
}
return -1;
}
第二种(左闭右开)
int search(int* nums, int numsSize, int target) {
int left = 0;
int right = numsSize;
int middle;
while(left < right){
middle = (left + right) / 2;
if(target < nums[middle])
right = middle;
else if(target >nums[middle] )
left = middle + 1;
else
return middle;
}
return -1;
总结
二分法要是一有序的数组才可以,区间的选择决定了whlie的的条件和right的值
思路:通过两个二分法分别找出左右两个边界。
错误和分析:我将数组从中间分成两半,然后这个中间值作为左右两个边界了,应该是先用二分法找出第一个出现的目标值,然后再根据找哪个边界值然后才进行下一个二分法。虽然我的想法是这个的,但是我的代码还是先是将中间值作为了边界值
新知识:>>1右移运算符,将二进制位数向右移动一位,相当于整数除法除以2
middle = left+((right - letf) >> 1) 等于 middle=(left+right)/2
代码实现
int searchLeftBorder(int *nums, int numsSize, int target) {
int left = 0, right = numsSize - 1;
// 记录leftBorder没有被赋值的情况
int leftBorder = -1;
// 边界为[left, right]
while (left <= right) {
// 更新middle值,等同于middle = (left + right) / 2
int middle = left + ((right - left) >> 1);
// 若当前middle所指为target,将左边界设为middle,并向左继续寻找左边界
if (nums[middle] == target) {
leftBorder = middle;
right = middle - 1;
} else if (nums[middle] > target) {
right = middle - 1;
} else {
left = middle + 1;
}
}
return leftBorder;
}
int searchRightBorder(int *nums, int numsSize, int target) {
int left = 0, right = numsSize - 1;
// 记录rightBorder没有被赋值的情况
int rightBorder = -1;
while (left <= right) {
int middle = left + ((right - left) >> 1);
// 若当前middle所指为target,将右边界设为middle,并向右继续寻找右边界
if (nums[middle] == target) {
rightBorder = middle;
left = middle + 1;
} else if (nums[middle] > target) {
right = middle - 1;
} else {
left = middle + 1;
}
}
return rightBorder;
}
int* searchRange(int* nums, int numsSize, int target, int* returnSize){
int leftBorder = searchLeftBorder(nums, numsSize, target);
int rightBorder = searchRightBorder(nums, numsSize, target);
// 定义返回数组及数组大小
*returnSize = 2;
int *resNums = (int*)malloc(sizeof(int) * 2);
resNums[0] = leftBorder;
resNums[1] = rightBorder;
return resNums;
}
代码实现
左闭右闭
int searchInsert(int* nums, int numsSize, int target) {
int left = 0;
int right = numsSize - 1;
int middle;
while(left <= right){
middle = (left + right)/2;
if(nums[middle] < target )
left = middle + 1;
else if(nums[middle] > target)
right = middle - 1;
else
return middle;
}
return right + 1;
}
左闭右开
int searchInsert(int* nums, int numsSize, int target) {
int left = 0;
int right = numsSize;
int middle;
while(left < right){
middle = (left + right)/2;
if(nums[middle] < target )
left = middle + 1;
else if(nums[middle] > target)
right = middle;
else
return middle;
}
return right;
}
遇到问题
return值写了middle
——当while循环后,还没有找到的话,证明目标值不在区间内,而middle是区间内的值
代码实现
暴力解法
int removeElement(int* nums, int numsSize, int val) {
for(int i = 0;i < numsSize; i++){
if(nums[i] == val)
{
for(int j = i + 1; j < numsSize; j++ )
nums[j - 1] = nums[j];
i--;
numsSize--;
}
}
return numsSize;
}
双指针
int removeElement(int* nums, int numsSize, int val) {
int slow = 0;
for(int fast = 0; fast < numsSize; fast++){
if(nums[fast] != val)
nums[slow++] = nums[fast];
}
return slow;
}
总结
数组理论知识:数组在内存上是连续的,不可以通过删除移除元素,只可以通过覆盖元素
双指针:慢指针是指向数组位置,快指针是指向数值,将原来的数组当作空白的数组,只要不是删除值,那么就将它复制数组中