二分查找函数
写一个二分查找函数
功能:在一个升序数组中查找指定的数值,找到了就返回下标,找不到就返回-1。
int bin_search(int arr[], int left, int right, int key) { int mid = 0; while (left <= right) { mid = (right + left) / 2; if (key<arr[mid]) { right = mid -1; } else if (key >arr[mid]) { left = mid +1; } else return -1; } }
打印乘法口诀
void Mutitable(int N) { for (int i = 1; i <= N; i++) { for (int j = i; j <= i:j++) { printf("%d*%d=%d", i, j, i * j); } printf("\n"); } }
判断闰年
实现函数判断year是不是闰年
int is_leap_year(int year) { if(((0 == year%4)&&(0!=year%100))||(0==year%400)) { return 1; } else { return 0; } }
判断素数
#include <stdio.h> #include<math.h> int is_prime(int n) { int i = 0; for (i = 2; i <= sqrt(n); i++) { if (0 == n % i) { return 0;//如果被其中一个数整除,那么结束程序 } } return 1; } int main() { int i = 0; for (i = 100; i <= 200; i++) { if (is_prime(i) == 1) { printf("%d ", i); } } return 0; }
创建一个整形数组,完成对数组的操作
- 实现函数init() 初始化数组为全0
- 实现print() 打印数组的每个元素
- 实现reverse() 函数完成数组元素的逆置。
void init(int arr[], int sz) { int i = 0; for (i = 0; i < sz; i++) { arr[i] = 0; } } void reverse(int arr[], int sz) { int left = 0; int right = sz - 1; while (left < right) { int temp = arr[left]; arr[left] = arr[right]; arr[right] = temp; left++; right--; } }
- 统计二进制中1的个数
这个题有两种方法,下面我将逐一介绍他们,并分析利弊。
方法一:思路:我们将该数据%2,如果除尽,则证明最后一位数字为0,如果未除尽,则最后一位为1。如果是1,则count++。
int Num(int n) { int count = 0; while (n) { if (n % 2 == 1) { count++; n = n / 2;//判断完毕后,将n右移一位 } } return count; }
该方法有一些缺陷:进行了大量的取模以及除法运算,取模和除法运算的效率本来就比较低。
方法二:
思路:一个int类型的数据,对应的二进制一共有32个比特位,可以采用位运算的方式一位一位的检测。
int Num(int n) { int count = 0; int i = 0; for (i = 0; i < 32; i++) { if ((n >> i) & 1 == 1) { count++; } return count; } }
优点:用位操作代替取模和除法运算,效率稍微比较高
缺陷:不论是什么数据,循环都要执行32次
方法三:
用相邻的两个数据进行按位与运算。
我们观察9999:10 0111 0000 1111按位与下一位的情况:
第一次循环:n=9999 n=n&(n-1)=9999&9998= 9998
第二次循环:n=9998 n=n&(n-1)=9998&9997= 9996
第三次循环:n=9996 n=n&(n-1)=9996&9995= 9992
第四次循环:n=9992 n=n&(n-1)=9992&9991= 9984
第五次循环:n=9984 n=n&(n-1)=9984&9983= 9728
第六次循环:n=9728 n=n&(n-1)=9728&9727= 9216
第七次循环:n=9216 n=n&(n-1)=9216&9215= 8192
第八次循环:n=8192 n=n&(n-1)=8192&8191= 0
我们可以观察到,该数按位与下一位,有几个1就可以进行几次。据此,我们可以写出代码:
int NumberOf1(int n) { int count = 0; while(n) { n = n&(n-1); count++; } return count; }
求两个数二进制中不同位的个数
1. 先将m和n进行按位异或,此时m和n相同的二进制比特位清零,不同的二进制比特位为1
2. 统计异或完成后结果的二进制比特位中有多少个1即可
int calc_diff_bit(int m, int n) { int tmp = m^n; int count = 0; while(tmp) { tmp = tmp&(tmp-1); count++; } return count; }
喝汽水问题
喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以喝多少汽水(编程实现)。
这个题目,同样有两个解法。第一种方法,让我们画图来理解:
以五瓶汽水为例子,演示一下。
当换汽水不能再执行的条件,也就是 只剩下一个空瓶子的时候。同样的,我们可以总结出来规律:empty=money;(一开始空的罐子等于花了多少钱)total=total+empty/2;(换得的饮料总数等于花的钱除以一开始花钱买的加上用空罐子换取的,empty=empty/2+empty%2;(比如说5瓶,能换2瓶喝了,剩下就是喝了的2个剩的空瓶和没法换的1个空瓶)
方法一:
#include<stdio.h> int main() { int money; scanf("%d", &money); int total = money; int empty = money; while (empty > 1) { total = total + empty / 2; empty = empty / 2 + empty % 2; } printf("%d\n", total); return 0; }
还有一个方法,就是采取等差数列的求法:
方法二:
#include<stdio.h> int main() { int money; scanf("%d", money); int total; if (money <= 0) { printf("请喝西北风"); } else { money = total * 2 - 1; } printf("%d", total); return 0; }
打印菱形
我们可以将上半部分和下半部分分开打印,首先画出总表,观察规律:
上半部分共有7行
由此可以总结出:空格个数等于line-1-i,星号个数等于 2*i+1。
再看下半部分:
星号个数为(line-1-i)*2-1,空格个数为i+1。据此我们就可以打印出此题的代码:
#include<stdio.h> int main() { int line = 7; for (int i = 0; i < line; i++)//打印上半部分 { for (int j = 0; j < line - 1 - i; j++) { printf(" "); } for (int j = 0; j < 2 * i + 1; j++) { printf("*"); } printf("\n"); } for (int i = 0; i < line - 1; i++) { for (int j = 0; j < i + 1; j++) { printf(" "); } for (int j = 0; j < (line - 1 - i) * 2-1; j++) { printf("*"); } printf("\n"); } return 0; }
打印奇数位和偶数位
打印水仙花数
求出0~100000之间的所有“水仙花数”并输出。
“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,如:153=1^3+5^3+3^3,则153是一个“水仙花数”。
要打印水仙花数,我们要知道位数,并且把要验证的每一位都取出来。
#include<stdio.h> #include<math.h> int main() { for (int i = 1; i <= 100000; i++) { int count = 0; int tmp = i; while (tmp != 0) { count++; tmp /= 10; } tmp = i; int sum = 0; while (tmp != 0) { sum += pow(tmp % 10, count); tmp /= 10; } if(i == sum) { printf("%d\n", i); } } return 0; }
求和
求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字,
例如:2+22+222+2222+22222
#include<stdio.h> #include<math.h> int main() { int n = 5; int a = 2; int tmp = 0; int sum = 0; for (int i = 0; i < n; i++) { tmp = tmp * 10 + a; sum += tmp; } printf("%d",sum); return 0; }
找只出现一次的数字
相同的数字异或都为0,0和任意数字异或都为其本身。据此,我们写出如下代码:
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int main() { int arr[] = { 1,2,3,2,1 }; int len = sizeof(arr) / sizeof(arr[0]); int sum = 0; for (int i = 0; i < len; i++) { sum ^= arr[i]; } printf("%d", sum); return 0; }
打印奇数位和偶数位
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
只要末位&1,就能知道最后一位是0还是1,如果是1,那么得到的是1,反之,则为0。
偶数位,也就是最左边的数字,应该右移31位,最后一个偶数应该右移一位,所以限制条件应当是i>=2。
#include<stdio.h> void function(int n) { for (int i = 31; i >= 1; i-=2)//偶数位 { printf("%d", (n >> i)&1); } printf("\n"); for (int i = 30; i >= 0; i -= 2)//奇数位 { printf("%d", (n >> i)&1); } printf("\n"); } int main() { function(9); return 0; }
递归
斐波那契数列
#include<stdio.h> int fabonacci(int n) { if (n <= 1) return n; else return fabonacci(n - 1) + fabonacci(n - 2); } int main() { int n = 10; printf("第%d个斐波那契数是%d", n, fabonacci(n)); return 0; }
递归实现n的k次方
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int fact(int n,int k) { if (k==1) return n; else return n*fact(n,k-1); } int main() { int n ; int k; printf("请输入n和k的值"); scanf("%d %d", &n, &k); printf("%d", fact(n, k)); return 0; }
计算一个数的每位之和(递归实现)
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int factsum(int n) { if (n<10) return n; else return n%10+factsum(n/10); } int main() { int n ; printf("请输入n"); scanf("%d", &n); printf("%d", factsum(n)); return 0; }
递归方式实现打印一个整数的每一位
#define _CRT_SECURE_NO_WARNINGS #include<stdio.h> void print(int n) { if (n < 10) { printf("%d ", n); } else { print(n/10); printf("%d ", n % 10); } } int main() { print(123); return 0; }