人生的第一次面试,一家做算法的小公司,面试官人挺好,但我发挥的太差了……
前面几到和数据库有关的业务题,就先不说了,哎。
有一道看似很简单的算法题,竟然做不出来……
看到这题,我首先想到了剑指offer的一道题目:
- 求字符的排列
- 题目描述
输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。
- 第一步交换第一个字符和剩余所有字符;
- 第二步固定第一个字符,求剩余字符的全排列;(递归)
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]);
}
}
};
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;
}