今天看到一个关于PHP的面试算法题目,心血来潮就写了下

1、第一题 统计数字出现个数

输入一串字符,只包含"0-10"和’,’,找出最小的数字和最大的数字(可能不止一个),输出最后剩余的数字个数,如输入"3,3,4,5,6,7,7"。

其实看题目就能看出是我们平时通过ajax提交数组,然后处理数组内的数据,很简单直接上代码
<?php declare(strict_types=1);
$string = "3,3,4,5,6,7,7,10,10";
$arr = explode(",", $string);
$minCount = 0; // 记录所有的最小值的个数
$maxCount = 0; // 记录所有最大值个数
$min = $max = $arr[0]; // 最小和最大初始值
$count = count($arr);

foreach ($arr as $val) {
	// 计算最小数据
    if ($val === $min) {
        $minCount++; //如果跟原数据相等,累计即可
    } else if($val < $min) {
        $min = $val; // 如果新的值比原数据更小,重新赋值并且累计重置到1
        $minCount = 1;
    }
	// 计算最大值
    if ($val === $max) {
        $maxCount ++;
    } else if($val > $max) {
        $max = $val;
        $maxCount = 1;
    }
}
// 注意:上面有个小坑,那就是 $string 值如果全部相等,即min和max的值相等时候的处理,
// 如:$string = '5,5,5,5,5,5,5,5',此时输出就有问题
$result = sprintf("最小值为%d,共计%d个\n最大值为%d,共计%d个\n总数字个数为:%d,剩余数字个数为%d\n",
    $min,$minCount,$max,$maxCount,$count,($count-$minCount-$maxCount)
);
echo $result;
//最小值为3,共计2个
//最大值为10,共计2个
//总数字个数为:9,剩余数字个数为5

2、第二题 计算相邻差值

输入一组身高在170-190之间(共5个),比较身高差,选出身高差最小的两个身高,若身高差相同,选择平均身高高的那两个身高,从小到大输出结果。

分析一下:其实就是计算相邻数字的差值比较,统计出比值最小的两个元素。
注意:如果所有相邻的数值差相等,就要取出最大的两个数值,如:[170,175,180,185,190]取出的就是185,190两个数据。

简单分析完看下代码

<?php declare(strict_types=1);
//$arr = [170,171,180,185,190];  // 最小身高差为1  170,171
//$arr = [170,175,182,185,190]
$arr = [170,175,180,185,190];  // 最小身高差一致   取 185,190
sort($arr); //首先从小到大排序数组,如果差值相同,取最后的数据即可
$hc = $arr[1] - $arr[0]; // 默认身高差
$min = $max = $arr[0]; // 初始化最小与最大的身高差的值
$count = count($arr);
// 从 1 开始是因为初始化时候已经取了第1个数据,所以第一个数据不用比较
for($i = 1; $i < $count; $i ++) {
    // 最小身高差
    if ($arr[$i] - $arr[$i - 1]  <= $hc) {
        $hc = $arr[$i] - $arr[$i - 1];
        [$min, $max] = [$arr[$i - 1], $arr[$i]];
    }
}
// 注意:此处有个坑,虽然计算出来没问题,但是显示的结果确有问题,那就是浮点数,身高肯定有
// 小数位的,修改修改就好,很简单。
echo sprintf("最小身高差为%d,最小身高与最大身高为%d,%d\n",$hc,$min,$max);
//最小身高差为1,最小身高与最大身高为170,171
//最小身高差为3,最小身高与最大身高为182,185
//最小身高差为5,最小身高与最大身高为185,190

3、第三题 统计字符串内的重复字符

有一串字符串strings = “ababab”,这个字符串可以看做是由3个"ab"组成。即n=3,L=“ab”,s=nL,现要求编写一段程序,使用单列模式输入任意字符串s,输出nL,如输入aaaaa输出为5a,输入ababa输出1ababa;

分析:首先字符是要有一定的规律重复才需要统计,若无规律直接返回即可;

代码如下:

<?php declare(strict_types=1);
class DoString
{
    private static $instance = null;
    private static $string = '';

    public static function getInstance(string $string = ''): self
    {
        if (!self::$instance || !self::$instance instanceof self) {
            self::$instance = new self();
        }
        if (!empty($string) && self::$string !== $string) {
            self::$string = $string;
        }
        return self::$instance;
    }

    public function makeString(): string
    {
        if (!self::$string)
            return '';
        //1、判断是否全部是重复的数据
        $arr = str_split(self::$string);
        $lx = array_unique($arr); // 除掉重复的字符
        // 如果全部是重复的,那么就直接返回
        if (count($lx) === 1) {
            return count($arr) . $lx[0];
        }
        $sep = $this->makeEvenData(self::$string);
        $arr = str_split(self::$string, strlen($sep));
        return count($arr) . $sep;
    }

    // 取原子
    private function makeEvenData(string $str = ''): string
    {
        $sepArr = [];
        $len = strlen($str);
        for ($i = 2; $i <= $len; $i++) {
            if ($len % $i === 0) {
                $sepArr[] = $i;
            }
        }
        $count = count($sepArr);
        if ($count === 1) {
            return $str;
        }

        foreach ($sepArr as $val) {
            $arr = str_split($str, $val);
            if ($this->equalData($arr)) {
                return $arr[0];
            }
        }
        return '';
    }

    private function equalData(...$arguments): bool
    {
        $res = true;
        $out = null;
        foreach ($arguments[0] as $k => $val) {
            if ($k === 0) {
                $out = $val;
            } else if ($out !== $val) {
                $res = false;
                break;
            }
        }
        return $res;
    }
}

echo DoString::getInstance('bbbaabbbaa')->makeString(), PHP_EOL;
echo DoString::getInstance()->makeString(), PHP_EOL;
//2bbbaa
//2bbbaa

4、总结

其实上面的几个题目都不复杂,甚至还有其它好几种方法可以解决。主要是看个人第一时间的想法怎么实现。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值