码迷,mamicode.com
首页 > 其他好文 > 详细

10个小球用天平找出重量不同的那个

时间:2016-05-24 13:26:18      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:

上周被人出了一道算法题目,题目的内容是:有10个小球,外观一样,其中1个小球和其他9个小球重量不一样,请使用天平以最少的次数找出这个重量不一样的小球。

解题思路:其实这是一个很典型使用分治算法的例子,由于不知道这个特别的小球是比其他球重还是轻,所以我们不能简单的使用二分法去求解,所以我选择3为模。

解题步骤:

1、将10个球分成4个数组,分别是A[a1, a2, a3],B[b1, b2, b3], C[c1, c2, c3], D[d1];假设这个重量不一样的球为n,其他普通球的任意一个是m;

2、首先拿A和B、A和C称,如果A==B && A== C,那么直接得到结果n = d1;否则我们可以获得两个结果,第一个n in [A|B|C],第二个是n比m重还是轻。

说明:

  如果A > B && A > C, 那么n in A,n > m

  如果A > B && A == C,那么n in B,n < m

  如果A > B && A < C, 这种情况不存在

  如果A == B && A > C,那么n in C, n < m

  如果A == B && A == C,这种情况我们已经得到结果

  如果A == B && A < C,那么n in C, n > m

  如果A < B && A < C, 那么n in A,n < m

  如果A < B && A == C, 那么n in B,n > m

  如果A < B && A > C,这种情况不存在 

3、我们得到n in [A|B|C]后,取A、B、C中的前两个球称,因为已经知道n比m重还是轻,所以称完后可以直接得到n。假设n in A

说明:

  如果a1 > a2 && n > m, 那么n = a1

  如果a1 > a2 && n < m, 那么n = a2

  如果a1 == a2 ,那么n = a3

  如果a1 < a2 && n > m,那么n = a2

  如果a1 < a2 && n < m,那么n = a1

 

上代码:

<?php

$data = array(0, 0, 0, 0, 1, 0, 0, 0, 0, 0);

class filterBall {
    public $theSpecial; //特殊球 1 = 重, -1 = 轻
    public $balanceTimes = 0;
    /*
     * param integer & array $left 左边的球
     * param integer & array $right 右边的球
     * return 左边的球重=-1 相同重=0 右边球重=1
     */
    public function balance($left, $right) {
        $this->balanceTimes++;
        if (is_array($left)) {
            $left = array_sum($left);
        }
        if (is_array($right)) {
            $right = array_sum($right);
        }
        if ($left == $right) {
            return 0;
        } elseif ($left > $right) {
            return -1;
        } else {
            return 1;
        }
    }

    function execute($data) {
        $mod = intval(count($data) / 3); //取模
        // 将数组切分成3 - 4个每个有$mod个元素的数组
        $i = 0;
        $j = 0;
        $newArray = array();
        while($i < count($data)) {
            if (isset($newArray[$j]) && count($newArray[$j]) >= $mod) {
                $j++;
            }
            $newArray[$j][] = $data[$i];
            $i++;
        }

        $return0 = $this->balance($newArray[0], $newArray[1]);
        $return1 = $this->balance($newArray[0], $newArray[2]);
        switch((string)$return0.(string)$return1) {
            case ‘11‘:
                $this->theSpecial = -1;
                return 0 + $this->compareThird($newArray[0]);
            case ‘10‘:
                $this->theSpecial = 1;
                return 3 + $this->compareThird($newArray[1]);
            case ‘01‘:
                $this->theSpecial = 1;
                return 6 + $this->compareThird($newArray[2]);
            case ‘00‘:
                return 9;
            case ‘0-1‘:
                $this->theSpecial = -1;
                return 6 + $this->compareThird($newArray[2]);
            case ‘-10‘:
                $this->theSpecial = -1;
                return 3 + $this->compareThird($newArray[1]);
            case ‘-1-1‘:
                $this->theSpecial = 1;
                return 0 + $this->compareThird($newArray[0]);
        }
    }

    /*
     * 通过前两次的比对,知道特别球是重还是轻,然后在三个球中比对一次,知道三个球中特殊球的索引
     */
    public function compareThird($childArray) {
        $return = $this->balance($childArray[0], $childArray[1]);
        switch($return) {
            case 1:
            case -1:
                if ($return == $this->theSpecial) {
                    return 1;
                } else {
                    return 0;
                }
                break;
            case 0:
                return 2;
                break;
        }
    }
}

echo ‘<pre>‘;
print_r($data);
$filter = new filterBall();
echo sprintf(‘键值:%s, 比对了%s次‘, $filter->execute($data), $filter->balanceTimes);

 

10个小球用天平找出重量不同的那个

标签:

原文地址:http://www.cnblogs.com/davidlu8/p/5522917.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!