LeetCode 307. Range Sum Query - Mutable (Java版; Medium)

welcome to my blog

LeetCode Top 100 Liked Questions 307. Range Sum Query - Mutable (Java版; Medium)

题目描述

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) -> 9
update(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.

第一次做; 前缀树, 直接用了现成的线段树代码; 核心:1)递归建立线段树, 递归函数逻辑:创建涵盖[ss,se]信息的节点, 该节点的索引是0; 创建这个节点的过程中会把整棵线段树创建完成, 最终用一个数组表示线段树, 索引从0开始, 如果当前节点索引是i, 那么它的左孩子索引是2i+1,右孩子索引是2i+2; 如果孩子的索引是i, 那么它的父节点索引是i/2, 这一点跟堆排序很像; 2)ss,se,qs,qe都是原始数组上的索引; 不是代表线段树的数组的索引, 别搞混了

class NumArray {
    
    private SegmentTree segmentTree;
    private int[] nums;
    private int n;
    
    public NumArray(int[] nums) {
        this.nums = nums;
        segmentTree = new SegmentTree(nums, nums.length);
    }
    
    public void update(int i, int val) {
        segmentTree.updateValue(nums, nums.length, i, val);
    }
    
    public int sumRange(int i, int j) {
        return segmentTree.getSum(n=nums.length, i, j);
    }
    
}

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * obj.update(i,val);
 * int param_2 = obj.sumRange(i,j);
 */

class SegmentTree
{
    int st[]; 

    SegmentTree(int arr[], int n)
    {
        //数组不为空
        if(n>0){
            int x = (int) (Math.ceil(Math.log(n) / Math.log(2)));

            int max_size = 2 * (int) Math.pow(2, x) - 1;

            st = new int[max_size]; // Memory allocation 

            constructSTUtil(arr, 0, n - 1, 0);
        }
        
    }

    int constructSTUtil(int arr[], int ss, int se, int si)
    {
        if (ss == se) {
            st[si] = arr[ss];
            return arr[ss];
        }

        int mid = getMid(ss, se);
        st[si] = constructSTUtil(arr, ss, mid, si * 2 + 1) +
                constructSTUtil(arr, mid + 1, se, si * 2 + 2);
        return st[si];
    }

    int getMid(int s, int e) {
        return s + (e - s) / 2;
    }

    void updateValueUtil(int ss, int se, int i, int diff, int si)
    {
        if (i < ss || i > se)
            return;

        st[si] = st[si] + diff;
        if (se != ss) {
            int mid = getMid(ss, se);
            updateValueUtil(ss, mid, i, diff, 2 * si + 1);
            updateValueUtil(mid + 1, se, i, diff, 2 * si + 2);
        }
    }

    void updateValue(int arr[], int n, int i, int new_val)
    {
        if (i < 0 || i > n - 1) {
            System.out.println("Invalid Input");
            return;
        }

        int diff = new_val - arr[i];

        arr[i] = new_val;

        updateValueUtil(0, n - 1, i, diff, 0);
    }

    int getSum(int n, int qs, int qe)
    {
        if (qs < 0 || qe > n - 1 || qs > qe) {
            System.out.println("Invalid Input");
            return -1;
        }
        return getSumUtil(0, n - 1, qs, qe, 0);
    }

    int getSumUtil(int ss, int se, int qs, int qe, int si)
    {
        if (qs <= ss && qe >= se)
            return st[si];

        if (qs > se  || qe < ss )
            return 0;

        int mid = getMid(ss, se);
        return getSumUtil(ss, mid, qs, qe, 2 * si + 1) +
                getSumUtil(mid + 1, se, qs, qe, 2 * si + 2);
    }


    public static void main(String args[])
    {
        int arr[] = {1, 3, 5, 7, 9, 11};
        int n = arr.length;
        SegmentTree  tree = new SegmentTree(arr, n);


        System.out.println("Sum of values in given range = " +
                tree.getSum(n, 1, 3));

        tree.updateValue(arr, n, 1, 10);

        System.out.println("Updated sum of values in given range = " +
                tree.getSum(n, 1, 3));
    }
}

优秀的线段树讲解

发布了580 篇原创文章 · 获赞 130 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/littlehaes/article/details/104212084