これはおそらく Java で最も効率的な実装です。
public static boolean isP(String s) {
char[] chars = s.toCharArray();
for (int i = 0; i < (chars.length / 2); i++) {
if (chars[i] != chars[(chars.length - i - 1)])
return false;
}
return true;
}
利点:
- 違いを一目見ただけで戻ります。
直接 char[] アクセスを使用して、charAt で行われる境界チェックを回避します。
- 文字列全体ではなく、文字列の半分だけを繰り返します。
それは、他のすべての提案されたソリューションと同様に、まだ O(N) です。
非常に大きな文字列の提示されたソリューションの時間を測定しました (ナノ秒単位の時間):
Aran: 32244042
Andreas: 60787894
Paul Tomblin: 18387532
まず、上記の測定はクライアント VMで行われました。したがって、計算i < (chars.length / 2)
は定数としてインライン化されませんでした。-server Vm パラメータを使用すると、より良い結果が得られました。
Aran: 18756295
Andreas: 15048560
Paul Tomblin: 17187100
少し極端にするには:
最初に警告の言葉: 使用/発送する予定のプログラムでこのコードを使用しないでください。
コメントで指摘されているように、隠れたバグが含まれており、Java APIに従わず、エラー処理もありません。これは純粋に、ダーティ トリックによって得られる理論上のパフォーマンスの向上を示すためのものです。
文字列クラスは内部的に防御的なコピーを作成するため、文字列から配列をコピーするときにオーバーヘッドが発生します。
文字列から元の char[] を直接取得すると、文字列でリフレクションと unsave 操作を使用することを犠牲にして、パフォーマンスを少し絞り出すことができます。これにより、さらに 20% のパフォーマンスが得られます。
public static boolean isPReflect(String s) {
char[] chars = null;
try {
final Field f = s.getClass().getDeclaredField("value");
f.setAccessible(true);
chars = (char[]) f.get(s);
}
catch (IllegalAccessException e) {
}
catch (NoSuchFieldException e) {
}
final int lenToMiddle = chars.length / 2;
for (int i = 0; i < lenToMiddle; i++) {
if (chars[i] != chars[(chars.length - i - 1)])
return false;
}
return true;
}
時間:
Aran: 18756295
Andreas1: 15048560
Andreas2: 12094554
Paul Tomblin: 17187100