数学题目系列(一)|丑数|各位和|埃氏筛|欧拉筛

news2024/11/25 20:48:46

一.丑数

链接:丑数
在这里插入图片描述
分析:

  • 丑数只有2,3,5这三个质因数,num = 2a + 3b + 5c
  • 也就是一个丑数是由若干个2,3,5组成,那么丑数除以这若干个数字最后一定变为1

代码

class Solution {
    public boolean isUgly(int n) {
        if (n <= 0) return false;

        int[] factors = { 2, 3, 5 };
        for (int factor : factors)
            while (n % factor == 0)
                n /= factor;

        return n == 1;
    }
}

二.丑数II

链接:丑数II
在这里插入图片描述
分析

  • 最容易想到的思路是暴力解法,因为在上一题中已经知道判断一个丑数的方法,但是时间复杂度太高,不能通过所有样例

暴力解法(无法通过所有样例)

class Solution {
    private boolean isUgly(int n) {
        int[] factors = {2,3,5};
        for(int factor : factors)
            while(n % factor == 0)
                n /= factor;

        return n == 1;
    }
    public int nthUglyNumber(int n) {
        int ret = 0, cnt = 0;
        for(int i = 1;;i++) {
            if(isUgly(i)) cnt++;
            if(cnt == n) return i;
        }
    }
}
  • 要取出第n大的丑数,可以使用优先级队列来存储丑数,丑数非常容易获得,就是由前一个丑数分别乘2,3,5所得
  • 首先创建最小堆,堆顶元素为最小的丑数
  • 初始化最小堆,堆顶元素为最小的丑数1
  • 取出堆顶元素x,第几次取出就是第几大的丑数
  • x是丑数,那么2x,3x,5x也都是丑数,将这三个数存储到优先级队列之中
  • 在这个过程中可能会出现重复元素,可以使用哈希表来去重
  • 这样,当第n次取出堆顶元素x时,x就是第n大的丑数

代码

class Solution {
    public int nthUglyNumber(int n) {
        int[] factors = {2, 3, 5};
        Set<Long> set = new HashSet<>();
        PriorityQueue<Long> q = new PriorityQueue<>();

        set.add(1L);
        q.add(1L);

        for(int i = 1; i < n; i++) {
            long top = q.poll();
            for(int factor : factors){
                long next = top * factor;
                if(set.add(next))
                    q.add(next); 
            }
        }

        return (int)q.poll().longValue();
    }
}

注意:

  1. 注意Long和long是不同的,Long是包装类,long是基本类型
  2. Java中,基本类型之间可以直接进行强制类型转换(int x = (int)long)
  3. 基本类型和其对应的包装类型在底层是通过方法进行转换的,但是在JDK5之后,编译器会自动帮助我们完成这个过程,也就是拆箱和装箱
  4. 包装类不能直接转换为另一个包装类或原始数据类型,必须先进行拆箱或装箱
  5. Long 不能直接转换为 int,因为它们是不同的类型,必须先将 Long 拆箱为 long,然后再转换为 int。
  6. Long转化为long是通过longvalue方法实现

三.各位相加

链接:各位相加
在这里插入图片描述
分析

  • 模拟思路:不断获得每一位,然后计算各位和,直到最后的结果是个位数

代码

class Solution {
    // 求各位和
    private int bitSum(int n) {
        int ret = 0;
        while (n > 0) {
            ret += n % 10;
            n /= 10;
        }

        return ret;
    }

    public int addDigits(int num) {
        int ret = num;
        while(ret / 10 != 0) {
            ret = bitSum(ret);
        }

        return ret;
    }
}

数学方法
看推导:
在这里插入图片描述

  • 核心在于:num和其各位和 MOD9同余
  • 进而推导出num和最后的结果MOD9同余

代码

class Solution {
    public int addDigits(int num) {
        if(num == 0) return 0;
        if(num % 9 == 0) return 9;
        return num % 9;
    }
}

四.计数质数

暴力解法(超时)

