文章目录
- 回顾
- 解题思路
- c 语言代码
回顾
- A+B III
- 问题 H: 三角数
- 问题 G: 3个数
- 等式 数组下标查询,降低时间复杂度
- 1405 问题 E: 世界杯
- xtu 数码串
- xtu oj 神经网络
- xtu oj 1167 逆序数(大数据)
- xtu oj 原根
- xtu oj 不定方程的正整数解
解题思路
冒泡排序模板
void sort(char arr[], int n) { int i, j, temp; for (i = 0; i < n-1; i++) { for (j = 0; j < n-i-1; j++) { if (arr[j] > arr[j+1]) { // 交换 arr[j] 和 arr[j+1] temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } }
}
下面贴一份过不了的代码,我不知道为啥过不了,问了几个朋友都没搞懂。思路是,我认为两个字符串排序之后完全相等,这两个字符串就互为可变字符串,先手写了一个冒泡排序,然后用一个临时数组存排序之前的字符串,比较完了之后再把临时数组的字符复制到原字符串数组,相当于做一个复原。
用一个数组 len
存每个字符串的长度,用一个数组 cnt
存当前字符串作为这一组可变字符串的第一个字符串,该组有多少个可变字符串。记录最大的 cnt
的值,还有这个 cnt
数组对应的下标,然后再查询出来。
#include<stdio.h>
#include<string.h>
#include<stdbool.h>//表示输入的数组,存字符串的
char a[110][15];
//表示当前组有多少个可变字符串,下标表示的是当前组的第一个可变字符串的 a 数组的下标,数值表示的是该组的可变字符串的数量
int cnt[110];
//字符串的长度
int len[110];//手写一个冒泡排序
void sort(char arr[], int n) { int i, j, temp; for (i = 0; i < n-1; i++) { for (j = 0; j < n-i-1; j++) { if (arr[j] > arr[j+1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } }
} int main(){int t;scanf("%d",&t);while(t--){//输入字符串的数目, n 个字符串int n;scanf("%d",&n);//输入字符串,记录字符串的长度for(int i=0;i<n;i++){scanf("%s",a[i]);len[i]=strlen(a[i]);}//表示最多的可变字符串的数目int max_times=1;//表示最多的可变字符串的第一个字符串的位置int pos=0;//枚举每一个字符串for(int i=0;i<n;i++){//算从 i+1 到最后一个字符串,判断是不是可变字符串for(int j=i+1;j<n;j++){//临时数组存字符串,方便后面还原char temp[15];for(int k=0;k<len[j];k++){temp[k]=a[j][k];}//排序,排序之后比较,假设相等就表示两个字符串是互为可变字符串sort(a[j],len[j]);bool is_same=true;//假设两个字符串的长度不一样,肯定就不行if(len[i]!=len[j]){is_same=false;}else{for(int k=0;k<len[i];k++){if(a[i][k]!=a[j][k]){is_same=false;break;}} }//假设两个字符串互为可变字符串就把计数器增加if(is_same){cnt[i]++;}//还原,方便下一次比较for(int k=0;k<len[j];k++){a[j][k]=temp[k];}}//维护最大的可变字符串的数目if(cnt[i]+1>max_times){max_times=cnt[i]+1;pos=i;}}//输出答案printf("%d\n",max_times);printf("%s\n",a[pos]);//重复上面的步骤,我们现在知道最多的可变字符串的那一组的第一个字符串,比较和这个字符串互为可变字符串的,输出,就是答案for(int j=pos+1;j<n;j++){char temp[15]={'\0'};for(int k=0;k<len[j];k++){temp[k]=a[j][k];}sort(a[j],len[j]);bool is_same=true;if(len[pos]!=len[j]){is_same=false;}else{for(int k=0;k<len[pos];k++){if(a[j][k]!=a[pos][k]){is_same=false;break;}} }if(is_same){printf("%s\n",temp);}}puts("");//方便下一次输入for(int i=0;i<110;i++){cnt[i]=0;for(int j=0;j<15;j++){a[i][j]='\0';}}}return 0;
}
能过样例,过不了题,这让我非常郁闷。有读者能帮我找出上面代码的问题,欢迎评论或者私信我,我真的非常想知道上面的代码的问题出现在哪里。
朋友告诉我,统计字母出现的次数也可以,就是比较两个字符串出现字母的次数,假设两个字符串出现的字母次数是相等的,那么两个字符串可以认为是互为可变字符串。其他的思路和我上面的一样。
以后我写题解或者啥的,还是在代码里面写一些注释,感觉会好一些,我把代码发给朋友,请教他,把思路和代码都发给他,他说看不懂我的代码,以后我只要发出来的算法题代码,尽量写一写注释,毕竟一些变量名啥的,具体的意思,在代码旁边看可能更加的直观。
找到前面代码的问题了,现在改一下。
简单地说,就是把字符串排序,看两个字符串排序之后是不是完全相等,假设完全相等就说明两个字符串是同一组可变字符串。前面代码的问题在于,我把原字符串看成是排序好的字符串了。但是其实需要额外用一个数组存排序好的字符串。
然后就是一些更新操作,细节都在注释里面了。对笔者来说,二维字符串的输入,还有字符串一些函数的使用其实不是那么熟练。比如说 strlen
这个函数返回的是 unsigned int
或者 unsigned long long
,就是假设直接把 strlen
写在循环体里面会有编译警告,但是不影响,但是我还是习惯定义一个变量在循环体外面,没有警告会让自己安心一些。之前写的快速排序会把字符串长度改变,所以用的是一个数组把字符串长度存下来。可能是我的快速排序的模板有点问题。
c 语言代码
#include<stdio.h>
#include<string.h>
#include<stdbool.h>//表示输入的数组,存字符串的
char a[110][15];
//存排序之后的字符串
char tempa[110][15];
//表示当前组有多少个可变字符串,下标表示的是当前组的第一个可变字符串的 a 数组的下标,数值表示的是该组的可变字符串的数量
int cnt[110];
//字符串的长度
int len[110];//手写一个冒泡排序
void sort(char arr[], int n) { int i, j, temp; for (i = 0; i < n-1; i++) { for (j = 0; j < n-i-1; j++) { if (arr[j] > arr[j+1]) { temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } }
} int main(){int t;scanf("%d",&t);while(t--){//输入字符串的数目, n 个字符串int n;scanf("%d",&n);//输入字符串,记录字符串的长度for(int i=0;i<n;i++){//输入二维数组scanf("%s",a[i]);//存每一个字符串的长度len[i]=strlen(a[i]);//把字符串存到另一个数组,并排序,因为我们要比较的是排序之后的字符串,但是又需要保留原来的字符串,上次考试好像考了这个函数//我当时不是很会用,用循环模拟的,这个函数是把后面的数组复制到前面,容易搞错strcpy(tempa[i],a[i]);sort(tempa[i],len[i]);}//表示最多的可变字符串的数目,最小也是一个,字符串自己int max_times=1;//表示最多的可变字符串的第一个字符串的位置//初始的时候就是第一个字符串的下标int pos=0;//枚举每一个字符串for(int i=0;i<n;i++){//算从 i+1 到最后一个字符串,判断是不是可变字符串for(int j=i+1;j<n;j++){//临时数组存字符串,方便后面还原char temp[15];for(int k=0;k<len[j];k++){temp[k]=a[j][k];}//排序,排序之后比较,假设相等就表示两个字符串是互为可变字符串sort(a[j],len[j]);bool is_same=true;//假设两个字符串的长度不一样,肯定就不行if(len[i]!=len[j]){is_same=false;}else{for(int k=0;k<len[i];k++){//注意这里是和排序之后的字符串去比较if(tempa[i][k]!=a[j][k]){is_same=false;break;}} }//假设两个字符串互为可变字符串就把计数器增加if(is_same){cnt[i]++;}//还原,方便下一次比较for(int k=0;k<len[j];k++){a[j][k]=temp[k];}}//维护最大的可变字符串的数目//加一是因为,比如说 abc 是第一个字符串,bca 是第二个字符串,我们计数器只会记录 1 ,但是实际上要把 abc 这个第一个字符串算上//相当于没算上第一个字符串,所以要加上if(cnt[i]+1>max_times){max_times=cnt[i]+1;pos=i;}}//输出答案printf("%d\n",max_times);printf("%s\n",a[pos]);//重复上面的步骤,我们现在知道最多的可变字符串的那一组的第一个字符串,比较和这个字符串互为可变字符串的,输出,就是答案for(int j=pos+1;j<n;j++){char temp[15]={'\0'};for(int k=0;k<len[j];k++){temp[k]=a[j][k];}sort(a[j],len[j]);bool is_same=true;if(len[pos]!=len[j]){is_same=false;}else{for(int k=0;k<len[pos];k++){if(a[j][k]!=tempa[pos][k]){is_same=false;break;}} }if(is_same){printf("%s\n",temp);}}//换行puts("");//清空数组,方便下一个样例for(int i=0;i<110;i++){cnt[i]=0;for(int j=0;j<15;j++){a[i][j]='\0';}}}return 0;
}