樹狀數(shù)組

樹狀數(shù)組(Binary Index Tree, BIT)是用用數(shù)組來模擬樹形結(jié)構(gòu)躺孝。最簡單的樹狀數(shù)組支持兩種操作,時間復(fù)雜度均為O(\log? n)

  • 單點(diǎn)修改:更改數(shù)組中一個元素的值
  • 區(qū)間查詢:查詢一個區(qū)間內(nèi)所有元素的和
樹狀數(shù)組-01.png

數(shù)組的構(gòu)建:

int[] tree = new int[len];

求前n項(xiàng)和:

求和時需要如此計(jì)算SUM_i=C[i]+C[i-2^(k1)]+C[i-2^(k1)-2^(k2)]+···,那么2^k應(yīng)該通過i&(-i)凄敢。求和就是不斷地去掉二進(jìn)制數(shù)最右邊的一個1的過程迅细。

public int query(int n) {
    int res = 0;
    for (int i = n; i > 0; i -= lowbit(i)) res += tree[i];
}

以計(jì)算前7項(xiàng)的和為例衅谷,最終結(jié)果會依次將C[7]C[6]膀斋、C[4]求和梭伐。

為什么使用i&(-i)替代2^k呢?

這里利用的負(fù)數(shù)的存儲特性仰担,負(fù)數(shù)是以補(bǔ)碼存儲的糊识,對于整數(shù)運(yùn)算x&(-x)有:

  • 當(dāng)x為0時,0&0=0
  • 當(dāng)x為奇數(shù)時摔蓝,最后一個比特位為1赂苗,取反加1沒有進(jìn)位,故x-x除最后一位外前面的位正好相反贮尉,按位與結(jié)果為0拌滋。結(jié)果為1
  • 當(dāng)x為偶數(shù)猜谚,且為2m次方時败砂,x的二進(jìn)制表示中只有一位是1(從右往左的第m+1位)赌渣,其右邊有m0,故x取反加1后昌犹,從右到左第有m個0坚芜,第m+1位及其左邊全是1。這樣斜姥,x&(-x)得到的就是x鸿竖。
  • 當(dāng)x為偶數(shù),卻不為2m次方的形式時疾渴,可以寫作x=y*(2^k)千贯,y的最低位為1x就是一個奇數(shù)左移k位來表示搞坝。這時搔谴,x的二進(jìn)制表示最右邊有k0,從右往左第k+1位為1桩撮。當(dāng)對x取反時敦第,最右邊的k0變成1,第k+1位變?yōu)?code>0店量;再加1芜果,最右邊的k位就又變成了0,第k+1位因?yàn)檫M(jìn)位的關(guān)系變成了1融师。左邊的位因?yàn)闆]有進(jìn)位右钾,正好和x原來對應(yīng)的位上的值相反。二者按位與旱爆,得到:第k+1位上為1舀射,左邊右邊都為0。結(jié)果為2^k怀伦。

總結(jié)一下:x&(-x)脆烟,當(dāng)x0時結(jié)果為0x為奇數(shù)時房待,結(jié)果為1邢羔;x為偶數(shù)時,結(jié)果為x2的最大次方的因子桑孩。

public int lowbit(int x) {
    return x & -x;
}

區(qū)間求和:

public int query(int a, int b) {
    return query(b) - query(a - 1);
}

單點(diǎn)修改:

public void update(int p, int v) {
    for (int i = p; i < len; i += lowbit(i)) tree[i] += v; 
}

下面針對775. 全局倒置與局部倒置問題使用樹狀數(shù)組進(jìn)行解決:

class Solution {

    public boolean isIdealPermutation(int[] nums) {
        int len = nums.length;
        int l = 0, g = 0;
        // local
        for (int i = 1; i < len; i++) {
            if (nums[i - 1] > nums[i]) {
                l++;
            }
        }

        // global
        int[] tree = new int[len + 1];
        for (int i = 1; i <= len; i++) {
            update(tree, nums[i - 1] + 1, 1);
            g += i - query(tree, nums[i - 1] + 1);
        }
        return l == g;
    }

    public int lowbit(int x) {
        return x & -x;
    }
    
    public void update(int[] tree, int p, int v) {
        for (int i = p; i < tree.length; i += lowbit(i)) {
            tree[i] += v;
        }
    }

    public int query(int[] tree, int n) {
        int ans = 0;
        for (int i = n; i > 0; i -= lowbit(i)) {
            ans += tree[i];
        }
        return ans;
    }

}

參考文獻(xiàn):

  1. 算法學(xué)習(xí)筆記(2) : 樹狀數(shù)組
  2. 樹狀數(shù)組詳解
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末拜鹤,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子流椒,更是在濱河造成了極大的恐慌署惯,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件镣隶,死亡現(xiàn)場離奇詭異极谊,居然都是意外死亡诡右,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門轻猖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來帆吻,“玉大人,你說我怎么就攤上這事咙边〔轮螅” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵败许,是天一觀的道長王带。 經(jīng)常有香客問我,道長市殷,這世上最難降的妖魔是什么饼记? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任躬充,我火速辦了婚禮荧琼,結(jié)果婚禮上缅阳,老公的妹妹穿的比我還像新娘。我一直安慰自己音羞,他們只是感情好囱桨,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嗅绰,像睡著了一般舍肠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上窘面,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天翠语,我揣著相機(jī)與錄音,去河邊找鬼民镜。 笑死啡专,一個胖子當(dāng)著我的面吹牛险毁,可吹牛的內(nèi)容都是我干的制圈。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼畔况,長吁一口氣:“原來是場噩夢啊……” “哼鲸鹦!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起跷跪,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤馋嗜,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后吵瞻,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體葛菇,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡甘磨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了眯停。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片济舆。...
    茶點(diǎn)故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖莺债,靈堂內(nèi)的尸體忽然破棺而出滋觉,到底是詐尸還是另有隱情,我是刑警寧澤齐邦,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布椎侠,位于F島的核電站,受9級特大地震影響措拇,放射性物質(zhì)發(fā)生泄漏我纪。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一儡羔、第九天 我趴在偏房一處隱蔽的房頂上張望宣羊。 院中可真熱鬧,春花似錦汰蜘、人聲如沸仇冯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽苛坚。三九已至,卻和暖如春色难,著一層夾襖步出監(jiān)牢的瞬間泼舱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工枷莉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留娇昙,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓笤妙,卻偏偏與公主長得像冒掌,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蹲盘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容