字符的排列和组合

人生的第一次面试,一家做算法的小公司,面试官人挺好,但我发挥的太差了……
前面几到和数据库有关的业务题,就先不说了,哎。
有一道看似很简单的算法题,竟然做不出来……


看到这题,我首先想到了剑指offer的一道题目:

  • 求字符的排列
  • 题目描述
    输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
  1. 第一步交换第一个字符和剩余所有字符;
  2. 第二步固定第一个字符,求剩余字符的全排列;(递归)
class Solution {
public:
    vector<string> Permutation(string str) {
        vector<string>ans;
        if (str.size()==0)return ans;
        dp(ans,str,0);          //   & *  ?? 
        sort(ans.begin(),ans.end()) ;
        return ans;
        
    }
    void dp(vector<string>&ans,string str,int begin) 
    {
    	if (begin==str.size())
    	{
    		ans.push_back(str);   
            return ;
		}
		
		for (int i =begin;i<str.size();i++)
		{
            if (i!=begin && str[i]==str[begin])continue;  //考虑重复!!
			swap(str[begin],str[i]);
			
			dp(ans,str,begin+1);
			
			swap(str[begin],str[i]);
			
		}
		
	}
};
  1. 组合
    参考:
    https://blog.csdn.net/Hackbuteer1/article/details/7462447
class zh{
	public:
		vector<string>zuhe(string str)
		{
			vector<string>ans;
			vector<char>tmp;
			if (str.size()==0)return ans;
			
			for (int i=1;i<=str.size();i++)
			{
				dp(ans,tmp,str,0,i);
			}
			return ans;
			
		}
		void dp(vector<string>&ans,vector<char>&tmp,string str,int begin,int num)  // num : the number of combion 
		{

			if (num==0 )
			{
				string s = "";
				for (int i=0;i<tmp.size();i++)
				{
					s+=tmp[i];
				}

				ans.push_back(s);
				return;
			}
			
			if (begin==str.size())return ;
			
			tmp.push_back(str[begin]);
			dp(ans,tmp,str,begin+1,num-1);
			tmp.pop_back();
			dp(ans,tmp,str,begin+1,num);
			
		}
}; 

位运算,所有1,0的组合,即为所有字符的组合

class wei{
	public:
		vector<string>zuhe(string str)
		{
			vector<string>ans;
			set<string>se;
			if (str.size()==0)return ans;
			
			for (int i=1;i<(1<<str.size());i++)
			{
				mj(se,i,str);         // 2 ** (n-1) 
			}
			
			for (set<string>::iterator it= se.begin();it!=se.end();it++ )
			{
				ans.push_back(*it);
			}
			
			return ans;
			
		}
		void mj(set<string>& ans, int n,string str)
		{
			string tmp = "";
			for (int i=0;i<str.size();i++)
			{
				if ((1<<i)&n)
				{
					tmp+=str[i];
//					cout<<"--"<<tmp<<endl;
				}
			}
			ans.insert(tmp);
		}
};

leetcode 一道组合题目,规定了返回组合数的长度。

Input: n = 4, k = 2
Output:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]

目前只是在之前位运算的基础上加了一个判断条件,复杂度依然为O(n**2),后面再优化吧

class Solution {
public:
    vector<vector<int>> combine(int n, int k) {
        vector<vector<int> >ans;
        for (int i=1;i<(1<<n);i++)
        {
            vector<int>v;
            for (int j=0;j<n;j++)
            {
                if ((1<<j)&i)
                {
                    v.push_back(j+1);
                }
            }
            if (v.size()==k)
            {
                ans.push_back(v);
            }
        }
        return ans;
    }
};

对于结构体

总结起来,排列,从第一个数开始,后面每个数和其交换,固定第一个数,递归的作用于后面的子序列;终止条件,begin==str.size()-1;
组合,外层的一个for循环决定要组合多少个数;对于每个固定的数,从0开始,判断当前数是否加入进去。 终止条件,number = 0 , 注意 begin 不要越界。

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;


struct node{
	char name;
	int number;
	 node(char s,int n):name(s),number(n){
	}
};

bool cmp(struct node a,struct node b)
{
	return a.number<b.number;
}

class  solve_bt{
	public:
		vector<vector<node> >pl(vector<node>str)
		{
			vector<vector<node> >ans;
			
			if (str.size()==0)return ans;
			
			dg(ans,str,0);
			
			return ans;
		}
		
		void dg(vector<vector<node> >&ans,vector<node>str,int begin)
		{
			if (begin==str.size()-1)
			{
//				sort(str.begin(),str.end(),cmp);
				ans.push_back(str);
				return ;
			}
			
			for (int i=begin;i<str.size();i++)
			{
				if (i!=begin && str[i].name==str[begin].name)continue;  
				
				swap(str[begin],str[i]);
				dg(ans,str,begin+1)	;
				swap(str[begin],str[i]);
			}
			
		}
		
};

class solve_zh{
	
	public:
		vector<vector<node> >zh(vector<node>str)
		{
			vector<vector<node> >ans;
			
			if (str.size()==0)return ans;
			
			vector<node>tmp;
			for (int i=1;i<=str.size();i++)
			{
				dg(ans,tmp,str,0,i);
			}
			return ans;
			
		}
		void dg(vector<vector<node> >&ans,vector<node>&tmp,vector<node>str,int begin,int number)
		{
			if (number==0)
			{
				sort(tmp.begin(),tmp.end(),cmp);
				
//				for (int i=0;i<tmp.size();i++)cout<<tmp[i].name<<endl;
//				cout<<tmp.size()<<endl;
				ans.push_back(tmp);
				return ;
			}
			
			if (begin==str.size())return ;
			
			tmp.push_back(str[begin]);
			dg(ans,tmp,str,begin+1,number-1);
			tmp.pop_back();
			dg(ans,tmp,str,begin+1,number);
			
		}
};

int main()
{
	node a('a',2);
	node b('b',1);
	node c('c',3);
	vector<node>str;
	str.push_back(a);
	str.push_back(b);
	str.push_back(c);
	
	swap(str[0],str[1]);
	
	for (int i=0;i<str.size();i++)
	{
		cout<<str[i].name<<endl;
	}
	
	cout<<"---"<<endl;
	
//	solve_bt bt;
//	vector<vector<node> >ans= bt.pl(str);

	solve_zh z;
	vector<vector<node> >ans = z.zh(str);
	
	for (int i=0;i<ans.size();i++)
	{
		for (int j=0;j<ans[i].size();j++)
		{
			cout<<ans[i][j].name;
		}
		cout<<endl;
	}
	
	return 0; 
} 

猜你喜欢

转载自blog.csdn.net/xnmc2014/article/details/86040441