leetcode第三题, 无重复字符的最长子串第一名代码解释记录
代码
public int lengthOfLongestSubstring(String s) {
// 第二次提交,参考执行范例,成功(用时+内存:100%,23%)
int ans = 0, start = 0, len = s.length();
int[] arr = new int[128];
for (int i = 0; i < len; i++) {
int x = s.charAt(i);
start = Math.max(start, arr[x]);
ans = Math.max(ans, i - start + 1);
arr[x] = i + 1;
}
return ans;
}
分解
第一部分, 去掉判断重复的逻辑
字符串"abcdab"
public int lengthOfLongestSubstring(String s) {
// 第二次提交,参考执行范例,成功(用时+内存:100%,23%)
int ans = 0, start = 0, len = s.length();
int[] arr = new int[128];
for (int i = 0; i < len; i++) {
ans = Math.max(ans, i - start + 1);
}
return ans;
}
假如逻辑中没有判断重复的, 那么字符串长度每次循环都要计算
那么ans相当于字符串的长度
第二部分, 当前字符相关信息假如数组
当i=4, 再次来到a的时候, 那么子字符串的长度怎么计算
arr[x] = i + 1;
现在先把每个字符相关信息放入arr数组
当前字符的ASCII码, 就是arr数组的下标
值是当前字符的下一个字符的下标
这样的话, 如果有重复的字符, 那么同一个下标的值会被替换
但是到现在位置, ans还是没有被影响到, 因为新加的代码没有影响到ans和start
int[] arr = new int[128];
int数组, 如果不赋值, 默认值为0
public int lengthOfLongestSubstring(String s) {
// 第二次提交,参考执行范例,成功(用时+内存:100%,23%)
int ans = 0, start = 0, len = s.length();
int[] arr = new int[128];
for (int i = 0; i < len; i++) {
int x = s.charAt(i);
arr[x] = i + 1;
ans = Math.max(ans, i - start + 1);
}
return ans;
}
放入arr
第三部分, 重复时, 更新起始位置
public int lengthOfLongestSubstring(String s) {
// 第二次提交,参考执行范例,成功(用时+内存:100%,23%)
int ans = 0, start = 0, len = s.length();
int[] arr = new int[128];
for (int i = 0; i < len; i++) {
int x = s.charAt(i);
start = Math.max(start, arr[x]);
ans = Math.max(ans, i - start + 1);
arr[x] = i + 1;
}
return ans;
}
start = Math.max(start, arr[x]);
如果一遇到重复的字符, 那么, start就从第一个重复的字符的下一个字符的下标开始
见下图, 如果再次遇见a, 那么start就变成b在字符串位置的下标, 1
所以, ans = Math.max(ans, i - start + 1);
计算的是bcda的长度, 而不是abcda的长度
然后再把, 字符串中, 当前a的下一个字符的下标, 放入arr数组97的下标对应的值, 覆盖值
小结
遍历了一次
用数组下标的形式和ASCII码, 存储了字符与下标的关系, 代替了HashSet或者HashMap
相对来说, 存储的内容变小, 查询也更快了一些
解释
数组通过下标计算长度
假如起始下标是0, 当前下标是0, 那么长度是1, 0 - 0 + 1 = 1
假如起始下标是0, 当前下标是1, 那么长度是2, 1 - 0 + 1 = 2
当前下标current, 起始下标start, 长度length, length = current - start + 1
ans变量
ans, 答案的意思, 最后返回的变量, 变量名叫答案, ans, answer
String.charAt()
char c = s.charAt(i);
int x = s.charAt(i);
string.charAt(下标索引)
返回一个char字符, 如果用int接收, 返回字符ASCII码对应的值
比如字符串 String s = "abc", s.charAt(0) 为 'a', int接收为97
为什么是128的int数组
int[] arr = new int[128];
ASCII码规定了128个字符的编码
所以, 字符的ASCII码就是数组的下标, 值是当前字符的下一个字符的下标
比如字符串, abc, a是97, 那么arr[x] = i + 1 ==> arr[97] = 1