1.无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。
示例 1:
输入: "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。
示例 2:
输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。
示例 3:
输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters
思路:定义一个数组,用于记录26个英文字母出现时的下标。从头到尾遍历字符串,如果下标小于0(未出现过)或两次重复出现字母的下标大于当前最长长度,就更新最长长度;否则,比较当前最长长度和总最长长度;更新当前最长长度以及字母出现的位置。
输入含空格时:
class Solution { public: int lengthOfLongestSubstring(string s) { // 哈希集合,记录每个字符是否出现过 unordered_set<char> occ; int n = s.size(); // 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动 int rk = -1, ans = 0; // 枚举左指针的位置,初始值隐性地表示为 -1 for (int i = 0; i < n; ++i) { if (i != 0) { // 左指针向右移动一格,移除一个字符 occ.erase(s[i - 1]); } while (rk + 1 < n && !occ.count(s[rk + 1])) { // 不断地移动右指针 occ.insert(s[rk + 1]); ++rk; } // 第 i 到 rk 个字符是一个极长的无重复字符子串 ans = max(ans, rk - i + 1); } return ans; } };
输入只有字母时:
class Solution { public: int lengthOfLongestSubstring(string s) { int curLength=0; int maxLength=0; if(s.length()==0) return 0; int* position=new int[26];//存储每个字符上次出现在字符串中位置的下标 for(int i=0;i<26;i++) { position[i]=-1; } for(int i=0;i<s.length();i++) { int preIndex=position[s[i]-'a']; if(preIndex<0||i-preIndex>curLength) { curLength++;//没出现过或d>f(i-1),f(i)=f(i-1)+1; } else { if(curLength>maxLength) { maxLength=curLength;//出现过,就与最终结果做对比 } curLength=i-preIndex;//f(i)=d; } position[s[i]-'a']=i;//更新位置 } if(curLength>maxLength) { maxLength=curLength; } delete[] position; return maxLength; } };