diff --git a/notes/Leetcode 题解 - 数学.md b/notes/Leetcode 题解 - 数学.md index 5269fb11..a2ec3928 100644 --- a/notes/Leetcode 题解 - 数学.md +++ b/notes/Leetcode 题解 - 数学.md @@ -26,6 +26,7 @@ * [3. 乘积数组](#3-乘积数组) * [4. 找出数组中的乘积最大的三个数](#4-找出数组中的乘积最大的三个数) * [5. 用 Rand7() 实现 Rand10()](#5-用-rand7-实现-rand10) + * [参考资料](#参考资料) @@ -91,14 +92,14 @@ int lcm(int a, int b) { ### 3. 使用位操作和减法求解最大公约数 -编程之美:2.7 +《编程之美》2.7 对于 a 和 b 的最大公约数 f(a, b),有: -- 如果 a 和 b 均为偶数,f(a, b) = 2\*f(a/2, b/2); -- 如果 a 是偶数 b 是奇数,f(a, b) = f(a/2, b); -- 如果 b 是偶数 a 是奇数,f(a, b) = f(a, b/2); -- 如果 a 和 b 均为奇数,f(a, b) = f(b, a-b); +- 如果 a 和 b 均为偶数,f(a, b) = 2\*f(a/2, b/2); +- 如果 a 是偶数 b 是奇数,f(a, b) = f(a/2, b); +- 如果 b 是偶数 a 是奇数,f(a, b) = f(a, b/2); +- 如果 a 和 b 均为奇数,f(a, b) = f(b, a-b)。 乘 2 和除 2 都可以转换为移位操作。 @@ -213,7 +214,7 @@ public String toHex(int num) { 28 -> AB ``` -因为是从 1 开始计算的,而不是从 0 开始,因此需要对 n 执行 -1 操作。 +这种表示没有 0,A \~ Z 对应 1 \~ 26,每一位的取值是 1 \~ 26 而不是 0 \~ 25。先把 n 减 1,最低位就变成 0 \~ 25,对应 A \~ Z,再对 (n - 1) / 26 递归处理更高位。例如 52:51 % 26 = 25 对应 Z,51 / 26 = 1 对应 A,结果为 AZ。 ```java public String convertToTitle(int n) { @@ -243,7 +244,7 @@ public int trailingZeroes(int n) { } ``` -如果统计的是 N! 的二进制表示中最低位 1 的位置,只要统计有多少个 2 即可,该题目出自 编程之美:2.2 。和求解有多少个 5 一样,2 的个数为 N/2 + N/22 + N/23 + ... +如果统计的是 N! 的二进制表示中最低位 1 的位置,只要统计有多少个 2 即可,该题目出自《编程之美》2.2。和求解有多少个 5 一样,2 的个数为 N/2 + N/22 + N/23 + ... ## 字符串加法减法 @@ -348,7 +349,7 @@ public int minMoves2(int[] nums) { #### 解法 2 -使用快速选择找到中位数,平均时间复杂度 O(N) +使用快速选择找到中位数,平均时间复杂度 O(N)。下面的实现固定以第一个元素为基准,输入已经有序时每次只能排除一个元素,退化为 O(N2),可以先随机打乱数组或随机选取基准。 ```java public int minMoves2(int[] nums) { @@ -414,7 +415,11 @@ public int majorityElement(int[] nums) { } ``` -可以利用 Boyer-Moore Majority Vote Algorithm 来解决这个问题,使得时间复杂度为 O(N)。可以这么理解该算法:使用 cnt 来统计一个元素出现的次数,当遍历到的元素和统计元素不相等时,令 cnt--。如果前面查找了 i 个元素,且 cnt == 0,说明前 i 个元素没有 majority,或者有 majority,但是出现的次数少于 i / 2,因为如果多于 i / 2 的话 cnt 就一定不会为 0。此时剩下的 n - i 个元素中,majority 的数目依然多于 (n - i) / 2,因此继续查找就能找出 majority。 +Boyer-Moore 多数投票算法(Boyer-Moore Majority Vote Algorithm)可以在 O(N) 时间、O(1) 空间内解决这个问题。它维护一个候选元素 majority 和计数 cnt:遇到和候选相同的元素 cnt 加一,不同的元素 cnt 减一,相当于让两个不同的元素互相抵消;cnt 为 0 时把当前元素作为新的候选。 + +每次抵消的是一对不同的元素,其中最多有一个是多数元素,所以抵消掉若干对之后,多数元素在剩下的元素中出现的次数仍然多于一半。cnt 回到 0 时,从上次 cnt 为 0 到现在扫过的一段恰好两两抵消完,可以整段丢掉,从下一个元素重新开始;扫描结束时没有被抵消的候选就是多数元素。本题保证多数元素存在,否则还要再遍历一次,确认候选的出现次数确实多于 n / 2。 + +