class Solution {
    private boolean isPrime(int n) {
        for(int i = 2; i <= Math.sqrt(n); i++){
            if(n % i == 0)
                return false;
        }

        return true;
    }
    public int countPrimes(int n) {
        int cnt = 0;
        for(int i = 2; i < n; i++)
            if(isPrime(i))
                cnt++;
        return cnt;
    }
}

埃氏筛

  • 核心:如果x是质数,则2x,3x,4x,5x…一定不是质数
  • 利用这个原理就能灵活处理很多问题

代码

class Solution {
    public int countPrimes(int n) {
        int[] is_prime = new int[n];// 标记第i个数是否是质数
        Arrays.fill(is_prime,1);// 默认全是质数

        int ret = 0;// 记录结果
        for(int i = 2; i < n; i++) {
            if(is_prime[i] == 1) {
                ret += 1;
                if((long)i*i < n)
                    for(int k = i * i; k < n; k += i)
                        is_prime[k] = 0;
            }
        }

        return ret;
    }
}

线性筛

  • 埃氏筛其实还存在冗余的地方,比如12这个数字,被2,4,6都删除过一次,这就是冗余操作,使用线性筛可以解决这个问题
  • 线性筛的核心在于:对于一个数x,x乘以小于x的所有质数的结果一定是合数,将这些结果标记为非质数即可,但是发现这样的删除过程仍然存在冗余操作,问题及解决方案如下

在这里插入图片描述
代码:

class Solution {
    public int countPrimes(int n) {
        List<Integer> list = new ArrayList<>();// 存储之前出现的所有质数
        int[] is_prime = new int[n];
        Arrays.fill(is_prime,1);

        int ret = 0;
        for(int i = 2; i < n; i++) {
            if(is_prime[i] == 1){
                list.add(i);
                ret++;
            }

            for(int k : list){
                if(k*i >= n) break;
                is_prime[k*i] = 0;
                if(i % k == 0) break;// k是i的最小质因数
            }
        }

        return ret;
    }
}

三种算法的时间复杂度对比(数据量大)

  • 线性筛 > 埃氏筛 > 暴力解法

对比实验:求2-n之间所有的质数
代码:

package org.example;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

// 打印2-n之间的所有质数
public class Demo2 {
    // 埃氏筛
    public static void Eratosthenes(int n) {
        List<Integer> list = new ArrayList<>();
        int[] is_prime = new int[n + 1];
        Arrays.fill(is_prime, 1);

        for(int i = 2; i <= n; i++) {
            if(is_prime[i] == 1){
                list.add(i);
                if((long)i*i <= n)
                    for(int k = i*i; k <= n; k += i)
                        is_prime[k] = 0;
            }
        }
    }

    // 暴力解法
    public static void isPrime(int n){
        List<Integer> list = new ArrayList<>();
        for(int i = 2; i<= n; i++){
            if(is_prime(i))
                list.add(i);
        }
    }

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

    // 线性筛
    public static void Euler_prime(int n){
        List<Integer> list = new ArrayList<>();
        int[] is_prime = new int[n + 1];
        Arrays.fill(is_prime, 1);

        for(int i = 2; i <= n; i++) {
            if(is_prime[i] == 1)
                list.add(i);
            for(int k : list){
                if(k*i > n) break;
                is_prime[k*i] = 0;
                if(i % k == 0) break;// k是i的最小质因数
            }
        }
    }


    public static void main(String[] args) {
        int n = 200000000;
        long start1 = System.currentTimeMillis();
        Eratosthenes(n);
        long end1 = System.currentTimeMillis();
        System.out.println("埃氏筛时间:" + (end1 - start1));

        long start2 = System.currentTimeMillis();
        isPrime(n);
        long end2 = System.currentTimeMillis();
        System.out.println("暴力时间:" + (end2 - start2));

        long start3 = System.currentTimeMillis();
        Euler_prime(n);
        long end3 = System.currentTimeMillis();
        System.out.println("线性筛时间:" + (end3 - start3));
    }
}

