每日一题:H指数

继续给大家带来每日一题

题目描述

给你一个整数数组 citations ,其中 citations[i] 表示研究者的第 i 篇论文被引用的次数。计算并返回该研究者的 h 指数。

根据维基百科上 h 指数的定义:h 代表“高引用次数” ,一名科研人员的 h 指数 是指他(她)至少发表了 h 篇论文,并且 至少 有 h 篇论文被引用次数大于等于 h 。如果 h 有多种可能的值,h 指数 是其中最大的那个。

题目示例

在这里插入图片描述

这道题目读起来可能有些拗口,我给大家翻译翻译,题目的核心就是找一个最大值h,使其能够满足

  • h<=数组大小
  • 数组里大于等于h的元素个数m,要求m>=h

如下图所示:
在这里插入图片描述

无论什么思路,其核心就是找上面的两个关系:

1.h<=数组大小,所以我们最简单粗暴的思路就是从h=1开始统计,直到h=n(数组大小,也就是题目中的论文个数)

2.数组里大于等于h的元素个数m,要求m>=h 这种才是有效的h

以题目中的case为例:

citations=3, 0, 6, 1, 5

  • h=1,满足大于等于1的数字有:3,6,1,5
  • h=2,满足大于等于2的数字有:3,6,5
  • h=3,满足大于等于3的数字有:3,6,5
  • h=4,满足大于等于4的数字有:6,5
  • h=5,满足大于等于5的数字有:6,5
  • h=6,满足大于等于6的数字有6

下面我们接着去找符合满足的数量要大于h

  • h=1,满足的论文数:4 4>=1符合
  • h=2,满足的论文数:3 3>=2符合
  • h=3,满足的论文数 3 3>=3符合
  • h=4,满足的论文数 2 2>=4 不符合
  • h=5,满足的论文数 2 2>=5 不符合
  • h=6,满足的论文数 1 1>=6 不符合

所以取符合的最大h h=3
然后我们接着来看代码实现:
最暴力的解法是:直接按照我们上面的思路来

    public static int hIndex(int[] citations) {
        int n = citations.length;
        Map<Integer, Integer> indexMap = new HashMap<>();
        for (int i = 1; i <= n; i++) {
            for (int j : citations) {
                int count = indexMap.getOrDefault(i, 0);
                if (j >= i) {
                    indexMap.put(i, ++count);
                }
            }
        }
        int max = 0;
        for (Map.Entry<Integer, Integer> entry : indexMap.entrySet()) {
            int h = entry.getKey();
            int count = entry.getValue();
            if (count >= h) {
                max = Math.max(h, max);
            }
        }

        return max;
    }

在这里插入图片描述

我们尝试着优化一下:如:

citations=3, 0, 6, 1, 5

我们先进行排序,排序后:0 1 3 6 5
h=1 我们发现1符合的时候,后面的就不用计算累加了,因为1后面的数组均符合,所以h=1 对应的论文数:n-index(1)=5-1=4

同理h=2 h=3…均可以以这种方式计算

    public static int hIndex2(int[] citations) {
        int n = citations.length;
        Arrays.sort(citations);
        Map<Integer, Integer> indexMap = new HashMap<>();
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < n; j++) {
                if (citations[j] >= i) {
                    indexMap.put(i, n - j);
                    break;
                }
            }
        }
        int max = 0;
        for (Map.Entry<Integer, Integer> entry : indexMap.entrySet()) {
            int h = entry.getKey();
            int count = entry.getValue();
            if (count >= h) {
                max = Math.max(h, max);
            }
        }

        return max;
    }

运行时间:
在这里插入图片描述

但是上面两种方式每次都需要从头开始找,浪费了我们排序的性能带来的便利,所以我们可以用一个索引指向计算下一个h时需要从数组的哪个位置开始读取

citations=3, 0, 6, 1, 5
排序后:0 1 3 6 5

h=1,遍历到index=1的位置
h=2,直接从index=1开始遍历,index=2时找到大于等于2的论文
h=3,直接从index=2开始遍历
依此类推
在这里插入图片描述

上面的三种方式均需要我们去二次遍历map,其实我们在第一次找每个h对应的论文数量时就可以去定位到符合条件的最大h,减少了一次遍历

    public static int hIndex4(int[] citations) {
        int n = citations.length;
        Arrays.sort(citations);
        int j = 0;
        int max = 0;
        for (int i = 1; i <= n; i++) {
            while (j < n) {
                if (citations[j] >= i
                        && (n - j) >= i) {
                    max = Math.max(max, i);
                    break;
                }
                j++;
            }
        }

        return max;
    }

