复试06-数字问题

数学问题,围绕着数理逻辑的问题

  • 进制转换
  • GCD&LCM(最大公约束,最小公倍数)
  • 质数&质数因子
  • 快速幂
  • 矩阵&矩阵快速幂
  • 高精度整数

进制转换

  • 10->N
  • M->10
  • M->N

在这里插入图片描述

例题6.1 二进制数

在这里插入图片描述
找到一个偷懒的办法。

10进制转化其他进制对应的方法,参数:n(原10进制数据),r(进制),返回值
10进制转2进制Integer.toBinaryString(n);一个二进制字符串.
10进制转8进制Integer.toOctalString(n);一个八进制字符串
10进制转16进制Integer.toHexString(n);一个16进制字符串
10进制转 r 进制Integer.toString(100, 16);一个r进制字符串
radix进制的字符串s转10进制Integer.parseInt((String) s,(int) radix);Int

太偷懒了,不可以这样,万一是线上面试,抽题来问,那我不是凉凉?

所以说我们还是来简单计算一下。

static LinkedList Convert(int n){
        LinkedList<Integer> LinkedList = new LinkedList<>();
        while (n!=0){
            LinkedList.addFirst(n%2);
            n/=2;
        }
        return LinkedList;
    }

如果这里采用的数字,就需要逆序输出。
10进制转换为2进制就需要,先%2取得余数,再/2。
比方说

在这里插入图片描述
这surface笔真的难用,复试完了就去找微软保修换了,不知道是机子得问题还是笔得问题。

注意得就是顺序问题啊,专门挑选了个不对称得二进制数来对比的。

如果是8进制,16进制只要把%2,/2换成%8,/8就好了,最后记得转换为String。
如果是转换为16进制,就记得把高于10的数字转换一下,10-16转换为A-F。

    static char IntToChar(int target){
        if(target<10){
            return (char) ('0'+target);
        }else {
            return (char)(target-10+'A');
        }
    }
例题GCD & LCM

最大公约数,最小公倍数

在这里插入图片描述
上面就是暴力的线性查找。
辗转相除法(欧几里得算法)
在这里插入图片描述

原理就是:

a = g*l
b = g*m
a = b*k + r
g*l = g*m*k + r
r = g*(l-m*k)
这里可以得到a和b的最大公约数,同时也是r的最大公约数

这样可以从a,b的最大公约数问题,转换为b和r的最大公约数问题
依次递归就可以不断循环。

例题6.5

在这里插入图片描述

static int GCD(int a, int b){
		if(a<b){
            int temp = a;
            a=b;
            b=temp;
        }
        if(b==0){
            return a;
        }else {
            return GCD(b,a%b);
        }
    }

记得a,b的位置哦。a一定大于b的,否则就要交换。

最小公倍数

在这里插入图片描述
可以通过上面的公式转换为求最大公倍数的

例题6.6 最小公倍数

在这里插入图片描述
emmm就上面的代码改一改就好啦。

例题6.7质数

对于穷举法来说,只需要遍历 n \sqrt{n} n 即可。
下面的是约数。
在这里插入图片描述
所以这个方法的思路就是把数据量从O(n)的时间复杂度变成了O( n \sqrt{n} n )的时间复杂度。
在这里插入图片描述

static boolean Judge(int n){
        if(n<2){
            return false;
        }
        int bound = (int)Math.sqrt(n)+1;
        for (int i = 2; i <= bound; i++) {
            if(n%i==0)return false;
        }
        return true;
    }

那么这里我们将题目升级一下,

判断0-n内的所有质数,如果我们采用刚才的方法,那么一定会出问题的。时间复杂度会变成O(n* n \sqrt{n} n )的。

这里了解到了一个叫质数筛法的方法,我靠,和我以前自己想到的一个方法一样。每次遍历的时候,只需要遍历比当前数小的质数即可。
为什么?

假设我们求得数是91,那么如果遍历了2不是,就不用遍历4,6,8,等等2的倍数了,如果遍历了5不是,那么就不用遍历10,15,20等5的倍数了。依次推类,我们需要一个数据结构来存储这些质数元素。

也可以这样说,设计一个表,每次去除质数的倍数个的元素。即可。两种方法都可以。

我更喜欢我设计的那个方法。

static void JudgeArrays(int n){
        ArrayList<Integer> arrayList= new ArrayList<Integer>();
        arrayList.add(2);
        for (int i = 3; i < n; i++) {
            for (int j = 0; j < arrayList.size(); j++) {
                if(i % arrayList.get(j)==0) break;
                if(j==arrayList.size()-1) arrayList.add(i);
            }
        }
        System.out.println(arrayList);
    }

有兴趣的可以去了解一下
Miller Rabin算法
Miller Rabin算法的依据是费马小定理。这里就不作过多解释了。
该算法是基于概率来的,也就是俗称的猜。虽然不能100正确,但是如果能保证99%以上的正确率那也是不错的。

