首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >组合多个质量以获得所需的总质量

组合多个质量以获得所需的总质量
EN

Code Review用户
提问于 2021-02-11 17:37:34
回答 1查看 93关注 0票数 2

这是我的密码。让我描述一下我在这里做什么。我有7公斤肥皂和2公斤肥皂。我总共有一公斤,也就是说我需要多少公斤香皂。我应该首先使用7公斤肥皂,如果没有必要,我不应该使用2公斤肥皂。如果我不使用任何2公斤肥皂,它必须返回-1,如果我使用2公斤肥皂,它必须返回的数量,其中多少我使用。我有prepareCargoPacket(int 7kg soap, int 2 kg soap, int totalKg)

例如,prepareCargoPacket(2,2,16);返回1s,因为我一次使用2kg肥皂。prepareCargoPacket(1,3,10);返回-1,因为我不能从这些值中得到10公斤,我不能使用2公斤肥皂

代码语言:javascript
复制
package com.bit32.cargocalculation;

public class CargoCalculation {


/**
 * Returns how many 2Kgs soap we need to use
 * 
 * @param count7Kg -> count of how many 7Kgs soaps we have
 * @param count2Kg -> count of how many 2Kgs soaps we have
 * @param totalKg  -> the needed Kg I have to get 
 * @return
 */


public int prepareCargoPacket(int count7Kg, int count2Kg, int totalKg) {

int solution = -1; // if there is no answer, or no need for 2Kgs soaps, the answer is -1

// if we have 7Kg ones many more than totalKg, we should decrease it to get from 2Kgs.      
if (7*count7Kg > totalKg) {
    return prepareCargoPacket(count7Kg-1, count2Kg, totalKg); 
    
// if we have enough 7Kgs that are equal to totalKg, we will not use 2Kgs.          
} else if (7*count7Kg == totalKg) {
    return solution; // solution = -1
    
// if we have 7Kgs less than totalKg        
} else {
    
// currentTotalKg is equal to the amount of Kg that we can use for 2Kgs     
    int currentTotalKg;
    for (int i = count7Kg; i>=0; i--) {
        
        currentTotalKg = totalKg - 7*i;
        
        if (currentTotalKg % 2 == 0 && count2Kg*2 >= currentTotalKg) {
            solution = currentTotalKg/2;
            break;

        } 
        return solution;
    }
                
}

return solution;

}
EN

回答 1

Code Review用户

回答已采纳

发布于 2021-02-12 00:56:44

首先,您的代码实际上在某些情况下不起作用。return循环中的for语句导致循环只运行一次。这意味着您的函数没有为prepareCargoPacket(2, 10, 12)找到解决方案(它使用1 7kg soap进行尝试,由于5不是2的倍数,所以无法通过if检查,然后在没有7kg肥皂的情况下返回-1 )。删除那个return修复了它。

另一件事,我想指出的是,你的方式上限7公斤肥皂是真的不太有效。当你有200000公斤肥皂时,如果你需要使总重量达到6公斤,你的功能就会称自己为200000次。由于多种原因,这是不理想的。这不仅是很多步骤(每一个步骤都需要一定的时间),而且程序还会在内部跟踪调用堆栈中的每个函数调用,而且在程序与java.lang.StackOverflowError崩溃之前,这种情况只会变得如此之大。

一种方法是注意到,如果你有超过totalKg / 7 7公斤肥皂,总重量已经太高了。所以如果你一开始有太多的7公斤肥皂,你不需要每次少试一次,因为totalKg / 7只是给了你一个很好的上限。

在结束一些挑剔,我不是一个狂热的球迷重复的重量肥皂到处这样。如果想要这个软件的人走过来对你说:“嗨,对不起,我们从7公斤肥皂换成了5公斤肥皂,你能帮我们更新一下程序吗?”在任何地方替换体重都会很烦人,而且会有丢失位置的危险。更好的方法可能是用常量变量代替数字,比如final int HEAVY_WEIGHT = 7;final int LIGHT_WEIGHT = 2;?这样,如果重量需要改变,它只发生在一个地方。在这一点上,我还可能考虑将输入参数重命名为类似于heavyAvailablelightAvailable的东西,以便在我进行此操作时匹配这些参数。

--再想想

我又看了看,想出了更多的评论。

除了可能存在大量函数调用的问题外,函数调用本身也会使逻辑变得更难理解。我想对它进行重构,这样就没有必要了,最初的检查不是用来重新输入函数,而是用来确定循环从哪里开始的。

另一个相当小的问题是,这个函数会持续更长的时间,即使它应该知道它不会找到解决方案。例如,如果被称为prepareCargoPacket(5, 0, 36),我们就进入循环,注意我们没有足够的2公斤肥皂来达到1公斤的重量。但是我们继续检查我们是否可以制造8公斤。因为我们的肥皂太少了。所以我们继续检查15公斤。但我们也做不到,所以我们检查一下我们能不能做22公斤.现在想象一下,如果我们不是从5岁和36岁开始,而是从142,857,142和1,000,000开始。

你没必要想象。我测试了它,它仍然非常快。千万不要低估计算机快速数学的能力。尽管如此,如果循环包含比几个基本的数学运算符和几个ifs更复杂的内容,这可能很重要,所以我将提出它,以供将来参考。我也觉得切换循环条件来考虑这一点也会使代码变得更简洁,但是它也变得不那么明显了,为什么它是这样写的,所以它可能并不是一个实际的改进。

老实说,解决方案变量似乎并不完全必要。每次函数返回时,它要么返回-1,要么第一次更改solution,然后立即返回。在这一点上,我可能会摆脱这个变量,以避免读者不得不跟踪它是否已经更新。这是一个品味的问题,但肯定有人会不同意我的意见。

最后,由于我已经对变量名进行了一些挑剔,我还不如抱怨最后几个。totalKg并不像它所能描述的那样具有描述性。它和currentTotalKg也有点混淆,因为“总计”和“当前总计”对我来说并没有那么明显--虽然这有时是描述两种价值观的最佳方式,但我们可能需要寻找一些东西,使它们的目的更加明显。按照他们正在做的事情,totalKg可能被更准确地描述为goalWeighttargetWeight,既然currentTotalKg是我们无法达到的数量,那么我们可以称之为missingWeightremainingWeight吗?

考虑到所有这些,我可能会写一些类似的东西

代码语言:javascript
复制
package com.bit32.cargocalculation;

public class CargoCalculation {

