算法题解----leetcode.1400.构造k个回文字符串
题目描述:
给你一个字符串 s 和一个整数 k 。请你用 s 字符串中 所有字符 构造 k 个非空 回文串 。
如果你可以用 s 中所有字符构造 k 个回文字符串,那么请你返回 True ,否则返回 False 。
示例1
输入:s = "annabelle", k = 2 输出:true 解释:可以用 s 中所有字符构造 2 个回文字符串。 一些可行的构造方案包括:"anna" + "elble","anbna" + "elle","anellena" + "b"
示例2
输入:s = "leetcode", k = 3 输出:false 解释:无法用 s 中所有字符构造 3 个回文串。
示例3
输入:s = "true", k = 4 输出:true 解释:唯一可行的方案是让 s 中每个字符单独构成一个字符串。
提示:
1 <= s.length <= 10^5 s 中所有字符都是小写英文字母。 1 <= k <= 10^5
这题纯纯的脑筋急转弯,没什么好说的,全是证明
我们不要真的划分这个字符串,把这个字符串划分成各种回文串然后计算个数,等于k个返回true
这题应该这样做:
猜想这个字符串可以划分成的回文串数量应该是一个区间[ min , max ]
假设这个字符串有n个字符,那么max很好求,就是把字符串的每一个字符当成一个回文串,max就是这个字符串的长度
那么这个min怎么求呢?
举个例子 : abaaba 这个回文串有4个a 2个b; abababa 这个回文串有3个b 4个a。那么我们可以大胆猜想奇数个字符的回文串一定有且只有一个字符是奇数个
偶数个字符的回文串一定没有奇数个字符
那么我们可以记录原来字符串每个字符出现的次数
奇数个字符出现的次数是odd 偶数个字符出现的次数是even
那么min一定等于odd ,如果odd是0那么min = 1 这也很好想,就是把那出现奇数次的字符分配到不同的回文串中,其他偶数个字符随便分到那些字符串就好了
那么我们又如何证明k一定在这个范围内呢?
这也不难证明:
既然最少的字符串个数的情况都是这样的:每个回文串都是奇数个字符,并且中间那个字符就是在原来字符串出现的奇数个字符 那么我们就可以拆
可以把一个回文串拆成这样的两个字符串:一个单个字符的回文串且这单个字符就是原来那个回文串中间的那个字符,还有一个原来那个回文串中间被拆掉的回文串
那么一个偶数个字符的回文串如何拆呢 ?
可以随便拆掉一个字符,然后原来那个字符对应的那个字符放到中间去。
所以能拆成的回文串个数就是[ min,max ] 只要k在这个范围就可以
代码如下:
class Solution { public: bool canConstruct(string s, int k) { int character[26]; memset(character,0,sizeof character); for(int i=0;i<s.size();i++) { character[s[i]-'a']++; } int odd = 0; int even = 0; for(int i=0;i<26;i++) { if(character[i]%2 == 0) even++; else odd++; } if(odd == 0) odd = 1; if(k>=odd && k<=s.size()) return true; else return false; } };