C语言每日一题(四)

       C语言作为嵌入式Linux开发的必备工具,作为嵌入式Linux开发的基础语言,那么在面试嵌入式工程师时C语言定是面试中的重中之重 。作为一名大三的老学长,不得不为找工作做必要准备。每天做一道C语言面试题,为面试打基础。
Alt

       本来还想着坚持每天一道面试题来准备找实习的,结果中间因为课设、电赛很多事情就给耽搁了发现距离上一次更新已经一个月过去了,决定重新拾起来继续开干。

2020.11.17

题目描述:
       如果统计的个数相同,则按照ASCII码由小到大排序输出 。如果有其他字符,则对这些字符不用进行统计。

实现以下接口:
       输入一个字符串,对字符中的各个英文字符,数字,空格进行统计(可反复调用),按照统计个数由多到少输出统计结果,如果统计的个数相同,则按照ASCII码由小到大排序输出,清空目前的统计结果,重新统计,调用者会保证:输入的字符串以‘\0’结尾。

输入描述:
       输入一串字符。

输出描述:
       对字符中的各个英文字符(大小写分开统计),数字,空格进行统计,并按照统计个数由多到少输出,如果统计的个数相同,则按照ASII码由小到大排序输出 。如果有其他字符,则对这些字符不用进行统计。

示例1
输入:
aadddccddc
输出:
dca

题目解析:

#include<stdio.h>
#include<string.h>
#define ASC_SIZE 128
int main() 
{     
    char str[1000]; 
    int i,len;   
    while(gets(str))   
    {         
        int count[ASC_SIZE]={0};   
        int max = 0;      
        len = strlen(str);    
        for(i=0;i<len;i++)        
        {            
            count[str[i]]++;   
            if(count[str[i]] > max)   
                max = count[str[i]];  
        }         
        while(max)      
        {             
            for(i=0;i<ASC_SIZE;i++)  
            {                 
                if(count[i] == max)   
                    printf("%c",i);         
            }             max--;     
        }   
        printf("\n");     
    }   
    return 0;  
}

       当我见到题目的时候我也是比较懵逼的,没有想到比较好的解题方案,然后偷偷的打开了通过的代码,看到了高赞的代码。通过分析别人的代码发现了解题思路。这道题的思想类似于桶排序的思想,定义了一个拥有ASCII码长度的数组(count[ASC_SIZE])并且初始化为0,然后对输入的字符串进行检索。当遇到对应的字符时,对应下标为该字符的count['字符']值加一,因为要按照字符个数从多到少的输出那么就可以定义一个max变量用于统计出现次数最多的字符。
       输出时,因为是要先输出出现次数最多的字符,如果次数相同则按照ASCII码的值从小到大进行输出。因此优先级最高的是max,遍历count数组输出对应的下标就是出现次数最多的字符,当然如果出现次数相同该怎么办呢?这就是这道题采用桶排序的巧妙之处,因为是采用桶排序的,下标按照从小到大存储的,我们就不需要对其进行排序,我们要做的只用关心这个地方的值是几就可以啦!当字符出现次数相同时,我们只需要将满足条件的下标给按照顺序输出就可以。

2020.11.18

题目描述

有ABC三组,每组10名队员,求出ABC三组中成绩最高的前五名成绩并输出。

A={65,85,65,75,78,41,89,99,98,96};
B={65,85,65,75,78,41,89,99,91,92};
C={65,85,65,75,78,41,89,97,98,90};

输出描述:

A:99 98
B:99
C:98 97

题目解析:

#include<stdio.h>
#include<string.h>
#define ASC_SIZE 128
struct Data
{
    int num_data;
    char num_sub;
}data[30];

