请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
    输入: “abcabcbb”
    输出: 3
    解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
    输入: “pwwkew”
    输出: 3
    解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
    请注意,你的答案必须是 子串 的长度,”pwke” 是一个子序列,不是子串。
    方法一:动态规划
    dp[j]={ dp[j−1]+1, (dp[j−1] j−i, (dp[j−1]≥j−i )
    哈希表统计: 遍历字符串 ss 时,使用哈希表(记为 dicdic )统计 各字符最后一次出现的索引位置 。
    左边界 ii 获取方式: 遍历到 s[j]s[j] 时,可通过访问哈希表 dic[s[j]]dic[s[j]] 获取最近的相同字符的索引 ii 。

    1. const LongestSubstring(str) => {
    2. let map = new Map(), max = 0, tmp = 0, j = 0
    3. for (let i = 0; i < s.length; i++) {
    4. if (map.has(s[i])) {
    5. j = map.get(s[i])
    6. }else{
    7. j = -1
    8. }
    9. map.set(s[i], i)
    10. if (tmp < i - j) {
    11. tmp++
    12. } else {
    13. tmp = i - j
    14. }
    15. max = Math.max(max, tmp)
    16. }
    17. return max
    18. }

    方法2:双指针 + 哈希表
    更新左指针 ii : 根据上轮左指针 ii 和 dic[s[j]]dic[s[j]] ,每轮更新左边界 ii ,保证区间 [i + 1, j][i+1,j] 内无重复字符且最大。
    i=max(dic[s[j]],i)

    更新结果 resres : 取上轮 resres 和本轮双指针区间 [i + 1,j][i+1,j] 的宽度(即 j - ij−i )中的最大值。
    res=max(res,j−i)