数学技巧

231 阅读2分钟

Day09 有关数学运算的一些常见算法

1、判断两个数相除的结果是否是无限循环小数。

  • 题解
    • 数学定理:
    • 辗转相除法
    • 当除数(分母)只有2或者5这两个质因数时,就是有限小数;当除数(分母)含有2和5以外的质因数时就是无限循环小数。
  • coding
public class Main {
   public static void main(String[] args) {
       System.out.println(isLoop(1, 2));
   }

   /**
    * 判断 a/b的结果是否是无限循环小数
    * @param a 被除数(分子)
    * @param b 除数(分母)
    * @return 判断结果
    */
   public static boolean isLoop(long a, long b) {
       //1、先将分式化为最简分式
       long commonDivisor = greatestCommonDivisor(a, b);
       b = b / commonDivisor;
       //2、判断分母是否存在除了2、5以外的因数
       while (b % 2 == 0){
           b /= 2;
       }
       while (b % 5 == 0){
           b /= 5;
       }
       //如果不存在,说明不是无限循环小数
       if (b == 1){
           return false;
       }else {
           return true;
       }
   }
   /**
    * 利用辗转相除法求最大公约数
    * @param a 较大的数
    * @param b 较小的数
    * @return 最大公约数
    */
   public static long greatestCommonDivisor(long a, long b) {
       long c = 0;
       while (true) {// 循环的辗转相除法
           c = a % b;
           a = b;
           b = c;
           //如果余数为0,则得到最大公约数
           if (b == 0) {
               return a;
           }
       }
   }
}

2、求两数相除的精确结果。如果有循环就只到循环节

  • 定理:当余数相同时,代表有循环截出现
class Solution{
    /**
     * 求两个数相除的结果
     * @param a 分子
     * @param b 分母
     * @return 除数结果
     */
    public static Double getLoop(long a,long b){
        StringBuilder result = new StringBuilder();
        //1、先将分式化为最简分式
        long commonDivisor = greatestCommonDivisor(a, b);
        b = b / commonDivisor;
        a = a / commonDivisor;
        //存储除数
        long[] ans = new long[1000];
        //存储余数
        long[] r = new long[1000];
        int j , len = 0;
        while (true){
            //记录除数
            ans[len] = (a / b);
            a = a % b;
            //判断余数是否重复
            for (j = len; j > 0; j --) {
                if (r[j] == a){
                    break;
                }
            }
            //当得到结果或者找到循环截,退出
            if (a == 0 || j > 0){
                break;
            }else {
                r[++len] = (int) a;
            }
            a *= 10;
        }
        result.append(ans[0]).append(".");
        for (int i = 1; i <= len; i++) {
            result.append(ans[i]);
        }
        return Double.parseDouble(result.toString());
    }
}

3、超级次方-快速模幂运算

  • 题解:
    • 快速求幂公式。a8=(a4)2=(a4)(a4)a^8=(a^4)^2=(a^4) * (a^4) 只需要对(a4)(a^4)求幂
    • 模运算规律。(ab)(modk)=(a(modk))(b(modk))(modk)(a*b) \pmod k = (a \pmod k)*(b \pmod k)\pmod k
  • coding
class Solution {
        int base = 1337;

        public int superPow(int a, int[] b) {
            return superP(a, b, b.length - 1);
        }

        private int superP(int a, int[] b, int len) {
            if (len == -1) return 1;
            int last = b[len];
            //拆分 成两个部分 一个部分是将数组末尾的数字计算取模
            //另一个是将剩余的 还有个10次方取模
            int part1 = myPow(a, last) % base;
            int part2 = myPow(superP(a, b, len - 1), 10) % base;
            return (part2 * part1) % base;
        }

        //求 a^b 对 base取模的结果
        private int myPow(int a, int b) {
            if (b == 0) return 1;
            if (b % 2 == 1) {
                return (a % base * myPow(a, b - 1) % base) % base;
            } else {
                int sub = myPow(a, b / 2) % base;
                return (sub * sub) % base;
            }
        }
    }

4、645. 错误的集合-缺失重复快速定位

  • 思路:
    • 利用[1,n][1,n]的区间性质。每找到一个数 curcur 让对应的下标位的数 arr[cur1]arr[cur - 1] 变为 负数
    • arr[cur1]<0arr[cur - 1] < 0 时,代表 curcur重复
    • 遍历 arr[cur1]arr[cur - 1],当arr[cur1]>0arr[cur - 1] > 0,表示该数缺失
  • 时间复杂度:O(n)O(n) 空间复杂度:O(1)O(1)
  • coding:
class Solution {
   public int[] findErrorNums(int[] nums) {
   	//重复的数
   	int num1 = 0;
   	//缺失的数
   	int num2 = 0;
   	for (int num : nums) {
   		int index = Math.abs(num) - 1;
   		if (nums[index] < 0){
   			num1 = Math.abs(num);
   		}else {
   			nums[index] *= -1;
   		}
   	}
   	for (int i = 0; i < nums.length; i++) {
   		if (nums[i] > 0){
   			num2 = i + 1;
   			break;
   		}
   	}
   	return new int[]{num1,num2};
   }
}