【华为OD题库-035】数据最节约的备份方法-java

题目

有若干个文件,使用刻录光盘的方式进行备份,假设每张光盘的容量是500MB.求使用光盘最少的文件分布方式。所有文件的大小都是整数MB,且不超过500MB:文件不能分割、分卷打包
输入描述:
一组文件大小的数据
输出描述:
使用光盘的数量
补充说明:
不用考虑输入数据不合法的情况:假设最多100个输入文件。
示例1
输入:
100,500,300,200,400
输出:
3
说明:
(100,400),(200,300),(500) 3张光盘即可,输入和输出内容都不含空格。
示例2
输入:
100,100,200,300
输出:
2

思路

以500 400 300 80 70 70 50 30为例(已将nums倒序排列),
备份第一个文件500,需要第一个光盘
备份第二个文件400,需要第二个光盘,还剩100空间
备份第三个文件300,上次只剩100空间,所以得另开第三个光盘,备份后还剩200空间
备份第四个文件80,此时第二和第三个光盘的剩余空间都能放下?到底该放入哪一个呢?

  1. 假设放入剩余空间较小的那一个
    备份第四个文件80,放入第二个光盘,此时剩余空间:20
    备份第五个文件70,放入第三个光盘,剩余空间:130
    备份第六个文件70,放入第三个光盘,剩余空间:60
    备份第七个文件50,放入第三个光盘,剩余空间:10
    备份第八个文件30,第二个光盘剩余了20的空间,第三个光盘剩余了10空间,均放不下,所以另起第四个光盘。
    在此分支得到答案为:4
  2. 假设放入剩余空间较大的那一个
    备份第四个文件80,放入第三个光盘,此时剩余空间:120
    备份第五个文件70,放入第三个光盘,剩余空间:60
    备份第六个文件70,放入第二个光盘,剩余空间:30
    备份第七个文件50,放入第三个光盘,剩余空间:10
    备份第八个文件30,放入第二个光盘,剩余空间:0
    在此分支得到答案为:3

很明显,从此用例的结果来看,放入剩余空间较大的那一个,可以更节省光盘。
从逻辑上来分析,当两个空间都能放下当前文件时,放入更大的空间能够保证放入后,两个最小剩余空间更大。比如上面的案例中,当前文件为80,两个光盘的剩余空间分别为100和200,如果放入100,那么两个剩余空间变为:20和200,最小值为20;如果放入200,那么两个剩余空间为100,120,最小值为100;此时再备份新的文件时,如果其大小超过了20,第一种方案,就只能备份到200的空间去,那20的剩余空间就要被浪费掉了。

因此,最小剩余空间越大,才最省空间。
综上,在代码实现时,应该用一种结构保证始终能找到剩余空间较大的那一个,而剩余空间=500-已使用空间。要想剩余空间最大,就是使用空间最小,可以考虑用最小堆来实现。

  1. 如果堆为空,或者当前值nums[i]+最大剩余空间>500,说明得另开一个光盘,将nums[i]放入最小堆,此时堆大小+1,代表新开了光盘
  2. 如果nums[i]+最大剩余空间<=500,当前文件可以拷贝到上一个光盘,那么直接把上一个光盘取出来,加上当前文件大小,再存回堆中,这样堆的size并没有变化,也就是没有新开光盘
  3. 最后返回堆的大小就代表最少光盘数量。

题解

package hwod;

import java.util.*;

public class DataCopy {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int[] nums = Arrays.stream(sc.nextLine().split(",")).mapToInt(Integer::parseInt).toArray();
        System.out.println(dataCopy(nums));
    }

    private static int dataCopy(int[] nums) {
        Arrays.sort(nums);
        PriorityQueue<Integer> queue = new PriorityQueue<>();
        for (int i = nums.length-1; i >=0; i--) {
            if (queue.isEmpty() || nums[i] + queue.peek() > 500) {
                queue.offer(nums[i]);
            } else {
                queue.offer(queue.poll() + nums[i]);
            }
        }
        return queue.size();
    }


}

推荐

如果你对本系列的其他题目感兴趣,可以参考华为OD机试真题及题解(JAVA),查看当前专栏更新的所有题目。

说明

本专栏所有文章均为原创,欢迎转载,请注明文章出处:https://blog.csdn.net/qq_31076523/article/details/134176793。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。

  • 44
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值