文章分上下两章,上是一些字符串相关的基础题,下会包括一些算法
1.字符串中是否有两两重复的元素,例如aabfc就有重复元素a
题目分析:改题目字符用ASCII表示,那么就可以用计数排序思想,转相应下标
//ti5-1-1
//字符串是否有重复元素,例如aabcdf就有重复的a字符
//用计数的思想,字符串转下标
#include<stdio.h>
#include<string.h>
bool jishu(char str[]);
void sort(char str[],int begin,int end);
int main(void)
{
char buf1[100];
scanf("%s",buf1);
if(jishu(buf1))
printf("字符串wuwuwuww重复元素\n");
else
printf("字符串有重复元素\n");
return 0;
}
bool jishu(char str[])
{
int buf[26]={0};
for(int i=0;i<strlen(str);i++)
{
if(buf[str[i]-'a']==1)
return false;
else
buf[str[i]-'a']++;
}
return true;
}
2.字符串翻转,在不开辟新的存储空间
题目分析:快速排序思想中前后双指针进行字符串的交换
//ti5-1-2
//字符串翻转,在不开辟新的空间下
#include<stdio.h>
#include<string.h>
int main(void)
{
char buf[100];
scanf("%s",buf);
int i=0;
int j=strlen(buf)-1;
while(i<j)
{
char a=buf[i];
buf[i]=buf[j];
buf[j]=a;
i++;
j--;
}
printf("%s",buf);
return 0;
}
3.是否为变形词,元素种类个数相同的字符串
题目分析:
法一:可以利用计数排序的思路,一个字符串计数时加加,一个字符串计数时减减,最后检查开辟的空间所有元素是否为0
法二:可以对字符串进行排序,然后在进行字符串的比较。
//ti5-1-3
//判断是否为变形词,元素个数和种类都相同,abcd,abdc
//法一:用计数的思想,字符串转下标
//法二:将两个字符串排序后进行比较
#include<stdio.h>
#include<string.h>
bool jishu(char str1[],char str2[]);
void sort(char str[],int begin,int end);
int main(void)
{
char buf1[100];
char buf2[100];
scanf("%s %s",buf1,buf2);
//法一
// if(jishu(buf1,buf2))
// printf("两个字符串相等\n");
// else
// printf("两个字符串bububu相等\n");
//法二
sort(buf1,0,strlen(buf1)-1);
sort(buf2,0,strlen(buf2)-1);
if(strcmp(buf1,buf2)==0)
printf("两个字符串相等\n");
else
printf("两个字符串bububu相等\n");
return 0;
}
bool jishu(char str1[],char str2[])
{
int buf[26]={0};
for(int i=0;i<strlen(str1);i++)
{
buf[str1[i]-'a']++;
}
for(int i=0;i<strlen(str2);i++)
{
buf[str2[i]-'a']--;
}
for(int i=0;i<26;i++)
{
if(buf[i]!=0)
{
return false;
}
}
return true;
}
void sort(char str[],int begin,int end)
{
if(begin>end)
return ;
int i=begin;
int j=end;
int base=begin;
while(i!=j)
{
while(i<j&&str[j]>=str[base])
j--;
while(i<j&&str[i]<=str[base])
i++;
if(i<j)
{
char a=str[i];
str[i]=str[j];
str[j]=a;
}
}
char a=str[base];
str[base]=str[i];
str[i]=a;
sort(str,begin,i-1);
sort(str,i+1,end);
}
4.将字符串中的空格字符转化为%20
题目分析:遇到空格字符就把字符串空格之后的往后挪动,然后将%20依次赋值上去
//ti5-1-4
//将字符串中空格替换为%20
#include<stdio.h>
#include<string.h>
int main(void)
{
char buf[100];
gets(buf);
for(int i=0;i<strlen(buf);i++)
{
int j=strlen(buf)-1;
while(buf[i]==' ')
{
int k=j+2;
while(i<j)
{
buf[k]=buf[j];
j--;
k--;
}
buf[i++]='%';
buf[i++]='2';
buf[i]='0';
}
}
printf("%s",buf);
return 0;
}
5.压缩字符串,若压缩后的字符串大于原字符串,那么输出原字符串,例如aaabbbc压缩后a3b3c1
题目分析:设置标志位,遇到不同的元素,切换标志位
//压缩字符串
#include<stdio.h>
#include<string.h>
int main(void)
{
char buf[100];
char str[100];
gets(buf);
char count='1';
int sum=0;
char log=buf[0];
for(int i=1;i<strlen(buf);i++)
{
if(buf[i]==log)
count++;
if(buf[i]!=log)
{
str[sum++]=log;
str[sum++]=count;
log=buf[i];
count='1';
}
}
str[sum++]=log;
str[sum++]=count;
if(strlen(str)>strlen(buf))
puts(buf);
else
puts(str);
return 0;
}
6.判断两个字符串的字符集是否相同
题目分析:采用计数排序思想,开辟两个空间对字符进行计数,然后再比较开辟的两个空间的所有元素。
//判断两个字符的字符串是否相同字符集是否相同
//两个字符串开辟两个空间分别进行计数
#include<stdio.h>
#include<string.h>
int main(void)
{
char buf1[]="aabcdeedff";
char buf2[]="abcdefg";
int str[26]={0};
int str0[26]={0};
for(int i=0;i<strlen(buf1);i++)
{
if(str[buf1[i]-'a']==0)
str[buf1[i]-'a']++;
}
for(int i=0;i<strlen(buf2);i++)
{
if(str0[buf2[i]-'a']==0)
str0[buf2[i]-'a']++;
}
for(int i=0;i<26;i++)
{
if(str[i]!=str0[i])
{
printf("两个字符串的字符集bbbbbu相同\n");
return 0;
}
}
printf("两个字符串的字符集xxxxiang相同\n");
return 0;
}
7.旋转词,字符串str0通过旋转,能否包含字符串str1
题目分析:有一个重要的点就是,若将str0的字符串使用str0+str0拼接起来,这个字符串将包括str0的所有旋转词,只需要检测str1是否含与str0str0就能判断str0是否可以通过旋转包含str1
//旋转词
//字符串str1翻转是否可以包含字符串str2
//重要思路,字符串str1+str1可以包含所有的旋转词,那么只需要查str2是否包含在内
#include<stdio.h>
#include<string.h>
int main(void)
{
char str0[100];//是保存str1+str1的
char str1[]="qwertyu";
char str2[]="rtqwx";
sprintf(str0,"%s%s",str1,str1);
for(int i=0;i<strlen(str0);i++)
{
if(str0[i]==str2[0])
{
int count=0;
for(int j=i;j<i+strlen(str2)&&(i+strlen(str2)-1<strlen(str0));j++,count++)
{
if(str2[count]!=str0[j])
break;
if(count==strlen(str2)-1)
{
printf("旋转能够包含字符串\n");
return 0;
}
}
}
}
printf("旋转不能包含到\n");
return 0;
}
8.将字符串按照单词翻转 例如 hi good morning,按照单词翻转morning good hi
题目分析:可以先进行字符翻转,这样一个逆序的单词就会交换位置,然后在进行单词内部调序,
//将字符串按单词翻转
//先按照字符翻转
//饭后在一个一个单次的翻转
#include<stdio.h>
#include<string.h>
int main(void)
{
char buf[100];
gets(buf);
int count;//记录空格位置
//按照字符翻转
for(int i=0,j=strlen(buf)-1;i<j;i++,j--)
{
int a=buf[i];
buf[i]=buf[j];
buf[j]=a;
}
for(int i=0;i<strlen(buf);i++)
{
int j=i;
while(buf[j]!=' '&&j<strlen(buf))
j++;
count=j;//记录空格位置
if(j!=strlen(buf)-1)//相当于到了末尾,就不进行减减了,减减是方便好进行单词内的字符转换
j--;
while(i<j)
{
int a=buf[i];
buf[i]=buf[j];
buf[j]=a;
i++;
j--;
}
i=count;
}
puts(buf);
return 0;
}
9.去掉连续出现的K个0
题目分析:检测到0就再往后面检测k个,若都满足,就将空格后的字符串向前移动k个字符
//去掉连续出现的k个0
#include<stdio.h>
#include<string.h>
int main(void)
{
int k;
scanf("%d",&k);
char buf[100];
scanf("%s",buf);
int count=0;//记录是否有k个连续的0
int count_num=strlen(buf);
for(int i=0;i<count_num;i++)
{
if(buf[i]=='0')
{
int j;
//这个for判断检测i后面的k个元素中有几个0
for(j=i;j<i+k&&(j+k)<=count_num;j++)
{
if(buf[j]=='0')
count++;
}
printf("%d\n",count);
if(count==k)//若上面for检测的有k个0,就要进行位移,否则就直接退出循环
{
while(j<count_num)
{
buf[j-k]=buf[j];
j++;
}
count_num-=k;
}
else
{
count=0;
}
continue;
while(buf[i]=='0'&&i<count_num)//跳过后面的0
i++;
i--;//上面的while跳到了正确的位置,由于for循环还有一个加加,所以这里就在减减一次
count=0;
}
}
for(int i=0;i<count_num;i++)
{
printf("%c",buf[i]);
}
printf("\n");
return 0;
}
10.判断是否为回文数
题目分析:法一:利用快速排序双指针思想,两两比较即可
法二:开辟新的空间,翻转字符串,与原字符串进行比较,若相同就输出
//判断回文串
//法一:快速排序前后双指针,进行比较
//翻转后与原字符串相同
#include<stdio.h>
#include<string.h>
int main(void)
{
char buf[100];
gets(buf);
//法一
// for(int i=0,j=strlen(buf)-1;i<j;i++,j--)
// {
// if(buf[i]!=buf[j])
// {
// printf("bbbbu是回文串\n");
// return 0;
// }
// }
// printf("ssss是回文串\n");
//法二
char buf1[strlen(buf)];
for(int i=0,j=strlen(buf)-1;i<strlen(buf);i++,j--)
{
buf1[i]=buf[j];
}
puts(buf1);
if(strcmp(buf1,buf))
printf("bbbbu是回文串\n");
else
printf("ssss是回文串\n");
return 0;
}
11.最短摘要
题目分析,一个一个单词的判断,若找到第一个元素,就可以对第二个元素进行标记,当前两个元素都已经标记,遇到第三个关键词就可以重新进行初始化。若在遇到第二个关键词之前,又遇到了第一个关键词,那么就要重新计数了。
//最短摘要
#include<stdio.h>
#include<string.h>
int main(void)
{
char key1[]="one";
char key2[]="two";
char key3[]="ten";
char danci_temp[100];
int key1_log=0;//两个个关键词是否找到的标志位
int key2_log=0;
int min_danci=100;//记录最小的摘要,因为essay数组都只有100个;
int danci_num=0;//记录实时的摘要数量
int count;//记录空格的下标
char essay[100];
gets(essay);
for(int i=0;i<strlen(essay);i++)
{
int j=i;
while(essay[j]!=' '&&j<strlen(essay)-1)
j++;
count=j;//记录当前空格的位置
if(key1_log==1)
danci_num++;
if(count==strlen(essay)-1)//当第三个关键词在最后的话,就会出错,因为count在空格的位置,那么去单词就是正确的,在末尾取单词就会少一个字符
count++;
strncpy(danci_temp,essay+i,count-i);//截取单词
if(strcmp(key1,danci_temp)==0&&key1_log==0)
{
key1_log=1;
danci_num=1;
}
//在没有找到第二个关键词之前,又遇到了第一个关键词那么就等重头再来
if(strcmp(key1,danci_temp)==0&&key1_log==1&&key2_log==0)
{
key1_log=1;
danci_num=1;
}
if(strcmp(key2,danci_temp)==0&&key1_log==1&&key2_log==0)
key2_log=2;
if(strcmp(key3,danci_temp)==0&&key1_log==1&&key2_log==2)
{
if(danci_num<min_danci)
{
min_danci=danci_num;
key1_log=0;
key2_log=0;
danci_num=0;
}
}
memset(danci_temp,0,sizeof(danci_temp));//初始化danci_temp数组为空,避免影响下一次单词的读取
i=count;
}
if(min_danci==100)
printf("最小摘要为%d",0);
else
printf("最小摘要为%d",min_danci);
}