Leetcode#3 最大无重复字符子串

题目描述

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

  • 示例 1:
    输入: “abcabcbb”
    输出: 3
    解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
  • 示例 2:
    输入: “bbbbb”
    输出: 1
    解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
  • 示例 3:
    输入: “pwwkew”
    输出: 3
    解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
    请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。

算法思路

首先,可以用暴力的方法来解决这个问题,依次遍历所有可能的子串,但是最后一个样例会超时,因此要去除其中一些冗余的情况。
算法步骤如下:
(1)设下标i为当前查询字符串的末尾字符,直到i=s.size(),循环结束。
(2)设下标j为从当前查询字符串开始位置的下标s_index到下标为i的末尾字符的下标,依次遍历子串,通过IsUnique函数检查s[i]是否等于s[s_index~(i-1)]子串中的某一元素。若有重复元素,则直接返回该重复字符的下标i;若无重复元素,则返回-1;
(3)返回标志flag等于-1,则长度加1;否则,说明以s_index为起始位置、以i-1为结束位置的子串中无重复字符,其长度等于子串的尾端下标i减去返回的重复字符的下标flag,即len = i - flag,同时,flag位置之前无重复子串,flag与i为重复子串,因此再重复检测i后的元素与flag之前的元素是否相等是冗余的工作,无需用s_index++语句来循环遍历以i+1为结尾位置最长子串的开始位置,而可直接用s_index=flag+1来优化该程序
(4)用max_len存最大无重复字符子串的长度,每次子循环遍历结束进行判断,更新并记录最大长度。

代码实现

初步实现代码如下,但其结果却不尽如人意,因为不停地调用IsUnique函数,将字符串s作为参数传递,会消耗大量内存和时间。

class Solution {
public:
    int IsUnique(string s, int start, int pre){
        for(int i = start; i < pre; i++){
            if( s[pre] == s[i] ) return i;
            else continue;
        }
        return -1;
    }
    int lengthOfLongestSubstring(string s) {
        if(s == "") return 0;
        int len = 1;
        int max_len = 1;
        int s_index = 0;
        int flag;
        for(int i = 1; i < s.size(); i++){
            flag = IsUnique(s, s_index, i);
            if(flag == -1){
                len ++;
            }
            else{
                len = i - flag;
                s_index = flag + 1;
            }
            if(max_len < len) max_len = len;
        }
        return max_len;
    }
};

因此,将判断当前字符s[i]是否与子串s[s_index~(i-1)]有重复子串的函数IsUnique拆出,放入主函数中,代码执行速度提升很大。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s == "") return 0;
        int len = 1;
        int max_len = 1;
        int s_index = 0; //下边
        int i,j;
        for( i = 1; i < s.size(); i++){
            for( j = s_index; j < i; j++){
                if (s[j] == s[i]){
                    s_index = j + 1;
                    len = i - j;
                    break;
                } 
                else continue;
            }
            if(j == i){
                len ++;
            }
            if(max_len < len) max_len = len;
        }
        return max_len;
    }
};

以上代码中仍然不够简洁,如果s[i]与子串s[s_index~(i-1)]中无重复字符,无需在逐字符判断完后叠加len,即if(j == i){len ++;},若无重复元素,则长度应等于i - s_index+1.

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s == "") return 0;
        int max_len = 1;
        int s_index = 0;
        int i,j;
        for( i = 1; i < s.size(); i++){
            for( j = s_index; j < i; j++){
                if (s[j] == s[i]){
                    s_index = j + 1;
                    break;
                } 
                else continue;
            }
            if(max_len < i-s_index+1 ) max_len = i-s_index+1;
        }
        return max_len;
    }
};

运行结果

运行时间运行性能

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值