[分享+散分]:高效率的全组合算法

止戈而立 2009-02-17 09:36:33
加精
最近发现论坛上问全组合的问题挺多的,自己之前也在这里问过类似的问题,一直没有找到特别高效的算法。
这两天看到了下面这个帖子,
http://topic.csdn.net/u/20090216/18/9104bda7-6ea3-4899-973c-cb7aae6612d8.html
特意又考虑了一下。终于写出了自己认为效率比较高的算法,拿出来给大家评评看,欢迎大家批评指正:

        static string[] m_Data = { "A", "B", "C", "D", "E" }; 

static void Main(string[] args)
{
Dictionary<string, int> dic = new Dictionary<string, int>();
for (int i = 0; i < m_Data.Length; i++)
{
Console.WriteLine(m_Data[i]);//如果不需要打印单元素的组合,将此句注释掉
dic.Add(m_Data[i], i);
}
GetString(dic);
Console.ReadLine();
}

static void GetString(Dictionary<string,int> dd)
{
Dictionary<string, int> dic = new Dictionary<string, int>();
foreach (KeyValuePair<string, int> kv in dd)
{
for (int i = kv.Value + 1; i < m_Data.Length; i++)
{
Console.WriteLine(kv.Key + m_Data[i]);
dic.Add(kv.Key + m_Data[i], i);
}
}
if(dic.Count>0) GetString(dic);
}


运行结果:
A
B
C
D
E
AB
AC
AD
AE
BC
BD
BE
CD
CE
DE
ABC
ABD
ABE
ACD
ACE
ADE
BCD
BCE
BDE
CDE
ABCD
ABCE
ABDE
ACDE
BCDE
ABCDE
...全文
10890 315 打赏 收藏 转发到动态 举报
写回复
用AI写文章
315 条回复
切换为时间正序
请发表友善的回复…
发表回复
techmaster 2011-06-01
  • 打赏
  • 举报
回复
上面贴的最后一个办法不对,没有1 3 4。算法错了,不要参考。
techmaster 2011-06-01
  • 打赏
  • 举报
回复
赫赫,看不懂c#的代码。。。
这个问题我知道有三种办法,
1. 简洁的办法:用循环或者递归都行,算出第n-1个数的全组合,存起来,然后算n的时候结果就是n-1的组合和每个组合加上第n个元素的组合。
2. 巧妙的办法:使用位操作,将n变换为n个1的二进制数,例如5就是11111,然后从0到11111遍历,输出每个位上对应的组合结果,需要转换一下,例如10101就输出,1,3,5,或者说A,C,E,明白?
3. 最直接也是最笨的办法,三个循环,第一个循环中的i代表这个循环内每行打印几个数,第二个循环的j代表从几开始打印,引入一个数组来存放循环中携带的固定数。最后一个循环中的k代表单次该打印的数。

前两个方法比较简单,最后一个麻烦。贴代码,只有c的啊,吼吼。

int n=4;

void clearArray(int c[])
{
int i;
for(i=0; i<n; i++) {
c[i] = 0;
}
}

int main(int argc, char* argv[])
{
int i, j, k, l;

/* dynamic alloc array, n can be get from user input */
int *a = new int[n];
int *b = new int[n];

for (i=0; i<n; i++) {
a[i] = i+1; /* store 1, 2, 3,...n*/
b[i] = 0;
}

for (i=1; i<=n; i++) { /* i means how many items to print in a line, if i=1, means 1 items to print in a line */
if (i == 1) {
for (j=0;j<n;j++) {
printf("{%d}\n", a[j]);
}
} else {
for (j=0; j<n; j++) { /* j means the start point when print multi items */
/* put a[j] to a[j+i-1] into a place*/
clearArray(b);
for(k=j; k<j+i-1; k++) {
b[k] = a[k];
}

for (k=j+i-1; k<n; k++) { /* k means each other number to print from the start point */
printf("{");
for (l=0; l<n; l++) {
if (b[l]!=0) {
printf("%d ", b[l]);
}
}
printf("%d", a[k]);
printf("}\n");
}
}
}
}

return 0;
}

