LeetCode解析------307.区域和检索 - 数组可修改-线段树

题目:

给定一个整数数组 nums,求出数组从索引 i 到 j (i ≤ j) 范围内元素的总和,包含 i, j 两点。

update(i, val) 函数可以通过将下标为 i 的数值更新为 val,从而对数列进行修改。

示例:

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

说明:

数组仅可以在 update 函数下进行修改。
你可以假设 update 函数与 sumRange 函数的调用次数是均匀分布的。

简单介绍:
题目:区域和检索 - 数组可修改
题目难度:中等
使用语言:JAVA
这道题来自leetcode题库的线段树标签。

概念引入:
为了方便读者理解,笔者在这里引入线段树的概念。
线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。
性质:除叶子结点外,其他点的值等于其左、右子树的和。(重要)

LeetCode解析------307.区域和检索 - 数组可修改-线段树_第1张图片
如上图,就是一个线段树。
根结点的值等于其左、右子树的和。

解题思路:
首先看题、分析题意,我们可以明确1个关键点:
1.该题是否有优于暴力解的解法?因为该题使用暴力解非常简单,但时间复杂度较高。
既然,我们已经分析出来题目的关键任务了,下面我们就可以开始思考实现了。
我们采用算法与数据结构的思路来剖析一下这题

数据结构:
要实现对数据的操作,我们要先明确存储数据的数据结构。
该题的数据结构的作用:
1.整型数组保存线段树。
2.整型保存数组的长度。

算法:
既然明确了我们的数据结构,我们就可以开始我们的算法分析了。
1.第一步,初始化工作,构建线段树。
2.第二步,更新某点的值,上方结点的值也相应更新
3.第三步,区间求和,如果左边界是左节点,就往上找,否则往右找。右边界同理

代码部分:


public class NumArray {
    int [] tree;
    int n;

    public NumArray(int[] nums) {
        n=nums.length;
        tree=new int[n*2];//线段树

        buildTree(nums);
    }

    void buildTree(int[] nums){
        //叶子结点赋值
        for(int i=n,j=0;i<2*n;i++,j++){
            tree[i]=nums[j];
        }
        //线段树构造
        for(int i=n-1;i>=0;i--){
            tree[i]=tree[2*i]+tree[2*i+1];
        }

    }
    public void update(int i, int val) {
        i=i+n;
        tree[i]=val;
        //如果不是左节点就调整为左结点,如果不是右结点就调整为右结点
        while(i>0){
            int left=i;
            int right=i;
            if(left%2==1){
                left--;
            }
            if(right%2==0){
                right++;
            }
            tree[i/2]=tree[left]+tree[right];//利用性质更新
            i=i/2;
        }
    }

    //如果左边界是左节点,就往上找,否则往右找。右边界同理
    public int sumRange(int i, int j) {
        i=i+n;
        j=j+n;
        int sum=0;
        
        while(i<=j){
            //左边界不是左节点,往右找
            if(i%2==1){
                sum+=tree[i];
                i++;
            }
            //右边界不是右节点,往左找
            if(j%2==0){
                sum+=tree[j];
                j--;
            }
            i=i/2;
            j=j/2;
        }
        return sum;
    }
}



时间、空间复杂度:

LeetCode解析------307.区域和检索 - 数组可修改-线段树_第2张图片

结语:
晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!晚安!

你可能感兴趣的:(leetcode,编程算法,数据结构,算法,leetcode,java)