打印结果:
在这里插入图片描述

  • 只有当数据量特别大时,才符合上述时间复杂度的排序,对于计算机来说,取模%是一个非常耗时的操作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1795730.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

27-unittest之断言(assert)

在测试方法中需要判断结果是pass还是fail&#xff0c;自动化测试脚本里面一般把这种生成测试结果的方法称为断言&#xff08;assert&#xff09;。 使用unittest测试框架时&#xff0c;有很多的断言方法&#xff0c;下面介绍几种常用的断言方法&#xff1a;assertEqual、assert…

基于javacv ffmpeg 使用原生ffmpeg命令

基于javacv ffmpeg 使用原生ffmpeg命令 1. ffmpeg2. ffprobe 相关阅读&#xff1a; javacv ffmpeg使用笔记 测试过程中&#xff0c;发现ffmpeg-6.0-1.5.9-linux-x86_64.jar 存在问题&#xff08;ffmpeg原生命令执行失败&#xff09;&#xff0c;降级到ffmpeg-5.1.2-1.5.8-linux…

【Python报错】已解决ValueError: If using all scalar values, you must pass an index

成功解决“ValueError: If using all scalar values, you must pass an index”错误的全面指南 在Pandas库中&#xff0c;当你尝试创建一个新的DataFrame或Series时&#xff0c;如果所有值都是标量&#xff08;scalar&#xff0c;即单个值而非列表、数组或Series&#xff09;…

Vuforia AR篇(六)— Mid Air 半空识别

目录 前言一、什么是Mid Air&#xff1f;二、使用步骤三、示例代码四、效果 前言 增强现实&#xff08;AR&#xff09;技术正在改变我们与数字世界的互动方式。Vuforia作为先进的AR开发平台&#xff0c;提供了多种工具来创造引人入胜的AR体验。其中&#xff0c;Mid Air功能以其…

UE5-AI

AI角色 角色控制器 AI角色必须要一个角色控制器 角色控制器最基本只需要执行行为树&#xff0c;在EventOnPossess后runBehaviorTree 如果要的是一个角色&#xff0c;可以创建一个Character&#xff0c;在类默认设置中可以找到 Pawn->AIControllerClass&#xff0c;在这里…

Linux网络的DHCP配置

文章目录 DHCP配置DHCP流程简述DHCP优点DHCP的分配方式DHCP的租约过程DHCP配置实验实验1实验2 DHCP配置 DHCP&#xff1a;动态主机配置协议 服务端和客户端 服务端&#xff1a;server&#xff0c;提供某种特定的服务 客户端&#xff1a;client&#xff0c;使用服务端提供的服…

代码随想录第26天|回溯part6 不需要搜索整棵树的回溯二维搜索

332.重新安排行程 难题&#xff0c;自己写的代码没过&#xff0c;但我认为逻辑没有问题 class Solution { public:vector<string> res;bool pruning(vector<string> res, vector<string> path) {if (res.size() 0)return true;bool check false;for (int …

fastapi学习前置知识点

前置知识点 FastApi&#xff1a;一个用于构建API的现代、快速&#xff08;高性能&#xff09;的web框架。 FastApi是建立在Pydantic和Starlette基础上&#xff0c;Pydantic是一个基于Python类型提示来定义数据验证、序列化和文档的库。Starlette是一种轻量级的ASGI框架/工具包…

Matlab|【重磅】配电网故障重构/孤岛划分

目录 1 主要内容 1.1 背景 1.2 流程图 2 部分代码 3 程序结果 4 下载链接 1 主要内容 程序主要复现《基于GA_BFGS算法的配电网故障恢复性重构研究_郑海广》&#xff0c;采用matlab编程软件实现&#xff0c;依据网络结构和DG供电方式对配电网进行孤岛划分&#xff0c;将含…

避免使用for循环操作高维数组:numpy.apply_along_axis用法

文章目录 场景实际操作编写相关函数np.apply_along_axis 场景 设想我有一列高维向量&#xff0c;读取之后的数据都是字符串变量&#xff0c;我需要把这些字符串数据转换为复数之后求绝对值 实际操作 在使用pd.read_csv()读取数据之后&#xff0c;将这一列数据转换为numpy数…

