[贪心|字符串] leetcode 3 无重复字符的最长子串

[贪心|字符串] leetcode 3 无重复字符的最长子串

1.题目

题目链接
给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
示例1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3

示例2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1

示例3:

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

2.分析

2.1.子串与子序列

子串要求必须是连续的,而子序列不一定连续。例如在例3中,pwwkew的一个子序列是pwke,其并不连续。

2.2.如何判断“无重复”

本题的一个核心需要解决的问题在于如何判断一个子串无重复字符。
可以借助哈希表(hashset)这一数据结构,对于某个给定的字符串str,我们将str内每个字符逐个加入hashset中,利用count方法来判断当前字符是否已经在字符串中出现过。

for (int i = 0; i < n; i++) {  //n为字符串长度
	//遍历字符串直到出现重复字符
    while (j + 1 < n && !_set.count(s[j + 1])) { 
        _set.insert(s[j + 1]);
        j++;
    }
}

2.3.如何获取子串

对于字符串str,子串substr(i, j)即为str中第i个到第j个之间的所有字符组成的字符串。因此,我们先解决i如何获取的问题。
i可以直接从0遍历到n-1(n为字符串长度)
从代码实现的角度来讲,子串(i + 1, j)可以通过删除子串(i, j)左侧的一个字符来实现。

for (int i = 0; i < n; i++) {
    if (i != 0) {
        _set.erase(s[i - 1]);
    }
}

而对于j,由于本题目的为“寻找无重复子串”,因此可以让右指针j右移,直到发现有重复字符为止 (见2.2)

3.代码

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_set<char> _set;  //存储当前子串内字符
        int n = s.size();
        int j = -1;  //子串右指针j
        int ans = 0;
        for (int i = 0; i < n; i++) {
            //左指针i右移,删除原串最左侧字符形成新串
            if (i != 0) { 
                _set.erase(s[i - 1]);
            }
            //右指针j向右移动直到发现重复字符为止
            while (j + 1 < n && !_set.count(s[j + 1])) {
                _set.insert(s[j + 1]);
                j++;
            }
            //子串长度为j - i + 1
            ans = max(ans, j - i + 1);
        }
        return ans;
    };
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值