zoukankan      html  css  js  c++  java
  • 线段树模版

    题目:https://leetcode-cn.com/problems/range-sum-query-mutable/

    给定一个整数数组  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

    说明:

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

    思路:

    线段树可以分为以下三个步骤:

    1. 从给定数组构建线段树的预处理步骤。
    2. 修改元素时更新线段树。
    3. 使用线段树进行区域和检索。

     

     

    //经典题型:线段树
    public class P307RangeSumQueryMutable {
    
        public static void main(String[] args) {
    
            NumArray obj = new NumArray(new int[]{1, 3, 5, 8});
            System.out.println(obj.sumRange(0, 3));
            obj.update(1, 2);
            System.out.println(obj.sumRange(0, 3));
        }
    
        static class NumArray {
    
            int[] arr;
            int numsLength;
    
            //构建初始化线段树[n,2n)和(0,n-1],一共有2n-1个数据,从[n,2n-1]的是输入的nums,从[1,n-1]是计算出的线段和
            public NumArray(int[] nums) {
                int len = nums.length;
                if (len > 0) {
                    arr = new int[2 * len];
                    numsLength = len;
                    for (int i = len; i < 2 * len; i++) {
                        arr[i] = nums[i - len];
                    }
    
                    //从后向前计算arr[i] = arr[2*i] + arr[2*i + 1],左节点为偶数节点,右节点为奇数节点
                    for (int i = len - 1; i > 0; i--) {
                        arr[i] = arr[2 * i] + arr[2 * i + 1];
                    }
                }
            }
    
            //每次更新都要从下向上更新父节点直至根节点
            public void update(int i, int val) {
                //先计算节点在arr数组的位置
                int position = i + numsLength;
                arr[position] = val;
    
                //从下向上更新到根节点
                while (position > 0) {
                    //当前在左节点
                    if ((position % 2) == 0) {
                        arr[position / 2] = arr[position] + arr[position + 1];
                    } else { //当前在右节点
                        arr[position / 2] = arr[position - 1] + arr[position];
                    }
    
                    //向上为父节点
                    position /= 2;
                }
            }
    
          
    //区域和检索每次确保左边界为偶数,右边界为奇数然后同时除以2 //如果左边界不为偶数,则当前和加上当前左边界值,左边界向右移动一位,然后除以2 //如果右边界不为奇数,则当前和加上当前右边界值,右边界向左移动一位,然后除以2 //直到左边界大于右边界截止 public int sumRange(int i, int j) { int sum = 0; //移动到arr正确的位置上 i += numsLength; j += numsLength; while (i <= j) { //左边界为奇数 if ((i % 2) == 1) { sum += arr[i]; i++; } //右边界为偶数 if ((j % 2) == 0) { sum += arr[j]; j--; } i /= 2; j /= 2; } return sum; } } }

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/range-sum-query-mutable

  • 相关阅读:
    loader加载png,并复制多份
    FLVPlayback应用
    Android自定义ExpandableListView
    Android startActivityForResult的使用
    Android中ExpandableListView的使用
    Android基础 获取手机分辨率、状态栏、标题栏高度
    Java 字符串拼接方式
    Java String字符串拼接,截取,查找及日期转换
    android中使用startActivityForResult回传数据
    android tabhost位于底部
  • 原文地址:https://www.cnblogs.com/zhihaospace/p/12607664.html
Copyright © 2011-2022 走看看