看起来很难的样子,隐约觉得要动态规划。
先用笨办法,基本就是枚举。。果然TLE。
public class Solution {
int res = 0;
public int longestSubstring(String s, int k)
{
int[] map = new int[26];
for(int i = 0; i < s.length(); i++)
{
map[s.charAt(i) - 'a']++;
int[] tempMap1 = map.clone();
if(checkMin(map,k)) res = Math.max(res,i+1);
for(int j = i; j > 0; j--)
{
tempMap1[s.charAt(j) - 'a']--;
if(checkMin(tempMap1,k)) res = Math.max(res, j-1);
}
int[] tempMap2 = map.clone();
for(int j = 0; j <= i; j++)
{
tempMap2[s.charAt(j) - 'a']--;
if(checkMin(tempMap2,k)) res = Math.max(res,i - j);
}
}
return res;
}
public boolean checkMin(int[] map, int k)
{
for(int n: map)
{
if(n <= 0) continue;
else
{
if(n < k) return false;
}
}
return true;
}
}
感觉上是动态规划能做的题。。
...
....
.....
经过一番思考,我感觉我刚才的感觉错了。
按部就班没什么好办法。
羞射地看了答案。
普遍思路是,分治。 先看26个字母里哪些出现次数不够k次。
重新遍历String,遇到那些不够K次的老鼠屎,为了避免他们坏一锅汤,把上一个老鼠屎到这个老鼠屎之间的String作为一个竞争者,递归。。
总之就是老鼠屎0~老鼠屎1 老鼠屎1~老鼠屎2 ...
这样下去。
需要注意的是,递归的时候如果当前String不含老鼠屎,那最大长度就是本身。
然后老鼠屎n到String最后别忘了算一下。
都是些edge case
public class Solution {
public int longestSubstring(String s, int k)
{
if(s.length() == 0) return 0;
int[] map = new int[26];
for(int i = 0; i < s.length();i++)
{
map[s.charAt(i) - 'a']++;
}
int[] check = new int[26];
for(int i = 0; i < 26; i++)
{
if(map[i] < k) check[i]=-1;
}
int res = 0;
int begin = 0;
for(int i = 0; i < s.length();i++)
{
if(check[s.charAt(i) - 'a'] == -1)
{
res = Math.max(res,longestSubstring(s.substring(begin,i),k));
begin = i+1;
}
}
if(begin == 0) return s.length();
else res = Math.max(res,longestSubstring(s.substring(begin,s.length()),k));
return res;
}
}
新题,思路比较少。过段时间大家集思广益,可能有意想不到的办法。