其他分享
首页 > 其他分享> > [20210602]LeetCode每日一题 - 523. 连续的子数组和

[20210602]LeetCode每日一题 - 523. 连续的子数组和

作者:互联网

题目描述【中等】

给你一个整数数组 nums 和一个整数 k ,编写一个函数来判断该数组是否含有同时满足下述条件的连续子数组:

子数组大小 至少为 2 ,且 子数组元素总和为 k 的倍数。 如果存在,返回 true ;否则,返回 false

如果存在一个整数 n ,令整数 x 符合 x = n * k ,则称 xk 的一个倍数。

示例 1:

输入:nums = [23,2,4,6,7], k = 6
输出:true
解释:[2,4] 是一个大小为 2 的子数组,并且和为 6

示例 2:

输入:nums = [23,2,6,4,7], k = 6
输出:true
解释:[23, 2, 6, 4, 7] 是大小为 5 的子数组,并且和为 42
426 的倍数,因为 42 = 7 * 67 是一个整数。

示例 3:

输入:nums = [23,2,6,4,7], k = 13
输出:false

提示:

1 <= nums.length <= 10^5
0 <= nums[i] <= 10^9
0 <= sum(nums[i]) <= 2^31 - 1
1 <= k <= 231 - 1

题目地址:地址


初步分析

本题涉及到一个算法:前缀和

如果需要做一个经典的题来练习这个算法,可以参考这个:560. 和为K的子数组


正式分析

我们继续使用上面分析使用的各项定义来具体分析此题

示例一 为例: nums = [23, 2, 4, 6, 7], k = 6
为了符合题目要求: 令整数 x 符合 x = n * k ,那么必须是 nums 前缀和可以被 k 整除

那么我们可以由 求前缀和 改为 求前缀余数和, 如果前缀余数和为 0,则代表在当前这个区间中,存在一个子区间满足 令整数 x 符合 x = n * k

而我们可以定义一个变量存放每次与 6 取余得到的余数,然后与循环值相加,如果再次得到的余数为 0 ,则代表满足了 令整数 x 符合 x = n * k 条件:

====这里有点写错了,正在修改


具体代码

function checkSubarraySum(nums: number[], k: number): boolean {
    if (nums.length < 2) return false

    const map = new Map()
    map.set(0, -1)

    const length = nums.length
    let remain = 0

    for (let i = 0; i < length; i++) {
        remain = (remain + nums[i]) % k

        if (map.has(remain)) {
            const prevIndex = map.get(remain)

            if (i - prevIndex >= 2) return true

        } else {
            map.set(remain, i)
        }
    }

    return false
};

TS AC,执行用时:128ms, 在所有 TypeScript 提交中击败了 33.33% 的用户

TS AC中击败 100% 用户的提交,目前执行下来用时 180ms,估计力扣增加了测试用例导致更简单的算法耗时比之前提交的复杂的算法耗时要久,这对后期用户提交并不友好


问题升级

本题用到了一位数组的前缀和,那么自然也有二维数组前缀和
可以参考此题:304. 二维区域和检索 - 矩阵不可变

各大公司对前缀和的考察还是比较多的


最后

如果我在哪里写的有问题,欢迎指出,共同进步,谢谢阅读~

标签:前缀,nums,sum,整数,LeetCode,remain,数组,523,20210602
来源: https://blog.csdn.net/mxd26888/article/details/117485159