与えられた長さで k の順列を見つけるにはどうすればよいですか?
例えば:
単語cat
には 3 文字あります: 単語内の 2 の順列をすべて見つけるにはどうすればよいでしょうかcat
。結果は次のようになります: ac
, at
, ca
,ac
など...
これは宿題の問題ではありません。任意の言語を使用できますが、C/C++ または C# の方が望ましいです。サイズ LENGTH の再帰を作成する方法は知っていますが、カスタム サイズについては知りません。
与えられた長さで k の順列を見つけるにはどうすればよいですか?
例えば:
単語cat
には 3 文字あります: 単語内の 2 の順列をすべて見つけるにはどうすればよいでしょうかcat
。結果は次のようになります: ac
, at
, ca
,ac
など...
これは宿題の問題ではありません。任意の言語を使用できますが、C/C++ または C# の方が望ましいです。サイズ LENGTH の再帰を作成する方法は知っていますが、カスタム サイズについては知りません。
これは C# のもので、文字が繰り返されても機能するはずです。たとえば、長さ 2 の順列の「バナナ」では、次のようになります。
ba bn ab aa an nb na nn
基本的な考え方は、最初の文字を修正してから、長さ k-1 のすべての順列を形成し、それらの k-1 の長さの順列の先頭に文字を追加することです。重複する文字を処理するために、残りの数 (つまり、サブ順列に使用できるもの) を追跡します。
模範的なコードではありませんが、アイデアが得られるはずです。(バグを見つけた場合はお知らせください。編集できます)。
static List<string> Permutations(Dictionary<char, int> input, int length) {
List<string> permutations = new List<string>();
List<char> chars = new List<char>(input.Keys);
// Base case.
if (length == 0) {
permutations.Add(string.Empty);
return permutations;
}
foreach (char c in chars) {
// There are instances of this character left to use.
if (input[c] > 0) {
// Use one instance up.
input[c]--;
// Find sub-permutations of length length -1.
List<string> subpermutations = Permutations(input, length - 1);
// Give back the instance.
input[c]++;
foreach (string s in subpermutations) {
// Prepend the character to be the first character.
permutations.Add(s.Insert(0,new string(c,1)));
}
}
}
return permutations;
}
そして、これを使用するための完全なプログラムを次に示します。
using System;
using System.Collections.Generic;
namespace StackOverflow {
class Program {
static void Main(string[] args) {
List<string> p = Permutations("abracadabra", 3);
foreach (string s in p) {
Console.WriteLine(s);
}
}
static List<string> Permutations(string s, int length) {
Dictionary<char, int> input = new Dictionary<char, int>();
foreach (char c in s) {
if (input.ContainsKey(c)) {
input[c]++;
} else {
input[c] = 1;
}
}
return Permutations(input, length);
}
static List<string> Permutations(Dictionary<char, int> input,
int length) {
List<string> permutations = new List<string>();
List<char> chars = new List<char>(input.Keys);
if (length == 0) {
permutations.Add(string.Empty);
return permutations;
}
foreach (char c in chars) {
if (input[c] > 0) {
input[c]--;
List<string> subpermutations = Permutations(input,
length - 1);
input[c]++;
foreach (string s in subpermutations) {
permutations.Add(s.Insert(0,new string(c,1)));
}
}
}
return permutations;
}
}
}
再帰的なソリューションと追加のパラメーター (深さ) を渡して、再帰関数が深さ > n に対してすぐに戻るようにすることの何が問題になっていますか。
void Prem (char *str, int k, int length) {
if (k == length-1){
printf("%s\n",str);
return;
} else {
for (int i = k ; i < length; ++i) {
char t = str[k];
str[k] = str[i];
str[i] = t;
Prem(str,k+1,length);
t = str[k];
str[k] = str[i];
str[i] = t;
}
}
}
最も効率的ではありませんが、機能します:
public class permutation
{
public static List<string> getPermutations(int n, string word)
{
List<string> tmpPermutation = new List<string>();
if (string.IsNullOrEmpty(word) || n <= 0)
{
tmpPermutation.Add("");
}
else
{
for (int i = 0; i < word.Length; i++)
{
string tmpWord = word.Remove(i, 1);
foreach (var item in getPermutations(n - 1, tmpWord))
{
tmpPermutation.Add(word[i] + item);
}
}
}
return tmpPermutation;
}
}