xtu oj 最多的可变换字符串

文章目录

回顾

解题思路

冒泡排序模板

c 复制代码
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 数组对应的下标,然后再查询出来。

c 复制代码
#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 语言代码

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;
}
相关推荐
汝即来归16 小时前
选择排序和冒泡排序;MySQL架构
数据结构·算法·排序算法
光头man20 小时前
【八大排序(二)】希尔排序
算法·排序算法
云边有个稻草人1 天前
【优选算法】—移动零(双指针算法)
算法·排序算法·双指针算法
黄亚磊112 天前
选择排序 冒泡排序 MySQL 架构
mysql·排序算法
In 20292 天前
堆【Lecode_HOT100】
java·算法·排序算法
啥也不会的研究僧2 天前
【算法篇】——数据结构中常见八大排序算法的过程原理详解
数据结构·算法·排序算法
小孩玩什么3 天前
堆排:一种高效的比较排序算法
java·c语言·数据结构·经验分享·redis·算法·排序算法
仟濹3 天前
洛谷【贪心算法】P1803 学习笔记
c语言·c++·笔记·学习·算法·贪心算法·排序算法
TANGLONG2223 天前
【初阶数据结构与算法】八大排序算法之交换排序(冒泡排序,快速排序---hoare、挖坑法、lomuto双指针3种版本)
c语言·数据结构·c++·算法·面试·蓝桥杯·排序算法
code monkey.3 天前
【排序算法】—— 归并排序
c++·算法·排序算法