zoukankan      html  css  js  c++  java
  • segment树(线段树)

    线段树(segment tree)是一种Binary Search Tree或者叫做ordered binary tree。对于线段树中的每一个非叶子节点[a,b],它的左子树表示的区间为[a,(a+b)/2],右子树表示的区间为[(a+b)/2+1,b]。如下图:

                                                                     [0-2]

                                                                    /      

                                                             [0-1]          [2-2]

                                                             /    

                                                        [0-0]    [1-1]

    下面看一道leetcode上的题,求动态区间的和(Range Sum Query - Mutable),题目如下:

    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

    分析如下:

    一、构造线段树节点:

        class SegmentTreeNode {
            int start, end;
            int sum;
            SegmentTreeNode ltree, rtree;
            public SegmentTreeNode(int s, int e) {
                start = s;
                end = e;
            }
        }

    二、建立线段树(根据数组nums,建立一个动态区间求和的线段树):

        public SegmentTreeNode buildTree(int[] nums, int left, int right) {
            SegmentTreeNode root = new SegmentTreeNode(left, right);
            if (left == right) {
                root.sum = nums[left];
            } else {
                int mid = left + (right - left)/2;
                root.ltree = buildTree(nums, left, mid);
                root.rtree = buildTree(nums, mid+1, right);
                root.sum = root.ltree.sum + root.rtree.sum;
            }
            return root;
        }

    三、线段树的更新(更新int数组下标i的值为val):

        private void update(SegmentTreeNode root, int i, int val) {
            if (root.start == root.end) {
                root.sum = val;
            } else {
                int mid = root.start + (root.end-root.start)/2;
                if (i <= mid) {
                    update(root.ltree, i, val);
                } else {
                    update(root.rtree, i, val);
                }
                root.sum = root.ltree.sum + root.rtree.sum;
            }
        }

    四、线段树的查询(查询int数组下标 i 到 j 的元素之和):

        private int sumRange(SegmentTreeNode root, int i, int j) {
            if (root.start == i && root.end == j) {
                return root.sum;
            } else {
                int mid = root.start + (root.end - root.start)/2;
                if (j <= mid) {
                    return sumRange(root.ltree, i, j);
                } else if (i > mid) {
                    return sumRange(root.rtree, i, j);
                } else {
                    return sumRange(root.ltree, i, root.ltree.end) + sumRange(root.rtree, root.rtree.start, j);
                }
            }
        }

    综上所述,上面Range Sum Query - Mutable的AC代码如下:

    class SegmentTreeNode {
        int start, end;
        int sum;
        SegmentTreeNode ltree, rtree;
        public SegmentTreeNode(int s, int e) {
            start = s;
            end = e;
        }
    }
    
    public class NumArray {
        SegmentTreeNode root = null;
        
        public NumArray(int[] nums) {
            if(nums == null || nums.length == 0) {
                return;
            }
            root = buildTree(nums, 0, nums.length-1);
        }
    
        public SegmentTreeNode buildTree(int[] nums, int left, int right) {
            SegmentTreeNode root = new SegmentTreeNode(left, right);
            if (left == right) {
                root.sum = nums[left];
            } else {
                int mid = left + (right - left)/2;
                root.ltree = buildTree(nums, left, mid);
                root.rtree = buildTree(nums, mid+1, right);
                root.sum = root.ltree.sum + root.rtree.sum;
            }
            return root;
        }
        
        void update(int i, int val) {
            update(root, i, val);
        }
    
        private void update(SegmentTreeNode root, int i, int val) {
            if (root.start == root.end) {
                root.sum = val;
            } else {
                int mid = root.start + (root.end-root.start)/2;
                if (i <= mid) {
                    update(root.ltree, i, val);
                } else {
                    update(root.rtree, i, val);
                }
                root.sum = root.ltree.sum + root.rtree.sum;
            }
        }
    
        public int sumRange(int i, int j) {
             return sumRange(root, i, j);
        }
    
        private int sumRange(SegmentTreeNode root, int i, int j) {
            if (root.start == i && root.end == j) {
                return root.sum;
            } else {
                int mid = root.start + (root.end - root.start)/2;
                if (j <= mid) {
                    return sumRange(root.ltree, i, j);
                } else if (i > mid) {
                    return sumRange(root.rtree, i, j);
                } else {
                    return sumRange(root.ltree, i, root.ltree.end) + sumRange(root.rtree, root.rtree.start, j);
                }
            }
        }
    }
  • 相关阅读:
    google jQuery 1.4.2引用文件,jQuery 1.4.2 引用地址,jQuery引用地址
    html input checkbox js,jQuery
    HTML <fieldset> 标签
    ul 水平,行内块放置,取消点点
    C# Xml 操作
    DropDownList 下拉菜单控件
    jQuery,js : missing)after argument list
    PHP会员权限设计
    主流ETL工具选型
    windows XP下MySQL Cluster集群安装配置 .
  • 原文地址:https://www.cnblogs.com/lasclocker/p/4979933.html
Copyright © 2011-2022 走看看