找出有序数组中绝对值最小的数

简介:

假设数组是从小到大排序,数值可能为负数、0、正数。

思路一

可以一次性遍历一遍,找出绝对值最小值,此时时间复杂度为O(N),缺点是没有利用数组是有序的这一特点。

 

思路二

数组有序,可以利用二分查找的特性。中间的数是正数,往后找;中间的数是负数,往前找。

问题的本质是找到正数的最小值,或负数的最大值,分析以下集中情况

数组为a[], 数组大小为n.

  • n=1,没有商量的余地,直接返回
  • a[0] * a[n-1] >= 0,说明这些元素同为非正或同为非负。要是a[0]>=0,返回a[0];否则返回a[n-1]
  • a[0] * a[n-1] < 0,说明这些元素中既有整数,也有负数。此时需要计算中间位置为mid = low + high/2,如果a[mid]*a[low] >=0说明a[mid]也为非正,缩小范围low=mid;如果a[mid]*a[high]>=0,说明a[mid]非负,缩小范围high=mid。在期间如果还有两个元素,那么就比较以下他俩,直接返回了

参考代码

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

int absMin(int *a, int size)
{
    if(size == 1)
        return a[0];
    if(a[0] * a[size-1] >= 0)
        return (a[0] >= 0) ? a[0] : a[size-1];
    else
    {
        int low = 0, high = size-1, mid;
        while(low < high)
        {
            if(low + 1 == high)
                return abs(a[low]) < abs(a[high]) ? a[low] : a[high];
            mid = low + (high - low) / 2;
            if(a[low] * a[mid] >= 0)
                low = mid;
            if(a[high] * a[mid] >= 0)
                high = mid;
        }
    }
}

int main()
{
    int arr1[] = {-8, -3, -1, 2, 5, 7, 10};
    size_t size1 = sizeof(arr1) / sizeof(int);
    int minabs1 = absMin(arr1, size1);
    cout << "Result:" << minabs1 << endl;

    int arr2[] = {-8, -3, 2, 5, 7, 10};
    size_t size2 = sizeof(arr2) / sizeof(int);
    int minabs2 = absMin(arr2, size2);
    cout << "Result:" << minabs2 << endl;
}
复制代码

结果

复杂度分析

时间复杂度O(log2n),空间复杂度O(1).

 ===========================================

改进1:完全可以把这些特例(size=1、同号,放到while循环里)

============================================

复制代码
int absMin(int *a, int size)
{
    int low = 0, high = size-1, mid;
    while(low <= high)
    {
        if(a[low] * a[high] >= 0)
            return (a[low] >= 0) ? a[low] : a[high]; 
        if(low + 1 == high)
            return abs(a[low]) < abs(a[high]) ? a[low] : a[high];
        mid = low + (high - low) / 2;
        if(a[low] * a[mid] >= 0)
            low = mid;
        if(a[high] * a[mid] >= 0)
            high = mid;
    }
cout << "ERROR, size <= 0" << endl;
return -1; //size <= 0 }
复制代码

 

拓展

有序(自小到达)绝对值最大呢?

如果有整数、0、负数的话,绝对值最小值在相对中间部位。但是如果求绝对值最大,绝对在两边,例如

  1. 1 2 3 
  2. -4 -3 -2 -1
  3. -4 -2 0 1 2

因此只需比较边上的两个值的绝对值大小,方可揭晓答案。





本文转自jihite博客园博客,原文链接:http://www.cnblogs.com/kaituorensheng/p/3576381.html,如需转载请自行联系原作者

相关文章
|
存储 关系型数据库 PostgreSQL
深入浅出PostgreSQL B-Tree索引结构
PostgreSQL 的B-Tree索引页分为几种类别 meta page root page # btpo_flags=2 branch page # btpo_flags=0 leaf page # btpo_flags=1 如果即
14901 0
|
SQL 存储 关系型数据库
京东面试:分库分表后,如何深度翻页?
在40岁老架构师尼恩的读者交流群中,有小伙伴在京东面试时遇到了MySQL分库分表后深度分页太慢的问题。本文详细分析了单表和分表场景下的性能问题及优化方法,包括索引覆盖、子查询分页、Join分页、禁止跳页查询、二次查询法等。此外,还介绍了使用ES+HBase的海量NOSQL架构方案。通过这些方法,可以显著提升分页查询的性能,帮助面试者在技术面试中脱颖而出。
京东面试:分库分表后,如何深度翻页?
|
存储 Linux 调度
太好用了!Python 定时任务调度框架 APScheduler 详解!
太好用了!Python 定时任务调度框架 APScheduler 详解!
1659 0
|
存储 Ubuntu Java
如何在 Unbuntu 下安装配置 Apache Zookeeper
如何在 Unbuntu 下安装配置 Apache Zookeeper
553 0
|
监控 关系型数据库 PostgreSQL
PostgreSQL bgwriter,walwriter,backend process 写磁盘的实时监控
标签 PostgreSQL , 背景 数据库有两大块buffer,wal buffer和shared buffer。 wal buffer是预写日志缓冲区。 shared buffer是数据页缓冲区。
2900 0
|
监控 安全 算法
这次锁面试题的连环16问,差点就跪了
这次锁面试题的连环16问,差点就跪了
428 0
|
负载均衡 NoSQL 网络协议
“12306” 是如何支撑百万 QPS 的?(一)
“12306” 是如何支撑百万 QPS 的?(一)
“12306” 是如何支撑百万 QPS 的?(一)
|
存储 安全 NoSQL
项目终于用上了 Spring 状态机,非常优雅!
项目终于用上了 Spring 状态机,非常优雅!