【问题标题】:returning all combination of index i,j in 2d vector that sum up to desired value返回二维向量中索引 i,j 的所有组合,总和为所需值
【发布时间】:2021-09-05 00:05:14
【问题描述】:

我有一个二维向量v(所有值都是正数,二维矩阵是方阵)和一个给定值k。例如,

v={
   {2,1},
   {3,4}
  }

k = 3

我想查找并存储i, j 的所有这些组合,以便

arr[i] + arr[j] = k, or
arr[i] = k, or
arr[j] = k

例如v[0][0] + v[0][1] = 3v[1][0] = 3。我想将这些对存储在这样的数组中std::vector<std::vector<std::pair<int, int>>>

Sample input:
v={
   {2,1},
   {3,4}
  }

k = 3

Sample output:
{{(0,0),(0,1)}, {(1,0)}}

我工作的各个部分;

#include<iostream>
#include<vector>
int main(){
    using namespace std;
    vector<vector<int>>v={{2,1},{3,4}};
    vector<pair<int,int>>k;
    int size=v.size();
    for(size_t i=0;i<size;i++){
        for(size_t j=0;j<size;j++){
            if(v[i][j]==3){
                k.push_back(make_pair(i,j));
            }     
        }
    }
}

编辑link 了解我认为并尝试以上述方式解决的实际问题。

【问题讨论】:

  • 为什么结果是地图向量?这不是成对的向量吗?
  • 什么是cost?请出示真实代码(minimal reproducible example)并在问题中包含错误信息
  • 是的,先生,配对会更好。
  • @463035818_is_not_a_number 哦,抱歉,cost 是另一个向量的名称,我将名称更改为 v,现在编辑相同
  • 在你写的文本中“......将所有地图(i,j)存储到vector&lt;vector&lt;map(int,int)&gt;&gt;”但这不是代码的作用。请包含minimal reproducible example,包括输入、输出和预期输出,或编译器错误消息(如果有)。在您发布的代码中,二维向量是空的,所以这显然不是您用于测试的代码(还有一个 ; 缺失)

标签: c++ algorithm dictionary vector stl


【解决方案1】:

编辑

我给出的第一个答案是考虑可以选择任意数量的元素来形成目标总和。但由于我们最多只能取 2 个,所以这里是一个编辑。

如果两个元素形成目标和,要点是当您输入元素x时,如果我们过去已经输入了y = target - x元素,则将x与@987654324的所有出现配对@。

这是应该很容易理解的代码。

#include <iostream>
#include <vector>
#include <unordered_map>

using namespace std;

typedef pair<int, int> pii;
typedef pair<pii, pii> PIJ;

int main() {
    int N, target;
    cin >> N >> target;

    vector<vector<int>> matrix(N, vector<int>(N));
    unordered_map<int, vector<pii>> M;
    vector<PIJ> res;
    for (int i = 0; i < N; ++i)
        for (int j = 0; j < N; ++j) {
            int x;
            cin >> x;

            matrix[i][j] = x;

            int y = target - x;
            for (const pii& p: M[y])
                res.emplace_back(p, make_pair(i, j));

            M[x].emplace_back(i, j);
        }
    }
}

首先考虑长度为n 的一维问题。最幼稚的算法是形成所有2^n-1 组合,并检查每个组合的元素总和是否等于target

幸运的是,相同的搜索空间可以被另一个遵循最优子结构属性的算法耗尽。让count(i, t) 表示第一个i 元素的组合总数,总和为t。然后count(i, t) = count(i-1, t-arr[i]) + count(i-1, t)。基本条件是t = 0。如果0 可以出现在输入数组中,那么您必须考虑到这一点。会有重叠的子问题需要动态规划。

保持一个正在运行的数组chosen 并且每次选择一个值(调用count(i-1, t-arr[i]) 时),将索引推入chosen,如果达到基本条件,将chosen 的副本推入你的@987654339 @ 大批。当控件返回到您调用count(i-1, t-arr[i]) 的位置时,将这个值从chosen 中弹出。

您的二维问题可以转换为pair&lt;int, int&gt; 的一维数组,并且可以应用相同的算法。

【讨论】:

  • 我猜你提到的一维问题是一个众所周知的子集和问题,当可以采用任何大小的子集来形成和时使用它。但在这里我猜我们最多可以取两个值。只需简单解决 TWO SUM 问题即可找到所有对。对于单个元素,只需计算有多少元素等于给定总和
  • @risingStark 问题已修改多次。当我第一次阅读这个问题时,我也认为我们最多可以取 2 来形成目标总和,但没有特别提到,所以我继续回答这个问题。
【解决方案2】:

您示例中的循环仅在 v{i,j} == k 处找到对 {i,j}。如果您还想包含所有组合 { {i1,j1}, {i2, j2} },那是完全不同的搜索。

您的示例输出 { { (0,0), (0,1) }, { (1,0) } } 的问题在于它们的大小不同。如果它的类型是

std::vector < std::vector < std::pair < int, int > > >

那么对的向量允许有多长?如果v 的所有值都是 1,那么解决方案是否会是 { { (0,0), (0,1), (1,0) }, { (0,0), (0,1), (1,1) }, { (0,0), (1,0), (1,1) }, { (0,1), (1,0), (1,1) }, }

作为@RisingStark cmets,最直接的运行方法是对允许的对数进行迭代。这在 2 之后不再是微不足道的。

2 的一些例子是here。对于子集和问题,有no general efficient solution

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    • 1970-01-01
    • 2012-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-06
    相关资源
    最近更新 更多