数组二分法

本文讲解了如何使用二分法解决704问题(二分查找)及其在其他相关问题(如插入位置、范围搜索)中的应用。通过实例代码演示了左闭右闭和左闭右开两种情况,展示了二分查找的时间复杂度和空间复杂度。同时介绍了与之相关的编程挑战和解决方案。
摘要由CSDN通过智能技术生成

数组二分法

一、题源:

704. 二分查找
问题描述

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

二、 思路:

1、暴力解法

最容易想到的方法就是直接对数组进行遍历,对比数组元素与target
时间复杂度: O ( n ) O(n ) O(n)
空间复杂度: O ( 1 ) O(1) O(1)
注:暴力法虽然思路简单,容易想到,但是对于这个问题还有时间复杂度更低的方法

2、二分法

对于有序不重复的数组,可以针对题目要求考虑是否可以用二分法实现。

对于二分法的实现有不同的写法,但是很容易写乱,循环里面到底是left <= right还是left < right,还有迭代时midleft还有right的关系,这些都是比较容易出错的点,对于这个问题大家可以详细参考二分查找

总结来看

  • 对于左闭右闭[left, right],循环时left <= right,因为left == right有意义
  • 对于左闭右开[left, right),循环时left < right,因为left == right没有意义
  • 对于迭代时保持循环不变量原则,保证迭代后的区间和之前设置的区间开闭一致。

参考代码 (左闭右闭[left, right])


int search(int* nums, int numsSize, int target) {
    int low = 0,high = numsSize - 1, mid;
    while(low <= high) {
        mid = (low + high) / 2;
        if(nums[mid] == target) return mid;
        else if(nums[mid] > target) {
            high = mid - 1;//[low, mid - 1]
        }
        else {
            low = mid + 1;//[mid + 1, high]
        }
    }
    return -1;
}

参考代码 (左闭右开[left, right))


int search(int* nums, int numsSize, int target) {
    int low = 0,high = numsSize, mid;
    while(low < high) {
        mid = (low + high) >> 1;
        if(nums[mid] == target) return mid;
        else if(nums[mid] > target) {
            high = mid;//[low, mid)
        }
        else {
            low = mid + 1;//[mid + 1, high)
        }
    }
    return -1;
}

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)
空间复杂度: O ( 1 ) O(1) O(1)

三、相关题目及C语言实现

35. 搜索插入位置

问题描述:

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O ( l o g n ) O(log n) O(logn) 的算法。

实现:


int searchInsert(int* nums, int numsSize, int target){
    int low = 0, high = numsSize - 1, mid;
    while(low <= high){
        mid = (low + high) >> 1;
        if(nums[mid] == target) return mid;
        else if(nums[mid] < target) low = mid + 1;
        else high = mid -1;
    }
    return low;
}

34. 在排序数组中查找元素的第一个和最后一个位置

问题描述:

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

实现:

int* searchRange(int* nums, int numsSize, int target, int* returnSize){
    int low = 0, high = numsSize - 1, mid;
    int* result = (int*)malloc(sizeof(int)*2);
    *returnSize = 2;
    while(low <= high){
        mid = (low + high) >> 1;
        if(nums[mid] == target)
        {
            int i = mid;
            while(i > 0 && nums[i-1] ==target)  i--;
            result[0] = i;
            i = mid;
            while(i < numsSize-1 && nums[i+1] == target)  i++;
            result[1] = i;
            return result;
        }else if(nums[mid] < target) low = mid + 1;
        else high = mid - 1;
    }
    result[0] = -1;
    result[1] = -1;
    return result;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值