PHP 经典算法面试题

最近几天整理了一些php经典算法题,偏基础,欢迎指正。

  1. 一群猴子排成一圈,按1,2,…,n依次编号。然后从第1只开始数,数到第m只,把它踢出圈,从它后面再开始数,再数到第m只,在把它踢出去…,如此不停的进行下去,直到最后只剩下一只猴子为止,那只猴子就叫做大王。要求编程模拟此过程,输入m、n, 输出最后那个大王的编号。

思路

把猴子放到有序数组里,按顺序把符合要求的unset掉或者放到数组最后,递归循环。

function circle($n,$m)
{
    $list = []; 
    for($i = 1; $i <= $n; $i++)
    {
        $list[$i] = $i;
    }

    $array = kick($list, $m);

    return implode($array);
}

function kick($array,$m)
{
    if(count($array) == 1)
    {
        return $array;
    }

    foreach($array as $key => $value)
   {
       if($key%$m == 0) 
       {
           unset($array[$key]);
       }
       else
       {
           array_push($array,$array[$key]);
           unset($array[$key]);
       }
   }

    $array = kick($array, $m);

    return $array;

}

//  7
echo circle(8,3);
  1. 有一母牛,到4岁可生育,每年一头,所生均是一样的母牛,到15岁绝育,不再能生,20岁死亡,问n年后有多少头牛。

思路

设置统计总数,对单个牛遍历每一年,如果小于15岁同时是4的倍数,总数就加一(生了小牛),如果达到20岁就减一(本体死了),超过20岁跳出循环(总量不会因它变化了)。本题的精华在于,每出生一头小牛,对于它的总年数=总年数-出生之前的年数,这样可以算出它的产出和死亡共计多少牛,同时作为静态变量的总数累加算出结果。

function cow($year)
{
    static $sum = 1;

    for($i = 1; $i <= $year; $i++)
    {
        if($i > 20)
        {
            break;
        }
        if($i <15 && $i%4 == 0)
        {
            $sum++;
            cow($year - $i);
        }
        if($i == 20)
        {
            $sum --;
        }
    }

    return $sum;
}

echo cow(100);
  1. 杨辉三角

在这里插入图片描述
思路

两边是1,其他每个数 = 上一行对应两个数之和

function triangle($n)
{
    $base = ['1'=>[1],'2'=>[1,1],'3'=>[1,2,1]];

    if($n <= 3)
    {
        return $base;
    }

    for($i =4; $i <= $n; $i ++)
    {
        $temp = [1];
        for($j = 0; $j < count($base[$i - 1]) - 1; $j ++)
        {
            $temp[] = $base[$i - 1][$j] + $base[$i - 1][$j+1];
        }
        $temp[] = 1;
        $base[$i] = $temp;
    }

    return $base;
}

var_dump(triangle(10));
  1. 冒泡排序

思路

从第一个数开始,每个数和后面的数比较,把小的放前面,这样经过一次遍历后,最大的数会到最后一位,第二次遍历到倒数第二位即可,以此类推。

function maopao($data)
{
    $len = count($data);

    for($i = $len; $i > 1; $i --)
    {
        for($j = 0; $j < $i - 1; $j ++)
        {
            if($data[$j] > $data[$j + 1])
            {
                $temp = $data[$j + 1];
                $data[$j + 1] = $data[$j];
                $data[$j] = $temp;
            }
        }
    }

    return $data;
}

var_dump(maopao([5,1,8,3,6,4,9,2,7]));
  1. 快速排序

思路

取出第一位,遍历数组,小于它就放到 left 数组,大于等于它就放到 right 数组,再分别对 left 和 right 数组进行递归排序,形成树状结构,这样当只剩一位时,上方的节点都已排序好,组合即得。
这种算法最优时间复杂度是O(log2n),比冒泡的O(n)要快,最慢的情况一样。

function quick($data)
{
    if(count($data) <= 1)
    {
        return $data;
    }

    $key = $data[0];
    $left = [];
    $right = [];

    for($i = 1; $i < count($data); $i ++)
    {
        if($data[$i] < $key)
        {
            $left[] = $data[$i];
        }
        else
        {
            $right[] = $data[$i];
        }
    }

    $left = quick($left);
    $right = quick($right);

    return array_merge($left,array($key),$right);
}

var_dump(quick([5,1,8,3,6,4,9,2,7]));
  1. 二分查找顺序数组 返回下标

思路

每次取中间数对比,大了就和左边数对比,小了就和右边对比,我是截取数组,其实使用左右两个下标,对比后替换下标更节省内存,你们可以试试。

function twoSearch($x, $data)
{
    $i = round(count($data)/2);
    $middle = $data[$i];
    if($x == $middle)
    {
        return $i;
    }
    else if($x > $middle)
    {
        twoSearch($x, array_slice($data, 0, $i));
    }
    else
    {
        twoSearch($x, array_slice($data, $i, -1));
    }

    return false;
}

var_dump(twoSearch(16,[11,12,13,14,15,16,17,18,19,20]));
  1. 字符集合:输入一个字符串,求出该字符串包含的字符集合,并按顺序排序(英文)

思路

把字符串分割成数组,去重,再排序。

function character($data)
{
    $array = str_split($data); 
    $array = array_unique($array); 
    sort($array); 
    return implode('', $array);
}

var_dump(character('optimization'));
  1. 遍历一个文件下的所有文件和子文件夹下的文件

思路

使用php读取文件和文件夹的函数,遍历读取。

function readFile($dir)
{
    $data = [];

    if($handle = opendir($dir))
    {
        while($file = readdir($handle) != false)
        {
            if($file != '.' && $file != '..')
            {
                if(is_dir($dir.'/'.$file))
                {
                    $data[$file] = readFile($dir.'/'.$file);
                }
                else
                {
                    $data[] = $file;
                }
            }
        }

        closedir($handle);
    }
    return $data;
}
  1. 上一个n级的台阶,每次只能跨1级或者跨2级,问:有多少种方法走完台阶。

思路

当一个人走到第n级时,只有两种可能,在n-1级台阶跨一级,或者在n-1级台阶跨两级。

function fibonacci($n)
{
    if($n <= 2)
    {
        return $n == 1 ? 1 : 2;
    }

    $n = fibonacci($n - 1) + fibonacci($n - 2);

    return $n;
}

var_dump(fibonacci(10));
发布了5 篇原创文章 · 获赞 0 · 访问量 79

猜你喜欢

转载自blog.csdn.net/jy615183000/article/details/105271632
今日推荐