问题
解答
1.暴力解法
算法
创建allUnique
函数,如果子字符串中的字符都是唯一的,它会返回 True
,否则会返回 False
。遍历字符串 s
的所有可能的子字符串,更新子串长度的最大值。
时间复杂度:O(N^3)
public class Solution
{
public int lengthOfLongestSubstring(String s)
{
int n = s.Length;
int ans = 0;
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j <= n; j++)
{
if (allUnique(s, i, j))
{ ans = Math.Max(ans, j - i); }
}
}
return ans;
}
public bool allUnique(String s, int start, int end)
{
HashSet<char> set = new HashSet<char>();
for (int i = start; i < end; i++)
{
char ch = s.ElementAt(i);
if (set.Contains(ch))
{ return false; }
set.Add(ch);
}
return true;
}
}
调试结果
2.滑动窗口
算法
i
,j
作为滑动窗口,遍历s
。如果s
中存在重复元素,i
后移一位,不存在则j
后移一位。
时间复杂度:O(N)
public class Solution
{
public int lengthOfLongestSubstring(String s)
{
int n = s.Length;
HashSet<char> set = new HashSet<char>();
int ans = 0, i = 0, j = 0;
while (i < n && j < n)
{
if (!set.Contains(s.ElementAt(j)))
{
set.Add(s.ElementAt(j++));
ans = Math.Max(ans, j - i);
}
else
{ set.Remove(s.ElementAt(i++)); }
}
return ans;
}
}
调试结果
该算法依旧超时,因为每个字符最多会被访问两次,执行步骤2n次。
3.优化滑动窗口
算法
如果出现重复元素,i无需后移一位,可直接跳过重复的子字符串。
时间复杂度:O(N)
public class Solution
{
public int lengthOfLongestSubstring(String s)
{
int n = s.Length, ans = 0;
Dictionary<char, int> dic = new Dictionary<char, int>();
for (int j = 0, i = 0; j < n; j++) {
if (dic.ContainsKey(s.ElementAt(j)))
{
i = Math.Max(dic[s.ElementAt(j)], i);
}
ans = Math.Max(ans, j - i + 1);
dic[s.ElementAt(j)]= j + 1;
}
return ans;
}
调试结果
c#永远在超时。。。
4.滑动窗口(python)
算法
时间复杂度:O(N)
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
n = len(s)
lookup = set()#储存无重复字符
left = ans = cur_len = 0
for i in range(n):
cur_len += 1
while s[i] in lookup:
lookup.remove(s[left])
left += 1
cur_len -= 1
if cur_len > ans:
ans = cur_len
lookup.add(s[i])
return ans
5.优化的滑动窗口(python)
算法
时间复杂度:O(N)
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
lookup = set()
n = len(s)
left = cur_len = ans = 0
for i in range(n):
cur_len += 1
while s[i] in lookup:#优化部分
lookup.remove(s[left])
left += 1
cur_len -= 1
if cur_len > ans:
ans = cur_len
lookup.add(s[i])
return ans
调试结果