输入一个字符串,打印该字符串中字符的所有排列
解法一:
递归得遍历所有位数,每一位替换所有数值(备用的不算,用数组tag记录数字被使用情况),用list记录要打印的结果,空间复杂度O(N),时间复杂度O(N^N),不划算
解法二:
分为两组,当前位和剩下位,用当前位于剩下的位数一一进行替换,可避免重复,即可导出全排列,空间O(1),时间O(N^2)
解法1
void Permutation(char* pStr, bool* tag, int pos, std::list<char>& plist)//diy
{
if (pStr[pos]=='\0')
{
for (auto& it : plist)
printf("%c,", it);
printf("\n");
return;
}
int i = 0;
while (pStr[i]!='\0')
{
if (tag[i] != true)
{
plist.push_back(pStr[i]);
tag[i] = true;
Permutation(pStr, tag, pos + 1, plist);
tag[i] = false;
plist.pop_back();
}
i++;
}
return;
}
void Permutation(char* pStr)//diy,space O(n),time O(n^n)
{
if (pStr == nullptr) return;
int len = 0;
for (int i = 0;;i++)
{
if (pStr[i]=='\0') break;
len++;
}
bool* tag = new bool[len]();
std::list<char> pList;
Permutation(pStr, tag, 0, pList);
}
解2:
void Permutation(char* pStr, char* pCurr)//diy
{
if (*pCurr=='\0')
{
for (int i=0;;i++)
{
if (*(pStr + i) != '\0')
printf("%c,", *(pStr + i));
else
{
printf("\n");
return;
}
}
}
int addnum = 1;
char ctemp = *pCurr;
while (true)
{
if (*(pCurr + addnum) == '\0')
{
Permutation(pStr, pCurr + 1);
return;
}
*pCurr = *(pCurr + addnum);
*(pCurr + addnum) = ctemp;
Permutation(pStr, pCurr + 1);
*(pCurr + addnum) = *pCurr;
*pCurr = ctemp;
addnum++;
}
}
void Permutation(char* pStr) //diy
{
if (pStr == nullptr) return;
Permutation(pStr, pStr);
}
38.2
求字符的所有组合
给定N个字符,组合的位数有1-N种
针对一种长度为M的组合,分为两部分,第1位,剩下m-1位
第1位要么选择某个符号,从剩下符号中选M-1位,要么不选,从剩下符号中选M位
void Combinations(char* pStr, int len, int m, int currPos, bool* tag)//diy
{
if (m == 0)
{
for (int i = 0;i<len;i++)//不够简洁
{
if (tag[i]==true)
printf("%c,", *(pStr + i));
}
printf("\n");
return;
}
if (len - currPos >= m)//边界条件,保证有足够的字符可以选
{
tag[currPos] = true;
Combinations(pStr, len, m - 1, currPos + 1,tag);
tag[currPos] = false;
}
if (len - currPos - 1 >= m)
Combinations(pStr, len, m, currPos + 1,tag);
return;
}
void Combinations(char* pStr)//diy
{
if (pStr == nullptr) return;
int len = 0;
while (*(pStr + len) != '\0')//cautions for non-existent of '\0'
len++;
bool* tag = new bool[len]();//额外空间O(N)
for (int m = 0;;m++)
{
if (*(pStr+m)=='\0') break;
Combinations(pStr, len, m + 1, 0,tag);
}
}
38.3输入一个含有8个数字的数组,把数字放到正方体的8个顶点,使得正方体三组相对面的四个顶点的和都相等
8个顶点分别为a1~a8,分于八个顶点上,三个相对的面组成三个等式,把八个顶点进行全排列,每次排列结果用三个等式检测即可
38.4皇后问题,8*8的棋盘摆8个皇后,使其互相不能攻击,皇后只能攻击同一行,同一列,同一对角线,判断共有多少种符合条件的摆法
用数组对每个皇后进行全排列,然后根据下标判断是否有同行或同对角线的情况,时间复杂度很高,具体来说,1-64个数里,抽取8个数字,做法就是抽取8位的所有组合,再进行判断即可
说白了,要是问题抽象涉及摆放数字问题,先求出所有排列,然后一一判断排列是否满足