C语言学习记录—作业6

1. ++操作符判断

int main()
{
	int a, b, c;
	a = 5;
	c = ++a;//a=6 c=6
	b = ++c, c++, ++a, a++;
	//       c=8       a=8  运算后各变量的值
	//  c=7  c=7  a=7  a=7  运算时的值
	b += a++ + c;
    //   a=9   运算后各变量的值
	//   a=8   运算时的值
	printf("a = %d b = %d c = %d\n:", a, b, c);
	return 0;
}

2. 统计二进制中1的个数

思路:让这个数与1按位与。如果最后一位是0,那么按位与的结果就是0,反之是1,结果就是1。

然后把这个数向右移动一位,直到遍历完所有位。

int main()
{
	int n = 3;
	int count = 0;
	int i = 0;

	for (i = 0; i < 32; i++)
	{
		if ((n & 1) == 1)
		{
			count++;
		}			
		n >>= 1;
	}
	printf("%d\n", count);
	return 0;
}

3. 打印整数二进制的奇数位和偶数位
获取一个整数二进制序列中所有的偶数位和奇数位,分别打印出二进制序列

思路:同上方类似,也是用给定数按位与1就可以得到每一位,只是要注意移动n移动的位数。

自己方法
int main()
{
    //偶数位
	int n = 2863311530;
	int i = 0;
	for (i = 0; i < 16; i++)
	{
        printf("%d ", n & 1);
		n >>= 2;
	}
	printf("\n");

    //奇数位
	n >>= 1;
	for (i = 0; i < 16; i++)
	{
		printf("%d ", n & 1);
		n >>= 2;
	}
	return 0;
}

老师方法
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)//整数的最高位是符号位,而不是奇偶位。所以循环从30开始
	{
		printf("%d ", (num >> i) & 1);
	}
	printf("\n");
}

4. 求两个数二进制中不同位的个数

思路:也是通过将最后一位与1按位与,再将这两个数向右移动一位,直到遍历完每一位再比较。

int main()
{
	int n = 1;
	int m = 2;
	
	int count = 0;
	int i = 0;

	for (i = 0; i < 32; i++)
	{
		if ((n & 1) != (m & 1))
			count++;
		n >>= 1;
		m >>= 1;
	}
	printf("%d\n", count);
	return 0;
}

5. 小乐乐上课需要走n阶台阶,因为他腿比较长,所以每次可以选择走一阶或者走两阶,那么他一共有多少种走法?

思路1:
假设n=10,fib(n)表示n个台阶的走法。
如果第一步走1个台阶,那么还剩9个台阶,剩余台阶走法是fib(9)
如果第一步走2个台阶,那么还剩8个台阶,剩余台阶走法是fib(8)

思路2:
假设台阶有5级
  n      跳法
  1        1
  2        2
  3        3
  4        5
  5        8
如果青蛙站在第1级台阶,那么剩下的4级台阶总共有5种跳法
如果青蛙站在第2级台阶,那么剩下的3级台阶总共有3种跳法
所以5级台阶的跳法:3级台阶的跳法+4级台阶跳法(3+5=8)
也就是当n<=2时,有几级台阶就只有几种跳法
当n>2时,跳法总共有:(n-1)+(n-2)
每次求n时,都是青蛙站在第1级,或第2级作为起点(动态规划:用上一步的结果,来计算下一步的结果)

int fib(int n)
{
	if (n <= 2)
		return n;
	else 
		return fib(n - 1) + fib(n - 2);
}
int main()
{
	int n = 0;
	scanf("%d", &n);

	int m = fib(n);
	printf("%d\n", m);
}

6. 有一个整数序列(可能有重复的整数),现删除指定的某一个整数,输出删除指定数字之后的序列,序列中未被删除数字的前后位置没有发生改变。

输入描述:
第一行输入一个整数(0≤N≤50)。
第二行输入N个整数,输入用空格分隔的N个整数。
第三行输入想要进行删除的一个整数。
输出描述:
输出为一行,删除指定数字之后的序列。

自己方法的思路:遍历数组,如果要删除的数和数组某个数相等则不打印
int main() {
    int n = 0;//有几个数
    scanf("%d\n", &n);

    int i = 0;
    int arr[n];//牛客网支持变长数组
    //接收n个数字
    for (i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }

    int b = 0;//要删除的数
    scanf("%d\n", &b);

    for (i = 0; i < n; i++) {
        if (b == arr[i])
            continue;
        printf("%d ", arr[i]);
    }

    return 0;
}

