青训营X豆包MarsCode技术训练营——连续子串和的整除问题 | 豆包MarsCode AI刷题

160 阅读2分钟

题目描述

image.png

解题思路:

思路一:暴力破解

方法: 使用两层循环,枚举所有连续子序列,计算其和,并检查是否可以被b整除

复杂度分析: O(n^2)

def solution(n,b,sequence):
    count = 0
    for i in range(n)
        summary = 0
        for j in range(i,n):
            summary += sequence[j]
            if summary%b==0:
                count+=1
    return count

思路二:使用哈希结构进行优化

方法: 优化的关键在于利用了前缀和及其余数的性质,从而可以避免重复计算,并快速找到符合条件的子序列个数。

复杂度分析: O(n)

1.前缀和

定义:序列起始位置到当前某个位置的所有元素之和 性质:对于任意一个区间[i,j]的和,可以表示为两个前缀和的差sum[i,j]=prefix_sum[j]-prefix_sum[i-1] 结论:若前缀和prefix_sum[j]与前缀和prefix_sum[i]对b取模有相同的余数,则表明子序列[i+1,j]是目标序列(其和可以被b整除)。每当相同余数情况出现时,当前前缀和与之前的每一个余数相同的位置之间的子序列都将满足条件。

2.利用哈希表存储余数,避免重复计算

哈希表是一种高效的数据结构,使用哈希函数建立键与存储地址的映射关系,借此实现时间复杂度为O(1)的快速访问。因此,可以利用哈希表记录可能出现的余数情况以及对应出现的次数,每次计算完余数后可以快速进行查找。

def solution(n,b,sequence):
    hashtable = {0:1}#初始化余数为0的情况
    count = 0
    prefix_sum =[0]*n
    for i in range(n):#计算前缀和数组
        if i!=0:
            prefix_sum[i]=prefix_sum[i]+sequence[i]
        else:
            prefix_sum[i]=sequence[i]
            
        
    for j in range(n):
        remainder = prefix_sum[j]%b
        if remainder in hashtable:#相同余数,更新count,更新hashtable
            count+=hashtable[remainder]#每次个数增加的是对应余数出现的次数
            hashtable[remainder]+=1
        else:
            hashtable[remainder]=1
    return count
        

注意:

  • 第一次余数为零时候比较特殊,因此在初始化时候要先设置其为1
  • 先更新count,再更新hashtable
  • 每次个数增加的是对应余数出现的次数,而不是增加1

经验总结

适合使用哈希表的情况:

1.元素查找类问题

2.频率统计问题

3.配对和问题

4.映射转换与查找

5.子字符串或者子序列匹配问题

适合使用前缀和的情况:

1.动态子数组和查询

2.平衡数组/分割数组问题