2022-03-22每日刷题打卡
力扣春季赛开始啦,佬们求求给战队点个赞吧(每天都可以点的):啊哈哈哈AC来咯
代码源——每日一题
可重排列 - 题目 - Daimayuan Online Judge
按字典序从小到大,输出所有序列,满足其中有p1个1, p2个2, ……, pn个n。
输入格式
第一行,一个整数n。
第二行,若干个整数p1,p2,…,pn。
输出格式
若干行,每行若干个整数,表示满足条件的序列。
样例输入
3
1 2 2
样例输出
1 2 2 3 3
1 2 3 2 3
1 2 3 3 2
1 3 2 2 3
1 3 2 3 2
1 3 3 2 2
2 1 2 3 3
2 1 3 2 3
2 1 3 3 2
2 2 1 3 3
2 2 3 1 3
2 2 3 3 1
2 3 1 2 3
2 3 1 3 2
2 3 2 1 3
2 3 2 3 1
2 3 3 1 2
2 3 3 2 1
3 1 2 2 3
3 1 2 3 2
3 1 3 2 2
3 2 1 2 3
3 2 1 3 2
3 2 2 1 3
3 2 2 3 1
3 2 3 1 2
3 2 3 2 1
3 3 1 2 2
3 3 2 1 2
3 3 2 2 1
数据规模
对于100%的数据,保证1≤n≤9,1≤pi≤9,保证总的序列个数不超过10^5个。
两个做法:
1、用dfs枚举每个位置上可能的数字,枚举完最后一位的时候把整个数组输出。
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;
int f[N], n, u;
vector<int> v;
void dfs()
{
if (v.size() == u)
{
for (auto i : v)cout << i << " ";
cout << endl;
return;
}
for (int i = 1; i <= n; i++)
{
if (f[i] != 0)
{
f[i]--;
v.push_back(i);
dfs();
v.pop_back();
f[i]++;
}
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> f[i];
u += f[i];
}
dfs();
return 0;
}
2、next_permutation
next_permutation() 会生成一个序列的重排列,它是所有可能的字典序中的下一个排列,默认使用 < 运算符来做这些事情。它的参数为定义序列的迭代器和一个返回布尔值的函数,这个函数在下一个排列大于上一个排列时返回 true,如果上一个排列是序列中最大的,它返回 false,所以会生成字典序最小的排列。
使用样例:(生成1~4的所有可能排列)
vector<int> range{ 1,2,3,4 };
do {
copy(begin(range), end(range), ostream_iterator<int>{cout, " "});
cout << endl;
} while (next_permutation(std::begin(range), end(range)));
结果:
1 2 3 4
1 2 4 3
1 3 2 4
1 3 4 2
1 4 2 3
1 4 3 2
2 1 3 4
2 1 4 3
2 3 1 4
2 3 4 1
2 4 1 3
2 4 3 1
3 1 2 4
3 1 4 2
3 2 1 4
3 2 4 1
3 4 1 2
3 4 2 1
4 1 2 3
4 1 3 2
4 2 1 3
4 2 3 1
4 3 1 2
4 3 2 1
只要一开始给出这组序列的最小字典序的序列,我们就可以很方便的得到一串数的全排列结果
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<iterator>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;
int f[10],len,mymap[N];
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n,x=1;
cin >> n;
vector<int>ans;
for (int i = 1; i <= n; i++)
{
cin >> f[i];
for (int j = 0; j < f[i]; j++)
{
ans.push_back(x);
}
x++;
}
do {
copy(begin(ans), end(ans), ostream_iterator<int>{cout, " "});
cout << endl;
} while (next_permutation(begin(ans), end(ans)));
return 0;
}
字典序最小 - 题目 - Daimayuan Online Judge
从序列 MM 个数中顺序选出 NN 个不同的数, 使得这 NN 个数的字典序最小。
输入格式
第一行两个整数 M, N分别表示序列长度,顺序选取数据的个数 (其中1<N≤M≤10^6)。
接下来 M 行,第 i 行输入为第 ai,表示序列 M 中第i 个数,其中 1≤ai≤N, 数据保证 [1,N] 范围内每个数至少出现一次。
输出格式
输出 N 个数, 用空格隔开, 表示最小字典序 (最后一个输出不能有多余空格)。
样例输入
6 3
3
2
1
3
1
3
样例输出
2 1 3
题目说明
求解的最小字典序不必在序列 M 中连续。
这题我们想要得到最小的字典序,那前面的数都要尽可能小,随着遍历数组我们要更新更小的元素,同时把大的元素从记录的序列中移除,这一性质就很适合我们单调栈。
我们先预处理一下,用一个数组f先记录每个数的出现次数,然后用一个栈遍历数组,每遍历到一个数,数组f里这个数的出现次数–,如果栈为空,就把遍历到的元素入栈,并且用一个数组记录当前栈内的元素;如果栈不为空,而且当前元素没有在栈内,就用当前元素和栈顶元素比较一下,如果栈顶元素在数组的出现次数不为0(数组后面还会出现),就把这个元素出栈,然后继续用当前元素和新的栈顶元素对比,直到新的栈顶元素在数组后面不再出现(如果此时再删,那这个数就永远丢失了),或者栈顶元素小于当前元素是停止出栈,把元素入栈。如果一开始当前元素已经在栈内了,那就不用进行出栈操作(我们出栈是为了把小的数尽可能放前面,既然这个元素已经有在栈内了就不用在出栈了),最后把栈内元素反向输出就行。
#include<iostream>
using namespace std;
#include<vector>
#include<algorithm>
#include<math.h>
#include<set>
#include<numeric>
#include<string>
#include<string.h>
#include<map>
#include<unordered_map>
#include<stack>
#include<list>
#include<queue>
#include<iomanip>
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 50;
int f[N];
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int n,m;
cin >> n >> m;
vector<int>v(n),mymap(N+1);
for (int i = 0; i < n; i++)
{
cin >> v[i];
f[v[i]]++;
}
stack<int>sta;
sta.push(v[0]);
f[v[0]]--;
mymap[v[0]] = 1;
for (int i = 1; i < n; i++)
{
while (!sta.empty() && sta.top() > v[i] && f[sta.top()] > 0 && mymap[v[i]] != 1)
{
mymap[sta.top()] = 0;
sta.pop();
}
if (mymap[v[i]] == 0)
{
sta.push(v[i]);
mymap[v[i]] = 1;
}
f[v[i]]--;
}
vector<int>res;
while (!sta.empty())
{
res.push_back(sta.top());
sta.pop();
}
cout << res[m - 1];
for (int i = m - 2; i >= 0; i--)cout << " " << res[i] ;
return 0;
}