Ecrivez une méthode pour vérifier si une chaîne remplit les conditions préalables pour devenir un palindrome.
Par exemple:
Input | Output mmo | True yakak | True travel | False
Je pense à cette approche:
Est-ce que je manque quelque chose?
Vraiment, tout ce que vous cherchez, c’est que toutes les lettres (ou toutes les lettres sauf une) soient jumelées. Tant qu'ils le seront, ils pourront être transformés en palindrome.
Donc, ce serait quelque chose comme ...
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;
}
Ce n'est pas le plus efficace (compter les lettres autant de fois qu'il les rencontre, même si elles ont déjà été comptées), mais cela fonctionne.
Tout ce que vous avez à faire, c'est de vérifier qu'il y a au plus un caractère avec un nombre impair d'occurrences. Voici un exemple 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 (oui - elles sont ordonnées pour avoir un sens, mais elles sont numérotées par ordre chronologique):
La mise en œuvre ci-dessus présente une inefficacité intrinsèque. Je ne pense pas que la première itération sur la chaîne puisse être évitée, mais il n'y a pas de vraie raison de garder un compte de toutes les occurrences - c'est assez pour garder une trace de ceux qui ont un compte impair. Pour ce cas d'utilisation, il suffit de garder trace de chaque caractère rencontré (par exemple, avec une variable Set
) et de le supprimer lorsque nous le rencontrons à nouveau. Dans le pire des cas, où tous les caractères de la chaîne sont différents, les performances sont comparables, mais dans le cas habituel, où il existe plusieurs occurrences de chaque caractère, cette implémentation améliore à la fois la complexité temporelle et mémoire de la maintenant réduite à une seule condition) de façon dramatique:
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 (oui - elles sont ordonnées pour avoir un sens, mais elles sont numérotées par ordre chronologique):
Java 8 fournit une API de streaming fluide qui pourrait être utilisée pour créer une implémentation semblable aux liners Python ci-dessous:
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;
}
MODIFIER:
Les fonctions intégrées et les capacités de compréhension de Python rendent cette option trop attrayante pour ne pas publier cette solution one-liner. C'est probablement moins efficace que celui de Java, mais il est assez élégant:
from collections import Counter
def canMakePalindrom(s):
return len([v for v in Counter(s).values() if v % 2 == 1]) <= 1
EDIT2:
Ou encore, une approche encore plus propre proposée par @DSM dans les commentaires:
from collections import Counter
def canMakePalindrom(s):
return sum(v % 2 == 1 for v in Counter(s).values()) <= 1
Au lieu de compter le nombre de fois que chaque lettre se produit, une autre approche permet de savoir si une lettre est survenue un nombre impair ou pair. Si une lettre est survenue un nombre pair de fois, vous n’avez pas à vous en soucier, vous devez seulement garder une trace des occurrences impaires d’un ensemble. En 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;
}
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]
Si je comprends bien votre question, voici comment je le comprends:
Si la chaîne d'entrée peut être réorganisée en un palindrome, indiquez "True", sinon indiquez "False".
Ensuite, vous pouvez utiliser ces règles simples:
Donc pour les 3 exemples donnés:
"mmo", longueur impaire, m
apparaît deux fois (multiple de 2), o
une fois (pas un multiple de 2), donc True
.
"yakak", longueur irrégulière, a
apparaît deux fois (multiple de 2), k
apparaît deux fois (multiple de 2), y
apparaît une fois (pas un multiple de 2), donc True
.
"voyage", plus d'un caractère ne se produit pas un multiple de 2, donc False
.
Exemples supplémentaires:
"mmorpg", seulement m
se produit un multiple de 2, le reste une seule fois, donc False
.
"mmom", aucun caractère ne correspond à un multiple de 2, plus d'un caractère "pas un multiple de 2 fois", donc False
.
À ce stade, vous devez comprendre que si un seul caractère est autorisé à apparaître une fois non multiple, vous pouvez ignorer la longueur. Une chaîne de longueur paire aura soit 2 caractères ou plus, soit un nombre de fois non multiple, soit aucun.
La règle finale devrait donc être la suivante:
Si au plus 1 caractère unique apparaît une fois non multiple de 2, le résultat est
True
sinon le résultat estFalse
.
def check(string):
bv = 0
for s in string:
bv ^= 1 << ord(s)
return bv == 0 or bv & (bv - 1) == 0
J'ai atteint la solution ci-dessous aujourd'hui (python). Je pense que c'est lisible et que, du point de vue des performances, c'est vraiment bon.
sum(map(lambda x: Word.count(x) % 2, set(Word))) <= 1
Nous comptons essentiellement le nombre d'occurrences de chaque caractère dans la chaîne "Word", obtenons le reste de la division par 2, les additionnant et vérifiant si vous en avez au plus 1.
L'idée est que vous devez associer tous les caractères, sauf potentiellement pour un (le milieu).
Mon idée est la suivante: si le nombre de lettres avec un nombre impair est égal à un et que le reste a un nombre égal, un palindrome est possible. Voici mon programme en 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")
C'est ma solution
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");
}
}
Question: Une chaîne peut-elle devenir un palindrome? Méthode 1: nombre de caractères EN 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");
}
}
}
EN 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)
Méthode 2: Utilisation de HashSet En Java:
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");
}
}
}
Si nous ne nous soucions pas de la casse des caractères et des espaces d'une chaîne, un exemple de solution en C # à l'aide de Dictionary peut ressembler à:
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;
}
Toute chaîne ne peut être palindrome que si au plus un caractère est impair impair. nombre de fois et tous les autres caractères doivent apparaître même nombre de fois. Le programme suivant peut être utilisé pour vérifier si un palindrome peut être une chaîne ou non.
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;
}
Avec O(n) complexité.
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();
}
}
}
C'est ma solution. La chaîne peut contenir plusieurs mots avec des espaces, tels que
Entrée: Tact Coa Sortie true Entrée: Tact Coa vvu Sortie: 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;
}
Nous pouvons y arriver via des collections également
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");
}
}