在矢量中选择正确的元素

时间:2014-07-03 09:40:21

标签: c++ vector

我尽可能清楚地解释我的问题: 我有两个向量prova1和prova2。在prova1内部有一组int数,即

prova1={0;1;2;4;6;7,8;9;10;11;12;13};

prova2是prova1的一个子集,即

prova2={2;4;6;8;10;12;13};

我的目标是在第三个载体(称为“prova”)中仅复制prova2内的元素序列,这些元素位于prova1和contigous内。 对于上述关于条件的载体,我有两个序列: {2; 4; 6}和{12; 13},实际上这两个序列在​​prova1中没有分离元素。

这是我的代码来解决这个问题:

std::vector<int> prova1 = {0, 1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13};
std::vector<int> prova2 = {2, 4, 6, 8, 10, 12, 13};
std::vector<int> prova;

for (int i=1;i<=prova1.size()-1;i++) {
    for (int j=1;j<=prova2.size()-1;j++) {
        if (prova2[j]==prova1[i]) {
            int variabile=prova2[j-1];
            if (prova1[i-1]==variabile) {
                prova.push_back(prova2[j]);
            }
        }
    }
}

但正如您所看到的那样存在一个问题:

不能包含任何序列的第一个元素

请尝试帮我解决一下。

3 个答案:

答案 0 :(得分:2)

这是一个高效且易于理解的解决方案 - 因为它贯穿v1中的每个元素,它会跟踪它是否不在正在运行的匹配中,只看到可能结果是多元素子序列匹配的第一个元素,或者肯定是在这样的匹配中,并且相应地push_back个元素。

enum { unmatched, once, many } state = unmatched;
for (int i = 0, j = 0; i < v1.size() && j < v2.size(); ++i)
    if (v1[i] == v2[j])
        if (state == unmatched)
        {
            ++j;
            state = once;
        }
        else if (state == once)
        {
            v.push_back(v2[j - 1]);
            v.push_back(v2[j++]);
            state = many;
        }
        else
            v.push_back(v2[j++]);
    else
        state = unmatched;

查看在ideone.com here运行的完整程序,输出:

2
4
6
12
13

更新:这里是如何包含一个哨兵来分隔子序列:

const int sentinel = -1;  // or std::numeric_limit<int>::min or whatever else...

enum { unmatched, once, many } state = unmatched;
for (int i = 0, j = 0; i < v1.size() && j < v2.size(); ++i)
    if (v1[i] == v2[j])
        if (state == unmatched)
        {
            ++j;
            state = once;
        }
        else if (state == once)
        {
            v.push_back(sentinel);
            v.push_back(v2[j - 1]);
            v.push_back(v2[j++]);
            state = many;
        }
        else
            v.push_back(v2[j++]);
    else
        state = unmatched;

然后当你迭代:

for (int i = 0; i < v.size(); ++i)
    if (v[i] == sentinel)
        std::cout << "starting new subsequence!\n";
    else
        std::cout << v[i] << '\n';

更新:捕获评论中要求的索引范围:

enum { unmatched, once, many } state = unmatched;
int j;
for (int i = j = 0; i < v1.size() && j < v2.size(); ++i)
    if (v1[i] == v2[j])
        if (state == unmatched)
        {
            ++j;
            state = once;
        }
        else if (state == once)
        {
            starts_at.push_back(j - 1);
            v.push_back(v2[j - 1]);
            v.push_back(v2[j++]);
            state = many;
        }
        else
            v.push_back(v2[j++]);
    else
    {
        if (state == many)
            finishes_at.push_back(j - 1);
        state = unmatched;
    }
if (state == many)
    finishes_at.push_back(j - 1);

答案 1 :(得分:0)

您只需使用复制功能复制范围即可。您不需要自己迭代向量来执行此操作。浏览std算法并使用它可以轻松完成。

答案 2 :(得分:0)

我来到这个简单的解决方案:

#include <iostream>
#include <vector>

int main()
{
    std::vector<int> sequenceA = {0, 1, 2, 4, 6, 7, 8, 9, 10, 11, 12, 13};
    std::vector<int> sequenceB = {2, 4, 6, 8, 10, 12, 13};
    std::vector<int> result;

    std::stable_sort(sequenceA.begin(), sequenceA.end());
    std::stable_sort(sequenceB.begin(), sequenceB.end());

    int indexA = 0;
    int indexB = 0;
    while (indexA < sequenceA.size() && indexB < sequenceB.size()) {
        const int valueA = sequenceA[indexA];
        const int valueB = sequenceB[indexB];
        if (valueA == valueB) {
            result.push_back(valueA);
            ++indexA;
            ++indexB;
        } else if (valueA < valueB) {
            ++indexA;
        } else {
            ++indexB;
        }
    }

    for (int value : result) {
        std::cout << value << ", ";
    }

    return 0;
}

这是你需要的结果吗?