web-dev-qa-db-ja.com

文字列の順列が回文になる可能性があるかどうかを確認します

文字列が回文になるための前提条件を満たしているかどうかをテストするメソッドを記述します。

例えば:

Input    | Output
mmo      | True  
yakak    | True  
travel   | False

私はこのアプローチを考えています:

  1. T $ Reverse(T)#となるように、Tのすべての順列の接尾辞木を作成します。
  2. 同じノードのすべての順列を確認します

私は何かが足りませんか?

7
user5080124

本当にあなたが探しているのは、すべての(または1つを除くすべての)文字がペアになっている場合です。それらがそうである限り、それらは回文に変えることができるでしょう。

だからそれは次のようなものになるでしょう...

bool canBeTurnedIntoAPalindrome(string drome)
{
  // If we've found a letter that has no match, the center letter.
  bool centerUsed = false;
  char center;

  char c;
  int count = 0;

  // TODO: Remove whitespace from the string.

  // Check each letter to see if there's an even number of it.
  for(int i = 0; i<drome.length(); i++)
  {
    c = drome[i];
    count = 0;

    for(int j = 0; j < drome.length(); j++)
      if (drome[j] == c)
         count++;

    // If there was an odd number of those entries
    // and the center is already used, then a palindrome
    // is impossible, so return false.
    if (count % 2 == 1)
    {
      if (centerUsed == true && center != c)
        return false;
      else
      {
        centerused = true;
        center = c;   // This is so when we encounter it again it
                      // doesn't count it as another separate center.
      }
    }
  }
  // If we made it all the way through that loop without returning false, then
  return true;
}

これは最も効率的ではありませんが(すでに数えられている場合でも、文字に出くわす回数だけ数えます)、機能します。

3
Matthew

あなたがする必要があるのは、奇数の出現を持つ最大で1つの文字があることを確認することです。これがJavaの例です:

private static boolean canMakePalindrom(String s) {
    Map<Character, Integer> countChars = new HashMap<>();

    // Count the occurrences of each character
    for (char c : s.toCharArray()) {
        Integer count = countChars.get(c);
        if (count == null) {
            count = Integer.valueOf(1);
        } else {
            count = count + 1;
        }
        countChars.put(c, count);
    }

    boolean hasOdd = false;
    for (int count : countChars.values()) {
        if (count % 2 == 1) {
            if (hasOdd) {
                // Found two chars with odd counts - return false;
                return false;
            } else {
                // Found the first char with odd count
                hasOdd = true;
            }
        }
     }

     // Haven't found more than one char with an odd count
     return true;
}

EDIT4(はい-これらは意味をなすように順序付けられていますが、時系列で番号が付けられています):
上記の実装には、非効率性が組み込まれています。文字列の最初の反復を回避できるとは思いませんが、すべての出現回数をカウントする本当の理由はありません。奇数カウントの出現回数を追跡するだけで十分です。このユースケースでは、遭遇した各文字を追跡し(たとえば、Setを使用)、再び遭遇したときに削除するだけで十分です。文字列内のすべての文字が異なる最悪の場合、パフォーマンスは同等ですが、各文字が複数回出現する一般的な場合、この実装により、2番目のループの時間とメモリの両方の複雑さが改善されます(現在、単一の状態に縮小されています)劇的に:

private static boolean canMakePalindrom(String s) {
    Set<Character> oddChars = new HashSet<>();

    // Go over the characters
    for (char c : s.toCharArray()) {
        // Record the encountered character:
        if (!oddChars.add(c)) {
            // If the char was already encountered, remove it - 
            // this is an even time we encounter it
            oddChars.remove(c);
        }
    }

    // Check the number of characters with odd counts:
    return oddChars.size() <= 1;
}

EDIT3(はい-これらは意味をなすように順序付けられていますが、時系列で番号が付けられています):
Java 8は、以下のPythonワンライナー)のような実装を作成するために使用できる流暢なストリーミングAPIを提供します。

private static boolean canMakePalindrom(String s) {
    return s.chars()
            .boxed()
            .collect(Collectors.groupingBy(Function.identity(),
                                           Collectors.counting()))
            .values()
            .stream()
            .filter(p -> p % 2 == 1)
            .count() <= 1;
}

