Medium
Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form.
Example 1:
Input:"aabb"Output:["abba", "baab"]
Example 2:
Input:"abc"Output:[]
解法:
直观的看,如果一个字符串能组成回文,那么它必然可以从中间被切分成两段,且折叠后相应位置上的字符相同。简单地说,就是除了中间的分割点字符(如果字符串长度是奇数的话),左右两段的字符都是成对出现的,也就是说它们的个数是呈偶数出现的。反之,如果给出的字符数组不足以满足上述条件,那么就组成不了回文。
所以这道题我们可以分成三步来解决:
1. 判断给定字符串能否具备组成回文的条件(如果不具备,那么就不用往下算了)
2. 找出组成回文的其中一侧的字符都有哪些,并识别是否存在独立的中间分割字符(如果字符串长度是奇数的话)
3. 基于上一步找到的所有字符生成全排列(就把问题转换成了LeetCode的47题)
4. 将第3步生成的每一组排列的后面加上中间分割字符(如果有的话),然后翻转该组排列并接到后面,即可得到一个符合要求的回文字符串
public static List<String> generatePalindromes(String s) {
// 1. check possibility
int[] map = new int[128] ;
int count = 0;
for(int i=0; i<s.length(); i++) {
map[s.charAt(i)] ++ ;
if(map[s.charAt(i)] % 2 == 0) {
count -- ;
} else {
count ++ ;
}
}
if(count > 1) {
return new ArrayList<>() ;
}
// 2. generate half palindrome string
Map<Character, Integer> groups = new HashMap<>() ;
// 2.1 grouping and find out the single char
Character single = null ;
for(int i=0; i<map.length; i++) {
if(map[i] % 2 == 1) {
single = (char) i ;
map[i] -- ;
}
if(map[i] !=0 ) {
groups.put((char) i, map[i]/2) ;
}
}
// 2.2 generate permutation with grouped string
return generatePermutation(groups, single) ;
}
private static List<String> generatePermutation(Map<Character, Integer> groups, Character single) {
// calculate max len
int max = groups.values().stream().reduce(Integer::sum).orElse(0) ;
List<String> ans = new ArrayList<>() ;
backtrack(max, new LinkedList<>(), groups, single, ans);
return ans ;
}
private static void backtrack(int maxLen, LinkedList<Character> currList, Map<Character, Integer> groups, Character single, List<String> ans) {
if(currList.size() == maxLen) {
// generate left half palindrome
StringBuilder sb = new StringBuilder();
Iterator<Character> iter = currList.iterator() ;
while(iter.hasNext()) {
sb.append(iter.next()) ;
}
if(single != null) {
sb.append(single) ;
}
iter = currList.descendingIterator() ;
while(iter.hasNext()) {
sb.append(iter.next()) ;
}
ans.add(sb.toString()) ;
}
for(Map.Entry<Character, Integer> entry : groups.entrySet()) {
char c = entry.getKey() ;
int count = entry.getValue() ;
if(count == 0) {
continue ;
}
currList.addLast(c) ;
groups.put(c, count - 1) ;
backtrack(maxLen, currList, groups, single, ans);
groups.put(c, count) ;
currList.removeLast() ;
}
}
本文介绍了如何通过Java实现从给定字符串生成所有不重复的回文排列。首先检查字符串是否具备形成回文的条件,然后找出一半的回文字符串并识别可能的中间字符,最后生成排列并构造完整回文。示例展示了对于输入aabb和abc的解题过程。
406

被折叠的 条评论
为什么被折叠?



