【Review】编程之法—面试和算法心得 第一章

第一章 字符串

1.1 字符串的旋转

  1. 三步反转
abc def
cba fed

最后defabc,每一部分反转通过两端字母交换,向中心靠拢的方式实现。

  1. 实现I am a student. -> student. a am I
  • 方法1 反转
#include<bits/stdc++.h> 
using namespace std;
char a[100];
void Reverse(int i,int j){
	while(i<j){
		swap(a[i],a[j]);
		i++;
		j--;
	}
}
int main(){
	cin.getline(a,100);
	int len=strlen(a);
	int l=0,r=0;
	for(int i=0;i<len;i++){
		if(a[i+1]==' '||a[i+1]=='\0'){
			r=i;
			Reverse(l,r);
			l=r+2;
			if(l>len-1)
			    break;
		}
	}
	for(int i=len-1;i>=0;i--){
		cout<<a[i];
	}
	return 0;
} 
  • 方法2 strtok函数
#include<bits/stdc++.h> 
using namespace std;
vector<string> temp;
char a[100];
int main(){
	cin.getline(a,100);
	char *t0=strtok(a," ");
	if(t0!=NULL){
		string tString(t0);
	    temp.push_back(t0);
	} 
	while(t0!=NULL){
		t0=strtok(NULL," ");
		if(t0==NULL)
		break;
		string t(t0);
		temp.push_back(t);
	} 
	for(vector<string>::iterator it=temp.end()-1;it!=temp.begin();it--){
		cout<<*it<<" ";
	}
	if(temp.size()>0)
	cout<<temp[0];
	return 0;
} 

1.2 字符串的包含

a字符串包含b的全部字符
计算Hash,每一位表示一个字母,用整数代表散列表,大小写可以分成两个int计算。

#include<bits/stdc++.h> 
using namespace std;
char a[100],b[100];
void getInt(char* a,int&aMin,int &aMax){
	int aLen=strlen(a);
	for(int i=0;i<aLen;i++){
		if(a[i]>='a'&&a[i]<='z'){
			aMin|=1<<(a[i]-'a');
		}
		else{
			aMax|=1<<(a[i]-'A');
		}
	}
}
int main(){
	scanf("%s%s",a,b);
	int aMin=0,aMax=0;
	int bMin=0,bMax=0;
	getInt(a,aMin,aMax);
	getInt(b,bMin,bMax);
	if((aMin&bMin)==bMin &&(aMax&bMax)==bMax){
		cout<<"b in a";
	}
	else cout<<"b isn't in a";
	
	return 0;
} 

1.3 字符串的全排列

字典序全排列

  • 递归
#include<bits/stdc++.h> 
using namespace std;
char Input[100];
bool chose[100];
vector<char> out;
void Cal(){
	if(out.size()==strlen(Input)){
		for(int i=0;i<out.size();i++){
			cout<<out[i];
		}
		cout<<endl;
		return ;
	}
	for(int i=0;i<strlen(Input);i++){
		if(chose[i]==false){	
			out.push_back(Input[i]);
			chose[i]=true;
			Cal();
			out.pop_back();
			chose[i]=false;
		}
	}
}
int main(){
	cin>>Input;
	sort(Input,Input+strlen(Input));
	for(int i=0;i<strlen(Input);i++){
		chose[i]=false;
	}
	Cal();
	return 0;
} 
  • 使用next_permutation
    头文件 algorithm
#include<bits/stdc++.h> 
using namespace std;
char a[100];
int main(){
while(scanf("%s",a)!=EOF) {
	for(int i=0;i<strlen(a);i++){
			cout<<a[i]; 
	}
	cout<<endl;
	while(next_permutation(a,a+strlen(a))){
		for(int i=0;i<strlen(a);i++){
			cout<<a[i]; 
		}
		cout<<endl;
	}
	cout<<endl;
}
	return 0;
} 
  • next_permutation 实现

从右向左,第一个不满足升序的为i,i与其右面从右向左第一个比它大的元素交换,之后把i+1到n-1的元素倒序

