1.字符串子序列 + 去重 O(2^n * n)
#include <bits/stdc++.h>
using namespace std;
//递归dfs求 字符串子序列 不重复
string ans; // ans存取当前字串
string s;
int n;
void f(int i,set<string>& hash) //i记录到字符串第几个位置了 , 判断是否完成一个字串
{
if(i == n)
{
hash.insert(ans);
}
else
{
//放
ans+=s[i];
f(i+1,hash);
//不放
ans.pop_back();
f(i+1,hash);
}
}
int main()
{
cin>>s;
n=s.size();
set<string> hash;
f(0,hash);
for(auto &it:hash)
{
cout<<it<<" ";
}
return 0;
}
2.子集II O(2^n * n)
class Solution {
public:
vector<int> a;
int n;
vector<vector<int>> ans;
void f(int i,vector<int>& nums)
{
if(i == n) //找到一个组合 , 放入答案
{
ans.push_back(a);
}
else
{
int j=i+1;
while(j<n && nums[i]==nums[j]) //找到下一组起点
{
j++;
}
//要0个 , 直接跳到下一组起点
f(j,nums);
int num=0; //计数该组放了几个
for(;i<j;i++) //分别放该组的每个个数
{
num++;
a.push_back(nums[i]);
f(j,nums);
}
while(num--) //还原 到上一组的情况
{
a.pop_back();
}
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(),nums.end()); //从小到大排序
n = nums.size();
f(0,nums);
return ans;
}
};
3.全排列 O(n! * n) 无重复元素
class Solution {
public:
vector<vector<int>> ans;
int n;
void f(int i,vector<int>& nums) //i记录填到了第几个位置
{
if(i == n) //找到一个排列
{
ans.push_back(nums);
}
else
{
for(int j=i;j<n;j++)
//从i依次交换后面的数,让每个数都有机会放在一个位置
{
swap(nums[i],nums[j]);
f(i+1,nums); //位置多了一个被填了
swap(nums[i],nums[j]); //回溯
}
}
}
vector<vector<int>> permute(vector<int>& nums) {
n = nums.size();
f(0,nums);
return ans;
}
};
4.全排列 O(n! * n) 有重复元素 剪枝
class Solution {
public:
int n;
vector<vector<int>> ans;
void f(int i,vector<int>& nums)
{
if(i == n)
{
ans.push_back(nums);
}
else
{
set<int> hash; //防重复 去重
for(int j=i;j<n;j++)
{
if(!hash.count(nums[j])) //保证来到i位置的都是不一样的数
{
hash.insert(nums[j]);
swap(nums[i],nums[j]);
f(i+1,nums);
swap(nums[i],nums[j]);
}
}
}
}
vector<vector<int>> permuteUnique(vector<int>& nums) {
n = nums.size();
f(0,nums);
return ans;
}
};
#include <bits/stdc++.h>
using namespace std;
int n;
string s;
void f(int i,set<string>& hash)
{
if(i == n)
{
hash.insert(s);
}
else
{
set<char> k;
for(int j=i;j<n;j++)
{
if(!k.count(s[j]))
{
k.insert(s[j]);
swap(s[i],s[j]);
f(i+1,hash);
swap(s[i],s[j]);
}
}
}
}
int main()
{
// 请在此输入您的代码
cin>>s;
n=s.size();
set<string> hash;
f(0,hash);
for(auto &it : hash)
{
cout<<it<<'\n';
}
return 0;
}
5.汉诺塔 O(2^n)
#include <bits/stdc++.h>
using namespace std;
int ans=0;
string path;
int N,M;
void f(int n,char a,char b,char c)
{
if(n == 1)
{
ans++;
if(ans == M) path = "#" + to_string(n) +": "+ a + "->" + b;
}
else
{
f(n-1,a,c,b);
ans++;
if(ans == M) path = "#" + to_string(n) +": "+ a + "->" + b;
f(n-1,c,b,a);
}
}
int main()
{
// 请在此输入您的代码
cin>>N>>M;
f(N,'A','C','B');
cout<<path<<endl<<ans<<endl;
return 0;
}
6. 逆序栈实现 (不用额外空间)
#include <bits/stdc++.h>
using namespace std;
//返回栈底元素 , 全部沉底
int bottom(stack<int> &s)
{
int ans = s.top(); //暂存当前最上面的
s.pop();
if(s.empty()) //如果为空 , 返回最底下的数字
{
return ans;
}
else
{
int last = bottom(s); //最底下的数字
s.push(ans); //除了最底下的数字 , 全部按序放回
return last;
}
}
void rever(stack<int> &s)
{
if(s.empty())
{
return ;
}
else
{
int num = bottom(s); //先保存最下面的 , 最后放
rever(s); //先放上面的
s.push(num);
}
}
int main()
{
stack<int> s;
s.push(3);
s.push(2);
s.push(1);
rever(s);
cout<<s.top()<<endl;
s.pop();
cout<<s.top()<<endl;
s.pop();
cout<<s.top()<<endl;
s.pop();
return 0;
}
7. 排序栈 (不用额外空间)
#include <bits/stdc++.h>
using namespace std;
void down(stack<int> &s,int d,int max_num,int k)
{
if(d == 0)
{
for(int i=0;i<k;i++)
{
s.push(max_num);
}
}
else
{
int num=s.top();
s.pop();
down(s,d-1,max_num,k);
if(num != max_num)
{
s.push(num);
}
}
}
int times(stack<int> &s,int d,int max_num)
{
if(d == 0)return 0;
int num=s.top();
s.pop();
int resttimes = times(s,d-1,max_num);
int t = resttimes + (num==max_num ? 1 : 0);
s.push(num);
return t;
}
//返回deep层里的最大值
int maxnum(stack<int>& s,int d)
{
if(d == 0) return INT_MIN;
int num=s.top();
s.pop();
int restmax = maxnum(s,d-1);
int max_num = max(num,restmax);
s.push(num);
return max_num;
}
int deep(stack<int> &s)
{
if(s.empty())return 0;
int num=s.top();
s.pop();
int d = deep(s) + 1;
s.push(num);
return d;
}
void sort_stack(stack<int> &s)
{
int d = deep(s); //计算当前深度
while(d > 0)
{
int max_num = maxnum(s,d); //最大元素
int k = times(s,d,max_num); //出现次数
down(s,d,max_num,k); //所有最大元素下沉
d -= k;
}
}
int main()
{
stack<int> s;
s.push(3);
s.push(5);
s.push(4);
s.push(4);
s.push(1);
s.push(6);
s.push(3);
s.push(6);
s.push(6);
sort_stack(s);
while(!s.empty())
{
cout<<s.top()<<endl;
s.pop();
}
return 0;
}