老师方法的思路:用两个下标变量(i和j)进行比较,i是原数组下标,如果i下标的数不等于要删除的数就放到j下标,最后打印遍历打印j下标的元素
int main() {
    int n = 0;//有几个数
    scanf("%d\n", &n);
    int arr[n];//牛客网支持变长数组
    
    //接收n个数字
    int i = 0;
    for (i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
    }

    int del = 0;//要删除的数
    scanf("%d\n", &del);

    int j = 0;//j作为下标锁定的位置就是用来存放不删除的数据的
    for (i = 0; i < n; i++) {
        if (arr[i] != del)
        {
            //j最开始是0,先试用,后++。如果arr[i]不等于要删除的数,就存到arr[j]里面并++
            //这一步是将不等于del的元素移到前面
            arr[j++] = arr[i];
            //等效下方
            //arr[j] = arr[i];
            //j++;
        }
    }

    for (i = 0; i < j; i++)
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

7. 输入n个成绩,换行输出n个成绩中最高分数和最低分数的差。
输入描述:
两行,第一行为n,表示n个成绩,不会大于10000。
第二行为n个成绩(整数表示,范围0~100),以空格隔开。
输出描述:
一行,输出n个成绩中最高分数和最低分数的差。

自己方法的思路:用冒泡排序将数组从小到大排列,比较第一个元素和最后一个元素的差
int main() {
	int n = 0;
	scanf("%d", &n);

	int i = 0;
	int arr[n];
	for (i = 0; i < n; i++) 
	{
		scanf("%d ", &arr[i]);
	}
	//冒泡排序
	for (i = 0; i < n - 1; i++) 
	{
		int j = 0;
		for (j = 0; j < n - 1 - i; j++) 
		{
			if (arr[j] > arr[j + 1]) 
			{
				int tmp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = tmp;
			}
		}
	}

	int ret = arr[n - 1] - arr[0];
	printf("%d\n", ret);

}

老师方法的思路:

假设第一个元素最大,将数组里面的元素和它逐一比较,比他大就替换;
假设第一个元素最小,将数组里面的元素和它逐一比较,比他小就替换;
优化:
在向数组输入数据时就可以比较
继续优化:
假设最大值是0,最小值是100,在向数组输入数据时直接比较

int main()
{
	int n = 0;
	scanf("%d", &n);

	int i = 0;
	int arr[n];
	//输入
	for (i = 0; i < n; i++)
	{
		scanf("%d ", &arr[i]);
	}

	//找出最大值
	int max = arr[0];//假设第一个元素最大
	for (i = 1; i < n; i++)//不需要从下标为0的第一个元素开始,因为已经假设了一个元素
	{
		if (arr[i] > max)
			max = arr[i];
	}
	//找出最小值
	int min = arr[0];//假设第一个元素最小
	for (i = 1; i < n; i++)
	{
		if (arr[i] < min)
			min = arr[i];
	}
	int ret = max - min;
	printf("%d\n", ret);
    
    //优化版本
	int max = arr[0];
	int min = arr[0];
	for (i = 1; i < n; i++)
	{
		scanf("%d ", &arr[i]);
		if (arr[i] > max)
			max = arr[i];
		if (arr[i] < min)
			min = arr[i];
	}

//继续优化
int main()
{
	int n = 0;
	scanf("%d", &n);
	int i = 0;
	int arr[n];
	int min = 100;//同下
	int max = 0;//最大值设置0,因为如果设置成100,那么可能数组里没有数比它大
	for (i = 0; i < n; i++)
	{
		scanf("%d ", &arr[i]);
		if (arr[i] > max)
			max = arr[i];
		if (arr[i] < min)
			min = arr[i];
	}
	return 0;
}


8. KiKi想完成字母大小写转换,有一个字符,判断它是否为大写字母,如果是,将它转换成小写字母;反之则转换为大写字母。
输入描述:多组输入,每一行输入一个字母。
输出描述:针对每组输入,输出单独占一行,输出字母的对应形式。

思路:通过scanf读取字符。判断读取到的字符,如果是小写就-32(因为字符保存的是ASCII码值);否则就+32

单次判断
//此方法输出一个字符会有一个*
//因为每输入一个字符就按回车,就会有换行,scanf读了字符但是没有读换行
//所以下次进来不是小写字符,就去到else读取了换行,在+32,所以出错
//scanf读取成功的时候,返回的是读取的数据的个数
//scanf函数在读取失败的时候返回EOF
//这个条件还可以写成(scanf("%c", &ch) != EOF)不等于EOF说明没有失败,所以进入循环
while (scanf("%c", &ch) == 1)
{
	if (ch >= 'a' && ch <= 'z')
		printf("%c\n", ch - 32);
	else
		printf("%c\n", ch + 32);
	//所以需要下方代码销毁换行
	getchar();//处理\n
}

两次判断
方法二:通过两次判断字符,就不需要处理\n
while (scanf("%c", &ch) == 1)
{
	if (ch >= 'a' && ch <= 'z')
		printf("%c\n", ch - 32);
	else if (ch >= 'A' && ch <= 'Z')
		printf("%c\n", ch + 32);
}

库函数方法
//方法三:使用库函数
while (scanf("%c", &ch) != EOF)
{
	if (islower(ch))
		printf("%c\n", toupper(ch));
	else if (isupper(ch))
		printf("%c\n", tolower(ch));
}

9. KiKi想判断输入的字符是不是字母,请帮他编程实现。
输入描述:多组输入,每一行输入一个字符。
输出描述:针对每组输入,输出单独占一行,判断输入字符是否为字母,输出内容详见输出样例。

思路:直接判断是否是大写字母或是小写字母。

需要单独处理\n版本
while (scanf("%c", &a) != EOF) {
    if ((a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z')) {
        printf("%c is an alphabet.\n", a);
    }
    else {
        printf("%c is not an alphabet.\n", a);
    }
    getchar();
}

不需要单独处理\n版本
//方法二:
//%c前面加空格,跳过下一个字符之前的所有字符
//这里的空格 " " 表示忽略任意数量的空白字符(包括空格、制表符、换行符等),直到遇到第一个非空白字符为止
while (scanf(" %c", &a) != EOF) 
{
    if ((a >= 'a' && a <= 'z') || (a >= 'A' && a <= 'Z'))//还可以使用库函数 if (isalpha(a)) 
    {
        printf("%c is an alphabet.\n", a);
    }
    else {
        printf("%c is not an alphabet.\n", a);
    }
}

10. KiKi参加了语文、数学、外语的考试,请帮他判断三科中的最高分。从键盘任意输入三个整数表示的分数,编程判断其中的最高分。
数据范围:0≤n≤100
输入描述:输入一行包括三个整数表示的分数(0~100),用空格分隔。
输出描述:输出为一行,即三个分数中的最高分。

自己的思路:3个数相互比较,a如果大于b c,那么a最大。其他两个数一样。
int main() {
    int a = 0;
    int b = 0;
    int c = 0;
    while (scanf("%d %d %d", &a, &b, &c) != EOF) {
        if (a >= b && a >= c) {
            printf("%d\n", a);
        }
        else if (b >= a && b >= c) {
            printf("%d\n", b);
        }
        else if (c >= a && c >= b) {
            printf("%d\n", c);
        }
    }
    return 0;
}

老师思路:假设最高是0分,输入的三个数和它比较,比它大就替换它。
//老师方法
int main()
{
	int i = 0;
	int max = 0;
	int score = 0;

	for (i = 0; i < 3; i++)
	{
		scanf("%d ", &score);
		if (max < score)
		{
			max = score;
		}
	}
	printf("%d\n", max);
	return 0;
}

11. 变种水仙花数 - Lily Number:把任意的数字,从中间拆分成两个数字,比如1461 可以拆分成(1和461), (14和61), (146和1), 
如果所有拆分后的乘积之和等于自身,则是一个Lily Number。
例如:
655 = 6 * 55 + 65 * 5
1461 = 1 * 461 + 14 * 61 + 146 * 1
求出 5位数中的所有 Lily Number。
输入描述:无
输出描述:一行,5位数中的所有 Lily Number,每两个数之间间隔一个空格。

自己的思路:如果是3位数,拆分需要分别除以或模10和100;4位数需要分别除以或模10、100、1000,以此类推到5位数。
int main() {
	int i = 0;

	for (i = 10000; i <= 99999; i++) 
	{
		int a = (i / 10) * (i % 10);
		int b = (i / 100) * (i % 100);
		int c = (i / 1000) * (i % 1000);
		int d = (i / 10000) * (i % 10000);
		int e = a + b + c + d;
		if (i == e) 
		{
			printf("%d ", i);
		}
	}
	return 0;
}

老师的思路:通用使用pow库函数来优化重复代码
//老师方法
//假设12345,对它进行拆分
//12345/10000 = 1		2345= 12345%10000
//12345/1000  = 12		345 = 12345%1000
//12345/100   = 123		45  = 12345%100
//12345/10    = 1234	5   = 12345%10
//其中除数(10 100 1000 10000)可以理解为10^1  10^2  10^3  10^4
#include <math.h>//pow库函数需要此头文件
int main()
{
	int i = 0;
	for (i = 10000; i < 99999; i++)//遍历所有5位数
	{
		//产生4个数字(10 100 1000 10000)
		int sum = 0;
		int j = 0;
		for (j = 1; j <= 4; j++)
		{
			int k = (int)pow(10, j);//10为底数,j为指数。此函数产生的结果是double类型,需要类型转换
			//然后用i来除以上面这个数,分别得到商和余数。在把商和余数相乘
			sum += (i % k) * (i / k);
		}
		if (sum == i)
			printf("%d ", i);
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值