编写一个可以“改变”的Java程序。使用适当的数据结构?

时间:2015-12-23 11:26:58

标签: java data-structures

我有一项任务,我不知道如何解决它的问题。

我不是要求你解决整个问题!所以,一旦看到"赋值",就不要进行投票。

这是数据结构和算法课程,它说使用适当的数据结构解决问题。首先,我将在此处复制作业:

编写一个可以进行更改的Java程序。"您的程序应该使用两个数字作为输入,一个是收取的货币金额,另一个是给定的货币金额。然后它应该返回每种账单和硬币的数量,以作为给定金额和收取金额之间的差异的变化。分配给账单和硬币的值可以基于任何现任或前任政府的货币系统。尝试设计你的程序,以便尽可能多地返回账单和硬币。

如果我理解正确,我们必须编写一个程序,可以用最少的使用量来计算用钞票和硬币偿还的金额。

到目前为止,我们只学习了堆栈,队列和链接列表,但我不知道如何使用其中一种数据结构来解决此分配。

哪种数据结构适合解决此类问题?为什么?

2 个答案:

答案 0 :(得分:1)

我会使用地图。例如,75将表示为:

100 -> 0
 50 -> 1
 20 -> 1
 10 -> 0
 5  -> 1
 ...
0.01 ->0

意思是零票据,五十票据之一等等。

答案 1 :(得分:1)

这是一种寻找最佳解决方案的算法。基本上,它会遍历所有可能的面额,寻找最短的变化值列表。

// How many cents in a dollar.
private static final int DOLLARS = 100;
// In cents.
private static final int[] denominations = {
    // $100
    100 * DOLLARS,
    // $50
    50 * DOLLARS,
    // $20
    20 * DOLLARS,
    // $10
    10 * DOLLARS,
    // $5
    5 * DOLLARS,
    // $2
    2 * DOLLARS,
    // $1
    1 * DOLLARS,
    // 50c
    50,
    // 25c
    25,
    // 5c
    5,
    // 1c
    1
};

private List<Integer> makeChange(int value) {
    // Null means none found so far.
    List<Integer> change = null;
    System.out.println("Make change for " + value);
    // For all denomination.
    for (int i : denominations) {
        // that is less than the value
        if (i <= value) {
            // Build a new candidate.
            List<Integer> newChange = new LinkedList<>();
            // Remember it.
            newChange.add(i);
            // If we are at zero we're done.
            if (i < value) {
                // Make change from the remaining value.
                List<Integer> theRest = makeChange(value - i);
                if (theRest != null) {
                    // Gode more.
                    newChange.addAll(theRest);
                }
            }
            // Is it shorter?
            if (change == null || newChange.size() < change.size()) {
                // Better.
                change = newChange;
                System.out.println("Better change for " + value + " = " + change);
            }
        }
    }
    return change;
}

使用26这样的低数字来尝试这一点会在合理的时间内给你一个好的结果。大约10美元以上的美元大关,它将会挣扎,因为它必须列举每种安排的所有可能的子安排 - 即使它之前已经看过它们。

如果我们被允许使用Map,我们可以通过记住之前的最佳计算(称为Memoisation)来改善问题。这个可以处理更大的数字,因为它永远不必重新计算任何数字的最佳变化。

// All the best lists I've seen so far.
Map<Integer, List<Integer>> memory = new HashMap<>();

private List<Integer> makeChangeUsingMap(int value) {
    // If we've seen this one before, use it.
    if (memory.containsKey(value)) {
        return memory.get(value);
    }
    // Null means none found so far.
    List<Integer> change = null;
    System.out.println("Make change for " + value);
    // For all denomination.
    for (int i : denominations) {
        // that is less than the value
        if (i <= value) {
            // Build a new candidate.
            List<Integer> newChange = new LinkedList<>();
            // Remember it.
            newChange.add(i);
            // If we are at zero we're done.
            if (i < value) {
                // Make change from the remaining value.
                List<Integer> theRest = makeChangeUsingMap(value - i);
                if (theRest != null) {
                    // Gode more.
                    newChange.addAll(theRest);
                }
            }
            // Is it shorter?
            if (change == null || newChange.size() < change.size()) {
                // Better.
                change = newChange;
                System.out.println("Better change for " + value + " = " + change);
                // Remember it.
                memory.put(value, change);
            }
        }
    }
    return change;
}