力扣题解 3233. 统计不是特殊数字的数字数量(中等)

Problem: 3233. 统计不是特殊数字的数字数量

文章目录

题目重述

给定两个正整数 ( l ) 和 ( r ),我们需要找出在区间 ([l, r]) 内的数字中,不是特殊数字的数量。一个数字被称为特殊数字,当且仅当它有且仅有两个真因数。根据定义,真因数是指除了数字本身之外的所有正因数。

关键词提取

  • 正整数
  • 真因数
  • 特殊数字
  • 区间 ([l, r])
  • 数量

特殊数字分析

  1. 因子的性质

    • 一个整数的因子通常成对出现。例如,考虑数字 12,其因子有 1, 2, 3, 4, 6, 和 12,这些因子可以成对匹配:1 和 12,2 和 6,3 和 4。因此,因子的数量通常是偶数。
    • 然而,对于完美的平方数(如 4, 9, 16 等),存在一个因子是它自身的平方根(例如,4 的平方根是 2),导致该数字的因子数量不成对,从而使得平方数的因子总数是奇数。
  2. 特殊数字的特征

    • 由上述性质可得,若某个数是特殊数字,则它必须是一个平方数。
    • 进一步分析,若这个特殊数字被表示为 ( n^2 )(其中 n 是正整数),当我们去掉这个数字本身(( n^2 ))和 1 后,该数字只剩下一个因子。为了说明这一点,我们可以表示 ( n^2 ) 的因子为 1、( n ) 和 ( n^2 )。去除 1 和 ( n^2 ) 后,剩下的因子就是 ( n )。
  3. 质数的要求

    • 由于 ( n ) 是剩余的唯一因子,而根据特殊数字的定义,这个因子也必须是质数。因此,特殊数字的形式可以表示为一个质数的平方。

思路一:使用质数筛法

java 复制代码
class Solution {  
    public int nonSpecialCount(int l, int r) {  
        // 计算上限,即 r 的平方根加 1
        int upperLimit = (int) Math.sqrt(r) + 1;
        boolean[] isPrime = new boolean[upperLimit + 1];
        
        // 初始化 isPrime 数组,将所有值设为 true
        for (int i = 2; i <= upperLimit; i++) {
            isPrime[i] = true;
        }
        
        // 埃拉托斯特尼筛法寻找质数
        for (int i = 2; i * i <= upperLimit; i++) {
            if (isPrime[i]) {
                // 将 i 的所有倍数标记为非质数
                for (int j = i * i; j <= upperLimit; j += i) {
                    isPrime[j] = false;
                }
            }
        }

        // 收集特殊数字(即质数的平方)
        ArrayList<Integer> specialNumbers = new ArrayList<>();
        for (int i = 2; i <= upperLimit; i++) {
            if (isPrime[i]) {
                int square = i * i;
                // 判断平方是否在区间 [l, r] 内
                if (square >= l && square <= r) {
                    specialNumbers.add(square);
                }
            }
        }

        // 计算非特殊数字的数量
        int totalNumbers = r - l + 1;
        int nonSpecialCount = totalNumbers - specialNumbers.size();

        return nonSpecialCount;
    }
}

思路二:使用映射 + 质数筛法

java 复制代码
class Solution {  
    public int nonSpecialCount(int l, int r) {  
        // 计算上限,即 r 的平方根加 1
        int upperLimit = (int) Math.sqrt(r) + 1;
        boolean[] isPrime = new boolean[upperLimit + 1];
        
        // 初始化 isPrime 数组,将所有值设为 true
        for (int i = 2; i <= upperLimit; i++) {
            isPrime[i] = true;
        }
        
        // 埃拉托斯特尼筛法寻找质数
        for (int i = 2; i * i <= upperLimit; i++) {
            if (isPrime[i]) {
                // 将 i 的所有倍数标记为非质数
                for (int j = i * i; j <= upperLimit; j += i) {
                    isPrime[j] = false;
                }
            }
        }

        // 使用 HashMap 存储特殊数字(即质数的平方)
        HashMap<Integer, Integer> specialCountMap = new HashMap<>();
        for (int i = 2; i <= upperLimit; i++) {
            if (isPrime[i]) {
                int square = i * i;
                // 判断平方是否在区间 [l, r] 内
                if (square >= l && square <= r) {
                    specialCountMap.put(square, specialCountMap.getOrDefault(square, 0) + 1);
                }
            }
        }

        // 计算非特殊数字的数量
        int totalNumbers = r - l + 1;
        int nonSpecialCount = totalNumbers - specialCountMap.size();

        return nonSpecialCount;
    }
}
相关推荐
Brilliantwxx1 分钟前
【C++】Stack和Queue(初认识和算法题OJ)
开发语言·c++·笔记·算法
fffzd4 分钟前
C++入门(二)
开发语言·c++·算法·函数重载·引用·inline内联函数·nullptr
傻瓜搬砖人5 分钟前
c语言绿皮书第三版第十章习题
c语言·开发语言·算法
Lazionr9 分钟前
数据结构堆详解:原理、实现与应用
数据结构·算法
故事和你9114 分钟前
蓝桥杯-2026年C++B组省赛
开发语言·数据结构·c++·算法·蓝桥杯·动态规划·图论
星恒随风15 分钟前
C语言算法复杂度详解:时间复杂度与空间复杂度一篇讲透
c语言·算法
傻瓜搬砖人17 分钟前
c语言绿皮书第三版第十一章习题
c语言·开发语言·算法·谭浩强·绿皮书第三版
计算机安禾19 分钟前
【c++面向对象编程】第3篇:类与对象(二):构造函数与析构函数
开发语言·c++·算法
小年糕是糕手20 分钟前
【C++】vector 不踩坑指南:用法、底层实现与迭代器失效解析
c++·算法
SilentSamsara1 小时前
生成器完全指南:`yield` 与惰性求值的工程价值
linux·开发语言·python·算法·机器学习·青少年编程