3. 无重复字符的最长子串 - 力扣(LeetCode) (leetcode-cn.com)
文章目录
题目
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
示例 4:
输入: s = ""
输出: 0
思路
双指针l,r res记录最大子串的长度
遍历r;l用于记录窗口最左端的值,当r当前遍历的值和l相同时,l更新
r每移动一次就更新一次res
当遇到重复元素,左指针如何更新
光l++没用,如果当前子列的重复元素不在最左端而是在中部呢
因此每次遍历需记录 下一次遍历时 碰到重复元素 左指针该更新的位置
采用哈希表
class Solution {
public int lengthOfLongestSubstring(String s) {
//哈希表记录遍历的每一个值.键:字符串元素 值:下标
Map<Character,Integer> map = new HashMap<Character, Integer>();
char[] num = s.toCharArray();
/*定义属性
* i 左指针
* j 右指针
* max 记录结果 子串长度最大值
* */
int res = 0;
for(int i=0,j=0;j<s.length();j++){
//若右指针所指元素x已经存在于map,更新左指针至map中x的所对应的下标的后一位
if(map.containsKey(num[j])){
i = Math.max(i,map.get(num[j]) + 1);
}
//判断当前元素是否包含在map中,若不包含,put进map、更新max
//每次都要更新num[j](右指针所指元素)在map中的最新位置
map.put(num[j],j);
res = Math.max(res,j-i+1);
}
return res;
}
}
17行代码解释
如果当前字符 ch 包含在 map中,此时有2类情况:
1)当前字符包含在当前有效的子段中,如:abca,当我们遍历到第二个a,当前有效最长子段是 abc,我们又遍历到a,那么此时更新 left 为 map.get(a)+1=1,当前有效子段更新为 bca;
2)当前最长有效子段不包含当前字符,如:abba,我们先添加a,b进map,此时left=0,我们再添加b,发现map中包含b,而且b包含在最长有效子段中,就是1)的情况,我们更新 left=map.get(b)+1=2,此时子段更新为 b,而且map中仍然包含a,
此时当前最长子段"b"不包含当前字符a.
map.get(a)=0;随后,我们遍历到a,发现a包含在map中,且map.get(a)=0,如果我们像1)一样处理,就会发现 left=map.get(a)+1=1,实际上,left此时应该不变,left始终为2,子段变成 ba才对。为了处理以上2类情况,我们每次更新left,left=Math.max(left , map.get(ch)+1).另外,更新left后,不管原来的 s.charAt(i) 是否在最长子段中,我们都要将 s.charAt(i) 的位置更新为当前的i,因此此时新的 s.charAt(i) 已经进入到当前最长的子段中!
当检索到重复时 获取重复的坐标和start比较 如果小于start则相当于忽略重复 然后在结尾的又一次put就更新了hash表
其他优解
直接比较ASCII码的方法,不明白char和int的本质,debug后了解
![image-20210928171545051](https://gitee.com/hearken_x/local_picture/raw/master/image-20210928171545051.png)
详谈char和int
string对象是不可变的,值不会发生变化
string类不是原始数据类型,我们学习的很多算法都能处理字符串的低级表示,如char类型的数组(消耗空间小,访问时间少)
![image-20210928163107780](https://gitee.com/hearken_x/local_picture/raw/master/image-20210928163107780.png)
字符型数据在内存中是以二进制形式存放的,并不是真正的把一个字符存进内存里。在对字符型数据进行相加减运算的时候,系统会首先将char型数据以隐形的方式转化为int型数据再进行相加减运算。因此,由字符型数据在内存的存储方式来看,字符型数据在做数字运算时实际上是对字符本身对应的ASCII码进行相应的数值运算。
既然char和int本质都是整数,为什么还要作区分呢?
因为字符的个数相对较少,因而char型变量的存储单元可以比int型变量的存储单元小。其实就是提出一种char型变量专门存储字符,方便程序员的数据选择。
‘A’ 65 ‘a’ 97 相差32
Ascii码
[(10条消息) ASCII码字符对照表_会飞的鱼的博客-CSDN博客_ascii码对照表](