1->求字符串中重复出现的最长子串(例如:字符串drgabcdeabcfh中,最长重复出现的子串为:abc)
解题方法:利用后缀树来求解:
字符串的后缀树:(对于字符串abcd来说:abcd、bcd、cd、d)那么要求字符串中出现的最长重复子串,就是找出后缀树中的最长公共前缀
int commStr(string str1,string str2){ //求两个字符串的公共前缀的长度
int len=(str1.size()>str2.size()?str2.size():str1.size());
int i=0;
while(i<len && str1[i]==str2[i]) i++;
return i;
}
void maxSub(sting& str,string &key){
int len=str.length();
string *sub=new string[len];
for(int i=0;i<len;i++) sub[i]=str.substr(i);
sort(sub,sub+len);
int max=1;
for(int i=1;i<len;i++){
int countcur=commStr(str[i],str[i-1]);
if(max<countcur){key=sub[i].substr(0,countcur); max=countcur;}
}
}
2->素数和分解(一个整数可以分解成若干素数的和,输入一个整数,试求出所有可能的分解)
bool isPrime(int n){ //判断一个数是否是素数
int i=2;
for(;i*i<=n;i++){
if(n%i==0) return false;
}
return true;
}
void generate(int n,vector<int>& prime){ //生成n以内的素数,并保存在prime内
prime.push(2);
for(int i=3;i<n;i++){
if(isPrime(i)) prime.push_back(i);
}
}
void helper(int n,int cur,vector<int>& prime){
static vector<int> result;
if(n<0) return ;
if(n==0){Print(result.begin(),result.end());}
for(int i=cur;i<prime.size();i++){
result.push_back(prime[i]);
helper(n-prime[i],i,prime);
result.pop_back();
}
}
3->判断一个数是否是平方数
解题方法:二分法
int isSqrt(int n,int low,int high){
if(n==0) return 0;
if(low<high){
int mid=(low+high)/2;
if(mid*mid==n)
return mid;
if(mid*mid<n) return isSqrt(n,mid+1,high);
else return isSqrt(n,low,mid);
}
return -1;
}
4->N的拆分
解题方法:DFS方法可以搞定
void cutN(int n,vector<int>& v){
if(n==0){
Print(v.begin(),v.end());
}else{
for(int i=1;i<=n;i++){
v.push_back(i); cutN(n-i,v); v.pop_back();
}
}
}
5->RGB序列(如果一个字符串是由RGB三个字母随机组成的,那么试将所有的R移动到字符串的左端,B移动到字符串的右端,G在字符串的中部)
解题方法:本题跟一个数组的奇数和偶数分开类似,起初可以将GB看成一种情况,将R和GB分开,之后再分割GB
void SpliceRGB(char *& str){
char* start,*end;
start=end=str;
while(*start=='R' && *start!='\0') start++;
if(*start=='\0') return ;
end=start;
while(*end!='\0'){
if(*end=='R'){
char ch=*start; *start=*end; *end=ch; while(*start=='R') start++;
}
end++;
}
//将BG分开
end--;
while(start<end){
if(*start=='G') start++;
if(*end=='B') end--;
if(*start=='B' && *end=='G' && start<end){
swap(*start,*end); start++; end--;
}
}
}
6->删除字符串开始以及末尾的空白符,并且把单词间的空格压缩
解题方法:这一题和数组删除某个元素有相似之处。
void changeStr(string &s){
string::iterator p1=find_first_not_of(s.begin(),s.end(),' ');
string::iterator p2=find_last_not_of(s.begin(),s.end(),' ');
s.substr(p1,p2);
string::iterator p=s.begin();
int index=0; int flag=1;
while(p!=s.end()){
if(*p!=' '){ s[index++]=*p;flag=1;}
else { if(flag==1){ s[index++]=*p; flag=0;}}
p++;
}
}
7->字符串移动(字符串为*和26个字母的组合,把*移到最左侧,把字母移到最右侧并且保持相对位置不变)
void partitionStr(char *str){
int len=strlen(str);
int i=str+len,j=str+len;
while(i>=0){
if(str[i]!='*') { swap(str ,i--,j--);}
else i--;
}
}
8->有一个单向循环链表,从头开始如果到第m个就开始出队,如此循环直到最后一个元素。再把所有出队的元素链接成一个新的链表。
ListNode* recorder(ListNode *head,int m){
ListNode *p,*pre,*tail;
p=head;
ListNode *newHead=new ListNode(-1); //新的链表的辅助头结点
tail=newHead;
int count=1;
while(p->next!=p){
count++; pre=p; p=p->next;
if(count%m==0){
pre->next=p->next; //将p点从原表中断开
tail->next=p; tail=p; //将p结点链接到新表
p=pre->next;
}
}
tail->next=p; tail=p;
tail->next=newHead->next;
return newHead->next;
}