代码改变世界

百度面试题:求绝对值最小的数

  youxin  阅读(883)  评论(0编辑  收藏  举报

有一个已经排序的数组(升序),数组中可能有正数、负数或0,求数组中元素的绝对值最小的数,要求,不能用顺序比较的方法(复杂度需要小于O(n)),可以使用任何语言实现
例如,数组{-20,-13,-4, 6, 77,200} ,绝对值最小的是-4。

我们首先要看到,是已经排序的。 

算法实现的基本思路三种情况:

全负数 全正数 正负皆有
1:取最右 时间复杂度为o(1)
2:取最左 时间复杂度为o(1)
3:二分查找0, 找到为最小,否则最后查找区间,左右取绝对值最小,时间复杂度为o(log2 n)

这个二分查找还是有点难写的,如果arr[mid]为正,还要分arr[mid-1]是否为负,若为负,则一定是arr[mid]或arr[mid-1],若

arr[mid-1]不为负,另high=mid-1;则半查找,从这点可以看出二分查找真是可以应用在许多场合。

 

复制代码
#include<iostream>
#include<vector>
#include<cmath>
using namespace std;

vector<int> getAbsMinVal(int arr[],int n)
{
    vector<int> ret;
    if(n<2)
    {
        ret.push_back(arr[0]);
    }
    else
    {
        if(arr[n-1]<=0)//全为负数
        {
            ret.push_back(arr[n-1]);
        }
        else if(arr[0]>=0)
        {
            ret.push_back(arr[0]);
        }
        else
        {
            int low=0,high=n-1;
            while(low<=high)
            {
                int mid=(low+high)/2;
                if(arr[mid]==0)//中间位置为0.返回0
                {
                    ret.push_back(arr[0]);
                }
                else if(arr[mid]>0)//中间位置为正数
                {
                    if(arr[mid-1]<0)//前一个位置为负数
                    {
                        if(abs(arr[mid-1])==abs(arr[mid]))
                        {
                            ret.push_back(arr[mid-1]);
                            ret.push_back(arr[mid]);
                        }
                        else
                        {
                            ret.push_back(abs(arr[mid-1])<abs(arr[mid])?arr[mid-1]:arr[mid]);
                        }
                        break;
                    }
                    high=mid-1;
                }
                else //中间位置为负数
                {
                    if(arr[mid+1]>0)//中间位置后一个为正数
                    {
                        if(abs(arr[mid])==abs(arr[mid+1]))
                        {
                            ret.push_back(arr[mid]);
                            ret.push_back(arr[mid+1]);
                        }
                        else
                        {
                            ret.push_back(abs(arr[mid])<abs(arr[mid+1])?arr[mid]:arr[mid+1]);
                        }
                        break;
                    }
                    low=mid+1;
                }
            }

        }
    }//end else
    
    return ret;
}

int main()
{
    int arr[]={-5,-4,2,3,5};
    vector<int> ret=getAbsMinVal(arr,sizeof(arr)/sizeof(arr[0]));
    for(int i=0;i<ret.size();i++)
        cout<<ret[i]<<ends;
}
复制代码

 

编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
历史上的今天:
2012-09-10 设计模式之装饰者模式
点击右上角即可分享
微信分享提示