int sort(struct Data src[])
{
    int x,y;
    struct Data tem;
    for(x=0;x<5;x++)
    {
        for(y=x+1;y<30;y++)
        {
            if(src[y].num_data>src[x].num_data)
            {
                tem=src[x];
                src[x]=src[y];
                src[y]=tem;
            }
        }
    }
    return 0;
}
int main() 
{     
    int i;
    int A[10]={65,85,65,75,78,41,89,99,98,96};
    int B[10]={65,85,65,75,78,41,89,99,91,92};
    int C[10]={65,85,65,75,78,41,89,97,98,90};
    for(i=0;i<10;i++)
    {
        data[i].num_data=A[i];
        data[i].num_sub='A';
    }
    for(i=10;i<20;i++)
    {
        data[i].num_data=B[i-10];
        data[i].num_sub='B';
    }
    for(i=20;i<30;i++)
    {
        data[i].num_data=C[i-20];
        data[i].num_sub='C';
    }
    sort(data);
    printf("A:");
    for(i=0;i<5;i++){
        if(data[i].num_sub=='A')
            printf("%d ",data[i].num_data); 
    }
    printf("\nB:");
    for(i=0;i<5;i++){
        if(data[i].num_sub=='B')
            printf("%d ",data[i].num_data); 
    }
    printf("\nC:");
    for(i=0;i<5;i++){
        if(data[i].num_sub=='C')
            printf("%d ",data[i].num_data); 
    }   
    return 0;  
} 

       这道题目当时拿到题目的第一瞬间就是想用比较暴力的方法,把三个数组给合成一个数组,然后再对这个合成的数组进行排序输出前5个同学的成绩,但是看到题目的输出格式以后发现还要分组输出相关的信息,这个我用了一个比较复杂的方法就是结构体数组,结构体变量中存放了两个变量:一个是数组对应的值num_data,另一个是对应的分组num_sub,然后根据num_data来对结构体数组进行排序。因为只需要输出前5名学生的信息,采用冒泡排序外层循环只需要循环5次。然后就可以按照指定格式输出相关的信息了。
       这道题肯定还有更好更优秀的方案能够降低时间复杂度和空间复杂度的方法,但是博主能力有限目前只想到了这一种方法。希望有那位大神看到这篇文章的时候可以在评论区分享更好的方法和思路。

2020.11.23

题目描述:
       解密QQ号,题目是啊哈算法中队列篇中的。解密规则:首先将第 1 个数删除,紧接着将第 2 个数放到这串数的末尾,再将第 3 个数删除并将第 4 个数放到这串数的末尾,再将第 5 个数删除……直到剩下最后一个数,将最后一个数也删除。按照刚才删除的顺序,把这些删除的数连在一起就是小哈的 QQ 啦!
       本题目旨在理解队列的基本操作以及简单应用,队列是一种特殊的线性结构,它只允许在队列的首部( head)进行删除操作,这称为“出队”,而在队列的尾部( tail)进行插入操作,这称为“入队”。当队列中没有元素时(即 head==tail),称为空队列。队列是广度优先搜索以及队列优化的Bellman-Ford 最短路算法的核心数据结构,队列的三个基本元素是:一个数组,两个变量

题目解析:

#include <stdio.h>
struct queue
{
    int data[100];
    int head;
    int tail;
};
int main()
{
    struct queue q;
    int i;
    q.head=1;
    q.tail=1;
    for(i=0;i<9;i++)
    {
        scanf("%d",&q.data[q.tail]);
        q.tail++;
    }
    while(q.head<q.tail)//当队列不为空的时候执行循环
    {
        printf("%d ",q.data[q.head]); //打印队首位置
        q.head++;

        //将新队首的数添加到队位
        q.data[q.tail]=q.data[q.head];
        q.tail++;
        q.head++;
    }
    printf("\n%d %d",q.head,q.tail);
    getchar();
    return 0;
}

       将引入两个整型变量 head 和 tail。 head 用来记录队列的队首(即第一位),tail 用来记录队列的队尾(即最后一位)的下一个位置。你可能会问:为什么 tail 不直接记录队尾,却要记录队尾的下一个位置呢?这是因为当队列中只剩下一个元素时,队首和队尾重合会带来一些麻烦。我们这里规定队首和队尾重合时,队列为空。
       现在有 9 个数, 9 个数全部放入队列之后 head=1;tail=10;此时 head 和 tail 之间的数就是
目前队列中“有效”的数。如果要删除一个数的话,就将 head++就 OK 了,这样仍然可以保持 head 和 tail 之间的数为目前队列中“有效”的数。这样做虽然浪费了一个空间,却节省了大量的时间,这是非常划算的。新增加一个数也很简单,把需要增加的数放到队尾即 q[tail]之后再 tail++就 OK 啦。

2020.11.24

