日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

c 最大子序列和_最大子序列和暴力法、分治+递归法、妙法

發(fā)布時(shí)間:2025/1/21 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c 最大子序列和_最大子序列和暴力法、分治+递归法、妙法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

你好,我是goldsunC

讓我們一起進(jìn)步吧!

最大子序列和

Question:給定整數(shù)(可能有負(fù)數(shù)),求的最大值(為方便起見,如果所有整數(shù)均為負(fù)數(shù),則最大子序列和為0)。

示例:IN????:???[-2,11,-4,13,-5,-2]
OUT????:???20??即從A2-A4

暴力求解

第一種思路很簡(jiǎn)單,暴力求解。從數(shù)組第一個(gè)整數(shù)開始遍歷每一種長(zhǎng)度的最大值,然后遍歷之后的最大值即是最大子序列和,如果最大值為負(fù)數(shù)則初始化為0,例如:指定數(shù)組為:[-2,11,-4,13,-5,-2]首先初始化最大值為-2,因?yàn)?2為負(fù)數(shù)所以最大值為0,然后計(jì)算-2+11,然后更新最大值為9,然后計(jì)算-2+11-4,保持當(dāng)前最大值,然后計(jì)算-2+11-4+13,更新最大值為18,一直加到數(shù)組最后一位數(shù),再?gòu)?1開始求最大值,然后再?gòu)?4開始,就這樣把數(shù)組每一種子序列和都遍歷了,求得最大值。源碼(Java):public?class?maxValueSum?{
????public?static?void?main(String[]?args)?{
????????int[]?array?=?{-2,11,-4,13,-5,-2};
????????System.out.println(Max(array));
????}
????public?static?int?Max(int[]?array)?{
????????int?maxnum?=?array[0];
????????for?(int?i=0;i????????????int?currentnum?=?0;
????????????for?(int?j=i;j????????????????currentnum?+=?array[j];
????????????????if?(currentnum>maxnum)
????????????????????maxnum?=?currentnum;
????????????}
????????}
????????return?maxnum;
????}
}
源碼(Python):def?Max(array)?:
????maxnum?=?0
????for?i?in?range(len(array)):
????????num?=?0
????????for?j?in?range(i,len(array)):
????????????num?+=?array[j]
????????????if?num?>?maxnum:
????????????????maxnum?=?num
????return?maxnum
array?=?[-2,11,-4,13,-5,-2]
print(Max(array))
上面暴力求解法很簡(jiǎn)單,但是有個(gè)突出的問(wèn)題,就是時(shí)間復(fù)雜度為O(),當(dāng)涉及到大量輸入的時(shí)候,效率非常低。

分治+遞歸求解

