持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情
描述
Given an integer array nums and an integer k, return true if nums has a continuous subarray of size at least two whose elements sum up to a multiple of k, or false otherwise. An integer x is a multiple of k if there exists an integer n such that x = n * k. 0 is always a multiple of k.
Example 1:
Input: nums = [23,2,4,6,7], k = 6
Output: true
Explanation: [2, 4] is a continuous subarray of size 2 whose elements sum up to 6.
Example 2:
Input: nums = [23,2,6,4,7], k = 13
Output: false
Note:
1 <= nums.length <= 10^5
0 <= nums[i] <= 10^9
0 <= sum(nums[i]) <= 2^31 - 1
1 <= k <= 2^31 - 1
解析
根据题意,给定一个整数数组 num 和一个整数 k ,如果 nums 中有长度至少 2 的连续子数组,且其元素总和为 k 的倍数,则返回 true ,否则为 false。如果存在一个整数 n ,使得 x = n * k , 则整数 x 是 k 的倍数,而且 0 始终是 k 的倍数。
像这种子数组求和的题目,一般情况可以优先试用前缀和去解题,而且这道题还需要用到一点数学知识—— 同余定理:
- 即当两个数除以某个数的余数相等的情况下,这两个数字相减后的值肯定可以被该数整除。
- 举例,8 和 13 对 5 取模,都是 3 ,那么 13 - 8 == 5 就就可以被 5 整除
我们定一个字典 d 用来保存出现过的余数及其对应的数组索引,然后在计算前缀和的同时不断判断出现的余数是否已经在 d 中出现,且两者的索引差大于等于 2 ,如果满足条件则直接返回 True 即可,由于可能存在 nums 前 N 个数字和恰好被 k 整除的情况,我们预先设置字典 {0:-1} 来规避该问题。当遍历结束之后,还没有找到直接返回 False 。
时间复杂度为 O(N) ,空间复杂度为 O(N) 。
解答
class Solution(object):
def checkSubarraySum(self, nums, k):
"""
:type nums: List[int]
:type k: int
:rtype: bool
"""
d = {0: -1}
pre = 0
for i, num in enumerate(nums):
pre += num
result = pre % k
target = d.get(result, i)
if target == i:
d[result] = i
elif i - 2 >= target:
return True
return False
运行结果
Runtime: 2157 ms, faster than 19.71% of Python online submissions for Continuous Subarray Sum.
Memory Usage: 33.5 MB, less than 19.46% of Python online submissions for Continuous Subarray Sum.
原题链接
您的支持是我最大的动力