CI20.6--求前K个数

本文探讨了在十亿个数中找到最大的一百万个数的有效算法。介绍了三种方法:直接排序、使用大顶堆及快速选择算法。重点讨论了每种方法的时间复杂度及其适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

描述一个算法,在十亿个(n)数中找出前一百万(k)大的数字。假设内存里可以放下十亿个数。

思路:

1、直接排序,然后输出前一百万个数,时间复杂度为O(n*logn)。

2、维护一个大小为一百万的大顶推,然后遍历完十亿个数,输出大顶推的数即可,时间复杂度为O(n*logk)。该思路适合大数据,尤其是内存放不下所有数据的时候。

3、利用快排的思想进行划分,一次划分后设主元的位置为index,如果index == k,输出前k个数;如果index > k,继续在左半部分进行划分寻找k;如果index < k,输出左半部分的数,继续在右半部分进行划分寻找剩下的k - index个数。时间复杂度为O(n)。

类似的题有:找出n个数中第k大(小)的数。

import pandas as pd import numpy as np import matplotlib.pyplot as plt from scipy.optimize import minimize # ====================== 参数设置 ====================== # 流域参数 AREA = 553 # 流域面积(km²) DT = 3 # 计算时段长度(小时) # 产流参数 (示例值,实际应通过任务1优选) params = { 'WM': 140, # 张力水蓄水容量(mm) 'WUM': 20, # 上层张力水容量(mm) 'WLM': 60, # 下层张力水容量(mm) 'WDM': 60, # 深层张力水容量(mm) 'b': 0.3, # 张力水蓄水容量曲线指数 'c': 0.16, # 深层蒸发系数 'Kc': 0.85, # 蒸发折算系数(应通过优化确定) 'fc': 10.0, # 稳定下渗率(mm/3h) 'WU0': 20, # 初始上层张力水(mm) - 取容量值 'WL0': 60, # 初始下层张力水(mm) - 取容量值 'WD0': 60 # 初始深层张力水(mm) - 取容量值 } # 汇流参数 unit_hydrograph = [0, 40, 80, 130, 100, 80, 48, 20, 10, 5, 0] # 单位线(m³/s) CG = 0.968 # 地下径流出流系数 Qg0 = 55.3 # 初始地下径流(m³/s) # ====================== 新安江模型核心类 ====================== class XinanjiangModel: def __init__(self, params): """初始化模型参数""" self.WM = params['WM'] self.WUM = params['WUM'] self.WLM = params['WLM'] self.WDM = params['WDM'] self.b = params['b'] self.c = params['c'] self.Kc = params['Kc'] self.fc = params['fc'] # 初始化土壤含水量 self.WU = params['WU0'] self.WL = params['WL0'] self.WD = params['WD0'] def evapotranspiration(self, P, E0): """三层蒸发计算""" Ep = E0 * self.Kc # 蒸散发能力 # 上层蒸发 EU = min(self.WU + P, Ep) # 剩余蒸发能力 E_remain = Ep - EU # 下层蒸发 if self.WL > self.c * self.WLM: EL = min(E_remain, self.WL) else: EL = min(self.c * E_remain, self.WL) # 深层蒸发 E_remain -= EL ED = min(self.c * E_remain, self.WD) # 总蒸发量 E_total = EU + EL + ED # 更新土壤含水量 self.WU = max(0, self.WU + P - EU) self.WL = max(0, self.WL - EL) self.WD = max(0, self.WD - ED) return E_total def runoff_generation(self, P, E0): """产流计算""" # 计算蒸发 E = self.evapotranspiration(P, E0) PE = P - E if PE <= 0: return 0.0, 0.0, 0.0 # 无产流 # 当土壤总含水量 W = self.WU + self.WL + self.WD # 张力水蓄水容量曲线计算 WMM = self.WM * (1 + self.b) A = WMM * (1 - (1 - min(W / self.WM, 1.0)) ** (1 / (1 + self.b))) # 产流量计算 if PE + A < WMM: R = PE - (self.WM - W) + self.WM * (1 - (A + PE) / WMM) ** (1 + self.b) else: R = PE - (self.WM - W) R = max(R, 0) # 确保产流不为负 # 更新土壤含水量 W_new = min(W + PE - R, self.WM) self.WU = min(W_new * self.WUM / self.WM, self.WUM) self.WL = min(W_new * self.WLM / self.WM, self.WLM) self.WD = min(W_new - self.WU - self.WL, self.WDM) # 分水源计算 if PE > self.fc: RG = min(R, self.fc) # 地下径流 RD = R - RG # 直接径流 else: RG = R RD = 0.0 return R, RD, RG # ====================== 数据准备 ====================== # 创建DataFrame data = { 'T': pd.to_datetime([ '2004-9-23 12:00', '2004-9-23 15:00', '2004-9-23 18:00', '2004-9-23 21:00', '2004-9-24 00:00', '2004-9-24 03:00', '2004-9-24 06:00', '2004-9-24 09:00', '2004-9-24 12:00', '2004-9-24 15:00', '2004-9-24 18:00', '2004-9-24 21:00', '2004-9-25 00:00', '2004-9-25 03:00', '2004-9-25 06:00', '2004-9-25 09:00', '2004-9-25 12:00', '2004-9-25 15:00', '2004-9-25 18:00', '2004-9-25 21:00', '2004-9-26 00:00', '2004-9-26 03:00', '2004-9-26 06:00', '2004-9-26 09:00', '2004-9-26 12:00', '2004-9-26 15:00', '2004-9-26 18:00', '2004-9-26 21:00' ]), 'E': [1.3, 1.3, 1.3, 1.3, 1.2, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.9, 0.8, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.2, 2.1, 2.1, 2.1, 2.1, 2.1, 2.1, 2], 'P1': [6.2, 7.6, 6.2, 8.8, 25, 29.9, 38.6, 6.9, 28.3, 25.6, 93.9, 85.3, 51.5, 39.8, 43.2, 20.5, 10.5, 7.4, 1.8, 0.2, 0, 0, 0, 0, 0, 0, 0, 0], 'P2': [9.9, 16, 6.4, 17.2, 34.8, 29.2, 24.8, 7.5, 29.9, 42.7, 137.6, 90.8, 47.7, 70.3, 47.3, 13.3, 8, 8.4, 2.8, 0, 0, 0, 0, 0, 0, 0, 0, 0], 'P3': [21.6, 20.6, 14.9, 29.4, 35.3, 43.9, 46.9, 6.1, 34.2, 39.8, 124, 85, 49.2, 42.1, 61.5, 15.8, 1.8, 7.6, 2.1, 0.3, 0, 0, 0, 0, 0, 0, 0, 0], 'P4': [17.3, 12.6, 15.9, 18.5, 24.6, 37.8, 33, 12.3, 28.5, 75.4, 13.2, 75.9, 38.5, 97.7, 45.9, 13.1, 3.3, 10.9, 4.6, 0, 0, 0, 0, 0, 0, 0, 0, 0] } df = pd.DataFrame(data) # 权重系数 weights = [0.33, 0.14, 0.33, 0.20] # 计算面平均雨量 df['P_avg'] = df[['P1', 'P2', 'P3', 'P4']].dot(weights) # ====================== 产流计算 ====================== # 初始化模型 model = XinanjiangModel(params) # 存储结果 df['R'] = 0.0 # 总径流(mm) df['RD'] = 0.0 # 直接径流(mm) df['RG'] = 0.0 # 地下径流(mm) # 逐时段计算产流 for i in range(len(df)): P = df.loc[i, 'P_avg'] E0_val = df.loc[i, 'E'] R, RD, RG = model.runoff_generation(P, E0_val) df.loc[i, 'R'] = R df.loc[i, 'RD'] = RD df.loc[i, 'RG'] = RG # ====================== 汇流计算 ====================== # 单位转换系数 (mm/3h → m³/s) # 公式: 流量(m³/s) = 径流深(mm) * 流域面积(km²) / (3.6 * 时段小时数) conversion_factor = AREA / (3.6 * DT) # 1. 直接径流汇流 (单位线法) # 将径流深转换为单位线倍比 RD_converted = df['RD'].values * conversion_factor / 10 # 单位线为10mm单位线 # 卷积计算 direct_flow = np.convolve(RD_converted, unit_hydrograph, mode='full')[:len(df)] # 2. 地下径流汇流 (线性水库法) # 将径流深转换为流量 RG_converted = df['RG'].values * conversion_factor # 线性水库演算 groundwater_flow = np.zeros(len(df)) groundwater_flow[0] = Qg0 # 初始值 for i in range(1, len(df)): groundwater_flow[i] = CG * groundwater_flow[i - 1] + (1 - CG) * RG_converted[i] # 3. 总流量过程 total_flow = direct_flow + groundwater_flow # ====================== 结果可视化 ====================== plt.figure(figsize=(14, 10)) # 1. 降雨过程 plt.subplot(3, 1, 1) plt.bar(df['T'], df['P_avg'], width=0.02, color='blue') plt.title('流域平均降雨过程 (3小时雨量)') plt.ylabel('降雨量 (mm)') plt.grid(True, linestyle='--', alpha=0.7) plt.xticks(rotation=45) # 2. 径流组分 plt.subplot(3, 1, 2) plt.plot(df['T'], df['R'], 'k-', label='总径流(R)') plt.plot(df['T'], df['RD'], 'r--', label='直接径流(RD)') plt.plot(df['T'], df['RG'], 'b-.', label='地下径流(RG)') plt.title('径流组分过程') plt.ylabel('径流量 (mm)') plt.legend() plt.grid(True, linestyle='--', alpha=0.7) plt.xticks(rotation=45) # 3. 流量过程 plt.subplot(3, 1, 3) plt.plot(df['T'], total_flow, 'k-', linewidth=2, label='总流量') plt.plot(df['T'], direct_flow, 'r--', label='直接径流') plt.plot(df['T'], groundwater_flow, 'b-.', label='地下径流') plt.title('流量过程线') plt.xlabel('时间') plt.ylabel('流量 (m³/s)') plt.legend() plt.grid(True, linestyle='--', alpha=0.7) plt.xticks(rotation=45) plt.tight_layout() plt.savefig('hydrograph_analysis.png', dpi=300) plt.show() # ====================== 结果保存 ====================== # 添加流量结果到DataFrame df['Direct_Flow'] = direct_flow df['Groundwater_Flow'] = groundwater_flow df['Total_Flow'] = total_flow # 保存结果 df.to_excel(r'C:\Users\80401\Desktop\hydrological_simulation_results.xlsx', index=False) print("模拟结果已保存到 'hydrological_simulation_results.xlsx'")改进代码,要不使用scipy库
最新发布
06-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值