1. 程式人生 > >Binary Indexed Tree(二進位制索引樹、樹狀陣列)

Binary Indexed Tree(二進位制索引樹、樹狀陣列)

今天在刷leetcode時遇到了一道可以使用Binary Indexed Tree的題,以前未接觸過,記下來以便以後複習

Binary Indexed Tree(樹狀陣列)是一種樹型資料結構,用於動態維護一個序列的字首和。在實踐中,它幾乎總是用陣列來實現;另外,由於程式碼易於記憶,它的樹型結構很容易被忽略掉。它的中文名稱“樹狀陣列”很可能是因為以上兩個特點得來。

低位(LowBit)

LowBit,即2進位制數中從最低位開始連續0的位數的關於2的冪,其值LowBit(x)=x∧-x(x&-x,x and -x)。也就是上文所說的2^k

LowBit(x)顯然就是not x中最低的是0的那一位,(not x)+1的那一位則會變成1,其更低的位全部變成0,而更高的位不變。由於更高的位就是原數取反,和原數求and的值為0,最低位就是唯一的是1的位了。所以LowBit(x)=x and((not x)+1)。 同時not x=-x-1,所以LowBit(x)=x and (-x)。


上圖就是一個長度為16的陣列的BIT,index(16)就表示落在16以內的個數,同時index(16)=sum(num[1]+num[2]+...+num[16])=index(8)+index(12)+index(14)+num[16]

即用index[i]表示從資料陣列num中某一處一直到num[i]共2^k個元素的總和

讀取累計的頻率和 如果我們需要讀取整數idx的頻率累計和,我們可以讓sum加上tree[idx]的值,然後讓idx減去最有一個1(我們也可以說移走最後的1,使最後的1變為0),然後重複上述過程直至idx為0.我們可以使用下面這段程式碼(C++)。
int read(int idx){
	int sum = 0;
	while (idx > 0){
		sum += tree[idx];
		idx -= (idx & -idx);
	}
	return sum;
}

舉例: idx=13,sum=0:

iteration idx position of the last digit idx & -idx sum
1 13 = 1101 0 1 (2 ^0) 3
2 12 = 1100 2 4 (2 ^2) 14
3 8 = 1000 3 8 (2 ^3) 26
4 0 = 0 --- --- ---
image 1.5 箭頭指示了在遍歷過程中使用的資料.

改變一些位置的頻率並更新tree

當改變某些位置的頻率時,所有tree中負責該位置的都需要更新。在讀取idx的累計和時我們移走idx最後的1並且迴圈繼續。修改tree中的一些值val時,我們需要增加當前idx的tree值tree[idx],增加idx最後一位的1(例如idx為6,該值增加了val,當tree[6]增加了val後。6的最後等於1的一位是2,所以6+2=8,需要繼續修改tree[8]的值)並且迴圈繼續之前的過程,只要idx小於MaxVal.C++寫的函式如下
void update(int idx ,int val){
	while (idx <= MaxVal){
		tree[idx] += val;
		idx += (idx & -idx);
	}
}
例如idx=5:
iteration idx position of the last digit idx & -idx
1 5 = 101 0 1 (2 ^0)
2 6 = 110 1 2 (2 ^1)
3 8 = 1000 3 8 (2 ^3)
4 16 = 10000 4 16 (2 ^4)
5 32 = 100000 --- ---

與普通陣列相比在查詢時時間複雜度變成logn,但增加了插入花銷(普通陣列插入複雜度為O(1),BIT為O(logn))

題目為找出陣列中每個數字後面比這個數小的數的個數

我們可以在將原陣列排序後把問題變成每個數的索引在BIT中有多少比他小的索引,從左向右進行掃描,每掃描完成一個將其在BIT中的佔位從BIT中減去,即可使用nlogn的複雜度完成任務。

題目要求求一個區間內數值的總和,是BIT的長項之一,直接構建BIT,將陣列放到相應的索引內,區間值就是大索引的和減去小索引的和

307程式碼

相關連結:http://www.nocow.cn/index.php/%E6%A0%91%E7%8A%B6%E6%95%B0%E7%BB%84

    http://www.xuebuyuan.com/1396639.html

相關推薦

Binary Indexed Tree(二進位制索引陣列)

今天在刷leetcode時遇到了一道可以使用Binary Indexed Tree的題,以前未接觸過,記下來以便以後複習 Binary Indexed Tree(樹狀陣列)是一種樹型資料結構,用於動態維護一個序列的字首和。在實踐中,它幾乎總是用陣列來實現;另外,由於程式碼

數組(Binary Indexed Tree,BIT)

應該 編碼 第一個 mbg 一個 運算 邏輯結構 元素 簡化 樹狀數組(Binary Indexed Tree) 前面幾篇文章我們分享的都是關於區間求和問題的幾種解決方案,同時也介紹了線段樹這樣的數據結構,我們從中可以體會到合理解決方案帶來的便利,對於大部

陣列Binary Indexed Tree) 總結(ing)

推薦一篇很好的部落格:http://www.cppblog.com/menjitianya/archive/2015/11/02/212171.html 一、樹狀陣列的定義 基本定義:樹狀陣列是利用二分的思想使得查詢和修改的複雜度都為 log(n) 的資料結構,樹狀陣列是通過字首和思想,

