【华为OD】区块链文件转储系统

文章目录

【华为OD】区块链文件转储系统

题目描述

区块链底层存储是一个链式文件系统,由顺序的 N 个文件组成,每个文件的大小不一,依次为F1,F2,...,Fn。随着时间的推移,所占存储会越来越大,云平台考虑将区块链按文件转储到廉价的SATA 盘,只有连续的区块链文件才能转储到 SATA盘上,且转储的文件之和不能超过SATA 盘的容量。假设每块 SATA 盘容量为 M,求能转储的最大连续文件大小之和。

输入描述

第一行为 SATA 盘容量 M,1000 ≤ M ≤ 1000000

第二行为区块链文件大小序列 F1, F2, ..., Fn。其中 1 ≤ n ≤ 100000,1 ≤ Fi ≤ 500

输出描述

求能转储的最大连续文件大小之和。

示例

示例一

输入:

复制代码
1000
100 300 500 400 400 150 100

输出:

复制代码
950

说明:

最大序列和为 950,序列为 [400, 400, 150]

示例二

输入:

复制代码
1000
100 500 400 150 500 100

输出:

复制代码
1000

说明:

最大序列和为 1000,序列为 [100, 500, 400]

解题思路

这是一个经典的最大连续子数组和问题的变种,需要在满足和不超过容量M的约束条件下,找到最大的连续子数组和。

我们可以使用两种方法来解决:

  1. 滑动窗口法:使用双指针维护一个滑动窗口,动态调整窗口大小
  2. 暴力枚举法:枚举所有可能的连续子数组,找到满足条件的最大和

解法一:滑动窗口法

滑动窗口是解决这类问题的最优方法,时间复杂度为O(n)。

Java实现

java 复制代码
import java.util.*;

public class Solution {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int M = scanner.nextInt();
        scanner.nextLine(); // 消费换行符
        
        String[] fileStr = scanner.nextLine().split(" ");
        int[] files = new int[fileStr.length];
        for (int i = 0; i < fileStr.length; i++) {
            files[i] = Integer.parseInt(fileStr[i]);
        }
        
        int maxSum = 0;
        int left = 0;
        int currentSum = 0;
        
        for (int right = 0; right < files.length; right++) {
            currentSum += files[right];
            
            // 如果当前和超过容量,收缩左边界
            while (currentSum > M && left <= right) {
                currentSum -= files[left];
                left++;
            }
            
            // 更新最大和
            maxSum = Math.max(maxSum, currentSum);
        }
        
        System.out.println(maxSum);
    }
}

Python实现

python 复制代码
def solve():
    M = int(input())
    files = list(map(int, input().split()))
    
    max_sum = 0
    left = 0
    current_sum = 0
    
    for right in range(len(files)):
        current_sum += files[right]
        
        # 如果当前和超过容量,收缩左边界
        while current_sum > M and left <= right:
            current_sum -= files[left]
            left += 1
        
        # 更新最大和
        max_sum = max(max_sum, current_sum)
    
    print(max_sum)

solve()

C++实现

cpp 复制代码
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
using namespace std;

int main() {
    int M;
    cin >> M;
    cin.ignore(); // 忽略换行符
    
    string line;
    getline(cin, line);
    istringstream iss(line);
    vector<int> files;
    int file;
    while (iss >> file) {
        files.push_back(file);
    }
    
    int maxSum = 0;
    int left = 0;
    int currentSum = 0;
    
    for (int right = 0; right < files.size(); right++) {
        currentSum += files[right];
        
        // 如果当前和超过容量,收缩左边界
        while (currentSum > M && left <= right) {
            currentSum -= files[left];
            left++;
        }
        
        // 更新最大和
        maxSum = max(maxSum, currentSum);
    }
    
    cout << maxSum << endl;
    return 0;
}

解法二:暴力枚举法

虽然时间复杂度较高O(n²),但思路简单直观,适合理解问题本质。

Java实现

java 复制代码
import java.util.*;