题目描述:
       "xyzyx"是一个回文字符串,所谓的回文字符串就是指正读反读均相同的字符串序列,如“席主席”、“记书记”、“ahaha”均是回文字,通过栈这个数据结构很容易判断一个字符串是否为回文字符串,请输入一个字符串,判断这个字符串是否为回文字符串。

输入描述: 输入一个字符串

输出描述: 如果是回文字符串输出YES,不是回文字符串则返回NO。

示例:
输入:ahaha
输出:YES

题目解析:

#include <stdio.h>
#include <string.h>
int main()
{
    char a[101],s[101];
    int i=0,len,mid,next,top;
    gets(a);
    len=strlen(a);
    mid=len/2-1;
    top=0;//栈初始化
    for(i=0;i<=mid;i++)
    {
        s[++top]=a[i];
    }
    if(len%2==0)
        next=mid+2;
    else
    {
        next=mid+1;
    }
    for(i=next;i<len;i++)
    {
        if(a[i]!=s[top])
            break;
        top--;
    }
    if(top==0)
        printf("YES\n");
    else
    {
        printf("NO\n");
    }
    
}

2020.11.25

题目描述:

       快速找到未知长度单链表的中间节点。

题目解析:
       这是一道比较经典的面试题,普通方法很简单,就是遍历一遍单链表以确定单链表的长度L,然后再从头节点出发循环L/2次到中间节点。算法复杂度为O(3L/2)。
       利用快慢指针原理,设置两个指针search和 mid分别指向链表的头节点。其中search的移动速度是mid移动速度的两倍,当*search指向末尾节点的时候,mid刚好在中间了。

Status GetMidNode(LinkList L,ElemType *e)
{
    LinkList search,mid;
    mid=serch=L;
    while(serch->next!=NULL)
    {
        if(search->next->next!=NULL)
        {
            search=search->next->next;
            mid=search->next;
        }
        else
        {
            search=search->next;
        }
        
    }
    *e=mid->data;
    return OK;
}

2020.11.26

       题目描述: 如何判断一个链表是否为环?

       题目解析: 判断一个链表是否为环,可能第一个想到的方法就是判断链表的最后一个节点是否与首节点相等,但是实际上这种方法是有局限性的。当遇到6字型的环形链表时,就可能会出现误判的情况,如果程序设计的不合理还很有可能陷入一个死循环。那么我们我们可以使用快慢指针法:就是让两个指针同时指向链表。在向后遍历的时候,一个指针每次走两步,称为快指针;一个指针每次走一步,称为慢指针。如果快慢指针相遇,则说明链表有环,否则无环。

int testLink(Link *head)
{
	Link *t1 = head, *t2 = head;
	while(t1->next && t2->next)
	{
		t1 = t1->next;
		if (NULL == (t2 = t2->next->next))
			return 0; //无环
		if (t1 == t2)
			return 1;
	}
	return 0;
}

2020.11.27

题目描述: 创建一个链表,并将链表逆置。

题目解析:

       创建一个链表如下:
在这里插入图片描述
       我们要将链表逆置,需要先定义两个结构体类型的指针变量*p (用于记录原链表的节点对应的data值)和 q(用于记录新链表头插的值),定义好节点以后将p指向data1,q指向p用来记录原链表和需要新插入的值,同时让原链表的头节点指向NULL。相当于重新建立一个链表。
在这里插入图片描述
       当准备工作完成后就是重头戏了,通过一个while循环判断p节点所指向的下一个位置如果不为空,那么就将当前p节点的值赋值给q节点,赋值给q节点后,让q节点的下一个节点指向头结点的下一个节点,然后让头节点指向q节点。
在这里插入图片描述
       通过以上步骤我们就完成了第一个节点头插入到新的链表中,完成后p向后移动一个节点继续重复以上步骤,就可以完成一个链表的逆置了。其代码核心就是将原链表头结点后面的节点顺序头插入到新的链表中。