編集:
Pythonの組み込み関数と理解機能により、これは魅力的すぎて、このワンライナーソリューションを公開できません。前述のJava 1よりもおそらく効率的ではありませんが、非常にエレガントです。

from collections import Counter

def canMakePalindrom(s):
    return len([v for v in Counter(s).values() if v % 2 == 1]) <= 1

EDIT2:
または、コメントで@DSMによって提案されたさらにクリーンなアプローチ:

from collections import Counter

def canMakePalindrom(s):
    return sum(v % 2 == 1 for v in Counter(s).values()) <= 1
18
Mureinik

別のアプローチでは、各文字が出現する回数をカウントする代わりに、文字が奇数回または偶数回発生したかどうかを追跡します。手紙が偶数回出現した場合、それについて心配する必要はなく、セット内の奇妙な出現を追跡するだけで済みます。 Javaの場合:

public static boolean canMakePalindrome(String s) {
    Set<Character> oddLetters = new HashSet<>();
    for ( char c : s.toCharArray() ) {
        if ( ! oddLetters.remove(c) ) {
            oddLetters.add(c);
        }
    }
    return oddLetters.size() <= 1;
}
7
Teepeemm
def can_permutation_palindrome(s):
    counter = {}
    for c in s:
        counter[c] = counter.get(c, 0) + 1
    odd_count = 0
    for count in counter.values():
        odd_count += count % 2
    return odd_count in [0, 1]
3
Jonathan Li

私があなたの質問を正しく理解しているなら、これは私がそれを理解する方法です:

入力文字列を回文に再配置できる場合は「True」を出力し、そうでない場合は「False」を出力します。

次に、次の簡単なルールを使用できます。

  1. 長さが偶数の場合、入力内のすべての一意の文字は2回の倍数で出現する必要があります。
  2. 長さが奇数の場合、1つを除くすべての一意の文字が2回の倍数で出現する必要があります。 1文字のみが許可されますnot 2回の倍数で発生します。

したがって、3つの例について:

「mmo」、奇数の長さ、mは2回(2の倍数)発生し、oは1回(2の倍数ではない)発生するため、True

「yakak」、奇数の長さ、aは2回(2の倍数)、kは2回(2の倍数)、yは1回(2の倍数ではない)発生します、したがってTrue

「旅行」、複数の文字は2の倍数にはなりません。したがって、False

追加の例:

「mmorpg」、mのみが2の倍数で発生し、残りは1回のみ発生するため、False

「mmom」、2の倍数で出現する文字はなく、「2回の倍数ではない」複数の文字が出現するため、False

この時点で、1文字のみが2の倍数以外で出現することが許可されている場合は、長さを無視できることを理解する必要があります。偶数の長さの文字列では、2文字以上が2の倍数以外で出現するか、まったく出現しません。

したがって、最終的なルールは次のようになります。

入力で最大1つの一意の文字が2の倍数以外で出現する場合、出力はTrueです。それ以外の場合、出力はFalseです。

3
def check(string):
    bv = 0
    for s in string:
        bv ^= 1 << ord(s)
    return bv == 0 or bv & (bv - 1) == 0
1
user7135792

今日、以下の解決策に到達しました(python)。読みやすく、パフォーマンス的には本当に良いと思います。

sum(map(lambda x: Word.count(x) % 2, set(Word))) <= 1

基本的に、文字列「Word」内の各文字の出現回数をカウントし、除算の余りを2で取得し、それらすべてを合計して、最大で1つあるかどうかを確認します。

アイデアは、潜在的に1つ(真ん中の文字)を除いて、すべての文字をペアにする必要があるということです。

1
Mawkee

私の考えは、奇数の文字の数が1で、残りがすべて偶数の場合、回文が発生する可能性があるということです。これがPythonでの私のプログラムです。

string = raw_input()

found = False
char_set = set(string) # Lets find unique letters

d_dict = {}
for c in char_set:
    d_dict[c] = string.count(c) # Keep count of each letter

