From jiuzhang
题目描述
给定一个字符串,找到最长的包含最多k个不同字符的子串,输出最长子串的长度即可。
Example:
给出字符串”eceba”,k = 2
输出答案3,最长包含最多2个不同字符的子串为”ece”
解题思路
最暴力的做法是穷举所有可能的子串,一共有n^2级别个不同的子串,然后对于每一个子串统计有多少不同的字符,如果少于k个就更新答案。这是一个三重循环的穷举,复杂度是O(n^3)。聪明的读者肯定想到了第二重和第三重循环可以合并,因为之前的统计信息可以继续使用而不需要每一次重新统计。这样的话穷举子串的开始位置和结束位置,复杂度是O(n^2)。如果在面试时提出了这个算法,面试官首先会表示认同,然后希望你进行优化。我们来看看如何进行优化。
在统计的过程中我们可以发现,当穷举的开始位置改变时我们会选择重新统计,但其实当开始位置改变时,我们之前记录的大部分信息都是有用的,我们只需在原有的统计结果上稍作修改。我们在两层for循环的时候其实会发现我们内层的fo循环其实并不需要每次都再重复遍历。比如外层for循环指针i每次向前移动变成i+1的时候,内层for循环的j没必要每次都退回到i的位置,其实是可以保留在j的位置不变的。因为可以证明对于从i+1到j-1这些情况都不会出现重复的元素,所以我们只用考虑从i+1到j就可以了。
分析一下这个算法的时间复杂度,虽然我们会用到两重循环(请看参考程序),但是因为这两个指针只增不减,每次循环指针增加1,因此while循环总共只会进入n次(n = s.length( )),所以时间复杂度是O(n)。
参考代码
1 | public class Solution{ |
算法分析
这是一道很有区分度的题目,有O(n^3),O(n^2),O(nlogn)(follow up),O(n)时间复杂度的做法。先提出一种可行算法,通过一步步分析、优化,最后提出O(n)的最优算法并完成代码就可以达到hire的程度。
相关练习
minimum-size-subarray-sum
longest-without-repeating-characters