无重复字符的最长子串 给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。(LeetCode题目) 方法一:暴力法 方法二:滑动窗口

无重复字符的最长子串
给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。(LeetCode题目)
方法一:暴力法
方法二:滑动窗口

示例 1:

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

输入: "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。

请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

方法一:暴力法

  • 思路
    • 逐个检查所有的子字符串,看它是否不含有重复的字符。
  • 算法
    • 1.为了枚举给定字符串的所有子字符串,我们需要枚举它们开始和结束的索引。假设开始和结束的索引分别为 i 和 j。那么我们有 0≤i<j≤n。因此,使用 i从 0 到 n−1以及 j从 i+1到n这两个嵌套的循环,我们可以枚举出 s 的所有子字符串。

    • 2.判断索引从i~j的字串是否包含重复的字符,若不包含则更新最大长度.

没使用Hash表,判断字符处可使用Hash表来降低时间复杂度
class Solution {
public:
	int lengthOfLongestSubstring(string s) {
		if (s.size() == 0)
			return 0;
		int len = 1;
		for (int i = 0; i < s.size(); ++i) {
			bool f = true;
			for (int j = i + 1; j < s.size(); ++j) {
				if (!f) //已检测到当前重复字符,则从当前j~i+1的后续字符不必再检测
					break;
				for (int k = i; k < j; ++k) { //判断从i~j+1的字符是否存在重复
					if (s[k] == s[j]) {
						f = false;
						break;
					}
				}
				if (f)
					len = len > (j - i + 1) ? len : (j - i + 1); //更新最大长度
			}
		}
		return len;
	}
};

方法二:滑动窗口

  • 算法
    • 滑动窗口是数组/字符串问题中常用的抽象概念。 窗口通常是在数组/字符串中由开始和结束索引定义的一系列元素的集合,即 [i,j)(左闭,右开)。而滑动窗口是可以将两个边界向某一方向“滑动”的窗口。使用 Hash表将字符存储在当前窗口 [i,j)(最初 j=i)中。 然后我们向右侧滑动索引 j,如果它不在 Hash表中,我们会继续滑动 j。直到 s[j] 已经存在于 Hash表中。此时,我们找到的没有重复字符的最长子字符串将会以索引 i开头。
class Solution {
public:
    //以字符作为key,以下表作为value
	struct Hash_data {
		int key, value;
	};
	struct Hash_table {
		Hash_data** table;
		int width;
		Hash_table(int width) {
			this->width = width;
			table = (Hash_data**)malloc(sizeof(Hash_data*) * width);
			memset(table, NULL, sizeof(Hash_data*) * width);
		}
		int addr(int key) {
			return key % width;
		}
		void insert(char ch, int index) {
			Hash_data* data = new Hash_data();
			data->key = ch;
			data->value = index;
			int k = addr(ch);
			table[k] = data;
		}
		void remove(char ch) {
			int k = addr(ch);
			table[k] = NULL;
		}
		bool contain(char ch) {
			int k = addr(ch);
			Hash_data* data = table[k];
			if (data)
				return true;
			else
				return false;
		}

	};
	int lengthOfLongestSubstring(string s) {
		int maxlen = 0;
		int len = s.size();
		int i, j;
		i = j = 0;
		Hash_table table(256);//初始化Hash表大小为256(char型大小)
		while (i<len&&j<len)
		{
			if (table.contain(s[j])) {
				table.remove(s[i]);
				i++;
			}
			else {
				table.insert(s[j], j);
				maxlen = maxlen > (j - i+1) ? maxlen : (j - i+1);
				j++;
			}
				
		}
		return maxlen;
	}
};