哈工大-C语言机试重点题目

目录

 

 

1.[编程题]字符串去特定字符

2. 字符串链接

3. 字符串内排序

4. //6.11 已知不等式1! + 2! +... + m! < n, 请编程对用户指定的n值计算,并输出满足该不等式的m的整数解

5. 百鸡问题

6. 百万富翁问题

7. 最小公倍数

8. 最大公约数GCD(greatest common divisor)

10. 互换最大最小数 

11. 判断三角形类型

二. Hash应用

三、排版问题

1. 输出梯形

2. 杨辉三角


一、字符串

1.[编程题]字符串去特定字符

链接:https://www.nowcoder.com/questionTerminal/d5d0450134db4cb994a1b323a35262da
来源:牛客网

输入字符串s和字符c,要求去掉s中所有的c字符,并输出结果。

输入描述:

测试数据有多组,每组输入字符串s和字符c。

输出描述:

对于每组输入,输出去除c字符后的结果。

示例1

输入

heallo
a

输出

hello

测试用例:

nwlrbbmqbhcdarzowkkyhiddqscdxrjmowfrxsjybldbefsarcbynecdyggxxpklorellnmpapqfwkhopkmcoqhnwnkuewhsqmgb
b

答案:

1. 注意用getchar()吸收回车;

2. 开头的while是非法输入检测, 

#include<stdio.h>
#include<string.h>
 
int main(){
    char c,str[100];
    while(scanf("%s",&str)!=EOF){   // 检测输入是否非法
        getchar();    //吸收键入的回车符号
        scanf("%c",&c);    // 需要删除的字符
        for(int i=0;i<strlen(str);i++){
            if(str[i]==c) continue;
            else printf("%c",str[i]);
        }
        printf("\n");  //输出字符串后换行
    }
    return 0;
}

2. 字符串链接

题目描述

不用strcat 函数,自己编写一个字符串链接函数MyStrcat(char dstStr[],charsrcStr[])

输入描述:

两个字符串,字符串由小写字母组成。

输出描述:

链接后的字符串

示例1

输入

复制

hello world
good morning

输出

复制

helloworld
goodmorning

答案1:数组版本

#include <stdio.h>
#include <stdlib.h>
# define N 80
void MyStrcat(char dstStr[], char srcStr[]);

int main()
{
    char dstStr[N], srcStr[N];
    scanf("%s %s", &dstStr, &srcStr);
//    dstStr = "hello";
//    srcStr = "world";
    MyStrcat(dstStr, srcStr);
    return 0;
}



void MyStrcat(char dstStr[], char srcStr[])
{
    int i = 0;
    int len1 = strlen(dstStr);
    for(;srcStr[i] != '\0'; i++){
        dstStr[len1 + i] = srcStr[i];
    }
    dstStr[len1 + i] = '\0';
    printf("%s", dstStr);
}

答案2:指针版本

#include <stdio.h>
#include <stdlib.h>
# define N 80
char* MyStrcat(char* dstStr, char* srcStr);

int main()
{
    char dstStr[N], srcStr[N];
    scanf("%s %s", &dstStr, &srcStr);
//    dstStr = "hello";
//    srcStr = "world";
    MyStrcat(dstStr, srcStr);
    return 0;
}



char* MyStrcat(char* dstStr, char* srcStr)
{
    char* pStr = dstStr;  // 首地址
    while(*dstStr != '\0')  dstStr++;
    while(*srcStr != '\0')
    {
        *dstStr = *srcStr;
        dstStr++;
        srcStr++;
    }
    *dstStr = '\0';
    printf("%s", pStr);
    return pStr;
}

3. 字符串内排序

题目描述

输入一个字符串,长度小于等于200,然后将输出按字符顺序升序排序后的字符串。

输入描述:

测试数据有多组,输入字符串。

输出描述:

对于每组输入,输出处理后的结果。

示例1

输入

复制

bacd

输出

复制

abcd

答案:冒牌排序

#include <stdio.h>
#include <stdlib.h>
# define N 200
void StrSort(char str[]);

int main()
{

    char str[N];
    scanf("%s", &str);
    StrSort(str);
    printf(str);
    return 0;

}

void StrSort(char str[])
{
    // bubble sort
    int len = strlen(str);
    char temp;
    int i,j;
    int flag;
    for(i=0; i<len-1; i++){
        flag = 0;
        for(j=len-1; j>i; j--){
            if(str[j] < str[j-1] ){   // 逆序对,交换
                temp = str[j];
                str[j] = str[j-1];
                str[j-1] = temp;
                flag = 1;    // 该轮有交换
            }
        }
        if(!flag)
            return;
    }
}

