【华为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. 是解决此类问题的标准算法

总结

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

相关推荐
lqqjuly5 分钟前
前沿算法深度解析(二)
人工智能·算法·机器学习
徐小夕1 小时前
万字长文!千万级文档 RAG 知识库系统落地实践
前端·算法·github
akunkuntaimei2 小时前
2026年高考数学各省真题及答案(完整版)
算法·高考
Hello:CodeWorld2 小时前
C 风格变参 vs C++ 变参模板:核心区别与选型指南
c语言·c++·算法
8Qi84 小时前
LeetCode 516:最长回文子序列
算法·leetcode·职场和发展·动态规划
CTA终结者4 小时前
期货量化主力换月程序怎么移仓:天勤 underlying_symbol 与任务切换
python·区块链
youngerwang5 小时前
【从搬运工到协处理器:网卡芯片架构、算法、验证与边缘演进深度剖析】
网络·算法·架构·芯片
KaMeidebaby5 小时前
卡梅德生物技术快报|纯化重组蛋白实操详解
人工智能·python·tcp/ip·算法·机器学习
手写码匠6 小时前
从零实现 Prompt 工程引擎:结构化提示、自动优化与多轮自省体系
人工智能·深度学习·算法·aigc
无限码力6 小时前
阿里算法岗 0530笔试真题 - 多约束条件下的元素匹配统计
算法·阿里笔试真题·阿里机试真题·阿里算法岗笔试