LeetCode 前缀和&差分数组

差分数组:

1109. 航班预订统计 https://leetcode-cn.com/problems/corporate-flight-bookings/

1094. 拼车 https://leetcode-cn.com/problems/car-pooling/

算法参考:

https://mp.weixin.qq.com/s?__biz=MzAxODQxMDM0Mw==&mid=2247487011&idx=1&sn=5e2b00c1c736fd7afbf3ed35edc4aeec&chksm=9bd7f02baca0793d569a9633cc14117e708ccc9eb41b7f0add430ea78f22e4f2443f421c6841&scene=21#wechat_redirect

前缀和:

构造前缀和:

最好是前置一个0

    int *preSum = (int *)malloc(sizeof(int) * (numsSize + 1));
    preSum[0] = 0; // 前缀和做一个前置空内容
    // 真正的前缀和是从preSum的1开始的
    for (int i = 0;i < numsSize;++i) {
        preSum[i + 1] = preSum[i] + nums[i];
    }

如果要求任意区间内的元素的和,如 i~ j这个区间里面的元素的和:

    // 上面这么写,就是为了下面循环可以算上nums[0]
    int res = 0;
    for (int left = 0;left < numsSize;++left) {
        for (int right = left;right < numsSize;++right) {
            // 区间和【left .. right】,注意下标
            if (preSum[right + 1] - preSum[left] == k) {
                res++;
            }
        }
    }

 计算区间和为k的所有情况

假设现在有数组a0、a1、a2、a3.....

S0 = 0;

S1 = a0;

S2 = a0 + a1;

S3 = a0 + a1 + a2;

S4 = ...........................;

一般需要配合Hash map一起使用:

前缀和介绍:

https://leetcode-cn.com/problems/subarray-sum-equals-k/solution/bao-li-jie-fa-qian-zhui-he-qian-zhui-he-you-hua-ja/

典型题目:

523. 连续的子数组和 https://leetcode-cn.com/problems/continuous-subarray-sum/

974. 和可被 K 整除的子数组 https://leetcode-cn.com/problems/subarray-sums-divisible-by-k/

560. 和为K的子数组 https://leetcode-cn.com/problems/subarray-sum-equals-k/

以560为例:


// hash map
typedef struct HashMap{
    int preSum; // key 保存前缀和
    int count; // 保存计数值
    UT_hash_handle hh;
}HashMap;
int subarraySum(int* nums, int numsSize, int k){
    if (nums == NULL) {
        return 0;
    }
    // 几乎所有的前缀和使用UT Hash进行优化的时候,均需要使用到一个前置0的提前变量
    HashMap *hashHandle = NULL;
    HashMap *tmp = (HashMap *)malloc(sizeof(HashMap));
    tmp->preSum = 0;
    tmp->count = 1; //这部分必须是1
    HASH_ADD_INT(hashHandle, preSum, tmp);
    int pre = 0;
    int res = 0;
    for (int i = 0;i < numsSize;++i) {
        pre += nums[i]; 
        int value = pre - k; // 顺序不能反了,和很有可能是k或者k的倍数
        HASH_FIND_INT(hashHandle, &value, tmp);
        if (tmp != NULL) {
            res += tmp->count;
        }
        //如果是相同的前缀和,那么需要更新计数值,UT Hash不允许存入preSum数值相同的内容
        // HASH_FIND_INT(hashHandle, &pre, tmp);
        /*
           [1,2,3]
           3
        */
        if (tmp != NULL) {
            tmp->count++; // 要自增
        } else {
            tmp = (HashMap *)malloc(sizeof(HashMap));
            tmp->preSum = pre;
            tmp->count = 1;
            HASH_ADD_INT(hashHandle, preSum, tmp);
        }
    }
    return res;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值