数字与数学的基础问题(算法村第十三关青铜挑战)

数学的门类很多,涉及的范围很广,很多难度也超大,但是在算法中,一般只会选择各个学科的基础问题来考察,例如素数问题、幂、对数、阶乘、幂运算、初等数论、几何问题、组合数学等等。

数字统计专题

数组元素积的符号

1822. 数组元素积的符号 - 力扣(LeetCode)

已知函数 signFunc(x) 将会根据 x 的正负返回特定值:

  • 如果 x 是正数,返回 1
  • 如果 x 是负数,返回 -1
  • 如果 x 是等于 0 ,返回 0

给你一个整数数组 nums 。令 product 为数组 nums 中所有元素值的乘积。

返回 signFunc(product)

计数法
public int arraySign(int[] nums)
{
    int count = 0; //nums 中负数的个数

    for(int num : nums)
    {
        if(num == 0)
            return 0;
        else if(num < 0)
            count++;
    }

    if(count % 2 == 1)
        return -1;
    else
        return 1;
}
交替法
public int arraySign(int[] nums)
{
    int ans = 1;

    for(int num : nums)
    {
        if(num == 0)
            return 0;
        else if(num < 0)
            ans = -ans; //交替
    }

    return ans;
}

阶乘尾数

面试题 16.05. 阶乘尾数 - 力扣(LeetCode)

设计一个算法,算出 n 阶乘有多少个尾随零。

示例 1:

输入: 3
输出: 0
解释: 3! = 6, 尾数中没有零。

示例 2:

输入: 5
输出: 1
解释: 5! = 120, 尾数中有 1 个零.

说明: 你算法的时间复杂度应为 O(log n) 。

要在末位产生0,则必然是5×2,因此我们需要求2 * 5出现了几对。又因阶乘中5出现的次数比2少,所以将题目简化为寻找阶乘中5的个数。

n / 5只找到了n中是5倍数的所有数,例如25,即在25!中找到了5个是5的倍数的数分别为5,10,15,20,25,要注意这之中的25依然可以分解为5的倍数

我们可以对n取25的商,即n / 25,这样就找到了包含有2个5的数(且因为是对5×5取商,没有重复计入),依此类推,可以循环对n取5, 25, 125…的商,将所有的情况都包括

n / 25 == n / 5 / 5,因此可以对n循环取5的商,其效果是一样的。

public int trailingZeroes(int n) 
{
    int count = 0;
    
    while (n >= 5)
    {
        n /= 5;
        count += n;
    }
    
    return count;
}

溢出问题

凡是涉及到输出结果为数字的问题,必须溢出问题!

整数反转

7. 整数反转 - 力扣(LeetCode)

给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。

如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。

假设环境不允许存储 64 位整数(有符号或无符号)。

示例 1:

输入:x = 123
输出:321

示例 2:

输入:x = -123
输出:-321

示例 3:

输入:x = 120
输出:21

示例 4:

输入:x = 0
输出:0

提示:

  • -231 <= x <= 231 - 1
public static int reverse(int x)
{
    int ans = 0;

    int Max = Integer.MAX_VALUE;
    int Min = Integer.MIN_VALUE;

    while (x != 0)
    {
        if(ans > Max / 10 || (ans == Max / 10 && x % 10 > Max % 10)
           ||
           ans < Min / 10 || (ans == Min / 10 && x % 10 < Min % 10))
                                                 //负数求余结果仍是负数
            return 0;

        ans = 10 * ans + x % 10;
        x /= 10;
    }

    return ans;
}

回文数

9. 回文数 - 力扣(LeetCode)

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false

回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

  • 例如,121 是回文,而 123 不是。

示例 1:

输入:x = 121
输出:true

示例 2:

输入:x = -121
输出:false
解释:从左向右读,-121 。 从右向左读,121- 。因此它不是一个回文数。

示例 3:

输入:x = 10
输出:false
解释:从右向左读,01 。因此它不是一个回文数。

提示:

  • -231 <= x <= 231 - 1

**进阶:**你能不将整数转为字符串来解决这个问题吗?

字符串法
public boolean isPalindrome(int x)
{
    if(x < 0)
        return false;

    String s = String.format("%d", x);
    char[] chars = s.toCharArray();

    int left = 0;
    int right = s.length() - 1;

    while (left < right)
    {
        if(chars[left] != chars[right])
            return false;

        left++;
        right--;
    }

    return true;
}
反转法
public boolean isPalindrome_2(int x)
{
    //非零数末尾若是0,则反转后0在首位,不符合要求,也可直接排除
        if(x < 0 || x % 10 == 0 && x != 0)
            return false;

    //反转
    long reverse = 0;	//long 类型避免反转过程中溢出
    int t = x;

    while (t != 0)
    {
        reverse = 10 * reverse + t % 10;
        t /= 10;
    }

    return x == reverse;
}

进制专题

七进制数

504. 七进制数 - 力扣(LeetCode)

给定一个整数 num,将其转化为 7 进制,并以字符串形式输出。

示例 1:

输入: num = 100
输出: "202"

示例 2:

输入: num = -7
输出: "-10"
Java库函数
public String convertToBase7(int num)
{
    return Integer.toString(num, 7);
}
循环取余和整除

最后将余数反转过来排列

public String convertToBase7(int num)
{
    StringBuilder sb = new StringBuilder();

    int sign = 1;
    if (num < 0)
    {
        sign = -1;
        num = -num; //先当正数来处理
    }

    do
    {
        sb.append(num % 7);
        num /= 7;
    }while (num > 0);

    if (sign == -1)
        sb.append("-");

    return sb.reverse().toString();
}

将十进制数 M 转化为 N 进制数

M是32位整数,2 <= N <= 16

public static String convertToBaseN(int M, int N)
{
    String[] F = {"0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"};
    StringBuilder sb = new StringBuilder();

    int sign = 1;
    if (M < 0)
    {
        sign = -1;
        M = -M; //先当正数来处理
    }

    do
    {
        int mod = M % N;
        //技巧一:通过数组F[]解决不同进制之间映射的问题
        sb.append(F[mod]);
        M /= N;
    }while (M > 0);

    //技巧二:最后处理正负,不要从一开始就揉在一起
    if (sign == -1)
            sb.append("-");

    //技巧三:使用StringBuffer的reverse()方法,让原本麻烦的反转瞬间美好
    return sb.reverse().toString();
}

你可能感兴趣的:(算法村,算法)