No. 1143 【LintCode 最长AB子串 O(N)复杂度 解法】

No. 1143 【LintCode 最长AB子串 O(N)复杂度 解法】

题目描述

给你一个只由字母’A’和’B’组成的字符串s,找一个最长的子串,要求这个子串里面’A’和’B’的数目相等,输出该子串的长度。

这个子串可以为空。
s的长度n满足 2<=n<=1000000。

样例1

输入: s = “ABAAABBBA”
输出: 8
【解释】:
子串 s[0,7] 和子串 s[1,8] 满足条件,长度为 8。

样例2

输入: s = “AAAAAA”
输出: 0
【解释】:
s 中除了空字串,不存在 ‘A’ 和 ‘B’ 数目相等的子串。

1. 暴力算法


暴力解法的时间复杂度太高,必然超时。

def maxLenFun(s):
	L = len(s)
	if L <= 1:
		return 0
	max_len = 0
	for i in range(0, L):
		for j in range(i + 1, L):
			sub = s[i:j+1]
			num_a = sub.count('A')
			num_b = sub.count('B')
			if num_a == num_b:
				max_len = max(max_len, j - i+1)
	return max_len


if __name__ == '__main__':
	s = 'ABBABBABA'   # 6
	ans = maxLenFun(s)
	print(ans)

2. 解法二(分割区间法)


O(N)时间复杂度的解法参考文末的 参考文献,并附上自己的理解与说明。

【总结解释】

一、

  1. 如果 cnt = (cntA-cntB) 曾经出现过,说明之后增加的A和B数量是相等的
  2. 也就是把 cnt相等的情况当做分隔符,处在分隔符之间的一段段就是满足题意的

二、

  1. 有一种想法是 cnt == 0 的之前都是满足题意的,但是并非如此。比如"ABB ABBABA" 这个字符串,是逆序来的,所以还要逆序来一遍,总而言之距离两个端点最远的cnt==0才是答案

class Solution:
    """
    @param s: a String consists of A and B
    @return: the longest of the longest string that meets the condition
    """
    def getAns(self, s):
       
        n = len(s)
        first = {}     # 新建哈希表
        first[0] = 0
        cntA = 0
        cntB = 0
        ans = 0
        for i in range(n):
            if s[i] == 'A':
                cntA += 1
            else:
                cntB += 1
            cnt = cntA - cntB     # cntA - cntB 即A的数量减去B的数量
            if cnt in first:      # 因为每个循环都要查询,所以用哈希表可以缩减查询时间   在表中就查询
                ans = max(ans, i + 1 - first[cnt])
            else:
                first[cnt] = i + 1   # 不在表中就添加
        print(first)
        print(cntA, cntB)
        return ans

if __name__ == '__main__':
	s = 'ABBABBABA'
	solution = Solution()
	print(solution.getAns(s))

【具体说明如下】
"""
S        'A   B   B   A   B   B   A   B   A'

i         0   1   2   3   4    5   6   7   8
cntA      1   1   1   1   2    2   3   3   4
cntB      0   1   2   2   3    4   4   5   5  
cnt       1   0  -1   0  -1    2  -1  -2  -1
value     1   2   3   4   5    6   7   8   9

hashmap = {key(cnt):value(i+1), ...}
在 cnt中,值为0-1都出现过 ,但是由-1作为边界隔断的区间比较大
即     
cnt     1   0-1   0  -1    2  -1  -2  -1】
value   1   23   4    5   6   7   8   99 - 3 = 6 即答案

"""

参考文档

发布了28 篇原创文章 · 获赞 4 · 访问量 1215

猜你喜欢

转载自blog.csdn.net/weixin_41888257/article/details/103895199
今日推荐