[LeetCode] Daily Practice 3 无重复字符的最长子串

原文链接

题目来源:
力扣(LeetCode)

题目描述 📑

给定一个字符串 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

提示:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成

解题思路 🤔

思路一 滑动窗口

首先审题,我们需要找出一个子串,最长且无重复,

让我们先从头开始,假设这个子串在字符串s中的index为head和tail,最开始 这两个index的值都为0,即head=tail=0;

  • tail开始递增遍历字符串,遍历的过程中,head和tail标识的子串不停的变长的,此时能不停获取到不同的子串.
  • 在tail递增的过程中,我们需要保证子串中没有重复对的字符,为了保证这点,我们需要对tail递增时新增的字符进行检查,检查head和tail代表的的子串中是否有该字符,有则移动head到子串中的字符index+1
  • 上述操作中我们会获得所有的无重复字符的子串,只要记录下最大长度,也就OK了

💡OK! 伪代码如下:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
    if(s.size() is 0 or 1)
	    return size;
    }
    int head =0, tail = 0;
    int max_len=1;
    for(int i=0;i<s.size()){
	    tail++;
	    查看子串是否含有 s[tail];
	    if(含有){
		    head=该字符在子串中index+1;
		}
		max_len= max{max_len,tail-head};
    }
    return max_len;
};

再进一步,做点优化:

当记录的最大长度已经大于s的长度减去head时,说明不会有更长的子串了,此时 直接返回max_len就可以了

伪代码如下:

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
    if(s.size() is 0 or 1)
	    return s.size();
    }
    int head =0, tail = 0;
    int max_len=1;
    for(int i=0;i<s.size();++i){
	    tail++;
	    查看子串是否含有 s[tail];
	    if(含有){
		    head=该字符在子串中index+1;
		    if(max_len>=s.size()-head){
			    return max_len;
			}
		}
		max_len= max{max_len,tail-head};
    }
    return max_len;
};

最多只做一个遍历

时间复杂度为:O(n)

思路一 Code

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        size_t size=s.size();
        if(0==size||1==size){
            return size;
        }
        size_t head = 0;
        int max_len=0;
        int cur_len=0;
        int tmp_index=0;
        std::map<char,size_t> sub_str;
        for(size_t tail = 0;tail<size;tail++){
            if(sub_str.find(s[tail])!=sub_str.end()){
                tmp_index=sub_str[s[tail]];
                if(tmp_index>=head){
                //当找到的字符的index在[head,tail)范围内才是重复的
                    head=tmp_index+1;
                    if(max_len>=size-head){
                        return max_len;
                    }
                }
            }
            sub_str[s[tail]]=tail;
            cur_len=tail-head+1;
            max_len=max_len>cur_len?max_len:cur_len;
        }
        return max_len;
    }
};

思路一 提交结果

提交3次结果如下

提交结果执行用时内存消耗用时击败内存击败
通过24 ms8.4 MB51.33%53.71%
通过16 ms8.3 MB70.72%54.68%
通过16 ms8.3 MB70.72%54.03%
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值