【芯片测试】有n片芯片,已知好芯片比坏芯片至少多1片。现在需要通过测试从中找出1片好芯片,测试方法如下:将2片芯片放到测试台上,2片芯片互相测试并报告测试结果(即好或者坏);其中,好芯片的报告是正确的,而坏芯片的报告是不可靠的。为保证使用更少的测试次数,请设计一个合适的算法解决上述问题
算法设计思路
- 当芯片数为偶数时,每两个互相测试,测试保存下来的芯片存到一个数组中(该数组记录原数组的芯片的下标)。
- 当芯片为奇数的时候,将从第一个芯片开始不断与最后一个芯片互相测试,当测试到最后一个芯片的结果为好的次数大于或者等于芯片数量的一半,则说明其为好芯片,否则为坏芯片。若为坏芯片,则不用管它,相当于奇数减一变成偶数了,因为偶数时是两个两个这样遍历的,如果最后一个为坏芯片,是多出来的奇数,也不会遍历到它(假设有5枚芯片,从第一片和第二片互相测试,第三片和第四片互相测试,再当n+2就大于5等于6了,不合乎循环条件了,则就自然不会遍历到最后一个芯片)
测试原则:
将这个数组的对应原数组的下标再开始两两测试。1、若测试结果都为好,则选一片出来保存,2、若测试结果一好一坏,或者两个都是坏,则都舍,这样的方法能保证舍弃的坏芯片最终会大于等于好芯片。
测试保存下来的芯片再放回这个数组,每次从该数组的首部开始放入,覆盖掉上一组的数据,不断循环下去,直到剩余3片芯片或者1片、2片。因为好芯片总要比坏芯片多1,所以剩下3片的时候,随便拿两片出来就可以得到一片好芯片(假设拿两个好的,直接保留一块,如果拿一好一坏,则都舍弃,剩下的就是好的),剩下2片或者剩下1片的时候,肯定都是好的。
算法实现的伪代码
算法compare( boolean[ ] chipArr , int left, int right)
输入:存放芯片的数组、左下标、右下标
输出:布尔值
- if (chipArr[left] = true && chipArr[right] = true)
- return true;
- else if ((chipArr[left] = true && chipArr[right] = false) || (chipArr[left] = false && chipArr[right] = true))
- return false;
- else
- if (r.nextInt(3) == 0)
- return true;
- else
- return false;
算法chipTest( boolean[ ] chipArr )
输入:存放芯片的数组、左下标、右下标
输出:布尔值
- count 当剩余芯片为奇数的时候用于记录对比结果为true的次数
- temp[chipArr.length] 用于记录筛选出来的芯片的下标
- Chip = chipArr.length 剩余芯片数
- for i = 0 to chipArr.length
- tempArr[ i ] = i
- while (Chip > 3)
- if (Chip % 2 != 0) 奇数
- compareChip = Chip-1 最后一枚芯片下标
- 将其他芯片与最后一片芯片互相测试
- if count 大于或等于芯片的数量的一半
- then 这个是好芯片,直接输出
- n = Chip 保留芯片的数量
- Chi = 0
- for i= 1 to n i+=2
- 后一片芯片与前一片芯片互相测试,
- if 保留到芯片
- then Chip++、
- if Chip = 3
- then 直接判断得出好芯片
实现代码
import java.util.Random;
public class Main {
static Random r = new Random();
public static void main(String[] args) {
boolean[] chipArr = {false,false,true,false,true,true,true,true,false};//初始化数组
chipTest(chipArr);
}
public static void chipTest(boolean[] chipArr) {
int count = 0; //当剩余芯片为奇数的时候用于记录对比结果为true的次数,若count >= 芯片数的一半,则说明被检测的那个芯片(选取最后一个)是好芯片,否则坏芯片
int[] tempArr = new int[chipArr.length]; //用于记录筛选出来的芯片的下标
int Chip = chipArr.length; //剩余芯片数
for (int i = 0; i < chipArr.length; i++) {
tempArr[i] = i; //为记录数组初始化,值对应这chipArr的下标
}
while (Chip > 3) { //当剩余芯片数大于3的时候就一直比较
if (Chip % 2 != 0) { //剩余芯片数为奇数时,用暴力算法,比较最后一枚芯片和其他芯片
int compareChip = Chip-1; //最后一枚芯片的下标
for (int i = 0; i < compareChip; i++) { //从第一枚芯片开始到最后一枚的前一枚与最后一枚芯片比较
if(compare(chipArr,compareChip,i))
count++; //若返回为true,则count++
if(count >= (Chip-1)/2){ //若刚刚好最后一个为好芯片,则直接输出,结束循环
System.out.println(tempArr[i]);
break;
}
else count = 0;
}
if(count >= (Chip-1)/2)
break;
}
int n = Chip; //记录剩余芯片数
Chip = 0; //令Chip为0,后面重新计算剩余的芯片数
for (int i = 1; i < n; i+=2) { //用后一枚芯片与前一枚芯片比较,两个两个比较
if(compare(chipArr,tempArr[i-1],tempArr[i])){
tempArr[Chip++] = tempArr[i-1]; //如果为真,temp数组以chip为下标就记录下原数组的该芯片的下标,剩余芯片+1
}
}
}
if(Chip==3){ //若剩余芯片刚好为3,则直接判断,得出好芯片
if(compare(chipArr,tempArr[0],tempArr[1])){
System.out.println(tempArr[0]);
}else
System.out.println(tempArr[2]);
}else
System.out.println(tempArr[0]);
}
public static boolean compare(boolean[] chipArr, int left, int right) { //两枚芯片互相测试
if (chipArr[left] == true && chipArr[right] == true) {
return true;
} else if ((chipArr[left] == true && chipArr[right] == false) || (chipArr[left] == false && chipArr[right] == true)) {
return false;
} else {
if (r.nextInt(3) == 0) { //两片芯片为坏的时候,有三分之一的概率返回测试结果为两个都为好
return true;
} else
return false;
}
}
}
写得不好,多请谅解!