📝 面试求职: 「面试试题小程序」 ,内容涵盖 测试基础、Linux操作系统、MySQL数据库、Web功能测试、接口测试、APPium移动端测试、Python知识、Selenium自动化测试相关、性能测试、性能测试、计算机网络知识、Jmeter、HR面试,命中率杠杠的。(大家刷起来…)
📝 职场经验干货:
题目描述:
无重复字符的最长子串问题是一个经典的字符串处理问题,旨在找到给定字符串中最长的不包含重复字符的子串。
示例 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%免费】