如何预先计算有效的组合数而不是使用while循环?

时间:2014-02-14 17:23:42

标签: java algorithm map while-loop

给出dc1,dc2,dc3和机器列表的数据中心列表,h1,h2,h3,h4如下所述 -

Datacenters = dc1, dc2, dc3
Machines = h1, h2, h3, h4

我想仅生成以下组合 -

a)  {dc1=h1, dc3=h3, dc2=h2}

b)  {dc1=h2, dc3=h4, dc2=h3}

c)  {dc1=h3, dc3=h1, dc2=h4}

d)  {dc1=h4, dc3=h2, dc2=h1}

每次传递中的每个数据中心都应该获得备用计算机/主机。他们不应该得到相同的机器。例如,如上所示在a - dc1 gets h1dc2 gets h2dc3 gets h3,因此每个数据中心的所有计算机都不同。在第二遍中,如b - 现在dc1 gets h2所示(因为dc1在第一遍中已经获得了h1),dc2 got h3(bcoz dc2在第一遍中已经获得了h2),并且dc3 got h4(bcoz dc3在第一遍中已经获得了h3)等等。

还有一个例子 - 如果我只有三个主机,那么下面的组合我应该只得到 -

Datacenters = dc1, dc2, dc3
Machines = h1, h2, h3    

{dc1=h1, dc3=h3, dc2=h2}
{dc1=h2, dc3=h1, dc2=h3}
{dc1=h3, dc3=h2, dc2=h1}

所以我提出了以下代码,它完全正常 -

public class DataCenterMapping {

    public static void main(String[] args) {

    DatacenterMachineMapping dcm = new DatacenterMachineMapping(Arrays.asList("dc1", "dc2", "dc3"), Arrays.asList(
        "h1", "h2", "h3", "h4"));

        // is there any way to avoid while loop here?
        while (true) {
            Map<String, String> coloHost = dcm.getDatacenterMachineMapping();
            System.out.println(coloHost);
            for (Map.Entry<String, String> entry : coloHost.entrySet()) {

            }
        }
    }
}

class DatacenterMachineMapping {

    private boolean firstCall = true;
    private int hostListIndex = 0;
    private List<String> datacenterList, hostList;
    private Map<String, Set<String>> dataCenterHostsMap = new HashMap<String, Set<String>>();

    public DatacenterMachineMapping(List<String> datacenterList, List<String> hostList) {
    this.datacenterList = datacenterList;
    this.hostList = hostList;
    }

    public Map<String, String> getDatacenterMachineMapping() {
    Map<String, String> datacenterMachineMapping = new HashMap<String, String>();
    if (!firstCall) {
        if (hostListIndex <= 0) {
        hostListIndex = hostList.size();
        }
        hostListIndex--;
    } else {
        firstCall = false;
    }
    for (String datacenter : datacenterList) {
        if (hostListIndex == hostList.size()) {
        hostListIndex = 0;
        }
        if (addDataCenterHost(datacenter, hostList.get(hostListIndex))) {
        datacenterMachineMapping.put(datacenter, hostList.get(hostListIndex++));
        }
    }
    hostListIndex--;
    return datacenterMachineMapping;
    }

    private boolean addDataCenterHost(String datacenter, String host) {
    Set<String> dataCenterHostSet = dataCenterHostsMap.get(datacenter);
    if (dataCenterHostSet == null) {
        dataCenterHostSet = new HashSet<String>();
        dataCenterHostsMap.put(datacenter, dataCenterHostSet);
    }
    return dataCenterHostSet.add(host);
    }
}

问题陈述: -

唯一的问题是我有一个while循环,它会一直运行,

有什么方法可以预先计算有效组合的数量,而不是使用while循环?

2 个答案:

答案 0 :(得分:1)

你在说数学。答案是(n选择k),其中n是机器数量,k是数据中心的数量。

原因如下:排序并不重要,因此我们假设数据中心始终按相同的顺序排列。对于第一个数据中心,我们可以选择任何一台n台机器。对于第二个,我们可以选择任何一台机器,除了之前选择的机器,因此n * (n-1)。下一个数据中心将导致n * (n-1) * (n-2)可能出现的情况。

因此,如果您有10台机器和4个数据中心,那么您将拥有:

10 * 9 * 8 * 7可能的组合。

此处有更多信息:http://en.wikipedia.org/wiki/Combination

如果您希望函数为您完成工作,那么它位于Apache公共区:http://commons.apache.org/proper/commons-math/apidocs/org/apache/commons/math3/util/ArithmeticUtils.html#binomialCoefficientDouble%28int,%20int%29

但是,如果您实际上想要生成这些组合,那么您需要一个for循环。

答案 1 :(得分:0)

不确定你在这里问过什么,但我想我能看到问题所在,每次调用get map你只生成1行。所以我重写了代码,以便生成所有代码,并返回一个地图列表。所以你可以用它们做你需要的。

public class DataCenterMapping {

    public static void main(String[] args) {

        DatacenterMachineMapping dcm = new DatacenterMachineMapping(
                Arrays.asList("dc1", "dc2", "dc3"), Arrays.asList("h1", "h2",
                        "h3", "h4"));


            List<Map<String, String>> coloHost = dcm
                    .getDatacenterMachineMappings();

            System.out.println(coloHost);

    }
}

class DatacenterMachineMapping {

    private boolean firstCall = true;
    private int hostListIndex = 0;
    private List<String> datacenterList, hostList;

    public DatacenterMachineMapping(List<String> datacenterList,
            List<String> hostList) {
        this.datacenterList = datacenterList;
        this.hostList = hostList;
    }

    public List<Map<String, String>> getDatacenterMachineMappings() {
        List<Map<String, String>> grid = new ArrayList<Map<String, String>>();
        for (int i = 0; i < datacenterList.size(); i++) {

            Map<String, String> datacenterMachineMapping = new HashMap<String, String>();
            String[] line = new String[hostList.size()];
            for (int j = 0; j < line.length; j++) {
                int off = j + i;
                if (off >= datacenterList.size()) {
                    off -= datacenterList.size();
                }
                datacenterMachineMapping.put(hostList.get(j) ,datacenterList.get(off));
            }

            grid.add(datacenterMachineMapping);
        }
        return grid;
    }

}

示例输出:

[{h4=dc1, h1=dc1, h3=dc3, h2=dc2}, {h4=dc2, h1=dc2, h3=dc1, h2=dc3}, {h4=dc3, h1=dc3, h3=dc2, h2=dc1}]
相关问题