Leetcode No. 3 无重复字符的最长子串

Leetcode No. 3 无重复字符的最长子串

Problem

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

示例 1:
输入: “abcabcbb” 输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:
输入: “bbbbb” 输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:
输入: “pwwkew” 输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。

注意: 答案必须是子串的长度,“pwke” 是一个子序列,不是子串。

Solving

滑动窗口法
寻找最长的无重复字符串,我们按照索引顺序从左往右扫描,首先给它一个左边界left,和一个当前扫描位置i,将当前扫描的字符与滑动窗口中的字符串比较,如果不存在,i向右扩展,如果存在,左边界left移到重复字符上次出现位置的下一个位置。每次计算字符串的长度,并与历史最长字符串比较。这样一次遍历之后,我们就会得到了字符串的长度。
代码设计分析

  1. 需要一个left变量实时跟踪左边界,左边界一开始的位置是什么,当然是从0开始,不过窗口要完全包含不重复的字符串,要从-1开始,这样扫描到第0个字符时,长度1可以直接用下标减去左边界。
  2. 需要一层for循环去扫描字符。
  3. 判断当前字符是否已经出现。
  4. 记录每个字符最后出现的位置,因为在移动左边界时需要记录位置。
  5. 记录最长长度和当前长度的两个变量。
    (3和4可以一起实现,用一个结构去存放每个字符最后出现的位置,如果这个位置比左边界大,即在窗口内,同时将左边界移动。)

方法一: 所有ASCII字符存储
ASCII只有256个字符,我们可以用一个256的数组对应存储每种字符的结果。
方法二: 出现字符存储
将出现过的字符加入到哈希表中,记录每个字符对应最后出现的位置。

Code(c++)

方法一:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int left = -1;
        int noRepeat = 0;
        vector<int> asciimap (256, -1);
        for(int i = 0; i < s.length(); i++){
            left = max(left, asciimap[s[i]]);
            asciimap[s[i]] = i;
            noRepeat = max(noRepeat, i - left);
        }
        return noRepeat;
    }
};

执行用时 :8 ms
内存消耗 :10.1 MB

方法二:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int left = -1;
        int noRepeat = 0;
        map<char, int> strmap;
        map<char, int>::iterator iter;
        for(int i = 0; i < s.length(); i++){
            iter  = strmap.find(s[i]);
            if(iter == strmap.end()){
                strmap.insert(pair<char, int>(s[i], i));
            }
            else{
                left = max(left, iter->second);
                strmap[s[i]] = i;
            }
            noRepeat = max(noRepeat, i - left);
        }
        return noRepeat;
    }
};

执行用时 :20 ms
内存消耗 :10.2 MB

从空间复杂度来说,第二种方法理论上所需的空间会更少,但看结果,并没有更好,时间复杂度反而更高。所以对于这个题目,推荐方法一。如果把寻找最长不重复字符串改成寻找数组中最长不重复的数,那第一种方法就无法实现了,但第二种方法却不受影响,可见方法二的鲁棒性更好!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值