4. 实现Mystrcmp函数

首先通过指针对字符串进行比较,如“abcd”和“efddd”,比较第一个字母即刻得出大小;

对于字符串如“abcd”和“abc”,因为前三个字母a和b都相同,然后b就结束了,跳出循环。此时需要循环外的判断

 

int MyStrCmp(char a[], char b[])
{
    int i;
    for(i=0; a[i]!='\0' || b[i]!='\0'; i++)
    {
        if(a[i] > b[i])    return 1;
        else if(a[i] < b[i])    return -1;
    }
    // 循环结束,某一指针指向'\0'
    if(a[i] == b[i])    return 0;
    else if(a[i] != '0')    return 1;
    else    return -1;
}

 

 

二、其他

4. //6.11 已知不等式1! + 2! +... + m! < n, 请编程对用户指定的n值计算,并输出满足该不等式的m的整数解

答案

阶乘也有技巧, 不用创造一个Fact函数,每次在term的基础上*i即可

#include <stdio.h>
#include <stdlib.h>

int main()
{

    unsigned long i, n, term =1 ,sum = 0;
    scanf("%lu", &n);
    for(i=1;; i++){
        term *= i;
        sum += term;
        if(sum >= n )
            break;
    }
    printf("the ans is %lu\n", i-1);


    return 0;
}


5. 百鸡问题

校招时部分企业笔试将禁止编程题跳出页面,为提前适应,练习时请使用在线自测,而非本地IDE。

题目描述

    用小于等于n元去买100只鸡,大鸡5元/只,小鸡3元/只,还有1/3元每只的一种小鸡,分别记为x只,y只,z只。编程求解x,y,z所有可能解。

输入描述:

    测试数据有多组,输入n。

输出描述:

    对于每组输入,请输出x,y,z所有可行解,按照x,y,z依次增大的顺序输出。

示例1

输入

复制

40

输出

复制

x=0,y=0,z=100
x=0,y=1,z=99
x=0,y=2,z=98
x=1,y=0,z=99

答案

为了省去x+y+z=100的约束关系,故对xyz进行穷举,而仅仅在x+y+z=100时进行输出,这样写代码更快

#include <stdio.h>
#include <stdlib.h>

int main()
{
    // 穷举法
    int x, y, z, n;
    scanf("%d", &n);
    for(x=0; x<=100; x++){
        for(y=0; y<=100; y++){
            for (z=0; z<=100; z++){
                if((x+y+z==100) && 5*x+3*y+z/3.0<=n){
                    printf("x=%d,y=%d,z=%d\n", x, y, z);
                }
            }
        }
    }

    return 0;
}


6. 百万富翁问题

题目描述

一个百万富翁遇到一个陌生人,陌生人找他谈了一个换钱的计划。该计划如下:我每天给你10 万元,你第一天给我1 分钱,第二天2 分钱,
第三天4 分钱……
这样交换 30 天后,百万富翁交出了多少钱?陌生人交出了多少钱?(注意一个是万元,一个是分)

输入描述:

该题没有输入

输出描述:

输出两个整数,分别代表百万富翁交出的钱和陌生人交出的钱,富翁交出的钱以万元作单位,陌生人交出的钱以分作单位。
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int sum1=0, term=1, sum2=0,i=1;
    while(i<=30)
    {
        sum1 += term;
        term *=2;
        i++;
    }
    sum2 = 10 * 30;
    printf("%d %d", sum2, sum1);
    return 0;
}


7. 最小公倍数

输入a和b,给出a和b的最小公倍数

输入: 5 10;输出10

输入:16,24; 输出:48

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int a, b, ret, i;
    scanf("%d %d", &a, &b);
    for(i=1; i<=b; i++)
    {
        if(i*a % b == 0)
        {

           ret = i*a;
            break;
        }

    }
    printf("the ans is %d", ret);
    return 0;
}


8. 最大公约数GCD(greatest common divisor)

对于给定的a和b,最大公约数gcd具有a%gcd=0 且 b%gcd=0;

法1:穷举法。得出a和b中较小者min,从min开始依次-1,判断a%min和b%min的余数是否为0,知道min=1;

法2:欧几里得法,也成辗转相除法。对a和b连续进行求余运算,知道余数为0。此时非0的除数即是最大公约数。

通过该性质:

