组合算法

顺德达人 2012-08-27 11:36:47
加精
现在我有26个元素a...z
我想自由生成相关的组合
从一位起
a
a+b
a+b+c
a+b+c+d
......
生成所有组合对顺序没有要求,即a+b 和 b+a可以当同一条,不用重复出现
...全文
6075 103 打赏 收藏 转发到动态 举报
写回复
用AI写文章
103 条回复
切换为时间正序
请发表友善的回复…
发表回复
LQH1029 2012-09-15
  • 打赏
  • 举报
回复
这样也可以想到26位二进制,厉害!
SebastianHe 2012-09-09
  • 打赏
  • 举报
回复
SebastianHe 2012-09-09
  • 打赏
  • 举报
回复
思路:
二进制-->逆序-->找出值为1的位对应的字母
1-->1-->A 10-->01-->B 11-->11-->AB
100-->001-->C 101-->101-->AC 110-->011-->BC
111-->111-->ABC

JAVA实现:
public class Thr{
public static void main(String[] args) {
System.out.println("总计" + ((1 << 26)-1)+"种组合");
char[] ch = {'A','B','C','D','E','F','G',
'H','I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z'};
int n = (1<<ch.length)-1;
int i = 0;
StringBuffer sb = new StringBuffer();
while(i++ < n){
String revBinStr = sb.append(Integer.toBinaryString(i))
.reverse().toString();//逆序二进制字符串
create(ch,revBinStr);
sb.delete(0,revBinStr.length());
System.out.println();//换行
}
}


//找出值为1的位的下标,输出ch中对应该下标的
public static void create(char[] ch,String revBinStr ){
int currentIndex = 0;
for(int x = 0; x < ch.length; ){
currentIndex = revBinStr.indexOf("1",x);
if(currentIndex != -1 ){
System.out.print(ch[currentIndex]);
x = currentIndex + 1;
}else{
break;
}
}
}
}
jkm8488 2012-09-09
  • 打赏
  • 举报
回复
楼主想表达什么意思
LAONINGA098 2012-09-09
  • 打赏
  • 举报
回复
有点深
dzq138 2012-09-08
  • 打赏
  • 举报
回复

if (n & temp)
buf[datalen++] = ch;
...
//代码在这里用得比较巧妙...

天涯倦客 2012-09-06
  • 打赏
  • 举报
回复
每个选取结果是可以排序
根据排序结果可以 直接算出 需要生成的序列。。
WuHuoDeYangGuangNa 2012-09-05
  • 打赏
  • 举报
回复
新手看的晕乎乎的...
超级大笨狼 2012-09-05
  • 打赏
  • 举报
回复
这个问题简单,你可以理解成二进制,每位选还是不选就是0和1.
有多少个字母就有多少位。
正在录入中 2012-09-05
  • 打赏
  • 举报
回复
怪怪、都是大牛啊、算法牛B啊、小弟一点不懂算法、唉…………
goat_13 2012-09-05
  • 打赏
  • 举报
回复
如果不是排列只算组合的话~
使用位图算法应该是最省空间的~
只不过展示的时候需要解析~
数据量这么大~
最费时间的应该是解析吧~
sayume 2012-09-05
  • 打赏
  • 举报
回复
居然用起了回溯,不知道直接用数学解决吗,算法不是用来让问题变复杂的。
规模为1时,有两种组合:null, a
规模为2时,在原有组合基础上增加b: b, a+b
再加上原有组合,所有排列为(null,a,b,a+b)
规模为3时,在原有组合上增加c: c, a+c, b+c, a+b+c
再加上原有组合,所有排列为 (null,a,b,a+b,c,a+c,b+c,a+b+c)
...
这个问题实际上是一个等比数列,设f(1)=2, f(n)=2*f(n-1),如果不计算空,最后结果减1即可,通项为2^n-1。
按照上述步骤一次性遍历所有结果,无任何多余操作,我就不信还有人能找出比这个更快的算法。
tianer124 2012-09-05
  • 打赏
  • 举报
回复
无顺序不重复的组合 abc、acb、bac、bca...都算一种组合
tianer124 2012-09-05
  • 打赏
  • 举报
回复
不重复的组合,abc、acb、bac、bca、cab、cba都是一样的,算一种
haorengoodman 2012-09-04
  • 打赏
  • 举报
回复
(C26 1 + C26 2 +........+C26 13)*2
  • 打赏
  • 举报
回复
求java版本的代码
名刀秋水 2012-09-04
  • 打赏
  • 举报
回复
程序可能存在bug,欢迎各位好友切磋
运行时间:30秒 (写入硬盘文件) 文件大小:895 MB (939,524,095 bytes)含“,”分隔符
运行时间:4秒 (不写硬盘只写入输出缓存)


void PrintStr(DWORD n, HANDLE hFile);

int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile = INVALID_HANDLE_VALUE;
char timebuf[20] = {0};

DWORD TimeStart;
DWORD TimeEnd;
DWORD TimeUsed;

system("pause");
TimeStart = GetTickCount();

hFile = CreateFileA( "./output.txt",
GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);

if (INVALID_HANDLE_VALUE == hFile)
return FALSE;

