在一组芯片之间找到有缺陷的芯片

时间:2018-05-24 12:55:23

标签: algorithm time time-complexity

我是一名本科学生 - 计算机科学,在阅读过去的一些论文时,我遇到了这个问题:

我在O(n ^ 2)中解决了这个问题:

  1. 随机挑选任何筹码(枢轴),并将其与其他筹码(O(n))连接

  2. 如果超过一半的芯片表明“枢轴”是正常芯片,我可以简单地将其连接到其他芯片并获得缺陷芯片(O(n))

  3. 最糟糕的情况:如果我选择的枢轴是缺陷芯片,那么我就不能使用它,我将不得不检查(2n-1)芯片,直到找到所有缺陷(O(n ^ 2) ))

  4. 有没有更好的算法 - 或者任何人都可以提出任何读数,以便我得到一个提示?

2 个答案:

答案 0 :(得分:3)

线性时间算法

以下算法基于构建 partial 的信息(而不是立即了解特定芯片的状态,我们逐渐缩小芯片组的可能性),但确定(我们不以任何方式依赖概率,特别是我们不假设坏芯片曾经存在,或者说过真相)。以下两个观察结果是关键:

观察1:如果你拿了一把芯片,按照你想要的顺序排序,将每个芯片按顺序进行比较,发现它们都报告了另一个芯片是正常的,然后这一小撮中的芯片全部正常或全部有缺陷。 (要看到这一点,请注意,唯一的另一种可能性是少数中至少有一种芯片 - 但如果是这种情况,则必须至少有一对相邻各种芯片,在这种情况下,当这两个芯片互相测试时,好的芯片会正确地报告有缺陷的芯片有缺陷。这与我们的假设相矛盾,即少数报告中的每个芯片都是好的&#34 ;对于所涉及的所有(一个或两个)测试,它不会发生。)

观察2:如果您知道大部分优质芯片,并且您删除了一些好的芯片,并且至少有很多坏芯片,那么剩下的大部分芯片都是好的

该算法最多包括log2(n)+1"配对阶段",每个阶段对当前问题进行线性工作量,并导致一半大小的新问题,成为下一阶段的当前问题。这些阶段使我们能够确定一个好的芯片。有了这个,我们就可以在线性时间内可靠地检查每个其他芯片。

配对阶段算法在芯片的 bags 上运行,我们假设同一个包中的每个芯片具有相同的状态(好的或有缺陷的)。我们首先将每个2n芯片放在一个单独的包中,所以这个条件一开始就清楚了。我们还假设每相输入中的大部分芯片都是好的。问题陈述保证最初这是真的。

配对阶段

  1. 设B为芯片袋的输入集,让M为B的子集,仅包含最大尺寸的包(例如,如果B = {{2,4},{3,5,10},{ 7,8,9},{1}},然后M = {{3,5,10},{7,8,9}}。
  2. 如果| M |是奇怪的,将其中一个袋子移到剩余的#34;桩。还要将任何非最大尺寸的行李放入B(即B中的任何行李但不包括M行李)进入残羹堆。
  3. 以M任意方式将M中剩余的袋子排列成| M | / 2对(例如,将M中的第一个袋子与第二个袋子配对,第三个袋子与第四个袋子配对,等等)。
  4. 每对:
    • 将一对中的第一个袋子中的一些芯片与一对中的第二个袋子中的一些芯片进行比较。
    • 如果测试结果是两个筹码都报告了另一个筹码,那么将这两个筹码组合成一个新的筹码(包含两倍筹码)。根据观察1,这个新的双尺寸包中的所有芯片都是好的,或者它们都是有缺陷的。
    • 否则(当两个芯片中至少有一个报告另一个为#34;有缺陷")时,我们知道该对中的两个包中至少有一个仅包含有缺陷的芯片。由于这一对中的两个包具有相同的尺寸,观察2告诉我们如果我们丢弃两个包,剩下的芯片将继续拥有大部分优质芯片。
  5. 该阶段的输出是最多| M | / 2个双尺寸行李的集合,以及"剩余物中的行李"桩。也就是说,我们有效地丢弃了M对的袋子对,其中测试结果不是"好+好"。
  6. 如果我们将袋子保持为双重链接芯片列表,我们可以在两个袋子中将它们固定在一个袋子中:对于第一个袋子中的任何芯片x和第二个袋子中的任何芯片y,设置x.next.prev = y.prev,y.prev.next = x.next,x.next = y,y.prev = x。这样做当然"摧毁"最初的两个袋子,但这对我们来说并不重要,因为我们不需要那些原包装袋。

    每次迭代都会将一组行李作为输入,并生成一组行李作为输出。输出中最大尺寸行李的数量最多为输入中最大尺寸行李数量的一半;作为产量生产的非最大尺寸袋子的数量最多增加1.保持大部分芯片良好的特性。因此,在最多log2(n)+1迭代之后,将有一个独特的最大尺寸袋(尺寸等于2的某个功率),加上最多log2(n)+1个不同尺寸的小袋(也都具有大小是(不同的)2的幂。此时我们停下来。在这个最后一组袋子中,独特的最大尺寸的袋子包含大部分芯片,因为所有较小的袋子具有明显较小的2的力量。(这可以通过感应正式显示,但也许它'足以看到数字16,以二进制表示为10000,大于你可以通过打开低4位的任意组合产生的任何数字(相当于将2的不同较小的幂相加)。)

    由于独特的最大尺寸袋子占据了最后一袋袋子中所有芯片的大部分,我们知道这些芯片中的大多数都很好,并且这个袋子中的每个芯片都是同一种(好的或有缺陷的,必须是这个袋子里的每个芯片都是好的(如果它们很糟糕,其他袋子中没有足够的芯片来形成大部分好的芯片)。因此,从这个包中选择任何芯片,并使用它来可靠地测试每个其他芯片。最终扫描也需要线性时间,因此算法总体上是线性时间。

    实施例

    下图显示了该算法将如何处理8个好的芯片:

    1 2 3 4 5 6 7 8
    X X X X X X X X   Phase 1: Input (8 1-chip bags)
    X-X X-X X-X X-X   Phase 1: Pair up bags and compare each pair using 1 chip in each bag
    X=X X=X X=X X=X   Phase 1 output, phase 2 input
    X=X-X=X X=X-X=X   Phase 2: Pair up bags and compare each pair using 1 chip in each bag
    X=X=X=X X=X=X=X   Phase 2 output, phase 3 input
    X=X=X=X-X=X=X=X   Phase 3: Pair up bags and compare each pair using 1 chip in each bag
    X=X=X=X=X=X=X=X   Phase 3: Output has a single max-size bag.
    

    在下面的示例中,芯片3,4和6是有缺陷的,芯片3和4都是"谎言"当相互比较时(每个报告另一个好):

    1 2 3 4 5 6 7 8
    X X ! ! X ! X X   Phase 1: Input (8 1-chip bags)
    X-X !-! X-! X-X   Phase 2: Pair up bags and compare each pair using 1 chip in each bag
    X=X !=!     X=X   Phase 2: Output (discard chips 5, 6; keep the all-defective bag {3, 4})
    X=X-!=!     X=X   Phase 3: Only 2 bags in M to pair up and compare
                X=X   Phase 3: Output discards 1, 2, 3, 4; a single max-size bag X=X remains.
    

    在以下示例中,芯片3,4和6如前所述有缺陷,并且芯片3继续错误地将芯片4报告为良好,但芯片4正确地将芯片3报告为有缺陷。请注意,在其余两种情况下,图表将是相同的,其中芯片3报告芯片4是好的但芯片4报告芯片3有缺陷,或者两个芯片都报告另一个有缺陷:

    1 2 3 4 5 6 7 8
    X X ! ! X ! X X   Phase 1: Input (8 1-chip bags)
    X-X !-! X-! X-X   Phase 2: Pair up bags and compare each pair using 1 chip in each bag
    X=X         X=X   Phase 2: Output (discard chips 3, 4, 5, 6)
    X=X---------X=X   Phase 3: Only 2 bags in M to pair up and compare
    X=X=========X=X   Phase 3: Output has a single max-size bag.
    

    最后,我们在芯片之间进行了总共最多2n-1次比较(-个字符的运行),每个比较最多导致一次连接操作。

答案 1 :(得分:-1)

编辑:j_random_hacker是更好的解决方案。我不想删除我的,因为我认为那里有一些有趣的推理。实际上,对于类似的任务,你不知道好/坏芯片的数量,这(可能)仍然是你可以带来的最好的线性解决方案。

正如评论中所述,您不能百分百肯定,但也许这是问题的一部分,能够提及您的解决方案的可靠性。

首先你必须找到正确的芯片。我们可以这样做:

1) i=0
2) take chip[i] and chip[i+1]
3) get their results 1000x times
4) if one chip tells you 1000x times same result, take it as good one
5) if neither of the chip continues with the same result, i=i+2 and continue until you find it

这可能导致1000 * 2N = 2000N重复,仍然是O(N)

你错的可能性是1:2^1000,它的数量比宇宙中的原子大。这意味着,如果整个宇宙中有一个原子,那么#34;特殊的"你必须随机选择一个原子,你选择的确切的机会"那个"类似于你选择错误芯片的机会。

找到好芯片后,你只需将它与其他所有芯片进行比较,看看它们是否有效,这也是O(N)

总体复杂性:O(N)

空间要求:O(1),你需要内存中最多2个芯片,当你检查它们1000x时,你只需要知道它们的最后一个值,看它是否仍然相同。

应该有效的实际代码



class Chip {
    constructor() {
        this.defective = Math.random() < 0.5;
    }

    isOtherChipDefective(chip) {
        if (this.defective) {
            return Math.random() > 0.5;
        }

        return chip.amIDefective();
    }

    amIDefective() {
        return this.defective;
    }
}

function generateChips(size) {
    const chips = [];
    for (let i=0; i < size; i++) {
        chips.push(new Chip());
    }
    return chips;
}

function findGoodChip(chips) {
    for (let i = 0; i < chips.length - 1; i++) {
        let prevRes = null;
        console.log(`trying chip no. ${i}`)
        for (let j = 0; j < 1000; j++) {
            res = chips[i].isOtherChipDefective(chips[i + 1]);
            if (prevRes === null) {
                prevRes = res;
            }

            if (prevRes !== res) {
                console.log(`chip no. ${i} is defective, found out on ${j} try`)
                break;
            }

            if (j === 999) {
                console.log(`chip no. ${i} is good, found out on ${j} try`)
                return i;
            }
        }
    }

    return null;
}

function findSolution(chips) {
    const goodChip = chips[findGoodChip(chips)];
    const goodChips = [];
    const badChips = [];
    chips.forEach(chip => {
        if (goodChip.isOtherChipDefective(chip)) {
            badChips.push(chip);
        } else {
            goodChips.push(chip);
        }
    })

    return {goodChips, badChips};
}
const solution = findSolution(generateChips(10));
solution.goodChips.forEach(goodChip => console.log('should be good chip', !goodChip.amIDefective()));
solution.badChips.forEach(badChip => console.log('should be bad chip', badChip.amIDefective()));
&#13;
&#13;
&#13;

输出如下:

trying chip no. 0
chip no. 0 is defective, found out on 1 try
trying chip no. 1
chip no. 1 is defective, found out on 3 try
trying chip no. 2
chip no. 2 is good, found out on 999 try
should be good chip true
should be good chip true
should be good chip true
should be bad chip true
should be bad chip true
should be bad chip true
should be bad chip true
should be bad chip true
should be bad chip true
should be bad chip true

PS:此算法也不受任何输入约束 - 它会发现所有芯片是否有缺陷,所有芯片都是好的或两者之间的任何组合。