2016-07-14 8 views
2

私はどの出力を期待しています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; 
} 

のベクトルを作成しようとしています私がメインでベクトルのベクトルを()私は、マップ内のベクトルの大きさを印刷するとき、私は1

だけでなく、ベクトルの全てのサイズを取得する印刷しようとすると、この

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

のように見えます、サイズlo私には大丈夫です。私はここで何が欠けていますか?

UPDATE - 変更以下

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); 
} 

でそれを修正

私はまだ終わりでマップをループ回避する方法があるかどうかを知って興味があると私は当初意図した何かを達成するであろう何をする?

+1

'for(string s:strs)'は 'strs'のすべての文字列のコピーを作成することに注意してください。 – kfsone

+1

"...最後に地図をループするのを避ける方法がある場合" - 単にベクトル<ベクトルに入るときに間違っている(間違っている)のが簡単であるため、その方向では答えたくない&> 'テリトリー。私自身の使用であっても、参照型のコンテナを渡すことは避けようとします。これは、値を同時に生成して「外側」のスコープに渡すだけでは、不良なメモリ管理の原因になります。あなたはポインタを使うこともできます。なぜそれが危険なのかは明らかです。 –

答えて

5

それはこの部分です:

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

たびresultは一つの要素を持つ新しいベクトル与えられています。ベクトルのベクトルではなくマップのベクトルの動作を変更する理由は、vector::push_backが毎回コピーを作成するためです。


これを解決するには2つの方法があります。

  1. マップと同時に結果を更新し、マップのコピーへの参照を格納するベクターを取得できます。
  2. 処理ステップにはresultを使用しないので、結果のためだけに、マップの終了後にベクトルをコンパイルできます。

マップ自体を返すことは決してないので、方法2の方が優先します。さらに、1つのコンテナタイプから次のコンテナタイプに変換する技術があります。例えば、this questionは、何が関係しているかについてのいくつかのアイデアを示します。

+1

問題を引き起こす部分は、 'it-> second.push_back(s)'行は 'result'ベクトルではなくマップにプッシュするだけです。なぜならそれらは別々のものなのです(newVector ') –

+0

あなたは結果に格納されているマップ&に格納されているベクトルが違うと言っていますか? マップに格納されているベクトル上で更新が行われていますが、結果が異なるベクトルは更新されていません。 – kimi

+0

@ ganta_engineerまさにそうです。マップが更新され、マップに格納されているベクトルを直接変更しています。しかし、結果は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); 

はそれにnewVectorコピーsの背面にstringのためのスペースを割り当てます。

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

TEMPとnewVectorのコピーのコピーを含むペア:: STDを作成する - その後、マップやコピー一時的なペアに一致するペアのための部屋を割り当てているとして、 (すなわちコピーした文字列とベクトル、もう一度)。

result.push_back(newVector); 

これが結果とそこにコピーnewVector背面の新しいベクトルのためのスペースを割り当てます。

resultおよびmyMapには、この時点でnewVectorという独立したスナップショットが含まれています。残りのコードはベクトルをmyMapに更新しますが、結果は変更されません。

// 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; 
}  
0

あなたはその場でresultを構築するが、すべての作業が行われたときにのみ、それを構築していないことにより、この問題を解決することができます

最後にマップをループすることを避け、最初にやろうとしていたことを達成する方法があるのか​​どうか、私はまだ興味がありますか?

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)); 
     } 

ここでは、ベクターのアドレスをマップに配置します。これは、第二のループを離れて取り、より少ないスペースを使用していますが、少し複雑なコードになります

eat tea ate 
tan nat 
bat 

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

ベクトルを反復し、ポインタ型を考慮するには、その結果を提供します。