题目:

假设有一个大水池,其容积为poolSize,还有n个彼此大小不同的水桶,分别是B1,B2,B3,B4,B5..Bn,放在一个数组中 。请给出水桶的所有组合,使得他们的容积之和刚好可以灌满整个水池poolSize

分析:

因为很久没弄算法了,这题目搞了我近2个小时,其实思路还是蛮简单的, 就是回溯。首先,先升序排列水桶,然后移除水桶容积直接超过水池容积的(这种水桶显然不可能成为解的集合) 。排序后,选出最大的水桶,如果最大的水桶容积刚好等于水池容积,那么返回。如果最大的水桶容积也没有水池大,那么必定是若干小水桶的组合来满足大水池的要求,假设满足要求的水桶集合为C.这时候,我们从排序了的水桶中选出最大的水桶,这样分2种情况:

假设目前最大的水桶Bmax是C的一部分,那么最终的C必定为Bmax  加上水桶集合中除去Bmax的某个组合来满足C-Bmax的结果集,这是一个递归

假设目前最大的水桶Bmax不是C的一部分,那么最终的C必定为水桶集合中除去Bmax的某个组合来满足C的结果集,这也是一个递归。

所以最后实现代码为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
package com.charles.algo;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
 *
 * 百度面试题:
 * 假设有一个大水池,其容积为poolSize,还有n个彼此大小不同的水桶,分别是B1,B2,B3,B4,B5..Bn,放在一个数组中
 * 请给出水桶的所有组合,使得他们的容积之和刚好可以灌满整个水池poolSize
 *
 * @author charles.wang
 *
 */
public class BucketAndPool {
    // 放置可能的解
    private static List<Integer> list = new ArrayList<Integer>();
    /**
     * 这是一个wrapper方法,用于做一些参数排序处理,和排除所有绝对不可能作为候选列表的桶,以免减少运行时间开销
     *
     * @param poolSize
     *            池的大小
     * @param buckets
     *            所有候选桶的数组
     */
    public static void fillPoolWithBuckets(int poolSize, int[] buckets) {
        // 局部变量,作为真正参与运算的buckets
        int[] actualBuckets = buckets;
        // 首先,吧所有的水桶按照升序排序,这样方便我们找到最大的桶
        Arrays.sort(actualBuckets);
        // 判断如果某个buckets的大小超过了池子,那么从这个bucket开始,比它大的buckets都不考虑
        // 于是缩减原来的buckets数组为新的buckets数组,并且只有不超过poolSize的buckets会列在其中
        for (int i = 0; i < buckets.length; i++) {
            if (buckets[i] > poolSize) {
                actualBuckets = Arrays.copyOf(actualBuckets, i);
                break;
            }
        }
        // 递归的调用方法来输出结果
        findSolution(poolSize, actualBuckets);
    }
    /**
     * 递归方法,用当前的可选已经排过序的桶的列表来填充一个池子poolSize
     *
     * @param poolSize
     * @param sortedBuckets
     */
    private static void findSolution(int poolSize, int[] sortedBuckets) {
        // 递归的出口,是当前没有可用的桶或者需要凑容积的池子尺寸已经为0了
        if ((sortedBuckets.length == 0) || (poolSize <= 0))
            return;
        // 输出结果
        //输出结果的条件是当前最大桶(已经排序过)直接满足条件,那么当前最大桶就作为可用解的一个值
        //比如用桶{1,2,3}去凑水池容积为3, 那么一旦找到3,那么就直接输出3
        //而解访问两部分,一个是已有的在计算子匹配之前的已经选出的桶的列表,在list列表中存着呢
        //另一个是找到的当前的解,所以依次输出已选桶的列表(来自list)和当前桶
        if (poolSize == sortedBuckets[sortedBuckets.length - 1]) {
            for (int i = 0; i < list.size(); i++) {
                System.out.print(list.get(i) + ",");
            }
            System.out.println(poolSize);
        }
                                                   
        //如果最大桶无法直接满足池子的容量,那么就必须用若干小桶来凑池子的容量,为此,先选出小桶中最大的那个。
                                                   
        // 最大的水桶
        int largestBucket = sortedBuckets[sortedBuckets.length - 1];
        //现在解决方案分2部分:
        //(1)放入可用桶桶列表中最大的这个到可用列表中,并且这个桶是有解的,
        //   则用桶列表剔除最大桶的子桶列表来凑 剩余池子容量-最大桶容量,这是个递归调用
        //(2)放入最大桶进去之后,是无解的,那么从可用列表中剔除这个最大桶
        //   并且用桶列表剔除最大桶的子桶列表来凑 剩余池子容量,这是也个递归调用
                                                   
        //放入最大的水桶到可用列表,递归解决其他的水桶来凑 池容量-最大桶容量
        list.add(largestBucket);
        findSolution(poolSize - largestBucket,
                Arrays.copyOf(sortedBuckets, sortedBuckets.length - 1));
        //不放入最大的水桶,递归的解决其他的水桶来凑 池容量
        list.remove(list.size() - 1);
        findSolution(poolSize,
                Arrays.copyOf(sortedBuckets, sortedBuckets.length - 1));
    }
    public static void main(String[] args) {
        int poolSize = 31;
        int[] buckets = { 687121728231316 };
                                                   
        fillPoolWithBuckets(poolSize, buckets);
    }
}

