BC115-小乐乐与欧几里得(最大公约数)
描述
小乐乐最近在课上学习了如何求两个正整数的最大公约数与最小公倍数,但是他竟然不会求两个正整数的最大公约数与最小公倍数之和,请你帮助他解决这个问题。
输入描述:
每组输入包含两个正整数n和m。(1 ≤ n ≤ 109,1 ≤ m ≤ 109)
输出描述:
对于每组输入,输出一个正整数,为n和m的最大公约数与最小公倍数之和。
核心思想:分别取n和m的较大值和较小值,较大值向上递增找最小公倍数,较小值向下找最大公约数
#include <stdio.h>
int main()
{
int n = 0;
int m = 0;
while (scanf("%d %d", &m, &n) == 2)
{
int min = n < m ? n : m;
int max = m > n ? m : n;
int i = min;
int j = max;
while (1)
{
if (n % i == 0 && m % i == 0)
{
break;
}
i--;
}
while (1)
{
if (j % n == 0 && j % m == 0)
{
break;
}
j++;
}
printf("%d", i + j);
}
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/9b12dd4908aa39629ab4c6b34ed08c11.png)
效率过低——改进算法
优化:最大公约数用辗转相除法,最小公倍数用两个数乘积除以最大公约数
#include <stdio.h>
int main()
{
long n = 0;
long m = 0;
while (scanf("%ld %ld", &m, &n) == 2)
{
long i = n;
long j = m;
long r = 0;
while (r = i % j)
{
i = j;
j = r;
}
printf("%ld", j + n * m / j);
}
return 0;
}
坑点:题目中给出的n和m的取值范围暗示必须至少是长整型才能完成任务
BC69-空心正方形图案
描述
KiKi学习了循环,BoBo老师给他出了一系列打印图案的练习,该任务是打印用“*”组成的“空心”正方形图案。
输入描述:
多组输入,一个整数(3~20),表示输出的行数,也表示组成正方形边的“*”的数量。
输出描述:
针对每行输入,输出用“*”组成的“空心”正方形,每个“*”后面有一个空格。
#include <stdio.h>
int main()
{
int n = 0;
while (scanf("%d", &n) == 1)
{
int i = 0;
int j = 0;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if (i == 0 || j == 0 || i == n - 1 || j == n - 1)
{
printf("* ");
}
else
{
printf(" ");
}
}
printf("\n");
}
}
return 0;
}
offsetof 宏的模拟实现
写一个宏,计算结构体中某变量相对于首地址的偏移
函数使用示例
#include <stdio.h>
#include <stddef.h>
struct S
{
char c1;
int i;
char c2;
};
int main()
{
struct S s = { 0 };
printf("%d\n", offsetof(struct S, c1));
printf("%d\n", offsetof(struct S, i));
printf("%d\n", offsetof(struct S, c2));
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/5d77e89cf773d85d3092bf348f7924da.png)
偏移量的计算实质上是地址(指针)作差
模拟实现
#include <stdio.h>
struct S
{
char c1;
int i;
char c2;
};
#define OFFSETOF(type, m_name) (size_t)&(((type*)0)->m_name)
int main()
{
struct S s = { 0 };
printf("%d\n", OFFSETOF(struct S, c1));
printf("%d\n", OFFSETOF(struct S, i));
printf("%d\n", OFFSETOF(struct S, c2));
return 0;
}
BC65-箭形图案
描述
KiKi学习了循环,BoBo老师给他出了一系列打印图案的练习,该任务是打印用“*”组成的箭形图案。
输入描述:
本题多组输入,每行一个整数(2~20)。
输出描述:
针对每行输入,输出用“*”组成的箭形。
分两部分打印,上面的n行和下面的n+1行
#include <stdio.h>
int main()
{
int n = 0;
while (scanf("%d", &n) == 1)
{
//打印上半部分
int i = 0;
for (i = 0; i < n; i++)
{
int j = 0;
for (j = 0; j < n - i; j++)
{
printf(" ");
}
for (j = 0; j <= i; j++)
{
printf("*");
}
printf("\n");
}
//打印下半部分
for (i = 0; i <= n; i++)
{
int j = 0;
for (j = 0; j < i; j++)
{
printf(" ");
}
for (j = 0; j <= n - i; j++)
{
printf("*");
}
printf("\n");
}
}
return 0;
}
BC76-公务员面试
描述
公务员面试现场打分。有7位考官,从键盘输入若干组成绩,每组7个分数(百分制),去掉一个最高分和一个最低分,输出每组的平均成绩。
(注:本题有多组输入)
输入描述:
每一行,输入7个整数(0~100),代表7个成绩,用空格分隔。
输出描述:
每一行,输出去掉最高分和最低分的平均成绩,小数点后保留2位,每行输出后换行。
依次输入,满七个成绩进行处理
#include <stdio.h>
int main()
{
int score = 0;
int n = 0;
int max = 0;
int min = 100;
int sum = 0;
while (scanf("%d", &score) == 1)
{
n++;
if (score > max)
max = score;
if (score < min)
min = score;
sum += score;
if (n == 7)
{
printf("%.2lf\n", (sum - max - min) / 5.0);
min = 100;
max = 0;
sum = 0;
n = 0;
}
}
return 0;
}
找单身狗
一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。
编写一个函数找出这两个只出现一次的数字。
分成两组:每个组中只有一个单身狗;然后每组各自异或全部元素,所得到的就是两个单身狗
分组依据:将全部数字异或在一起(得到的是两个单身狗异或的结果),取其中一个不为0的位,将该位不同的元素分组
#include <stdio.h>
void find_single_dog(int arr[], int sz, int* pd1, int* pd2)
{
int i = 0;
int ret = 0;
for (i = 0; i < sz; i++)
{
ret ^= arr[i];
}
int pos = 0;
for (pos = 0; pos < 32; i++)
{
if ((ret >> pos) & 1 == 1)
break;
}
for (i = 0; i < sz; i++)
{
if ((arr[i] >> pos) & 1 == 1)
*pd1 ^= arr[i];
else
*pd2 ^= arr[i];
}
}
int main()
{
int arr[] = { 1,2,3,4,5,1,2,3,4,6 };
//分组
int sz = sizeof(arr) / sizeof(arr[0]);
int dog1 = 0;
int dog2 = 0;
find_single_dog(arr, sz, &dog1, &dog2);
printf("%d %d", dog1, dog2);
return 0;
}
模拟实现atoi
示例
#include <stdio.h>
#include <stdlib.h>
int main()
{
char arr[] = "123456";
int ret = atoi(arr);
printf("%d", ret);
return 0;
}
注意事项
专门用来将字符串转化为整数的函数
负数也可以转换
过大的数字可能无法转换
遇到非数字字符就停止转换
可以过滤多余的空格字符
模拟实现
空指针:进行断言报错
空字符串:状态值判断字符串是否非法——全局变量
空格(空白字符):直接跳过
正负号:用标志位记录正负
非数字字符:判断是否是数字字符,不是就返回
越界:每次计算新的和的时候都判断是否越界(同时为了防止被截断无法判断越界,创建ret变量为更长的整型)
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#include <limits.h>
enum Status
{
VALID,
INVALID
}sta = INVALID;
int my_atoi(const char* str)
{
int flag = 1;
long long ret = 0;
assert(str);
if (*str == '\0')
return 0;//非法0
while (isspace(*str))
str++;
if (*str == '+')
{
flag = 1;
str++;
}
else if(*str == '-')
{
flag = -1;
str++;
}
while (*str)
{
if (isdigit(*str) == 0)
{
return (int)ret;
}
else
{
ret = ret * 10 + flag * (*str - '0');
if (ret > INT_MAX || ret < INT_MIN)
{
return 0;
}
}
str++;
}
if (*str == '\0')
{
sta = VALID;
}
return (int)ret;
}
int main()
{
char arr[] = "123a56";
int ret = my_atoi(arr);
if (sta == INVALID)
{
printf("非法访问:%d", ret);
}
else
{
printf("合法转换:%d", ret);
}
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/4a14adedaa443de3e855c5fce72ca270.png)
交换奇偶位
写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。
交换奇偶位,相当于拿出所有偶数位和奇数位分别左移和右移一位
取出奇偶位的方式是要取出的位&1,不要的位&0
#include <stdio.h>
#define SWAP_BIT(n) n = (((n&0x55555555) << 1 ) + ((n & 0xaaaaaaaa) >> 1))
int main()
{
int n = 0;
scanf("%d", &n);
SWAP_BIT(n);
printf("%d", n);
return 0;
}
![](https://img-blog.csdnimg.cn/img_convert/313c0166741565c5b978862d55dec150.png)
链接: https://www.nowcoder.com/questionTerminal/18ecd0ecf5ef4fe9ba3f17f8d00d2d66
Fibonacci数列是这样定义的:
F[0] = 0
F[1] = 1
for each i ≥ 2: F[i] = F[i-1] + F[i-2]
因此,Fibonacci数列就形如:0, 1, 1, 2, 3, 5, 8, 13, ...,在Fibonacci数列中的数我们称为Fibonacci数。给你一个N,你想让其变为一个Fibonacci数,每一步你可以把当前数字X变为X-1或者X+1,现在给你一个数N求最少需要多少步可以变为Fibonacci数。
先找到改数字最近的两个斐波那契数,然后分别相减取差值绝对值较小者
#include <stdio.h>
int main()
{
int n = 0;
scanf("%d", &n);
int a = 0;
int b = 1;
int c = 0;
while (1)
{
if (n == b)
{
printf("0\n");
break;
}
else if (n < b)
{
if ((b - n) < (n - a))
{
printf("%d", b - n);
break;
}
else
{
printf("%d", n - a);
break;
}
}
c = a + b;
a = b;
b = c;
}
return 0;
}
https://www.nowcoder.com/questionTerminal/4060ac7e3e404ad1a894ef3e17650423
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。
class Solution {
public:
void replaceSpace(char *str,int length) {
}
};
预先统计空格个数,计算出需要增加的字符串长度,从后向前挪动字符串,每遇到一个空格替换成%20
具体实现:两个指针,一个指向源字符串末尾,一个指向新字符串末尾
class Solution {
public:
void replaceSpace(char *str,int length) {
char* cur = str;
int space_count = 0;
while(*cur)
{
if(*cur == ' ')
{
space_count++;
}
cur++;
}
int end1 = length - 1;
int end2 = end1 + space_count * 2;
while(end1 != end2)
{
if(str[end1] != ' ')
{
str[end2--] = str[end1--];
}
else
{
end1--;
str[end2--] = '0';
str[end2--] = '2';
str[end2--] = '%';
}
}
}
};