#include<stdio.h>
#include<malloc.h>
typedef struct node
{
    int data;
    struct node*next;
 }node;
 node*creat()
 {
    node*head,*p,*q;
    char ch;
    head=(node*)malloc(sizeof(node));
    q=head;
    ch='*';
    puts("单链表尾插法,?结束");
    while(ch!='?')
    {
        int a; 
        scanf("%d",&a);
        p=(node*)malloc(sizeof(node));
        p->data=a;
        q->next=p;
        q=p;
        ch=getchar();
     }
     q->next=NULL;
     return(head);
 }
 void print(node*a)
 {
    puts("print ");
    a=a->next;
    while(a!=NULL)
    {
        printf("%d ",a->data);
        a=a->next;
     }
  }
 void reverse(node*head)
{
    node*p,*q;
    p=head->next;
    head->next=NULL;
    while(p)
    {
        q=p;
        p=p->next;
        q->next=head->next;
        head->next=q;
    }
} 
 main()
 {
    node*a;
    a=creat();
    print(a);
    reverse(a);
    puts("\nhaved reversed:"); 
    print(a);
     return 0;
 }

2020.11.28

题目描述:
       使用递归将一个字符串进行翻转。
输入描述:
       输入一个字符串。
示例:

输入:hello world !
输出:! dlrow olleh

题目解析:
       通过定义一个str_reverse(char *p1,char *p2)函数,传入的参数分别为字符串的首地址和尾地址。如果需要交换的字符的首地址和尾地址重合那么就结束当前函数,如果不重合就进行交换。这里并没有定义一个中间变量来进行交换两个变量,而是通过数学运算得到的(交换a,b:a=a+b;b=a-b;a=a-b;)。交换完成后判断是否为最后两个交换的数,如果是最后两个交换的数那么就结束当前的递归函数。

#include<stdio.h>
#include<string.h>
//#define SPACE ' '
//#define ENDL '\0'
void str_reverse(char *p1,char *p2)
{
    if(p1==p2) return;//如果需要交换的只有一个字符
    *p1=(*p1)+(*p2);
    *p2=(*p1)-(*p2);
    *p1=(*p1)-(*p2);
    if(p1==p2-1)return;//交换后判断是否是最后两个交换的,如果是则结束程序避免再交换
    else str_reverse(++p1,--p2);
}
int main()
{
    char str1[100];
    int len;
    gets(str1);
    len=strlen(str1);
    str_reverse(str1,str1+len-1);
    puts(str1);
    return 0;
}

2020.11.30

       交换两个参数的宏定义为:#define SWAP(A,B) (A)=(A)+(B);(B)=(A)-(B);(A)=(A)-(B);

2020.12.01

题目描述:
       写一个函数实现将内存中的字符串进行翻转。
输入描述:
       输入一个字符串。
示例:

输入:The quick brown fox jumps over the lazy dog

输出:dog lazy the over jumps fox brown quick The

题目解析:
       这道题目比较方便的解法就是分为两大步骤,第一步:将输入的字符串进行整体的翻转;第二步:将整体翻转后的字符串对应的单词进行翻转。

#include<stdio.h>
#include<string.h>
#define SPACE ' '
#define ENDL '\0'
void str_reverse(char *p1,char *p2)
{
    if(p1==p2) return;//如果需要交换的只有一个字符
    *p1=(*p1)+(*p2);
    *p2=(*p1)-(*p2);
    *p1=(*p1)-(*p2);
    if(p1==p2-1)return;
    else str_reverse(++p1,--p2);
}
void word_reverse(char *str)
{
    //q2用来记录需要交换的单词的尾地址
    char *q1=str,*q2=str,*t;//q1用来记录字符串中,需要交换单词的起始地址。
    while(*q1==SPACE)q1++;
    if(*q1==ENDL)return;//如果结束标志则结束函数
    else q2=q1+1;
    while((*q2!=SPACE)&&(*q2!=ENDL))q2++;
    t=q2--;//t用来记录下一个单词的起始地址
    str_reverse(q1,q2);//交换这个单词的顺序
    if(*t==ENDL)return;//交换后判断是否结束
    else word_reverse(t);
}
int main()
{
    char str1[100];
    int len;
    gets(str1);
    len=strlen(str1);
    str_reverse(str1,str1+len-1);
    puts(str1);
    word_reverse(str1);
    puts(str1);
    return 0;
}

       不积小流无以成江河,不积跬步无以至千里。而我想要成为万里羊,就必须坚持学习来获取更多知识,用知识来改变命运,用博客见证成长,用行动证明我在努力。
       如果我的博客对你有帮助、如果你喜欢我的博客内容,记得“点赞” “评论” “收藏”一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