通常來(lái)講,我們遇見遞歸的時(shí)候往往伴隨的還有很高的時(shí)間復(fù)雜度,但對(duì)于這個(gè)問(wèn)題來(lái)講還有一個(gè)使用遞歸+分治實(shí)現(xiàn)的稍微復(fù)雜的方法,其時(shí)間復(fù)雜度卻僅為O(),或許這個(gè)算法就是體現(xiàn)遞歸為例的最好范例了。這個(gè)算法使用一種"分治"的策略,其想法是把問(wèn)題分成兩個(gè)大致相等的子問(wèn)題,然后采用遞歸對(duì)他們求解,這是分,治是將兩個(gè)子問(wèn)題的解合并到一起并再做些少量的附加工作,最后得到整個(gè)問(wèn)題的解。假如將傳入的數(shù)組從中間分成左右兩個(gè)部分,例如:[-2,11,-4,13,-5,-2]->[-2,11,-4]和[13,-5,-2]那么問(wèn)題的解可能出現(xiàn)在三處出現(xiàn):
  • 左半部分[-2,-11,-4]

  • 右半部分[13,-5,-2]

  • 或者橫跨兩個(gè)部分,它一定包括左半部分的最后一個(gè)值和右半部分的第一個(gè)值。

  • 對(duì)上述問(wèn)題求解得:左半部分的最大值為11,右半部分的最大值為13,而橫跨這兩個(gè)部分包含左半部分最后一個(gè)值以及右半部分第一個(gè)值的最大值為20,即11-4+13,將三者對(duì)比,則返回最大值20。而這個(gè)時(shí)候我們求各部分最大值是直接看出來(lái)的,那實(shí)際應(yīng)該怎么求呢?機(jī)器可看不出來(lái),只能靠算法求解。那怎么求?用剛才講過(guò)的暴力求解?那樣的話我們分這一次沒有意義,因此我們需要遞歸地繼續(xù)分下去。看一下算法源碼(Java):public?class?maxVlaueSum2?{
    ????public?static?void?main(String[]?args)?{
    ????????//?初始化數(shù)組
    ????????int[]?array?=?{-2,11,-4,13,-5,-2};
    ????????System.out.println(maxSum(array,0,array.length-1));
    ????}

    ????/**
    ?????*?遞歸求解函數(shù)
    ?????*?@param?array :傳入要解決的數(shù)組
    ?????*?@param?left ?:要解決子問(wèn)題的左界
    ?????*?@param?right :要解決子問(wèn)題的右界
    ?????*?@return??:返回三個(gè)部分的最大值
    ?????*/
    ????public?static?int?maxSum(int[]?array,int?left,int?right)?{
    ????????//?? BASE情況,如果遞歸到了最后一層,那么返回合適的值,小于0返回0,大于0返回該數(shù)。
    ????????if(left?==?right)?{
    ????????????if?(array[left]?>?0)
    ????????????????return?array[left];
    ????????????else?return?0;
    ????????}
    ????????int?center?=?(left+right)/2;????//??取得數(shù)組中點(diǎn)
    ????????int?leftSubSUM?=?maxSum(array,left,center);?????//??子問(wèn)題左半部分最優(yōu)解
    ????????int?rightSubSUM?=?maxSum(array,center+1,right);?????//??子問(wèn)題右半部分最優(yōu)解

    ????????int?leftNowSum?=?0,?maxleftSum?=?0;?????//??當(dāng)前問(wèn)題左半部分等待求和的當(dāng)前值以及最大值

    ????????//??遍歷求包含左半部分最后一個(gè)值的最大值
    ????????for?(int?i=center;i>=left;i--)?{
    ????????????leftNowSum?+=?array[i];
    ????????????if?(leftNowSum?>?maxleftSum)?{
    ????????????????maxleftSum?=?leftNowSum;
    ????????????}
    ????????}
    ????????int?rightNowSum?=?0,maxrightSum?=?0;????//??當(dāng)前問(wèn)題右半部分等待求和的當(dāng)前值以及最大值

    ????????//??遍歷求包含右半部分的第一個(gè)值的最大值
    ????????for?(int?j=center+1;j<=right;j++)?{
    ????????????rightNowSum?+=?array[j];
    ????????????if?(rightNowSum>maxrightSum)?{
    ????????????????maxrightSum?=?rightNowSum;
    ????????????}
    ????????}
    ????????//??返回當(dāng)前問(wèn)題的左半部分最大值、右半部分的最大值和橫跨兩部分最大值的最大值。即為當(dāng)前問(wèn)題的解。
    ????????return?Math.max(Math.max(leftSubSUM,rightSubSUM),(maxleftSum+maxrightSum));
    ????}
    }
    源碼(Python):def?maxSUM(array,left,right):
    ????if?left==right:
    ????????if?array[left]?>?0:
    ????????????return?array[left]
    ????????else:
    ????????????return?0
    ????center?=?int((left+right)/2)
    ????leftSubSUM?=?maxSUM(array,left,center)
    ????rightSubSUM?=?maxSUM(array,center+1,right)

    ????leftNowNum,maxleftSum?=?0,0
    ????for?i?in?reversed(range(left,center+1)):
    ????????leftNowNum?+=?array[i]
    ????????if?leftNowNum?>?maxleftSum:
    ????????????maxleftSum?=?leftNowNum

    ????rightNowNum,maxrightSum?=?0,0
    ????for?i?in?range(center+1,right+1):
    ????????rightNowNum?+=?array[i]
    ????????if?rightNowNum?>?maxrightSum:
    ????????????maxrightSum?=?rightNowNum
    ????return?max(leftSubSUM,rightSubSUM,maxleftSum+maxrightSum)
    if?__name__?==?'__main__':
    ????array?=?[-2,11,-4,13,-5,-2]
    ????print(maxSUM(array,0,len(array)-1))
    兩個(gè)程序的原理相同,運(yùn)行正確,不過(guò)鄙人水平有限,如果各位發(fā)現(xiàn)有問(wèn)題還煩請(qǐng)指出,謝謝!這個(gè)算法稍微復(fù)雜一點(diǎn),程序更長(zhǎng)一點(diǎn),不過(guò)時(shí)間復(fù)雜度只有O(),相比O()已經(jīng)好了很多,不過(guò)事實(shí)上還有一種更加有效且巧妙的算法。

    算法3

    這個(gè)算法我也不清楚它的名字,不過(guò)它確是最好的,首先看源代碼:源碼(Java):public?class?maxValueSum3?{
    ????public?static?void?main(String[]?args)?{
    ????????int[]?array?=?{-2,11,-4,13,-5,-2};
    ????????System.out.println(maxSubSum(array));
    ????}
    ????public?static?int?maxSubSum(int?[]?array)?{
    ????????int?maxSum?=?0,NowSum?=?0;
    ????????for?(int?i?=?0;?i?????????????NowSum?+=?array[i];

    ????????????if?(NowSum?>?maxSum)
    ????????????????maxSum?=?NowSum;
    ????????????else?if?(NowSum?0)
    ????????????????NowSum?=?0;
    ????????}
    ????????return?maxSum;
    ????}
    }
    源碼(Python):def?maxSubSum(array):
    ????maxSum,NowSum?=?0,0
    ????for?i?in?range(len(array)):
    ????????NowSum?+=?array[i]
    ????????if?NowSum?>?maxSum:
    ????????????maxSum?=?NowSum
    ????????elif?NowSum?0:
    ????????????NowSum?=?0
    ????return?maxSum
    if?__name__?==?'__main__':
    ????array?=?[-2,11,-4,13,-5,-2]
    ????print(maxSubSum(array))
    代碼很短,不過(guò)要想清楚原理可能比之前都稍微難點(diǎn)。它是正確可行的,并且不難看出時(shí)間復(fù)雜度為O(N),它的效率很高,不過(guò)到底是怎么實(shí)現(xiàn)的呢?那寧哥我就用蹩腳的話來(lái)簡(jiǎn)單分享下我的理解吧。首先可以看到,該算法只是簡(jiǎn)單遍歷了一遍數(shù)組而已,就找到了最大子序列和。為什么可以這樣?首先,任何負(fù)的子序列不可能是最優(yōu)子序列的前綴。除非數(shù)組中的所有值均為負(fù)數(shù),只要有一個(gè)正數(shù),那么最優(yōu)子序列的和的前綴一定不可能是負(fù)數(shù)。因此這也就說(shuō)明了代碼中的else if(NowSum<0) NowSUm=0;了,也就是如果當(dāng)前子序列的和為負(fù)值,那么初始化為0,它已經(jīng)不可能是最有子序列的前綴了,就把它的記錄拋棄了,如果當(dāng)前位置在N,那問(wèn)題就變成了求array[N+1]-array[array.length-1]的最有子序列了。然后還有一個(gè)判斷語(yǔ)句if(NowSum > maxSum) maxSum = thisSum;,看起來(lái)很簡(jiǎn)單,意思就是如果當(dāng)前子序列和大于記錄的最大值,那就更新。可如果放到整個(gè)程序里如何保證能正確運(yùn)行呢?對(duì)一個(gè)子序列,如果是每一個(gè)數(shù)都遞增或者遞減比較好理解,遞增的話最大子序列值就是從第一個(gè)大于0的數(shù)開始到整個(gè)序列,如果是遞減的話就是第一個(gè)數(shù)開始到第一個(gè)小于等于0之前的那個(gè)數(shù)。還有兩種情況,子序列整體遞增或整體減小,但是數(shù)大大小小不確定。如果子序列整體是增加的,也好理解,仍然是整個(gè)序列值唄,那如果子序列是整體遞減呢?如果整體是遞減的,說(shuō)明剛開始某個(gè)地方會(huì)有一個(gè)最大值,那樣的話我們的方法在剛開始就已經(jīng)把序列最大值記錄了,后面只是更新而已,哈哈哈突然解決。明白了嗎?

    ???end???

    走在路上

    goldsunC

    總結(jié)

    以上是生活随笔為你收集整理的c 最大子序列和_最大子序列和暴力法、分治+递归法、妙法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。