Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions 49/step1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
Time: 7:07

Time: O(N * M log M)
Space: O(N * M)
*/
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
map<string, vector<string>> sorted_to_str;
for (auto str: strs) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const auto&

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます、こちらのほうが良さそうですね。

string key = str;
sort(key.begin(), key.end());
sorted_to_str[key].push_back(str);
}
vector<vector<string>>grouped_anagrams;
for (auto [key, group]: sorted_to_str) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

こちらも、値のコピーを避けるため const auto& [key, group] としたほうがよいと思います。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほど、ありがとうございます。const auto&を利用すべきときは利用します。

grouped_anagrams.push_back(group);
}
return grouped_anagrams;
}
};
19 changes: 19 additions & 0 deletions 49/step2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
無駄なコピーをなくして空間計算量を改善。
*/
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
map<string, vector<string>> sorted_to_str;
for (auto& str: strs) {
string key = str;
sort(key.begin(), key.end());
sorted_to_str[key].push_back(str);
}
vector<vector<string>>grouped_anagrams;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vector<vector<string>>grouped_anagrams; のあいだにスペースを 1 つ空けることをおすすめいたします。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます、気をつけます。

for (auto& [key, group]: sorted_to_str) {
grouped_anagrams.push_back(move(group));
}
return grouped_anagrams;
}
};
21 changes: 21 additions & 0 deletions 49/step2_2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
sortを利用せずに時間計算量を改善
*/
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
map<vector<int>, vector<string>> sorted_to_str;
for (auto& str: strs) {
vector<int> keys(26);
for (char c : str) {
keys[c - 'a']++;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これ、仮に str に小文字のアルファベットでないものが入っていたら何が起きるでしょうか。
入力の validation はどれくらいするべきだと思いますか。(これはユースケース次第なのでユースケースを適当にでっちあげて考えてみて下さい。)
仮に validate するとしたらどのような動作が望ましいでしょうか。(これもユースケース次第でしょうし唯一の正解があるわけではありません。)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

これ、仮に str に小文字のアルファベットでないものが入っていたら何が起きるでしょうか。

vectorの範囲外の参照でエラーで落ちますね

入力の validation はどれくらいするべきだと思いますか。(これはユースケース次第なのでユースケースを適当にでっちあげて考えてみて下さい。)

各文字列の文字がa-zの範囲内にあることは確認すべきかなと思います。

仮に validate するとしたらどのような動作が望ましいでしょうか。(これもユースケース次第でしょうし唯一の正解があるわけではありません。)

文字のチェックはいくつかやり方あると思いますが一文字ずつループで回してc - 'a'をチェックする、strに正規表現を使うなどが考えられそうです。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.at と [] で振る舞いが違い、[] のほうは未定義動作であるというのはいいですか。
C++ の未定義動作という概念はありますか。

書き方はループでチェックでいいんですが、チェックした結果どう振る舞うのが好ましいですか。
Exception を投げる、プログラムが終了する、特殊な値を返す、単に取り除いた結果を返すなどです。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

未定義動作については知っていました、なるべく発生させるべきでないものという浅い理解でした。

結果に対する振る舞いについては、Exceptionを投げて呼び出し側で対応するのが良いと思います。

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

未定義動作は、何が起きても構わない、ということです。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

未定義動作は絶対避けるように気をつけます。
https://ja.cppreference.com/w/cpp/language/ub

}
sorted_to_str[keys].push_back(str);
}
vector<vector<string>>grouped_anagrams;
for (auto& [key, group]: sorted_to_str) {
grouped_anagrams.push_back(move(group));
}
return grouped_anagrams;
}
};
26 changes: 26 additions & 0 deletions 49/step2_3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
文字列構築にstd::ostringstreamを使う
*/
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
map<string, vector<string>> sorted_to_str;
for (auto& str: strs) {
vector<int> counter(26);
for (char c : str) {
counter[c - 'a']++;
}
std::ostringstream key;
for (auto& count : counter) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intなら参照にする必要はないでしょう。

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ありがとうございます、たしかにこれは不要な&をつけてしまっていました。

key << "#" << to_string(count);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

すいません この"#"ってなんですか??

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

各文字の出現回数を文字列上で区切るためのセパレーターですね。

}

sorted_to_str[key.str()].push_back(str);
}
vector<vector<string>>grouped_anagrams;
for (auto& [key, group]: sorted_to_str) {
grouped_anagrams.push_back(move(group));
}
return grouped_anagrams;
}
};
16 changes: 16 additions & 0 deletions 49/step3.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
class Solution {
public:
vector<vector<string>> groupAnagrams(vector<string>& strs) {
map<string, vector<string>> sorted_to_strings;
for (auto& str : strs) {
string key = str;
sort(key.begin(), key.end());
sorted_to_strings[key].push_back(str);
}
vector<vector<string>> grouped_anagrams;
for (auto& [key, strings] : sorted_to_strings) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modernの書き方だと以下よく見るのでご参考程度に!

transform(begin(sorted_to_strings), end(sorted_to_strings), back_inserter(grouped_anagrams), [](const auto& groups) {
    return groups.second;
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

なるほど、ありがとうございます。参考にします。

grouped_anagrams.push_back(move(strings));
}
return grouped_anagrams;
}
};