public class Solution2 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int M = scanner.nextInt();
        scanner.nextLine();
        
        String[] fileStr = scanner.nextLine().split(" ");
        int[] files = new int[fileStr.length];
        for (int i = 0; i < fileStr.length; i++) {
            files[i] = Integer.parseInt(fileStr[i]);
        }
        
        int maxSum = 0;
        
        // 枚举所有可能的起始位置
        for (int i = 0; i < files.length; i++) {
            int currentSum = 0;
            // 从起始位置开始累加
            for (int j = i; j < files.length; j++) {
                currentSum += files[j];
                if (currentSum <= M) {
                    maxSum = Math.max(maxSum, currentSum);
                } else {
                    break; // 超过容量,停止扩展
                }
            }
        }
        
        System.out.println(maxSum);
    }
}

Python实现

python 复制代码
def solve_brute_force():
    M = int(input())
    files = list(map(int, input().split()))
    
    max_sum = 0
    
    # 枚举所有可能的起始位置
    for i in range(len(files)):
        current_sum = 0
        # 从起始位置开始累加
        for j in range(i, len(files)):
            current_sum += files[j]
            if current_sum <= M:
                max_sum = max(max_sum, current_sum)
            else:
                break  # 超过容量,停止扩展
    
    print(max_sum)

solve_brute_force()

C++实现

cpp 复制代码
#include <iostream>
#include <vector>
#include <sstream>
#include <algorithm>
using namespace std;

int main() {
    int M;
    cin >> M;
    cin.ignore();
    
    string line;
    getline(cin, line);
    istringstream iss(line);
    vector<int> files;
    int file;
    while (iss >> file) {
        files.push_back(file);
    }
    
    int maxSum = 0;
    
    // 枚举所有可能的起始位置
    for (int i = 0; i < files.size(); i++) {
        int currentSum = 0;
        // 从起始位置开始累加
        for (int j = i; j < files.size(); j++) {
            currentSum += files[j];
            if (currentSum <= M) {
                maxSum = max(maxSum, currentSum);
            } else {
                break; // 超过容量,停止扩展
            }
        }
    }
    
    cout << maxSum << endl;
    return 0;
}

算法分析

时间复杂度

  • 滑动窗口法:O(n),每个元素最多被访问两次
  • 暴力枚举法:O(n²),需要枚举所有可能的子数组

空间复杂度

  • 两种方法的空间复杂度都是O(n),主要用于存储输入数组

推荐方案

对于本题的数据规模(n ≤ 100000),强烈推荐使用滑动窗口法,因为:

  1. 时间复杂度更优,能够在规定时间内通过所有测试用例
  2. 代码简洁,逻辑清晰
  3. 是解决此类问题的标准算法

总结

区块链文件转储系统问题本质上是一个约束条件下的最大连续子数组和问题。通过滑动窗口技术,我们可以高效地解决这个问题。这种方法在处理连续子数组相关问题时非常有用,是算法面试中的常考知识点。

相关推荐
DeepVis Research几秒前
【Chaos/Neuro】2026年度混沌动力学仿真与机器遗忘算法基准索引 (Benchmark Index)
人工智能·算法·数据集·混沌工程·高性能计算
white-persist19 分钟前
【内网运维】Netstat与Wireshark:内网运维溯源实战解析
运维·网络·数据结构·测试工具·算法·网络安全·wireshark
会员果汁20 分钟前
7.设计模式-模板方法模式
算法·设计模式·模板方法模式
努力学算法的蒟蒻21 分钟前
day52(1.2)——leetcode面试经典150
算法·leetcode·面试
java修仙传24 分钟前
力扣hot100:字符串解码
算法·leetcode·职场和发展
Joe_Blue_0225 分钟前
Matlab入门案例介绍—如何创建代码
算法·matlab·matlab基础入门案例介绍
梭七y28 分钟前
【力扣hot100题】(116)矩阵置零
算法·leetcode·矩阵
应用市场34 分钟前
# 内容平台推荐算法与创作者激励机制——从抖音/B站看流量分配的技术逻辑
算法·机器学习·推荐算法
啊董dong37 分钟前
noi-2025年12月23号作业
数据结构·c++·算法·noi
surtr141 分钟前
【算法自用】一些比较有趣的题目
算法·动态规划·概率论·图论