陣列 Binary Indexed Tree 學習筆記

看了不少樹狀陣列的資料,講解大多十分清楚,但是都沒有明確的推導過程,所以自己嘗試不那麼嚴謹地推導一下 一個長度為n的陣列C,需要能修改任意位置的數,並求前k個數的和(或者連續k個數的和) 如果直接累加,則修改時間複雜度O(1),求和時間複雜度O(n) 如果使用輔助陣列儲存前k個數的和,則修改時需

陣列Binary Indexed Tree),看這一篇就夠了

定義 根據維基百科的定義: A Fenwick tree or binary indexed tree is a data structure that can efficiently update elements and calculate pr

【LeetCode】線段 segment-tree(共9題)+ 陣列 binary-indexed-tree(共5題)

第一部分---線段樹:https://leetcode.com/tag/segment-tree/   p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px Helvetica } 【218】The Skyline Problem&n

陣列binary indexed tree)

樹狀陣列是一種用於查詢區間和的資料結構。 比如對於陣列a[1,2,3,4,5,6,7,8,9,10],我們要知道它的前4項和,我們就需要把這前四個一個個加起來才能得到結果,也就是O(K)(前k項和)的複雜度。如果查詢次數少,k也比較小還可以接受,但是在大規模的查詢和資料量時

1064. Complete Binary Search Tree (30)【二叉】——PAT (Advanced Level) Practise

function namespace his () 技術 androi sed tel evel 題目信息 1064. Complete Binary Search Tree (30) 時間限制100 ms 內存限制65536 kB 代碼長度限制

[LeetCode]501. Find Mode in Binary Search Tree二叉搜索尋找眾數

pri fin lis 需要 efi lee value spa find 這次是二叉搜索樹的遍歷 感覺只要和二叉搜索樹的題目,都要用到一個重要性質: 中序遍歷二叉搜索樹的結果是一個遞增序列; 而且要註意,在遞歸遍歷樹的時候,有些參數如果是要隨遞歸不斷更新(也就是如果遞歸返

Find Mode in Binary Search Tree 二叉搜索中查找眾數

class div 問題 xtra 空間分析 deb spa pos out [抄題]: Given a binary search tree (BST) with duplicates, find all the mode(s) (the most frequently

132.Find Mode in Binary Search Tree(二分搜索的眾數)

ati 之前 復雜度 i++ cit 二分搜索 無法 treenode 重復 題目: Given a binary search tree (BST) with duplicates, find all the mode(s) (the most frequently oc

[LeetCode] Insert into a Binary Search Tree 二叉搜索中插入結點

original arc long any turn amp there new 二叉 Given the root node of a binary search tree (BST) and a value to be inserted into the tree

[leetcode]270. Closest Binary Search Tree Value二叉搜尋中找target的最接近值

Given a non-empty binary search tree and a target value, find the value in the BST that is closest to the target. Note: Given target

[leetcode]173. Binary Search Tree Iterator 二叉搜尋迭代器

Implement an iterator over a binary search tree (BST). Your iterator will be initialized with the root node of a BST. Calling next() will return

pat-A1043:Is it a Binary Search Tree(二叉搜尋和及其映象的遍歷)

目錄 題目解釋: 解題思路: ac程式碼: 題目地址:https://pintia.cn/problem-sets/994805342720868352/problems/994805440976633856 題目解釋: 給出一個二叉樹的序列,判斷它是否是“二叉搜尋樹

LeetCode 173.Binary Search Tree Iterator (二叉搜尋迭代器)

題目描述: 實現一個二叉搜尋樹迭代器。你將使用二叉搜尋樹的根節點初始化迭代器。 呼叫 next() 將返回二叉搜尋樹中的下一個最小的數。 注意: next() 和hasNext() 操作的時間複雜度是O(1),並使用 O(h)&

LeetCode 98. Validate Binary Search Tree (有效二叉搜尋)

原題 Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as follows: The left subtree of a n

LeetCode 98.Validate Binary Search Tree (驗證二叉搜尋)

題目描述: 給定一個二叉樹,判斷其是否是一個有效的二叉搜尋樹。 假設一個二叉搜尋樹具有如下特徵: 節點的左子樹只包含小於當前節點的數。 節點的右子樹只包含大於當前節點的數。 所有左子樹和右子樹自身必須也是二叉搜尋樹。 示例 1: 輸入: 2 / \

Leetcode 98 Validate Binary Search Tree 驗證二叉查詢

題目描述 Given a binary tree, determine if it is a valid binary search tree (BST). 給出一個二叉樹,判斷其是否是合法的二叉查詢樹。 解題思路 首先,我們來看二叉查詢樹的

173. Binary Search Tree Iterator(二叉查詢迭代器)的C++解法

注意是二叉查詢樹,意味著左子樹<根<右子樹,因此,如果沒有特殊要求,只需要中序遍歷樹,將每個結點儲存即可。 但是題目要求空間複雜度為O(h),h是二叉查詢樹的深度,因此考慮每次只放一部分樹的結點入棧。首先我們知道根的左子樹的左子樹的左子樹...一直到最左的左子樹L一定是最小值,那