我设计那个数据量太大了,不好用。

更高效的质数查找方法
static boolean[] Judege(int num,ArrayList arrayList){
        boolean isPrime[] = new boolean[num];
        for (int i = 0; i < isPrime.length; i++) {
            isPrime[i]=true;//将所有数预制为true
        }
        isPrime[0]=false;
        isPrime[1]=false;
        for (int i = 2; i < isPrime.length; i++) {
            if(!isPrime[i]){//如果为假,就直接跳过本次及以后的数据
                continue;
            }
            arrayList.add(i);
            for (int j = i; j < isPrime.length; j+=i) {//遍历剩余的数据,将其置换为false
                isPrime[j] = false;
            }
        }
        return isPrime;
    }
例题6.6

在这里插入图片描述

质因子分解
在这里插入图片描述

例题6.9

在这里插入图片描述

短除法
短除法一定是除的质数哦

在这里插入图片描述
由于这次数据是109的数据量,所以我们要考虑一下时间ok吗?

其实我们不需要这么多的数据,分析如下

在这里插入图片描述
第一种情况,所有质因素都小于 n \sqrt{n} n 的,
第二种情况,有且仅有一个数大于等于 n \sqrt{n} n 的,
但凡出现两个大于 n \sqrt{n} n 的数,其乘积必定大于其n。

实际测试,用那n n \sqrt{n} n 在数据量大于1000000的时候会很吃力,就算是1000000都等了很多秒。
刚才实验了一下,还是第一种更快,1000000级别基本上秒出,就算是再加2个00也是仅仅等了3秒多。效率更高。

static int NumberOfPrimeFactor(int num,ArrayList<Integer> arrayList){
        int answer = 0;
        for (int i = 0; i < arrayList.size(); i++) {
            int factor =  arrayList.get(i);
            if(num<factor){
                break;
            }
            int current = 0;//计数器
            while (num % factor == 0){//满足目标条件
                current++;
                num /= factor;
            }
            answer+=current;
        }
        if(num>1){//如果最后一个数除不尽
            answer++;
        }
        return answer;
    }

记住我们这里是有重复值的。
在这里插入图片描述

约数的个数

在这里插入图片描述
在这里插入图片描述

例题6.7

在这里插入图片描述
这里思路都差不多,只需要增加或者修改属性参数标志符等等,就好了.


下面就是快速幂
在这里插入图片描述
这里需要额外拓展一个知识。
任何一个数n都可以被分为

n = 2i+2j+…+2k

因为任何一个数都可以用二进制的形式表达出来

在这里插入图片描述
然后我们就能在O(logn)内算出ab的内容
 在这里插入图片描述

例题6.10

在这里插入图片描述
一般来说java有内置math.pow()函数,但是怕被问起来,所以说我们就写一个方法高效的实现

static int QuickPower(int x, int n) {
        int answer = 1;
        while (n != 0) {
            if (n % 2 == 1) {
                answer *= x;//计算前面的值
            }
            n /= 2;
            x*=x;//升位
        }
        return answer;
}

这里其实是求n的二进制数,
在这里插入图片描述
所以说要注意的就是升位的x*=x;这里来说,我们是因为

在这里插入图片描述
右上角的次方数,是逐步递增2倍的,也就是a2倍的数据。所以每次位移之后都要把当前待乘的数升级。

矩阵&快速矩阵幂

矩阵这一部分来说,一般很简单

  • 矩阵相加
  • 矩阵相乘
  • 矩阵转置
  • 矩阵求幂

以上几个为常考

矩阵相加

在这里插入图片描述

蛮简单的

class Matrix{
    int matrix[][];

    int row;
    int cow;

    public Matrix(int row,int cow) {
        this.row = row;
        this.cow = cow;
        matrix = new int[row][cow];
        for (int i = 0; i < row; i++) {
            Arrays.fill(matrix[i],3);
        }
    }

    public Matrix ADD (Matrix M){
        Matrix X = new Matrix(row,cow);
        if(M.row!=this.row || M.cow!=this.cow)
            X=null;
        else {

            for (int i = 0; i < this.row; i++) {
                for (int j = 0; j < this.cow; j++) {
                    X.matrix[i][j]=M.matrix[i][j]+this.matrix[i][j];
                }
            }
        }
        return X;
    }
}

也可以不用类,直接用数组进行,可以简化。
同理
除了加,还有乘。(减和除化为加和乘就好了)
乘法仅仅需要把x[i][j]*x[j][i]就好了。行×列

例题6.11

在这里插入图片描述
仅仅需要注意输入输出就好了。
在这里插入图片描述
转置也很简单。

在这里插入图片描述
求幂也不说了哈,理解为两个相同的矩阵进行乘即可,和上面原理一致。

高精度整数

int:2147483647
long long :9223372036854775807

如果更大会怎么样呢,我们建议在java用BigInteger和BigDecimal等等。
c和c++就需要更多的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值