public class Test10 {
public static void main(String[] args) {
System.out.println("#####################方法一检测#####################");
System.out.println(buyCoke1(28));
System.out.println(buyCoke1(50));
//检测当人数能被3整除的情况
System.out.println(buyCoke1(99));
System.out.println("#####################方法二检测#####################");
System.out.println(buyCoke2(28));
System.out.println(buyCoke2(50));
System.out.println(buyCoke3(99));
System.out.println("#####################方法三检测#####################");
System.out.println(buyCoke3(28));
System.out.println(buyCoke3(50));
System.out.println(buyCoke3(99));
System.out.println("#####################健壮方法检测#####################");
System.out.println(buyCoke(28,1,3));
System.out.println(buyCoke(50,1,3));
System.out.println(buyCoke(99,1,3));
System.out.println(buyCoke(2014,7,9));
}
/*
* 思路:最后剩下的瓶盖,加上每个人喝掉的可乐,等于购买的可乐。
*
* 1、最后余下的瓶盖数capLeft,capLeft取值只可能是1、2、3(为什么会出现3呢?请见下面第3条分析。);计算式capLeft=28%3
* 2、一瓶可乐相当于3个瓶盖,每个人假如喝掉一瓶可乐(喝完可乐剩下一个瓶盖),则相当于每个人消费了2个瓶盖换取的可乐;
* 那么28个人喝掉的可乐转换成瓶盖总量,计算式28*2
* 3、总共瓶盖等于capLeft+28*2,即等于购买的可乐转换成的瓶盖数:bottleAll*3=capLeft+28*2
* 4、为什么会出现最后剩余瓶盖数为3呢?
* a、当总人数除3的余数是1的情况时,就会出现这种情况;
* b、先举例理解,如27个人时:当26个人都喝到了可乐,这时剩下2个瓶盖,有一种办法是去借一个瓶盖,然后凑足3个瓶盖换了一瓶可乐给第27个喝了,
* 然后产生的那个瓶盖再还给别人;但是我们找不到人借瓶盖,只能再买一瓶可乐,给第27个人,剩下一个瓶盖加上前面的2个,就剩下了3个;
* c、所以,用上面3步分析出来的结果:27个人应该是需要买18瓶,但是就会产生举例分析时的尴尬境地;所以27个人时应该是买27瓶,最后余3个瓶盖;
* 即:当人数除3余0时,结果是前3步的计算结果再加1;
* d、此分析也要加入到下面2个方法的分析中。
*/
//方法一:
public static int buyCoke1(int num){
//最后余下的瓶盖数capLeft
int capLeft = num%3;
//根据等式bottleAll*3=capLeft+28*2,总瓶盖数除3则是需要买的可乐瓶数
int bottleAll = (num*2+capLeft)/3;
//如果人数能被3整除,则返回bottleAll+1
if(capLeft == 0)
return bottleAll+1;
//否则返回bottleAll
return bottleAll;
}
/*
* 思路:假设每个人手上现在购买了两个瓶盖,则再需要加入1个瓶盖,就能使这个瓶盖循环利用,使大家都喝到可乐。
*
* 1、每个人手上有2个瓶盖,则有capUse = 28*2个瓶盖;
* 2、考虑到方法一的第4条分析,再额外添加1-3个瓶盖,就能让所有人喝到可乐;
* 3、capUse除3则是实际喝掉的可乐,考虑到不能整除情况下的类型自动提升为int,
* 则计算出的需要买的可乐瓶数为capUse/3 + 1;此时也满足了当人数是3的倍数的分析。
*/
//方法二:
public static int buyCoke2(int num){
//每个人手上有2个瓶盖,则有capUse = 28*2个瓶盖
int capUse = num*2;
//需要买的可乐瓶数为capUse/3 + 1
return capUse/3+1;
}
/*
* 思路:一瓶可乐相当于3个瓶盖,每个人假如喝掉一瓶可乐(喝完可乐剩下一个瓶盖),则相当于每个人实际喝掉了2/3瓶可乐。
*
* 1、总共喝掉的可乐瓶数为2/3*num,考虑到这个计算结果是浮点型,其中2/3对应的浮点数会被类型提升,则强制转型double bottleUse = (double)2/3*num;
* 2、参考方法一的第4条分析;由于最后会剩下1-3个瓶盖,则总共买的可乐瓶数是刚好大于bottleUse的整数;
* 3、所以采用Math.ceil方法,并且把返回的double数强转为int型;
* 4、加入判断,满足了当人数是3的倍数的分析;
* 5、参考方法二的第3条分析,则可将第3、4步简化为int bottleAll = bottleUse + 1,且不再做判断。
*/
//方法三:
public static int buyCoke3(int num){
//由于每个人实际相当于喝掉了2/3瓶可乐,则实际喝掉的可乐为bottleUse
double bottleUse = (double)2/3*num;
return (int)(bottleUse + 1);
}
//健壮函数,封装方法(采用方法二):
//分别传入参数:假设人数为num,每人要喝numBottle瓶可乐,每numCap个瓶盖可以换一瓶可乐,则需要买多少瓶可乐呢?
//使用JDK1.5新特性,可变参数
public static int buyCoke(int ... args){
//每个人手上的瓶盖数为args[1]*2,所有人手上瓶盖数int capUse = args[0]*args[1]*2
int capUse = args[0]*args[1]*2;
//需要购买的可乐瓶数为capUse/args[2]+1
return capUse/args[2]+1;
}
}
|