力扣真题
力扣第3题详解(多方法)
题目链接:3. 无重复字符的最长子串
题目描述
给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。
题目分析:
①可以直接使用暴力破解的方法,使用哈希进行遍历当出现次数大于1的时候结束循环
②使用滑动窗口算法破解
③使用滑动窗口&哈希 共同破解
解决方案:
【暴力破解】(超时)
int check(char *s, int start, int len) {
char hash[128] = {0};//使用哈希遍历
for (int i = start; i < start + len; ++i) {
++hash[s[i]];
if (hash[s[i]] > 1) {//出现次数大于一次结束循环
return 0;//hash遍历数组 如果出现重复的就返回0结束
}
}
return 1;
}
//lengthOfLongestSubstring1 暴力解法
int lengthOfLongestSubstring1(char *s) {
int n = strlen(s);
//先假设全部都是不重复的,然后len--循环找到重复的消去
for (int len = n; len >= 1; --len) {//外层循环决定要循环的子串长度,从最长开始
int end = n - len;
for (int start = 0; start <= end; ++start) {//内存循环决定每次循环的起始位置和结束位置,从最短开始
if (check(s, start, len)) {//检测符合条件的长度
return len;
}
}
}
return 0;
}
【滑动窗口】解法1
int lengthOfLongestSubstring2(char *s) {
int left = 0;
int right = 0;
int max = 0;
while (s[right] != '\0') {//从右 滑动开始
int flag = -1;//标志位,left到right中有无重复字符
for (int i = left; i < right; ++i) {//i从左到右遍历
if (s[i] == s[right]) {//若存在相同字符
flag = i + 1; //标志位+1 跳出循环
break;
}
}
if (flag != -1) {//在窗口内存在相同字符
left = flag;//移动left到相同字符的下一位,左滑动
}
++right;//右滑动
max = max < right - left ? right - left : max;
}
return max;
}
【滑动窗口】解法2
int lengthOfLongestSubstring3(char *s) {
int left = 0;
int right = 0;
int max = 0;
while (s[right] != '\0') {//从右 滑动开始
//标志位使用strchr返回首次出现位置.(str:地址类型 指针)
int pos = strchr(s + left, s[right]) - s;
if (pos != right) {//首次出现位置与当前位置不同说明第二次出现
left = pos + 1;
}
++right;//右滑动
max = max < right - left ? right - left : max;
}
return max;
}
【滑动窗口&哈希】
int lengthOfLongestSubstring4(const char *s) {
int left = 0;
int right = 0;
int max = 0;
int hash[128];
memset(hash, -1, sizeof(hash));
while (s[right] != '\0') {//从右 滑动开始
if(left<=hash[s[right]]){
left=hash[s[right]]+1;
}
hash[s[right]]=right;//给首次出现的字符赋值,当第二次出现时同下标的值已有且>=0
++right;//右滑动
max = max < right - left ? right - left : max;
}
return max;
}