LeetCode系列之——3. Longest Substring Without Repeating Characters(JavaScript)

Q:

题目链接:Longest Substring Without Repeating Characters
先看题目要求:
Given a string, find the length of the longest substring without repeating characters.

Examples:

Given “abcabcbb”, the answer is “abc”, which the length is 3.

Given “bbbbb”, the answer is “b”, with the length of 1.

Given “pwwkew”, the answer is “wke”, with the length of 3. Note that the answer must be a substring, “pwke” is a subsequence and not a substring.

  你有一个字符串,从中找到最长的没有重复字符的子串,并返回其长度。

分析

  这个题目估计需要一个时间复杂度为O(n)的算法,也就是将源字符串遍历一遍,怎么能遍历一遍又能做到字符的比对(判断是否重复)?一定需要一个变量做缓存的。
  所以得出最初的思路为:用一个Object类型的变量cache来存储元素和索引值,如:{{a:0},{b:1}},每遍历到一个字母就来比对,如果有一样的就用当前索引值减去比对到的cache中元素的索引值,得到一个差值,遍历完毕后找出最大的差值就是要求的值。
  于是我根据这个思路写出代码:

var lengthOfLongestSubstring = function(s) {
    var len = s.length;
    var cache = {};
    var max = 1;
    if(len > 0){
        for(var i = 0;i < len;i++){
            var w = s.substring(i,i+1);
            if(cache[w]){//匹配到了
                if(i - cache[w] > max){
                    max = i - cache[w];
                }
            }
            //更新缓存obj
            cache[w] = i;
        }
    }else{
        max = 0;
    }
    return max;
};

  这个算法的问题是显而易见的:如果字符串中没有重复的元素,显然就不成立了。于是,我们改进了算法:

var lengthOfLongestSubstring = function(s) {
    var max = 0;
    var last = -1;
    var cache = {};

    for (var i = 0, l = s.length; i < l; ++i) {
        if (cache[s[i]] !== undefined) {
            last = cache[s[i]];
        }

        if (i - last > max) {
            max = i - last;
        }

        cache[s[i]] = i;
    }
    return max;
};

  这次给匹配到的元素加了一个索引指针,如果一直没有匹配到的元素,指针就一直停留下-1的位置,如果有匹配到重复元素,指针就更新到cache中匹配到的元素的索引。
  看似没啥毛病了,结果一提交又报错了…当输入’abba’时问题来了,当遍历到最后一个’a’时,last被更新为0,后面就不用说了,肯定是出错了。问题的原因在于:我们需要从上一个匹配到的元素开始重新计数,所以这次匹配到的 cache[s[i]] = 0在当前last指针(指向1)的左边,不属于计数范围,故不需要更新last指针,因此将代码修改为:

var lengthOfLongestSubstring = function(s) {
    var max = 0;
    var last = -1;
    var cache = {};

    for (var i = 0, l = s.length; i < l; ++i) {
        if (cache[s[i]] > last) {
            last = cache[s[i]];
        }

        if (i - last > max) {
            max = i - last;
        }

        cache[s[i]] = i;
    }
    return max;
};

  另外在Discuss中看到一个只有9行的答案,贴出来学习:

function lengthOfLongestSubstring(s) {
    const map = {};
    var left = 0;

    return s.split('').reduce((max, v, i) => {
        left = map[v] >= left ? map[v] + 1 : left;
        map[v] = i;
        return Math.max(max, i - left + 1);
    }, 0);
}

  思路都是一样的,但是使用了数组的api->reduce方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值