检查数组对是否可以被 k 整除

标签: 数组 哈希表 计数

难度: Medium

给你一个整数数组 arr 和一个整数 k ,其中数组长度是偶数,值为 n

现在需要把数组恰好分成 n / 2 对,以使每对数字的和都能够被 k 整除。

如果存在这样的分法,请返回 True ;否则,返回 False

示例 1:

输入:arr = [1,2,3,4,5,10,6,7,8,9], k = 5
输出:true
解释:划分后的数字对为 (1,9),(2,8),(3,7),(4,6) 以及 (5,10) 。

示例 2:

输入:arr = [1,2,3,4,5,6], k = 7
输出:true
解释:划分后的数字对为 (1,6),(2,5) 以及 (3,4) 。

示例 3:

输入:arr = [1,2,3,4,5,6], k = 10
输出:false
解释:无法在将数组中的数字分为三对的同时满足每对数字和能够被 10 整除的条件。

提示:

  • arr.length == n
  • 1 <= n <= 105
  • n 为偶数
  • -109 <= arr[i] <= 109
  • 1 <= k <= 105

Submission

运行时间: 76 ms

内存: 29.4 MB

class Solution:
    def canArrange(self, arr: List[int], k: int) -> bool:
        mod = [0] * k
        for num in arr:
            mod[num % k] += 1
        if any(mod[i] != mod[k - i] for i in range(1, k // 2 + 1)):
            return False
        return mod[0] % 2 == 0

Explain

这个题解的思路是首先统计每个数字模 k 的结果出现的次数,然后检查是否存在一种分配方法使得每对数字的和都能被 k 整除。具体来说,对于每个非零的模数 i,必须有相同数量的数字模数为 k - i,这样它们才能配对组成和为 k 的倍数。另外,模数为 0 的数字数量必须是偶数,这样它们才能相互配对。

时间复杂度: O(n + k)

空间复杂度: O(k)

class Solution:
    def canArrange(self, arr: List[int], k: int) -> bool:
        mod = [0] * k  # 创建一个长度为 k 的数组,用于统计各个模数的出现次数
        for num in arr:
            mod[num % k] += 1  # 统计每个数字模 k 的结果
        if any(mod[i] != mod[k - i] for i in range(1, k // 2 + 1)):
            return False  # 检查是否每个非零模数 i 有相同数量的 k - i 模数
        return mod[0] % 2 == 0  # 检查模数为 0 的数字数量是否为偶数

Explore

模数为0的数字意味着这些数字直接是k的倍数。在配对这些数字时,只有两个同样是k的倍数的数字相加仍然是k的倍数。因此,为了确保所有这些模数为0的数字可以通过相互配对来组成k的倍数,它们的数量必须是偶数。如果是奇数,则会剩下一个无法配对的数字,导致无法满足题目要求。

在Python中,负数进行取模运算可能得到负的模数。例如,-1 % k 得到的结果是 k-1 而不是 1。这可能会影响统计模数的准确性。为了处理这种情况,我们可以将负的模数转换为正的模数,即将计算模数的步骤修改为 `mod[(num % k + k) % k] += 1`。这样,不论正负数,都能统一到一个正确的模数区间内,保证计数的正确性。

检查模数i和k-i的数量是否相等时,遍历到k/2是因为当你考虑一个模数i时,同时也在考虑与之配对的模数k-i。如果遍历超过k/2,那么将会重复检查已经考虑过的配对,因为对于任何i > k/2,其配对的k-i已经在之前的迭代中作为某个j < k/2的配对考虑过了。因此,遍历到k/2就足够了,完整遍历将导致不必要的重复检查。

在Python中,`any`函数用于检查传入的可迭代对象中是否至少有一个元素为True。在此代码中,它用于检查从1到k/2的所有模数i是否存在其数量与模数k-i的数量不相等的情况。如果存在这样的模数i,则`any`函数返回True,表示无法找到完全匹配的模数对来满足题目要求,从而函数返回False表示不可能按要求配对数组。使用`any`函数可以简洁地在找到第一个不符合条件的情况时立即结束检查,提高代码效率。