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

上周被人出了一道算法题目,题目的内容是:有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);
时间: 2024-10-07 05:23:07

10个小球用天平找出重量不同的那个的相关文章

c语言:用户输入10个整数,程序找出其中的最大值和最小值

程序: #include<stdio.h> int main() { int arr[10] = {0}; int i = 0; int max = 0; int min = 0; printf("请输入10个整数:"); for (i = 0; i < sizeof(arr)/ sizeof(arr[0]); i++) { scanf("%d",&arr[i]); } max = arr[0]; for (i = 0; i < si

编这样一个程序,用户输入10个整数,程序找出其中的最大值和最小值

#include<stdio.h> #include<string.h> int main() { char arr[10]={8,12,14,12,12,15,15,5,6,7}; char arr1[10]={8,12,14,12,12,15,15,5,6,7}; int max; int min; int i,j,k; for(i=0;i<9;i++) { j=i+1; if(arr[i]>arr[j]) { max=arr[i]; arr[j]=arr[i];

输入10个整数,程序找出其中的最大值和最小值

#include <stdio.h> int main() { int a[10], i, max,min; for (i = 0; i<10; i++) { printf("num%d=", i + 1); scanf("%d", &a[i]); } max = a[0]; min = a[0]; for (i = 0; i<10; i++) { if (a[i]>max) max = a[i]; if (a[i]<mi

【原创】字符串工具类--找出单元字符串

package week01; import java.util.regex.Matcher; import java.util.regex.Pattern; /**** * * 字符串帮助类 * @author csharper * @since 2014.10.08 * */ public class StringHelper { /*** * 找出单位字符串大小 * @param str 源字符串 * @return 单位字符串大小 */ public static int findUni

03-2. 用天平找小球(10)

三个球A.B.C,大小形状相同且其中有一个球与其他球重量不同.要求找出这个不一样的球. 输入格式: 输入在一行中给出3个正整数,顺序对应球A.B.C的重量. 输出格式: 在一行中输出唯一的那个不一样的球. 输入样例: 1 1 2 输出样例: C #include "stdio.h" int main() { int a,b,c; scanf("%d %d %d",&a,&b,&c); if(a==b) { printf("C&quo

分支-05. 用天平找小球(10)

#include<iostream>using namespace std;int main(){    int a,b,c;    cin>>a>>b>>c;    if(a==b)        cout<<"C"<<endl;    else if(b==c)        cout<<"A"<<endl;    else        cout<<&q

小球称重问题~通过三次称重找出十二个小球质量不一样的小球,并判断小球轻重

小球称重问题 一.问题描述 十二个小球进行称重,只能称三次,找出不一样的小球,并判断异球的轻重. 二.问题分析 将12个小球分成三组,将小球分别标号为1到12,分组情况如下: A组小球:1,2,3,4: B组小球:5,6,7,8: C组小球:9,10,11,12 情况分析:每个小球都有两种可能,一共会有24种判断结果. 三.算法分析 第一次,先将1-4号放在左边,5-8号放在右边. 1.如果右重则坏球在1-8号. 第二次将2-4号拿掉,将6-8号从右边移到左边,把9-11号放 在右边.就是说,把

从一千万条短信中找出重复次数最多的前10条

题目:      有1千万条短信,有重复,以文本文件的形式保存,一行一条.请用5分钟时间,找出重复出现最多的前10条. struct TNode { BYTE* pText; //直接指向文件映射的内存地址 DWORD dwCount; //计算器,记录此节点的相同短信数 TNode* ChildNodes[256]; //子节点数据,由于一个字母的ASCII值不可能超过256,所以子节点也不可能超过256 TNode() { //初始化成员 } ~TNode() { //释放资源 } }; /

怎样从10亿查询词找出出现频率最高的10个

转自:http://dongxicheng.org/big-data/select-ten-from-billions/ 1. 问题描述 在大规模数据处理中,常遇到的一类问题是,在海量数据中找出出现频率最高的前K个数,或者从海量数据中找出最大的前K个数,这类问题通常称为“top K”问题,如:在搜索引擎中,统计搜索最热门的10个查询词:在歌曲库中统计下载率最高的前10首歌等等. 2. 当前解决方案 针对top k类问题,通常比较好的方案是[分治+trie树/hash+小顶堆],即先将数据集按照h