Loading...

使子数组和能被P整除

在这里插入图片描述

求解思路

首先计算整个数组的和对p取模得到余数mod,如果mod为0说明已经满足条件直接返回0。

移除一段子数组后,剩余部分的和能被p整除,等价于找到一个子数组其和模p的余数恰好等于mod。

利用前缀和的性质,如果前缀和pre[j] - pre[i]的余数等于mod,那么移除(i, j]这段区间即可。

为了快速查找符合条件的左端点,用哈希表存储每个余数最晚出现的位置,遍历时对于当前位置i的前缀和余数cur,需要找到之前某个位置的余数find满足(cur - find) % p = mod,变换后得到find = (cur - mod + p) % p,从哈希表中查询find是否存在即可更新最短长度。

代码实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public int minSubarray(int[] nums, int p) {
    // 计算整体余数
    int mod = 0;
    for (int num : nums) {
        mod = (mod + num) % p;
    }
    if (mod == 0) {
        return 0;
    }
    
    // key: 前缀和%p的余数, value: 最晚出现的位置
    HashMap<Integer, Integer> map = new HashMap<>();
    map.put(0, -1);
    int ans = Integer.MAX_VALUE;
    
    for (int i = 0, cur = 0, find; i < nums.length; i++) {
        // 当前前缀和的余数
        cur = (cur + nums[i]) % p;
        // 需要找的余数
        find = cur >= mod ? (cur - mod) : (cur + p - mod);
        
        if (map.containsKey(find)) {
            ans = Math.min(ans, i - map.get(find));
        }
        map.put(cur, i);
    }
    
    return ans == nums.length ? -1 : ans;
}

如果觉得有帮助,欢迎点赞、关注、转发~

最后更新于 2026-04-05 17:35:33
Code Road Record