例子如下:123456 和 7890 的最大公因数是 6,这可由下列步骤(其中,“a mod b”是指取 a ÷ b 的余数)看出:

a

b

a mod b

123456

7890

5106

7890

5106

2784

5106

2784

2322

2784

2322

462

2322

462

12

462

12

6

12

6

0

法3:递归方法。通过如下性质:

答案1:穷举法

时空消耗:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int a, b, min, gcd;
    scanf("%d %d", &a, &b);
    min = (a>b)? b : a;

    while(min>=1)
    {
        if(a%min==0 && b%min==0)
        {
            gcd = min;
            break;
        }
        min--;
    }
    printf("%d", gcd);
    return 0;
}


答案2:辗转相除法

时空消耗:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int a, b, max, min, temp;
    scanf("%d %d", &a, &b);
    if(a>b)
    {
        max = a;
        min = b;
    }
    else
    {
        max = b;
        min = a;
    }
    while(min!=0)
    {
        temp = min;
        min = max % min;
        max = temp;
    }
    printf("%d", max);

    return 0;
}


答案3:递归法

时空消耗:

#include <stdio.h>
#include <stdlib.h>
int GcdRecurse(int a, int b);

int main()
{
    int a, b, gcd;
    scanf("%d %d", &a, &b);
    gcd = GcdRecurse(a, b);
    printf("%d", gcd);
    return 0;
}

int GcdRecurse(int a, int b)
{
    if(a==b)    return a; // 递归终止条件
    // 递归体
    if(a > b)   return GcdRecurse(a-b, b);
    else    return GcdRecurse(a, b-a);
}

9. 互换最大最小数

题目描述

输入一个数n,然后输入n个数值各不相同,调换数组中最大和最小的两个数,然后输出。

输入描述:

测试数据有多组,输入n(1<=n<=20),接着输入n个数。

输出描述:

对于每组输入,输出交换后的结果。

示例1

输入

复制

2
1 3

输出

复制

3 1

答案:

找到最大最小值对应的下标,并将二者交换

时空消耗:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int n, i, maxIn=0, minIn=0, temp;
    scanf("%d", &n);
    int A[n];
    for(i=0; i<n; i++)
    {
        scanf("%d", &A[i]);
    }
    for(i=0; i<n; i++)
    {
        if(A[i] > A[maxIn]) maxIn = i;
        if(A[i] < A[minIn]) minIn = i;
    }
    temp = A[maxIn];
    A[maxIn] = A[minIn];
    A[minIn] = temp;
    for(i=0; i<n; i++)  printf("%d ", A[i]);
    return 0;
}


 

10. 判断三角形类型

题目描述

给定三角形的三条边,a,b,c。判断该三角形类型。

输入描述:

测试数据有多组,每组输入三角形的三条边。

输出描述:

对于每组输入,输出直角三角形、锐角三角形、或是钝角三角形。

示例1

输入

复制

3 4 5

输出

复制

直角三角形

答案:

先把三角形的各条边提取max,mid,min。其中提取mid的方法比较特殊,是先计算sum,在计算max和min,接着根据mid = sum- max -min得出。否则通过比较的方法得到mid比较复杂。然后根据勾股定理判断三角形的类型

时空复杂度:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int a, b, c, max, mid, min, sum, min2, mid2, max2;
    scanf("%d %d %d", &a, &b, &c);
    sum = a+b+c;
    max = a>b?a:b;
    max = max>c? max: c;
    min = a<b? a: b;
    min = min<c? min: c;
    mid = sum - max - min;
    min2 = min*min;
    max2 = max*max;
    mid2 = mid*mid;
    if(max2 > mid2 + min2)  printf("钝角三角形");
    else if(max2 == mid2 + min2)  printf("直角三角形");
    else    printf("锐角三角形");
    return 0;
}


 

11. 找众数

题目描述

输入20个数,每个数都在1-10之间,求1-10中的众数(众数就是出现次数最多的数,如果存在一样多次数的众数,则输出权值较小的那一个)。

输入描述:

测试数据有多组,每组输入20个1-10之间的数。

输出描述:

对于每组输入,请输出1-10中的众数。

示例1

输入

复制

5 1 5 10 3 5 3 4 8 6 8 3 6 5 10 7 10 2 6 2 

输出

复制

5

答案:

用桶排序的思路来解,A[]数组长度11, 标记着1-10的数字在数组中出现的次数。长度11是为了计算方便,如5出现,使A[5]++即可;若A[]数组长度为10,则为A[5-1]++;

