Boos直聘上问答题:给定一个商品集合,不知道瑕疵品重量,请用天平找到瑕疵品。
import java.util.Arrays;
public class Main {
public static int weighingTimes(int[] products, int l, int r, int times, int isMoreHeavy) {
int len = products.length;
if (times == 0) {
if (len <= 2) {
return 0;
}
}
if (isMoreHeavy == -1) {
if (r - l == 0) {
System.out.println("|瑕疵品下标: " + l);
return times;
} else if (r - l == 1) {
return weighingTimes(products, l - 1, r, times, -1);
}
} else if (isMoreHeavy == 0) {
return trichotomy(products, l, r, times, 0);
} else if (isMoreHeavy == 1) {
return trichotomy(products, l, r, times, 1);
}
int rangeLen = (r - l + 1) / 3;
int s1 = sum(products, l, l + rangeLen - 1);
int s2 = sum(products, l + rangeLen, l + 2 * rangeLen - 1);
int s3 = sum(products, l + 2 * rangeLen, l + 3 * rangeLen - 1);
System.out.println("|将堆分出三份, 每份长度: " + rangeLen);
System.out.println("|分别判断产品集合的重量, 下标 [" + l + ", " + (l + rangeLen - 1) + "]、[" + (l + rangeLen) + ", " + (l + 2 * rangeLen - 1) + "]、[" + (l + 2 * rangeLen) + ", " + (l + 3 * rangeLen - 1) + "]");
System.out.println("|三份重量分别为: " + s1 + " 、" + s2 + " 、" + s3);
if (s1 == s2 && s2 == s3) {
int remain = len - 3 * rangeLen;
System.out.println("|不知道瑕疵品重量, 但是判定是在 [" + (l + 3 * rangeLen) + ", " + (l + 3 * rangeLen + remain - 1) + "]");
return weighingTimes(products, l + 3 * rangeLen, l + 3 * rangeLen + remain - 1, times + 2, -1);
} else {
if (s2 == s3) {
if (s1 > s2) {
System.out.println("|经过 2 次判断, 判定瑕疵品是重的, 且在 [" + l + ", " + (l + rangeLen - 1) + "]");
return trichotomy(products, l, l + rangeLen - 1, times + 2, 1);
} else {
System.out.println("|经过 2 次判断, 判定瑕疵品是轻的, 且在[" + l + ", " + (l + rangeLen - 1) + "]");
return trichotomy(products, l, l + rangeLen - 1, times + 2, 0);
}
}
if (s1 == s3) {
if (s2 > s1) {
System.out.println("|经过 2 次判断, 判定瑕疵品是重的, 且在[" + (l + rangeLen) + ", " + (l + 2 * rangeLen - 1) + "]");
return trichotomy(products, l + rangeLen, l + 2 * rangeLen - 1, times + 2, 1);
} else {
System.out.println("|经过 2 次判断, 判定瑕疵品是轻的, 且在[" + (l + rangeLen) + ", " + (l + 2 * rangeLen - 1) + "]");
return trichotomy(products, l + rangeLen, l + 2 * rangeLen - 1, times + 2, 0);
}
}
if (s1 == s2) {
if (s3 > s1) {
System.out.println("|经过 2 次判断, 判定瑕疵品是重的, 且在[" + (l + 2 * rangeLen) + ", " + (l + 3 * rangeLen - 1) + "]");
return trichotomy(products, l + 2 * rangeLen, l + 3 * rangeLen - 1, times + 2, 1);
} else {
System.out.println("|经过 2 次判断, 判定瑕疵品是轻的, 且在[" + (l + 2 * rangeLen) + ", " + (l + 3 * rangeLen - 1) + "]");
return trichotomy(products, l + 2 * rangeLen, l + 3 * rangeLen - 1, times + 2, 0);
}
}
}
return 0;
}
public static int trichotomy(int[] products, int l, int r, int times, int isMoreHeavy) {
if (isMoreHeavy == -1) {
System.err.println("error余分法");
return 0;
}
int H = r - l;
int range;
int s1, s2;
if (H == 0) {
System.out.println("|瑕疵品下标: " + l);
return times;
} else {
range = (int) Math.ceil(H / 3.0);
}
s1 = sum(products, l, l + range - 1);
s2 = sum(products, l + range, l + 2 * range - 1);
System.out.println("|将[" + l + ", " + r + "]的产品分出来两份, 每份有" + range + "个 [" + l + ", " + (l + range - 1) + "] 和 [" + (l + range) + ", " + (l + 2 * range - 1) + "]");
System.out.println("|第一份重量为: " + s1 + ", 第二份重量为: " + s2);
if (s1 == s2) {
System.out.println("|经过 1 次判断, 两份相等, 说明瑕疵品在剩余的那份[" + (l + 2 * range) + ", " + r + "]中, 继续对比");
return trichotomy(products, l + 2 * range, r, times + 1, isMoreHeavy);
} else if (s1 > s2) {
if (isMoreHeavy == 1) {
System.out.println("|经过 1 次判断, 第一份重, 说明瑕疵品在第一份[" + l + ", " + (l + range - 1) + "]中, 继续对比");
return trichotomy(products, l, l + range - 1, times + 1, isMoreHeavy);
} else if (isMoreHeavy == 0) {
System.out.println("|经过 1 次判断, 第二份轻, 说明瑕疵品在第二份[" + (l + range) + ", " + (l + 2 * range - 1) + "]中, 继续对比");
return trichotomy(products, l + range, l + 2 * range - 1, times + 1, isMoreHeavy);
}
} else {
if (isMoreHeavy == 1) {
System.out.println("|经过 1 次判断, 第二份重, 说明瑕疵品在第二份[" + (l + range) + ", " + (l + 2 * range - 1) + "]中, 继续对比");
return trichotomy(products, l + range, l + 2 * range - 1, times + 1, isMoreHeavy);
} else if (isMoreHeavy == 0) {
System.out.println("|经过 1 次判断, 第一份轻, 说明瑕疵品在第一份[" + l + ", " + (l + range - 1) + "]中, 继续对比");
return trichotomy(products, l, l + range - 1, times + 1, isMoreHeavy);
}
}
return 0;
}
public static int sum(int[] arr, int l, int r) {
int sum = 0;
for (int i = l; i <= r; i++) {
sum += arr[i];
}
return sum;
}
public static void startWeighting(int plen, int faultyProductIndex, int qualifiedProductWeight,
int faultyProductWeight, boolean isKnowFaultyProductWeight) {
if (qualifiedProductWeight == faultyProductWeight) {
System.out.println("根据条件不能生成瑕疵品");
return;
} else if (faultyProductIndex >= plen) {
System.out.println("生成条件有误: Out Of Index");
System.out.println("瑕疵品下标是: " + faultyProductIndex);
System.out.println("产品长度: " + plen);
return;
}
int[] ints = new int[plen];
Arrays.fill(ints, qualifiedProductWeight);
ints[faultyProductIndex] = faultyProductWeight;
System.out.println("┌-----------------------------------------┐");
System.out.println("|");
System.out.println("|产品集合长度为: " + plen + ", 瑕疵品下标: " + faultyProductIndex);
System.out.println("|合格产品重量为: " + qualifiedProductWeight + ", 不合格重量为: " + faultyProductWeight);
System.out.println("|------------开始进行分堆识别-------------|");
int times = weighingTimes(ints, 0, ints.length - 1, 0, isKnowFaultyProductWeight?
(faultyProductWeight > qualifiedProductWeight ? 1 : 0) : -1);
System.out.println("|称重次数: " + times);
System.out.println("└-----------------------------------------┘");
System.out.println();
}
public static void main(String[] args) {
for (int i = 0; i <= 12; i++) {
startWeighting(6, i, 3, 2, false);
}
}
}