LeetCode题库第三题,无重复字符的最长字符(C++)

第三题,无重复字符的最长字符

题目描述:

给定一个字符串s,请你找出其中不含有重复字符的最长子串的长度。

示例1:

输入:s=”abcabcbb”;

输出:3

解释:因为无重复字符的最长子串是“abc”,所以其长度为3。

示例2:

输入:s=”bbbbb”;

输出:1

解释:因为无重复字符的最长子串是“b”,所以其长度为1。

示例3:

输入:s=“pwwkew”

输出:3

解释:因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

解题思想1:

假定一个窗空间。这个窗最后的长度就是就是该字符串中最长子串的长度。

我们假定整个字符串有n位,由于我们要找到最大的无重复子串,所以我们的窗的长度由大到小进行遍历。

  1. 先假设窗的长度为n位

我们判断这个n位的字符串中是否有重复的字符,若没有,则程序即可直接输出该窗的长度。

若有,则将窗的长度减一位,进入第二步。

  1. 现在窗的长度为n-1位

我们就先判断n位字符的前n-1位是否有重复的字符,若没有,程序即可直接输出该窗的长度,n-1。若有重复的字符,则代表前n-1位不符合题设条件,我们将窗口移动到后n-1位,重复上述过程。如果还不满足,则再将窗长度减少一位,重复第三步过程,直到找到符合条件的长度作为结果输出

在这里面我们就需要一个能够判断字符串中是否有重复字符的函数,于是我们在类中重新定义了一个函数。

在该函数中,主要利用两个循环对该字符串进行判断。取出字符串中的第一个字符,跟后续的所有字符进行比较,一旦发现有重复的即可退出函数,如果没有发现重复的,则取第二个字符,再跟后续的字符进行比较。如果所有的字符都判断完毕依然没有发现重复,那么该字符串则没有重复。

在提交该算法后,显示时间超时,说明该算法的时间复杂度太高。

于是我们提出了改进算法。

解题思想2:

在解题思想2中我们依然采用了上述构建的判断字符串是否重复的函数。

与上述思想不同,我们先构建一个长度为1的窗。

算法的思想为,我们每一次将窗后面一位加入到窗内,判断后一位中是否有重复的字符在现有的窗中,若有,则维持窗长度不变,将窗整体往右平移一位。若没有则将窗长度直接增加一位。直到窗的最后一位到达字符串的末端就停止循环。

举例说明:

假设有一字符串“abcabcde”

  1. 初始设置窗长度为1;
  2. 截取字符串为“a”,将后一个字符加入进来,即为“ab”,经函数验证“ab”为无重复字符串,于是最大无重复字符串的长度增加一个,变为2,窗也向右增加一位,变为“ab”
  3. 继续试探下一位字符,即“abc”,经函数验证也为无重复字符串,重复2步过程,窗长度变为3位,最大无重复字符串长度也变为3位。
  4. 继续试探下一位字符:“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;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值