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

資訊專欄INFORMATION COLUMN

運(yùn)用樹(shù)狀數(shù)組解決動(dòng)態(tài)數(shù)組求和

Barrior / 886人閱讀

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

對(duì)于一組一維數(shù)組解決前n項(xiàng)和,如果使用linear scan的方法, 需要O(n)的時(shí)間來(lái)找到前n項(xiàng)數(shù)字的和,但是可以用O(1)的時(shí)間來(lái)更新對(duì)應(yīng)數(shù)字的值,但是仍然需要Linear的時(shí)間來(lái)更新?tīng)砍兜较鄳?yīng)數(shù)字?jǐn)?shù)組的和,相反可以使用樹(shù)狀數(shù)組來(lái)降低運(yùn)行時(shí)間求數(shù)組內(nèi)一段數(shù)組的和,但同樣我們?cè)黾恿烁聵?shù)狀數(shù)組內(nèi)任意節(jié)點(diǎn)數(shù)值的時(shí)間。
樹(shù)狀數(shù)組(Binary Indexed Tree)中每個(gè)節(jié)點(diǎn)的值是原數(shù)組中一個(gè)或幾個(gè)數(shù)組的和,所以在原數(shù)組中進(jìn)行求和操作就是在樹(shù)狀數(shù)組中進(jìn)行節(jié)點(diǎn)的求和操作, 相對(duì)應(yīng)的時(shí)間復(fù)雜度為O(logN)

Binary Index Tree 基于二進(jìn)制編碼建立:

需要保持一個(gè)原始數(shù)組a[], 和新建立一個(gè)樹(shù)狀數(shù)組e[],相對(duì)應(yīng)的二進(jìn)制編碼:

1 : 1     a[1]
2 : 10    e[2] = e[1] + a[2];
3 : 011   e[3] = a[3];
4 : 110   e[4] = e[2] + e[3] + a[4];
5 : 101   e[5] = a[5];
6 : 110   e[6] = e[5] + e[6];
7 : 111   e[7] = a[7];
8 : 1000  e[8] = e[4] + e[6] + e[7] + a[8];
e[4] = a[1] + a[2] + a[3] + a[4];

如果二進(jìn)制表示中末尾有連續(xù)的0,則e[i]是原數(shù)組中2^k數(shù)值的和
因此可以通過(guò)計(jì)算e[i]的前驅(qū)和后繼節(jié)點(diǎn)來(lái)計(jì)算出相對(duì)應(yīng)e[i]的值,實(shí)現(xiàn)方法:
lowBit = (i & (-i))
因此,我們有一個(gè)數(shù)組:

