面试_算法_折半查找

57 阅读1分钟
    /**************************************************************************************/
    //非递归的折半查找
    static int BinarySearch1(int[] arr, int target) {
        int left = 0;
        int right = arr.length - 1; // 注意
        while (left <= right) {
          // 和 (left + right)/2 的结果相同,但是有效防止了 left 和 right 太大直接相加导致mid溢出。
            int mid = left + (right - left) / 2;
            if (arr[mid] > target)
                right = mid - 1;  // 注意
            else if (arr[mid] < target)
                left = mid + 1;  // 注意
            else
                return mid;
        }
        return -1;
    }
    /**************************************************************************************/







    /**************************************************************************************/
    //递归的折半查找
    static int BinarySearch2(int[] arr, int target, int left, int right) {
        while (left <= right) {
            int mid = left + (right - left) / 2;
            if (arr[mid] > target)
                return BinarySearch2(arr, target, left, mid - 1);
            else if (arr[mid] < target)
                return BinarySearch2(arr, target, mid + 1, right);
            else
                return mid;
        }
        return -1;
    }
/**************************************************************************************/


折半查找的改进:插值查找

考虑一个新问题,为什么上述算法一定要是折半,而不是折四分之一或者折更多呢?

打个比方,比如要在取值范围1 ~ 1000 之间 1000个元素从小到大均匀分布的数组中查找5, 我们自然会考虑从数组下标较小的开始查找,而不必从中间的500开始。即自适应确定查找位置。

二分查找中查找点计算如下:   

int mid=(left+right)/2, 即 mid=left+1/2*(right-left)/2;

通过类比,我们可以将查找的点改进为如下:

int mid = left + (target - arr[left]) / (arr[right] - arr[left]) * (right - left);


二分(模糊)查找+插入

#include <iostream>

using namespace std;

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(target==nums[mid]) return mid;
        else if(target<nums[mid])
        {
            right=mid-1;
        }
        else
        {
            left=mid+1;
        }
    }
    return left;
}

int main()
{
    //原数组为a的前5个数,a的总长度为6
    //想插入的值:a[5]
       int a[]={1,2,4,5,9,3};

       cout<<"插入前的数组:";
       for(int i=0;i<6;i++)
        cout<<a[i]<<" ";
       cout<<endl<<endl;
       int loca=search(a,6,a[5]);
       cout<<"应改将a[5]插入到下标为"<<loca<<"的地方"<<endl<<endl;
       cout<<"插入后的数组:";




       //插入过程
       int temp=a[5];
       for(int s=5;s>loca;s--)
       {
           a[s]=a[s-1];
       }
       a[loca]=temp;




       for(int i=0;i<6;i++)
        cout<<a[i]<<" ";
    return 0;
}