    public static final int HEAVY_WEIGHT = 7;
    public static final int LIGHT_WEIGHT = 2;

    /**
    * Calculates how many lightweight soaps we need to use to reach exactly the target weight, if possible
    * If no lightweight soaps are required, or if the target weight can't be reached, returns -1
    *
    * @param heavyAvailable The number of heavy soaps that can be used
    * @param lightAvailable The number of light soaps that can be used
    * @param targetWeight The desired sum of the weights of all the soaps
    * @return
    */
    public int prepareCargoPacket(int heavyAvailable, int lightAvailable, int targetWeight) {
        int maxHeavyUsed;
        if (HEAVY_WEIGHT * heavyAvailable > targetWeight) {
            maxHeavyUsed = targetWeight / HEAVY_WEIGHT;
        } else {
            maxHeavyUsed = heavyAvailable;
        }

        // Loop until we find a solution, or until we know we can't
        for (int remainingWeight = targetWeight - HEAVY_WEIGHT * maxHeavyUsed;
             remainingWeight <= LIGHT_WEIGHT * lightAvailable;
             remainingWeight += HEAVY_WEIGHT) {
            if (remainingWeight == 0) {
                // Special case: We have to return -1 if we don't need light soaps
                return -1;
            } else if (remainingWeight % LIGHT_WEIGHT == 0 &&
                       lightAvailable * LIGHT_WEIGHT >= remainingWeight) {
                return remainingWeight / LIGHT_WEIGHT;
            }
        }

        // No solution
        return -1;
    }
}

尽管正如我所说的,如果您认为将循环编写为for (int i = maxHeavyUsed; i >= 0; i--) (然后在循环中定义remainingWeight )更清楚,那么您可以这样做。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/255895

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档