競技プログラミングでよく現れる回文判定をGoで書きました。数値の場合は計算すると遅いので文字列に変換して比較しましょう。
ソースコード: github.com/ebiiim/palindrome
文字列の場合
元の文字列と逆順に並べ替えた文字列を比較するだけですね。
|
|
stringは読み取り専用のbyteのsliceなので、そのまま逆順にすると1バイト文字以外はおかしくなります。そのため、rune型に変換してから並べ替えます。
数値の場合
すぐに思いつく手法が2種類あります。結論から言うと手法2が速いです。
- 手法1 数値のまま回文判定
- 手法2 文字列に変換して回文判定
手法1 数値のまま回文判定
12345
をイイ感じに計算して54321
にするreverseInt
関数を考えます。
12345
を54321
にするには、桁数を数えてから、次の表のように1桁ずつ計算していきます。
ループ | 見る桁 | 計算結果 |
---|---|---|
初期状態 | 12345 | 00000 |
1 | 12345 | 50000 |
2 | 12345 | 54000 |
3 | 12345 | 54300 |
4 | 12345 | 54320 |
5 | 12345 | 54321 |
|
|
この関数の出力と元の数値を比較すれば、回文数かどうかがわかります。
|
|
手法2 文字列に変換して回文判定
strconv.Itoa
を使うだけです。
|
|
ベンチマーク
手法1は数値の比較なので速そうですが、変換のためにそこそこ計算しています。手法2は文字列に変換してから文字列比較を行います。なるほどわからん。計測します。
結果
桁数を変えながら計測したところ、4桁以上で手法2(文字列に変換して回文判定)が速いです。int64で一番長い19桁だと倍以上の差が出ました。
桁数 | 手法1 | 手法2 |
---|---|---|
3 | 75 ns | 80 ns |
4 | 99 ns | 82 ns |
19 | 586 ns | 222 ns |
考察
一般的に長い桁数を扱うことが多いと思うので手法2でやりましょう。何も考えなくて良いのもアドです。
手法1は私のアルゴリズムがアレなのかもしれません。もっと良い計算方法があったら教えてください。