全排列与组合,相信大家都不陌生。
全排列:
N = 3
print----------------------------------------
(图1)
1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
共6个--------------------------------------
组合(N中选M个):
N = 5,M = 3
print----------------------------------------
(图2)
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
共10个--------------------------------------
代码有些像,但是有差别。
全排列:
(图3)
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int st[N];
bool ways[N];
int n;
void dfs(int u)
{
if (u > n)
{
for (int i = 1; i <= n; i++) printf("%d ",st[i]);
puts("");
return ;
}
for (int i = 1; i <= n; i++)
{
if (!ways[i])
{
st[u] = i;
ways[i] = true;
dfs(u + 1);
st[u] = 0;
ways[i] = false;
}
}
}
int main()
{
cin>>n;
dfs(1);
return 0;
}
我遇到挫折,绝不半途而废,干事“掉血掉汗不掉泪”。这个也一样。开始,没有想到用ways[],只能用for循环一一验证:
(图4)
#include <bits/stdc++.h>
#include <cstring>
using namespace std;
const int N = 16;
int st[N];
int flag[N];
int n;
void dfs(int dad, int value)
{
if (dad == n)
{
st[dad] = value;
for (int i = 1; i <= n; i++)
{
printf("%d ", st[i]);
}
puts("");
return;
}
for (int i = 1; i <= n; i++)
{
memset(flag, 0, sizeof(flag));
st[dad] = value;
for (int i = 1; i <= dad; i++)
{
flag[st[i]] = 1;
}
if (flag[i] == 0)
{
dfs(dad + 1, i);
}
}
}
int main()
{
cin >> n;
memset(flag, 0, sizeof(flag));
dfs(0, 0);
return 0;
}
后来,我优化后发现, 376 ms完全可以提升至269 ms,请见(图1);
组合:
(图5)
#include <bits/stdc++.h>
using namespace std;
const int N = 100010;
int st[N];
int u;
int n;
void dfs (int start, int v)
{
if (n - v < u - start)
{
return ;
}
if (start == u)
{
st[start] = v;
for (int i = 1; i <= u; i++)
{
printf("%d ",st[i]);
}
puts("");
return ;
}
for (int i = v + 1; i <= n; i++)
{
st[start] = v;
st[start + 1] = 0;
dfs (start + 1, i);
}
}
int main()
{
cin>>n>>u;
dfs (0, 0);
return 0;
}
组合没啥好说的。接下来,我们尝试着它们算一算时间复杂度和空间复杂度。
全排列:
时间复杂度:
空间复杂度:
组合:
时间复杂度:
空间复杂度:
好了,今天的内容就到这里,我们下期再见,拜拜!