剑指Offer 48. 最长【无】重复字符的子字符串(Medium)/ 1044. 最长重复子串(返回任一子串)(Hard) / 重复子串问题!!!

  1. 最长不含重复字符的子字符串(动态规划 / 双指针 + 哈希表,清晰图解)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码

class Solution:
    ### 1104 动态规划 + 哈希表 O(N)(64 ms,13.4 MB)
    def lengthOfLongestSubstring(self, s: str) -> int:
        dic, res, tmp = {}, 0, 0                    # tmp表示前一时刻最长不含重复字符的子字符串的长度,初始化为0
        for j in range(len(s)):                     # 遍历字符串中每一个字符
            i = dic.get(s[j], -1)                   # 获取下标i
            dic[s[j]] = j                           # 更新某个字符s[j]出现的最新位置j(下标),更新哈希表
            tmp = tmp + 1 if tmp < j - i else j - i # dp[j - 1] -> dp[j]
            res = max(res, tmp)                     # 更新最大值
        return res

    ### 1104 动态规划 + 线性查找 O(N2)(484 ms,13.6 MB)
    def lengthOfLongestSubstring(self, s: str) -> int:
        res = tmp = 0                               # tmp表示前一时刻最长不含重复字符的子字符串的长度,初始化为0
        for j in range(len(s)):                     # 遍历字符串中每一个字符
            i = j - 1                               # 初始化下标i,将i初始化为j左边的值
            while i>=0 and s[i] != s[j]: i -= 1     # 从右往左更新i(逆序)
            tmp = tmp + 1 if tmp < j - i else j - i # dp[j - 1] -> dp[j]
            res = max(res, tmp)                     # 更新最大值
        return res

    ### 1104 动态规划 + 双指针 O(N)(68 ms,13.6 MB)
    def lengthOfLongestSubstring(self, s: str) -> int:
        dic, res, i = {}, 0, -1       # 初始化左指针i为-1
        for j in range(len(s)):       # 遍历字符串中每一个字符
            if s[j] in dic:           # 检查当前字符是否在哈希表中
                i = max(dic[s[j]], i) # 若存在,则更新左指针i
            dic[s[j]] = j             # 更新某个字符s[j]出现的最新位置j(下标),更新哈希表
            res = max(res, j - i)     # 更新最大值
        return res
  • 返回最长无重复字符的子串
# 返回无重复字符的最长子串
class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        if s is None or len(s) == 0:
            return ''
        d = {}
        maxlen = tmp = 0
        start = 0 # 初始化无重复字符子串的开始位置
        for i in range(len(s)):
        	# 若在字典 d 中查询到当前字符 且 此字符的最近位置在start之后,则表示已有重复串
            if s[i] in d and d[s[i]] >= start:
                start = d[s[i]] + 1    # 更新的重复串的开始位置
            tmp = i - start + 1        # 计算当前重复串的长度,并保证重复串长度至少为 1
            d[s[i]] = i                #(重新)保存第 i 个字符的起始位置,用于下次计算重复串
            
            # 比较当前重复串长度和历史最大重复串长度,以更新最大重复串长度
            if maxlen < tmp:
            	maxlen = tmp
            	res = s[start: start+maxlen]
        return res

1044. 最长重复子串(返回任一子串)

在这里插入图片描述

class Solution:
    def longestDupSubstring(self, s: str) -> str:
        ans = ''
        max_len, start, end, n = 0, 0, 1, len(s)
        
        # 每次看s[start:end]在之后s[start+1:]是否也出现,因为在s[start:]肯定出现一次,所以总共出现次数>=2
        # 出现的话,更新max_len,同时end后移,看更长的是否满足
        # 不出现的话,表明以start开头的子串不可能出现>=2次,start后移
        while end < n:
            if s[start:end] in s[start+1:]: # 判断子串出现至少两次
                # 如果子串长度超过当前最大值,更新最大值和ans
                if max_len < end - start:
                    max_len = end - start
                    ans = s[start:end]
                end += 1
                continue
                
            start += 1
            
        return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值