odd_l = [e for e in d_dict.values() if e%2 == 1] # Check how many has odd number of occurrence     
if len(odd_l) >1:
    pass
else:
    found = True



if not found:
    print("NO")
else:
    print("YES")

Java

private static boolean isStringPalindromePermutation(String input) {

    if(input == null) return false;

    if(input.isEmpty()) return false;

    int checker = 0;
    for (int i = 0; i < input.length(); i++) {
        int character = input.charAt(i) - 'a';

        int oneShiftedByNumberInCharacter = 1 << character;

        int summaryAnd = checker & oneShiftedByNumberInCharacter;
        if ( summaryAnd > 0 ) {
            int revertToShiftedByChar = ~oneShiftedByNumberInCharacter;
            checker = checker & revertToShiftedByChar;
        } else {
            checker |= oneShiftedByNumberInCharacter;
        }
    }
    if ( input.length() % 2 == 0 ) {
        if ( checker == 0) {
            return true;
        }
        else return false;
    } else {
        int checkerMinusOne = checker-1;
        if((checkerMinusOne & checker) == 0){
            return true;
        }else{
            return false;
        }
    }

}
0

この質問の迅速な例。

var str = "mmoosl"
extension String {
func count(of needle: Character) -> Int {
    return reduce(0) {
        $1 == needle ? $0 + 1 : $0
    }
}
}



func canBeTurnedIntoAPalinpolyString(_ polyString: String) -> Bool {
var centerUsed = false
var center = Character("a")
for i in polyString {
    let count  = polyString.count(of: i)
    if count == 1 && !centerUsed {
        center = i
        centerUsed = true
    } else {
        if count % 2 != 0 {
            return false
        }
    }
}
 return true
}

print(canBeTurnedIntoAPalinpolyString(str))
0
Aravind Sekar

これが私の解決策です

public static void main(String[] args) {
    List<Character> characters = new ArrayList<>();
    Scanner scanner = new Scanner(System.in);
    String input = scanner.nextLine();
    for (int i = 0; i < input.length(); i++){
        char val = input.charAt(i);
        if (characters.contains(val)){
            characters.remove(characters.indexOf(val));
        } else{
            characters.add(val);
        }
    }
    if (characters.size() == 1 || characters.size() == 0){
        System.out.print("Yes");
    } else{
        System.out.print("No");
    }
}
0
Anand Mishra

質問:ストリングは回文になることができますか?方法1:文字数IN Java:

public class TEST11 {

    public static void main(String[] args) {
        String a = "Protijayi";

        int[] count = new int[256];
        Arrays.fill(count, 0);
        for (int i = 0; i < a.length(); i++) {
            char ch = a.charAt(i);
            count[ch]++;
        } // for
            // counting of odd letters
        int odd = 0;
        for (int i = 0; i < count.length; i++) {
            if ((count[i] & 1) == 1) {
                odd++;
            }

        } // for
        if (odd > 1) {
            System.out.println("no");
        } else {
            System.out.println("yes");
        }

    }

}

Pythonの場合:

def fix (a):
    count = [0] * 256
    for i in a: count[ord(i)] += 1
    # counting of odd characters
    odd = 0 
    for i in range(256): 
        if((count[i] & 1) == 1): odd += 1

    if(odd > 1):print("no")
    else:print("yes")


a = "Protijayi"

fix(a)

方法2:JavaでのHashSetの使用:

public class TEST11 {

    public static void main(String[] args) {

        String a = "Protijayi";
        Set<Character> set = new HashSet<>();
        for (char ch : a.toCharArray()) {

            if (set.contains(ch)) {
                set.remove(ch);
            }
            set.add(ch);
        } // for

        if (set.size() <= 1) {
            System.out.println("yes can be a palindrome");
        } else {
            System.out.println("no");
        }

    }

}
0
Soudipta Dutta

