LeetCode_03 无重复最长子串

题目描述

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

示例

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

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

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

知识点

  • 字符串+子串
  • 集合
  • 滑动窗口

滑动窗口

滑动窗口是数组/字符串问题中常用的抽象概念。
窗口通常是在数组/字符串中由开始和结束索引定义的一系列元素的集合,即 [i, j)[i,j)(左闭,右开)。而滑动窗口是可以将两个边界向某一方向“滑动”的窗口。

可以把滑动窗口看成一个队列,向右滑动的时候,就是左边元素出队

子串

串中字符各不相同,则子串的个数为n(n+1)/2+1空串
如果串中有重复数字,则子字符串的个数为n(n+1)/2+1-重复个数

ublic char charAt(int index)
返回指定索引处的 char 值。索引范围为从 0 到 length() - 1。序列的第一个 char 值在索引 0 处,第二个在索引 1 处,依此类推,这类似于数组索引。
如果索引指定的 char 值是代理项,则返回代理项值。

解法

思路一 暴力破解

逐个检查所有的子字符串,看它是否不含有重复的字符。
需要枚举给定字符串的所有子字符串

 for (int i = 0; i < n; i++)
            for (int j = i + 1; j <= n; j++)

检查一个字符串是否有重复字符,我们可以使用集合。我们遍历字符串中的所有字符,并将它们逐个放入 set 中。在放置一个字符之前,我们检查该集合是否已经包含它。如果包含,我们会返回 false。循环结束后,我们返回 true。

//java
//代码注释来自于‘学习那些事’场外援助
public class Solution {
//返回长度
    public int lengthOfLongestSubstring(String s) {
        int n = s.length();
        int ans = 0;
        for (int i = 0; i < n; i++)//遍历整个字符串s
            for (int j = i + 1; j <= n; j++)
                if (allUnique(s, i, j)) ans = Math.max(ans, j - i);
                //allUnique 会返回一个字符串是否含有重复字符,如果有返回false,没有返回true,而字符串便是s从i位置到j位置的字符
                //故,如果当此子串没有喊有重复字符,其长度为j-i,math.max()则是,比较ans,和(j-i),并选择最大的返回,以保证ans时刻为最大的不重复字符串长度
        return ans;
    }
//检查一个字符串是否有重复字符
    public boolean allUnique(String s, int start, int end) {
        Set<Character> set = new HshSet<>();//?
        for (int i = start; i < end; i++) {
            Character ch = s.charAt(i);//charAt返回指定i处的 char 值
            if (set.contains(ch)) return false;//contains:判断集合是否包含ch
            set.add(ch);
        }
        return true;
    }
}

思路二 滑动窗口


#include <iostream>
#include <string>
    using namespace std;
    class Solution {
    public:
        // 查找是否重复,若有重复则返回重复数字下标,若没有重复,则返回-1
        int isRepeat(string s, string sub) {
            if (s.find(sub) == s.npos) {//没有重复;find返回字母sub在母串s中的位置(下标记录);npos表示不存在的位置
                return -1;
            }
            else {
                return s.find(sub);//重复数字下标
            }
        }
        int lengthOfLongestSubstring(string s) {//定义函数lengthOfLongestSubstring返回最大不重复的位数
            if (s.length() == 0 || s.length() == 1)//如果字符串长度是0或者1直接返回长度
                return s.length();
            int maxSize(1);//=1!全部重复的时候,长为1;用maxSize来记录不重复的字符串最长长度
            string substring = s.substr(0, 1);//substr(0,1)从0开始向后截取一位,代表着字符串的第一位
            for (int i = 1; i < s.length(); ++i) {
                string temp = s.substr(i, 1);//substr(i,1)从i开始截取一位
                int repeatPosit = isRepeat(substring, temp);//开始比较substr字符串和遍历第i字符串,如果有重复,返回数字下标
                if (repeatPosit == -1) {//如果没有重复
                    substring.append(temp);//append直接在substring后面添加字符串temp(从i开始截取一位)
                    if (substring.length() > maxSize) {//把substring的长度直接返回给maxSize
                        maxSize = substring.length();
                    }
                }
                else {//如果有重复,repeatPosit是重复数字下标
                    substring.append(temp);//append直接在substring后面添加字符串temp(从i开始截取一位)
                    substring = substring.substr(repeatPosit + 1);//更换无重复字符串;substr截取了重复字符数字下标repeatPosit+1一直到结尾
                }
            }
            return maxSize;
        }
    };

    int main() {
        Solution solution;
        string s("asdf123"), s1("pwwkew");
        cout << solution.lengthOfLongestSubstring(s) << endl;
        cout << solution.lengthOfLongestSubstring(s1) << endl;
    }


posted on 2020-02-17 23:16  琢磨亿下  阅读(235)  评论(0编辑  收藏  举报

导航