吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

一個小而美的算法技巧:差分數組

算法與數據結構 ? 來源:labuladong ? 作者:labuladong ? 2020-09-21 15:54 ? 次閱讀

本文給大家介紹一個小而美的算法技巧:差分數組。

讀完本文,你可以去解決力扣第 1109 題「航班預訂統計」,難度Medium

差分數組技巧是前文前綴和技巧詳解寫過的前綴和技巧的兄弟。

前綴和主要適用的場景是原始數組不會被修改的情況下,頻繁查詢某個區間的累加和。

沒看過前文沒關系,這里簡單介紹一下前綴和,核心代碼就是下面這段:

classPrefixSum{ //前綴和數組 privateint[]prefix; /*輸入一個數組,構造前綴和*/ publicPrefixSum(int[]nums){ prefix=newint[nums.length+1]; //計算nums的累加和 for(inti=1;i

prefix[i]就代表著nums[0..i-1]所有元素的累加和,如果我們想求區間nums[i..j]的累加和,只要計算prefix[j+1] - prefix[i]即可,而不需要遍歷整個區間求和。

本文講一個和前綴和思想非常類似的算法技巧「差分數組」,差分數組的主要適用場景是頻繁對原始數組的某個區間的元素進行增減。

比如說,我給你輸入一個數組nums,然后又要求給區間nums[2..6]全部加 1,再給nums[3..9]全部減 3,再給nums[0..4]全部加 2,再給…

一通操作猛如虎,然后問你,最后nums數組的值是什么?

常規的思路很容易,你讓我給區間nums[i..j]加上val,那我就一個 for 循環給它們都加上唄,還能咋樣?這種思路的時間復雜度是 O(N),由于這個場景下對nums的修改非常頻繁,所以效率會很低下。

這里就需要差分數組的技巧,類似前綴和技巧構造的prefix數組,我們先對nums數組構造一個diff差分數組,diff[i]就是nums[i]和nums[i-1]之差:

int[]diff=newint[nums.length]; //構造差分數組 diff[0]=nums[0]; for(inti=1;i

通過這個diff差分數組是可以反推出原始數組nums的,代碼邏輯如下:

int[]res=newint[diff.length]; //根據差分數組構造結果數組 res[0]=diff[0]; for(inti=1;i

這樣構造差分數組diff,就可以快速進行區間增減的操作,如果你想對區間nums[i..j]的元素全部加 3,那么只需要讓diff[i] += 3,然后再讓diff[j+1] -= 3即可:

原理很簡單,回想diff數組反推nums數組的過程,diff[i] += 3意味著給nums[i..]所有的元素都加了 3,然后diff[j+1] -= 3又意味著對于nums[j+1..]所有元素再減 3,那綜合起來,是不是就是對nums[i..j]中的所有元素都加 3 了?

只要花費 O(1) 的時間修改diff數組,就相當于給nums的整個區間做了修改。多次修改diff,然后通過diff數組反推,即可得到nums修改后的結果。

現在我們把差分數組抽象成一個類,包含increment方法和result方法:

classDifference{ //差分數組 privateint[]diff; publicDifference(int[]nums){ assertnums.length>0; diff=newint[nums.length]; //構造差分數組 diff[0]=nums[0]; for(inti=1;i

這里注意一下increment方法中的 if 語句:

publicvoidincrement(inti,intj,intval){ diff[i]+=val; if(j+1

當j+1 >= diff.length時,說明是對nums[i]及以后的整個數組都進行修改,那么就不需要再給diff數組減val了。

算法實踐

這里看一下力扣第 1109 題「航班預訂統計」:

函數簽名如下:

int[]corpFlightBookings(int[][]bookings,intn)

這個題目就在那繞彎彎,其實它就是個差分數組的題,我給你翻譯一下:

給你輸入一個長度為n的數組nums,其中所有元素都是 0。再給你輸入一個bookings,里面是若干三元組(i,j,k),每個三元組的含義就是要求你給nums數組的閉區間[i-1,j-1]中所有元素都加上k。請你返回最后的nums數組是多少?

PS:因為題目說的n是從 1 開始計數的,而數組索引從 0 開始,所以對于輸入的三元組(i,j,k),數組區間應該對應[i-1,j-1]。

這么一看,不就是一道標準的差分數組題嘛?我們可以直接復用剛才寫的類:

int[]corpFlightBookings(int[][]bookings,intn){ //nums初始化為全0 int[]nums=newint[n]; //構造差分解法 Differencedf=newDifference(nums); for(int[]booking:bookings){ //注意轉成數組索引要減一哦 inti=booking[0]-1; intj=booking[1]-1; intval=booking[2]; //對區間nums[i..j]增加val df.increment(i,j,val); } //返回最終的結果數組 returndf.result(); }

這道題就解決了。

其實我覺得差分數組和前綴和數組都是比較常見且巧妙的算法技巧,分別適用不同的常見,而且是會者不難,難者不會。所以,關于差分數組的使用,你學會了嗎?!

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 算法
    +關注

    關注

    23

    文章

    4630

    瀏覽量

    93359
  • 差分
    +關注

    關注

    0

    文章

    53

    瀏覽量

    21412
  • 數組
    +關注

    關注

    1

    文章

    417

    瀏覽量

    26028

原文標題:論那些小而美的算法技巧:差分數組/前綴和

文章出處:【微信號:TheAlgorithm,微信公眾號:算法與數據結構】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    ADS1256四路分輸出讀取數值間的干擾問題求解答

    =AIN1.并通過發送SYNC 命令緊接WAKEUP 命令從新啟動轉換進程.命令之間的時間滿足手冊要求,接著利用RDATA命令讀取數據,該數據應該是 AIN6與AIN7間的電壓值,將其存入數組Data【3】;. 不斷循環b)
    發表于 01-10 06:30

    有內部模式讓ADS8363里面有兩AD,能AD工作在全分,工作在偽分嗎?

    PDE位只能控制工作2 x 2 fully-differential和4 x 2 pseudo-differential。 有內部模式讓ADS8363里面有兩AD,能AD工作在全
    發表于 01-02 07:57

    美的攜手亞馬遜云科技,提升全球客戶體驗

    近日,亞馬遜云科技宣布了項重要合作成果:全球領先的科技企業美的已成功應用Amazon Connect,在海外14國家和地區迅速且成功地部署了云端全渠道客戶聯絡中心。 這部署不僅展
    的頭像 發表于 12-24 11:48 ?299次閱讀

    數組的下標為什么可以是負數

    最近有同學發來這樣段代碼,并提出問題,數組的下標為什么可以是負數? ? ? #include int main(){ const char *s = "helloworld";
    的頭像 發表于 12-20 11:18 ?165次閱讀

    指針數組和二維數組有沒有區別

    。 首先是指針數組 s1。 s1 本身是數組數組有三元素,每個元素都是
    的頭像 發表于 11-24 11:12 ?218次閱讀

    C語言數組應用計算機導論A第6講:數組

    C語言數組應用計算機導論A第6講:數組
    發表于 11-20 15:33 ?0次下載

    labview字符串數組轉化為數值數組

    常重要的。LabVIEW支持多種數據類型,包括數值、字符串、數組、簇等。在本例中,我們將關注字符串數組和數值數組。 字符串數組 :由系列字
    的頭像 發表于 09-04 17:47 ?2845次閱讀

    為什么電勢計測量的是電池的電動勢不是其端電壓?

    電勢計是種精密的測量儀器,它能夠測量出電池的電動勢,不是其端電壓。
    的頭像 發表于 05-21 15:27 ?2488次閱讀

    .c文件中定義個數組遇到的疑問求解

    .c文件中定義個數組,然后在其他文件中引用,用sizeof求數組長度,那么按說是必須要聲明這個
    發表于 05-14 07:03

    嵌入式中零長度數組基本操作方法

    就是長度為0的數組,也就是說不包含任何元素的數組。零長度數組在C99標準中引入,并在C11中得到進
    的頭像 發表于 05-11 08:49 ?1050次閱讀
    嵌入式中零長度<b class='flag-5'>數組</b>基本操作方法

    while的循環里面,怎么樣可以通過控件去讓其中的數組值全部初始化?

    這種方式是讓所有的數據都初始化了,我只需要部分數據初始化,就是所有的數組,大佬們求幫助!
    發表于 04-18 21:19

    深入探索KUKA KRL中的數組應用

    如果 CHAR 類型數組的所有數組元素都擁有相同的字符串,則不必單獨初始化每個數組元素。忽略右側的數組下標。(對于
    的頭像 發表于 04-18 10:37 ?1341次閱讀
    深入探索KUKA KRL中的<b class='flag-5'>數組</b>應用

    鴻蒙TypeScript入門學習第11天【Array(數組)】

    數組對象是使用單獨的變量名來存儲系列的值。 數組非常常用。
    的頭像 發表于 04-09 14:38 ?1241次閱讀
    鴻蒙TypeScript入門學習第11天【Array(<b class='flag-5'>數組</b>)】

    隨機抽取SV數組中的元素方法實現

    如果想從關聯數組中隨機選取元素,需要逐個訪問它之前的元素,原因是沒辦法能夠直接訪問到第N
    的頭像 發表于 03-21 10:11 ?1118次閱讀
    隨機抽取SV<b class='flag-5'>數組</b>中的<b class='flag-5'>一</b><b class='flag-5'>個</b>元素方法實現

    數組和鏈表在內存中的區別 數組和鏈表的優缺點

    內存中的存儲方式: 數組種連續存儲的數據結構,它將元素存儲在相鄰的內存位置中。這使得數組的訪問效率高,可以通過下標來直接訪問任何
    的頭像 發表于 02-21 11:30 ?1139次閱讀
    顶尖百家乐开户| 网上百家乐官网是真是假天涯论坛| 大发888 894| 百家乐梅花图标| 百家乐官网博彩通网| 德州扑克和梭哈| 半圆百家乐桌布| 百家乐官网的看路技巧| 优博网址| 百家乐好不好| 百家乐官网论坛| 百家乐官网娱乐城体育| 大发888游乐场| 百家乐娱乐注册就送| 百家乐官网免佣台| 永利高足球投注网| 百家乐下注技巧| 百家乐网上最好网站| 网上百家乐官网大赢家| 皇冠娱乐城| sz新全讯网xb112| 克拉克百家乐试玩| 百家乐官网入庄闲概率| 珠海市| 大发888娱乐城帝豪| 网络百家乐诈骗| LV百家乐官网客户端LV| 澳门百家乐官网怎么赢钱| 皇冠网文学网址| 大发888游戏场下载| 百家乐双面数字筹码怎么出千| 百家乐官网最新分析仪| 中国百家乐官网游戏| 镇原县| 大发888在线投注| 宝马会百家乐的玩法技巧和规则| 游戏百家乐押发| HG百家乐官网大转轮| 百家乐官网真人荷官| 皇冠娱乐网| 东京太阳城王子大酒店|