LeetCode 307 Range Sum Query

来源:互联网 发布:笨马网络 编辑:程序博客网 时间:2024/06/07 01:36

Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive.
The update(i, val) function modifies nums by updating the element at index i to val.

Example:Given nums = [1, 3, 5]sumRange(0, 2) -> 9update(1, 2)sumRange(0, 2) -> 8

Note:
The array is only modifiable by the update function.
You may assume the number of calls to update and sumRange function is distributed evenly.
题目大意:给出一个数组,在数组上有两种操作。一个是sumRange(i, j),即求数组中下标从i到j的元素之和;另一个操作是update(i, val),即将数组中下标为i的元素的值更新为val。要求编程实现这两种操作。
解题思路:单点更新,区间查询,树状数组和线段树的模板题。使用树状数组时要注意更新操作的实现,因为树状数组的add(i, val)是将val加到arr[i]中,而不是将val赋值给arr[i]。
代码如下:

//线段树实现typedef struct {    int *tree;    int size;} NumArray;int merge(int x, int y) {    return x + y;}//构造线段树void buildSegTree(NumArray *obj, int *arr, int treeIndex, int lo, int hi) {    if (lo >= hi) {        obj->tree[treeIndex] = arr[lo];        return;    }    int mid = lo + (hi - lo) / 2;    buildSegTree(obj, arr, 2 * treeIndex + 1, lo, mid);    buildSegTree(obj, arr, 2 * treeIndex + 2, mid + 1, hi);    obj->tree[treeIndex] = merge(obj->tree[2 * treeIndex + 1], obj->tree[2 * treeIndex + 2]);}//查询区间[i, j]内元素的和int querySegTree(NumArray *obj, int treeIndex, int lo, int hi, int i, int j) {    if (lo > j || hi < i) return 0;    if (i <= lo && j >= hi) return obj->tree[treeIndex];    int mid = lo + (hi - lo) / 2;    if (i > mid) return querySegTree(obj, 2 * treeIndex + 2, mid + 1, hi, i, j);    else if (j <= mid) return querySegTree(obj, 2 * treeIndex + 1, lo, mid, i, j);    int leftQuery = querySegTree(obj, 2 * treeIndex + 1, lo, mid, i, mid);    int rightQuery = querySegTree(obj, 2 * treeIndex + 2, mid + 1, hi, mid + 1, j);    return merge(leftQuery, rightQuery);}//线段树更新void updateValSegTree(NumArray *obj, int treeIndex, int lo, int hi, int arrIndex, int val) {    if (lo >= hi) {        obj->tree[treeIndex] = val;        return;    }    int mid = lo + (hi - lo) / 2;    if (arrIndex > mid) updateValSegTree(obj, 2 * treeIndex + 2, mid + 1, hi, arrIndex, val);    else if (arrIndex <= mid) updateValSegTree(obj, 2 * treeIndex + 1, lo, mid, arrIndex, val);    obj->tree[treeIndex] = merge(obj->tree[2 * treeIndex + 1], obj->tree[2 * treeIndex + 2]);}NumArray *numArrayCreate(int *nums, int numsSize) {    NumArray *obj = (NumArray *) malloc(sizeof *obj);    obj->tree = (int *) malloc(sizeof(int) * (4 * numsSize + 1));    obj->size = numsSize;    buildSegTree(obj, nums, 0, 0, obj->size - 1);    return obj;}void numArrayUpdate(NumArray *obj, int i, int val) {    updateValSegTree(obj, 0, 0, obj->size - 1, i, val);}int numArraySumRange(NumArray *obj, int i, int j) {    return querySegTree(obj, 0, 0, obj->size - 1, i, j);}void numArrayFree(NumArray *obj) {    free(obj->tree);    free(obj);}
//树状数组实现typedef struct {    int* origin;    int* arr;    int size;} NumArray;int sum(NumArray* obj, int pos){    int sum = 0;    while(pos > 0) {        sum += obj->arr[pos];        pos -= (pos & -pos);    }    return sum;}void add(NumArray* obj, int pos, int val){    while(pos <= obj->size){        obj->arr[pos] += val;        pos += (pos & -pos);    }}NumArray* numArrayCreate(int* nums, int numsSize) {    NumArray* obj = malloc(sizeof *obj);    obj->origin = malloc(sizeof(int));    obj->origin = nums;    obj->arr = malloc(sizeof(int) * (numsSize + 1));    memset(obj->arr,0,sizeof(int)*(numsSize+1));    obj->size = numsSize;    for(int i = 1;i <= numsSize;i++){        add(obj, i, nums[i-1]);    }    return obj;}void numArrayUpdate(NumArray* obj, int i, int val) {    int diff = val - obj->origin[i];    obj->origin[i++] = val;    add(obj, i, diff);}int numArraySumRange(NumArray* obj, int i, int j) {    return sum(obj, j + 1) - sum(obj, i);}void numArrayFree(NumArray* obj) {    free(obj->arr);    free(obj->origin);    free(obj);}
原创粉丝点击