PHP面试题精选

精选一些PHP面试题汇总一下给个参考:

数据库字段int(10)int(11)的区别

在字段被指定为int时就确定了他是占用4bytes(字节),也就是8bit(位),而int(10)代表的其实是显示宽度,也就是存储的时候如果不足10位会自动补全,比如int(4),输入的是100,那么会被补全为0100

所以int(M)中的M理解为最大显示宽度。最大有效显示宽度是255。显示宽度与存储大小或类型包含的值的范围无关。

charvarchar的区别

char(10)指定字符串长度为10,即使不足10位也一样占用10字节,并且MySQL在存储时会自动删除字符串末尾的空格。char一般用来存储很短并且固定长度的字符串,比如md5值。

varchar(n)用于存储可变长的字符串,长度为n个字节的可变长度且非Unicode的字符数据。比如varchar(10), 输入abc三个字符,那么实际存储大小为3个字节。除此之外,varchar还需要使用1或2个额外字节记录字符串的长度,如果列的最大长度小于等于255字节(是定义的最长长度,不是实际长度),则使用1个字节表示长度,否则使用2个字节来表示。

综上,在存储很短的固定长度的字符串上应该采用效率更高的char,而存储可变长度的字符串应该采用存储空间上更有优势的varchar

MyISAMInnoDB引擎的区别,怎样选用

InnoDB:
支持事务处理等
不加锁读取
支持外键
支持行锁
不支持FULLTEXT类型的索引
不保存表的具体行数,扫描表来计算有多少行
DELETE 表时,是一行一行的删除
InnoDB 把数据和索引存放在表空间里面
跨平台可直接拷贝使用
InnoDB中必须包含AUTO_INCREMENT类型字段的索引
表格很难被压缩

MyISAM:
不支持事务,回滚将造成不完全回滚,不具有原子性
不支持外键
不支持外键
支持全文搜索
保存表的具体行数,不带where时,直接返回保存的行数
DELETE 表时,先drop表,然后重建表
MyISAM 表被存放在三个文件 。frm 文件存放表格定义。 数据文件是MYD (MYData) 。 索引文件是MYI (MYIndex)引伸
跨平台很难直接拷贝
MyISAM中可以使AUTO_INCREMENT类型字段建立联合索引
表格可以被压缩

如何选择:
因为MyISAM相对简单所以在效率上要优于InnoDB.如果系统读多,写少。对原子性要求低。那么MyISAM最好的选择。且MyISAM恢复速度快。可直接用备份覆盖恢复。
如果系统读少,写多的时候,尤其是并发写入高的时候。InnoDB就是首选了。

MySQL扩展实现方式,分库分表策略

实现方式
业务拆分、主从复制,数据库分库与分表。

分库分表策略
id取模
首字符a-z
hash路由
中间件(例如Cobar)

参考:数据库分库分表策略的具体实现方案

mysql的索引是什么数据结构,为什么使用这种数据结构。

B+tree结构。
myisam引擎使用b+tree作为索引结构,叶节点的data域存放的是数据记录的地址,myisam索引文件和数据文件是分离的。
而innodb的数据文件本身就是索引文件,表数据文件本身就是按b+tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。

原因参考:
为什么mysql innodb索引是B+树数据结构

以下为常用算法

冒泡排序

function bubble_sort($array){
    $count = count($array);
    if ($count<=0) {
        return false;
    }
    for ($i=0; $i <$count ; $i++) {

        for ($j=0; $j <$count-$i-1 ; $j++) {

            if ($array[$j]>$array[$j+1]) {
                $tmp = $array[$j+1];
                $array[$j+1]=$array[$j];
                $array[$j]=$tmp;
            }
        }
    }
    return $array;
}

遍历文件夹内文件和子文件夹

function my_dir($dir) {
    $files = array();
    if(@$handle = opendir($dir)) { //加一个@,不然会有warning错误提示
        while(($file = readdir($handle)) !== false) {
            if($file != ".." && $file != ".") { //排除根目录;
                if(is_dir($dir."/".$file)) { //如果是子文件夹,就进行递归
                    $files[$file] = my_dir($dir."/".$file);
                } else { //不然就将文件的名字存入数组;
                    $files[] = $file;
                }
            }
        }
        closedir($handle);
        return $files;
    }
}

