【问题标题】:Get all possible palindromes from a given string从给定的字符串中获取所有可能的回文
【发布时间】:2019-07-11 12:29:38
【问题描述】:

子字符串是字符串中连续的字符范围。

现在我需要找出可以重新排列的子串有多少可以形成回文。

例如:对于输入 - aabb

a
aa
aab (because after re-arranging it becomes aba)
aabb (because after re-arranging it becomes abba)
a
abb (because after re-arranging it becomes bab)
b
bb
b

So we have 9 substring palindromes.

这是我试过的代码:

public static int getPalindromeCount(String str) {
    // all single characters are treated as palindrome
    int count = str.length();

    // Get all sub strings
    List<String> subs = new ArrayList<>();
    subString(str, subs);

    for (String sub : subs) {
        String rev = new StringBuilder(sub).reverse().toString();

        if (rev.equals(sub)) {
            System.out.println(sub);
            count++;
        } else {
            boolean valid = isPalindrome(sub);
            System.out.println(sub + " : " + valid);
            if (valid) {
                count++;
            }
        }
    }
    return count;
}

// Check if substring can form a Palindrome
private static boolean isPalindrome(String input) {
    Set<Character> oddChars = new HashSet<>();

    for (char c : input.toCharArray()) {
        if (!oddChars.add(c)) {
            oddChars.remove(c);
        }
    }
    return oddChars.size() <= 1;
}

// Get all substrings
private static void subString(String input, List<String> list) {
    for (int i = 0; i < input.length(); i++) {
        for (int j = i + 2; j <= input.length(); j++) {
            list.add(input.substring(i, j));
        }
    }
}

方法isPalindrome部分逻辑我从这篇帖子Check if a permutation of a string can become a palindrome中得到的

此代码运行良好,但因超时错误而失败。

我不确定哪些输入是失败的,因为它们隐藏在我的hackerrank 挑战中。

编辑:

我已经修改了我的getPalidromeCount 方法来检查输入中有多少个奇数字母来决定回文数。

这是基于对这篇文章的评论:

提示:回文由所有偶数或所有字母组成 偶数个字母加一个奇数个字母(中间 特点)。现在,您可以轻松计算可能的回文数。 – vivek_23

public static int getPalindromeCount(String str) {
    List<Integer> list = new ArrayList<>(strToEvaluate.size());
    for (String str : strToEvaluate) {
        int count = str.length();

        List<String> subs = new ArrayList<>();
        subString(str, subs);
        for (String sub : subs) {
            Map<Character, Integer> map = new HashMap<>();
            for (int i = 0; i < sub.length(); i++) {
                char c = sub.charAt(i);
                map.put(c, map.getOrDefault(c, 0) + 1);
            }
            int odds = 0;
            for (char key : map.keySet()) {
                if (map.get(key) % 2 != 0) {
                    odds++;
                    if (odds > 1) {
                        break;
                    }
                }
            }
            if (odds <= 1) {
                System.out.println(sub);
                count++;
            }

            list.add(count);
        }
    }
    return list;
}

但我仍然看到超时错误。我没有在这个逻辑中使用isPalindrome 方法。

【问题讨论】:

  • 如果一个字符串向后读和向前读一样,难道不是回文吗?你为什么还要计算重新排列字母?编辑:没关系,看到你编辑了这个问题。
  • 提示:回文由所有偶数字母或所有偶数字母和一个奇数字母(中间字符)组成。现在,您可以轻松计算可能的回文数了。
  • @vivek_23,我已根据您的建议在我的编辑部分添加了修改后的代码。但我仍然看到相同的超时问题。我这里有什么需要改变的吗?我将所有字母添加到地图,然后检查地图是否存在多少奇数字母。
  • @learner 你能分享一个问题的链接吗?我敢肯定,当您遍历每个字符串时,您可以删除以前的字符数并增加当前字符数并检查回文。
  • @learner 我假设 26 * O(n^2) = O(n^2) 解决方案应该被接受。

标签: java algorithm palindrome


【解决方案1】:

n(n+1)/2 可能的子字符串,对于每个子字符串,您检查它是否可以重新排列,以便它在O(k) 中形成回文,其中k 是给定子字符串的长度,让我们考虑是否有必要分别解析每个子字符串。

提示:

假设您有从索引pk 的子字符串,那么您对从索引pk + 1 的子字符串有什么看法。真的有必要单独解析这个扩展子串吗?

【讨论】:

  • 对不起,我没看懂提示。如果取bba,则重新排列为bab,则为回文。现在如果我取bbac,这不是回文。您能否详细解释一下提示的用途?
  • @learner 考虑单词aabb的索引0中的所有子字符串,所以我们有aaaaabaabb。您正在分别分析每个案例,但这不是必需的,当您附加新字母时,更新oddChars 的编号并确定它是否满足条件就足够了。多亏了这一点,可以在O(n) 中而不是在O(n^2) 中计算所有具有特定起始索引的子字符串(您不必生成所有可能的子字符串然后单独分析)。因此整个复杂性是O(n^2) 而不是O(n^3)
  • 我已经更新了我的代码,编辑部分有最新的代码,在最新的代码中我没有使用isPalindrome 方法所以没有使用oddChars 变量。那么现在,这个提示仍然适用吗?你能检查一下吗
  • 是的,它仍然适用。正如我所说,当你有词 aabb 时,你分别检查 aaaaabaabb 是否满足条件。您可以在一个循环中完成,从“a”开始满足条件(1 个奇数字符和奇数长度),“aa”满足(1 个偶数字符和偶数长度)等。您可以一次性完成特定的开始索引。
  • 所以我的理解是void subString(String input, List&lt;String&gt; list) 在这里我得到子字符串,所以在这里我需要找到偶数和奇数(就像我在使用 HashMap 的代码编辑部分中所做的那样)并决定是否是否是回文。对吗?
【解决方案2】:
  • 我的假设是字符串由小写字母组成。如果没有,您可以增加以下数组中的哈希大小以适应 ASCII 值或更好地使用 UTF-8 字符的映射。
  • 无需收集所有子字符串,然后单独检查每个子字符串(这将占用 O(n2) 空间,您可以一路迭代它们,增加当前字符数并检查回文如下图。

代码:

 class Solution{
  public static long getPalindromeCount(String s) {
    long cnt = 0,len = s.length();    
    for(int i=0;i<len;++i){
       int[] hash = new int[26];
       cnt++; // since 1 character is palindrome anyway
       for(int j=i+1;j<len;++j){
          hash[s.charAt(j)-'a']++;
          if(palindromePossible(hash)) cnt++; 
       }
    }
    return cnt;
  }

  private static boolean palindromePossible(int[] hash){
    int odd_cnt = 0;
    for(int i=0;i<hash.length;++i){
      if(hash[i] % 2 != 0) odd_cnt++;
    }
    return odd_cnt < 2;
  }

  public static void main(String[] args){
    System.out.println(getPalindromeCount("aabb"));
  }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-26
    • 1970-01-01
    • 2018-06-29
    • 2012-02-28
    • 1970-01-01
    • 2020-06-23
    • 2018-07-21
    • 1970-01-01
    相关资源
    最近更新 更多