代码随想录day01|704.二分查找 、27移除元素

本文详细介绍了二分查找算法的两种实现方式(左闭右闭和左闭右开),以及如何应用二分法解决在有序数组中查找元素的插入位置和移除元素的问题。作者还讨论了错误分析和新知识,如右移运算符在改进代码中的应用。
摘要由CSDN通过智能技术生成

题目链接:704.二分查找

代码实现

第一种(左闭右闭)

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的值

相关题目:34在排序数组中查找元素的第一个和最后一个位置

思路:通过两个二分法分别找出左右两个边界。

错误和分析:我将数组从中间分成两半,然后这个中间值作为左右两个边界了,应该是先用二分法找出第一个出现的目标值,然后再根据找哪个边界值然后才进行下一个二分法。虽然我的想法是这个的,但是我的代码还是先是将中间值作为了边界值

新知识:>>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;
}

题目链接:35搜索插入位置

代码实现

左闭右闭

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是区间内的值

题目链接:27移除元素

代码实现

暴力解法

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;
}

总结

数组理论知识:数组在内存上是连续的,不可以通过删除移除元素,只可以通过覆盖元素

双指针:慢指针是指向数组位置,快指针是指向数值,将原来的数组当作空白的数组,只要不是删除值,那么就将它复制数组中

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值