其他分享
首页 > 其他分享> > 无重复字符的最长子串第一名代码解释记录

无重复字符的最长子串第一名代码解释记录

作者:互联网

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相当于字符串的长度   0    

第二部分, 当前字符相关信息假如数组

 
当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 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);
        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   0   所以, 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   0   0    

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   0   0    

参考文档

  https://www.ruanyifeng.com/blog/2007/10/ascii_unicode_and_utf-8.html https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/ https://leetcode-cn.com/submissions/detail/305470233/

标签:子串,字符,第一名,下标,int,arr,start,ans
来源: https://www.cnblogs.com/loseself/p/16197872.html