发布于2021-06-07 20:56 阅读(992) 评论(0) 点赞(16) 收藏(2)
本文适合对算法处于朦胧期的初学者,文字浅显易懂,并且配有生动有趣的动图,也是作者呕心沥血之作,希望对刚入大学,或者职场上想要涉足算法的青年同僚有所启示。
学习算法,任何时候都不嫌晚,大不了就是大器晚成而已,所以无论你是30岁,40岁,50岁,甚至60岁,只要下了决心,就已经成功了一半!本文的故事发生在 ❤️学姐教你 10 道题搞定 c 语言❤️ 的两年后,剧情扑朔迷离,作者至今回忆起来还历历在目。
【例题1】给定 n ( n ≤ 65535 ) n(n \le 65535) n(n≤65535),求 ∑ i = 1 n i = 1 + 2 + . . . + n \sum_{i=1}^n i = 1 + 2 + ... + n ∑i=1ni=1+2+...+n。
int sum(int n) {
return n * (n + 1) / 2;
}
原因是因为 n ∗ ( n + 1 ) = 65535 ∗ 65536 = ( 2 16 − 1 ) 2 16 = 2 32 − 2 16 n * (n + 1) = 65535 * 65536 = (2^{16}-1)2^{16} = 2^{32} -2^{16} n∗(n+1)=65535∗65536=(216−1)216=232−216,而 i n t int int 能够表示的最大值为 2 31 − 1 2^{31}-1 231−1,所以产生了溢出。就变成了负数。至于为什么溢出会变成负数,可以了解补码相关的知识:c++ 补码详解。
int sum(int n) {
if(n % 2 == 1) {
return (n + 1) / 2 * n;
}else {
return n / 2 * (n + 1);
}
}
int sum(int n) {
return (n%2) ? (n+1)/2*n : n/2*(n+1);
}
这里的
condition ? a : b
是 c/c++ 中的三目运算符,含义是根据表达式condition
的值的真或假,选择返回a
还是b
。由于对于一个数 x x x, x x x 非0就是真,为0就是假,所以可以直接省略x == 0
的判断。
【例题2】给定 n ( n < 16 ) n(n \lt 16) n(n<16),求 ∏ i = 1 n i = 1 × 2 × . . . × n \prod_{i=1}^n i = 1 \times 2 \times ... \times n ∏i=1ni=1×2×...×n。
int sum(int n) {
int s = 1;
for(int i = 1; i <= n; ++i) {
s *= i;
}
return s;
}
s
这个变量放到循环体内和i
一起初始化,并且把乘法和循环放到同一行,变成了下面这副样子。int sum(int n) {
for(int s = 1, i = 1; i <= n; ++i) s *= i;
return s;
}
s
的作用域在循环体内,所以无法在循环体外部进行使用,但是我们这个函数有需要有一个返回值,总不能把函数体给返回吧?这可如何是好!int f(int x) {
if(x == 0) {
return 1;
}else {
return f(x-1) * x;
}
}
int f(int x) {
return x ? f(x-1) * x : 1;
}
【例题3】现在有一个 n ( n ≤ 10000 ) n(n \le 10000) n(n≤10000) 个元素的数组 a [ i ] a[i] a[i],但是我们已知的是前 i i i 个元素的和 f [ i ] ( 1 ≤ i ≤ n , 1 ≤ f [ i ] ≤ 100000 ) f_[i](1 \le i \le n, 1 \le f[i] \le 100000) f[i](1≤i≤n,1≤f[i]≤100000),然后给出 Q ( Q ≤ 1000000 ) Q(Q \le 1000000) Q(Q≤1000000) 次询问 ( l , r ) ( 1 ≤ l ≤ r ≤ n ) (l, r) (1 \le l \le r \le n) (l,r)(1≤l≤r≤n),求 ∑ i = l r a [ i ] \sum_{i=l}^r a[i] ∑i=lra[i]。
for
循环计算出所有a[i]
的值。const int maxn = 100005;
void preCalculate(int f[maxn]) {
int a[maxn];
for(int i = 1; i <= n; ++i) {
a[i] = f[i] - f[i-1];
}
}
int get(int a[], int l, int r) {
int s = 0;
for(int i = l; i <= r; ++i) {
s += a[i];
}
return s;
}
int g(int l, int r) {
return f[r] - f[l-1];
}
【定义1】对于一个数 a a a,如果有数 b b b 能够整除 a a a,则称 a a a 是 b b b 的倍数, b b b 是 a a a 的约数。
【定义2】如果一个数 c c c 同时是数 a a a 和 数 b b b 的约数,则称 c c c 是 a a a 和 b b b 的公约数。
【定义3】如果 c c c 是 a a a 和 b b b 中最大的公约数,则称 c c c 为 a a a 和 b b b 的最大公约数,记为 c = g c d ( a , b ) c = gcd(a, b) c=gcd(a,b)。
int gcd(int a, int b) {
int maxret = 1;
for(int i = 2; i <= a; ++i) {
if(a % i == 0 && b % i == 0)
maxret = max(maxret, i);
}
}
首先,当 b ≠ 0 b \neq 0 b=0 时,我们令 a = k b + r a = kb + r a=kb+r,其中 k = ⌊ a b ⌋ k = \lfloor \frac a b \rfloor k=⌊ba⌋, r = a m o d b r = a \ mod \ b r=a mod b,并且满足 ( 0 ≤ r < b ) (0 \le r < b) (0≤r<b),当一个数 c c c,是 a a a 的约数,也是 b b b 的约数,则必然也是 a − k b a-kb a−kb 的约数,即 r r r 的约数。自然 a a a 和 b b b 的公约数 也就是 b b b 和 r r r 的公约数。
所以, a a a 和 b b b 的最大公约数 = = = b b b 和 r r r 的最大公约数。表示为: g c d ( a , b ) = g c d ( b , a m o d b ) gcd(a, b) = gcd(b, a \ mod \ b) gcd(a,b)=gcd(b,a mod b)
int gcd(int a, int b) {
return !b ? a : gcd(b, a % b);
}
!
是 c/c++ 中的表达式取非的意思,即 真变假,假变真,且 c/c++ 中 0 为假,非0为真;%
是取模,即
m
o
d
mod
mod 的程序语法。
知识点 | 难度 |
---|---|
整除 | ★☆☆☆☆ |
倍数 | ★☆☆☆☆ |
约数 | ★☆☆☆☆ |
前缀和 | ★★★☆☆ |
差分法 | ★★★☆☆ |
递推公式 | ★★★☆☆ |
递归调用 | ★★★★★ |
整数取模 | ★☆☆☆☆ |
最大公约数 | ★★★☆☆ |
表达式取反 | ★☆☆☆☆ |
整数的溢出 | ★★☆☆☆ |
三目运算符 | ★★☆☆☆ |
变量的作用域 | ★★☆☆☆ |
整数的补码表示 | ★★☆☆☆ |
表达式真值的省略写法 | ★☆☆☆☆ |
// 算法1:求和公式
int sum(int n) {
return (n%2) ? (n+1)/2*n : n/2*(n+1);
}
// 算法2:递归求阶乘
int f(int x) {
return x ? f(x-1) * x : 1;
}
// 算法3:差分法求部分和
int g(int l, int r) {
return f[r] - f[l-1];
}
// 算法4:递归求最大公约数
int gcd(int a, int b) {
return !b ? a : gcd(b, a % b);
}
原文链接:https://blog.csdn.net/WhereIsHeroFrom/article/details/117596791
作者:动漫魔动
链接:http://www.phpheidong.com/blog/article/89446/27438034c58879f441db/
来源:php黑洞网
任何形式的转载都请注明出处,如有侵权 一经发现 必将追究其法律责任
昵称:
评论内容:(最多支持255个字符)
---无人问津也好,技不如人也罢,你都要试着安静下来,去做自己该做的事,而不是让内心的烦躁、焦虑,坏掉你本来就不多的热情和定力
Copyright © 2018-2021 php黑洞网 All Rights Reserved 版权所有,并保留所有权利。 京ICP备18063182号-4
投诉与举报,广告合作请联系vgs_info@163.com或QQ3083709327
免责声明:网站文章均由用户上传,仅供读者学习交流使用,禁止用做商业用途。若文章涉及色情,反动,侵权等违法信息,请向我们举报,一经核实我们会立即删除!