给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
思路一:dp[i]表示以i开始的最长不包含重复的str[i]的字串,然后对于每一位j(i>j>=dp[i])判断dp[j]的位置确定最长不重复字串的位置。
这个办法速度较慢,差不多是O(n*n)的复杂度
class Solution {
public int lengthOfLongestSubstring(String s) {
int ans = 1;
int l = s.length();
if(l==0)
return 0;
int dp[] = new int [l];
for(int i=0;i<l;i++)
{
dp[i] = i;
for(int j=i+1;j<l;j++)
{
if(s.charAt(i)==s.charAt(j))
break;
dp[i] = j;
}
}
for(int i=0;i<l;i++)
{
int dir = dp[i];
for(int j=i+1;j<=dp[i];j++)
dir = Math.min(dir,dp[j]);
ans = Math.max(ans,dir-i+1);
}
return ans;
}
}
思路二:双端队列,维护当前最长字串的起始位置,用cnt统计字母个数,用数组模拟双端队列
class Solution {
public int lengthOfLongestSubstring(String s) {
int l = s.length();
int queue[] = new int [l+1];
int cnt[] = new int [300];
int rear,front;
rear = front = 0;
int ans = 0;
for(int i=0;i<l;i++)
{
if(cnt[s.charAt(i)]==0)
{
cnt[s.charAt(i)]++;
queue[++rear] = s.charAt(i);
}
else
{
while(true)
{
if(queue[(front+1)%(l+1)]==s.charAt(i))
{
cnt[s.charAt(i)]--;
front = (front+1)%(l+1);
break;
}
cnt[queue[(front+1)%(l+1)]]--;
front = (front+1)%(l+1);
}
cnt[s.charAt(i)]++;
queue[++rear] = s.charAt(i);
}
ans = Math.max(ans,(rear-front+l+1)%(l+1));
}
return ans;
}
}