对向量中的整数序列求和

时间:2015-01-10 09:43:06

标签: c++ algorithm vector sequences

我有bool exists(int sum, vector<int>& vec)功能 它的作用是返回vec中是否有任何等于sum的数字序列。

e.g

Vec = 140 80 90 180 70 sum = 300

该函数返回true,因为序列140 90 70存在且等于300。

现在我有了代码:

bool possible(int sum, vector<int> &vec)
{
do
{
    int s = 0;
    for (int i = 0; i < vec.size(); i++)
    {
        s += vec.at(i);
        if (s == sum)
        {
            return true;
        }

    }
}while(next_permutation(vec.begin(), vec.end()));

return false;
}

虽然矢量大小只有20,但它的工作时间却很长。

任何人都可以用更好的方法帮助我吗?

3 个答案:

答案 0 :(得分:4)

  

它有效

首先,它不起作用,除非vec被排序开始。否则,next_permutation(...)会产生false而不会耗尽所有可能性,可能会跳过找到正确解法的排列。

  

但即使矢量大小只有20,也需要太长时间。

那是因为这是一个O(N!)解决方案。请注意,即使对于强力解决方案,N!也不必要地高,因为您执行添加的顺序无关紧要。您只需要O(2 N )来尝试所有子集。

通过对0/1 knapsack problem使用伪多项式解,你可以做得更好。我们的想法是创建一组所有可能的总和,直到所需的数字N.用一个数字零开始设置。每次迭代时都会产生另一个集合,其中包含上一次迭代中集合的所有元素,以及通过将列表中的数字添加到前面的每个总和而生成的集合,将值限制在目标数量(即300):< / p>

{ 0 }
{ 0, 140 } -- Added 0+140
{ 0, 80, 140, 220 } -- Added 0+80, 140+80
{ 0, 80, 90, 140, 170, 220, 230 } -- Added 0+90, 80+90, 140+90; 220+90 > 300, so it is not added
... // And so on

在此过程结束时,您将获得集合中所有可能的总和。现在您需要做的就是检查集合中的项目中是否存在目标号码。

答案 1 :(得分:0)

bool possible(int sum, vector<int> &vec)
{
    int s = 0;
    for (int i = 0; i<vec.size(); i++)
    {
      s += vec.at(i);
    }

    if (s==sum)
    return true;
    else
    return false;

}

这会更有效,只需将矢量值加在一起并比较最后的结果。在这种情况下,你不会进行任何排列计算,你也不需要在do ... while循环中有一个for循环。

答案 2 :(得分:0)

我得到了这个有效的代码。

bool possible(int sum, vector<int &vec)
{
    vector<int> previous;
    previous.push_back(0);

    for(auto i = vec.begin(); i != vec.end(); i++)
    {
        vector<int> temp(previous);
        for(auto j = temp.begin();  j != temp.end(); j++)
            *j += *i;
        for(auto k = temp.begin(); k != temp.end(); k++)
        {
            if(*k <= sum)
                previous.push_back(*k);
        }
    }
    sort(previous.begin(),previous.end());
    return binary_search(previous.begin(),previous.end(),sum);
}

谢谢你们。