使数组能被p整除方法总结(暴力破解,前缀,同余)

要求:给你一个正整数数组 nums,请你移除 最短 子数组(可以为 空),使得剩余元素的 和 能被 p 整除。 不允许 将整个数组都移除。

请你返回你需要移除的最短子数组的长度,如果无法满足题目要求,返回 -1 。

子数组 定义为原数组中连续的一组元素。(题目来源:LeetCode)

思路一:暴力破解(O(n^3))

枚举每一种移除子数组的情况情况,用for循环嵌套。如数组长度为n,可以判断第一层循环要循环n-1轮,每轮可以循环取(n-当前轮数)次,每次取当前轮数个数。

(运行环境Java8)

public int minSubarray(int[] nums, int p) {
int a = nums.length;
    long sum = 0;//用long防止取数超出int范围
    for(int num:nums){
        sum=sum+num;
    }
if (sum % p == 0)
return 0; //整除时直接返回
    if (a != 0) {
for (int i = 1; i < a; i++) { //取多少轮
            for (int j = 0; j < a-i+1 ; j++) {//每轮取多少次
                int k = 0;
                for (int n = 0; n < i; n++) {//每次取多少个
                    k += nums[j+n];
                    }
if ((sum - k) % p == 0) {
return i;
                }
            }
        }
return -1;
    }
return a;
}

思路二:同余的方法(O(n))

结论:x%p==z,y%p==z则(x-y+p)%p==0。

在数学中一个正数x取余x%p==z(z为任意数),另一个正数y取余y%p==z,则(x-y)%p==0;如果是负数x与负数y当有x%p==z,y%p==z则(x-y)%p==0;而当x为正数y为负数时当有x%p==z,y%p==z则(x-y+p)%p==0,而当x为负数y为正数时当有x%p==z,y%p==z则(x-y+p)%p==0得对于任意下x,y满足x%p==z,y%p==z则(x-y+p)%p==0。

分析题目:由于题目要求从一个数组x中取一个数组y后可被p整除。即要(x-y)%p=0,只需要x%p=y%p=z。把题设数组sums[]可以得到前缀数组s[]例如:nums={1,2,3}则s={0,1,2,6}而nums中的{2,3}子数组的和为s[3]-s[1]。题设要求可写成s[n]-(s[right]-s[left])%p==0即s[right]-s[n]==s[left]%p。

public int minSubarray2(int [] nums,int p){

        int n=nums.length;
        int res=n;
        long [] s=new long[n+1];
        s[0]=0;
        for(int i=0;i<n;++i){
            s[i+1]=(s[i]+nums[i])%p;//s[left]%p

        }
        Map map= new HashMap<Integer,Integer>();
        for (int i=0;i<n+1;i++){
            map.put(s[i],i);
            int j= (int) map.getOrDefault((s[i]-s[n]+p)%p,-n);
             res=Math.min(res,i-j);
        }
        return res<n ? res:-1;



    }
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值