京东测试开发面试题:无重复字符的最长子串

题目描述:

无重复字符的最长子串问题是一个经典的字符串处理问题,旨在找到给定字符串中最长的不包含重复字符的子串。

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

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

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

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

示例4:输入: s = ""输出: 0

解法1:暴力法

思想:通过穷举所有可能的子串,检查每一个子串是否含有重复字符,记录最长的有效子串长度。

def length_of_longest_substring(s: str) -> int:

def is_unique(sub: str) -> bool:

return len(sub) == len(set(sub)) # 检查子串是否唯一


max_length = 0 # 记录最长子串的长度

for i in range(len(s)):

for j in range(i + 1, len(s) + 1):

if is_unique(s[i:j]): # 如果子串是唯一的

max_length = max(max_length, j - i) # 更新最长长度

return max_length


# 示例用法

print(length_of_longest_substring("abcabcbb")) # 输出3

时间复杂度:O(n²)

  • 解释:外层循环遍历字符串的每个字符,内层循环遍历所有可能的子串。对于每个子串,检查其是否包含重复字符的操作需要 O(k) 的时间,其中 k 是子串的长度。因此,整体复杂度为 O(n²)。

空间复杂度:O(1)

  • 解释:只使用了常量空间来存储变量,没有使用额外的数据结构。

解法2:滑动窗口法

思想:使用两个指针来表示当前的子串范围,利用一个哈希集(或字典)来检查字符的重复情况。

def length_of_longest_substring(s: str) -> int:

char_set = set() # 用于存储当前子串的字符

left = 0 # 左指针

max_length = 0 # 记录最长子串的长度


for right in range(len(s)):

# 如果右边的字符已经在子串中,则移动左指针

while s[right] in char_set:

char_set.remove(s[left]) # 移除左指针指向的字符

left += 1

char_set.add(s[right]) # 添加右边的字符

max_length = max(max_length, right - left + 1) # 更新最长长度


return max_length


# 示例用法

print(length_of_longest_substring("abcabcbb")) # 输出3

时间复杂度:O(n)

  • 解释:每个字符最多被访问两次(一次由右指针访问,一次由左指针访问)。因此,整体复杂度为 O(n)。

空间复杂度:O(min(n, m))

解法3:使用哈希表

思想:利用哈希表记录字符的最后出现位置,减少了对字符的重复遍历。

def length_of_longest_substring(s: str) -> int:

char_index = {} # 字符及其最后出现位置的字典

max_length = 0 # 记录最长子串的长度

left = 0 # 左指针


for right in range(len(s)):

if s[right] in char_index and char_index[s[right]] >= left:

left = char_index[s[right]] + 1 # 更新左指针

char_index[s[right]] = right # 更新字符的最后出现位置

max_length = max(max_length, right - left + 1) # 更新最长长度


return max_length


# 示例用法

print(length_of_longest_substring("abcabcbb")) # 输出3

时间复杂度:O(n)

  • 解释:每个字符最多被访问两次,因此整体复杂度为 O(n)。

空间复杂度:O(min(n, m))

  • 解释:与方法 2 类似,最坏情况下,空间复杂度取决于字符集的大小。

解法4:优化的滑动窗口法

def length_of_longest_substring(s: str) -> int:

char_index = {} # 存储字符最新出现位置的字典

max_length = 0

left = 0


for right in range(len(s)):

# 如果字符 s[right] 在当前窗口内,更新左指针

if s[right] in char_index:

left = max(left, char_index[s[right]] + 1)

char_index[s[right]] = right # 更新字符的最新位置

max_length = max(max_length, right - left + 1) # 更新最大长度


return max_length


# 示例用法

print(length_of_longest_substring("abcabcbb")) # 输出3

时间复杂度:O(n)

  • 解释:与方法 2 相同,每个字符最多被访问两次,因此整体复杂度为 O(n)。

空间复杂度:O(min(n, m))

  • 解释:同样,最坏情况下,空间复杂度取决于字符集的大小。

总结

这四种方法中,暴力法最简单但效率最低,时间复杂度为 O(n²)。滑动窗口法及哈希表的结合方法具有较高的效率,时间复杂度为 O(n),适合用于处理较大规模的字符串。

最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】

​​​软件测试面试文档

我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值