成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

leetcode307. Range Sum Query - Mutable

Lemon_95 / 918人閱讀

摘要:題目要求可以先參考數(shù)組不發(fā)生變動(dòng)時(shí)的題目。最后的葉節(jié)點(diǎn)為當(dāng)前數(shù)組的值,非葉結(jié)點(diǎn)則記錄了子數(shù)組的范圍以及該子數(shù)組中所有元素的和。它是一個(gè)非常輕量級(jí)的數(shù)據(jù)結(jié)構(gòu),而且?guī)缀蹙褪菫檫@種題目量身打造。

題目要求
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.

可以先參考數(shù)組不發(fā)生變動(dòng)時(shí)的題目。

這里的難度在于數(shù)組可以在中間出現(xiàn)變動(dòng),那么面對(duì)大容量數(shù)組的時(shí)候如何選擇一個(gè)合適的數(shù)據(jù)結(jié)構(gòu)及很重要。

思路一:map緩存

最開始我們有兩種直觀的想法,一種是在插入時(shí)同時(shí)更新后面所有的和,這意味著O(n)的插入復(fù)雜度和O(1)的讀取復(fù)雜度。我決定選擇第二種方式,也就是采用類似日志的形式記錄下每一次的變更。這樣當(dāng)我們讀取的時(shí)候,再遍歷日志,將相關(guān)的變更結(jié)果添加到當(dāng)前的數(shù)值上。缺點(diǎn)是,變更很多以及數(shù)組很龐大時(shí),效率依然很差。

這個(gè)方法超時(shí)了。

private int[] sum;
    private int[] nums;
    private Map log;
    public NumArray(int[] nums) {
        this.nums = nums;
        sum = new int[nums.length];
        for(int i = 0 ; i();
    }
    
    public void update(int i, int val) {
        log.put(i, val - nums[i]);
    }
    
    public int sumRange(int i, int j) {
        int origin = 0;
        if(i==0) origin = sum[j];
        else origin = sum[j] - sum[i-1];
        for(Integer key : log.keySet()){
            if(key>=i && key <= j){
                origin += log.get(key);
            }
        }
        return origin;
    } 
思路二:Segment Tree

我們將一個(gè)數(shù)組轉(zhuǎn)化為一棵樹,其中當(dāng)前的數(shù)組被均勻的分割并且分別用左子數(shù)組和右子數(shù)組構(gòu)建左子樹和右子樹。最后的葉節(jié)點(diǎn)為當(dāng)前數(shù)組的值,非葉結(jié)點(diǎn)則記錄了子數(shù)組的范圍以及該子數(shù)組中所有元素的和。

舉個(gè)例子說明一下:
假設(shè)當(dāng)前的數(shù)組為[1,2,5],則構(gòu)成的Segment Tree為:

        8
       / 
      3   5
     / 
    1   2

這里先將[1,2,5]分割為[1,2][5]兩個(gè)子數(shù)組,然后分別構(gòu)造子樹。最后的樹如上所示。

    class SegmentTreeNode{
        int start;
        int end;
        SegmentTreeNode left;
        SegmentTreeNode right;
        int sum;
        
        public SegmentTreeNode(int start, int end){
            this.start = start;
            this.end = end;
        }
    }
    
    private SegmentTreeNode buildSegmentTree(int[] nums, int start, int end){
        if(start > end) return null;
        SegmentTreeNode cur = new SegmentTreeNode(start, end);
        if(start == end) cur.sum = nums[start];
        else{
            int mid = (start + end) / 2;
            cur.left = buildSegmentTree(nums, start, mid);
            cur.right = buildSegmentTree(nums, mid+1, end);
            cur.sum = cur.left.sum + cur.right.sum;
        }
        return cur;
    }
    
    private SegmentTreeNode root;
    public NumArray(int[] nums) {
        this.root = buildSegmentTree(nums, 0, nums.length-1);
    }
    
    public void update(int i, int val) {
        update(root, i, val);
    }
    
    private void update(SegmentTreeNode root, int position, int val){
        if(root.start == root.end){
            root.sum = val;
        }else{
            int mid = (root.start + root.end) / 2;
            if(position <= mid){
                update(root.left, position, val);
            }else{
                update(root.right, position, val);
            }
            root.sum = root.left.sum + root.right.sum;
        }
    }
    
    public int sumRange(int i, int j) {
        return sumRange(root, i, j);
    }    
    
    public int sumRange(SegmentTreeNode root, int i, int j){
        if(root.start==i && root.end==j){
            return root.sum;
        }
        int mid = (root.start + root.end )/2;
        if(j<=mid){
            return sumRange(root.left, i, j);
        }else if(i>mid){
            return sumRange(root.right, i, j);
        }else{
            return sumRange(root.left, i, mid) + sumRange(root.right, mid+1, j);
        }
    }

要想了解更多關(guān)于Segment Tree,請(qǐng)參考這篇文章。

思路三:Binary Indexed Tree

網(wǎng)上有非常多的關(guān)于二進(jìn)制索引數(shù)樹的教程。它是一個(gè)非常輕量級(jí)的數(shù)據(jù)結(jié)構(gòu),而且?guī)缀蹙褪菫檫@種題目量身打造??梢韵葟倪@篇文章和這篇文章了解一下。

    class NumArray {
           int[] nums;
            int[] BIT;
            int n;

            public NumArray(int[] nums) {
                this.nums = nums;

                n = nums.length;
                BIT = new int[n + 1];
                for (int i = 0; i < n; i++)
                    init(i, nums[i]);
            }

            //每次更新當(dāng)前節(jié)點(diǎn)的同時(shí)更新父節(jié)點(diǎn)
            public void init(int i, int val) {
                i++;
                while (i <= n) {
                    BIT[i] += val;
                    i += (i & -i);
                }
            }

            //更新當(dāng)前節(jié)點(diǎn),同時(shí)將改變傳遞給父節(jié)點(diǎn)
            void update(int i, int val) {
                int diff = val - nums[i];
                nums[i] = val;
                init(i, diff);
            }

            //
            public int getSum(int i) {
                int sum = 0;
                i++;
                while (i > 0) {
                    sum += BIT[i];
                    i -= (i & -i);
                }
                return sum;
            }

            public int sumRange(int i, int j) {
                return getSum(j) - getSum(i - 1);
            }
        }