Python高阶学习记录

文章导读 阅读本文需要一定的python基础&#xff0c;部分知识点是对python入门篇学习记录和python并发编程学习记录的深入探究&#xff0c;本文记录的Python知识点包括函数式编程&#xff0c;装饰器&#xff0c;生成器&#xff0c;迭代器&#xff0c;正则表达式&#xff0c;内存…

面试题------>JVM虚拟机!!!

一、Java对象内存布局 二、JVM 内存结构 程序计数器: 线程私有的(每个线程都有一个自己的程序计数器),是一个指针.代码运行,执行命令.而每个命令都是有行号的,会使用程序计数器来记录命令执行到多少行了.记录代码执行的位置. Java虚拟机栈: 线程私有的(每个线程都有一个自己…

【计算机网络】计算机网络的组成与功能

计算机网络的组成与功能 导读一、计算机网络的组成1.1 从组成方式上1.1.1 硬件1.1.2 软件1.1.3 协议 1.2 从工作方式上1.3 从功能组成上 二、计算机网络的功能2.1 数据通信2.2 资源共享2.3 分布式处理2.4 提高可靠性2.5 负载均衡2.6 其它 结语 导读 大家好&#xff0c;很高兴又…

可视化数据科学平台在信贷领域应用系列五:零代码可视化建模

信贷风控模型是金融机构风险管理的核心工具&#xff0c;在信贷风险管理工作中扮演着至关重要的角色。随着信贷市场的环境不断变化&#xff0c;信贷业务的风险日趋复杂化和隐蔽化&#xff0c;开发和应用准确高效的信贷风控模型显得尤为重要。信贷风险控制面临着越来越大的挑战和…

orbslam2代码解读(1):数据预处理过程

写orbslam2代码解读文章的初衷 首先最近陆陆续续花了一两周时间学习视觉slam&#xff0c;因为之前主要是做激光slam&#xff0c;有一定基础所以学的也比较快&#xff0c;也是看完了视觉14讲的后端后直接看orbslam2的课&#xff0c;看的cvlife的课&#xff08;课里大部分是代码…

规则引擎LiteFlow发布v2.12.1版本,决策路由特性

个人博客&#xff1a;无奈何杨&#xff08;wnhyang&#xff09; 个人语雀&#xff1a;wnhyang 共享语雀&#xff1a;在线知识共享 Github&#xff1a;wnhyang - Overview 简介 标题其实是不准确的&#xff0c;了解过的会知道在LiteFlow的2.12.0已经有了决策路由的特性&…

python数据文件处理库-pandas

内容目录 一、pandas介绍二、数据加载和写出三、数据清洗四、数据转换五、数据查询和筛选六、数据统计七、数据可视化 pandas 是一个 Python提供的快速、灵活的数据结构处理包&#xff0c;让“关系型”或“标记型”数据的交互既简单又直观。 官网地址: https://pandas.pydata.o…

树形表/树形数据接口的开发

数据表格式 需要返回的json格式 点击查看json数据 [{"childrenTreeNodes" : [{"childrenTreeNodes" : null,"id" : "1-1-1","isLeaf" : null,"isShow" : null,"label" : "HTML/CSS","na…

14.pinia初始与安装

pinia初始与安装 pinia官网 https://pinia.vuejs.org/ https://pinia.vuejs.org/introduction.html pinia安装 npm install pinia main.ts引入pinia import { createApp } from vue // import ./style.css import App from ./App.vue import router from ./router/index // …

LangChain :构建个人AI代理从这里开始

LangChain&#xff0c;一个强大的工具&#xff0c;允许根据用户输入创建对语言模型和其他工具的复杂调用链。就像拥有一个私人助理&#xff0c;可以根据手头的任务做出决定。本文来分享一下在 LangChain 中使用 Agents 的心路历程。 LangChain中代理的概念 在 LangChain 中&a…