试题链接:有假币__牛客网
先贴代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()){
//输入硬币数n:
int n = scanner.nextInt();
if (n == 0){ //当假币为0时,输入结束,退出循环
break;
}
if (n == 1){ //当假币为1时,不用称量就能知道它是否是假币(因为假币比真币轻)
System.out.println(0);
}else if (n <= 3){ //当假币数小于等于3时,只要称量一次就可以
System.out.println(1);
}else { //当假币数量大于3时:
int count = 1; //count为称量次数
while (n > 3){
if (n % 3 == 0){
n /= 3;
}else {
n = n / 3 + 1;
}
count++;
}
System.out.println(count);
}
}
}
}
解题思路:
题目要求我们要在最快时间内找出假币,并且给我们一个可以称量的天平,还告诉我们假币比真币要轻,那么此时很显然,我们需要将这些硬币分成相同的几堆,再对这几堆硬币分别进行称量,重量轻的那一堆就是假币所在的那一堆,再将轻的那一堆分开,继续上述步骤,就可以找出那一枚假币了。
可是问题来了,我们要分几堆呢?是分成两堆还是分成三堆亦或者分更多堆呢?再来看看题目的要求:想让我们在最快时间内找出来。那么就说明我们称量次数是越少越好,因为次数一多,难免要花费更多的时间。所以就应该在分两堆或者三堆中进行选择;为什么不选更多的堆数?
假如我们分成平均四堆,假币就在这四堆当中,那么我们需要称量几次得知假币的位置?两次!因为天平每次只能称量两堆硬币。而如果分成两堆或者三堆就只要称量一次就可以得知假币的位置。可是最后到底是分两堆还是三堆呢?因为若是分两堆,每次称量过后只能排除一半,而分三堆的话每一次称量后可以排除三分之二,相对来说更加高效一点。
确定分三堆后,接下来就是分硬币数 n 情况来讨论:
1、当n == 1时:只有一个硬币,无法上天平称量,但是可以直接判断是否为假币,所以是0次。
2、当n <= 3时:此时只要称量一次就可以得知假币的位置。
3、当n > 3时:需要将这些硬币分成三堆,分法是,能被3整除的,分成均匀的三堆,不能被3整除的,先将n除以3,得到的数无视小数取整,这个数是前两堆,剩下的为第三堆;比较的时候先比较前两堆,如果前两堆重量相等,那么假币就在第三堆里,再按照前面的方法,将第三堆也分为三堆,继续比较。