本题要求实现一个函数,求N个集合元素A[]的中位数,即序列中第⌊(N+1)/2⌋大的元素。其中集合元素的类型为自定义的ElementType。
函数接口定义:
ElementType Median( ElementType A[], int N );
其中给定集合元素存放在数组A[]中,正整数N是数组元素个数。该函数须返回N个A[]元素的中位数,其值也必须是ElementType类型。
裁判测试程序样例:
#include <stdio.h>
#define MAXN 10
typedef float ElementType;
ElementType Median( ElementType A[], int N );
int main ()
{
ElementType A[MAXN];
int N, i;
scanf("%d", &N);
for ( i=0; i<N; i++ )
scanf("%f", &A[i]);
printf("%.2f\n", Median(A, N));
return 0;
}
/* 你的代码将被嵌在这里 */
CODE 1
**用了选择排序法后,返回中位数;但是在测试点5(大N,卡时)处运行超时
**这题的偶数个元素的序列不需要中间两个数取平均欸(+_+)?
ElementType Median( ElementType A[], int N )
{
int i, j, index;
ElementType tmp;
for ( i=0; i<N-1; i++ ){
index = i;
for ( j=i+1; j<N; j++ ){
if ( A[j]<A[index] ) index = j;
}
tmp = A[i];
A[i] = A[index];
A[index] = tmp;
}
//if ( N%2 ) return A[N/2];
//else return (A[N/2-1]+A[N/2])/2;
return A[N/2];
}
**目测要用时间复杂度更低的算法来解
CODE 2
**用的希尔排序法
ElementType Median( ElementType A[], int N )
{
int i, j, gap;
ElementType tmp;
for ( gap=N/2; gap>0; gap/=2 ){
//分组进行插入排序,每次分组数量为上一次的一半
for ( i=gap; i<N; i++ ){
//将A[i]插入到所在分组的正确位置上
for ( j=i-gap; j>=0 && a[j]>a[j+gap]; j-=gap ){
//按组进行直接插入,每组两两相隔gap
//这里其实是组内通过两两交换的方式来排序
tmp = A[j];
A[j] = A[j+gap];
A[j+gap] = tmp;
}
}
}
return A[N/2];
}
本题要求实现一个打印非负整数阶乘的函数。
函数接口定义:
void Print_Factorial ( const int N );
其中N是用户传入的参数,其值不超过1000。如果N是非负整数,则该函数必须在一行中打印出N!的值,否则打印“Invalid input”。
裁判测试程序样例:
#include <stdio.h>
void Print_Factorial ( const int N );
int main()
{
int N;
scanf("%d", &N);
Print_Factorial(N);
return 0;
}
/* 你的代码将被嵌在这里 */
CODE
void Print_Factorial( const int N )
{
int num[3001] = {
0}; //数组的每一个元素对应n!结果的每一位数,num[0]对应个位数,以此类推
int i, j, tmp; //tmp用于记录每一位和i相乘的临时结果
int k = 1; //位数,默认有1位
int n = 0; //进位标志,1则进位,0则不进;一开始不进位
num[0] = 1; //阶乘从1开始
if ( N<0 ){
printf("Invalid input");
}
else{
//就是手算乘法的顺序
for ( i=2; i<=N; i++ ){
//从2开始乘
for ( j=0; j<k; j++ ){
//i需要与k位数分别相乘,从个位开始乘
tmp = num[j]*i + n; //还要加上前面相乘结果需要的进位数
num[j] = tmp%10; //更新该位上的数字,为tmp的个位数
n = tmp/10; //看是否进位,需要进几位
}
//与最高位相乘后,如果进位,需要增加一个位数,并且更新该位的数为进位数
while(n){
num[k++] = n%10; //先在n!的第k位记下最高位带来的进位数,同时位数增加一位
n /= 10; //看是否还要进位,因为i增到1000,和一位数相乘就会带来多次进位
}
}
for ( i=k-1; i>=0; i-- ){
//注意是逆序输出,因为数组从个位数开始记录
printf("%d", num[i]);
}
}
}
BCD数是用一个字节来表达两位十进制的数,每四个比特表示一位。所以如果一个BCD数的十六进制是0x12,它表达的就是十进制的12。但是小明没学过BCD,把所有的BCD数都当作二进制数转换成十进制输出了。于是BCD的0x12被输出成了十进制的18了!
现在,你的程序要读入这个错误的十进制数,然后输出正确的十进制数。提示:你可以把18转换回0x12,然后再转换回12。
输入格式:
输入在一行中给出一个[0, 153]范围内的正整数,保证能转换回有效的BCD数,也就是说这个整数转换成十六进制时不会出现A-F的数字。
输出格式:
输出对应的十进制数。
CODE
** 一开始看不懂题目啊(。_。)…
** 小明的错误思路其实是BCD数中的8421码,用八个比特表示两位十进制数,每位十进制数用四个比特(二进制)表示,即用0000, 0001, 1001分别表示0,1,2,…9的数字;
** 然后,BCD数的十六进制0x12,当作二进制数转换成十进制,即把1和2分别用四个比特表示为0001 0010,再转换成十进制就是18了
** 题意即, 输入一个十进制数,把它转换成十六进制数,由于不会出现A-F的数字,所以得出的十六进制数正好是十进制数。
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n); //读入十进制
printf("%x", n); //输出十六进制
return 0;
}
乌龟与兔子进行赛跑,跑场是一个矩型跑道,跑道边可以随地进行休息。乌龟每分钟可以前进3米,兔子每分钟前进9米;兔子嫌乌龟跑得慢,觉得肯定能跑赢乌龟,于是,每跑10分钟回头看一下乌龟,若发现自己超过乌龟,就在路边休息,每次休息30分钟,否则继续跑10分钟;而乌龟非常努力,一直跑,不休息。假定乌龟与兔子在同一起点同一时刻开始起跑,请问T分钟后乌龟和兔子谁跑得快?
输入格式:
输入在一行中给出比赛时间T(分钟)。
输出格式:
在一行中输出比赛的结果:乌龟赢输出@@,兔子赢输出_,平局则输出--;后跟1空格,再输出胜利者跑完的距离。
CODE
**常见错误大赏
**一开始,在控制兔子休息30分钟的那个循环条件用的i
#include <stdio.h>
int main()
{
int t;
int i = 0;
int tur, rab; //分别代表乌龟和兔子跑的距离
tur = rab = 0;
scanf("%d", &t);
while ( i<t ){
tur += 3;
rab += 9;
i++; //过了一分钟
if ( i%10==0 && rab>tur ){
t = t - i; //还剩t-i分钟
i = 0;
while( i<30 && i<t ){
//兔子休息,同时有可能在兔子休息的时候到时间
tur += 3;
i++; //兔子休息1分钟,这时乌龟继续跑了1分钟
}
}
}
if ( tur>rab ) printf("@_@ %d", tur);
else if ( rab>tur ) printf("^_^ %d", rab);
else printf("-_- %d", tur);
return 0;
}
7-23 币值转换
输入一个整数(位数不超过9位)代表一个人民币值(单位为元),请转换成财务要求的大写中文格式。如23108元,转换后变成“贰万叁仟壹百零捌”元。为了简化输出,用小写英文字母a-j顺序代表大写数字0-9,用S、B、Q、W、Y分别代表拾、百、仟、万、亿。于是23108元应被转换输出为“cWdQbBai”元。
输入格式:
输入在一行中给出一个不超过9位的非负整数。
输出格式:
在一行中输出转换后的结果。注意“零”的用法必须符合中文习惯。
CODE
**所有测试点全通过的时候简直太开心了啊啊啊啊啊啊啊啊
**这必须有排面!!!
#include <stdio.h>
int main()
{
char a[10] = {
'a','b','c','d','e','f','g','h','i','j'};
char b[5] = {
'S','B','Q','W','Y'};
int num[9]; //输入数字的每位数
int n, tmp; //临时用用
int i=0, len=0; //len是数字的位数
int cnt = 0; //低位0的个数
int flag1 = 0; //记录万位以上,亿位以下的第flag1位
int flag2 = 0; //亿位以下,万位及以前都是0则为1
scanf("%d", &n);
/*计算n的位数*/
tmp = n;
do{
tmp /= 10;
len++;
}while(tmp);
/*把n的每一位数按从高位到低位依次装入数组*/
tmp = n;
for ( i=len-1; i>=0; i-- ){
num[i] = tmp%10;
tmp /= 10;
}
/*最小个位数单独拎出来*/
if ( n==0 ) printf("%c", a[0]);
/*计算低位0的个数*/
i = 1;
while ( num[len-i]==0 ){
//数组高位记录的数字低位
cnt++;
i++;
}
/*这就开始了!*/
for ( i=0; i<len-cnt; i++ ){
//输出低位0后的数即可
n = num[i]; //这时n存的是每一位数字(就为了下面a[n])
printf("%c", a[n]); //将数字转化成a[]中的字母并输出
if ( num[i] ){
//非0数字后必有字
/*第一个大写汉字*/
switch(len-i){
case 9: printf("%c", b[4]); break; //亿
case 8: case 7: case 6: //万位以上
flag1 = len-i; //记录下千万位/百万位/十万位的位数
printf("%c", b[len-i-6]);
break;
case 5: case 4: case 3: case 2: //万位及以下
printf("%c", b[len-i-2]); break;
}
/*千万、百万、十万的第二个大写汉字 + 跳过中间的0*/
if ( flag1>5 ){
if ( i==len-cnt-1 ){
/*低位0前最后一个非0数字*/
printf("%c", b[3]); //输出“万”就结束了
}
else{
/*后面还有非0数字*/
while ( num[++i]==0 ){
//跳过万位及以上的0
if ( len-i==5 || i>=len-cnt ){
//万位仍是0或已是低位0前末位,输出“万”并结束
printf("%c", b[3]);
flag2 = 1;
break;
}
}
flag1 = 0; //重置,下一轮重新判断
if ( flag2==0 ){
/*如果百万位/十万位/万位上不全是0的话*/
i--; //需要退一个i,使之进到下一轮循环并输出这个数字对应的字母
flag2 = 0; //重置,下一轮重新判断
}
}
}
}
else{
/*万位以下 之 跳过中间的0*/
while ( num[i]==0 ){
i++;
}
i--; //前面的循环多跳了一个非0数,因为后面又要i++了(同上)
}
}
return 0;
}
输入2个字符串S1和S2,要求删除字符串S1中出现的所有子串S2,即结果字符串中不能包含S2。
输入格式:
输入在2行中分别给出不超过80个字符长度的、以回车结束的2个非空字符串,对应S1和S2。
输出格式:
在一行中输出删除字符串S1中出现的所有子串S2后的结果字符串。
输入样例:
Tomcat is a male ccatat
cat
输出样例:
Tom is a male
CODE
**想着直接用之前 实验与习题指导 实验11-1-8 查找子串 来作函数,结果发现之前写的函数有错;大概是那题的测试点没有这题如上的样例,在第二次删除子串时,第一个c对应上了,但是非子串,得重新比对,紧接着就是子串;而我之前在这种情况下没有(*)i–就退出了,导致c后面的c被跳过,就找不到cat子串了。
#include <stdio.h>
#include <string.h>
#define N 82
int search( char *s, char *t );
int main()
{
char s1[N], s2[N];
int flag; //标记是否有子串,子串首地址的逻辑地址
int i, len1, len2;
i = 0;
s1[i] = getchar();
while( s1[i]!='\n' ){
i++;
s1[i] = getchar();
}
s1[i] = '\0';
i = 0;
s2[i] = getchar();
while( s2[i]!='\n' ){
i++;
s2[i] = getchar();
}
s2[i] = '\0';
flag = search(s1,s2);
len2 = strlen(s2);
while( flag!=-1 ){
len1 = strlen(s1);
for ( i=flag; i+len2<len1; i++ ){
s1[i] = s1[i+len2];
}
s1[i] = '\0';
flag = search(s1,s2);
}
printf("%s", s1);
return 0;
}
/*在字符串s中查找子串t,返回子串t在s中的首地址。若未找到,则返回-1。*/
int search( char *s, char *t )
{
int p = -1; //默认为-1
int i, j;
int flag = 0; //有子串为1
for ( i=0; s[i]!='\0'; i++ ){
j = 0; //注意,每一次比对都从第一个字符开始
while( s[i] && t[j] && s[i]!=t[j] ) i++; //找到第一个相同的字符
if ( s[i]=='\0' ) break; //都没找到
else if ( s[i]==t[j] ){
//找到了
p = i; //赋予首地址的逻辑地址
while( s[i] && t[j] ){
//循环至不同了或者t[]结束了或者s[]先结束了
if ( s[i]!=t[j] ){
i--; //(*)退回到之前相等的最后一位,因为进入下一轮for循环还要i++,要保证不对等的这一位与t的第一位可以进行对比
break; //在这里结束是因为t[]扫描到'\0'了
}
i++;
j++;
}
if ( t[j]=='\0' ){
flag = 1; //如果是t[]扫描到'\0'了,标记为有子串
break; //有子串了即可退出
}
if ( flag==0 ) p = -1; //没有子串需要置p为-1
}
}
return p;
}
给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。
输入格式:
测试输入包含一个测试用例,在一行内给出总长度不超过500 000的字符串。字符串由若干单词和若干空格组成,其中单词是由英文字母(大小写有区分)组成的字符串,单词之间用若干个空格分开。
输出格式:
每个测试用例的输出占一行,输出倒序后的句子,并且保证单词间只有1个空格。
CODE
**跳过空格的部分不要了,str[-1]会进入if( str[i]!=’ ’ )的条件语句中,导致:如果最后一个单词输出后,后面还有空格的话,就会在跳过空格后进入下一个if语句,多输出一个空格
**str[-1]是合法的!只是值不确定罢了
#include <stdio.h>
#include <string.h>
#define N 500001
int main()
{
char str[N];
int len = 0;
int front, rear; //分别为每个单词的第一个字母和最后一个字母
int cnt = 0; //控制除第一个单词外的单词前有一个空格
int i, j, k;
gets(str);
len = strlen(str);
for ( i=len-1; i>=0; i-- ){
//逆序查找+输出
// if ( str[i]==' ' ){ //跳过空格
// while( str[i]==' ' ){
// i--;
// if ( i<=0 ) break; //(*******)
// }
// }
if ( str[i]!=' ' ){
rear = i; //标记词尾
while( str[i]!=' ' ){
i--;
if ( i<0 ) break;
}
front = ++i; //标记词头,并保证for循环下一轮i是单词后的第一个空格或者直接结束
if ( cnt>0 )
printf(" ");
for ( j=front; j<=rear; j++ ){
printf("%c", str[j]);
}
cnt++;
}
}
return 0;
}
将一个正整数N分解成几个正整数相加,可以有多种分解方法,例如7=6+1,7=5+2,7=5+1+1,…。编程求出正整数N的所有整数分解式子。
输入格式: 输出格式: CODE **自己还搞不出来的代码>︿< **学习的这篇(侵删)5-37 整数分解为若干项之和 - 文之 - 博客园 给定某数字A(1≤A≤9)以及非负整数N(0≤N≤100000),求数列之和S=A+AA+AAA+⋯+AA⋯A(N个A)。例如A=1, N=3时,S=1+11+111=123。 输入格式: 输出格式: CODE **(与阶乘计算升级版联系起来,阶乘是手算乘法,这里是手算加法)
每个输入包含一个测试用例,即正整数N (0
按递增顺序输出N的所有整数分解式子。递增顺序是指:对于两个分解序列N1={n1,n2,⋯}和N2={m1,m2,⋯},若存在i使得n1=m1,⋯,ni=mi,但是ni+1#include <stdio.h>
int n;
int a[31]; //存放拆分结果
int top = -1; //数组指针
int cnt = 0; //输出次数
int sum = 0; //拆分项累加和
void division(int i);
int main()
{
scanf("%d", &n);
division(1);
return 0;
}
void division(int i)
{
int j, k;
/*输出部分*/
if ( sum==n ){
//直到递归调用至sum==n时,才会输出
cnt++;
printf("%d=", n);
for ( j=0; j<top; j++ ){
printf("%d+", a[j]);
}
if ( cnt%4==0 || a[top]==n ){
printf("%d\n", a[top]);
}
else{
printf("%d;", a[top]);
}
}
if ( sum>n ) //输出之后,回到算法主体还会经过很多次“跳出”
return;
/*算法主体*/
for ( k=i; k<=n; k++ ){
a[++top] = k;
sum += k;
division(k);
sum -= k; //最深调用结束后才会从这里开始执行,总和还一个k
top--; //数组指针也退一位,并且下一轮k++
}
}
7-38 数列求和-加强版
输入数字A与非负整数N。
输出其N项数列之和S的值。#include <stdio.h>
int main()
{
int a, n;
int num; //每一位的a的和
int number[100001] = {
0}; //装结果的每一位数字,从个位数字开始
int t = 0; //记录进位位数
int i;
scanf("%d%d", &a, &n);
if ( n==0 ){
printf("%d", n);
}
else{
for ( i=n; i>0; i-- ){
num = a*i + t; //个位是n个a相加,十位是n-1个a相加...除了a的和,还要加上进位位数
number[n-i] = num % 10; //装每一位数字
t = num / 10; //需要进位为t
}
/*高位还需进位*/
i = n;
while(t){
number[i] = t % 10;
t /= 10;
i++;
}
for ( i=i-1; i>=0; i-- ){
printf("%d", number[i]);
}
}
return 0;
}