diff --git a/6/6.md b/6/6.md new file mode 100644 index 0000000..4f22841 --- /dev/null +++ b/6/6.md @@ -0,0 +1,158 @@ +## 何も見ずに解いてみる + +```cpp +class Solution { +public: + string convert(string s, int numRows) { + if (numRows == 1) { + return s; + } + vector strings_by_line(numRows); + int pos = 0; + int dir = 1; + for (char c : s) { + strings_by_line[pos].push_back(c); + if (pos == 0) { + dir = 1; + } + if (pos == numRows - 1) { + dir = -1; + } + pos += dir; + } + return accumulate(strings_by_line.begin(), strings_by_line.end(), string()); + } +}; +``` + +## 他の人のコードを見てみる + +https://github.com/tokuhirat/LeetCode/pull/60/files +https://github.com/ryosuketc/leetcode_arai60/pull/60/files +https://github.com/Ryotaro25/leetcode_first60/pull/66/files +https://github.com/philip82148/leetcode-swejp/pull/5/files + +https://cpprefjp.github.io/reference/numeric/reduce.html +https://cpprefjp.github.io/reference/numeric/accumulate.html +今回の場合はaccumulateの方が良さそう。 + +https://www.geeksforgeeks.org/cpp/stl-ropes-in-c/ +ropeという不思議なデータ構造があるらしい。 + +indexを直接求める方式のコードも書いてみた。 + +```cpp +class Solution { +public: + string convert(string s, int numRows) { + if (numRows == 1) { + return s; + } + string result; + int cycle_length = (numRows - 1) * 2; + for (int row = 0; row < numRows; ++row) { + for (int cycle_start = 0; cycle_start < s.size(); cycle_start += cycle_length) { + int first_index = cycle_start + row; + if (first_index < s.size()) { + result.push_back(s[first_index]); + } + if (row == 0 || row == numRows - 1) { + continue; + } + int second_index = cycle_start + cycle_length - row; + if (second_index < s.size()) { + result.push_back(s[second_index]); + } + } + } + return result; + } +}; +``` + +goto文なるものを使って書いてみたバージョン +https://en.cppreference.com/w/cpp/language/goto.html +(ちなみにこのコード上のやつに比べて結構遅かったです、おそらくvectorの中をfor文でいちいち回してるせい?) + +```cpp +class Solution { +public: + string convert(string s, int numRows) { + if (numRows == 1) { + return s; + } + string result; + int cycle_length = (numRows - 1) * 2; + for (int row = 0; row < numRows; ++row) { + vector indexes = {row}; + if (row != 0 && row != numRows - 1) { + indexes.push_back(cycle_length - row); + } + while (true) { + for (int& index : indexes) { + if (index < s.size()) { + result.push_back(s[index]); + index += cycle_length; + } else { + goto next_row; + } + } + } + next_row: ; + } + return result; + } +}; +``` + +そういえば最初のコードの最後の部分で、 +```cpp + string result; + for (string str : strings_by_line) { + result.append_range(str); + } + return result; +``` +こういう風にstd::basic_string::append_rangeを使って構築しようとしたら、次のコンパイルエラーが出てできなかった。 +``` +Line 22: Char 20: error: no member named 'append_range' in 'std::basic_string' + 22 | result.append_range(str); + | ~~~~~~ ^ +1 error generated. +``` +append_rangeはc++23から追加されたメソッドとあり、leetcodeは下の画像にあるようにc++23の環境で動いているものと思っていたのですが、なぜなんでしょうか?(わかる方教えてください。。) +image + +## 最終コード + +こっちの方が結構早かったのでこっちにしてみました。 +`numRows <= 0`の挙動は書いているときには考えてなかったですが、見返してみると空文字列を返すようになってるのでいい感じな気がします。 + +```cpp +class Solution { +public: + string convert(string s, int numRows) { + if (numRows == 1) { + return s; + } + string result; + int cycle_length = (numRows - 1) * 2; + for (int row = 0; row < numRows; ++row) { + for (int cycle_start = 0; cycle_start < s.size(); cycle_start += cycle_length) { + int first_index = cycle_start + row; + if (first_index < s.size()) { + result.push_back(s[first_index]); + } + if (row == 0 || row == numRows - 1) { + continue; + } + int second_index = cycle_start + cycle_length - row; + if (second_index < s.size()) { + result.push_back(s[second_index]); + } + } + } + return result; + } +}; +```