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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

递归算法学习系列之寻找第K大

發(fā)布時間:2024/9/21 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 递归算法学习系列之寻找第K大 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
  • 概述
  • ????????國人向來喜歡論資排輩的,每個人都想當(dāng)老大,實(shí)在當(dāng)不成,當(dāng)個老二,老三,老K也不錯,您一定看過這樣的爭論: 兩個人吵架,一個人非常強(qiáng)勢,另外一個忍受不住了便說:"你算老幾呀?",下面就通過這篇文章就是要解決找出老幾的問題!

    ??? 2.?? 應(yīng)用場景

    ??????? 在向量V[first,last)中查找出第K大元素的值

    ??? 3.? 分析

    ??????? 如果利用排序算法將向量V排好序,那么第K大元素就是索引為v.length-k的元素了,這樣能解決問題,但效率不高,因?yàn)檫@相當(dāng)于為了殲滅敵人一個小隊而動用了我們?nèi)姷牧α?#xff0c;得不償失,回想快速排序中的分表,每次都將目標(biāo)向量分為兩個子表,左子表中全部小于中間元素v[mid],右邊都大于中間元素v[mid],這樣就可以減小了查找范圍,因?yàn)槲铱梢灾徊檎易笞颖砘蛘哂易颖砭湍苷业侥繕?biāo)元素了。如下圖所示,我們可以將向量 v劃分成如下

    ? Left(<=KLargest)KLargest??? Right(>=KLargest)

    按照這樣的思路,我們?nèi)允褂每焖倥判蛑械姆直聿呗?#xff0c;首先將向量V從中間位置分開,分成左和右,分好后,中間值的索引如果恰恰等于K,就找到了,否則如果中間元素索引大于K,則在左子表中繼續(xù)查找,忽略右子表,如果中間值索引小于K,則在右子表中繼續(xù)查找,如此循環(huán)往復(fù)。

    快速排序中的子表劃分函數(shù)為:

    ??/**////?<summary>
    ????????
    ///?交換位置
    ????????
    ///?</summary>
    ????????
    ///?<param?name="v"></param>
    ????????
    ///?<param?name="index1"></param>
    ????????
    ///?<param?name="index2"></param>

    ????????private?void?Swrap(int[]?v,?int?index1,?int?index2)
    ????????
    {
    ????????????
    int?temp?=?v[index1];
    ????????????v[index1]?
    =?v[index2];
    ????????????v[index2]?
    =?temp;
    ????????}

    ????????
    /**////?<summary>
    ????????
    ///?將向量V中索引{first,last)劃分成兩個左子表和右子表
    ????????
    ///?</summary>
    ????????
    ///?<param?name="v">向量V</param>
    ????????
    ///?<param?name="first">開始位置</param>
    ????????
    ///?<param?name="last">結(jié)束位置</param>

    ????????private?int?PivotIndex(int[]?v,?int?first,?int?last)
    ????????
    {
    ????????????
    if?(last?==?first)
    ????????????
    {
    ????????????????
    return?last;
    ????????????}

    ????????????
    if?(last?-?first?==?1)
    ????????????
    {
    ????????????????
    return?first;
    ????????????}

    ????????????
    int?mid?=?(first?+?last)?/?2;
    ????????????
    int?midVal?=?v[mid];
    ????????????
    //交換v[first]和v[mid]
    ????????????Swrap(v,?first,?mid);
    ????????????
    int?scanA?=?first?+?1;
    ????????????
    int?scanB?=?last?-?1;
    ????????????
    for?(;?;?)
    ????????????
    {

    ????????????????
    while?(scanA?<=?scanB?&&?v[scanA]?<?midVal)
    ????????????????
    {
    ????????????????????scanA
    ++;
    ????????????????}

    ????????????????
    while?(scanB?>?first?&&?midVal?<=?v[scanB])
    ????????????????
    {
    ????????????????????scanB
    --;
    ????????????????}

    ????????????????
    if?(scanA?>=?scanB)
    ????????????????
    {
    ????????????????????
    break;
    ????????????????}

    ????????????????Swrap(v,?scanA,?scanB);
    ????????????????scanA
    ++;
    ????????????????scanB
    --;
    ????????????}

    ????????????Swrap(v,?first,?scanB);
    ????????????
    return?scanB;

    ????????}

    ???設(shè)計一個函數(shù),FindKLargest(int[] v,int first,int last,int k);這個函數(shù)包括四個參數(shù):向量V,開始位置first,結(jié)束位置last,和第k大中的K,則該函數(shù)為:

    調(diào)用FindKLargest后,因?yàn)閿?shù)組是從小到大排序,所以第K大元素的值為V[v.Length-k];

    void?FindKLargest(int[]?v,?int?first,?int?last,?int?k)
    ????????
    {

    ????????????
    //表示分表中值的索引
    ????????????int?index?=?0;
    ????????????index?
    =?PivotIndex(v,?first,?last);
    ????????????
    if?(index?==?k)
    ????????????
    {
    ????????????????
    //找到了K大
    ????????????????return;
    ????????????}


    ????????????
    if?(index?>?k)
    ????????????
    {
    ????????????????
    //只在左子表中查找
    ????????????????FindKLargest(v,?first,?index,?k);
    ????????????}


    ????????????
    else
    ????????????
    {
    ????????????????
    //只在右子表中查找
    ????????????????FindKLargest(v,?index,?last,?k);
    ????????????}

    ????????}

    4.運(yùn)行結(jié)果:
    ? 原向量 :v? = {?100, 200, 50, 23, 300, 560, 789, 456, 123, 258}?
    ? first = 0; last = v.Length;k=3
    ? 輸出:456

    5.結(jié)論
    ? 利用遞歸算法可以將比較復(fù)雜的問題劃分為越來越小的小問題,這樣能夠使復(fù)雜問題簡單化,這樣的思路在系統(tǒng)設(shè)計和架構(gòu)中同樣有著至關(guān)重要的作用,一個好的架構(gòu)師,面對復(fù)雜的問題,能庖丁解牛般化腐朽為神奇,而壞的卻往往適得其反,他們的特長是簡單問題復(fù)雜化。

    6.? 項(xiàng)目文件
    ?? /Files/jillzhang/FindK.rar
    ?
    ?? 上幾篇文章索引:?
    ??? 1.算法:【一列數(shù)的規(guī)則如下: 1、1、2、3、5、8、13、21、34 ,求第30位數(shù)是多少, 用遞歸算法實(shí)現(xiàn)。(C#語言)】
    ??? 2.大牛生小牛的問題?
    ????3.遞歸算法學(xué)習(xí)系列一(分而治之策略)
    ??? 4. 遞歸算法學(xué)習(xí)系列二(歸并排序)
    ??? 5.遞歸算法學(xué)習(xí)系列之三(快速排序)



    -------------------------------------------------------
    人老了,腦袋不好用了,偶爾用算法來練練腦子,可以防止早衰。呵呵
    ??????????????????????????????????????????????????????? jillzhang jillzhang@126.com

    總結(jié)

    以上是生活随笔為你收集整理的递归算法学习系列之寻找第K大的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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