先说结论:自己没做出来,抄的别人的。
https://www.cnblogs.com/ariel-dreamland/p/8668286.html
给定一个字符串,找出不含有重复字符的最长子串的长度。
示例:
给定 "abcabcbb"
,没有重复字符的最长子串是 "abc"
,那么长度就是3。
给定 "bbbbb"
,最长的子串就是 "b"
,长度是1。
给定 "pwwkew"
,最长子串是 "wke"
,长度是3。请注意答案必须是一个子串,"pwke"
是 子序列 而不是子串。
JAVA 滑动窗口
class Solution {
public int lengthOfLongestSubstring(String s) {
// 哈希集合,记录每个字符是否出现过
Set<Character> occ = new HashSet<Character>();
int n = s.length();
// 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
int rk = -1, ans = 0;
for (int i = 0; i < n; ++i) {
if (i != 0) {
// 左指针向右移动一格,移除一个字符
occ.remove(s.charAt(i - 1));
}
while (rk + 1 < n && !occ.contains(s.charAt(rk + 1))) {
// 不断地移动右指针
occ.add(s.charAt(rk + 1));
++rk;
}
// 第 i 到 rk 个字符是一个极长的无重复字符子串
ans = Math.max(ans, rk - i + 1);
}
return ans;
}
}
class Solution {
public int lengthOfLongestSubstring(String s) {
int length = s.length();
int left = 0, right = 0;
int result = 0;
Set<Character> set = new HashSet<>();
for (; left < length; left++) {
while (right < length && !set.contains(s.charAt(right))) {
set.add(s.charAt(right));
right++;
}
result = Math.max(result, right - left);
set.remove(s.charAt(left));
}
return result;
}
}
7-24更新,自己在剑指offer上又看到这个题目了,重新做了一下:
思路:
动态规划,
建立一个数组当哈希表用。本来用pos[26],结果测试用例中有很多非英语字符,所以用pos[256]
分两种情况
- 没有见过这个字母,那么就对dp[i]=dp[i-1]+1;
- 之前遇到过这个字母,又分两种情况:
- (1)距离上一个字母的距离大于dp[i-1]。比如arabcacfr----检测到r,发现其实不影响状态方程:dp[i]=dp[i-1]+1
- (2)距离上一个字母的距离小于等于dp[i-1]。比如arabcacfr----检测到a,考虑等于的情况,必须把dp[3]设置为距离2,不能再用状态方程了。
坑:
字符串为0,以后这个要最先考虑。
有其他的字符,pos数组必须256大小。
数组必须初始化为-1,因为0是存在的。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
if(s.size()==0)
return 0;
int dp[50000]={0};
int pos[256]={0};
for(int i=1;i<256;i++)
pos[i]=-1;
pos[s[0]]=0;
dp[0]=1;
int maxlen=1;
for (int i=1;i<s.size();i++)
{
if (pos[s[i]]==-1||i-pos[s[i]]>dp[i-1])
{
dp[i]=dp[i-1]+1;
maxlen=max(dp[i],maxlen);
}else {
dp[i]=i-pos[s[i]];
maxlen=max(dp[i],maxlen);
}
pos[s[i]]=i;
}
return maxlen;
}
};
调试代码:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int lengthOfLongestSubstring(string s) {
if(s.size()==0)
return 0;
int dp[50000]={0};
int pos[256]={0};
for(int i=1;i<256;i++)
pos[i]=-1;
pos[s[0]]=0;
dp[0]=1;
int maxlen=1;
for (int i=1;i<s.size();i++)
{
if (pos[s[i]]==-1||i-pos[s[i]]>dp[i-1])
{
dp[i]=dp[i-1]+1;
maxlen=max(dp[i],maxlen);
}else {
dp[i]=i-pos[s[i]];
maxlen=max(dp[i],maxlen);
}
pos[s[i]]=i;
}
return maxlen;
}
int main()
{
string str("abcabcbb");
int res=lengthOfLongestSubstring(str);
cout<<res<<endl;
return 0;
}
思路:
循环字符串,找下一个相同的字符,计算间隔。写了半天发现是错的。。。凉凉因为aab都过不了。。。
暴力搜索:
循环所有字符串,两个循环,然后还要再判断这个里面重复不。用set来做。最后超时了。凉凉。。。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
set<char> myset;
int res=0;
for(int i=0;i<s.size()-1;i++)
for(int j=0;j<s.size();j++){
string s1(s,i,j-i);
for(int k=0;k<s1.size();k++){
if(!myset.insert(s1[k]).second)
break;
}
if(res<myset.size())
res=myset.size();
myset.clear();
s1.clear();
}
return res;
}
};
优化了一下,让i从0到n-1;j从n开始往前走j--,如果发现不重复的子串,就没有必要再往前走了。但是还是超时了。。。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
set<char> myset;
int res=0;
int flag=0;
int success=0;
for(int i=0;i<s.size()-1;i++){
success=0;
for(int j=s.size();j>i;j--){
string s1(s,i,j-i);
for(int k=0;k<s1.size();k++){
if(!myset.insert(s1[k]).second)
{
flag=1;//insert fail -- substring has same character
break;
}
}
if(!flag){//insert success for substring whose characters are all different
if(res<myset.size())
res=myset.size();
success=1;//no need to decrease j
flag=0;
myset.clear();
s1.clear();
break;
}
flag=success=0;
myset.clear();
s1.clear();
}
}
return res;
}
};
又不甘心,再优化,感觉myset插入的时候太耗时间,改为手动排序子字符串,结果还是超时啊。。。
class Solution {
public:
int lengthOfLongestSubstring(string s) {
// set<char> myset;
int res=0;
int flag=0;
int success=0;
for(int i=0;i<s.size()-1;i++){
success=0;
for(int j=s.size();j>i;j--){
string s1(s,i,j-i);
sort(s1.begin(),s1.end());
for(int k=0;k<s1.size()-1;k++){
if(s1[k]==s1[k+1])
flag=1;
}
if(!flag){//insert success for substring whose characters are all different
if(res<s1.size())
res=s1.size();
success=1;//no need to decrease j
flag=0;
// myset.clear();
s1.clear();
break;
}
flag=success=0;
//myset.clear();
s1.clear();
}
}
return res;
}
};
心态崩了。。。去看看人家的吧。
这个博客讲的太好: