数字の集合(例えば1 2 3)とインデックス(例えば2)を与えたアルゴリズムを探しています。レキシコグラフィーの順序。たとえば、この場合、アルゴリズムは1 3 2を返します。字句索引で与えられた数値順列を求めるアルゴリズム
答えて
は単純な解決である:
from math import factorial # python math library
i = 5 # i is the lexicographic index (counting starts from 0)
n = 3 # n is the length of the permutation
p = range(1, n + 1) # p is a list from 1 to n
for k in range(1, n + 1): # k goes from 1 to n
f = factorial(n - k) # compute factorial once per iteration
d = i // f # use integer division (like division + floor)
print(p[d]), # print permuted number with trailing space
p.remove(p[d]) # delete p[d] from p
i = i % f # reduce i to its remainder
出力:
3 2 1
時間複雑性は、Oある(N^2)p
であればリストであり、O(N )p
がハッシュテーブルで、factorial
があらかじめ計算されている場合は償却されます。ここで
あなたが使用する言語を指定していないので、here's an implementation in pythonです。
シーケンスのn番目の要素を取得するだけで済みます。
アルゴリズムの考え方の1つは、入力シーケンスのデカルト積を表すシーケンスを生成し、反復する要素をスキップして反復することです。
これは最速の方法ではないかもしれませんが、間違いなく簡単です。速い人はサイボーグの答えを見てください。ここ
は、私は詳細に説明しますScalaではサンプル溶液、次のとおりです。
/**
example: index:=15, list:=(1, 2, 3, 4)
*/
def permutationIndex (index: Int, list: List [Int]) : List [Int] =
if (list.isEmpty) list else {
val len = list.size // len = 4
val max = fac (len) // max = 24
val divisor = max/len // divisor = 6
val i = index/divisor // i = 2
val el = list (i)
el :: permutationIndex (index - divisor * i, list.filter (_ != el)) }
Scalaはそのあまり知られていないので、私はある、私はアルゴリズムの最後の行を説明する必要があると思いますそれ以外は、かなり自明です。
el :: elist
は、要素elとリストelistから新しいリストを構成します。 Elistは再帰呼び出しです。
list.filter (_ != el)
は要素elなしの単なるリストです。
テストも徹底的に小さなリストと:
(0 to fac (4) - 1).map (permutationIndex (_, List (1, 2, 3, 4))).mkString ("\n")
テスト2例との大きなリストのスピード:
scala> permutationIndex (123456789, (1 to 12).toList)
res45: List[Int] = List(4, 2, 1, 5, 12, 7, 10, 8, 11, 6, 9, 3)
scala> permutationIndex (123456790, (1 to 12).toList)
res46: List[Int] = List(4, 2, 1, 5, 12, 7, 10, 8, 11, 9, 3, 6)
結果は、5歳のラップトップ上ですぐに表示されます。 12要素のListには479 001 600個の置換がありますが、要素が100または1000の場合、このソリューションはまだ高速に動作するはずです.BigIntをIndexとして使用するだけです。
どのように動作しますか?私は、例を視覚化するために、一覧のグラフィックを作った(1、2、3、4)、15のインデックス:
4つの要素のリスト4を生成します!順列(= 24)。
すべての並べ替えをツリー内で視覚化することができます。最初のノードは1..4です。私たちは4を分けます!すべての第1ノードが6つのサブツリーにつながることがわかります。インデックス15を6で割ると、結果は2になり、インデックス2を持つゼロベースリストの値は3になります。したがって、最初のノードは3であり、リストの残りは(1,2,4) 。ここでは/配列/リストのインデックス2を持つ要素にどのように15本のリード線を示し、表が何であれ:
0 1 2 3 4 5 | 6 ... 11 | 12 13 14 15 16 17 | 18 ... 23
0 | 1 | 2 | 3
| | 0 1 2 3 4 5 |
我々は今、12を引く、のためのセルの最初の要素(12 ... 17)最後の3つの要素は、6つの可能な順列を持ち、どのように15が3にマップされるかを見てください。3は配列インデックス1になり、これは要素2であったため、これまでの結果はList(3,2、...) 。
| 0 1 | 2 3 | 4 5 |
| 0 | 1 | 3 |
| 0 1 |
再び、我々は2を減算し、2個の置換、及びインデックス(0,3)との2つの残りの要素で終わり、値へのマッピング(1、4)。私たちは、2番目の要素は、上から15に属する、3の評価にマップすることを、見て、最後のステップのための残りの要素は、他のいずれかです。
| 0 | 1 |
| 0 | 3 |
| 3 | 0 |
私たちの結果は(3、2、4一覧です、1)または索引(2、1、3、0)を指定します。すべてのインデックスを順にテストすると、すべての順列が順番に返されます。言及した記事への
+1、あなたがそれに入れたすべての仕事。 –
リンク: http://penguin.ewu.edu/~trolfe/#Shuffle
/* Converting permutation index into a permutation
* From code accompanying "Algorithm Alley: Randomized Shuffling",
* Dr. Dobb’s Journal, Vol. 25, No. 1 (January 2000)
* http://penguin.ewu.edu/~trolfe/#Shuffle
*
* Author: Tim Rolfe
* [email protected]
* http://penguin.ewu.edu/~trolfe/
*/
#include <stdio.h>
#include <stdlib.h>
// http://stackoverflow.com/questions/8940470/algorithm-for-finding-numerical-permutation-given-lexicographic-index
// Invert the permutation index --- generate what would be
// the subscripts in the N-dimensional array with dimensions
// [N][N-1][N-2]...[2][1]
void IndexInvert(int J[], int N, int Idx)
{ int M, K;
for (M=1, K=N-1; K > 1; K--) // Generate (N-1)!
M *= K;
for (K = 0; M > 1; K++)
{ J[K] = Idx/M; // Offset in dimension K
Idx = Idx % M; // Remove K contribution
M /= --N; // next lower factorial
}
J[K] = Idx; // Right-most index
}
// Generate a permutation based on its index/subscript set.
// To generate the lexicographic order, this involves _shifting_
// characters around rather than swapping. Right-hand side must
// remain in lexicographic order
void Permute (char Line[], char first, int N, int Jdx[])
{ int Limit;
Line[0] = first;
for (Limit = 1; Limit < N; Limit++)
Line[Limit] = (char)(1+Line[Limit-1]);
for (Limit = 0; Limit < N; Limit++)
{ char Hold;
int Idx = Limit + Jdx[Limit];
Hold = Line[Idx];
while (Idx > Limit)
{ Line[Idx] = Line[Idx-1];
Idx--;
}
Line[Idx] = Hold;
}
}
// Note: hard-coded to generate permutation in the set [abc...
int main(int argc, char** argv)
{ int N = argc > 1 ? atoi(argv[1]) : 4;
char *Perm = (char*) calloc(N+1, sizeof *Perm);
int *Jdx = (int*) calloc(N, sizeof *Jdx);
int Index = argc > 2 ? atoi(argv[2]) : 23;
int K, Validate;
for (K = Validate = 1; K <= N; K++)
Validate *= K;
if (Index < 0 || Index >= Validate)
{ printf("Invalid index %d: %d! is %d\n", Index, N, Validate);
return -1; // Error return
}
IndexInvert(Jdx, N, Index);
Permute (Perm, 'a', N, Jdx);
printf("For N = %d, permutation %d in [0..%d] is %s\n",
N, Index, Validate-1, Perm);
return 0; // Success return
}
- 1. 与えられた文字列のPython順列
- 2. 配列のインデックスの与えられた範囲の中央値を求める
- 3. 数値引数を求めるBash文字列の連結
- 4. 与えられた順序
- 5. 与えられた文字列に整数値だけを加えたい
- 6. 絶対値を計算するために文字列に与えられた数字を使うには?
- 7. 使用Pythonは与えられた検索語句とURL
- 8. 文字列内の文字の数を求める再帰アルゴリズム
- 9. 配列から与えられたコマンドライン引数
- 10. 良いアルゴリズム与えられたAZ
- 11. データが与えられた文字列
- 12. 与えられた文字列中の各文字の数
- 13. 配列から与えられた数値の和をとるアルゴリズムを取得する
- 14. 例えば、整数のジャグ配列与えられた値
- 15. 配列が与えられます。与えられた配列から一意の数値を返します
- 16. 与えられた文字列を数え、ファイル名で印刷するUnixコマンド
- 17. 与えられた文字列中の母音数を数える
- 18. 与えられた単語を斜めに文字パズルに検索する
- 19. 与えられた関数の時間複雑さを求める
- 20. 与えられた順序に基づいて数字の配列を並べ替える
- 21. 与えられた数字から数値書式とロケール文字列を取得するには?
- 22. 与えられた数値で割り切れる数を数えるプログラム
- 23. その値が与えられた数
- 24. 与えられた数字に向かって丸めます
- 25. 与えられた文字列から与えられた文字列をPHPを使って数える方法
- 26. どの組み合わせがあなたに与えられた値を与えるのかを決める数字のリストを与えてください
- 27. 与えられたノードのピクセル位置をエッジルーティングするためのアルゴリズム?
- 28. 弾性検索:この文書が与えられた文字列配列
- 29. 与えられた文字列の要素の数を数えます。
- 30. 与えられた開始時間と終了時間の合計アイドル時間を求めるアルゴリズム
あなたがこれまでに試してみましたか?素朴なアプローチは、すべての順列を生成し、辞書順に並べ替えてからn番目を選ぶことです。 – Gumbo
ヒント:まず、n番目の順列の最初の桁を決定するアルゴリズムを見つけます。 –
関連ヒント: "factorial base"と "Lehmer code"の検索を試してください – Nemo