LeetCode题库3:无重复字符的最长子串

LeetCode题库3:无重复字符的最长子串

思路

最容易想到的是两层循环,第一层循环依次选择子串的起始字符;第二层循环检查从这个起始字符开始,最多几个字符之后会出现重复字符。
但是,这样的思路显然不会是最有效率的算法,时间复杂度为O(n2),空间复杂度为O(1)。
简化的方法之一是使用哈希表,将查找的效率提高到O(1),但是我还没看懂哈希表是怎么做到的(捂脸.jpg),所以我希望能换一种更容易理解的算法。
然后我在和无敌小星星散步的时候和他讨论了一下这个问题,回家之后实现了这个算法。

方法大概是这样的:一个指针指向子串头,一个指针指向子串尾,再用一个数组保存ASCII码为n的字符上次在什么地方出现的。
最重要的事情是保证子串中没有重复字符。
在执行过程中,指向子串尾的指针每次循环+1;如果最后一个字符发现是重复字符,就把头指针向前移动,直到字符串里没有重复字符(当然,这个“直到”不是通过循环实现的)。期间要记得对比记录一下max_len和len就行啦

代码

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int len = 0;        //当前子串长度
        int max_len = 0;    //最长子串长度,会用于输出
        int head = 0;       //记录子串从哪个字符开始
        int rep[128];       //记录上一次某个字符出现的位置
        for(int i = 0 ; i< 128; i ++){
            rep[i] = -1;    //初始化为-1
        }
        int sSize = s.size();   //字符串的长度
        for (int i = 0 ; i < sSize; i++){      //循环的i其实是字符串末尾
            char ch = s[i];
            if(rep[ch] == -1 || rep[ch] < head){        //如果这个字符没有出现过,或者最近一次出现是在head指针前面
                rep[ch] = i;            //  将字符出现的位置记录下来
                len ++;
                if(len > max_len){
                    max_len = len;      
                }
            }else{                      // 如果子串中出现了重复字符
                head = rep[ch] + 1;     // rep[ch]中保存的就是重复字符的位置。将head移到重复字符之后,这样剩余子串中就没有重复字符了
                len = i - head + 1;
                rep[ch] = i;
            }
            // printf("i = %d ; ch = %c ; head = %d ; len = %d ; max_len = %d\n",i,ch,head,len,max_len);
        }
        if(len > max_len){     //更新max_len
            max_len = len;
        }
        return max_len;
    }
};

运行结果

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值