本文题目难度标识:🟩简单,🟨中等,🟥困难。
进制转换
令 N 是一个十进制数,它表示为下面的形式:
N=aknk+ak−1nk−1+⋯+a1n+a0+b1n−1+b2n−2+...++bl−1n−(l−1)+bln−l
可记为 (akak−1……a1a0.b1b2…bl−1bl)n。其中十进制的下标 10 可以省略。
n 进制数转十进制数
给出一个 n 进制数 (akak−1……a1a0.b1b2…bl−1bl)n,我们可以快速通过上面的式子得出十进制数 N。
十进制数转 n 进制数
简单来说就是两步:
- 整数部分取余除以基,最先取得的余数为最低位
- 小数部分乘基取整,最先取得的整数为最高位
- 最后结果拼接
接下来就是理解部分,设十进制数 N=I+D,其中 I 表示 N 的整数部分,D 表示其小数部分。
我们先理解「整数部分取余除以基」。观察:
I==aknk+ak−1nk−1+⋯+a1n+a0(aknk−1+ak−1nk−2+⋯+a1)n+a0
对 N 进行取余,先得到最低位 a0。余数拿走,然后在除以 n,得到:
N′==(N−a0)/naknk−1+ak−1nk−2+⋯+a1
重复取余除以基,就能依次拿到 a1,a2,...,ak。
「整数部分取余除以基」的另一种理解方式。

再看「小数部分乘基取整」。观察:
D=D⋅n=b1n−1+b2n−2+...++bl−1n−(l−1)+bln−lb1+b2n−1+...++bl−1n−(l−2)+bln−(l−1)
b2n−1+...+bl−1n−(l−2)+bln−(l−1) 部分一定是小数,取整时得到 b1。整数拿走,继续乘 n,有:
D′==(D⋅n−b1)⋅nb2+...+bl−1n−(l−3)+bln−(l−2)
重复取整乘 n,就能依次拿到 b1,b2,...,bl。
两数交换
常用写法
中间变量法
1 2 3 4
| int t = a; a = b; b = t;
|
这种方法可读性高,但是需要在内存中存放临时变量。
数学运算法
1 2 3 4 5 6 7 8 9
| a = a + b; b = a - b; a = a - b;
a ^= b; b ^= a; a ^= b;
|
方法评价:
- 加减法:两个数相加之后,可能其结果超出了变量类型能表达的最大范围,这个时候结果就会出数据溢出,不推荐使用。
- 异或法:效率是最高的,但是可读性不是很好。
Java 中编写 swap
交换函数
Java 在有参函数调用时,如果参数传递的是基本类型,进行的是值传递,而不是 地址或引用传递。
因此,以下的写法是错误的:
1 2
| public static void swap(int a, int b); public static void swap(Integer a, Integer b);
|
正确的写法是传入一个数组,在数组的基础上进行交换:
1 2 3 4 5
| public static void swap(int[] arr) { int temp = arr[0]; arr[0] = arr[1]; arr[1] = temp; }
|
循环增减
1 2 3
| idx=(idx+1) % SIZE; idx=(idx + SIZE - 1) % SIZE;
|
将比较关系整数化
得到 a 和 b 的大小关系,小于是 -1,等于是 0,大于是 1
四舍五入
1 2 3
| double x; x = (int)((x * 1000) + 0.5) / 1000.0)
|
向上取整转变为向下取整
对于正整数 m,有:
⌈mn⌉=⌊mn+m−1⌋=⌊mn−1⌋+1
我们可以根据这个性质将一些向上取整操作处理为向下取整。
最大公约数 GCD
辗转相除法数学定理:gcd(a,b) = gcd(b,a mod b)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public int gcd(int a, int b) { while (b != 0) { a %= b; swap(new int[]{a,b}); } return a; }
public int gcd(int a,int b){ while(a%b!=0){ a%=b; swap(new int[]{a,b}); } return b; }
|
递归版本:
1 2 3 4 5
| public static int gcd(int a,int b){ if (b == 0) return a; return gcd(b, a % b); }
|
相关题目:
质数的判断
详看:站内文章【刷题日记】判断质数
本文参考