1. 程式人生 > >兩個經典遞迴問題:算瓶蓋與約瑟夫環

兩個經典遞迴問題:算瓶蓋與約瑟夫環

但凡遞迴,大部分都是兩句話能搞定的,先確定遞迴停止條件,向外翻轉,再確定迴圈條件,向內遞進

if(xx) return xx;

return  def(xx...);

首先是算瓶蓋,一百元買啤酒,五元一瓶,三個換一瓶,兩個瓶身換一瓶,求最後總數:

首先,確定條件:

//規則
    static int capRule=3,bottleRule=2;

然後是函式,為了方便大家一般都是取20作為條件的,(100/5)這個統一。

往後是形參有一點小不同,一種是總數=20,瓶蓋=0,瓶身=0,在函式裡再賦值瓶蓋跟瓶身

看到某華為面試題解方法參照如下:

int initCBDG(int drinks,int caps,int bottles){
        caps%=capRule;  bottles%=bottleRule;
        caps+=drinks;  bottles+=drinks;
        if(caps<capRule&&bottles<bottleRule){
            return drinks;
        }
        else{
            return initCBDG(caps/capRule+bottles/bottleRule,caps,bottles)+drinks;
        }
    }

看上面那篇前,自己求了個解,既然總數是20,那其他兩個引數也是20了,所以:

int dg(int count,int caps,int bottles){
        if (caps<capRule&&bottles<bottleRule) return count;
        return dg(caps/capRule+bottles/bottleRule,caps%capRule+caps/capRule+bottles/bottleRule,bottles%bottleRule+bottles/bottleRule+caps/capRule)+count;
    }

(遞迴只寫兩行的倔強)

兩個函式求的解是一樣的。

接下來是約瑟夫環,這個問題挺經典的,很多人都聽說過就不講了(沒聽過的戳這裡)

關於解,有很多,不同程式語言的,不同運算型別的,我找了一個最符合遞迴只寫兩行的解。

非常出色的一個解:

int ysfdg ( int sum, int value, int n) {
        if ( n == 1 ) return ( sum + value - 1 ) %sum;
        else return ( ysfdg ( sum-1, value,n-1 ) +value ) %sum;
    }

原作者找不到了,但這個解真的很強,非常感謝。

第一個引數是總數,第二個引數指輪循次數,第三個引數就是你想要第幾個人出列他的下標是幾。

ps:有一點需要注意的是,這個解不是單純求最後一個出列人數,而是指定第幾個人出列,得出他的下標(記得+1)