C語言作為嵌入式Linux開發的必備工具,作為嵌入式Linux開發的基礎語言,那么在面試嵌入式工程師時C語言定是面試中的重中之重 ,作為一名大三的老學長,不得不為找作業做必要準備,每天做一道C語言面試題,為面試打基礎,
本來還想著堅持每天一道面試題來準備找實習的,結果中間因為課設、電賽很多事情就給耽擱了發現距離上一次更新已經一個月過去了,決定重新拾起來繼續開干,
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;
}
不積小流無以成江河,不積跬步無以至千里,而我想要成為萬里羊,就必須堅持學習來獲取更多知識,用知識來改變命運,用博客見證成長,用行動證明我在努力,
如果我的博客對你有幫助、如果你喜歡我的博客內容,記得“點贊” “評論” “收藏”一鍵三連哦!聽說點贊的人運氣不會太差,每一天都會元氣滿滿呦!如果實在要白嫖的話,那祝你開心每一天,歡迎常來我博客看看,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/231478.html
標籤:其他