int[] nums;
public int[] NumArray(int[] nums) {
    this.nums = nums;
    //Binary Indexed Trees
    int[] tree = new int[nums.length + 1];
    for(int i = 0; i < tree.length; i++) {
        sum = 0;
        lowBit = i & (-i);
        for(int j = i; i > i - lowBit; j--) {
            sum += sum + nums[j - i];
        }
        tree[i] = sum;
}
public void update(int i, int val) {
    //更新差值,從后往前相加
    int diff = val - nums[i];
    nums[i] = val;
    i++;
    for(; i < tree.length; i++) {
        tree[i] += diff;
    }
}
public void sumRange(int i, int j) {
    return sum(i + j) - sum(i);
}
private int sumRange(int i, int j) {
    int sum = 0;
    for(int i = k; i > 0; i -= i & (-i)) {
        sum += tree[i];
    }
    return sum;
}

Binary Index Tree 主要運(yùn)用是 Range Sum with Mutable Elements:

Range Sum with Mutable Elements 1D
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

class Solution{
    int[] nums;
    int[] tree;
    int size;
    
    //time: O(nlogn)
    public RangeSumQueryMutable(int[] nums) {
        this.size = nums.length;
        this.tree = new int[size + 1];
        this.nums = new int[size];
    
        for(int i = 0; i < n; i++) {
            updateTree(i, nums[i]);
        }
   }
   
   public void updateTree(int i, int val) {
       i = i + 1;
       while(i < size) {
           tree[i] += val;
           i += i & (-i); //the last set bits, 2s compliment
       }
   }
   
   public void update(int i, int val) {
       if(size == 0) return;
       update(i, val - nums[i]);
       nums[i] = val;
   }
   
   public int sumRange(int i, int j) {
       if(i == 0) return j;
       return getSum(j) - getSum(i - 1);     
   }
   
   private void getSum(int i) {
      int sum = 0;
      i = i + 1;
      while(i > 0) {
          sum += tree[i];
          i -= i & (-i);//go to ancestor
      }
      return sum;
   }


Range Sum with Mutable Elements 2D
Given matrix =

  [[3, 0, 1, 4, 2],
  [5, 6, 3, 2, 1],
  [1, 2, 0, 1, 5],
  [4, 1, 0, 1, 7],
  [1, 0, 3, 0, 5]]

sumRegion(2, 1, 4, 3) -> 8
update(3, 2, 2)
sumRegion(2, 1, 4, 3) -> 10

class Solution {
    int[][] nums;
    int[][] tree;
    int rows;
    int cols;
    public class RangeSum2D(int[][] nums) {
        rows = nums.length;
        cols = nums[0].length;
        nums = new int[rows][cols];
        tree = new int[rows + 1][cols + 1];
        for(int i = 0; i < rows; i++) {
            for(int j = 0; j < cols; j++) {
                update(nums[i][j], i, j);
            }
        }
    }
    public void update(int val, int row, int col) {
        int diff = val - nums[i][j];
        nums[row][col] = val;
        for(int i = row + 1; i < rows; i += (i & (-i))) {
            for(int j = col + 1; i < cols; j += (j & (-j))) {
                tree[i][j] += diff;
            }
        }
    }
   public int sumRegion(int row1, int col1, int row2, int col2) {
        return getSum(row2 + 1, col2 + 1) + getSum(row1, col1) - getSum(row1, col2 + 1) - getSum(row2 + 1, col1);
   }

    private int getSum(int i, int j) {
        int sum = 0;
        for(int i = rows; i > 0; i -= (i & (-i))) {
            for(int j = cols; j > 0; j -= (j & (-j)) {
                sum += tree[i][j];
            }
        }
        return sum;
    }
    //O(m * logn * n * logn)

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

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

相關(guān)文章

  • 斐波那契數(shù)列求和的js方案以及優(yōu)化

    摘要:在上做了一道斐波那契數(shù)列求和的題目,做完之后做了一些簡(jiǎn)單的優(yōu)化和用另一種方法實(shí)現(xiàn)。動(dòng)態(tài)規(guī)劃解決方案斐波那契數(shù)列求和除了可以用遞歸的方法解決,還可以用動(dòng)態(tài)規(guī)劃的方法解決。 在codewars上做了一道斐波那契數(shù)列求和的題目,做完之后做了一些簡(jiǎn)單的優(yōu)化和用另一種方法實(shí)現(xiàn)。 題目 function fibonacci(n) { if(n==0 || n == 1) r...

    xinhaip 評(píng)論0 收藏0
  • 遞歸就這么簡(jiǎn)單

    摘要:那么,有了循環(huán),為什么還要用遞歸呢在某些情況下費(fèi)波納切數(shù)列,漢諾塔,使用遞歸會(huì)比循環(huán)簡(jiǎn)單很多很多話說(shuō)多了也無(wú)益,讓我們來(lái)感受一下遞歸吧。 遞歸介紹 本來(lái)預(yù)算此章節(jié)是繼續(xù)寫(xiě)快速排序的,然而編寫(xiě)快速排序往往是遞歸來(lái)寫(xiě)的,并且遞歸可能不是那么好理解,于是就有了這篇文章。 在上面提到了遞歸這么一個(gè)詞,遞歸在程序語(yǔ)言中簡(jiǎn)單的理解是:方法自己調(diào)用自己 遞歸其實(shí)和循環(huán)是非常像的,循環(huán)都可以改寫(xiě)成遞歸...

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

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

0條評(píng)論

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