题目描述: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1: 输入: “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2: 输入: “bbbbb” 输出: 1 解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3: 输入: “pwwkew” 输出: 3 解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。 请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
方法1: 主要思路: (1)声明一个大小为128的数组,初始值置为-1,来直接对字符进行映射,映射为字符在字符串中出现的最靠后面的索引; (2)若当前字符对应的数组中的值是-1,则说明该字符之前需要判断的子字符串内没有出现过该字符,则直接将该数组值映射为对应的索引值 i,并同时将统计当前没有重复的字符的变量count自增1; (3)若当前字符对应的数组中的值非-1,则说明该字符在当前判断的子字符中出现过,则此时可以将该count进行判断保存到ret中,同时将该字符之前所在的索引位置,并将该位置之前(包括该位置)的字符对应的索引值全部置为-1,便于后面接着判断后续的新的子字符串,并将当前的字符对应的新的索引进行映射;
class Solution { public: int lengthOfLongestSubstring(string s) { if(s.size()<2) return s.size(); vector<int>dp(128,-1); int res=-1; int count=0; for(int i=0;i<s.size();++i){ if(dp[s[i]]!=-1){ //判断当前的字符串的不重复的长度是否是最大的,并进行保存 res=max(count,res); //获得当前字符之前对应的索引 int temp=dp[s[i]]; //将该子字符串中,该索引之前的出现过的字符对应的索引值置为初始的-1 //j=i-count,是为了获得当前的子字符串的首个字符所在的位置 for(int j=i-count;j<=temp;++j){ dp[s[j]]=-1; } //更新当前的字符对应的索引 dp[s[i]]=i; //获得新的子字符串的当前的长度 count=i-temp; } else{ //更新当前的需要判断的子字符串中没有重复的字符的个数 ++count; dp[s[i]]=i; } } return max(res,count); } };方法2:使用unordered_map配合双指针 主要思路: (1)其实思路和上述方法基本一致;
class Solution { public: int lengthOfLongestSubstring(string s) { unordered_map<char,int> mp; int right=0; int left=0; int max_len=0; while(right<s.size()){ char ch=s[right]; if(mp.count(ch)){ max_len=mp.size()>max_len?mp.size():max_len; while(left!=mp[ch]){ mp.erase(s[left++]); } ++left; mp[ch]=right; } else{ mp[ch]=right; } ++right; } return max(max_len,right-left); } };