跳转至

266. 回文排列 🔒

题目描述

给你一个字符串 s ,如果该字符串的某个排列是 回文串 ,则返回 true ;否则,返回 false

 

示例 1:

输入:s = "code"
输出:false

示例 2:

输入:s = "aab"
输出:true

示例 3:

输入:s = "carerac"
输出:true

 

提示:

  • 1 <= s.length <= 5000
  • s 仅由小写英文字母组成

解法

方法一:计数

如果一个字符串是回文串,那么至多只有一个字符出现奇数次数,其余字符都出现偶数次数。因此我们只需要统计每个字符出现的次数,然后判断是否满足这个条件即可。

时间复杂度 $O(n)$,空间复杂度 $O(|\Sigma|)$。其中 $n$ 是字符串的长度,而 $|\Sigma|$ 是字符集的大小,本题中字符集为小写字母,因此 $|\Sigma|=26$。

1
2
3
class Solution:
    def canPermutePalindrome(self, s: str) -> bool:
        return sum(v & 1 for v in Counter(s).values()) < 2
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class Solution {
    public boolean canPermutePalindrome(String s) {
        int[] cnt = new int[26];
        for (char c : s.toCharArray()) {
            ++cnt[c - 'a'];
        }
        int odd = 0;
        for (int x : cnt) {
            odd += x & 1;
        }
        return odd < 2;
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class Solution {
public:
    bool canPermutePalindrome(string s) {
        vector<int> cnt(26);
        for (char& c : s) {
            ++cnt[c - 'a'];
        }
        int odd = 0;
        for (int x : cnt) {
            odd += x & 1;
        }
        return odd < 2;
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func canPermutePalindrome(s string) bool {
    cnt := [26]int{}
    for _, c := range s {
        cnt[c-'a']++
    }
    odd := 0
    for _, x := range cnt {
        odd += x & 1
    }
    return odd < 2
}
1
2
3
4
5
6
7
function canPermutePalindrome(s: string): boolean {
    const cnt: number[] = Array(26).fill(0);
    for (const c of s) {
        ++cnt[c.charCodeAt(0) - 97];
    }
    return cnt.filter(c => c % 2 === 1).length < 2;
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
/**
 * @param {string} s
 * @return {boolean}
 */
var canPermutePalindrome = function (s) {
    const cnt = new Map();
    for (const c of s) {
        cnt.set(c, (cnt.get(c) || 0) + 1);
    }
    return [...cnt.values()].filter(v => v % 2 === 1).length < 2;
};

评论