文字列内の文字とスペースの大文字と小文字の区別を気にしない場合、Dictionaryを使用したC#のサンプルソリューションは次のようになります。

    private static bool IsPalindromePermutation(string inputStr)
    {
        // First, check whether input string is null or whitespace.
        // If yes, then return false.
        if (string.IsNullOrWhiteSpace(inputStr))
            return false;

        var inputDict = new Dictionary<char, int>();

        // Big/small letter is not important
        var lowerInputStr = inputStr.ToLower();

        // Fill input dictionary
        // If hit a space, then skip it
        for (var i = 0; i < lowerInputStr.Length; i++)
        {
            if (lowerInputStr[i] != ' ')
            {
                if (inputDict.ContainsKey(lowerInputStr[i]))
                    inputDict[lowerInputStr[i]] += 1;
                else
                    inputDict.Add(lowerInputStr[i], 1);
            }
        }

        var countOdds = 0;
        foreach(var elem in inputDict)
        {
            if(elem.Value % 2 != 0)
                countOdds++;
        }

        return countOdds <= 1;
    }
0
ersegun

最大で1つの文字が奇数である場合にのみ、任意の文字列が回文になる可能性があります。の回数と他のすべての文字は偶数回出現する必要があります。次のプログラムを使用して、回文が文字列であるかどうかを確認できます。

void checkPalindrome(string s)
{
vector<int> vec(256,0);    //Vector for all ASCII characters present.
for(int i=0;i<s.length();++i)
{
    vec[s[i]-'a']++;
}
int odd_count=0,flag=0;
for(int i=0;i<vec.size();++i)
{
    if(vec[i]%2!=0)
        odd_count++;
    if(odd_count>1)
    {
        flag=1;
         cout<<"Can't be palindrome"<<endl;
        break;  
    }
}
if(flag==0)
    cout<<"Yes can be palindrome"<<endl;
}
0

O(n)複雑さ。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PallindromePemutation
{
    class charcount
    {
        public char character { get; set; }
        public int occurences { get; set; }
    }
    class Program
    {
        static void Main(string[] args)
        {

            List<charcount> list = new List<charcount>();
            charcount ch;
            int count = 0;
            char[] arr = "travel".ToCharArray();
            for (int i = 0; i < arr.Length; i++)
            {
                charcount res = list.Find(x => x.character == arr.ElementAt(i));
                if (res == null)
                {
                    ch = new charcount();
                    ch.character = arr.ElementAt(i);
                    ch.occurences = 1;
                    list.Add(ch);
                }
                else
                {
                    charcount temp=  list.Find(x => x.character == arr.ElementAt(i));
                    temp.occurences++;
                }
            }
            foreach (var item in list)
            {
                if (!(item.occurences % 2 == 0))
                {
                    count++;
                }
            }
            if (count > 1)
            {
                Console.WriteLine("false");
            }
            else
            {
                Console.WriteLine("true");
            }
            Console.ReadKey();
        }
    }
}
0
hussain

それが私の解決策です。文字列には、スペースを含む複数の単語を含めることができます。
入力:Tact Coa出力true入力:Tact Coa vvu出力:false

public static boolean checkForPalindrome(String str) {
    String strTrimmed = str.replaceAll(" ","");
    System.out.println(strTrimmed);
    char[] str1 = strTrimmed.toCharArray();

    for (int i = 0; i < str1.length; i++) {
        str1[i] = Character.toLowerCase(str1[i]);
    }

    Arrays.sort(str1);
    String result = new String(str1);
    System.out.println(result);
    int count = 0;
    for (int j = 0; j < str1.length; j += 2) {
    if (j != str1.length-1) {
        if (str1[j] != str1[j+1]) {
            count++;
            j++;

        }
    } else {
        count++;
    }
   }        
    if (count > 1) return false;
    else return true;
}
0
Loay

コレクションを介してこれを達成することもできます

String name = "raa";
        List<Character> temp = new ArrayList<>(name.chars()
                .mapToObj(e -> (char) e).collect(Collectors.toList()));

        for (int i = 0; i < temp.size(); i++) {
            for (int j = i + 1; j < temp.size(); j++) {
                if (temp.get(i).equals(temp.get(j))) {
                    temp.remove(j);
                    temp.remove(i);
                    i--;
                }

            }

        }

        if (temp.size() <= 1) {
            System.out.println("Pallindrome");
        } else {
            System.out.println(temp.size());
            System.out.println("Not Pallindrome");
        }
    }
0
Rahul Singh