来自力扣第三题,题目描述如下:
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
提示:
0 <= s.length <= 5 * 104
s 由英文字母、数字、符号和空格组成
解题思路:
本题最重要的一点,要先理解题目所说的 最长子串是什么意思。我的理解是,将字符串划分为一个char数组,以下标为0开始遍历数组,每一个元素都要与已遍历过的元素进行对比,如果出现该元素的值在前面已经遍历的数组中出现过,那么就截至到该元素的前一个元素,作为不重复子字符串
例如“abcabcbb”——》char[] arr = {'a','b','c','a','b','c','b','b'}
以arr[0]为开始的最长不重复子字符串为abc,我们暂且称之为a1吧
然后我们需要进行下一个查询可能比上面a1长的不重复子字符串(假如仍然以arr[0]为开始寻找是没有意义的,因为我们上面的a1已经是以arr[0]为开始的最长不重复子字符串),所以我们下一个查找的有潜力比a1长的字符串开头,应该在arr[0+1],并且下一个进行对已经遍历过的元素进行比较的元素,下标应该是a1.length+a1的第一个元素的下标,如此,我们既可以保证不会错过拥有可能超过已知最长不重复子字符串,也可以直接略过没有潜力的哪些子字符串。
其中编程思绪比较混乱(可能是受到最近写Java类的影响,一开始将其设计为方法分离调用,并且用static的变量放入另外比较长度是否大于已记录的长度的方法中,可以既返回Boolean结果,又可以直接在方法内对已经遍历的数组进行头元素以及尾元素的调整),但其实写一个leetcode的demo的话,直接变量写方法内比较合适。
以下是java代码
publicclassT3 {
publicstaticvoidmain(String[] args) {
Strings="pwwkew";
System.out.println(lengthOfLongestSubstring(s));
}
publicstaticintlengthOfLongestSubstring(Strings) {
//将s转化为char数组
char[] arr=s.toCharArray();
//这里偷懒了,直接将数组长度小于等于1的情况返回,一开始挺不愿意的,然后多次修改无果后只能如此,虽然多出个if语句看起来挺捞的,但是确实客观的答案,时间复杂度我也没看出来会变差,既然无法做到代码更加简洁,那么就如此吧
if(arr.length<=1){
returnarr.length;
}
//设置两个指针,来指明当前未重复的数组的头与尾巴
inthead=0,last=1;
//设置已知最长子字符串的长度为0
intans=0;
for (intj=last; j<arr.length ; j++) {
//对数组进行遍历
for (inti=head; i<last; i++) {
//判断是否和数组内的元素重复
if (arr[i] ==arr[last]) {
//判断数组的长度是否大于已知最大长度
if (last-head>ans) {
ans=last-head;
}
head=i+1;
break;
}
}
last++;
//在这里判断是否大于已记录的答案
if(last-head>ans){
ans=last-head;
}
}
returnans;
}
}