我们假设有若干小水桶,6L,8L,7L,12L,28L,23L,1L,3L,16L,我们要凑出31L的水池, 那么运行这个程序之后,结果如下:

本文转自 charles_wang888 51CTO博客,原文链接:http://blog.51cto.com/supercharles888/1345561,如需转载请自行联系原作者

一道百度算法面试题讲解相关推荐

  1. 一道JS算法面试题——冒泡、选择排序

    JS排序算法 基础排序 冒泡排序 选择排序 面试题 基础排序 今天学习了数据结构,遇到了一个关于算法的面试题,然后从中想到了冒泡排序和选择排序对一个数组从小到大的排序的方法,今天分享给大家,顺便记录下 ...

  2. 记一道超级简单的 Java 算法面试题,但无人通过

    点击上方蓝字设为星标 下面开始今天的学习- 作者:方志宏(已获作者授权转载,禁止二次转载) 来源:https://zhuanlan.zhihu.com/p/57859872 这可能是历史上最简单的一道 ...

  3. 记一道超级简单的算法面试题,90%的人没能完整答出来

    作者:方志宏(已获作者授权转载,禁止二次转载) 来源:https://zhuanlan.zhihu.com/p/57859872 这可能是历史上最简单的一道 Java 算法面试题了. 题目很简单,完成 ...

  4. 一道亚马逊算法面试题的情景分析

    阅读博客的朋友可以观看视频: http://study.163.com/course/courseMain.htm?courseId=1002942008 我们聚焦于一道亚马逊的算法面试题,通过分析该 ...

  5. 分享一道算法面试题和它的三种解法

    最近遇到了一道很有趣的算法面试题,乍一看逻辑很简单,O(N^2)时间复杂度的解决方式可以在常规语义下得到解决.但是O(N^2)时间复杂度之下缓慢的运行效率和重复的计算总让人觉得还有可以优化的空间.接下 ...

  6. 微软的100道算法面试题(终结版)

    前言 数据结构与算法的重要性已不言而喻,最近,我整理出十大经典排序算法.五大常用算法总结,今天特意整理出微软面试的100题,若有不足之处,欢迎指正!由于篇幅过长,前30道题目写在上一篇,大家可以进我的 ...

  7. 数据结构经典算法面试题

    转自:http://hi.baidu.com/geogre_jsj/blog/item/e4b98fd2aab5aa3611df9b92.html 由于这些题,实在太火了.所以,应广大网友建议要求,在 ...

  8. twitter java_Twitter算法面试题详解(Java实现)

    最近在网上看到一道Twitter的算法面试题,网上已经有人给出了答案,不过可能有些人没太看明白(我也未验证是否正确),现在给出一个比较好理解的答案.先看一下题目. 图1 先看看图图1.可以将方块看做砖 ...

  9. 现实中的算法面试题(已拿Offer)赚到了,赚到了

    算法面试题 阅读目录 写在前面 算法百科 算法题目 参考答案 博客总结 博客前言 有提到分享一下面试题,最近也是才能新公司入职没多久,忙着熟悉环境,加上前不久出去玩了一趟(顺便写了篇游记,感兴趣的可以 ...

最新文章

  1. 设计模式 之美 -- 代理模式
  2. “Jupyter的杀手”:Netflix发布新开发工具Polynote
  3. nginx反向代理(proxy_pass)tomcat的过程中,session失效的问题解决
  4. Access和SQL SERVER两种数据库的直接转换,不需要第三方工具
  5. 让全球数亿人拍摄到更美的照片,【北京三星研究院】招聘
  6. 无维护地稳定运行了8 年的 Hyperic HQ
  7. 现在市面上卖的贵州茅台镇原浆酒20元一瓶是什么酒?
  8. vue--配套axios用法
  9. 如何获取git diff文件,并将其应用于作为同一存储库副本的本地分支?
  10. lync登录时一直停留在登录界面
  11. 《数据结构与算法 C语言版》—— 2.2线性表的顺序表示与实现
  12. 转 json数组对象和对象数组
  13. 人力资源SaaS“一哥”,二十年艰难进化
  14. 软件开发必备英语汇总(持续更新)
  15. sir模型初始值_SIR模型
  16. 使用webgl(three.js)搭建一个3D智慧园区、3D建筑,3D消防模拟,web版3D,bim管理系统——第四课...
  17. My SQL数据库基本操作
  18. BeanUtils.copyProperties()复制对象时改变属性类型
  19. 职场心理学-心理学第一天(非原创)
  20. 电子商务法律法规【1】

热门文章

  1. linux 系统性能指标采样脚本
  2. jQuery Template的用法
  3. GNU make 和 makefile
  4. 【观点】程序员应知——循序渐进
  5. C#.net模拟提交表单POST
  6. sklearn API快速上手
  7. 在局域网访问_管理Windows访问凭证,快速访问局域网上的共享资源
  8. 30+的程序猿,路在何方?
  9. 一道Python面试题,据说大部分人都中招了,纷纷开始怀疑自己
  10. android vlc 参数,【VLC-Android】LibVLC API简介(至关于VLC的MediaPlayer)