基础编程题目集

函数题

6-11 求自定类型元素序列的中位数(***)

本题要求实现一个函数,求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];
}

6-10 阶乘计算升级版

本题要求实现一个打印非负整数阶乘的函数。

函数接口定义

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]);
        }
    }
    
}

编程题

7-4 BCD解密(***)

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;
}

7-22 龟兔赛跑

乌龟与兔子进行赛跑,跑场是一个矩型跑道,跑道边可以随地进行休息。乌龟每分钟可以前进3米,兔子每分钟前进9米;兔子嫌乌龟跑得慢,觉得肯定能跑赢乌龟,于是,每跑10分钟回头看一下乌龟,若发现自己超过乌龟,就在路边休息,每次休息30分钟,否则继续跑10分钟;而乌龟非常努力,一直跑,不休息。假定乌龟与兔子在同一起点同一时刻开始起跑,请问T分钟后乌龟和兔子谁跑得快?

输入格式
输入在一行中给出比赛时间T(分钟)。

输出格式
在一行中输出比赛的结果:乌龟赢输出@@,兔子赢输出_,平局则输出--;后跟1空格,再输出胜利者跑完的距离。

CODE

**常见错误大赏👇
**一开始,在控制兔子休息30分钟的那个循环条件用的i<i+30,导致一旦进入循环就不会因为这个条件不满足而退出…

#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;
}

7-29 删除字符串中的子串

输入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;
}

7-32 说反话-加强版

给定一句英语,要求你编写程序,将句中所有单词的顺序颠倒输出。

输入格式
测试输入包含一个测试用例,在一行内给出总长度不超过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;
}

7-37 整数分解为若干项之和(*****)

将一个正整数N分解成几个正整数相加,可以有多种分解方法,例如7=6+1,7=5+2,7=5+1+1,…。编程求出正整数N的所有整数分解式子。

输入格式
每个输入包含一个测试用例,即正整数N (0<N≤30)。

输出格式
按递增顺序输出N的所有整数分解式子。递增顺序是指:对于两个分解序列N​1​​={n​1​​,n​2​​,⋯}和N​2​​={m​1​​,m​2​​,⋯},若存在i使得n​1​​=m​1​​,⋯,n​i​​=m​i​​,但是n​i+1​​<m​i+1​​,则N​1​​序列必定在N​2​​序列之前输出。每个式子由小到大相加,式子间用分号隔开,且每输出4个式子后换行。

CODE

**自己还搞不出来的代码>︿<

**学习的这篇(侵删)👉5-37 整数分解为若干项之和 - 文之 - 博客园

#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(1≤A≤9)以及非负整数N(0≤N≤100000),求数列之和S=A+AA+AAA+⋯+AA⋯A(N个A)。例如A=1, N=3时,S=1+11+111=123。

输入格式
输入数字A与非负整数N。

输出格式
输出其N项数列之和S的值。

CODE

**(与阶乘计算升级版联系起来,阶乘是手算乘法,这里是手算加法)

#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;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值