斐波那契数列

function fibonaci($n){
    if($n <= 0){
        return 0;
    }else if($n == 1){
        return 1;
    }
    $num1 = 0;
    $num2 = 1;
    $res = 0;
    for($i = 2; $i <= $n; $i++){
        $res = $num1 + $num2;
        $num1 = $num2;
        $num2 = $res;
    }
    return $res;
}

快速排序

方法一(递归):

/**
 * @param $arr
 * @return array
 * 快速排序
 */
function quick_sort($arr) {
    // 递归结束: 数组长度为1,直接返回
    $length = count($arr);
    if ($length <= 1) {
        return $arr;
    }
    // 数组元素有多个,则定义两个空数组
    $left = $right = array();
    // 使用for循环进行遍历,默认第一个元素作为中枢点
    for ($i = 1; $i < $length; $i++) {
        // 判断当前元素的大小
        if ($arr[$i] < $arr[0]) {
            $left[] = $arr[$i];
        } else {
            $right[] = $arr[$i];
        }
    }
    // 递归调用
    $left = quick_sort($left);
    $right = quick_sort($right);
    // 将所有的结果合并
    return array_merge($left, array($arr[0]), $right);// 中间切点
}

方法二(效率高):

/**
 * @param $low
 * @param $high
 * @param $arr
 * 快速排序 递归调用
 * 关键点在于part动作
 */
function qsort($low, $high, &$arr){
    if($low < $high){
        $pivot = part($low, $high, $arr);
        qsort($low, $pivot-1, $arr);
        qsort($pivot+1, $high, $arr);
    }

}


/**
 * @param $low
 * @param $high
 * @param $arr
 * @return mixed
 * part的核心动作在于-- 中枢点的位置不断变换,比它小的换到它的左边,比它大的换到它的右边
 */
function part($low, $high, &$arr){
    $pivot = $arr[$low];// 中枢点默认是列表第一个

    while($low < $high){
        while($low < $high && $arr[$high] >= $pivot){// 右边选比中枢点小的
            $high--;
        }
        swap($arr, $low, $high);// 此时中枢点在低位置,而此时的高位置小于中枢点。两点交换

        while($low < $high && $arr[$low] <= $pivot){// 左边选比中枢点大的
            $low++;
        }
        swap($arr, $low, $high);// 此时中枢点在高位置,而此时的低位置大于中枢点。两点交换
    }

    return $low;// 低位此时是中枢点,返回中枢点位置
}

/**
 * @param $arr
 * @param $i
 * @param $j
 * 交换位置
 */
function swap(&$arr, $i, $j){
    $temp = $arr[$i];
    $arr[$i] = $arr[$j];
    $arr[$j] = $temp;
}

计算N的质数

方法一(效率高):

/**
 * 求n以内的质数(在大于1的自然数中,除了1和它本身意外,无法被其他自然数整除的数)
 * @param int $n
 * @return array
 */
function get_prime($n) {
    $prime = array(2);//2为质数

    for ($i = 3; $i <= $n; $i += 2) {//偶数不是质数,步长可以加大
        $sqrt = intval(sqrt($i));//求根号n,只计算小于平方根的数,进一步缩小范围

        for ($j = 3; $j <= $sqrt; $j += 2) {//i是奇数,当然不能被偶数整除,步长也可以加大。
            if ($i % $j == 0) {
                break;
            }
        }

        if ($j > $sqrt) {
            array_push($prime, $i);
        }
    }

    return $prime;
}

方法二:

function get_prime_2($n) {
    $prime = array(2);

    for ($i=3; $i <= $n; $i++) { 
        $flag = 0;

        for ($j=2; $j < $i; $j++) { 
            if($i % $j == 0){
                $flag += 1;
                break;
            }
        }

        if(!$flag){
            array_push($prime, $i);
        }
    }

    return $prime;
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注