python实现字符串——无重复字符的最长子串、串联所有单词的子串、替换子串得到平衡字符串

1.无重复字符的最长子串

leetcode 3:https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/

给定一个字符串,请你找出其中不含有重复字符的最长子串的长度。

示例1

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

示例2

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

示例3

输入: "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

代码:

  • 暴力解法:

    # 暴力解法
    class Solution(object):
        def lengthOfLongestSubstring(self, s):
            """
            :type s: str
            :rtype: int
            """
            m = 0
            if s != "":
                m = 1
            for i in range(len(s)):
                for j in range(i + 1, len(s)):
                    if s[i] != s[j]:
                        if self.check_str(s[i:j + 1]):
                            m = max(m, len(s[i:j + 1]))
            return m
    
        # 检查子字符串是否有重复
        def check_str(self, s: str) -> bool:
            for i in range(len(s)):
                if s[i] in s[i+1:]:
                    return False
            return True
    
    if __name__ == '__main__':
        s = 'abcabcbb'
        sol = Solution()
        print(sol.lengthOfLongestSubstring(s))
    
  • 滑动窗口解法:

    # 滑动窗口解法
    class Solution(object):
        def lengthOfLongestSubstring(self, s):
            """
            :type s: str
            :rtype: int
            """
            # 窗口的定义
            dic = {}
            # 定义窗口左边和最大无重复子字符串长度为0
            i ,res = 0, 0
            # 向右从0依次滑动窗口右边j
            for j in range(len(s)):
                # 当窗口中的字符串有重复
                if s[j] in dic:
                    #将窗口左边i向后移动
                    i = max(dic[s[j]], i)
                    # i +=1
                # 获取新的最大无重复子字符串长度
                res = max(res, j-i+1)
                # 将j滑过的字符存入dic
                dic[s[j]] = j+1
            return res
    
    if __name__ == '__main__':
        s = 'abcabcbb'
        sol = Solution()
        print(sol.lengthOfLongestSubstring(s))
    

    执行结果:

在这里插入图片描述

2.串联所有单词的子串

leetcode 30:https://leetcode-cn.com/problems/substring-with-concatenation-of-all-words/

给定一个字符串s和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。

注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。

示例1

输入:
  s = "barfoothefoobarman",
  words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoo" 和 "foobar" 。输出的顺序不重要, [9,0] 也是有效答案。

示例2

输入:
  s = "wordgoodgoodgoodbestword",
  words = ["word","good","best","word"]
输出:[]

代码:

# 滑动窗口
class Solution(object):
	def findSubstring(self, s, words):
		"""
		:type s: str
		:type words: List[str]
		:rtype: List[int]
		"""
		if not s or len(s)==0 or not words or len(words)==0:
			return []
		# 将每个单词以及出现的频率记录到字典中
		words_map,res = dict(),[]
		for i in words:
			if i not in words_map:
				words_map[i] = 1
			else:
				words_map[i] += 1
		one_word_size = len(words[0])
		all_words_size = len(words)*one_word_size
		for i in range(len(s)-all_words_size+1):
			# 每次取 all_words_size长度的子串
			tmp_str,d = s[i:i+all_words_size],dict(words_map)
			# 将子串和临时字典进行比较
			for j in range(0,len(tmp_str),one_word_size):
				# 从子串tmp_str中取出one_word_size长度的子串,看是否出现在临时字典中
				# 如果是就将临时字典记录的频率-1,如果不在就跳出循环
				key = tmp_str[j:j+one_word_size]
				if key in d:
					d[key] -= 1
					if d[key] == 0:
					    del d[key]
				else:
					break
			# 当内层循环遍历完后,如果临时字典为空则表示全部匹配上了
			# 记录数组的下标
			if not d:
				res.append(i)
		return res

if __name__ == '__main__':
    s = "barfoothefoobarman"
    words = ["foo", "bar"]
    sol = Solution()
    print(sol.findSubstring(s, words))

执行结果:

在这里插入图片描述

3.替换子串得到平衡字符串

leetcode 1234:https://leetcode-cn.com/problems/replace-the-substring-for-balanced-string/

有一个只含有'Q', 'W', 'E','R'四种字符,且长度为 n的字符串。假如在该字符串中,这四个字符都恰好出现n/4次,那么它就是一个「平衡字符串」。

给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串s变成一个「平衡字符串」。你可以用和「待替换子串」长度相同的任何其他字符串来完成替换。

请返回待替换子串的最小可能长度。

如果原字符串自身就是一个平衡字符串,则返回 0。

示例1:

输入:s = "QWER"
输出:0
解释:s 已经是平衡的了。

示例2:

输入:s = "QQWE"
输出:1
解释:我们需要把一个 'Q' 替换成 'R',这样得到的 "RQWE" (或 "QRWE") 是平衡的。

示例3:

输入:s = "QQQW"
输出:2
解释:我们可以把前面的 "QQ" 替换成 "ER"。 

示例4:

输入:s = "QQQQ"
输出:3
解释:我们可以替换后 3 个 'Q',使 s = "QWER"。

代码:

class Solution(object):
    def balancedString(self, s):
        """
        :type s: str
        :rtype: int
        """
        n = len(s)
        average = n // 4
        import collections
        counter = collections.Counter(s)
        saveCounter = collections.Counter()
        # 所有超过1/4的都是需要转换的
        for key, val in counter.items():
            if val > average:
                saveCounter[key] = val
        if not saveCounter:
            return 0

        l = r = 0
        count = float("inf")
        for r in range(n):
            # 每一个如果都要需要转化的过程中,则滑动窗口需要包含,直到滑动窗口足够大,saveCounter包含的元素对应的次数都要小于等于average
            if s[r] in saveCounter:
                saveCounter[s[r]] -= 1
            while l <= r:
                include = True
                for ch in 'QWER':
                    if saveCounter[ch] > average:
                        include = False
                        break
                if include:
                    # 如果滑动窗口已经包含了 那么接下来我们将左边右移,需要将s[l] 次数++
                    count = min(count, r - l + 1)
                    saveCounter[s[l]] += 1
                    l += 1
                else:
                    break
        return count

if __name__ == '__main__':
    s = "QQQQ"
    sol = Solution()
    count = sol.balancedString(s)
    print(count)

执行结果:
在这里插入图片描述

欢迎关注微信公众号 shinerise,与你一起慢慢进步~

Alt

发布了34 篇原创文章 · 获赞 9 · 访问量 3万+

猜你喜欢

转载自blog.csdn.net/Shine_rise/article/details/103994812
今日推荐