再谈子数组/子串问题

这类问题都是求一个满足某种条件的连续的段,相对于子序列。字符串和数组的主要区别是,前者因为由字符而不是数值组成,一般不会有最大值,最小值,求和这种问题。对于字符串的子串问题,一般条件是子串符合某种pattern(回文、有序)或者满足某种统计特征(子串内无重复字符,最多重复2次,包含了给定字符集的所有字符,字符个数均等)


子数组问题包含了子串问题,但是可以用子数组的一些数值计算特征值(比如sum, max)作为条件,最大子数组和, 最短的和为target的子数组


最基本的暴力枚举框架是O(n^3)的,枚举所有子数组需要O(n^2),然后判断子数组是否满足条件(计算特征值,check pattern),一般要check子数组内所有元素,是O(n)的,整体就是O(n^3)。

暴力枚举的框架就是由 枚举+计算子数组特征值两部分组成,都有可能优化,计算特征值的优化是累加利用之前的结果,比如 A[i...j]上的sum或 max 可以由A[i...j-1]上的结果O(1)累加而来,不用遍历子数组。枚举的可能的优化是滑动窗口法,(即内层循环不回退的双重循环)。


计算特征值的的优化还可以通过预处理,先求前缀和数组,然后就可以O(1)得到任意子数组A[i...j]的和,或者做一棵区间树,之后都可以O(logn)查询。


关于子数组的条件,满足某种pattern的(回文,有序)没办法,就得O(n)的去check,关于统计特征,有些可以转换为特征值,比如:

1)01串找最长的01出现次数相等的子串,通过把‘0’当成-1,‘1’当成1,可以转化为最长的sum为0的子数组问题

2)最长的可整合子数组(排序后连续,e.g. [3, 2,1]),可以转化为,max - min  == j - i

import sys
def longestConsecutiveSubArray(A):
    ans = 0
    for i in xrange(len(A)):
        lo, hi, s = sys.maxint, -sys.maxint - 1, set()
        for j in xrange(i, len(A)):
            if A[j] in s: continue
            s.add(A[j])
            lo, hi = min(lo, A[j]), max(hi, A[j])
            if hi - lo == j - i:
                ans = max(ans, j - i + 1)
    return ans






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值