Palindrome Permutation II

题目描述

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:

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

解题方法

一开始没啥想法,不知道如何下手,看了提示之后顿悟,如果能够有palindrome,只需要找出前half string的所有permutation就可以了。

  • 先判断是否能有palindrome,用1的方法
  • 如果能够组成,找出前half string可用的所有characters(可以重复)
  • permutation找出所有(如果是奇数的话注意中间的字母不可以变)

Solution

class Solution(object):
    def generatePalindromes(self, s):
        """
        :type s: str
        :rtype: List[str]
        """
        if not s:
            return []

        canPalindrome, dic = self.canPermutePalindrome(s)
        if not canPalindrome:
            return []

        halfS = []
        for c in dic:
            for i in range(dic[c] / 2):
                halfS.append(c)

        results = []
        self.permuteUnique(results, halfS)

        if len(s) % 2 == 1:
            oddC = ""
            for c in dic:
                if dic[c] % 2 == 1:
                    oddC = c
            if not results:
                results = [oddC]
            else:
                for idx, result in enumerate(results):
                    results[idx] = result + oddC + result[::-1]
        else:
            for idx, result in enumerate(results):
                results[idx] = result + result[::-1]


        return results


    def canPermutePalindrome(self, s):
        if len(s) == 0:
            return True

        dic = {}
        for i in range(len(s)):
            if s[i] not in dic:
                dic[s[i]] = 1
            else:
                dic[s[i]] += 1

        foundOdd = 0
        for key in dic:
            if dic[key] % 2 == 1:
                foundOdd += 1

        if len(s) % 2 == 0:
            if foundOdd != 0:
                return False, dic
            else:
                return True, dic
        else:
            if foundOdd == 1:
                return True, dic
            else:
                return False, dic

    def permuteUnique(self, results, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        if not nums:
            return results
        length = len(nums)
        nums.sort()
        used = [False for i in range(length)]
        self.permuteHelper(nums, used, results, [])
        return results

    def permuteHelper(self, nums, used, results, curList):
        if len(curList) == len(nums):
            tmpList = "".join(curList)
            results.append(tmpList)

        for i in range(len(nums)):
            if i != 0 and nums[i] == nums[i-1] and used[i-1] == False:
                continue
            if not used[i]:
                curList.append(nums[i])
                used[i] = True
                self.permuteHelper(nums, used, results, curList)
                curList.pop()
                used[i] = False

Reference