意味:
回文とは、単語、句、数字、またはその他の一連の単位であり、どちらの方向にも同じものを読むという性質があります。
指定された文字列が回文かどうかを確認するには?
これは少し前の FAIQ [よくあるインタビューの質問] の 1 つですが、ほとんど C を使用しています。
可能なすべての言語で解決策を探しています。
意味:
回文とは、単語、句、数字、またはその他の一連の単位であり、どちらの方向にも同じものを読むという性質があります。
指定された文字列が回文かどうかを確認するには?
これは少し前の FAIQ [よくあるインタビューの質問] の 1 つですが、ほとんど C を使用しています。
可能なすべての言語で解決策を探しています。
PHPサンプル:
$string = "A man, a plan, a canal, Panama";
function is_palindrome($string)
{
$a = strtolower(preg_replace("/[^A-Za-z0-9]/","",$string));
return $a==strrev($a);
}
英数字以外の文字(スペース、コンマ、感嘆符など)を削除して、上記のような完全な文と単純な単語を使用できるようにします。
Windows XP(2000でも動作する可能性があります)以降のBATCHスクリプト:
@echo off
call :is_palindrome %1
if %ERRORLEVEL% == 0 (
echo %1 is a palindrome
) else (
echo %1 is NOT a palindrome
)
exit /B 0
:is_palindrome
set word=%~1
set reverse=
call :reverse_chars "%word%"
set return=1
if "$%word%" == "$%reverse%" (
set return=0
)
exit /B %return%
:reverse_chars
set chars=%~1
set reverse=%chars:~0,1%%reverse%
set chars=%chars:~1%
if "$%chars%" == "$" (
exit /B 0
) else (
call :reverse_chars "%chars%"
)
exit /B 0
言語にとらわれないメタコードなら...
rev = StringReverse(originalString)
return ( rev == originalString );
C#インプレースアルゴリズム。大文字と小文字を区別しない、空白や句読点を削除するなどの前処理は、この関数に渡す前に実行する必要があります。
boolean IsPalindrome(string s) {
for (int i = 0; i < s.Length / 2; i++)
{
if (s[i] != s[s.Length - 1 - i]) return false;
}
return true;
}
編集:ループ状態の不要な " +1
"を削除し、保存された比較を冗長な長さの比較の削除に費やしました。コメント投稿者に感謝します!
C#:LINQ
var str = "a b a";
var test = Enumerable.SequenceEqual(str.ToCharArray(),
str.ToCharArray().Reverse());
Hal の Ruby バージョンをより Ruby スタイルに書き直したもの:
class String
def palindrome?
(test = gsub(/[^A-Za-z]/, '').downcase) == test.reverse
end
end
これで、任意の文字列を呼び出すことができpalindrome?
ます。
Javaソリューション:
public class QuickTest {
public static void main(String[] args) {
check("AmanaplanacanalPanama".toLowerCase());
check("Hello World".toLowerCase());
}
public static void check(String aString) {
System.out.print(aString + ": ");
char[] chars = aString.toCharArray();
for (int i = 0, j = (chars.length - 1); i < (chars.length / 2); i++, j--) {
if (chars[i] != chars[j]) {
System.out.println("Not a palindrome!");
return;
}
}
System.out.println("Found a palindrome!");
}
}
最適化されていない Python:
>>> def is_palindrome(s):
... return s == s[::-1]
優れたデータ構造を使用すると、通常、教授に印象を与えるのに役立ちます。
文字の半分をスタックにプッシュします(長さ/ 2)。
最初の不一致まで各文字をポップして比較します。
スタックの要素がゼロの場合:回文。
※長さが奇数の文字列の場合は、真ん中の文字を捨ててください。
家の中の C. (ここに C の例が必要ないかどうかはわかりません)
bool IsPalindrome(char *s)
{
int i,d;
int length = strlen(s);
char cf, cb;
for(i=0, d=length-1 ; i < length && d >= 0 ; i++ , d--)
{
while(cf= toupper(s[i]), (cf < 'A' || cf >'Z') && i < length-1)i++;
while(cb= toupper(s[d]), (cb < 'A' || cb >'Z') && d > 0 )d--;
if(cf != cb && cf >= 'A' && cf <= 'Z' && cb >= 'A' && cb <='Z')
return false;
}
return true;
}
これは、「racecar」、「Racecar」、「race car」、「racecar」、および「RaCe cAr」に対して true を返します。記号やスペースも含めるように変更するのは簡単ですが、文字だけを数えて大文字と小文字を区別しない方が便利だと思います。これは、ここでの回答で見つけたすべての回文で機能しますが、偽陰性/陽性に騙すことはできませんでした。
また、「C」プログラムで bool が気に入らない場合は、明らかに int を返すことができます。true と false に対してそれぞれ return 1 と return 0 を返します。
これがPythonの方法です。注:これは実際には「pythonic」ではありませんが、アルゴリズムを示しています。
def IsPalindromeString(n):
myLen = len(n)
i = 0
while i <= myLen/2:
if n[i] != n[myLen-1-i]:
return False
i += 1
return True
編集:コメントから:
bool palindrome(std::string const& s)
{
return std::equal(s.begin(), s.end(), s.rbegin());
}
C++の方法。
エレガントなイテレータを使用した私の素朴な実装。実際には、フォワードイテレータがストリングの中間点を超えたら、おそらくチェックして停止します。
#include <string>
#include <iostream>
using namespace std;
bool palindrome(string foo)
{
string::iterator front;
string::reverse_iterator back;
bool is_palindrome = true;
for(front = foo.begin(), back = foo.rbegin();
is_palindrome && front!= foo.end() && back != foo.rend();
++front, ++back
)
{
if(*front != *back)
is_palindrome = false;
}
return is_palindrome;
}
int main()
{
string a = "hi there", b = "laval";
cout << "String a: \"" << a << "\" is " << ((palindrome(a))? "" : "not ") << "a palindrome." <<endl;
cout << "String b: \"" << b << "\" is " << ((palindrome(b))? "" : "not ") << "a palindrome." <<endl;
}
ここで間違った答えがたくさん見られます。正しい解決策では、空白と句読点 (および実際にはアルファベット以外の文字) を無視する必要があり、大文字と小文字を区別しない必要があります。
いくつかの良い例のテスト ケースは次のとおりです。
「男、計画、運河、パナマ」
「トヨタはトヨタだ」
「あ」
""
いくつかの非回文と同様に。
C# でのソリューションの例 (注: この設計では、空文字列と null 文字列は回文と見なされます。これが望ましくない場合は、簡単に変更できます):
public static bool IsPalindrome(string palindromeCandidate)
{
if (string.IsNullOrEmpty(palindromeCandidate))
{
return true;
}
Regex nonAlphaChars = new Regex("[^a-z0-9]");
string alphaOnlyCandidate = nonAlphaChars.Replace(palindromeCandidate.ToLower(), "");
if (string.IsNullOrEmpty(alphaOnlyCandidate))
{
return true;
}
int leftIndex = 0;
int rightIndex = alphaOnlyCandidate.Length - 1;
while (rightIndex > leftIndex)
{
if (alphaOnlyCandidate[leftIndex] != alphaOnlyCandidate[rightIndex])
{
return false;
}
leftIndex++;
rightIndex--;
}
return true;
}
Delphi
function IsPalindrome(const s: string): boolean;
var
i, j: integer;
begin
Result := false;
j := Length(s);
for i := 1 to Length(s) div 2 do begin
if s[i] <> s[j] then
Exit;
Dec(j);
end;
Result := true;
end;
boolean isPalindrome(String str1) {
//first strip out punctuation and spaces
String stripped = str1.replaceAll("[^a-zA-Z0-9]", "");
return stripped.equalsIgnoreCase((new StringBuilder(stripped)).reverse().toString());
}
Java バージョン
これが、strrevを使用しない私の解決策です。C#で記述されていますが、文字列の長さ関数を持つすべての言語で機能します。
private static bool Pal(string s) {
for (int i = 0; i < s.Length; i++) {
if (s[i] != s[s.Length - 1 - i]) {
return false;
}
}
return true;
}
std::string a = "god";
std::string b = "lol";
std::cout << (std::string(a.rbegin(), a.rend()) == a) << " "
<< (std::string(b.rbegin(), b.rend()) == b);
function ispalin { [ "$( echo -n $1 | tac -rs . )" = "$1" ]; }
echo "$(ispalin god && echo yes || echo no), $(ispalin lol && echo yes || echo no)"
/* obvious solution */
function ispalin(cand, i) {
for(i=0; i<length(cand)/2; i++)
if(substr(cand, length(cand)-i, 1) != substr(cand, i+1, 1))
return 0;
return 1;
}
/* not so obvious solution. cough cough */
{
orig = $0;
while($0) {
stuff = stuff gensub(/^.*(.)$/, "\\1", 1);
$0 = gensub(/^(.*).$/, "\\1", 1);
}
print (stuff == orig);
}
Haskellでそれを行ういくつかの脳死の方法
ispalin :: [Char] -> Bool
ispalin a = a == (let xi (y:my) = (xi my) ++ [y]; xi [] = [] in \x -> xi x) a
"Just reverse the string and if it is the same as before, it's a palindrome"
難読化された C バージョン:
int IsPalindrome (char *s)
{
char*a,*b,c=0;
for(a=b=s;a<=b;c=(c?c==1?c=(*a&~32)-65>25u?*++a,1:2:c==2?(*--b&~32)-65<26u?3:2:c==3?(*b-65&~32)-(*a-65&~32)?*(b=s=0,a),4:*++a,1:0:*++b?0:1));
return s!=0;
}
これがC#での私の解決策です
static bool isPalindrome(string s)
{
string allowedChars = "abcdefghijklmnopqrstuvwxyz"+
"1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
string compareString = String.Empty;
string rev = string.Empty;
for (int i = 0; i <= s.Length - 1; i++)
{
char c = s[i];
if (allowedChars.IndexOf(c) > -1)
{
compareString += c;
}
}
for (int i = compareString.Length - 1; i >= 0; i--)
{
char c = compareString[i];
rev += c;
}
return rev.Equals(compareString,
StringComparison.CurrentCultureIgnoreCase);
}
これは、さまざまなケース、句読点、および空白を扱う Python バージョンです。
import string
def is_palindrome(palindrome):
letters = palindrome.translate(string.maketrans("",""),
string.whitespace + string.punctuation).lower()
return letters == letters[::-1]
編集:ブレア・コンラッドのきちんとした答えから恥知らずに盗んで、以前のバージョンから少し不器用なリスト処理を削除しました。
class String
def is_palindrome?
letters_only = gsub(/\W/,'').downcase
letters_only == letters_only.reverse
end
end
puts 'abc'.is_palindrome? # => false
puts 'aba'.is_palindrome? # => true
puts "Madam, I'm Adam.".is_palindrome? # => true
このJavaコードは、ブールメソッド内で機能するはずです。
注:文字の前半と後半のみをチェックする必要があります。そうしないと、チェックの量が重複して2倍になります。
private static boolean doPal(String test) {
for(int i = 0; i < test.length() / 2; i++) {
if(test.charAt(i) != test.charAt(test.length() - 1 - i)) {
return false;
}
}
return true;
}
馬鹿げたものから正しいものまで、Smalltalk の 3 つのバージョン。
Smalltalk では、=
は比較演算子です。
isPalindrome: aString
"Dumbest."
^ aString reverse = aString
メッセージ#translateToLowercase
は、文字列を小文字で返します。
isPalindrome: aString
"Case insensitive"
|lowercase|
lowercase := aString translateToLowercase.
^ lowercase reverse = lowercase
また、Smalltalk では、文字列はCollection
フレームワークの一部であり、 message を使用できます#select:thenCollect:
。そのため、最後のバージョンは次のとおりです。
isPalindrome: aString
"Case insensitive and keeping only alphabetic chars
(blanks & punctuation insensitive)."
|lowercaseLetters|
lowercaseLetters := aString
select: [:char | char isAlphabetic]
thenCollect: [:char | char asLowercase].
^ lowercaseLetters reverse = lowercaseLetters
別の C++ のもの。速度とサイズが最適化されています。
bool is_palindrome(const std::string& candidate) {
for(std::string::const_iterator left = candidate.begin(), right = candidate.end(); left < --right ; ++left)
if (*left != *right)
return false;
return true;
}
シンプルな Java ソリューション:
public boolean isPalindrome(String testString) {
StringBuffer sb = new StringBuffer(testString);
String reverseString = sb.reverse().toString();
if(testString.equalsIgnoreCase(reverseString)) {
return true;
else {
return false;
}
}
上記の C++ ソリューションには、いくつかの問題があることに注意してください。
1 つの解決策は、半分の文字のみを比較するのではなく、コピーによって std::string を渡し、すべての文字を反復処理したため、非効率的でした。次に、文字列が回文ではないことを発見した場合でも、ループを継続し、「false」を報告する前にループの終了を待ちました。
もう 1 つは、関数が非常に小さいため、std::string 以外をテストできないという問題がありました。C++ では、アルゴリズムを類似のオブジェクト全体に拡張するのは簡単です。その std::string を "T" にテンプレート化することにより、std::string、std::wstring、std::vector、および std::deque の両方で機能します。しかし、演算子 < の使用による大幅な変更がなければ、std::list はその範囲外でした。
私自身のソリューションは、C++ ソリューションが正確な現在の型で動作することをやめないことを示そうとしていますが、型に関係なく同じように動作するものは何でも動作するように努めます。たとえば、std::string、int のベクトル、または "Anything" のリストに回文テストを適用できますが、演算子 = (組み込みの型とクラス) を介して Anything が比較可能である場合に限ります。
テンプレートは、データの比較に使用できるオプションのタイプで拡張することもできることに注意してください。たとえば、大文字と小文字を区別せずに比較したい場合や、似たような文字 (è、é、ë、ê、e など) を比較したい場合などです。
レオニダス王が言ったように:「テンプレート?これはC ++です!!!」
したがって、C++ では、少なくとも 3 つの主要な方法があり、それぞれが他の方法につながります。
問題は、C++0X まで、文字の std::string 配列を連続していると見なすことができないため、c_str() プロパティを「チート」して取得する必要があることです。読み取り専用で使用しているので、問題ないはずです...
bool isPalindromeA(const std::string & p_strText)
{
if(p_strText.length() < 2) return true ;
const char * pStart = p_strText.c_str() ;
const char * pEnd = pStart + p_strText.length() - 1 ;
for(; pStart < pEnd; ++pStart, --pEnd)
{
if(*pStart != *pEnd)
{
return false ;
}
}
return true ;
}
ここで、同じ解決策を適用しようとしますが、演算子 [] を介してアイテムにランダム アクセスする任意の C++ コンテナーに適用します。たとえば、任意の std::basic_string、std::vector、std::deque などです。演算子 [] はこれらのコンテナーへの一定のアクセスであるため、過度に速度が低下することはありません。
template <typename T>
bool isPalindromeB(const T & p_aText)
{
if(p_aText.empty()) return true ;
typename T::size_type iStart = 0 ;
typename T::size_type iEnd = p_aText.size() - 1 ;
for(; iStart < iEnd; ++iStart, --iEnd)
{
if(p_aText[iStart] != p_aText[iEnd])
{
return false ;
}
}
return true ;
}
これは、双方向イテレータを持つほぼすべての順序付けられていない STL のようなコンテナで動作します。次の条件を持つコンテナのようなコンテナ: 1 - T は双方向イテレータを持つコンテナです 2 - T のイテレータは同等の型を指します (演算子 = を介して)
template <typename T>
bool isPalindromeC(const T & p_aText)
{
if(p_aText.empty()) return true ;
typename T::const_iterator pStart = p_aText.begin() ;
typename T::const_iterator pEnd = p_aText.end() ;
--pEnd ;
while(true)
{
if(*pStart != *pEnd)
{
return false ;
}
if((pStart == pEnd) || (++pStart == pEnd))
{
return true ;
}
--pEnd ;
}
}
舌足らずの発音:
(defun palindrome(x) (string= x (reverse x)))
Python:
if s == s[::-1]: return True
Java:
if (s.Equals(s.Reverse())) { return true; }
PHP:
if (s == strrev(s)) return true;
Perl:
if (s == reverse(s)) { return true; }
Erlang:
string:equal(S, lists:reverse(S)).
JavaScriptを使用した解決策はまだありませんか?
function palindrome(s) {
var l = 0, r = s.length - 1;
while (l < r) if (s.charAt(left++) !== s.charAt(r--)) return false;
return true
}
それを行うための多くの方法。重要なのは、可能な限り最も効率的な方法で(文字列をループせずに)実行することだと思います。私はそれを(C#を使用して)簡単に逆にすることができるchar配列として行います。
string mystring = "abracadabra";
char[] str = mystring.ToCharArray();
Array.Reverse(str);
string revstring = new string(str);
if (mystring.equals(revstring))
{
Console.WriteLine("String is a Palindrome");
}
Perl:
sub is_palindrome {
my $s = lc shift; # normalize case
$s =~ s/\W//g; # strip non-word characters
return $s eq reverse $s;
}
c ++:
bool is_palindrome(const string &s)
{
return equal( s.begin(), s.begin()+s.length()/2, s.rbegin());
}
Perl:
sub is_palindrome($)
{
$s = lc(shift); # ignore case
$s =~ s/\W+//g; # consider only letters, digits, and '_'
$s eq reverse $s;
}
大文字と小文字を無視し、英数字以外の文字を削除します(ロケールおよびUnicodeニュートラル)。
私はプログラミングの挑戦のためにこれをしなければなりませんでした、これが私のHaskellのスニペットです:
isPalindrome :: String -> Bool
isPalindrome n = (n == reverse n)
私の2c。文字列の性質が決定されるとすぐに戻るショートサーキットを利用して、毎回完全な文字列反転のオーバーヘッドを回避します。はい、最初に文字列を調整する必要がありますが、IMO は別の関数の仕事です。
C# の場合
/// <summary>
/// Tests if a string is a palindrome
/// </summary>
public static bool IsPalindrome(this String str)
{
if (str.Length == 0) return false;
int index = 0;
while (index < str.Length / 2)
if (str[index] != str[str.Length - ++index]) return false;
return true;
}
シンプルなJavaScriptソリューション。デモ用のコード スニペットを実行します。
function checkPalindrome(line){
reverse_line=line.split("").reverse().join("");
return line==reverse_line;
}
alert("checkPalindrome(radar): "+checkPalindrome("radar"));
アーランはすごい
palindrome(L) -> palindrome(L,[]).
palindrome([],_) -> false;
palindrome([_|[]],[]) -> true;
palindrome([_|L],L) -> true;
palindrome(L,L) -> true;
palindrome([H|T], Acc) -> palindrome(T, [H|Acc]).
Java を使用し、Apache Commons String Utils を使用:
public boolean isPalindrome(String phrase) {
phrase = phrase.toLowerCase().replaceAll("[^a-z]", "");
return StringUtils.reverse(phrase).equals(phrase);
}
Ruby では、小文字に変換し、アルファベット以外のすべてを削除します。
def isPalindrome( string )
( test = string.downcase.gsub( /[^a-z]/, '' ) ) == test.reverse
end
しかし、それは不正行為のように感じますよね?ポインターも何もありません!ここに C バージョンもありますが、小文字と文字の除去の良さはありません。
#include <stdio.h>
int isPalindrome( char * string )
{
char * i = string;
char * p = string;
while ( *++i ); while ( i > p && *p++ == *--i );
return i <= p && *i++ == *--p;
}
int main( int argc, char **argv )
{
if ( argc != 2 )
{
fprintf( stderr, "Usage: %s <word>\n", argv[0] );
return -1;
}
fprintf( stdout, "%s\n", isPalindrome( argv[1] ) ? "yes" : "no" );
return 0;
}
うーん、楽しかったです。
プロローグ
palindrome(B, R) :-
palindrome(B, R, []).
palindrome([], R, R).
palindrome([X|B], [X|R], T) :-
palindrome(B, R, [X|T]).
数字や簡単な単語を探しているなら、多くの正解があります。
ただし、一般的に書記言語で回文と見なされるもの(たとえば、「犬、パニック、塔の中!」)を探している場合、正しい答えは、文の両端から繰り返してスキップすることです。英数字以外の文字を個別に指定し、不一致が見つかった場合はfalseを返します。
i = 0; j = length-1;
while( true ) {
while( i < j && !is_alphanumeric( str[i] ) ) i++;
while( i < j && !is_alphanumeric( str[j] ) ) j--;
if( i >= j ) return true;
if( tolower(string[i]) != tolower(string[j]) ) return false;
i++; j--;
}
もちろん、無効な文字を取り除き、結果の文字列を逆にして、元の文字列と比較することもできます。それはあなたが取り組んでいる言語の種類に帰着します。
Delphiからのもう1つは、提出された他のDelphiの例よりも少し厳密だと思います。これは簡単にゴルフの試合になりますが、私は私のものを読みやすくしようとしました。
Edit0:パフォーマンス特性に興味があったので、少しテストしました。私のマシンでは、この関数を60文字の文字列に対して5,000万回実行し、5秒かかりました。
function TForm1.IsPalindrome(txt: string): boolean;
var
i, halfway, len : integer;
begin
Result := True;
len := Length(txt);
{
special cases:
an empty string is *never* a palindrome
a 1-character string is *always* a palindrome
}
case len of
0 : Result := False;
1 : Result := True;
else begin
halfway := Round((len/2) - (1/2)); //if odd, round down to get 1/2way pt
//scan half of our string, make sure it is mirrored on the other half
for i := 1 to halfway do begin
if txt[i] <> txt[len-(i-1)] then begin
Result := False;
Break;
end; //if we found a non-mirrored character
end; //for 1st half of string
end; //else not a special case
end; //case
end;
そして、これはC#でも同じことですが、複数の出口点を残している点が異なりますが、これは気に入らないものです。
private bool IsPalindrome(string txt) {
int len = txt.Length;
/*
Special cases:
An empty string is *never* a palindrome
A 1-character string is *always* a palindrome
*/
switch (len) {
case 0: return false;
case 1: return true;
} //switch
int halfway = (len / 2);
//scan half of our string, make sure it is mirrored on the other half
for (int i = 0; i < halfway; ++i) {
if (txt.Substring(i,1) != txt.Substring(len - i - 1,1)) {
return false;
} //if
} //for
return true;
}
ここにさらに2つのPerlバージョンがあり、どちらも。を使用していませんreverse
。どちらも、文字列の最初の文字を最後の文字と比較し、それらを破棄してテストを繰り返すという基本的なアルゴリズムを使用しますが、個々の文字を取得するためのさまざまな方法を使用します(最初の文字は正規表現で一度に1つずつ剥がします。 2番目split
は文字列を文字の配列に変換します)。
#!/usr/bin/perl
my @strings = ("A man, a plan, a canal, Panama.", "A Toyota's a Toyota.",
"A", "", "As well as some non-palindromes.");
for my $string (@strings) {
print is_palindrome($string) ? "'$string' is a palindrome (1)\n"
: "'$string' is not a palindrome (1)\n";
print is_palindrome2($string) ? "'$string' is a palindrome (2)\n"
: "'$string' is not a palindrome (2)\n";
}
sub is_palindrome {
my $str = lc shift;
$str =~ tr/a-z//cd;
while ($str =~ s/^(.)(.*)(.)$/\2/) {
return unless $1 eq $3;
}
return 1;
}
sub is_palindrome2 {
my $str = lc shift;
$str =~ tr/a-z//cd;
my @chars = split '', $str;
while (@chars && shift @chars eq pop @chars) {};
return scalar @chars <= 1;
}
Scala
def pal(s:String) = Symbol(s) equals Symbol(s.reverse)
ここでは、回文が文字単位だけでなく単語単位にも基づく可能性があることを考慮した単一の解決策はありません。
つまり、与えられた解決策のいずれも、「女の子、ビキニを浴びている、男の子を狙っている、男の子がビキニを浴びている女の子を見ている」のような回文には当てはまりません。
これがC#でハッキングされたバージョンです。正規表現は必要ないと思いますが、上記のビキニ回文でも「男、計画、運河-パナマ!」と同じように機能します。
static bool IsPalindrome(string text)
{
bool isPalindrome = IsCharacterPalindrome(text);
if (!isPalindrome)
{
isPalindrome = IsPhrasePalindrome(text);
}
return isPalindrome;
}
static bool IsCharacterPalindrome(string text)
{
String clean = Regex.Replace(text.ToLower(), "[^A-z0-9]", String.Empty, RegexOptions.Compiled);
bool isPalindrome = false;
if (!String.IsNullOrEmpty(clean) && clean.Length > 1)
{
isPalindrome = true;
for (int i = 0, count = clean.Length / 2 + 1; i < count; i++)
{
if (clean[i] != clean[clean.Length - 1 - i])
{
isPalindrome = false; break;
}
}
}
return isPalindrome;
}
static bool IsPhrasePalindrome(string text)
{
bool isPalindrome = false;
String clean = Regex.Replace(text.ToLower(), @"[^A-z0-9\s]", " ", RegexOptions.Compiled).Trim();
String[] words = Regex.Split(clean, @"\s+");
if (words.Length > 1)
{
isPalindrome = true;
for (int i = 0, count = words.Length / 2 + 1; i < count; i++)
{
if (words[i] != words[words.Length - 1 - i])
{
isPalindrome = false; break;
}
}
}
return isPalindrome;
}
set l = index of left most character in word
set r = index of right most character in word
loop while(l < r)
begin
if letter at l does not equal letter at r
word is not palindrome
else
increase l and decrease r
end
word is palindrome
public static boolean isPalindrome( String str ) {
int count = str.length() ;
int i, j = count - 1 ;
for ( i = 0 ; i < count ; i++ ) {
if ( str.charAt(i) != str.charAt(j) ) return false ;
if ( i == j ) return true ;
j-- ;
}
return true ;
}
C# バージョン:
MyString が char[] であると想定します。文字列の検証後にメソッドが返されます。スペースと <,> は無視されますが、これを拡張してさらに無視することができます。おそらく、無視リストの正規表現一致を実装します。
public bool IsPalindrome()
if (MyString.Length == 0)
return false;
int len = MyString.Length - 1;
int first = 0;
int second = 0;
for (int i = 0, j = len; i <= len / 2; i++, j--)
{
while (i<j && MyString[i] == ' ' || MyString[i] == ',')
i++;
while(j>i && MyString[j] == ' ' || MyString[j] == ',')
j--;
if ((i == len / 2) && (i == j))
return true;
first = MyString[i] >= 97 && MyString[i] <= 122 ? MyString[i] - 32 : MyString[i];
second = MyString[j] >= 97 && MyString[j] <= 122 ? MyString[j] - 32 : MyString[j];
if (first != second)
return false;
}
return true;
}
クイック テスト ケース
負 1. ABCDA 2. AB CBAG 3. A#$BDA 4. NULL/EMPTY
ポジティブ 1. ABCBA 2. A, man a plan a canal,,Panama 3. ABC BA 4. M 5. ACCB
考え/エラーを教えてください。
Java API と追加ストレージを使用できる場合:
public static final boolean isPalindromeWithAdditionalStorage(String string) {
String reversed = new StringBuilder(string).reverse().toString();
return string.equals(reversed);
}
Java のインプレース メソッドが必要になる場合があります。
public static final boolean isPalindromeInPlace(String string) {
char[] array = string.toCharArray();
int length = array.length-1;
int half = Math.round(array.length/2);
char a,b;
for (int i=length; i>=half; i--) {
a = array[length-i];
b = array[i];
if (a != b) return false;
}
return true;
}
public class palindrome {
public static void main(String[] args) {
StringBuffer strBuf1 = new StringBuffer("malayalam");
StringBuffer strBuf2 = new StringBuffer("malayalam");
strBuf2.reverse();
System.out.println(strBuf2);
System.out.println((strBuf1.toString()).equals(strBuf2.toString()));
if ((strBuf1.toString()).equals(strBuf2.toString()))
System.out.println("palindrome");
else
System.out.println("not a palindrome");
}
}
//Single program for Both String or Integer to check palindrome
//In java with out using string functions like reverse and equals method also and display matching characters also
package com.practice;
import java.util.Scanner;
public class Pallindrome {
public static void main(String args[]) {
Scanner sc=new Scanner(System.in);
int i=0,j=0,k,count=0;
String input,temp;
System.out.println("Enter the String or Integer");
input=sc.nextLine();
temp=input;
k=temp.length()-1;
for(i=0;i<=input.length()-1;i++) {
if(input.charAt(j)==temp.charAt(k)) {
count++;
}
//For matching characters
j++;
k--;
}
System.out.println("Matching Characters = "+count);
if(count==input.length()) {
System.out.println("It's a pallindrome");
}
else {
System.out.println("It's not a pallindrome");
}
}
}
public bool IsPalindrome(string s)
{
string formattedString = s.Replace(" ", string.Empty).ToLower();
for (int i = 0; i < formattedString.Length / 2; i++)
{
if (formattedString[i] != formattedString[formattedString.Length - 1 - i])
return false;
}
return true;
}
この方法は、「私が見たのはネズミでしたか」のようなおとり捜査に有効です。しかし、正規表現を通じて特殊文字を排除する必要があると感じています。
このPHPの例はどうですか:
function noitcnuf( $returnstrrevverrtsnruter, $functionnoitcnuf) {
$returnstrrev = "returnstrrevverrtsnruter";
$verrtsnruter = $functionnoitcnuf;
return (strrev ($verrtsnruter) == $functionnoitcnuf) ;
}
これは、サンプル サーバー コントロールを実行するときに使用した C# 用の別のものです。ASP.NET 3.5 Step by Step (MS Press) という本に記載されています。1 つは非英数字を削除する方法で、もう 1 つは回文をチェックする方法です。
protected string StripNonAlphanumerics(string str)
{
string strStripped = (String)str.Clone();
if (str != null)
{
char[] rgc = strStripped.ToCharArray();
int i = 0;
foreach (char c in rgc)
{
if (char.IsLetterOrDigit(c))
{
i++;
}
else
{
strStripped = strStripped.Remove(i, 1);
}
}
}
return strStripped;
}
protected bool CheckForPalindrome()
{
if (this.Text != null)
{
String strControlText = this.Text;
String strTextToUpper = null;
strTextToUpper = Text.ToUpper();
strControlText =
this.StripNonAlphanumerics(strTextToUpper);
char[] rgcReverse = strControlText.ToCharArray();
Array.Reverse(rgcReverse);
String strReverse = new string(rgcReverse);
if (strControlText == strReverse)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
Const-correct C/C++ ポインター ソリューション。ループ内の最小限の操作。
int IsPalindrome (const char *str)
{
const unsigned len = strlen(str);
const char *end = &str[len-1];
while (str < end)
if (*str++ != *end--)
return 0;
return 1;
}
const
英数字以外の文字 (空白や句読点など) を無視するプレーン Cの、大文字と小文字を区別しない、フレンドリーなバージョン。したがって、「男、計画、運河、パナマ」のような古典を実際に伝えます。
int ispalin(const char *b)
{
const char *e = b;
while (*++e);
while (--e >= b)
{
if (isalnum(*e))
{
while (*b && !isalnum(*b)) ++b;
if (toupper(*b++) != toupper(*e)) return 0;
}
}
return 1;
}
通常のアプローチ:
flag = True // Assume palindrome is true
for i from 0 to n/2
{ compare element[i] and element[n-i-1] // 0 to n-1
if not equal set flag = False
break }
return flag
XORを使用するが、同じ複雑さの
XOR アプローチを持つ、より優れたマシン最適化方法があります。
n = length of string
mid_element = element[n/2 +1]
for i from 0 to n
{ t_xor = element[i] xor element[i+1] }
if n is odd compare mid_element and t_xor
else check t_xor is zero
public static boolean isPalindrome(String str) {
return str.equals(new StringBuilder(str).reverse().toString());
}
1.5 より前のバージョンの Java の場合、
public static boolean isPalindrome(String str) {
return str.equals(new StringBuffer().append(str).reverse().toString());
}
また
public static boolean istPalindrom(char[] word){
int i1 = 0;
int i2 = word.length - 1;
while (i2 > i1) {
if (word[i1] != word[i2]) {
return false;
}
++i1;
--i2;
}
return true;
}
C#3 - 最初から数えた char が最後に対応する文字と一致しない場合、これはすぐに false を返します。
static bool IsPalindrome(this string input)
{
char[] letters = input.ToUpper().ToCharArray();
int i = 0;
while( i < letters.Length / 2 )
if( letters[i] != letters[letters.Length - ++i] )
return false;
return true;
}
boolean IsPalindrome(string s) {
return s = s.Reverse();
}
効率的な C++ バージョン:
template< typename Iterator >
bool is_palindrome( Iterator first, Iterator last, std::locale const& loc = std::locale("") )
{
if ( first == last )
return true;
for( --last; first < last; ++first, --last )
{
while( ! std::isalnum( *first, loc ) && first < last )
++first;
while( ! std::isalnum( *last, loc ) && first < last )
--last;
if ( std::tolower( *first, loc ) != std::tolower( *last, loc ) )
return false;
}
return true;
}
AZ または az の間に収まらない文字を取り除くソリューションは、非常に英語中心です。à や é などの分音記号を含む文字は削除されます。
ウィキペディアによると:
分音符号の扱いはさまざまです。チェコ語やスペイン語などの言語では、分音符号またはアクセント記号 (チルダを除く) を含む文字は、アルファベット内の別の場所に割り当てられないため、繰り返される文字に装飾があるかどうかにかかわらず、回文が保持されます。ただし、スウェーデン語やその他の北欧言語では、A とリング (å) の付いた A は別個の文字であり、真の回文と見なされるには正確に鏡像化する必要があります。
したがって、他の多くの言語をカバーするには、照合を使用して分音記号を同等の非分音記号に変換するか、必要に応じてそのままにしてから、比較する前に空白と句読点のみを削除することをお勧めします。
これで問題ありませんが、アルゴリズムを改善する方法はありますか? 私はあるインタビューで、線形時間と一定空間の回文を認識するように求められました。
あの時は何も考えられなかったし、今も考えられない。
(それが役に立ったら、私はインタビュアーに答えを尋ねました.彼は、その文字列が回文である場合にのみ、特定の文字列を同じ値にハッシュするようなハッシュ関数のペアを構築できると言いました.私には方法がわかりません.実際には、この関数のペアを作成します。)
スタックを持つ Java。
public class StackPalindrome {
public boolean isPalindrome(String s) throws OverFlowException,EmptyStackException{
boolean isPal=false;
String pal="";
char letter;
if (s==" ")
return true;
else{
s=s.toLowerCase();
for(int i=0;i<s.length();i++){
letter=s.charAt(i);
char[] alphabet={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
for(int j=0; j<alphabet.length;j++){
/*removing punctuations*/
if ((String.valueOf(letter)).equals(String.valueOf(alphabet[j]))){
pal +=letter;
}
}
}
int len=pal.length();
char[] palArray=new char[len];
for(int r=0;r<len;r++){
palArray[r]=pal.charAt(r);
}
ArrayStack palStack=new ArrayStack(len);
for(int k=0;k<palArray.length;k++){
palStack.push(palArray[k]);
}
for (int i=0;i<len;i++){
if ((palStack.topAndpop()).equals(palArray[i]))
isPal=true;
else
isPal=false;
}
return isPal;
}
}
public static void main (String args[]) throws EmptyStackException,OverFlowException{
StackPalindrome s=new StackPalindrome();
System.out.println(s.isPalindrome("“Ma,” Jerome raps pot top, “Spare more jam!”"));
}
私はまだ再帰を見たことがないので、ここに行きます...
import re
r = re.compile("[^0-9a-zA-Z]")
def is_pal(s):
def inner_pal(s):
if len(s) == 0:
return True
elif s[0] == s[-1]:
return inner_pal(s[1:-1])
else:
return False
r = re.compile("[^0-9a-zA-Z]")
return inner_pal(r.sub("", s).lower())
// JavaScript Version.
function isPalindrome(str) {
str = str.replace(/[^a-zA-Z]/g, '')
return str.split('').reverse().join('').toUpperCase() === str.toUpperCase()
}
基本クラス ライブラリのみを使用する C# の簡易モード
編集:誰かが Array.Reverse も行ったのを見た
public bool IsPalindrome(string s)
{
if (String.IsNullOrEmpty(s))
{
return false;
}
else
{
char[] t = s.ToCharArray();
Array.Reverse(t);
string u = new string(t);
if (s.ToLower() == u.ToLower())
{
return true;
}
}
return false;
}