找出有序數組中絕對值最小的數


假設數組是從小到大排序,數值可能為負數、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

因此只需比較邊上的兩個值的絕對值大小,方可揭曉答案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM