【问题标题】:Arranging word to formpalindrome排列单词以形成回文
【发布时间】:2014-12-23 19:02:08
【问题描述】:

你好,我一直试图从这个输入中形成回文:

String[] text ={"ivcci", "oyotta", "cecarar","bbb","babbbb"};
getPalindrome(text);

我需要重新排列数组中的所有单词来产生这个输出

civic
-1
rececar
bbb
bbabb

该方法期望接收一个字符串数组,例如

public static String getPalindrome(String[] text){}

“返回 -1 表示数组中的 i.g “oyotta” 不能形成回文

我一直在测试这段代码并且它可以工作,但是例如“cecarar”没有产生“racecar”,因为我在 java 中有点新我使用了一个字符串而不是一个字符串数组,任何人都可以帮助正确编写这段代码请问?

非常感谢!

public static String getPalindrome(String s) {

    if (s == null)
        return null;
    Map<Character, Integer> letters = new HashMap<Character, Integer>();

    for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (!letters.containsKey(c))
            letters.put(c, 1);
        else
            letters.put(c, letters.get(c) + 1);
    }

    char[] result = new char[s.length()];
    int i = 0, j = result.length - 1;
    Character middle = null;
    for (Entry<Character, Integer> e : letters.entrySet()) {
        int val = e.getValue();
        char c = e.getKey();

        if (val % 2 != 0) {
            if (middle == null && s.length() % 2 != 0) {
                middle = c;
                val--;
            } else
                return "-1";
        }
        for (int k = 0; k < val / 2; k++) {
            result[i++] = c;
            result[j--] = c;
        }
    }
    if (middle != null)
        result[result.length / 2] = middle;
    return new String(result);
}

【问题讨论】:

  • 好吧ivcci,cecararbabbbb不是回文
  • 我确定他的意思是 civicracecar
  • 不管他的意思是什么,程序都不会知道那些意图……有了这些输入。
  • 你得到的输出是什么?
  • 我的猜测是找到可以转换为回文的输入并这样做。

标签: java arrays palindrome sequences


【解决方案1】:

为了让一组字符能够产生回文,只有一个字母可以重复奇数次,所以你可以先把它去掉。

无需为您编写实际代码,以下是我将使用的算法:

创建一个字符映射到一个计数器。可以做int[] counts = new int[26]; 遍历输入字符串中的每个字符,并增加计数:++counts[Character.toLower(c)-'a']; 然后遍历每个字符,看看它是否为奇数 if (counts[i] &amp; 1 != 0) { if (oddIndex != -1) { return -1; } oddIndex=i; } 如果有两个或更多奇数计数,这将返回 -1。 然后,您可以创建一个StringBuilder,并从中间的oddIndex(如果存在)开始。 然后检查计数,并将 count[i]/2 添加到字符串生成器的前后。

这将为您提供来自原始输入的对称字符串。

现在,如果您确实需要单词,那么您必须拥有一本回文词典。您实际上可以预处理所有回文以获得“排序字符串”=>“回文”的映射

class PalindromeChecker
{
    final Map<String, String> palindromes = new HashMap<String, String>();

    public PalindromeChecker(Iterable<String> allPalindromes) {
        for (String palindrome: allPalindromes) {
           char[] chars = palindrome.getChars();
           Arrays.sort(chars);
           palindromes.put(String.valueOf(chars), palindromes);
        }
    }

    public String getPalindrome(String input) {
           char[] chars = input.getChars();
           Arrays.sort(chars);

           return palindromes.get(String.valueOf(chars));
    }
}

【讨论】:

    【解决方案2】:

    正如其他用户指出的那样,只有当最多有一个字符出现奇数次时,才能将字符串重新排列为回文。

    一旦确认字符串可以转换为回文,就可以按如下方式构造回文(当然这只是众多方法之一):

    • 将你能得到的所有字符对放在字符串的两侧
    • 将省略的单个字符放在字符串的中间,以防有这样的字符。

    例子:

    public class Palindromes {
    
        public static void main(String[] args) {
            String[] text = {"ivcci", "oyotta", "cecarar","bbb","babbbb"};
            for(String str : text){
                evaluatePalindrome(str);
            }
        }
    
        private static void evaluatePalindrome(String str){
            PalindromeCandidate pc = new PalindromeCandidate(str);
            if(pc.isPalindrome()){
                System.out.println(pc.getPalindrome());
            } else {
                System.out.println("-1");
            }
        }
    }
    
    public class PalindromeCandidate {
    
        private final CharacterCount characterCount;
    
        public PalindromeCandidate(String originalString) {
            this.characterCount = new CharacterCount(originalString);
        }
    
        public boolean isPalindrome(){
            Collection<Integer> counts = characterCount.asMap().values();
            int oddCountOccurrences = 0;
            for(Integer count : counts){
                oddCountOccurrences += (count%2);
            }
            return (oddCountOccurrences <= 1);
        }
    
        public String getPalindrome(){
            if(!isPalindrome()){
                throw new RuntimeException("Cannot be rearranged as a palindrome.");
            }
            Map<Character, Integer> counts = characterCount.asMap();
            StringBuilder leftSide = new StringBuilder();
            StringBuilder middle = new StringBuilder();
            for(Character ch : counts.keySet()){
                int occurrences = counts.get(ch);
                while(occurrences > 1){
                    leftSide.append(ch);
                    occurrences -= 2;
                }
                if(occurrences > 0){
                    middle.append(ch);
                }
            }
            StringBuilder rightSide = new StringBuilder(leftSide).reverse();
            return leftSide.append(middle).append(rightSide).toString();
        }
    }
    
    /**
     * Thin wrapper around a Map<Character, Integer>. Used for counting occurences
     * of characters.
     */
    public class CharacterCount {
    
        private final Map<Character, Integer> map;
    
        public CharacterCount(String str) {
            this.map = new HashMap<>();
            for(Character ch : str.toCharArray()){
                increment(ch);
            }
        }
    
        private void increment(Character ch){
            this.map.put(ch, getCount(ch) + 1);
        }
    
        private Integer getCount(Character ch){
            if(map.containsKey(ch)){
                return map.get(ch);
            } else {
                return 0;
            }
        }
    
        public Map<Character, Integer> asMap(){
            return new HashMap<>(map);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-03-02
      • 2016-08-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-17
      • 2021-07-30
      • 2015-06-25
      相关资源
      最近更新 更多