LeetCode 数学问题(下篇)

137 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第26天,点击查看活动详情

2. 最大公约数

int gcd(int a, int b) {
    return b == 0 ? a : gcd(b, a % b);
}

最小公倍数为两数的乘积除以最大公约数。

int lcm(int a, int b) {
    return a * b / gcd(a, b);
}

3. 使用位操作和减法求解最大公约数

编程之美: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);

乘 2 和除 2 都可以转换为移位操作。

public int gcd(int a, int b) {
    if (a < b) {
        return gcd(b, a);
    }
    if (b == 0) {
        return a;
    }
    boolean isAEven = isEven(a), isBEven = isEven(b);
    if (isAEven && isBEven) {
        return 2 * gcd(a >> 1, b >> 1);
    } else if (isAEven && !isBEven) {
        return gcd(a >> 1, b);
    } else if (!isAEven && isBEven) {
        return gcd(a, b >> 1);
    } else {
        return gcd(b, a - b);
    }
}

进制转换

1. 7 进制

  1. Base 7 (Easy)

Leetcode / 力扣

public String convertToBase7(int num) {
    if (num == 0) {
        return "0";
    }
    StringBuilder sb = new StringBuilder();
    boolean isNegative = num < 0;
    if (isNegative) {
        num = -num;
    }
    while (num > 0) {
        sb.append(num % 7);
        num /= 7;
    }
    String ret = sb.reverse().toString();
    return isNegative ? "-" + ret : ret;
}

Java 中 static String toString(int num, int radix) 可以将一个整数转换为 radix 进制表示的字符串。

public String convertToBase7(int num) {
    return Integer.toString(num, 7);
}

2. 16 进制

  1. Convert a Number to Hexadecimal (Easy)

Leetcode / 力扣

Input:
26
​
Output:
"1a"Input:
-1
​
Output:
"ffffffff"

负数要用它的补码形式。

public String toHex(int num) {
    char[] map = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    if (num == 0) return "0";
    StringBuilder sb = new StringBuilder();
    while (num != 0) {
        sb.append(map[num & 0b1111]);
        num >>>= 4; // 因为考虑的是补码形式,因此符号位就不能有特殊的意义,需要使用无符号右移,左边填 0
    }
    return sb.reverse().toString();
}

3. 26 进制

  1. Excel Sheet Column Title (Easy)

Leetcode / 力扣

1 -> A
2 -> B
3 -> C
...
26 -> Z
27 -> AA
28 -> AB

因为是从 1 开始计算的,而不是从 0 开始,因此需要对 n 执行 -1 操作。

public String convertToTitle(int n) {
    if (n == 0) {
        return "";
    }
    n--;
    return convertToTitle(n / 26) + (char) (n % 26 + 'A');
}

阶乘

1. 统计阶乘尾部有多少个 0

  1. Factorial Trailing Zeroes (Easy)

Leetcode / 力扣

尾部的 0 由 2 * 5 得来,2 的数量明显多于 5 的数量,因此只要统计有多少个 5 即可。

对于一个数 N,它所包含 5 的个数为:N/5 + N/52 + N/53 + ...,其中 N/5 表示不大于 N 的数中 5 的倍数贡献一个 5,N/52 表示不大于 N 的数中 52 的倍数再贡献一个 5 ...。

public int trailingZeroes(int n) {
    return n == 0 ? 0 : n / 5 + trailingZeroes(n / 5);
}

如果统计的是 N! 的二进制表示中最低位 1 的位置,只要统计有多少个 2 即可,该题目出自 编程之美:2.2 。和求解有多少个 5 一样,2 的个数为 N/2 + N/22 + N/23 + ...