考点整合
A + B 问题
分离一个整数每一位
- 从后往前
- 从前往后→
- 字符数组(字符串) / 看成一堆字符
- 栈(先入后出) → 递归
while → 循环版的if (while循环的直接应用 → 模拟)
gcd 和 lcm
打擂法 求max, min
判断素数
- O(n)
- O(log n) → 分离因子的快捷的求法
打印素数表
数列求和、斐波那契数列(递推)
递推和递归
- 递推往往用迭代(循环)来实现
- 讲从前往后分离整数的递归写法
判断平方数
语法点
- while
- do-while
- for
- break, continue
while循环
- 循环版的if
if()
{
}
判断()内为真, 如果为真执行{}里的内容
while()
{
}
反复判断 ()内是否为真, 如果为真执行{}里的内容
- 如果里面没有修正条件, 可能会死循环
int n = 1;
while(n % 2 == 0)
{
printf("%d", n);
n++; //修正条件, 防止死循环
}
// TLE
- while循环最开始可能进不去
int n = 1;
while(n < 0)
{
printf("%d", n);
}
//如果最开始就不满足while()括号内的条件,while循环会直接进不去 → 可能在一些特殊的情况下没有/没有输出
while(1) //死循环
{
//一定要有一个break条件
}
do-while
一定要执行一次的while循环
do
{
i++;
j++;
}while(i < n);
do i++; while();
//会先执行一次do{}中的语句,再判断是否满足while()里的条件
int n = 1;
do
{
printf("%d", n);
}
while(n < 0);
for
- 基本语法
for(1; 2; 3)
{
;
}
1: 初始化变量
for(int i = 1; ; ;) i 是个局部变量, for循环结束之后会销毁 → 如果i用不到
int i;
for(i = 1; ; ) for循环结束之后,i的值为循环运行之后的i的值 → 如果i用的到
2: 判断条件
3: 修正条件
执行流程:
1 初始化 → 判断 2 是否成立
如果2成立 → {} → 3 修正条件 → 2 → {} → 3
如果2不成立 → 退出循环
- 可以根据人的需求来自由的控制循环次数
int n = 5;
for(int i = 1; i <= n; i++)
{
sum += i;
}
for(int i = 1; i <= n; i += 2)
{
sum += i;
}
for(int i = 2; i <= n; i += 2)
int i, n;
int sum = 0;
while(i < n)
{
sum += i;
i++;
}
for(int i = 1; i <= n; i++)
{
sum += i;
}
for(int i = 0, j = 1; i <= n && j <= m; i++, j++)
for(int i = 0; i < n; i++)
break 和 continue
- break和continue适用于三种循环
- break → 直接跳出当前循环
- break 不能用在if
- break跳出来的是当前的循环体,而不是整个循环体
- break和return的区别
- break → 跳出循环
- return → 跳出函数
for(int i = 0; i < n; i++)
{
for(int j = 0; j < n; j++)
{
for(int k = 0; k < n; k++)
{
for(int l = 0; l < n; l++)
{
break;
return 0; //程序直接结束
}
//break出来会跳到这儿
break;
}
//break出来会跳到这儿
break;
}
//break出来会跳到这儿
break;
}
//break出来会跳到这儿→ 跳出了整个循环
- continue → 跳过当前的这个值,继续运行后面的值
//求奇数的和
for(int i = 1; i <= n; i++)
{
if(i % 2 == 0) continue;
sum += i;
}
具体应用
A + B 问题 → 多组输入
- 组数(数据的个数)已知 → for / while
- 组数(数据的个数)未知 → while( EOF )
- 有额外的结束条件 → 多一个if
- 没有额外的结束条件
注意: 多组数据每一组数据输出的时候一般都要加上 \n
while 7-1 7-8 7-9
for 7-1
- a series of / 多组输入 / 题目中没有给出有几组具体的数据 → 不确定组数
//没有额外的结束条件
int a, b;
while(scanf("%d %d", &a, &b) != EOF)
while(~scanf("%d %d", &a, &b))
while(scanf("%d %d", &a, &b) == 2)
1 2
3 4
EOF
-1 → 11111111
~(-1) → 00000000 → 0
//scanf()的返回值 如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。
EOF → end of file 文件结束符
#define EOF -1 <stdio.h>
//有额外的结束条件
while(scanf("%d %d", &a, &b) != EOF)
{
if(额外条件) break;
if(a == 0 && b == 0) break;
printf("%d\n", a + b);
}
while(scanf("%d %d", &a, &b) != EOF && (a || b))
- 组数已知 →
while(t--) / for(int i = 0; i < t; i++)
int t;//组数
while(t--)
{
//对每一组数据的操作
for(int i = 0; i < n; i++)
}
for(int i = 0; i < t; i++)
{
for(int j = 0; j < n; j++)
}
t组测试样例, 每一组 n 个数
while(t--)
{
for(int i = 0; i < n; i++)
}
分离每一位
- 从后往前分离每一位
//3 2 1
int n = 123444;
int cnt = 0;
while(n)
{
int dig = n % 10;
// printf("%d ", dig);
n /= 10;
cnt++;
}
- 从前往后分离每一位
- 看成字符数组
- 栈
//法一:
12344
* 当成字符串
char s[100];
scanf("%s", s);
for(int i = 0; i < strlen(s); i++)
{
printf("%c", s[i]);
}
//法二:
* 当成很多字符,一个一个读进去
char c;
scanf("%c", &c);
char c;
c = getchar();
char c;
while((c = getchar()) && c >= '0' && c <= '9') //注意赋值运算符的优先级低, 需要用括号提高优先级
{
// '0' '1' '2'
printf("%c ", c);
//变成数
int dig = c - '0';
}
控制行末空格
pta 忽略最后\n, 但一般不会忽略行末空格
n = 5
for(int i = 0; i < n; i++)
{
printf("%d ", i);
}
0 1 2 3 4
//方法一: 特判第一个或者最后一个
for(int i = 0; i < n; i++)
{
if(i == 0) printf("%d", i);
else printf(" %d", i);
}
0 1 2 3 4
for(int i = 0; i < n; i++)
{
if(i < n - 1) printf("%d ", i);
else printf("%d", i);
}
for(int i = 0; i < n; i++)
{
if(i == n - 1) printf("%d", i);
else printf("%d ", i);
}
//方法二:
int f = 0; //标志, 当第一次出现的时候, 不打印空格, 后面的数都先打印一个空格,在打印这个数
int i = 0;
while(i < n)
{
if(f == 0)
{
f = 1;
}
else printf(" ");
printf("%d", i);
i++;
}