问题#
【无重复字符的最长子串】给定一个字符串 s
,请你找出其中不含有重复字符的 最长子串 的长度。
解法一:滑动窗口 + 哈希表#
求最大长度#
Console.WriteLine(LengthOfLongestSubstring("abcabcbb"));
Console.WriteLine(LengthOfLongestSubstring("bbbbb"));
Console.WriteLine(LengthOfLongestSubstring("pwwkew"));
// 得到给定字符串中最大不重复的子字符串的长度
int LengthOfLongestSubstring(string str)
{
if (string.IsNullOrWhiteSpace(str)) return 0;
// 哈希表统计字符 str[right] 最后一次出现的索引
Dictionary<char, int> dic = new();
// 定义左指针(-1和0都可以),最大不重复子字符串的长度
int left = -1, res = 0;
// 不断地增加 right 扩大窗口
for (int right = 0; right < str.Length; right++)
{
//Console.WriteLine($"向右扩大区间: [{left}, {right}]");
var currentChar = str[right];
if (dic.ContainsKey(currentChar))
{
// 不断增加 left 缩小窗口,因为遇到了重复的字符,更新左指针为重复值的索引
left = dic[currentChar];
//Console.WriteLine($"向右缩小区间: [{left}, {right}]");
}
// 更新哈希表记录:当前遍历的字符最后一次在字符串中的出现的索引
dic[currentChar] = right;
// 更新结果:用右指针减去左指针,得到双闭区间内最大不重复子串的长度
// 再用 Max 函数取上轮 res 和本轮双指针区间 [left+1, right] 的宽度(即 right -left)中的最大值
res = Math.Max(res, right - left);
//Console.WriteLine($"------第 {right} 轮结果: {res}------{Environment.NewLine}");
}
return res;
}
求最大连续子串#
Console.WriteLine($"结果: {MaxChild("abca2f")}");
Console.WriteLine($"结果: {MaxChild("aabbcc")}");
Console.WriteLine($"结果: {MaxChild("aaaaa")}");
// 最长不重复子串(连续)
string MaxChild(string str)
{
if (string.IsNullOrWhiteSpace(str)) return string.Empty;
Dictionary<char, int> dic = new();
int left = 0;
string res = "";
// [left, right]
for (int right = 0; right < str.Length; right++)
{
// 当前遍历的字符
char currentChar = str[right];
// 是否已出现过,如果已出现就将左边界缩小为重复出现的索引
if (dic.ContainsKey(currentChar))
{
// 当包含时代表出现重复字符串,缩小窗口
left = dic[currentChar] + 1;
//Console.WriteLine($"update {currentChar} {right}");
// 更新索引
//dic[currentChar] = right;
dic.Clear();
}
dic[currentChar] = right;
// 更新结果
string sub = str.Substring(left, right - left + 1);
if (sub.Length > res.Length)
{
res = sub;
}
}
return res;
}
(待学习)解法二:动态规划 + 哈希表#
(看 K 神图解)