树状数组算法

1.思考

        已知存在长度为n的数组,批量修改指定元素,每次增加val,如何快速求解指定范围内[n,m]区间元素的和。

a.暴力

        单次修改:O(1)

        单次求和:O(n)

        n次修改:O(n)

        n次求和:O(n^2)

b.合并

        (1)如果将元素两两合并进行存储时

        单次修改:2

        单次求和:n/2

        n次修改:2n

        n次求和:(n^2)/2

        如果四个合并一次,八个合并一次那。。。。

2.树状数组

        a.前置知识lowbit(x)

        b.推导

                根据b.合并中合并多次的时是否可以移除重复项,使用其他已有的结果进行组合求值那?

        规律总结:

        上面时树状数组的结构图,t[x]保存以x为根的子数中叶子节点值的和,原数组为a[]
那么原数组前4项的和t[4]=t[2]+t[3]+a[4]=t[1]+a[2]+t[3]+a[4]=a[1]+a[2]+a[3]+a[4],我们通过观察节点的二进制数,进一步发现,树状数组中节点x的父节点为x+lowbit(x),例如t[2]的父节点为t[4]=t[2+lowbit(2)]   

c.场景

        1.单点修改,单点查询,

        2.区间修改,单点查询,

        3.区间查询,区间修改

d.模板

public class NumArray {
    int[] nums;
    int[] tree;
    int n;
    public  NumArray(int[] nums) {
        n = nums.length;
        this.nums = nums;
        tree = new int[n + 1];
        for(int i = 0; i < n; i++){
            add(i + 1, nums[i]);
        }
    }
    //单点新增
    void add(int x, int u) {
        for (int i = x; i <= n; i += lowBit(i)) {
            tree[i] += u;
        }
    }
    //单点求和
    int query(int x) {
        int ans = 0;
        for (int i = x; i > 0; i -= lowBit(i)) {
            ans += tree[i];
        }
        return ans;
    }
    //单点更新
    public void update(int i, int val) {
        add(i, val - nums[i-1]);
        nums[i-1] = val;
    }
    //区间求和
    public int sumRange(int l, int r) {
        if (r >n){
            return  0;
        }
        return query(r) - query(l-1);
    }

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

    public static void main(String[] args) {
        int[] nums = {1,2,3,4,5,6,7,8,9,10};
        NumArray numArray = new NumArray(nums);

        System.out.println(numArray.sumRange(9,10));
    }
}

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值