无重复字符的最长子串

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

示例 1:

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

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

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-substring-without-repeating-characters
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这道题看到后第一反映是采用快慢指针进行遍历,也就是最原始的暴力破解法。
1.暴力破解:采用left,right两个指针来遍历整个字符串,在每次循环移动left时都需要遍历一遍从left到right之间的字符是否有重复,没有则right++,知道遇见重复或者right到头为止。浪费时间最多的就在于查找重复字符串的部分。这里还可以再加一个对right== size -1的判断跳出循环,进一步优化。
2.类似暴力破解:和第一种方法相比就是采用了c++的hash表,大大的缩短了查找重复字符的时间。其余部分和第一种方法几乎一样。也是两层循环不断更新left和right,循环次数相同。还是得益于高级语言的特性,否则自己写个hash还是很有难度的。
3. 优化版暴力破解:和前两种方法采用的相同的遍历原理,但是采用了map,记录了字符的同时也记录了字符的位置,采用临时变量记录当前的字符串长度,然后和两个重复字符之间的长度取最小值,来不断求取字符串的长度(使用abba推导一下即可明白求取原理)。这种方法只需要一层循环,相比与第二种方法减少了外层循环的一些操作以及查询hash表的次数。

这道题与另一道题有很大的相似之处,背后的原理很相似:
https://blog.youkuaiyun.com/weixin_41777654/article/details/124775630?spm=1001.2014.3001.5502

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
#if 0
        int max_len = 0;
        int left = 0, right = 0;
        int matched = 0;
        while (left < s.size() && max_len < (s.size() - left))
        {
            while(right < s.size())
            {
                for (int i = left; i < right; i++) // 如果只有一个字符for循环不执行, matched = 0, max_len = 1
                {
                    if (s[i] == s[right])
                    {
                        matched = 1;
                    }
                }
                if (matched == 0)
                {
                    max_len = max(right - left + 1, max_len);
                    right++;
                }
                else
                {
                    matched = 0;
                    break;
                }
            }
            left++;
        }
        return max_len;
#endif
#if 0
        int max_len = 0;
        unordered_set<char> child_str;
        int left = 0, right = 0;

        while ((left < s.size()) && (max_len < (s.size() - left)))
        {
            if (left != 0)
            {
                child_str.erase(s[left - 1]);
            }

            while (right < s.size() && !child_str.count(s[right]))
            {
                child_str.insert(s[right]);
                max_len = max(right - left + 1, max_len);
                right++;
            }

            left++;
        }
        return max_len;
#endif
        int len = s.size();
        //滚动数代替dp数组
        int res = 0, temp = 0;
        unordered_map<char, int> hashtable;
        for (int i = 0; i < len; i++)
        {
            temp++;
            if (hashtable.count(s[i]) != 0)
            {
                temp = min(temp, i - hashtable[s[i]]);
            }
            hashtable[s[i]] = i;
            res = max(res, temp);
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值