leetcode筆記:Permutation Sequence,sequencenumber

來源:互聯網
上載者:User

leetcode筆記:Permutation Sequence,sequencenumber

一.題目描述

題目的意思是,假設有{1,2,3,4,…,n},對其中的元素進行排列,總共有n!種組合,將它們從小到大排序,問其中第k個組合的形式是怎樣的?

二.題目分析

方法一:可以一個一個的按次序暴力求解。具體實現可參照題目:Next Permutation。這裡並沒有實現,主要研究的是方法二的Cantor expansion演算法。

方法二:數學解法:Cantor expansion

Cantor expansion演算法的思想是,在n!個排列中,第一位的元素總是(n-1)!一組出現的,也就說如果p = k / (n-1)!,那麼排列的最開始一個元素一定是nums[p]。以下公式給出了全排列到一個自然數的一一雙射:

X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0!

舉個例子:

1324{1,2,3,4}排列數中第幾個組合:

第一位是1,小於1的數沒有,是0個,0*3!,第二位是3,小於3的數有12,但1已經存在於第一位了,所以只有一個數21*2! 。第三位是2小於2的數是1,但1在第一位,所以有0個數,0*1!,所以比1324小的排列有0*3!+1*2!+0*1!=2個,1324是第3個組合。

以上是Cantor編碼的過程,即把一個全排列映射1324為一個自然數3,而該題目是已知一個自然數k,求其對應的全排列,相對以上步驟來說是一個解碼的過程,下面給出一個具體的例子:

如何找出{1,2,3,4,5}的第16個排列?
1. 首先用16-1,得到15
2. 用15去除4! ,得到0,餘15
3. 用15去除3! ,得到2,餘3
4. 用3去除2! ,得到1,餘1
5. 用1去除1! ,得到1,餘0
6. 有0個數比它小的數是1,所以第一位是1
7. 有2個數比它小的數是3,但1已經在之前出現過,所以第二位是4
8. 有1個數比它小的數是2,但1已經在之前出現過了所以第三位是3
9. 有1個數比它小的數是2,但1,3,4都出現過了所以第四位是5
10. 根據上述推論,最後一個數只能是2

所以排列為{1,4,3,5,2}

按照以上思路,可以開始設計演算法。

三.範例程式碼

#include <iostream>#include <string>#include <iterator>using namespace std;class Solution{public:    string PermutationSequence(int n, int k)    {        int total = CombinedNumber(n - 1);        if (k > total)        {            cout << "The k is larger then the total number of permutation sequence:" << total << endl;            return "Null!";        }        string a(n, '0');        for (int i = 0; i < n; ++i)            a[i] += i + 1;   // sorted        // Cantor expansion        string s = a, result;        k--; // (k - 1) values are less than the target value         for (int i = n - 1; i > 0; --i)        {            auto ptr = next(s.begin(), k / total);            result.push_back(*ptr);            s.erase(ptr);  // delete the already used number            k %= total;    // update the dividend            total /= i;    // update the divider        }        result.push_back(s[0]);  // The last bit        return result;    }private:    int CombinedNumber(int n)    {        int num = 1;        for (int i = 1; i < n + 1; ++i)            num *= i;        return num;    }};

以下是簡易的測試代碼:

#include "PermutationSequence.h"int main(){    Solution s;    int n = 6, k = 150;    string result = s.PermutationSequence(n, k);    std::cout << "n = " << n << " and the " << k << "th sequence is: " << result << std::endl;    getchar();    return 0;}

一個正確的測試結果,n = 6k = 16

k的取值超過可能的組合數量時:

四.總結

該題應嘗試使用Cantor expansion解法來做,數學的魅力是無窮的。

參考資料:http://www.bianceng.cn/Programming/sjjg/201407/43080.htm

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.