腾讯面试题

Boos直聘上问答题:给定一个商品集合,不知道瑕疵品重量,请用天平找到瑕疵品。

import java.util.Arrays;

/**
 * 腾讯算法:给定一个商品集合,不知道瑕疵品重量,请用天平找到瑕疵品。
 */
public class Main {
    /**
     * 获取当前的称重次数
     *
     * @param products    商品数组
     * @param l           集合左边下标
     * @param r           集合右边下标
     * @param times       称重次数
     * @param isMoreHeavy 是否知道残次品轻重, -1表示不知道, 0表示否, 1表示是
     * @return 当前的称重次数
     */
    public static int weighingTimes(int[] products, int l, int r, int times, int isMoreHeavy) {
        int len = products.length;
        if (times == 0) {
            // 次数为0
            if (len <= 2) {
                return 0;
            }
        }
        if (isMoreHeavy == -1) {
            // 不知道瑕疵品轻重的时候
            if (r - l == 0) {
                // 如果不知道产品中是否有瑕疵品, 则需要多称重一次
//                    if (products[l - 1] == products[l]) {
//                        System.out.println("没有瑕疵产品");
//                        return times + 1;
//                    }

                // 如果知道, 则直接输出
                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;
//            if (remain == 0 || s1 == 0) {
//                System.err.println("没有残次品");
//                return 0;
//            }
            System.out.println("|不知道瑕疵品重量, 但是判定是在 [" + (l + 3 * rangeLen) + ", " + (l + 3 * rangeLen + remain - 1) + "]");
            // 9 9 9 2
            return weighingTimes(products, l + 3 * rangeLen, l + 3 * rangeLen + remain - 1, times + 2, -1);
        } else {
            // s1是残次品
            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);
                }
            }

            // s2是残次品
            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);
                }
            }

            // s2是残次品
            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;
    }

    /**
     * 余分法
     *
     * @param products    产品数量
     * @param l           产品左边下标
     * @param r           产品右边下标
     * @param times       称重次数
     * @param isMoreHeavy 是否知道残次品轻重, -1表示不知道, 0表示否, 1表示是
     * @return 天平称重次数
     */
    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; // 堆1和堆2
        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) {
                // 在s1上面
                System.out.println("|经过 1 次判断, 第一份重, 说明瑕疵品在第一份[" + l + ", " + (l + range - 1) + "]中, 继续对比");
                return trichotomy(products, l, l + range - 1, times + 1, isMoreHeavy);
            } else if (isMoreHeavy == 0) {
                // 在s2上面
                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) {
                // 在s2上面
                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) {
                // 在s1上面
                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;
    }

    /**
     * 开始天平称重环节
     *
     * @param plen:                   产品数量
     * @param faultyProductIndex:     瑕疵品下标
     * @param qualifiedProductWeight: 合格产品重量
     * @param faultyProductWeight:    不合格产品重量
     * @param isKnowProductWeight:	  是否知道瑕疵品轻重, 影响产品分堆逻辑
     */
    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 len = 10, faultyProductIndex = 0, qualifiedProductWeight = 3, faultyProductWeight = 2;
        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);
        }
//        start(11, 10, 3, 2);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值