LeetCode #526: Beautiful Arrangement

Problem

Suppose you have N integers from 1 to N. We define a beautiful arrangement as an array that is constructed by these N numbers successfully if one of the following is true for the ith position (1 ≤ i ≤ N) in this array:

The number at the ith position is divisible by i.
i is divisible by the number at the ith position.
Now given N, how many beautiful arrangements can you construct?

Example 1:

Input: 2
Output: 2
Explanation: 

The first beautiful arrangement is [1, 2]:

Number at the 1st position (i=1) is 1, and 1 is divisible by i (i=1).

Number at the 2nd position (i=2) is 2, and 2 is divisible by i (i=2).

The second beautiful arrangement is [2, 1]:

Number at the 1st position (i=1) is 2, and 2 is divisible by i (i=1).

Number at the 2nd position (i=2) is 1, and i (i=2) is divisible by 1.

Note:
N is a positive integer and will not exceed 15.

題意

輸入整數(shù)N料饥,表示有N個數(shù)需要放置在N個位置上(數(shù)字和位置的下標(biāo)都是從1到N),如果能夠找出一個序列中任意一個數(shù)都滿足以下兩個條件中的一個哎甲,則將這個序列稱為一個Beautiful Arrangement:

  1. arr[i]能夠被i整除芽隆,i = 1, 2, ..., N
  2. i能夠被arr[i]整除僵闯,i = 1, 2, ..., N

對于給出的N奉呛,要求計算出共有多少種Beautiful Arrangement.

分析

簡單分析該題可以發(fā)現(xiàn)藏杖,將N個數(shù)字放置在N個位置上懂盐,這樣的問題是較為典型的回溯問題:假設(shè)前i個數(shù)字已經(jīng)放置好(滿足條件1或條件2)竭恬,則對于第i+1個位置跛蛋,如果能從還未被放置的數(shù)字集合unused(或visited)中找到一個滿足條件的數(shù)字k,則將其放在第i+1個位置痊硕,同時將k從unused中去掉(或者將visited[k - 1]標(biāo)記為true)问芬,繼續(xù)對第i+2執(zhí)行相同的操作(通過遞歸調(diào)用);如果找不到滿足條件的數(shù)字寿桨,則回溯到上一層此衅,修改第'i'個位置的數(shù)字,再嘗試第'i+1'個位置···依此類推亭螟。
遞歸的base case應(yīng)當(dāng)是遞歸樹的高度達(dá)到了N挡鞍,如果當(dāng)前層次為第N層,則表示從0到N-1層得到的這條路徑是一個Beautiful Arrangement预烙,count++墨微。

Code

對于回溯同樣也有不同的實現(xiàn),下面貼出兩段代碼扁掸,都用到了回溯的思想翘县,但在具體的實現(xiàn)上有所不同最域。

使用visited

//主要的思想是從后向前開始遞歸,即遞歸樹的根節(jié)點是最后一個元素
//使用visited數(shù)組標(biāo)識數(shù)字i是否已經(jīng)被使用過

//Runtime: 19ms
class Solution {
private:
    vector<bool> visited;
    int count;
    void _dfs(int N, int nextPos){
        if (nextPos == 0){
            count++;
            return;
        }
        for (int i = 1; i <= N; i++){
            //該數(shù)字已經(jīng)被使用 || 兩個條件都不滿足
            if (visited[i - 1] || nextPos % i != 0 && i % nextPos != 0)
                continue;
            visited[i - 1] = true;
            //深入
            _dfs(N, nextPos - 1);
            //回溯
            visited[i - 1] = false;
        }
    }
public:
    int countArrangement(int N){
        count = 0;
        visited.resize(N);
        for (int i = 0; i < N; i++) visited[i] = false;
        _dfs(N, N);
        return count;
    }
};

使用swap

//這是Solution中效率很高的一份代碼锈麸,貼在這里以供學(xué)習(xí)
//同樣是從后向前镀脂,這個解法的作者使用swap函數(shù)代替了visited數(shù)組,主要思路如下:
//1. 初始化一個數(shù)組容器v忘伞,存放的元素為[1...N](不包括0)
//1. 假設(shè)后面的下標(biāo)從p+1到N-1的位置都已經(jīng)放置好薄翅,考慮下標(biāo)為p的位置
//2. for(int i = 0; i < p; i++) 遍歷從v[0]到v[p-1]的數(shù),如果v[i]滿足條件氓奈,則將v[i]與v[p-1]交換
//3. 再次遞歸時翘魄,需要考慮的就只是下標(biāo)從0到p-1的位置該如何放置了
//4. 返回結(jié)果時,再將v[i]與v[p-1]交換回來

//Runtime: 6ms
class Solution {
private:
    int _count(int n, vector<int>& v){
        if (n <= 1)    return 1;
        int result = 0;
        for (int i = 0; i < n; i++){
            if (v[i] % n == 0 || n % v[i] == 0){
                swap(v[i], v[n - 1]);
                result += _count(n - 1, v);
                swap(v[i], v[n - 1]);
            }
        }
        return result;
    }
public:
    int countArrangement(int N) {
        vector<int> v;
        v.resize(N);
        for (int i = 0; i < N; i++)    v[i] = i + 1;
        return _count(N, v);
    }
};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末舀奶,一起剝皮案震驚了整個濱河市暑竟,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌育勺,老刑警劉巖光羞,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異怀大,居然都是意外死亡,警方通過查閱死者的電腦和手機呀闻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進店門化借,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人捡多,你說我怎么就攤上這事蓖康。” “怎么了垒手?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵蒜焊,是天一觀的道長。 經(jīng)常有香客問我科贬,道長泳梆,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任榜掌,我火速辦了婚禮优妙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘憎账。我一直安慰自己套硼,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布胞皱。 她就那樣靜靜地躺著邪意,像睡著了一般九妈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上雾鬼,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天萌朱,我揣著相機與錄音,去河邊找鬼呆贿。 笑死嚷兔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的做入。 我是一名探鬼主播冒晰,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼竟块!你這毒婦竟也來了壶运?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤浪秘,失蹤者是張志新(化名)和其女友劉穎蒋情,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體耸携,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡棵癣,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了夺衍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片狈谊。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖沟沙,靈堂內(nèi)的尸體忽然破棺而出河劝,到底是詐尸還是另有隱情,我是刑警寧澤矛紫,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布赎瞎,位于F島的核電站,受9級特大地震影響颊咬,放射性物質(zhì)發(fā)生泄漏务甥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一喳篇、第九天 我趴在偏房一處隱蔽的房頂上張望缓呛。 院中可真熱鬧,春花似錦杭隙、人聲如沸哟绊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽票髓。三九已至攀涵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間洽沟,已是汗流浹背以故。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留裆操,地道東北人怒详。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像踪区,于是被迫代替她去往敵國和親昆烁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

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