力扣——质数排列思路分析

题目描述:

请你帮忙给从 1 到 n 的数设计排列方案,使得所有的「质数」都应该被放在「质数索引」(索引从 1 开始)上;你需要返回可能的方案总数。

让我们一起来回顾一下「质数」:质数一定是大于 1 的,并且不能用两个小于它的正整数的乘积来表示。

由于答案可能会很大,所以请你返回答案 模 mod 10^9 + 7 之后的结果即可。

示例 1:

输入:n = 5
输出:12
解释:举个例子,[1,2,5,4,3] 是一个有效的排列,但 [5,2,3,4,1] 不是,因为在第二种情况里质数 5 被错误地放在索引为 1 的位置上。
示例 2:

输入:n = 100
输出:682289015

提示:

1 <= n <= 100

解题思路1:关于本题的思考,我觉得应该分以下三步进行解题:

  • 1.应该找出1-n中有多少质数
  • 2.给非质数做全排列
  • 3.排列完的值乘以质数的全排列

所遇问题1:我自认为由于数字庞大,所以可以利用到java当中的BigInteger类的方法进行计算,但是虽然通过了测试,但是导致运行效率太低,只有空间占用率达到100%,但是时间却只有百分之五;

public int numPrimeArrangements(int n) {
		//首先要知道100以内哪些是质数
        int[] flag = {0,1,1,0,1,0,1,0,0,0,
                      1,0,1,0,0,0,1,0,1,0,
                      0,0,1,0,0,0,0,0,1,0,
                      1,0,0,0,0,0,1,0,0,0,
                      1,0,1,0,0,0,1,0,0,0,
                      0,0,1,0,0,0,0,0,1,0,
                      1,0,0,0,0,0,1,0,0,0,
                      1,0,1,0,0,0,0,0,1,0,
                      0,0,1,0,0,0,0,0,1,0,
                      0,0,0,0,0,0,1,0,0,0};
        BigInteger res = new BigInteger("1");
        long t = (int)Math.pow(10,9)+7;
        BigInteger math = new BigInteger(String.valueOf(t));
        //求得非质数的个数
        int add = 0;
        for (int i = 0; i < n; i++) {
            if(flag[i] == 1)
                add++;
        }
        //求得质数的个数
        int bdd = n-add;
        //对非质数进行全排列
        while (add > 1){
            BigInteger temp = new BigInteger(String.valueOf(add));
            res = res.multiply(temp);
            add--;
        }
        //对质数进行全排列
        while (bdd > 1){
            BigInteger temp = new BigInteger(String.valueOf(bdd));
            res = res.multiply(temp);
            bdd--;
        }
        //将结果除以相应的数
        res = res.remainder(math);
        return res.intValue();
    }

解题思路3:最后我在浏览解题评论区当中发现了超级优化的解题思路,原作者是这样解释他的思路的:代码详解

public int numPrimeArrangements(int n) {
        int[] zhishu={
            2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,
            83,89,97
        };
        //计算质数个数
        int nzhishu=0;
        for(int c:zhishu){
            if(n>=c){
                nzhishu++;
            }
        }
        //计算非质数的个数
        int nfeizhishu=n-nzhishu;
        long ans=1;
        for(int i=nfeizhishu;i>1;i--){
            ans=ans*i%1000000007;
        }
        for(int i=nzhishu;i>1;i--){
            ans=ans*i%1000000007;
        }
        return (int)ans%1000000007;
    }

代码理解:其实作者的思路和我一样,但是他没有利用BigInteger类进行大数相乘,而是直接将结果除以相应的值进行相加求和最后输出。
学习收获
1.赋值:

BigInteger a=new BigInteger(“1”);

BigInteger b=BigInteger.valueOf(1);

2.运算:

① add(); 大整数相加
BigInteger a=new BigInteger(“23”);
BigInteger b=new BigInteger(“34”);
a. add(b);

②subtract(); 相减
③multiply(); 相乘
④divide(); 相除取整
⑤remainder(); 取余
⑥pow(); a.pow(b)=a^b
⑦gcd(); 最大公约数
⑧abs(); 绝对值
⑨negate(); 取反数
⑩mod(); a.mod(b)=a%b=a.remainder(b);

3.BigInteger构造函数:
一般用到以下两种:
BigInteger(String val);
将指定字符串转换为十进制表示形式;
BigInteger(String val,int radix);
将指定基数的 BigInteger 的字符串表示形式转换为 BigInteger
4.基本常量:
A=BigInteger.ONE 1
B=BigInteger.TEN 10
C=BigInteger.ZERO 0

5.n.compareTo(BigInteger.ZERO)==0 /相当于n == 0/

6.if(a[i].compareTo(n)>=0 &&a[i].compareTo(m)<=0) // a[i]>=n && a[i]<=m

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值