新路历程:
一开始想到了用暴力循环去做,但是不用想也知道肯定会超时。
当暴力超时时,优化思路一般两个:双指针 or 动态规划。这道题看不出来有明显的双指针思路,于是转而思考如何用DP做这道题。思考DP函数的输入大概是i, j,表示[i, j]区间内的最长字串的长度,感觉返回应该是max(dfs(i-1, j) +1, dfs(i-1, j-1) + 2, …)大概这种样子。
结果写一半发现不对,递归的本质在于原问题转化为下一层级的子问题,因此需要思考原问题的解与子问题的解有什么关系?这道题假设[i,j]区间内的最长满足要求的子串长为k, 那么[i+1, j-1]内的最长字串与其有什么关系呢?
[i+1, j-1]内的最长子串既可以与[i, j]的结果相关,也可以不相关。1、假设相关,那么i, j至少有一个元素落入了最长字串的统计中,此时a.可能i落入,dfs(i,j) = dfs(i, j-1),b.可能j落入,dfs(i,j) = dfs(i-1, j),c.也可能i,j全都落入, dfs(i,j)=dfs(i-1,j-1) + 2 ;此时又得分情况如果统计了两个A,那么后面判断A-2与B的数量,此时想到这里发现已经破坏递归中‘循环不变量’的性质了,因为这一层判断A B相等,但下一层判断A比B是不是少两个,这个时候又想到在函数里再传一个参数表示A与B的差值,越想越乱。。。2、假设不相关,那么dfs(i,j) = dfs(i+1, j-1)。
或者说这道题没办法用DP解决的难点在于无法确定当前层的答案与下一层的答案的相关性?这个点还需要进一步考虑。不管这道题能不能用DP想到这都很复杂了。
注意的点:
1、前缀初始化第一个前缀和的值(i=0)
2、前缀和这种操作可以很好地解决数量统计类的题目(AB串,1111方形矩阵)
解法:一维数组前缀和
class Solution:
"""
@param s: a String consists of a and b
@return: the longest of the longest string that meets the condition
"""
def get_ans(self, s: str) -> int:
# 一维数组的前缀和
presum = 0
hist = {0: -1}
max_len = 0
for i in range(len(s)):
if s[i] == 'A': v = 1
else: v = -1
presum += v
if presum in hist.keys():
l1 = i - hist[presum]
max_len = max(max_len, l1)
else:
hist[presum] = i
return max_len