时空复杂度:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int A[11]={0};
    int i, n, mode=0;
    for(i=0; i<20; i++)
    {
        scanf("%d", &n);
        A[n]++;
    }
    for(i=0; i<10; i++)
    {
        if(A[i] > A[mode])  mode = i;
    }
    printf("%d", mode);
    return 0;
}


12. 素数检测

输入一个数n,判断n是否是素数

方法:因子检测法

就是从2到n-1一个个的拿来尝试,看能否整除n,如果存在能够整数n的(找到一个因子),则n不是素数,否则认为n是素数。

优化1:实际,是不需要试探到n-1的,只要的n/2即可。因为若n=a*b,设a>=b, 必然有a>=2,所以b<=n/2

优化2:只要到n的二次方根即可,原因是:设n = a * b,且a、b均为n非平凡约数,显然a > n的二次方根和b > n的二次方根不可能同时成立,因为同时成立时 a * b就会大于n,所以如果n存在非平凡约数,至少有一个小于等于n的二次方根,因此遍历时i*i<=n即可

// 优化算法1
int IsPrime(int n)
{
    int i, flag=1;
    if(n==1)    flag=0;

    for(i=2; i*i<=n; i++)     \\ 此方法比开方好
    {  
        if(n%i==0)
        {
            flag = 0;
            break;
        }
    }
    if(flag == 1)   printf("%d    ", n);
}


13 回文数检测算法

输入n,判断n是否是回文数(1<=n <=1000)

回文数:回文数(或回文数)是指一个像14641这样“对称”的数,如1,11,121,。

思路1:开辟数组a[]存储n的各个位的值,然后再对a[]头尾2 方向遍历,判断其是否左右对称。

思路2(更好):设置一个变量inv,该数是变量n的逆数;若inv和n最终相等,则是回文数;

// 思路1
int IsHuiwen1(int n)
{
    int a[4]={0};
    int len=0, p1=0, p2=0, i=0;  //数组实际长度,头尾指针
    int num=n, flag=1;    // 剩下的大小, flag
    // 提取n的各个位数
    while(num>0)
    {
        a[i] = num%10;
        num = num/10;
        i++;
    }
    len = i;
    p2 = len-1;
    // 对各个位数比较是否对称
    for(; p1<p2; p1++,p2--)
    {
        if(a[p1] != a[p2])
        {
            flag = 0;
            break;
        }
    }
    return flag;
}

// 思路2
int IsHuiwen2(int n)
{
    int num=n, inv=0;
    while(num>0)
    {
        inv = inv * 10 + (num%10);
        num = num / 10;
    }
    if(inv == n)  return 1;
    else    return 0;
}

 

 

 

二. Hash应用

1. 统计同乘积学生人数

答案:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int n, t;
    while(scanf("%d", &n) != EOF && n!=0)
    {
        int Hash[101] = {0};
        int i;
        for(i=0; i<n; i++){
            scanf("%d", &t);
            Hash[t]++;
        }
        int x;
        scanf("%d", &x);
        printf("%d\n", Hash[x]);
    }
    return 0;
}


三、排版问题

1. 输出梯形

答案

观察图像特点,“ ”和“*”的频率和高度特点

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int h, maxLen, nStar, nSpace, i, j;
    while(scanf("%d", &h) != EOF)
    {
        maxLen = h + (h-1) * 2;
        for(i=0; i<h; i++)
        {
            nStar = h + i*2;
            nSpace = maxLen - nStar;
            for(j=0; j<nSpace; j++) printf(" ");
            for(j=0; j<nStar; j++)  printf("*");
            printf("\n");
        }
    }
    return 0;
}


2. 杨辉三角

输入h行数,输出入下图所示的杨辉三角:

组合公式:

 

答案:

为二项式的展开项的系数。

注意:想要输出占4位,使用printf("%4d");

#include <stdio.h>
#include <stdlib.h>
// 阶乘公式
int Fact(int n)
{
    if(n <= 1)    return 1;
    int ret=1, i;
    for(i=2; i<=n; i++) ret *= i;
    return ret;
}

// 组合公式
int Com(int n, int m)
{
    return (Fact(n)/(Fact(m)*Fact(n-m)));
}

int main()
{
    int h, i, j;
    while(scanf("%d", &h) != EOF)
    {
        for(i=0; i<h; i++)
        {
            for(j=0; j<=i; j++)
            {
                printf("%4d ", Com(i,j));   // 输出占4位,方便对齐
            }
            printf("\n");   // 换行
        }
    }
    return 0;
}

输出:

  • 9
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值