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


    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
     
     

    参考文档

     
  • 相关阅读:
    angularjs学习访问服务器(5)
    sublime text 3解放鼠标的快捷键总结
    AngularJS与服务器交互(4)
    android 串口调试
    QCom MSM MDP显示驱动一些点的简记
    如何提高android串口kernel log等级
    高通平台msm8909 LK 实现LCD 兼容
    MSM8909平台 LED背光的控制
    铝聚合物电池工作温度及低温电量差异的说明
    液晶屏工作稳定说明
  • 原文地址:https://www.cnblogs.com/loseself/p/16197872.html
Copyright © 2020-2023  润新知