查找排序数组中的所有差异
Find all differences in sorted array
我有一个排序(升序)的实数值数组,称之为 a(可能重复)。我希望在给定值范围 [x, y] 的情况下找到所有索引 j 存在的值 (i) 的索引,以便:
j>我和
x <= a[j]-a[i] <= y
或者简单地说,找到在给定范围内存在“前向差异”的值。
输出是一个长度为 a.Length 的布尔数组。
由于数组对所有前向差异进行排序,因此 x 和 y 为正。
我能做的最好的事情是从每个索引开始,查看它前面的子数组,然后对 x+a[i] 执行二进制搜索并检查是否 a[j]<=y+a [一世]。我认为这是 O(n log n)。
有更好的方法吗?或者我可以做些什么来加快速度。
我应该注意到,最终我想在同一个数组 a 上搜索许多这样的范围 [x,y],但是范围的数量远小于数组的长度 (4-6小几个数量级)——因此我更关心搜索的复杂性。
示例:
a= 0, 1, 46, 100, 185, 216, 285
范围 x,y=[99,101] 应该 return:
[true, true, false, false, true, false, false]
只有值 0,1 和 185 在范围内具有前向差异。
记忆中的代码,可能有一些错误:
int bin_search_closesmaller(int arr[], int key, int low, int high)
{
if (low > high) return high;
int mid = (high - low)/2;
if (arr[mid] > key) return bin_search_closesmaller(arr, key, low, mid - 1);
if (arr[mid] < key) return bin_search_closesmaller(arr, key, mid + 1, high);
return mid;
}
bool[] findDiffs(int[] a, int x, int y)
{
bool[] result = new bool[a.Length];
for(int i=0; i<a.Length-1;i++)
{
int idx=bin_search_closesmaller(a, y+a[i], i+1, a.Length-1);
if (idx==-1) continue;
if (a[idx]-a[i] >= x) result[i]=true;
}
}
谢谢!
只要输入数组排序,问题就有线性解。关键是利用两个索引遍历数组a
.
bool[] findDiffs(int[] a, int x, int y)
{
bool[] result = new boolean[a.Length];
int j = 0;
for (int i = 0; i < a.Length; ++i) {
while (j < a.Length && a[j] - a[i] < x) {
++j;
}
if (j < a.Length) {
result[i] = a[j] - a[i] <= y;
}
}
return result;
}
与 a = [0,100,1000,1100]
和 (x,y) = (99,100)
:
i = 0, j = 0 => a[j] - a[i] = 0 < x=99 => ++j
i = 0, j = 1 => a[j] - a[i] = 100 <= y=100 => result[i] = true; ++i
i = 1, j = 1 => a[j] - a[i] = 0 < x=99 => ++j
i = 1, j = 2 => a[j] - a[i] = 900 > y=100 => result[i] = false; ++i
i = 2, j = 2 => a[j] - a[i] = 0 <= x=99 => ++j
i = 2, j = 3 => a[j] - a[i] = 100 <= y=100 => result[i] = true; ++i
i = 3, j = 3 => a[j] - a[i] = 0 <= x=99 => exit loop
创建两个索引 left
和 right
并遍历数组。 Right
索引移动直到超出当前 left
的范围,然后检查前一个元素是否在范围内。索引只向前移动,所以算法是线性的
right=2
for left = 0 to n-1:
while A[right] < A[left] + MaxRangeValue
right++
Result[left] = (A[right - 1] <= A[left] + MinRangeValue)
关于这个算法的另一种观点:
-当差异太小时,向右增加
-当差异太大时,向左增加
我有一个排序(升序)的实数值数组,称之为 a(可能重复)。我希望在给定值范围 [x, y] 的情况下找到所有索引 j 存在的值 (i) 的索引,以便: j>我和 x <= a[j]-a[i] <= y 或者简单地说,找到在给定范围内存在“前向差异”的值。
输出是一个长度为 a.Length 的布尔数组。 由于数组对所有前向差异进行排序,因此 x 和 y 为正。
我能做的最好的事情是从每个索引开始,查看它前面的子数组,然后对 x+a[i] 执行二进制搜索并检查是否 a[j]<=y+a [一世]。我认为这是 O(n log n)。 有更好的方法吗?或者我可以做些什么来加快速度。
我应该注意到,最终我想在同一个数组 a 上搜索许多这样的范围 [x,y],但是范围的数量远小于数组的长度 (4-6小几个数量级)——因此我更关心搜索的复杂性。
示例:
a= 0, 1, 46, 100, 185, 216, 285
范围 x,y=[99,101] 应该 return:
[true, true, false, false, true, false, false]
只有值 0,1 和 185 在范围内具有前向差异。
记忆中的代码,可能有一些错误:
int bin_search_closesmaller(int arr[], int key, int low, int high)
{
if (low > high) return high;
int mid = (high - low)/2;
if (arr[mid] > key) return bin_search_closesmaller(arr, key, low, mid - 1);
if (arr[mid] < key) return bin_search_closesmaller(arr, key, mid + 1, high);
return mid;
}
bool[] findDiffs(int[] a, int x, int y)
{
bool[] result = new bool[a.Length];
for(int i=0; i<a.Length-1;i++)
{
int idx=bin_search_closesmaller(a, y+a[i], i+1, a.Length-1);
if (idx==-1) continue;
if (a[idx]-a[i] >= x) result[i]=true;
}
}
谢谢!
只要输入数组排序,问题就有线性解。关键是利用两个索引遍历数组a
.
bool[] findDiffs(int[] a, int x, int y)
{
bool[] result = new boolean[a.Length];
int j = 0;
for (int i = 0; i < a.Length; ++i) {
while (j < a.Length && a[j] - a[i] < x) {
++j;
}
if (j < a.Length) {
result[i] = a[j] - a[i] <= y;
}
}
return result;
}
与 a = [0,100,1000,1100]
和 (x,y) = (99,100)
:
i = 0, j = 0 => a[j] - a[i] = 0 < x=99 => ++j
i = 0, j = 1 => a[j] - a[i] = 100 <= y=100 => result[i] = true; ++i
i = 1, j = 1 => a[j] - a[i] = 0 < x=99 => ++j
i = 1, j = 2 => a[j] - a[i] = 900 > y=100 => result[i] = false; ++i
i = 2, j = 2 => a[j] - a[i] = 0 <= x=99 => ++j
i = 2, j = 3 => a[j] - a[i] = 100 <= y=100 => result[i] = true; ++i
i = 3, j = 3 => a[j] - a[i] = 0 <= x=99 => exit loop
创建两个索引 left
和 right
并遍历数组。 Right
索引移动直到超出当前 left
的范围,然后检查前一个元素是否在范围内。索引只向前移动,所以算法是线性的
right=2
for left = 0 to n-1:
while A[right] < A[left] + MaxRangeValue
right++
Result[left] = (A[right - 1] <= A[left] + MinRangeValue)
关于这个算法的另一种观点:
-当差异太小时,向右增加
-当差异太大时,向左增加