webank---9.3---笔试第三题

题目描述:
输入三个整数,n,u,v,n是接下来输入数组的长度,u和v等下再用
再输入一个数组nums
然后求nums的连续子数组有多少个,这个子数组的均值等于u/v

思路:前缀和+hash表

技巧:由于平均数比较麻烦,先将所有元素都乘v然后再减去u,这样方便后面的前缀和(即,原来是avg(子数组)=u/v,我们更改以后是:子数组的和等不等于0),算式是这样的:(x1+x2+……xn) / n= u/v --->(转化成)(x1+x2+……xn)*v -n*u = 0 --->(再化简) (x1*v-u) + (x2*v-u) + (x3*v-u) + …… + (xn*v-u) = 0,将这个数组全新定义为新的nums。接下来的问题就是【LC:和为k的子数组个数】

代码:

while(1):
    line1 = input().strip()
    if len(line1)<=0:break
    line1 = line1.split(' ')
    n,u,v = int(line1[0]),int(line1[1]),int(line1[2])
    line2 = input().strip()
    nums = [int(x) for x in line2.split(' ')]
    def f(nums,u,v):
        nums = [x*v-u for x in nums]
        res = 0
        presum = [0]
        for x in nums:presum.append(presum[-1]+x)
        presum = presum[1:]
        hashset = dict()
        for x in presum:
            # print(x,hashset,res)
            if x==0:res+=1
            if x in hashset:
                res+=hashset[x]
                hashset[x]+=1
            else:hashset[x] = 1
        return res
    print(f(nums,u,v))

#笔试##webank##好难啊##心态崩了##晒一晒我的offer#
全部评论
调整心态,继续前进
1 回复 分享
发布于 2023-09-03 21:58 广东
给个简介的公式,用前缀和prefix数组。对于子数组[i, j],如果满足均值条件,则有(prefix[j] - prefix[i - 1]) = u / v * (j - i + 1)。这个公式化简以下就有prefix[j] * v - u * j = prefix[i - 1] * v - u * (i - 1)。可以看到左右两边形式都是一样的,只和j和(i- 1)有关,所以可以线性解法,遍历每个位置用哈希表记录prefix[x] * v - u * x,然后对比前面记录的相同的个数。除此之外,还有个边界条件,是i=0的情况,只要判断prefix[j] * v - u * j是否等于0,是则result+1
1 回复 分享
发布于 2023-09-03 22:30 上海
哈希表的操作是:每当遇到一个前缀和数组中的元素x,如果它本来就是0,那就res+=1,然后再看哈希表里面是不是已经有x了,有几个,就res加上几。
点赞 回复 分享
发布于 2023-09-03 21:43 湖南
顺带:其实我当时也没想出来,还是各方面都差了些,调整心态,继续前进
点赞 回复 分享
发布于 2023-09-03 21:43 湖南

相关推荐

coffrar:全都是已读😅沟通一千五百多个了
点赞 评论 收藏
分享
评论
2
2
分享

创作者周榜

更多
牛客网
牛客企业服务