C练题笔记之:Leetcode-307. 区域和检索 - 数组可修改

这篇博客介绍了如何使用C语言解决LeetCode上的307题,即实现一个可更新数组并返回指定区间和的类。博主对比了暴力法(超时)和树状数组法,详细解释了树状数组的解题思路,并给出了树状数组的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:

给你一个数组 nums ,请你完成两类查询。

其中一类查询要求 更新 数组 nums 下标对应的值
另一类查询要求返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 ,其中 left <= right
实现 NumArray 类:

NumArray(int[] nums) 用整数数组 nums 初始化对象
void update(int index, int val) 将 nums[index] 的值 更新 为 val
int sumRange(int left, int right) 返回数组 nums 中索引 left 和索引 right 之间( 包含 )的nums元素的 和 (即,nums[left] + nums[left + 1], ..., nums[right])
 

示例 1:

输入:
["NumArray", "sumRange", "update", "sumRange"]
[[[1, 3, 5]], [0, 2], [1, 2], [0, 2]]
输出:
[null, 9, null, 8]

解释:
NumArray numArray = new NumArray([1, 3, 5]);
numArray.sumRange(0, 2); // 返回 1 + 3 + 5 = 9
numArray.update(1, 2);   // nums = [1,2,5]
numArray.sumRange(0, 2); // 返回 1 + 2 + 5 = 8

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/range-sum-query-mutable
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

结果:

方法一:暴力法(无法通过,超时)

方法二:树状数组

解题思路:

方法一:暴力法

暴力法真的就不用说了,就按照题目要求写就可以。但是这个方法会超时。

方法二:树状数组

树状数组我也是先看题解,然后了解了下才明白其妙用。

 当一个数字变化的时候,它对应的父节点也会产生变化。

树状数组学习参考:树状数组 数据结构详解与模板(可能是最详细的了)_bestsort的博客-CSDN博客_树状数组

这位大大的博客用图形说明了树状数组,对照这个图就能够理解我们这题是怎么做的啦!

代码:

方法一:

typedef struct {
    int numsSize;
    int *nums;
} NumArray;


NumArray* numArrayCreate(int* nums, int numsSize) {
    NumArray *obj = (NumArray *)malloc(sizeof(NumArray));
    //obj->nums = (int *)malloc(sizeof(int) * numsSize);
    obj->numsSize = numsSize;
    obj->nums = nums;

    //for (int i = 0; i < numsSize; i++) {
    //    obj->nums[i] = nums[i];
    //}
    return obj;
}

void numArrayUpdate(NumArray* obj, int index, int val) {
    obj->nums[index] = val;
}

int numArraySumRange(NumArray* obj, int left, int right) {
    int sum = 0;
    for (; left <= right; left++, right--) {
        if (left != right) {
            sum = sum + obj->nums[left] + obj->nums[right];
        } else {
            sum += obj->nums[left];
        }
    }
    return sum;
}

void numArrayFree(NumArray* obj) {
    //free(obj->nums);
    free(obj);
    obj = NULL;
}

/**
 * Your NumArray struct will be instantiated and called as such:
 * NumArray* obj = numArrayCreate(nums, numsSize);
 * numArrayUpdate(obj, index, val);
 
 * int param_2 = numArraySumRange(obj, left, right);
 
 * numArrayFree(obj);
*/

方法二:

typedef struct {
    int treeSize;
    int *nums;
    int *tree;
} NumArray;

int lowBit(int a)
{
    return a & (-a);
}

void Add(int *tree, int treeSize, int index, int value)
{
    while (index < treeSize) {
        tree[index] += value;
        index += lowBit(index);
    }
}

int Sum(int *tree, int index)
{
    int sum = 0;
    while (index > 0) {
        sum += tree[index];
        index -= lowBit(index);
    }
    return sum;
}

NumArray* numArrayCreate(int* nums, int numsSize) {
    NumArray *obj = (NumArray *)malloc(sizeof(NumArray));
    obj->treeSize = numsSize + 1;
    obj->nums = nums;
    obj->tree = (int *)malloc(sizeof(int) * obj->treeSize);
    memset(obj->tree, 0, sizeof(int) * obj->treeSize);
    for (int i = 0; i < numsSize; i++) {
        Add(obj->tree, obj->treeSize, i + 1, nums[i]);
    }

    return obj;
}

void numArrayUpdate(NumArray* obj, int index, int val) {
    Add(obj->tree, obj->treeSize, index + 1, val - obj->nums[index]);
    obj->nums[index] = val;
}

int numArraySumRange(NumArray* obj, int left, int right) {
    return Sum(obj->tree, right + 1) - Sum(obj->tree, left);
}

void numArrayFree(NumArray* obj) {
    free(obj->tree);
    free(obj);
    obj = NULL;
}

/**
 * Your NumArray struct will be instantiated and called as such:
 * NumArray* obj = numArrayCreate(nums, numsSize);
 * numArrayUpdate(obj, index, val);
 
 * int param_2 = numArraySumRange(obj, left, right);
 
 * numArrayFree(obj);
*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值