#include<bits/stdc++.h> 
using namespace std;
char a[100];
bool NextPermutation(char a[]){
	int i;
	for(i=strlen(a)-1;i>0;i--){
		if(a[i-1]<a[i]){
			i=i-1;
			break;
			
		}
	}
	if(i==0&&a[0]>a[1])
	return false;
	int j;
	for( j=strlen(a)-1;j>=i;j--){
		if(a[j]>a[i]){
			break;
		}
	}
	
	if(i<j){
		//cout<<a[i]<<" "<<a[j]<<endl; 
		swap(a[i],a[j]);
	}
	else 
	   return false;
	int l=i+1,r=strlen(a)-1;
	while(l<r){
		swap(a[l],a[r]);
		l++;r--;
	} 
	return true;
}
int main(){
while(scanf("%s",a)!=EOF) {
	for(int i=0;i<strlen(a);i++){
			cout<<a[i]; 
	}
	cout<<endl;
	while( NextPermutation(a)){
		for(int i=0;i<strlen(a);i++){
			cout<<a[i]; 
		}
		cout<<endl;
	}
	cout<<endl;
}
	return 0;
} 
  • 有重复的全排列
    http://codeup.cn/problem.php?id=2903
    • 数字版
#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std;


int main(){
    int n;
    while(cin>>n){
    int cnt=0;
    while(1){
        if(cnt==(int)pow(n,n))
            break;
        for(int j=1;j<=n;j++){
            cout<<(cnt/(int)pow(n,n-j))%n+1;
        }
        cout<<endl;
        cnt++;
    }
    }
    return 0;
}
  • 字母版
#include<bits/stdc++.h>
using namespace std;
int main(){
    char a[100];
    while(cin>>a){
    int cnt=0;
    int n=strlen(a);
    while(1){
        if(cnt==(int)pow(n,n))
            break;
        for(int j=1;j<=n;j++){
            cout<<a[(cnt/(int)pow(n,n-j))%n];
        }
        cout<<endl;
        cnt++;
    }
    }
    return 0;
}

1.4 字符串转换成整数

注意用long long,如果用int考虑n*10的时候可能已经发生溢出错误

1.5 回文判断

两头往中间扫

1.6 最长回文子串

  • 动态规划
    bool dp[i][j]表示从i->j的串是否为回文
    题目
#include<bits/stdc++.h>
using namespace std;
char input[5010];
int pos[5010];	
bool dp[5010][5010];
string toBig(char *a){
	char temp[5010];
	int tempInt=0;
	int cnt=0;
	for(int i=0;a[i]!='\0';i++){
		if(a[i]>='a'&&a[i]<='z'||a[i]>='A'&&a[i]<='Z'){
			pos[tempInt]=cnt;
			temp[tempInt++]=a[i];
		}
		else{
			pos[i]=i;
			cnt++;
		}
	}
	temp[tempInt]='\0';
	string re(temp);
	transform( re.begin(),re.end(),re.begin(),::toupper );
	return re;
}
void get(string a,int &l,int &r){
	int MaxL=1; 
	for(int i=0;i<a.length();i++){
		dp[i][i]=1;
	}
	for(int i=1;i<a.length();i++){
		if(a[i-1]==a[i]){
			dp[i-1][i]=1;
			if(MaxL<2){
				MaxL=2;
				l=i-1;
     	        r=i;
			}
		}
	}
	for(int L=3;L<=a.length();L++){
		//左端点为i时,右端点为i+L-1
		//cout<<L;
		for(int i=0;(i+L-1)<a.length();i++){
			if(a[i]==a[i+L-1]){
				dp[i][i+L-1]=dp[i+1][i+L-2];
				if(dp[i][i+L-1]==1){
					if(L>MaxL){
						MaxL=L;
						l=i;
						r=i+L-1;
					}
				}
			}
			else{
				dp[i][i+L-1]=0;
			}
		}
	}
	return ;
}
void rcv(int &l,int &r){
	l=l+pos[l];
	r=r+pos[r];
}
int main(){
	while(gets(input)!=NULL){
		string a=toBig(input); 
		int l=5010,r=5010;
		get(a,l,r);
		rcv(l,r);
		for(int i=l;i<=r;i++)
		   cout<<input[i];
		cout<<endl; 
	} 
    return 0;
}
上一篇:朴素贝叶斯—豆瓣Top250影评的情感分析与预测


下一篇:bat文件注释(jenkins中windows命令行中可以使用)