n=4 结果:

{1}
{2}
{3}
{4}
{1 2}
{1 3}
{1 4}
{2 3}
{2 4}
{3 4}
{1 2 3}
{1 2 4}
{2 3 4}
{1 2 3 4}
吾shi谁 2010-12-02
  • 打赏
  • 举报
回复
收藏,lz要多发一些
Tanhualin 2010-11-24
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 king19840811 的回复:]
向楼主学习啊。。高手!!!!!!!!!!!!
[/Quote]
+1
yylooker2008 2010-09-07
  • 打赏
  • 举报
回复
mark一下 很智慧的帖子
IT征途 2010-09-06
  • 打赏
  • 举报
回复
太感谢了!刚好需要此算法!
zdbfba739 2010-08-31
  • 打赏
  • 举报
回复
看一下
qwerrewq888 2010-08-31
  • 打赏
  • 举报
回复
谢谢楼主分享
洛神印 2010-08-19
  • 打赏
  • 举报
回复
看了下。不错的算法。大致明白了。有时间自己来测试下
zierben 2010-08-17
  • 打赏
  • 举报
回复
原来都结贴了,没有赶上热乎趟!!!
zierben 2010-08-17
  • 打赏
  • 举报
回复
[Quote=引用 116 楼 min_jie 的回复:]
引用 103 楼 litaoye 的回复:
如果不考虑输出的话,肯定不是最高效率的,因为大部分进位实际只变化了1个字符,不用将前面的再算一遍。

http://blog.csdn.net/medie2005/archive/2007/11/10/1877412.aspx

引用 89 楼 fireseed 的回复:
有点瑕疵,8行有效代码以最高效率搞定!

C/C++ code
……
[/Quote]

实在不理解大家为什么讨论问题都只用8个数字做测试!
我当时也想当然这也过,对一个n!的用15个数字做得测试,结果发现效率不错,
后来在25!的时候与师兄的程序一比就出了问题了!
一定要用dp记录结果集,不是每一个结果都需要算的!
现在算了25!次,很显然效率是抵得要死的!
这么多红星的怎么都。。。。。。哎!!!
六六木木 2010-07-21
  • 打赏
  • 举报
回复
这也叫高效算法啊、、
tanweiwu 2010-07-20
  • 打赏
  • 举报
回复
个人认为在数据比较少的情况下你使用HashMap这个泛型,效率反而低下!
数据比较大的情况你也得看看你的那个Dictionary泛型是怎么实现的。

我并没有研究过C#的许多知识,只是说下。
gaoqh2009 2010-07-20
  • 打赏
  • 举报
回复
膜拜中, 像各位大神学习
HsuChine 2010-07-20
  • 打赏
  • 举报
回复
收藏了,学习
GZ_kenny 2010-07-20
  • 打赏
  • 举报
回复
学习~
Ade子夜 2010-07-19
  • 打赏
  • 举报
回复
[Quote=引用 87 楼 fireseed 的回复:]
C++实现,敢问还有更高效的么?可以用计时器测试一下,比一比!


C/C++ code

// 算法说明:当n大于2时,n个数的全组合一共有(2^n)-1种。
// 当对n个元素进行全组合的时候,可以用一个n位的二进制数表示取法。
// 1表示在该位取,0表示不取。例如,对ABC三个元素进行全组合,
// 100表示取A,010表示取B,001表示取C,101表示取AC
// ……
[/Quote]


很巧妙!当然这个看起来效率高。
loull 2010-07-19
  • 打赏
  • 举报
回复
先收藏再看
Adchilles 2010-07-19
  • 打赏
  • 举报
回复
谢谢 收藏起来
xiangfeidecainiao 2010-07-19
  • 打赏
  • 举报
回复
mark
加载更多回复(292)

111,119

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