有序数组二分查找最接近的值

有序数组二分查找最接近的值

  • 问题
  • 思路
  • 代码
    • 循环的终止条件
    • 如何改为求upper_bound

问题

给你一个有序数组,数组里面有正有负,有重复值,再给你扔一个target 数,求这个数组中最接近target的数的值。如果有多个返回一个即可。

思路

求lower_bound,也就是我们可以通过求第一个大于等于targetnum的值来获取。
但是求得lower_bound之后不一定代表着最接近,因为可能比target小的数更接近target,因此最后来一个比较即可。

代码

最简单的直接调用API

int binaryfind(vector<int>& vec, const int target)
{
 	auto j = lower_bound(vec.begin(), vec.end(), target);
    if (j - vec.begin() == 0 || abs(*(j - 1) - target) > abs(*j - target)) 
    {
        return *j;
    }
    else 
    {
        return *(j - 1);
    }
} 

也可以自己手动实现:

int binaryfind(vector<int>& vec, const int target)
{
    int size = vec.size();
    if (target <= vec[0])
    {
        return vec[0];
    }
    if (target >= vec[size - 1])
    {
        return vec[size - 1];
    }
    int left, right, mid;
    left = 0;
    right = size - 1;
    while (left < right)
    {
        mid = left + (right - left) / 2;
        if (vec[mid] == target)
        {
            return vec[mid];
        }
        else if (vec[mid]<target)
        {
            left = mid+1;
        }
        else
        {
            right = mid;
        }
    }
    if (left==0||abs(target - vec[left]) < abs(target - vec[left - 1])) 
    {
        return vec[left];
    }
    else
    {
        return vec[left-1];
    }
}

有两个值得注意的地方,也是很多人写二分老是搞不清楚的地方

循环的终止条件

有两种写法:

   while (left < right)
   {
		if(A)
		{
			left=mid+1;
		}
		else
		{
			right=mid;
		}
	}

以及

   while (left <= right)
   {
		if(A)
		{
			left=mid+1;
		}
		else
		{
			right=mid-1;
		}
	}

这两种写法是等价的

如何改为求upper_bound

我们只需要更改第一个if条件语句从<改为<=即可

你可能感兴趣的:(数据结构及算法笔记,数据结构,c++,算法,二分法)