使用映射查找具有给定和(带有负数)的子数组
Using a map to find subarray with given sum (with negative numbers)
考虑以下问题陈述:
给定一个未排序的整数数组,找出一个与给定数字相加的子数组。如果有多个以sum为给定数值的子数组,则输出其中任意一个。
Examples:
Input: arr[] = {1, 4, 20, 3, 10, 5}, sum = 33
Ouptut: Sum found between indexes 2 and 4
Input: arr[] = {10, 2, -2, -20, 10}, sum = -10
Ouptut: Sum found between indexes 0 to 3
Input: arr[] = {-10, 0, 2, -2, -20, 10}, sum = 20
Ouptut: No subarray with given sum exists
在这个站点上,建议使用以下线性时间解决方案,其中包括使用映射来存储算法遍历数组时当前子集的和:
// Function to print subarray with sum as given sum
void subArraySum(int arr[], int n, int sum)
{
// create an empty map
unordered_map<int, int> map;
// Maintains sum of elements so far
int curr_sum = 0;
for (int i = 0; i < n; i++)
{
// add current element to curr_sum
curr_sum = curr_sum + arr[i];
// if curr_sum is equal to target sum
// we found a subarray starting from index 0
// and ending at index i
if (curr_sum == sum)
{
cout << "Sum found between indexes "
<< 0 << " to " << i << endl;
return;
}
// If curr_sum - sum already exists in map
// we have found a subarray with target sum
if (map.find(curr_sum - sum) != map.end())
{
cout << "Sum found between indexes "
<< map[curr_sum - sum] + 1
<< " to " << i << endl;
return;
}
map[curr_sum] = i;
}
// If we reach here, then no subarray exists
cout << "No subarray with given sum exists";
}
// Driver program to test above function
int main()
{
int arr[] = {10, 2, -2, -20, 10};
int n = sizeof(arr)/sizeof(arr[0]);
int sum = -10;
subArraySum(arr, n, sum);
return 0;
}
对于post中提供的测试用例,检查current_sum - sum是否的第二个if语句永远不会输入。而是在第一个if语句中找到和并打印出来。这里有一些混淆的地方:
1:在地图中查找current_sum-sum
的目的是什么?
2:在什么情况下,甚至需要输入第二个if语句来使用映射来解决问题?
curr_sum = curr_sum + arr[i];
:
curr_sum保存从arr[0]开始的所有条目(不超过arr[i])的和
if (curr_sum == sum)
{
cout << "Sum found between indexes "
<< 0 << " to " << i << endl;
return;
}
:
if条件检查curr_sum是否等于给定的和。记住,curr_sum保存从arr[0]开始的和。
因此,如果结果子数组的索引为2和4,则上述条件是不够的。
Input: arr[] = {1, 4, 20, 3, 10, 5}, sum = 33
Ouptut: Sum found between indexes 2 and 4
在这个例子中,
当I = 4时,curr_sum为38。但是如果你把1和4拿出来(arr[0]和arr[1]是一个子数组),你得到33。
if (map.find(curr_sum - sum) != map.end())
{
cout << "Sum found between indexes "
<< map[curr_sum - sum] + 1
<< " to " << i << endl;
return;
}
map[curr_sum] = i;
上面的代码就是这样做的。
map[curr_sum] = i;
map以子数组sum(索引0和索引i之间的arr之和)作为键存储索引值i。所以对于这个例子,它将是:
- 地图[1]= 0
- 地图[5]= 1
- 地图[25]= 2
- 地图[28]= 3
- 地图[38]= 4
map.find(curr_sum - sum)
搜索映射是否有一个键为(curr_sum - sum)的条目。
在我们的示例中,当i = 4时,curr_sum将为38,而给定的sum将为33。如果我们消去子数组arr[0,2],我们得到33。因此,地图。Find (curr_sum - sum) => map. Find(38-33)是命中的,因为我们有条目map[5] = 1。
希望你明白了
有两种情况:
-
从索引0到
n
的和就是我们要找的数字。cur_sum
是所有指标的运行和,所以只需检查该变量即可。 -
指数
m
到n
的和就是我们要找的数字。如果是这样,那么存在一个m
,使得(从0到n
的和)减去(从0到m
的和)就是我们要找的和。所有这些中间和都存储在映射中,所以这就是为什么我们要寻找cur_sum - sum
——如果这个差对应于某个部分和,那么我们就完成了。第二种情况的一个例子是你的问题中的第一个测试用例-在
{1, 4, 20, 3, 10, 5}
中寻找33。在n==4
,我们有38
的cur_sum
。但是5
在映射中是前两个索引的和。
如果数组中没有负整数,则不需要映射。在这种情况下,你可以只维护一个start变量,从currSum中减去arr[start],并在currSum> sum时将start增加1。
如果数组中可能有负整数,则可以使用带映射的方法。
试试这个例子来理解解决方案:
-5、2、10、20、3、8
sum = 33
答案:索引2到索引4的和
- 哈希映射使用 nullptr c++ 初始化节点的动态数组
- 具有 2 个分量的数组的特征映射到 3 的向量
- 将数组的元素插入映射的时间复杂度是多少?
- 如何初始化字节数组的映射?
- 数组中未映射的内存访问从python传递到c++
- 当 map 是一个整数数组并且由 operator[] 创建时,它是否初始化其映射类型
- 如何为映射和priority_queue编写比较器,其中元素是二维数组
- 特征:将数组映射到矩阵大小未知的矩阵
- 一维数组映射方式的性能差异问题
- 如何在Windows上将BYTE数组映射为FILE *
- 将数组映射回现有特征矩阵
- 如何在将多维 int 数组映射到 C++ 中的字符串时实现在地图上查找或计数
- 从数组映射到整数在C++中无法正常工作
- 安全地将数组映射到类C++
- 将c++数组映射到特征矩阵
- 将二维数组映射到Eigen::Matrix
- 将2D数组映射到CUDA中的RGB到GreyScale程序中的块网格
- 在c++中存储数组映射
- 使用可变模板和类型列表将不透明数组映射到函数参数
- 2D 数组映射与 if 语句 C++