想要了解更多開發(fā)技術(shù),面試教程以及互聯(lián)網(wǎng)公司內(nèi)推,歡迎關(guān)注我的微信公眾號(hào)!將會(huì)不定期的發(fā)放福利哦~

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/68694.html

相關(guān)文章

  • Range Sum Query

    摘要:表現(xiàn)在二進(jìn)制上的規(guī)律每次加上最末尾的求末尾的就拿這個(gè)數(shù)和它的補(bǔ)碼于。還有要求不是,要轉(zhuǎn)換一下,和之前那道的思路差不多。這里用一個(gè)的表示從到的和。 Range Sum Query - Immutable Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), i...

    zhongmeizhi 評(píng)論0 收藏0
  • leetcode303-304 Range Sum Query Immutable

    摘要:假設(shè)有一個(gè)整數(shù)數(shù)組,計(jì)算下標(biāo)從到包含和的數(shù)字的和。求和的請(qǐng)求將會(huì)在同一個(gè)整數(shù)數(shù)組上多次請(qǐng)求。這一題思路很簡(jiǎn)單,因?yàn)椤6脛?dòng)態(tài)規(guī)劃則很容易知道。這里將原先的一維數(shù)組替換成二維數(shù)組。要求計(jì)算一個(gè)矩形內(nèi)的所有元素的值。 Range Sum Query Immutable Given an integer array nums, find the sum of the elements be...

    Worktile 評(píng)論0 收藏0
  • [LeetCode] 304. Range Sum Query 2D - Immutable

    Problem Given a 2D matrix matrix, find the sum of the elements inside the rectangle defined by its upper left corner (row1, col1) and lower right corner (row2, col2). https://leetcode.com/static/i...s...

    chinafgj 評(píng)論0 收藏0
  • [LeetCode] Range Sum Query Immutable

    Problem Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. Example Given nums = [-2, 0, 3, -5, 2, -1] sumRange(0, 2) -> 1 sumRange(2, 5) -> -1 sumRan...

    LiuZh 評(píng)論0 收藏0
  • 運(yùn)用樹狀數(shù)組解決動(dòng)態(tài)數(shù)組求和

    摘要:對(duì)于一組一維數(shù)組解決前項(xiàng)和,如果使用的方法需要的時(shí)間來找到前項(xiàng)數(shù)字的和,但是可以用的時(shí)間來更新對(duì)應(yīng)數(shù)字的值但是仍然需要的時(shí)間來更新牽扯到相應(yīng)數(shù)字?jǐn)?shù)組的和,相反可以使用樹狀數(shù)組來降低運(yùn)行時(shí)間求數(shù)組內(nèi)一段數(shù)組的和,但同樣我們?cè)黾恿烁聵錉顢?shù)組內(nèi) 對(duì)于一組一維數(shù)組解決前n項(xiàng)和,如果使用linear scan的方法, 需要O(n)的時(shí)間來找到前n項(xiàng)數(shù)字的和,但是可以用O(1)的時(shí)間來更新對(duì)應(yīng)數(shù)...

    Barrior 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<