美文网首页
记一次简单的算法题

记一次简单的算法题

作者: yoona幻尘 | 来源:发表于2019-12-05 21:23 被阅读0次

    题目:给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
    例子:输入: "abcabcbb"
    输出: 3
    解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

    看到字符串取最长,我立马想到暴力循环法,理论上是每个位置的字符串都可以作为首位开始,所以只需要依次循环重复,直到出现重复子串。

    /*
    param: 用于判断的总字符串 
    param: 循环开始位数
    param: 初始字符串
    */
       let deff = function(s,c,str){
        for(let i =c;i<s.length;i++){
            if(str.indexOf(s[i]) ==-1){
                str+=s[i]
            }else{
                return [str.length, c+1]
            }
        }
        return [str.length, c+1]
    }
    

    对于传入的字符串,进行移位迭代

    // 建立一个数组,依次存储从头开始的长度
    let lengthOfLongestSubstring = function(s) { 
      let b = [];
      let initKey = 0;
      while(initKey<s.length){
          let temp = deff(s,initKey,str='');
          b.push(temp[0]);
          initKey = temp[1];
      }
      return b.sort((c,d)=>d-c).length ? b.sort((c,d)=>d-c)[0] : 0
    };
    

    暴力循环是解决了问题,但是是比较浅显的思想,有什么更好的呢? 我们来再思索一下问题。
    给定一个任意字符串,就以"abcabcbb"为例吧,我们看执行到"abc"的时候,暴力循环就记下这个长度3,然后从b开始继续循环,直到循环结束。但是我们会发现一点,第一次循环之后我们得到了“abc”,下一个是"a",我们完全可以排除首个a,以“bca”继续循环下去,没有必要在重新从无意义的循环开始,这个例子比较巧,刚好是首字母重叠,换个例子“abcb”,得到“ab”之后,完全没有必要再从“b”开始循环,因为得到的最大子串也不过是等于之前的子串长度。

    let lengthOfLongestSubstring = function(s) { 
       let num = 0,res = 0;
       let m = '';
      for (n of s) {
        if (m.indexOf(n) == -1) {
          m += n;
          num++;
          res = res < num ? num: res;
        } else {
          m += n;
          m = m.slice(m.indexOf(n)+1);
          num = m.length;
        }
      }
      return res;
    };
    

    只需要对原字符串循环一次,就可以得到整个字符串中最大的子串长度。其实也比较好理解这个,想一想就能想到,只是我们一般不会考虑性能问题,是否存在浪费。我觉得这道题挺有意思,不难,但是提醒了我们编程人员,要深入去思考一个问题,不要只浮于表面。

    对于字符串有很多有意思的题目,这其中有著名的“KMP”算法,还有比较小众的江湖戏称的“马拉车”Manacher算法,每一个算法都能水一章,蕴含的都是数学原理,只能说学无止境,大家苦海自渡,各凭本事。

    相关文章

      网友评论

          本文标题:记一次简单的算法题

          本文链接:https://www.haomeiwen.com/subject/hdpjgctx.html