1.递归打印一个数的每一位
思想:首先要确保每个数>9 才可以进行下一步操作
我们先定义一个变量存放 n%10 再进行递归下一步 最后进行打印
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
prin(int n)
{
if (n == 0)
return ;
int bbb = n % 10;
prin(n / 10);
printf("%d", bbb);
}
int main()
{
int num = 12345;
prin(num);
printf("\n");
return 0;
2.递归和非递归分别实现求n的阶乘(不考虑溢出的问题)
1.非递归 采用循环即可
注意:我们在定义函数类型时,由于阶乘较大 我们采用long long整形
long long Fac(int N)
{
long long ret = 1;
for(int i = 2; i <= N; ++i)
{
ret *= i;
}
return ret;
}
2. 递归 首先进行判断是否大于1 后进行递归 return Fac(N-1)*N
Fac(N)
Fac(N-1)*N N >= 2
*/
long long Fac(int N)
{
if(N <= 1)
return 1;
return Fac(N-1)*N;
}
3.递归和非递归分别实现strlen
strlen的含义是:求字符串中有效字符的长度,不包括\0。以下是循环实现
int my_strlen(cahr* str)
{
int count = 0;
while('\0' != *str)
{
count++;
str++
}
return count;
}
递归实现
int my_strlen(char *str)
{
if('\0' == *str)
return 0;
else
return 1+my_strlen(1+str);
}
4.字符串逆序(递归实现)
思想:逆置字符串方法很简单 先给两个指针 分别指向首元素地址和末尾元素地址 交换两个指针上的字符 left指针向前走 right指针向右走 相遇后 逆置结束
void reverse_string(char* string)
{
char* left = arr;
char* right = arr+strlen(arr)+1;
while(left<right)
{
char tmp = *left;
*left = * right;
*right = tmp;
left++;
right--;
}
}
递归方式: 对于字符串“abcdefg”,递归实现的大概原理: 1. 交换a和g, 2. 以递归的方式逆置源字符串的剩余部分,剩余部分可以看成一个有效的字符串,再以类似的方式逆置
void reverse_string(char* arr)
{
int len = strlen(arr);
char tmp = *arr;
*arr = *(arr+len-1);
*(arr+len-1) = '\0';
if(strlen(arr+1)>=2)
reverse_string(arr+1);
*(arr+len-1) = tmp;
}
5.计算一个数的每位之和(递归实现)
思路: n n < 10 DigiSum(n) = DibiSum(n/10)+n%10 // 前n-1位之和+第N位
int DigitSum(int n)//1729
{
if(n>9)
return DigitSum(n/10)+n%10;
else
return n;
}
6.递归实现n的k次方
思想: 如果为0 任何数的0次方==1 如果为整数 n的k次方等于n*n的(k-1)ci方进行递归
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
double power(double n, int k) {
if (k == 0) {
// 任何数的0次方都等于1
return 1.0;
}
else if (k > 0) {
// 如果k为正数,n的k次方等于n乘以n的(k-1)次方
return n * power(n, k - 1);
}
else {
// 如果k为负数,n的k次方等于1除以n的-k次方
return 1.0 / (n * power(n, -k - 1));
}
}
int main() {
double n;
int k;
printf("请输入底数n:");
scanf("%lf", &n);
printf("请输入指数k:");
scanf("%d", &k);
double result = power(n, k);
printf("%.2lf 的 %d 次方结果是 %.2lf\n", n, k, result);
return 0;
}
7.计算斐波那契数
long long Fac(int N)
{
if(N < 3)
return 1;
return Fac(N-1) + Fac(N-2);
}
8.求两个数二进制中不同位的个数
编程实现:两个int(32位)整数m和n的二进制表达中,有多少个位(bit)不同?
输入例子:
1999 2299
输出例子:7
思想:首先有32个比特位 我们可以利用for循环进行遍历 将m向右移动一步和1进行按位与(&)
因为1的二进制是 00000000000000000000000000000001
m每向右移动一次和1进行按位与 有0则0 此时我们将n也进行右移按位与
如果m和n按位与后的结果不同 哦我们就创建一个变量统计数据
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int ocunt_diff(int m, int n)
{
int count = 0;
int i = 0;
for (i=0; i < 32; i++)
{
if (((m >> i) & 1) !=( (n >> i) & 1))
count++;
}
return count;
}
int main()
{
int m = 0;
int n = 0;
scanf("%d %d", &m, &n);
int ret = ocunt_diff(m, n);
printf("%d\n", ret);
return 0;
}
9.获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列
思路: 1. 提取所有的奇数位,如果该位是1,输出1,是0则输出0 2. 以同样的方式提取偶数位置 检测num中某一位是0还是1的方式: 1. 将num向右移动i位 2. 将移完位之后的结果与1按位与,如果: 结果是0,则第i个比特位是0 结果是非0,则第i个比特位是1
void Printbit(int num)
{
for(int i=31; i>=1; i-=2)
{
printf("%d ", (num>>i)&1);
}
printf("\n");
for(int i=30; i>=0; i-=2)
{
printf("%d ", (num>>i)&1);
}
printf("\n");
}
10.统计二进制中1的个数
方法一: 思路: 循环进行以下操作,直到n被缩减为0: 1. 用该数据模2,检测其是否能够被2整除 2. 可以:则该数据对应二进制比特位的最低位一定是0,否则是1,如果是1给计数加1 3. 如果n不等于0时,继续1
int NumberOf1(int n)
{
int count = 0;
while(n)
{
if(n%2==1)
count++;
n = n/2;
}
return count;
}
上述方法缺陷:进行了大量的取模以及除法运算,取模和除法运算的效率本来就比较低。 方法二思路: 一个int类型的数据,对应的二进制一共有32个比特位,可以采用位运算的方式一位一位的检测,具体如下
int NumberOf1(unsigned 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;
}