![](/img/trans.png)
[英]How do I efficiently count elements less than a certain value in a sorted array?
[英]How to efficienlty calculate the difference between array items and find out how many differences are less than a certain value?
我有一個數組,需要計算每個項目與所有其他項目之間的差。 如果差異小於或等於某個值(限制),我必須將其計為1。
我使用蠻力方法實現了它:
for (int i = 0; i < n; i++) {
int j = 0;
while (j < n) {
if (Math.abs(arr1[i] - arr1[j]) <= limit) {
sum = sum + 1;
}
j++;
}
}
現在,我正在尋找優化的解決方案,因為這里的時間復雜度是O(n^2)
。 如果要避免2個循環,什么是解決此問題的好方法?
如果必須確定數組中每對元素之間的差異是否小於或等於限制,則最好對數組進行排序(O(NlogN))。
現在,對於排序數組中的每個元素x,您必須找到值在x-limit和x + limit之間的元素范圍的長度。 可以在O(logN)
時間內使用二進制搜索(即調用Arrays.binarySearch(sortedArray, x - limit)
和Arrays.binarySearch(sortedArray, x + limit)
)找到此內容。 您將該范圍的長度加到總和中。
由於您必須對每個元素重復該操作,因此總時間為O(NlogN)。
最后,由於您要對每對進行兩次計數,因此必須將結果除以二。
總運行時間為O(NlogN) + O(NlogN) = O(NlogN)
。
順便說一句,您當前的實現似乎不正確:
您正在將每個元素與其自身進行比較,該元素的總和將具有n的額外值。
您將每對元素進行兩次比較,因此每對足夠接近的元素將被計數兩次。
編輯:實際上,由於不是只對每個接近對進行兩次計數然后除以2,因此,如果我們僅對array[i]
(不包括)和array[i] + limit
(包括)之間的元素數進行計數,則可以對這些對進行一次計數)。 這意味着為每個索引運行一次二進制搜索就足夠了。
這是一個正在運行的示例:
public static int comparePairs (int[] arr1, int limit) {
int sum = 0;
Arrays.sort (arr1);
for (int i = 0; i < arr1.length - 1; i++) {
int last = Arrays.binarySearch (arr1, arr1[i] + limit);
if (last > 0) {
sum += last - i;
} else {
sum += -last - i - 2;
}
}
return sum;
}
請注意,它不支持重復元素,因此需要進行一些調整才能使用重復元素。
例如,它為數組{2,6,4,3,1,5}
返回9
,並為極限2
(兩對為(1,2)(1,3)(2,3)(2,4) (3,4)(3,5)(4,5)(4,6)(5,6))。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.