给定一个数字数组和一个确定的目标和sum,如何找到一个接一个的子数组,有多少对的和等于sum?我试过使用哈希表,找出sum-x和x的出现次数,x是子数组的一个元素。但是如何针对多个查询(端点对)进行优化呢?为每个查询创建哈希表的成本太高。
sum
sum-x
x
pjngdqdw1#
首先,我们先来讨论一下预计算所有结果,然后让它们更有效地被访问。预计算所有索引对<i, j>,其中a[i] + a[j] = sum可以在O(n)中离线执行,其中n是输入数组a的大小。然后,您可以将预先计算的对存储在2D空间索引结构中(例如,R树或四叉树)。然后,子数组查询(start, end)对应于2d索引上的范围查询(具有二次框),其中min = (start, start)和max = (end, end)。根据查询的范围,这在O(log m)中应该是可能的,其中m是对的总数。
<i, j>
a[i] + a[j] = sum
O(n)
n
a
(start, end)
min = (start, start)
max = (end, end)
4sup72z82#
不需要为特定的总和构建哈希表:可以在初始步骤中构造散列表,并且对于整个阵列,可以在线性时间内回答对任何sum的查询。对于长度为n的数组arr,请执行以下步骤:
arr
arr[i]
0
total
x = arr[i]
x * 2 < sum
sum - x
count
count * 2
x * 2 == sum
count + 1
total / 2
要回答子数组的查询,上述方法不起作用。当然,你可以总是使用嵌套循环,并在没有额外空间的情况下找到二次时间的计数。下面是一个针对子阵列和任何给定sum的更有效的解决方案:
{ index: i, value: arr[i] }
value
下面是int数组的实现:
int
#include <stdlib.h> struct array_values { size_t index; int value; }; static int array_values_compare(const void *aa, const void *bb) { const struct array_values *a = aa; const struct array_values *b = bb; return (a->value > b->value) - (a->value < b->value); } struct array_values *sum_initialize(const int *arr, size_t n) { struct array_values *av = malloc(sizeof(*av) * n); for (size_t i = 0; i < n; i++) { av[i].index = i; av[i].value = arr[i]; } qsort(av, n, sizeof(*av), array_values_compare); return av; } /* get the count of pairs whose sum is sum for subarray arr[start : end] * start index is included, end index is excluded. */ size_t sum_query(struct array_values *av, size_t n, size_t start, size_t end, int sum) { size_t i, j, count = 0; if (n > 0) { for (i = 0; j = n - 1; i < j; i++) { if (av[i].index >= start && av[i].index < end) { while (j > i && av[i].value + av[j].value > sum) { j--; } while (j > i && av[i].value + av[j].value == sum) { if (av[j].index >= start && av[j].index < end) count++; j--; } } } } return count; }
xfb7svmp3#
一种算法,用于找出给定子阵列中和等于确定目标和的对的数量:1.创建一个Map来存储数组中每个数字的频率。1.对于每个元素,检查它是否可以与任何其他元素组合(除了它自己!)以给予所需的总和。相应地增加计数器。
s=set() result=set() for item in a: target=original_target-i if target not in s: s.add(i) else: result.add((i,target)) print(len(result))
在Python中,注解集被实现为哈希表,所以除非加载因子太高,否则搜索将花费O(1)时间。所以总的复杂度是O(n)
0h4hbjxa4#
#include <bits/stdc++.h> using namespace std; vector<vector<int>> pairSum(vector<int> &arr, int s){ int n = arr.size(); vector<vector<int>>pairs; for(int i=0; i<=n;i++) { for(int j=i+1;j<=n;j++) { if((arr[i]+arr[j]) == s) { vector<int> pair = {arr[i], arr[j]}; pairs.push_back(pair); } } } return pairs; }
pnwntuvh5#
一种内存消耗量很大的方法:给定一个长度为n的数组values和一个目标和sum。确定 * 小于 、 等于 * 和 * 大于 * sum/2的元素的计数-如果需要 * 有序 * 对的数量,则可能需要特殊处理 * 等于 * 的元素。对于无序对 * 的索引 *:假设 * 较小 * 不大于 * 较大 *。对于values中不超过sum/2的每个值x,保持一个数据结构,允许确定x在values中出现的次数在给定范围内,例如,长度为n的数组,其计数在给定索引之前。对于每一个查询,将子数组的值x重新排序。累计起点和终点sum - x的计数;如果x等于sum/2,则减去1(这可以在预先计算中考虑)。
values
5条答案
按热度按时间pjngdqdw1#
首先,我们先来讨论一下预计算所有结果,然后让它们更有效地被访问。
预计算所有索引对
<i, j>
,其中a[i] + a[j] = sum
可以在O(n)
中离线执行,其中n
是输入数组a
的大小。然后,您可以将预先计算的对存储在2D空间索引结构中(例如,R树或四叉树)。
然后,子数组查询
(start, end)
对应于2d索引上的范围查询(具有二次框),其中min = (start, start)
和max = (end, end)
。根据查询的范围,这在O(log m)中应该是可能的,其中m是对的总数。
4sup72z82#
不需要为特定的总和构建哈希表:可以在初始步骤中构造散列表,并且对于整个阵列,可以在线性时间内回答对任何
sum
的查询。对于长度为
n
的数组arr
,请执行以下步骤:arr
中具有值arr[i]
的元素的数量。sum
:从0
的total
开始x = arr[i]
集合arr
的每个元素:x * 2 < sum
,得到值为sum - x
的元素的count
,将count * 2
添加到total
。x * 2 == sum
,则获取值为x
的元素的count
,将count + 1
添加到total
arr
的元素对的数目加起来为sum
是total / 2
要回答子数组的查询,上述方法不起作用。当然,你可以总是使用嵌套循环,并在没有额外空间的情况下找到二次时间的计数。
下面是一个针对子阵列和任何给定
sum
的更有效的解决方案:{ index: i, value: arr[i] }
,并按value
字段进行排序:这个初始步骤使用**O(n)额外空间和O(n.log(n))**时间。下面是
int
数组的实现:xfb7svmp3#
一种算法,用于找出给定子阵列中和等于确定目标和的对的数量:
1.创建一个Map来存储数组中每个数字的频率。
1.对于每个元素,检查它是否可以与任何其他元素组合(除了它自己!)以给予所需的总和。相应地增加计数器。
编辑1:这是我的python解决方案。它也可以使用集合来完成。
在Python中,注解集被实现为哈希表,所以除非加载因子太高,否则搜索将花费O(1)时间。所以总的复杂度是O(n)
0h4hbjxa4#
pnwntuvh5#
一种内存消耗量很大的方法:
给定一个长度为
n
的数组values
和一个目标和sum
。确定 * 小于 、 等于 * 和 * 大于 *
sum
/2的元素的计数-如果需要 * 有序 * 对的数量,则可能需要特殊处理 * 等于 * 的元素。对于无序对 * 的索引 *:
假设 * 较小 * 不大于 * 较大 *。
对于
values
中不超过sum
/2的每个值x
,保持一个数据结构,允许确定x
在values
中出现的次数在给定范围内,例如,长度为n
的数组,其计数在给定索引之前。对于每一个查询,将子数组的值
x
重新排序。累计起点和终点
sum - x
的计数;如果x
等于sum
/2,则减去1(这可以在预先计算中考虑)。