在C ++和C ++中使用载体的载体。推回( )

时间:2016-07-14 05:31:43

标签: c++ vector

我是C ++的新手,可能会遗漏一些非常基本的东西,但我正在尝试创建一个矢量矢量

#include <iostream>
#include <stack>
#include <string>
#include <map>
#include <vector>
#include <algorithm>


using namespace std;

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs)
    {
        vector<vector<string>> result;
        map<string,vector<string>> myMap;

        if(strs.size() == 0)
        {
            return result;
        }

        for(string s : strs)
        {
            string temp = s;
            sort(temp.begin(),temp.end());
            auto it = myMap.find(temp);
            if(it != myMap.end())
            {
                it->second.push_back(s);
            }
            else
            {
                vector<string> newVector;
                newVector.push_back(s);
                myMap.insert(pair<string,vector<string>>(temp,newVector));
                result.push_back(newVector);
            }
        }
        cout<< myMap["abt"].size() <<endl;
        return result;
    }
};


int main(int argc, const char * argv[])
{
    Solution mySolution;
    vector<string> myStrings {"eat", "tea", "tan", "ate", "nat", "bat"};
    auto result = mySolution.groupAnagrams(myStrings);

    for(vector<string> v: result)
    {
        //cout << v.size() << endl;
        for(string s: v)
        {
            cout << s << " ";
        }
        cout << endl;
    }
    return 0;
}

我期待一个看起来像这样的输出

[
  ["ate", "eat","tea"],
  ["nat","tan"],
  ["bat"]
]

当我尝试在main()中打印矢量矢量时,我将矢量的所有大小都设为1。

当我在地图中打印矢量的大小时,那里的大小看起来还不错。我在这里缺少什么?

更新 -

修正了以下更改

for(string s : strs)
{
    string temp = s;
    sort(temp.begin(),temp.end());
    auto it = myMap.find(temp);
    if(it != myMap.end())
    {
        it->second.push_back(s);
    }
    else
    {
        vector<string> newVector;
        newVector.push_back(s);
        myMap.insert(pair<string,vector<string>>(temp,newVector));
    }
}
for(auto it: myMap)
{
    result.push_back(it.second);
}

我仍然有兴趣知道是否有办法避免在最后通过地图循环并实现我最初打算做的事情?

3 个答案:

答案 0 :(得分:5)

这是这一部分:

{
    vector<string> newVector;
    newVector.push_back(s);
    myMap.insert(pair<string,vector<string>>(temp,newVector));
    result.push_back(newVector);
}

每次result被赋予一个具有一个元素的新向量。地图矢量的更改工作而不是矢量矢量的原因是因为vector::push_back每次都会创建一个副本。

要解决这个问题,有两种方法。

  1. 您可以尝试在地图的同时更新结果,并获取向量以存储对地图副本的一些引用。
  2. 由于您没有将result用于处理步骤,仅针对结果,您可以在完成地图后编译矢量。
  3. 我更喜欢方法#2,因为你永远不会返回地图本身。此外,还有一种从一种容器类型转换到另一种容器类型的艺术,例如this question给出了一些关于所涉及的内容的想法。

答案 1 :(得分:0)

问题在于这部分代码:

vector<string> newVector;
newVector.push_back(s);
myMap.insert(pair<string,vector<string>>(temp,newVector));
result.push_back(newVector);

细分:

vector<string> newVector;

创建一个新的本地临时向量。

newVector.push_back(s);

string的后面为newVector分配空间,并将s复制到其中。

myMap.insert(pair<string,vector<string>>(temp,newVector));

创建一个包含temp副本和newVector副本的std ::对,按原样, 然后为地图中的匹配对分配空间并复制临时对(即再次将字符串和向量复制到其中)。

result.push_back(newVector);

这会在结果的后面为新向量分配空间,并将newVector复制到其中。

resultmyMap此时包含newVector的独立快照。其余代码更新了myMap中的向量,但结果未受影响。

您可以通过不动态构建result来解决此问题,但只有在完成所有工作后才构建它:

    // take a reference to each string in the vector,
    // const indicates it will be immutable
    for(const string& s : strs)
    {
        string temp = s;
        sort(temp.begin(),temp.end());
        std::vector<string>& dest = myMap[temp];
        dest.emplace_back(s);
    }

    cout<< myMap["abt"].size() <<endl;

    for (auto& kv : myMap)  // kv: key value
    {
        // std::move tells 'emplace_back' it can steal the
        // vector's data right out of kv.second.
        result.emplace_back(std::move(kv.second));
    }

此处演示了生成的代码:http://ideone.com/eofloM

#include <iostream>
#include <stack>
#include <string>
#include <map>
#include <vector>
#include <algorithm>


using namespace std;

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs)
    {
        vector<vector<string>> result;
        map<string,vector<string>> myMap;

        if(strs.size() == 0)
        {
            return result;
        }

        for(const string& s : strs)
        {
            string temp = s;
            sort(temp.begin(),temp.end());
            std::vector<string>& dest = myMap[temp];
            dest.emplace_back(s);
        }

        cout<< myMap["abt"].size() <<endl;

        for (auto& kv : myMap)  // kv: key value
        {
            result.emplace_back(std::move(kv.second));
        }

        return result;
    }
};


int main(int argc, const char * argv[])
{
    Solution mySolution;
    vector<string> myStrings {"eat", "tea", "tan", "ate", "nat", "bat"};
    auto result = mySolution.groupAnagrams(myStrings);

    for(vector<string> v: result)
    {
        //cout << v.size() << endl;
        for(string s: v)
        {
            cout << s << " ";
        }
        cout << endl;
    }
    return 0;
}       

答案 2 :(得分:0)

  

我仍然有兴趣知道是否有办法避免在最后通过地图循环并实现我最初打算做的事情?

class Solution {

private:
        vector<vector<string>*> result;
        map<string,vector<string>> myMap;

public:
    vector<vector<string>*> groupAnagrams(vector<string>& strs)
    {
//        vector<vector<string>*> result;
//        map<string,vector<string>> myMap;

只需制作结果并映射该类的成员即可。请参阅更改为矢量指针向量的类型。

        else
        {
            vector<string> newVector;
            newVector.push_back(s);
            auto p = myMap.insert(pair<string,vector<string>>(temp,newVector));

            //p is pair<iterator, bool>
            //where iterator is pointing to the inserted element
            //so p.first->second is the new vector

            result.push_back(&(p.first->second));
        }

请注意,我们在地图中放置了矢量的地址。

for(vector<string>* v: result)
{
    for(string s: *v)
    {
        cout << s << " ";
    }
    cout << endl;
}

迭代向量并考虑指针类型给出结果:

eat tea ate 
tan nat 
bat

这会消除第二个循环并占用更少的空间,但会使代码变得有点复杂。