Leetcode数学知识题

本文深入探讨了数学算法在计算机科学中的应用,包括素数分解、最大公约数与最小公倍数计算、进制转换、位操作、阶乘、加减法、相遇问题、多数投票问题等,提供了丰富的代码实现与理论解析。
部署运行你感兴趣的模型镜像

素数

素数的分解
每一个数都可以分解成素数的乘积,例如 84 = 22 * 31 * 50 * 71 * 110 * 130 * 170 * …

令 x = 2m0 * 3m1 * 5m2 * 7m3 * 11m4 * …
令 y = 2n0 * 3n1 * 5n2 * 7n3 * 11n4 * …
如果 x 整除 y(y mod x == 0),则对于所有 i,mi <= ni。
x 和 y 的最大公约数为:
gcd(x,y) = 2min(m0,n0) * 3min(m1,n1) * 5min(m2,n2) * …
x 和 y 的最小公倍数为:
lcm(x,y) = 2max(m0,n0) * 3max(m1,n1) * 5max(m2,n2) * …

204 生成素数序列

详细讲解过程
我的解决方案

    public int countPrimes(int n) {    
    boolean[] notPrimes = new boolean[n + 1];    
    int count = 0;    
    Arrays.fill(notPrimes,true);    
    for (int i = 2; i < n; i++) {        
    if (notPrimes[i]) {
for (long j = (long) (i) * i; j < n; j += i) {
                   notPrimes[(int)j] = false;       
                    }        
    count++;       
     }                   
      }    
      return count;}

最大公约数以及最小公倍数

最小公倍数为两数的乘积除以最大公约数
辗转相除法求最大公约数

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);
}

位操作以及减法求解最大公约数

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

进制转换

504 七进制数

注意在此题当中返回的是字符串

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);
}

16进制

复习源码,反码和补码
(原码 反码 补码之间的转换 , 符号位不要动)
正数: 原码 = 反码 = 补码
负数: 原码 = 补码取反加1 给补码求原码
负数: 补码 = 原码取反加1 给原码求补码
位移知识讲解

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();
}

26进制

辗转相除问题,进制转换计算变种

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

阶乘

172 统计阶乘尾部有多少个零

首先题目的意思是末尾有几个0
比如6! = 【1* 2* 3* 4* 5* 6】
其中只有25末尾才有0,所以就可以抛去其他数据 专门看2 5 以及其倍数 毕竟 4 * 25末尾也是0
比如10! = 【2
456810】
其中 4能拆成22 10能拆成25
所以10! = 【2*(22)5(23)(222)(25)】
一个2和一个5配对 就产生一个0 所以10!末尾2个0
转头一想 2肯定比5多 所以只数5的个数就行了
假若N=31 31里能凑10的5为[5, 2
5, 35, 45, 25, 6*5] 其中 25还能拆为 52
所以 里面的5的个数为 int(31/(5
1)) + int(31/(52))
所以 只要先找个一个 5
x < n 的x的最大数 然后按上面循环加起来

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

字符产加减法

67 二进制加法

public String addBinary(String a, String b) {
    int i = a.length() - 1, j = b.length() - 1, carry = 0;
    StringBuilder str = new StringBuilder();
    while (carry == 1 || i >= 0 || j >= 0) {
        if (i >= 0 && a.charAt(i--) == '1') {
            carry++;
        }
        if (j >= 0 && b.charAt(j--) == '1') {
            carry++;
        }
        str.append(carry % 2);
        carry /= 2;
    }
    return str.reverse().toString();
}

415 字符串加法

思路同上

public String addStrings(String num1, String num2) {
    StringBuilder str = new StringBuilder();
    int carry = 0, i = num1.length() - 1, j = num2.length() - 1;
    while (carry == 1 || i >= 0 || j >= 0) {
        int x = i < 0 ? 0 : num1.charAt(i--) - '0';
        int y = j < 0 ? 0 : num2.charAt(j--) - '0';
        str.append((x + y + carry) % 10);
        carry = (x + y + carry) / 10;
    }
    return str.reverse().toString();
}

相遇问题

462 改变数组元素使所有的数组元素都相等

每次可以对一个数组元素加一或者减一,求最小的改变次数。这是个典型的相遇问题,移动距离最小的方式是所有元素都移动到中位数。
理由如下:设 m 为中位数。a 和 b 是 m 两边的两个元素,且 b > a。要使 a 和 b 相等,它们总共移动的次数为 b - a,这个值等于 (b - m) + (m - a),也就是把这两个数移动到中位数的移动次数。设数组长度为 N,则可以找到 N/2 对 a 和 b 的组合,使它们都移动到 m 的位置。
先排序,时间复杂度:O(NlogN)

public int minMoves2(int[] nums) {
    Arrays.sort(nums);
    int move = 0;
    int l = 0, h = nums.length - 1;
    while (l <= h) {
        move += nums[h] - nums[l];
        l++;
        h--;
    }
    return move;
}