四次改进的耗时对比:
在这里插入图片描述

这道题目并不难,只是想通过这道题目告诉大家不要上来就去尝试最优解,可以逐步推进来提升自己的逻辑思维和算法思维

2021年五一数学建模竞赛C题深度解决方案 问题1:非风险性与风险性异常判定模型 方法改进与实施步骤: 数据预处理与特征工程 数据清洗:使用小波变换去除高频噪声,插值处理缺失值。 多维特征提取: 统计特征:滑动窗口(5分钟)内的均值、方差、偏度、峰度。 时序特征:自相关系数(ACF)、趋势斜率(线性回归拟合)。 频域特征:快速傅里叶变换(FFT)提取主频能量占比。 非风险性异常检测 偶发性波动:采用孤立森林(Isolation Forest)检测残差项的离群点,设置动态阈值(如前1%分位数)。 规律性波动: 使用STL分解提取季节项,通过Lomb-Scargle周期图验证周期性(如每小时/每日周期)。 若波动与周期模式匹配,判定为非风险。 独立性检验: 构建传感器关系网络,基于动态时间规整(DTW)计算两两相似性,定义关联权重。 若某传感器异常时,其邻居节点无显著异常(通过卡方检验),则判定为独立异常。 风险性异常判定 持续性分析: 定义马尔可夫链状态转移模型,计算连续异常状态的转移概率。 若窗口内连续异常概率超过阈值(如95%置信区间),判定为持续性风险。 联动性分析: 采用格兰杰因果检验识别传感器间的因果关系。 结合社区发现算法(如Louvain)检测同步异常簇,若簇内传感器数≥3且因果关系显著,判定为联动风险。 问题2:异常程度量化评价模型 模型构建与优化: 多维度评分指标 波动强度(40%):归一化Z-score绝对值,反映偏离基准的程度。 持续时间(30%):连续异常时间占窗口长度的比例(对数变换增强区分度)。 联动影响(30%): 广度:异常传感器数量(标准化为[0,1])。 深度:异常传感器在网络中的PageRank值(衡量节点重要性)。 非线性评分模型 采用随机森林回归模型,输入上述特征,输出0-100分异常评分。 特征重要性分析:通过Gini指数确定权重,避免人为赋权偏差。 结果展示与验证 Top 5异常时刻示例: 排名 第一高分 第二高分 第三高分 第四高分 第五高分 异常程度得分 95 90 88 85 82 异常时刻 08:15:23 14:30:47 17:10:05 09:55:12 20:45:38 异常传感器 S05, S12 S08, S03 S22, S09 S1
04-16
<think>嗯,用户需要2021年五一数学建模竞赛C题的深度解决方案,特别是关于非风险性和风险性异常判定模型以及异常程度量化评价模型的具体方法和步骤。首先,我得回顾一下题目要求,确保理解正确。题目可能涉及时间序列数据的异常检测,需要区分风险性和非风险性异常,并进行量化评价。 用户提到的数据预处理部分,可能需要处理缺失值、异常值,以及数据分布的问题。根据引用[2],他们使用了箱型图来检测异常值,因为数据不服从正态分布。这可能是一个关键点,因为不同的数据分布需要不同的处理方法。例如,K-S检验用来判断数据是否正态,而箱型图适用于非正态数据。所以在预处理阶段,我需要先检查数据分布,然后选择合适的异常值检测方法。 接下来是特征工程。用户提到了构造时域、频域和统计特征,比如移动平均、傅里叶变换、偏度峰度等。引用[2]中使用了幅度差、噪声水平等特征,这可能适用于电磁辐射和声发射数据。对于时间序列,STL分解和Lomb-Scargle周期图可以帮助提取趋势、季节性和周期性特征。这里需要注意,STL分解适用于有季节性的数据,而Lomb-Scargle适用于非均匀采样的周期检测。需要确认数据是否均匀采样,再决定使用哪种方法。 然后是模型构建。非风险性和风险性异常的判定可能需要分类模型,比如孤立森林、随机森林。引用[2]中的随机森林分类模型准确率很高,可能是一个好的选择。而异常程度量化可能需要回归模型,比如随机森林回归或马尔可夫链模型。用户还提到了格兰杰因果检验,这可能用于分析不同变量之间的因果关系,帮助特征筛选。 关于模型实现步骤,可能需要分阶段处理。首先数据预处理,然后特征提取,接着构建分类模型区分异常类型,再构建回归模型量化异常程度。模型融合或集成学习可能会提升效果,比如结合孤立森林和随机森林的结果。 需要注意的是,用户引用的资料中有一些具体的方法,比如平均数编码、热图等,但这些可能在时间序列数据中不太适用,需要调整。另外,如何定义非风险性和风险性异常?可能需要领域知识或题目给出的定义,比如风险性异常可能导致系统故障,而非风险性可能是自然波动。 在实现细节上,比如使用Python的statsmodels库进行STL分解,或者使用scikit-learn的IsolationForest。对于Lomb-Scargle周期图,可以使用Astropy库。格兰杰因果检验可能需要自己实现或查找合适的库。 可能遇到的挑战包括数据的高维度、非平稳性,以及如何有效结合多个模型的结果。例如,孤立森林可能对高维数据有效,但需要调整参数。随机森林回归可能需要特征重要性分析,以优化模型性能。 最后,模型评估部分,分类模型用准确率、召回率等,回归模型用MSE、R²。同时,可能需要可视化,比如残差图、特征重要性图,来辅助解释模型结果。 总结一下,解决方案的步骤大致是:数据预处理→特征工程→构建分类模型区分异常类型→构建回归模型量化程度→模型评估与优化。需要结合具体的数据特点和题目要求调整方法和参数。</think>### 2021年五一数学建模竞赛C题深度解决方案 --- #### **一、数据预处理** 1. **异常值处理** - 使用箱型图分析非正态分布数据的异常值(参考引用[2]方法) - 结合K-S检验验证数据分布特性,采用修正分布正态化(如Box-Cox变换)处理偏态数据 - 通过孤立森林算法检测高维度数据中的异常样本 2. **缺失值填充** - 对时间序列数据使用STL分解(Seasonal-Trend decomposition using LOESS)提取趋势项和季节项,结合线性插值填补缺失值 - 公式:$$y_t = T_t + S_t + R_t$$,其中$T_t$为趋势项,$S_t$为季节项,$R_t$为残差项 3. **周期性分析** - 应用Lomb-Scargle周期图检测非均匀采样数据的周期性特征 - 代码示例: ```python from astropy.timeseries import LombScargle frequency, power = LombScargle(t, y).autopower() ``` --- #### **二、特征工程** 1. **时域特征** - 构造移动平均、标准差、偏度、峰度等统计量 - 提取极值点密度、突变点检测(如CUSUM算法) 2. **频域特征** - 通过傅里叶变换提取主频成分能量占比 - 公式:$$X(f) = \int_{-\infty}^{\infty} x(t)e^{-j2\pi ft}dt$$ 3. **交叉特征** - 利用格兰杰因果检验(Granger Causality Test)筛选关键变量 - 构建变量间时滞相关系数矩阵(参考引用[1]中的热图方法) --- #### **三、非风险性与风险性异常判定模型** 1. **孤立森林(Isolation Forest)** - 通过随机划分特征空间检测异常,设置阈值区分风险/非风险异常 - 公式:异常得分$s(x) = 2^{-\frac{E(h(x))}{c(n)}}$,其中$h(x)$为路径长度 2. **随机森林分类器** - 使用TreeBagger训练包含100棵决策树的模型(参考引用[2]方法) - 特征重要性排序筛选关键指标(如基尼不纯度下降量) 3. **马尔可夫链状态转移** - 定义正常/异常状态转移概率矩阵,计算风险性异常的稳态概率 --- #### **四、异常程度量化评价模型** 1. **随机森林回归** - 以异常得分为目标变量,构建回归模型量化异常程度 - 评估指标:$$R^2 = 1 - \frac{\sum(y_i - \hat{y}_i)^2}{\sum(y_i - \bar{y})^2}$$ 2. **动态阈值法** - 基于STL分解残差的3σ原则设定动态阈值 - 公式:$$\text{异常程度} = \frac{|R_t| - \mu_R}{\sigma_R}$$ 3. **模型融合** - 加权集成孤立森林、随机森林回归和马尔可夫链输出结果 - 使用Stacking方法优化预测稳定性(参考引用[1]中的模型融合策略) --- #### **五、实现步骤** 1. 数据预处理 → 2. 特征构造 → 3. 训练分类模型 → 4. 回归量化 → 5. 模型融合 **代码框架示例**: ```python from sklearn.ensemble import IsolationForest, RandomForestRegressor # 孤立森林检测异常 iso_forest = IsolationForest(n_estimators=100).fit(X) # 随机森林回归量化 rf_reg = RandomForestRegressor().fit(X_train, y_train) ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZNineSun

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值