Palindrome Permutation II 解答

时间:2023-03-08 18:32:14

Question

Given a string s, return all the palindromic permutations (without duplicates) of it. Return an empty list if no palindromic permutation could be form.

For example:

Given s = "aabb", return ["abba", "baab"].

Given s = "abc", return [].

Hint:

  1. If a palindromic permutation exists, we just need to generate the first half of the string.
  2. To generate all distinct permutations of a (half of) string, use a similar approach from: Permutations II or Next Permutation.

Answer

这道题思考起来其实不难,就是步骤比较多,要小心。

1. 判断输入是否能有permutation构成palindrome => HashMap或HashSet,这里因为判断完后还有下一步,所以采用Map

2. 根据Map获得first half of the string

3. Backtracking生成first half的permutation

4. 根据生成的permutation,补齐last half

另外解答中处理反转String的方法也值得学习:先利用原String构造一个StringBuffer,然后从后往前遍历原String,将char一一加到StringBuffer中。

 public class Solution {
public List<String> generatePalindromes(String s) {
List<String> result = new ArrayList<>();
if (s == null || s.length() == 0) {
return result;
}
int len = s.length();
Map<Character, Integer> map = new HashMap<>();
if (!isPalindromePermutation(map, s)) {
return result;
}
char mid = '\0';
StringBuilder sb = new StringBuilder();
for (char cur : map.keySet()) {
int num = map.get(cur);
while (num > 1) {
sb.append(cur);
num -= 2;
}
if (num == 1) {
mid = cur;
}
}
Set<String> prefix = new HashSet<String>();
boolean[] visited = new boolean[sb.length()];
dfs(sb, visited, prefix, "");
for (String left : prefix) {
StringBuffer tmp = new StringBuffer(left);
if (mid != '\0') {
tmp.append(mid);
} for (int i = left.length() - 1; i >= 0; i--) {
tmp.append(left.charAt(i));
}
result.add(tmp.toString());
}
return result;
} private void dfs(StringBuilder sb, boolean[] visited, Set<String> result, String prev) {
if (prev.length() == sb.length()) {
result.add(prev);
return;
}
int len = sb.length();
int prevIndex = -1;
for (int i = 0; i < len; i++) {
if (visited[i]) {
continue;
}
if (prevIndex != -1 && sb.charAt(i) == sb.charAt(prevIndex)) {
continue;
}
visited[i] = true;
dfs(sb, visited, result, prev + sb.charAt(i));
visited[i] = false;
prevIndex = i;
}
} private boolean isPalindromePermutation(Map<Character, Integer> map, String s) {
int tolerance = 0;
int len = s.length();
for (int i = 0; i < len; i++) {
char cur = s.charAt(i);
if (!map.containsKey(cur)) {
map.put(cur, 1);
} else {
map.put(cur, map.get(cur) + 1);
}
}
for (char cur : map.keySet()) {
int num = map.get(cur);
if (num % 2 == 1) {
tolerance++;
}
}
return tolerance < 2;
}
}