3. Longest Substring Without Repeating Characters

题目:

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given "abcabcbb", the answer is "abc", which the length is 3.

Given "bbbbb", the answer is "b", with the length of 1.

Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring"pwke" is a subsequence and not a substring.

就是找到一个字符串里不含重复字符的最大子串并返回其长度。


算法1:

比较简单直接的办法就是从字符串的每一个字符开始判断,直到遇到重复字符为止,并从这一系列结果中选取最长的作为结果。在下面的代码中,整形数组ch用于记录在每一次判断中该字符是否出现过,不用bool数组是因为这样的话每次判断前都要清空,而用int数组的话则只需为每次判断设定一个标识符f,假设在某次判断中字符c出现过一次,则ch[c] = f。

时间复杂度貌似不太好求?虽然应该是属于O(n)级别的,因为第二层循环最多循环129次。在Leetcode中该算法提交样例测试的Run Time为36ms。

class Solution {
public:
	int lengthOfLongestSubstring(string s) {
		int l = s.size();
		int *ch = new int[128];
		for (int i = 0; i < 128; i++)
			ch[i] = 0;
		int res = 0, cnt = 0, f = 1;
		for (int i = 0; i < l; i++) {
			for (int j = 0; j < l - i; j++) {
				if (ch[s[i + j]] != f) {
					ch[s[i + j]] = f;
					cnt++;
				}
				else {
					cnt = 0;
					f++;
					break;
				}
				if (res < cnt) res = cnt;
			}
		}
		return res;
	}
};

但实际上我们可以发现,假设有一个字符串为abcdefghcikm,若按照算法1,则第一次判断abcdefghc,满足要求的子串长度为8,第二次判断bcdefghc,满足要求的子串长度为7,第三次判断cdefghc,满足要求的子串长度为6,第四次判断defghcikm,满足要求的子串长度为9。可以看到,第二次和第三次判断是没有必要的,因为得出的子串长度必然小于第一次判断,而第四次判断中,第二个c之前的defgh也没有必要再计算一次。避免这两类不必要的判断后,得出算法2。


算法2:

int数组idx用于记录各种字符在字符串s中的下标,start用于记录当前子串的起始位置,再看刚刚的例子,第一次判断abcdefghc,遇到重复字符,停止,此时cnt = 8,因下一次判断我们直接从“i”开始,所以两个重复字符c之间的defgh保留,再加上第二个c,得cnt=6,然后将start设为3,即d的下标,表示下一次判断的子串的起始位置是d。第二次判断的子串为(defghc)ikm,括号内的是已经遍历了的字符,因此第二次只需判断ikm是否重复。

显然,算法2只需遍历一次字符串,则时间复杂度为O(n)。在Leetcode中该算法提交样例测试的Run Time为12ms,明显优于算法1。

class Solution {
public:
	int lengthOfLongestSubstring(string s) {
		int l = s.size();
		int *idx = new int[128];
		int res = 0, cnt = 0, start = 0;
		for (int i = 0; i < 128; i++)
			idx[i] = -1;
		for (int i = 0; i < l; i++) {
			if (idx[s[i]] < start) {
				idx[s[i]] = i;
				cnt++;
			}
			else {
				cnt -= (idx[s[i]] - start);
				start = idx[s[i]] + 1;
				idx[s[i]] = i;
			}
			if (res < cnt) res = cnt;
		}
		return res;
	}
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值