簡體   English   中英

如何在O(log(N))時間內找到排序數組中在一定范圍內的整數數?

[英]How to find number of integers in a sorted array that are within a certain range in O(log(N)) time?

我有一個排序的整數數組:

{1,2,4,4,5,8,12,15,15,23,54}

我想知道該數組中有多少數字落在一個范圍之間,例如4到15之間。

{4,4,5,6,12,15,15}

因此,陣列中有7個項目在該范圍內。

我需要在O(log(N))時間內執行此操作,並且我認為我可以使用二進制搜索,但由於重復,因此無法找到下限和上限。

如何在O(log(N))時間內完成?

我想過從前面循環,然后從最后循環,但這可能達到O(N)

它可以在O(logN)時間內通過范圍二進制搜索來完成下限和上限。 下限和上限的范圍二進制搜索是不同的 這里不同意味着它們具有不同的停止標准和返回步驟。

  1. 對於下限(左范圍) ,您可以調用以下函數來獲取值大於或等於它的排序數組中的索引,否則為-1。

     int binarySearchForLeftRange(int a[], int length, int left_range) { if (a[length-1] < left_range) return -1; int low = 0; int high = length-1; while (low<=high) { int mid = low+((high-low)/2); if(a[mid] >= left_range) high = mid-1; else //if(a[mid]<i) low = mid+1; } return high+1; } 
  2. 對於上限(右側范圍) ,您可以調用以下函數來獲取排序數組中的索引,其中值小於或等於它,否則為-1。

     int binarySearchForRightRange(int a[], int length, int right_range) { if (a[0] > right_range) return -1; int low = 0; int high = length-1; while (low<=high) { int mid = low+((high-low)/2); if(a[mid] > right_range) high = mid-1; else //if(a[mid]<i) low = mid+1; } return low-1; } 
  3. 最后 ,如果您想獲得此范圍內的元素數量,則可以根據上述兩個函數的返回值輕松實現。

     int index_left = binarySearchForLeftRange(a, length, left_range); int index_right = binarySearchForRightRange(a, length, right_range); if (index_left==-1 || index_right==-1 || index_left>index_right) count = 0; else count = index_right-index_left+1; 

測試 :(有重復)

    int a[] = {1,2,4,4,5,8,12,15,15,23,54};
    int length = sizeof(arr)/sizeof(arr[0]);

    int left_range = 4;
    int right_range = 15;
    int index_left = binarySearchForLeftRange(a, length, left_range); // will be 2
    int index_right = binarySearchForRightRange(a, length, right_range); // will be 8

    int count; // will be 7
    if (index_left==-1 || index_right==-1 || index_left>index_right)
        count = 0;
    else
        count = index_right-index_left+1;

編輯 :當然,您可以通過傳遞一個額外的標志來將前兩個函數合並為一個,以指示它是下限或上限,但如果不是,則會更清楚。 你的選擇!

在二進制搜索中,當您找到所需的數字或數字不在列表中時,您將停止遞歸過程。
在這里,您必須修改二進制搜索算法。 與較低的范圍開始, ,不斷重復,直到你找到了一些不足 在這樣做的同時保持兩個指數,即低點高點 如果您要比較的數字小於a ,則更新低其他更新高。 現在你有較低的指數,現在應用這個遞歸過程來找到一個比這更大的數量。 該索引將給出起始索引。
現在,做上限范圍的免費贈送,您將獲得結束指數。
答案是ending index - starting index + 1

imin = 0, imax = A.size()-1
low = 0, high = A.size()-1
while(imax >= imin)
{
   imid = mid(imin,imax)
   if(key < A[imid])
   {
       imax = imid -1
       high = imid
   }
   else if(key > A[imid])
   {
       imin = imid + 1
       low = imid
   }
   else 
   {
       high = imid
       break;
   }
 }

現在,一旦它從循環中檢出imin > imax ,如果是,則較低范圍索引將是imax。 否則,使用相同的鍵再次使用imin = lowimax = high重復搜索,直到達到imin > imax的條件。 對上限范圍重復相同的操作。
時間復雜度介於O(log(n))O(n)

您需要一個修改過的二進制搜索,它具有一個參數,無論是查找元素的第一個還是最后一個。
您必須自己編寫修改后的binsearch。

我沒有解釋我已經在java中給出了代碼,如果你想要你可以改進它。

 public class Test {

public static int binSearch(int array[], int key, int left, int right,boolean lb)
{
int mid = left + (right-left)/2;
if (key < array[mid])
    return binSearch(array, key, left, mid-1,lb);
else if (key > array[mid])
    return binSearch(array, key, mid+1, right,lb);
else if (key == array[mid]){
    if(!lb){
    if(key==array[mid+1]){
        int ctr=mid+1;
        while(key==array[++ctr]);
        return ctr--;
      }
    else
        return mid;
    }
    else{
    if(key==array[mid-1]){
        int ctr=mid-1;
        while(key==array[--ctr]);
        return ctr++;
    }
    else
        return mid;
   }

}
return -0; // Not Found

}

public static void main(String[] args) {
int a[]={1,2,4,4,5,8,12,15,15,23,54};
int start=binSearch(a, 4, 0, a.length,true);
int end=binSearch(a, 15, 0, a.length,false);
System.out.println(end-start+1);// number are include
}

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM