如何在给定长度内找到k的排列?
例如:
单词cat
有3个字母:如何在单词cat
中找到2的所有排列。
结果应为:ac
,at
,ca
,ac
等...
这不是作业问题。 可以使用任何语言,但更优选:C / C ++或C#。 我知道如何为大小LENGTH创建递归,但不知道自定义大小的递归。
答案 0 :(得分:3)
这是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;
}
}
}
答案 1 :(得分:1)
递归解决方案有什么问题并传递一个额外的参数(深度),以便递归函数立即返回深度&gt; Ñ
答案 2 :(得分:1)
效率最高,但效果很好:
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;
}
}
答案 3 :(得分:1)
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;
}
}
}
答案 4 :(得分:0)
如果我没弄错的话,这个问题也可以通过combinadics来解决,就像在http://en.wikipedia.org/wiki/Combinadic/上一样,那里也有参考实现。
我自己使用Java解决方案(http://docs.google.com/Doc?id=ddd8c4hm_5fkdr3b/)从一系列数字生成所有可能的三元组,这应该没有什么不同。
我没有足够的资金来解释它背后的数学,但据我所知,这是迭代所有可能的nCr(即你的猫例子中的3C2)选择的最简单的方法。
答案 5 :(得分:0)
首先找到数组的可能子集。你可以这样做 在Iterating over subsets of any size
中讨论的递归方式其次使用STL算法计算每个子集的排列 next_permutation
我没有实现它,但我认为它应该有用。