递归问题 —— 熟悉递归 —— (全排列 —— 组合 —— 栈)

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值