使用快速选择找到中位数,时间复杂度 O(N)

public int minMoves2(int[] nums) {
    int move = 0;
    int median = findKthSmallest(nums, nums.length / 2);
    for (int num : nums) {
        move += Math.abs(num - median);
    }
    return move;
}

private int findKthSmallest(int[] nums, int k) {
    int l = 0, h = nums.length - 1;
    while (l < h) {
        int j = partition(nums, l, h);
        if (j == k) {
            break;
        }
        if (j < k) {
            l = j + 1;
        } else {
            h = j - 1;
        }
    }
    return nums[k];
}

private int partition(int[] nums, int l, int h) {
    int i = l, j = h + 1;
    while (true) {
        while (nums[++i] < nums[l] && i < h) ;
        while (nums[--j] > nums[l] && j > l) ;
        if (i >= j) {
            break;
        }
        swap(nums, i, j);
    }
    swap(nums, l, j);
    return j;
}

private void swap(int[] nums, int i, int j) {
    int tmp = nums[i];
    nums[i] = nums[j];
    nums[j] = tmp;
}

多数投票问题

169 数组中出现次数多余n/2的元素

先对数组排序,最中间那个数出现次数一定多于 n / 2。

public int majorityElement(int[] nums) {
    Arrays.sort(nums);
    return nums[nums.length / 2];
}

摩尔投票/对拼消耗算法 Boyer-Moore Majority Vote Algorithm
1.算法原理:先第一个数字假设为众数,然后计算器设为1,比较下个数和次数是否相等,若相等则计数器加一,反之减一。然后看此时计数器值是否为零,若为零,则将当前值设为候选众数
2. 算法前提:数组中一定含有众数
3.应用场景:从一个数组中找出出现半数以上的元素,可变形为出现次数超过1/k次的元素有哪些。
3. 时间复杂度:O(n) 空间复杂度:O(1)

public int majorityElement(int[] nums) {
    int cnt = 0, majority = nums[0];
    for (int num : nums) {
        majority = (cnt == 0) ? num : majority;
        cnt = (majority == num) ? cnt + 1 : cnt - 1;
    }
    return majority;
}

其他数学问题

367 平方数

生成完全平方数做加法,判断是否为完全平方数做减法

public boolean isPerfectSquare(int num) {
    int subNum = 1;
    while (num > 0) {
        num -= subNum;
        subNum += 2;
    }
    return num == 0;
}

326 n次方问题

暴力循环迭代

正则表达式,函数库方法

class Solution {  
     public boolean isPowerOfThree(int n) {   
      return  Integer.toString(n,3).matches("^10*$");
      }
     }

数论知识

public boolean isPowerOfThree(int n) {
    return n > 0 && (1162261467 % n == 0);
}

238 乘积数组

左右列表方法,优化空间在输出数组上进行操作

public int[] productExceptSelf(int[] nums) {
    int n = nums.length;
    int[] products = new int[n];
    Arrays.fill(products, 1);
    int left = 1;
    for (int i = 1; i < n; i++) {
        left *= nums[i - 1];
        products[i] *= left;
    }
    int right = 1;
    for (int i = n - 2; i >= 0; i--) {
        right *= nums[i + 1];
        products[i] *= right;
    }
    return products;
}

628 找出数组中的乘积最大的三个数

利用函数

class Solution {    
public int maximumProduct(int[] nums) {         Arrays.sort(nums);         
int n= nums.length;         
int max1=nums[n-1],max2=nums[n-2],max3=nums[n-3];        
 int min1=nums[0],min2=nums[1];        
  return Math.max(max1*max2*max3,max1*min1*min2);    }}

一次排序过程寻找

public int maximumProduct(int[] nums) {
    int max1 = Integer.MIN_VALUE, max2 = Integer.MIN_VALUE, max3 = Integer.MIN_VALUE, min1 = Integer.MAX_VALUE, min2 = Integer.MAX_VALUE;
    for (int n : nums) {
        if (n > max1) {
            max3 = max2;
            max2 = max1;
            max1 = n;
        } else if (n > max2) {
            max3 = max2;
            max2 = n;
        } else if (n > max3) {
            max3 = n;
        }

        if (n < min1) {
            min2 = min1;
            min1 = n;
        } else if (n < min2) {
            min2 = n;
        }
    }
    return Math.max(max1*max2*max3, max1*min1*min2);
}

部分内容参考自:https://github.com/CyC2018/CS-Notes/blob/master/notes/Leetcode%20%E9%A2%98%E8%A7%A3%20-%20%E6%95%B0%E5%AD%A6.md

您可能感兴趣的与本文相关的镜像

Stable-Diffusion-3.5

Stable-Diffusion-3.5

图片生成
Stable-Diffusion

Stable Diffusion 3.5 (SD 3.5) 是由 Stability AI 推出的新一代文本到图像生成模型,相比 3.0 版本,它提升了图像质量、运行速度和硬件效率

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值