总结一些常见的笔试题:
最小公约数和最大公倍数:
这个其实很简单,记住概念就可以了,我们利用辗转相除法计算:
最大公约数:(摘自百度百科)
一般地,如果求a和b的最大公约数(a>b),那么
当时,得,这里表示b整除a,而表示b不能整除,当时,设余数为,根据整除的性质,有;当时,得
,当时,设余数为,于是
最小公倍数=两数的乘积/最大公约(因)数
#include <stdio.h> void func1(int a, int b)//非递归实现 { int max, min, temp; 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); printf("最小公倍数 %d ",(a*b)/max); } int func2(int a, int b)//递归实现 { if(a == 0) return b; else if(b == 0) return a; int max, min; if(a > b) {max = a; min = b;} else {max = b; min = a;} max = func2(min, max%min); return max; } void main() { int x , y, ret; printf("please input two num: "); scanf("%d %d",&x, &y); func1(x,y); ret = func2(x,y); printf("最大公约数 %d ",ret); printf("最小公倍数 %d ",(x*y)/ret); }
2.字符串翻转问题
这个太简单了,就不多说了
#include <stdio.h> #include <string.h> void turn(char *s) { int len = strlen(s), mid = len/2, i = 0; while(i < mid)//此处不能相等 { char temp = s[len-1-i]; s[len-1-i] = s[i]; s[i] = temp; i++; } } int main() { printf("please input a string "); char s[20]; gets(s); turn(s); printf("after turn, the string is:%s ", s); return 0; }
3.判断小端还是大端
使用联合体,取低字节
int main() { union{ int x; char c; }u; u.x = 1; if(u.c == 1) printf("little endian "); else printf("big endian "); return 0; }
4.给定一个字符串,翻转一些位数
例如:给定abcdefg,翻转后变为:efgabcd,这个也不难,先全部翻转过来,再翻转一定的位数,再把这些位数后面的翻转
#include <stdio.h> #include <string.h> void turn(char *s, int n) { int len = n, mid = len/2, i = 0; while(i < mid) { char temp = s[len-1-i]; s[len-1-i] = s[i]; s[i] = temp; i++; } } int main() { char s[] = "abcdefg"; turn(s, strlen(s)); printf("after turn: %s ",s); turn(s, 3); printf("after turn: %s ",s); turn(s+3,strlen(s)-3); printf("after turn: %s ",s); return 0; }
5.两个线程交替输出1-10个数
考察线程的基本知识,要能写出来
#include <pthread.h> #include <stdio.h> struct X { int data; pthread_mutex_t lock; }x = {10,PTHREAD_MUTEX_INITIALIZER}; void *func1(void *arg) { pthread_mutex_lock(&x.lock); while(x.data >= 1) { printf("int the thread1: %d ",x.data); x.data--; sleep(1); } pthread_mutex_unlock(&x.lock); } void *func2(void *arg) { pthread_mutex_lock(&x.lock); while(x.data >= 1) { printf("int the thread2: %d ",x.data); x.data--; sleep(1); } pthread_mutex_unlock(&x.lock); } void main() { pthread_t ptid[2]; int *ret, j; pthread_create(&ptid[0], NULL, func1, NULL); pthread_create(&ptid[1], NULL, func2, NULL); for(j = 0; j < 2; j++) pthread_join(ptid[j], (void**)&ret);//等待线程的退出 }
注意头文件<pthread.h>和编译链接项 -pthread
6.宏定义交换两个数
有多种写法
#include <stdio.h> #define SWAP(x, y) (x = x+y, y = x-y, x = x-y) #define swap(x, y) (x = x^y, y = x^y, x = x^y)//不会产生大数字溢出问题 //带有换行的 #define Swap(x, y) x = x+y; y = x-y; x = x-y void main() { int x = 3, y = 5; //SWAP(x, y); //Swap(x, y); swap(x ,y); printf("x:%d y:%d ",x, y); }
7.全排列的实现
全排列是一个比较复杂的算法,例如“123”的全排列,我们可以枚举出来是123,132,231,213,321,312,我们发现,每一个数都会排在开头,那么这是不是递归的思想,
我们把每一个数放到开头,剩下的数再全排列一下,这样就是拿出1,全排列23,拿出2,全排列13,拿出3,全排列12,这样一分析就简单了
但是有一个问题,例如:如果有这样的数:1223那怎么办呢?我们这样想,在把第2个2拿到第一个位置的时候,我们发现这个2前面已经有个2了,这样就重复了呀,
怎么办呢?(好多2啊-_-!),这里我们就不把第二个2拿到第一个位置就是了,我们写了一个 is_swap函数在每次把数拿到第一个位置的时候判断了一下
#include <stdio.h> #include <string.h> void swap(char *s, char *t) { char temp = *s; *s = *t; *t = temp; } int is_swap(char *s, int begin, int end) { int i; for(i = begin; i < end; i++) { if(s[i] == s[end]) return 0; } return 1; } void all_rang(char *s, int m, int n) { int i, j; if(m == n) { static int i = 1; printf("第%d个全排列是:%s ", i++, s); return; } for(j = m; j <= n; j++) { if(is_swap(s, m, j)) { swap(s+m,s+j); all_rang(s, m+1, n); swap(s+m, s+j); } } } void main() { char s[10] = "1223"; all_rang(s, 0, strlen(s)-1); }
关于二维数组的总结:
#include <stdio.h> void main() { int a[4][4] = { {1,2,3,4}, {50,60,70,80}, {900,1000,1100,1200}, {13000,14000,15000,16000} }; int (*p1)[4] = a; int (*p2)[4] = &a[0]; int (*p3)[4] = &a[0][0]; printf("%d %d ",*(*p1+7), *(*(p2+1)-4));//这里是这种写法 int *p6 = a; int *p5 = &a[0]; int *p4 = &a[0][0]; printf("%d ",*(p4+7));//这里是这种写法 //int *(p7)[4][4] = a; //int *(p8)[4][4] = &a[0]; //int *(p9)[4][4] = &a[0][0]; //printf("%d ",*(p7+7)); }
这个在笔试中常考,记住只有两种写法,并且指针的运算在这两种写法上的区别