题目要求:
算法分析:
本题采用“滑动窗口法”。
使用java中Colloction
的接口Set
,存放已识别的子串,此子串要更新,更新原则是有相同元素出现,因此选用Set<String>
中创建HashSet
字符串对象,HashSet是Set的一个实现子类,即此类实现Set接口,它由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变,可以理解为元素的存取顺序不一致。之后就是对原字符串进行遍历,此处区别于暴力循环!!!因为暴力循环拆解字符串的时间复杂度为O(n^3),超时通过不了。
在这里由于用Set,只需要一层循环,开始条件是定位字符的位置为0,结束为最后一个字符遍历结束。循环内部首先有一个判断:判断“新来的”字符是否在已存储的子串中出现过,这里用的是set的contains
方法。如果出现过就说明这个子字符串不满足,所以要做的事情有四件,第一件是将原来的子串中所有元素移除,用到的是clear
方法,与此平行的是将字串长度计数器num置0,同时字串开始位置要后移一位并且将遍历计数器i重新置数,置为子串新开始的位置。不论有没有出现过相同元素,都要把子串计数器加一(如果出现相同元素了也就是重新从1开始,没有的话就从原来的数继续增加1),接着要去判断(储存)最大子串长度,最后一步将本次“新来的”字符添加到新的子串中去。
源代码:
class Solution {
public int lengthOfLongestSubstring(String s) {
int num=0, nummax=0, n=0; //分别存放本次最大字符串长度,所有最大字符串长度,子串开始位置
Set<String> setting = new HashSet<String>(); //一个集合存放子串
for(int i=0; i<s.length(); i++){
if(setting.contains(s.charAt(i)+"")){ //如果子串中包含原字符串第i个位置上的这个字符
setting.clear(); //清空子串
num = 0; //字符串长度为0
n++; //字串开始位置后移一位
i = n; //遍历从新位置开始
}
num++; //字串长度加1
if(nummax < num){
nummax = num;
}
setting.add(s.charAt(i)+""); //把当前这个字符加进去
}
return nummax;
}
}
时间和空间:
笔记:
- java中
set
集合用法:Set主要方法以及相关接口 s.charAt(i)
:返回字符串s中第i个位置的字符setting.contains(x)
:集合setting中是否包含元素xsetting.add(x)
:向集合setting中增加元素xsetting.claer()
:移除集合setting中所有的元素
感想:
这个题目核心思想就是滑动窗口法来代替暴力遍历节省运行时间,参考了一些博客上其他人的解法,需要掌握的就是java中的专用类和相关接口。