for (DWORD i=1; i<67108864; i++)
PrintStr(i, hFile);

CloseHandle(hFile);

TimeEnd = GetTickCount();
TimeUsed = TimeEnd - TimeStart;
printf("67108863 records, time costs: %ld(ms)\n", TimeUsed);
system("pause");

return 0;
}



void PrintStr(DWORD n, HANDLE hFile)
{
/*

26 bits for a ~ z:

| 8bits | 8bits | 8bits | 8bits |
|------00|00000000|00000000|00000000|
| zy|xwvutsrq|ponmlkji|hgfedcba|

a ~ z: 97 ~ 122

*/

static char buf[28*1024*1024] = {0}; //28mb
static int datalen = 0;

DWORD temp = 1;
char ch = 'a';

for (int i=0; i<26; i++)
{
if (n & temp)
buf[datalen++] = ch;

ch++;
temp = temp << 1;
}

buf[datalen++] = ',';

if ((datalen > (28*1024*1024 - 28)) || 67108863 == n)
{
DWORD wtlen = 0;
WriteFile(hFile, buf, datalen, &wtlen, 0);
memset(buf, 0, sizeof(buf));
datalen = 0;
}
}
名刀秋水 2012-09-04
  • 打赏
  • 举报
回复
程序可能存在bug,欢迎各位好友切磋
运行时间:30秒 (写入硬盘文件) 文件大小:895 MB (939,524,095 bytes)含“,”分隔符
运行时间:4秒 (不写硬盘只写入输出缓存)


void PrintStr(DWORD n, HANDLE hFile);

int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile = INVALID_HANDLE_VALUE;
char timebuf[20] = {0};

DWORD TimeStart;
DWORD TimeEnd;
DWORD TimeUsed;

system("pause");
TimeStart = GetTickCount();

hFile = CreateFileA( "./output.txt",
GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);

if (INVALID_HANDLE_VALUE == hFile)
return FALSE;

for (DWORD i=1; i<67108864; i++)
PrintStr(i, hFile);

CloseHandle(hFile);

TimeEnd = GetTickCount();
TimeUsed = TimeEnd - TimeStart;
printf("67108863 records, time costs: %ld(ms)\n", TimeUsed);
system("pause");

return 0;
}



void PrintStr(DWORD n, HANDLE hFile)
{
/*

26 bits for a ~ z:

| 8bits | 8bits | 8bits | 8bits |
|------00|00000000|00000000|00000000|
| zy|xwvutsrq|ponmlkji|hgfedcba|

a ~ z: 97 ~ 122

*/

static char buf[28*1024*1024] = {0}; //28mb
static int datalen = 0;

DWORD temp = 1;
char ch = 'a';

for (int i=0; i<26; i++)
{
if (n & temp)
buf[datalen++] = ch;

ch++;
temp = temp << 1;
}

buf[datalen++] = ',';

if ((datalen > (28*1024*1024 - 28)) || 67108863 == n)
{
DWORD wtlen = 0;
WriteFile(hFile, buf, datalen, &wtlen, 0);
memset(buf, 0, sizeof(buf));
datalen = 0;
}
}
名刀秋水 2012-09-04
  • 打赏
  • 举报
回复
程序可能有BUG或错误的地方,欢迎各路好友切磋!!
写硬盘程序运行时间:30秒 (普通机械硬盘)
不写硬盘运行时间:4秒 (仅写入输出缓存)
输出文件大小:895 MB (939,524,095 bytes)(含“,”分隔符)


int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile = INVALID_HANDLE_VALUE;
char timebuf[20] = {0};

DWORD TimeStart;
DWORD TimeEnd;
DWORD TimeUsed;

system("pause");
TimeStart = GetTickCount();

hFile = CreateFileA( "./output.txt",
GENERIC_WRITE|GENERIC_READ,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL);

if (INVALID_HANDLE_VALUE == hFile)
return FALSE;

for (DWORD i=1; i<67108864; i++)
PrintStr(i, hFile);

CloseHandle(hFile);

TimeEnd = GetTickCount();
TimeUsed = TimeEnd - TimeStart;
printf("67108863 records, time costs: %ld(ms)\n", TimeUsed);
system("pause");

return 0;
}



void PrintStr(DWORD n, HANDLE hFile)
{
/*

26 bits for a ~ z:

| 8bits | 8bits | 8bits | 8bits |
|------00|00000000|00000000|00000000|
| zy|xwvutsrq|ponmlkji|hgfedcba|

a ~ z: 97 ~ 122

*/

static char buf[28*1024*1024] = {0}; //28mb
static int datalen = 0;

DWORD temp = 1;
char ch = 'a';

for (int i=0; i<26; i++)
{
if (n & temp)
buf[datalen++] = ch;

ch++;
temp = temp << 1;
}

buf[datalen++] = ',';

if ((datalen > (28*1024*1024 - 28)) || 67108863 == n)
{
DWORD wtlen = 0;
WriteFile(hFile, buf, datalen, &wtlen, 0);
memset(buf, 0, sizeof(buf));
datalen = 0;
}
}
诚朴勇毅 2012-09-04
  • 打赏
  • 举报
回复
回溯,子集树
加载更多回复(64)

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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