第三题,无重复字符的最长字符
题目描述:
给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。
示例1:
输入:s=”abcabcbb”;
输出:3
解释:因为无重复字符的最长子串是“abc”,所以其长度为3。
示例2:
输入:s=”bbbbb”;
输出:1
解释:因为无重复字符的最长子串是“b”,所以其长度为1。
示例3:
输入:s=“pwwkew”
输出:3
解释:因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。
解题思想1:
假定一个窗空间。这个窗最后的长度就是就是该字符串中最长子串的长度。
我们假定整个字符串有n位,由于我们要找到最大的无重复子串,所以我们的窗的长度由大到小进行遍历。
- 先假设窗的长度为n位
我们判断这个n位的字符串中是否有重复的字符,若没有,则程序即可直接输出该窗的长度。
若有,则将窗的长度减一位,进入第二步。
- 现在窗的长度为n-1位
我们就先判断n位字符的前n-1位是否有重复的字符,若没有,程序即可直接输出该窗的长度,n-1。若有重复的字符,则代表前n-1位不符合题设条件,我们将窗口移动到后n-1位,重复上述过程。如果还不满足,则再将窗长度减少一位,重复第三步过程,直到找到符合条件的长度作为结果输出
在这里面我们就需要一个能够判断字符串中是否有重复字符的函数,于是我们在类中重新定义了一个函数。
在该函数中,主要利用两个循环对该字符串进行判断。取出字符串中的第一个字符,跟后续的所有字符进行比较,一旦发现有重复的即可退出函数,如果没有发现重复的,则取第二个字符,再跟后续的字符进行比较。如果所有的字符都判断完毕依然没有发现重复,那么该字符串则没有重复。
在提交该算法后,显示时间超时,说明该算法的时间复杂度太高。
于是我们提出了改进算法。
解题思想2:
在解题思想2中我们依然采用了上述构建的判断字符串是否重复的函数。
与上述思想不同,我们先构建一个长度为1的窗。
算法的思想为,我们每一次将窗后面一位加入到窗内,判断后一位中是否有重复的字符在现有的窗中,若有,则维持窗长度不变,将窗整体往右平移一位。若没有则将窗长度直接增加一位。直到窗的最后一位到达字符串的末端就停止循环。
举例说明:
假设有一字符串“abcabcde”
- 初始设置窗长度为1;
- 截取字符串为“a”,将后一个字符加入进来,即为“ab”,经函数验证“ab”为无重复字符串,于是最大无重复字符串的长度增加一个,变为2,窗也向右增加一位,变为“ab”
- 继续试探下一位字符,即“abc”,经函数验证也为无重复字符串,重复2步过程,窗长度变为3位,最大无重复字符串长度也变为3位。
- 继续试探下一位字符:“abca”,此时不满足无重复条件,即窗长度不增加,窗整体向右平移一位,即窗内字符变为“bca”。
重复上述步骤,直到窗中最后一位变为字符串的最后一位,返回最大的无重复字符串长度。
代码如下:
解题思想1:
#include<iostream>
using namespace std;//使用命名空间std
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int i = 0;
int t = 0;
int judge = 0;
int sublength = 1;
string temp;
int length = s.length();
if (length == 0)
return 0;
for (t = length; t > 0; t--) {
for (i = 0; i < length - t + 1; i++) {
temp = s.substr(i, t);
judge = repeat(temp);
if (judge) {
sublength = t;
break;
}
}
if (judge)
break;
}
return sublength;
}
int repeat(string s) {
int length = s.length();
int i = 0;
int j = 0;
int judge = 1;
for (i = 0; i < length; i++) {
for (j = 1+i; j < length; j++) {
if (s[i] == s[j]) {
judge = 0;
break;
}
}
if (judge == 0)
break;
}
return judge;//judge=1代表没有重复,judge=0代表有重复
}
};
int main(){
string s1 = "";
Solution k;
int g=k.lengthOfLongestSubstring(s1);
cout << "最大长度为"<<g;
return 0;
}
解题思想2:
#include<iostream>
using namespace std;//使用命名空间std
class Solution {
public:
int lengthOfLongestSubstring(string s) {
int length = s.length();
int i = 0; int j = 0;
int max_length = 0;
string temp;
string temp1;
if (length == 0)
return max_length;
int window_length = 1;
max_length = 1;
while (j!=length-1) {
temp = s.substr(i, window_length);
if (window_length == length) {
max_length = window_length;
break;
}
if (repeat(s.substr(i, window_length + 1))) {
window_length++;
if (window_length > max_length)
max_length = window_length;
j = i + window_length - 1;
}
else {
i++;
j = i + window_length - 1;
}
}
return max_length;
}
int repeat(string s) {
int length = s.length();
int i = 0;
int j = 0;
int judge = 1;
for (i = 0; i < length; i++) {
for (j = 1 + i; j < length; j++) {
if (s[i] == s[j]) {
judge = 0;
break;
}
}
if (judge == 0)
break;
}
return judge;//judge=1代表没有重复,judge=0代表有重复
}
};
int main(){
string s1 = "";
Solution k;
int g=k.lengthOfLongestSubstring(s1);
cout << "最大长度为"<<g;
return 0;
}