在这里插入图片描述

本文件中讲述了c语言经典的282个案例,由浅入深。有利于提高广大爱好c语言编程的人员。 其中包括: 第1章 初识C语言 1 实例001 第一个C语言程序 2 实例002 一个完整的C语言程序 2 实例003 输出名言 3 实例004 用TC 2.0打开文件 4 实例005 计算正方形的周长 5 第2章 简单的C程序 6 实例006 输出一个正方形 7 实例007 输出一个三角形 8 实例008 一个简单的求和程序 9 实例009 求10! 10 实例010 3个数由小到大排序 11 实例011 猴子吃桃 13 实例012 阳阳买苹果 14 第3章 算法入门 15 实例013 任意次方后的最后三位 16 实例014 计算某日是该年的第几天 16 实例015 婚礼上的谎言 18 实例016 百元买百鸡 19 实例017 打渔晒网问 20 实例018 判断三角形的类型 22 实例019 直接插入排序 23 实例020 希尔排序 25 实例021 冒泡排序 26 实例022 快速排序 27 实例023 选择排序 28 实例024 归并排序 29 实例025 二分查找 31 实例026 分块查找 32 实例027 哈希查找 34 实例028 斐波那契数列 37 实例029 哥德巴赫猜想 38 实例030 尼科彻斯定理 39 第4章 常用数据类型 41 实例031 数值型常量的使用 42 实例032 字符型变量的使用 42 实例033 求100~200之间的素数 43 实例034 利用#输出三角形 44 实例035 十进制转换为二进制 45 实例036 n进制转换为十进制 46 实例037 小球下落问 48 实例038 巧分苹果 49 实例039 老师分糖果 50 实例040 IP地址形式输出 51 实例041 特殊的完全平方数 52 实例042 一数三平方 54 实例043 求等差数列 55 实例044 亲密数 56 实例045 自守数 57 第5章 运算符与表达式 60 实例046 求二元一次不定方程 61 实例047 可逆素数 63 实例048 判断闰年 64 实例049 黑纸与白纸 65 实例050 阿姆斯特朗数 67 实例051 最大公约数和最小公倍数 67 实例052 求一元二次方程的根 69 实例053 自然对数的底e的计算 70 实例054 满足abcd=(ab+cd)2的数 70 实例055 整数加减法练习 71 实例056 判断整倍数 73 实例057 阶梯问 73 实例058 乘积大于和的数 74 实例059 求各位数之和为5的数 75 第6章 数据输入与输出函数 77 实例060 使用字符函数输入/输出字符 78 实例061 输出相对的最小整数 79 实例062 将小写字母转换为大写字母 80 实例063 水池注水问 80 实例064 用*号输出图案 81 实例065 输出一个字符的前驱字符 82 实例066 求学生总成绩和平均成绩 83 实例067 回文素数 84 第7章 选择和分支结构程序设计 86 实例068 判断偶数 87 实例069 判断字母是否为大写 88 实例070 检查字符类型 89 实例071 求最低分和最高分 90 实例072 模拟自动售货机 91 实例073 计算工资 93 实例074 平方和值判断 94 实例075 加油站加油 95 实例076 简单计算器 97 第8章 循环结构 98 实例077 使用while语句求n! 99 实例078 使用while为用户提供 菜单显示 100 实例079 一元钱的兑换方案 102 实例080 特殊等式 103 实例081 打印乘法口诀表 104 实例082 平方和运算的问 105 实例083 求从键盘中输入字符的个数 106 实例084 打印杨辉三角 108 实例085 求总数问 109 实例086 彩球问 110 实例087 新同学年龄 112 实例088 灯塔数量 113 实例089 计算12+22+…+102 114 实例090 循环显示随机数 115 实例091 卖西瓜 116 实例092 银行存款问 117 实例093 统计不及格的人数 118 实例094 猜数字游戏 119 第9章 数组 123 实例095 求各元素之和 124 实例096 使用二维数组保存数据 125 实例097 计算字符串中有多少个单词 126 实例098 不使用strcpy()函数实现 字符串复制功能 127 实例099 逆序存放数据 1
相关推荐
©️2020 CSDN 皮肤主题: 撸撸猫 设计师:马嘣嘣 返回首页