PHP Interview Questions(11)

面试时间:2019 年 11 月 4 日,星期一,下午两点。


1. 给定一个二维数组,数组每一行从左到右都是递增的,每一列也是递增的。请完成一个函数,输入为如上二维数组和一个整数,函数功能为判断该整数是否存在于数组中。时间复杂度尽可能的低。(请说明你的算法的复杂度。)

下面是一个例子:

二维数组:

1 2 8 9

2 4 9 12

4 7 10 13

6 8 11 15

数字:9

<?php

$array = [
    [1, 2, 8, 9],
    [2, 4, 9, 12],
    [4, 7, 10, 13],
    [6, 8, 11, 15],
];

$number = 9;

/**
 * 最简单的方法就是遍历整个数组
 * 时间复杂度 O(Row*Column-1)
 */
function findNumberInArray($array, $number) {
    foreach ($array as $rowArray) {
        foreach ($rowArray as $value) {
            echo $value, " ";
            if ($number == $value) {
                return true;
            }
        }
    }

    return false;
}

/**
 * 从二维数组的左下角开始逐行查找
 * 时间复杂度 O(Row+Column-1)
 */
function findNumberInArray2($array, $number) {
    $minRow = 0;
    $minColumn = 0;
    $maxRow = count($array) - 1;
    $maxColumn = count($array[0]) - 1;

    if ($number < $array[0][0] || $number > $array[$maxRow][$maxColumn]) {
        return false;
    }

    for ($row = $maxRow; $row >= $minRow; $row--) {
        for ($column = $minColumn; $column <= $maxColumn; $column++) {
            echo $array[$row][$column], " ";
            if ($array[$row][$column] == $number) {
                return true;
            }
            if ($array[$row][$column] > $number) {
                break;
            }
            if ($array[$row][$column] < $number) {
                $minColumn = $column + 1;
            }
        }
    }

    return false;
}

/**
 * 从二维数组的右上角开始逐行查找
 * 时间复杂度 O(Row+Column-1)
 */
function findNumberInArray3($array, $number) {
    $minRow = 0;
    $minColumn = 0;
    $maxRow = count($array) - 1;
    $maxColumn = count($array[0]) - 1;

    if ($number < $array[0][0] || $number > $array[$maxRow][$maxColumn]) {
        return false;
    }
    
    for ($row = $minRow; $row <= $maxRow; $row++) {
        for ($column = $maxColumn; $column >= $minColumn; $column--) {
            echo $array[$row][$column], " ";
            if ($array[$row][$column] == $number) {
                return true;
            }
            if ($array[$row][$column] > $number) {
                $maxColumn = $column - 1;
            }
            if ($array[$row][$column] < $number) {
                break;
            }
        }
    }

    return false;
}

echo "/**
* 最简单的方法就是遍历整个数组
* 时间复杂度 O(Row*Column-1)
*/\n";
for ($number = 0; $number <= 15; $number++) {
    echo "find ", $number, ": ";
    findNumberInArray($array, $number);
    echo "\n";
}

echo "/**
* 从二维数组的左下角开始逐行查找
* 时间复杂度 O(Row+Column-1)
*/\n";
for ($number = 0; $number <= 15; $number++) {
    echo "find ", $number, ": ";
    findNumberInArray2($array, $number);
    echo "\n";
}

echo "/**
* 从二维数组的右上角开始逐行查找
* 时间复杂度 O(Row+Column-1)
*/\n";
for ($number = 0; $number <= 15; $number++) {
    echo "find ", $number, ": ";
    findNumberInArray3($array, $number);
    echo "\n";
}

2.把数组最开始的若干个元素搬到数组末尾,称为数组的旋转。给定一个递增数组的旋转数组,请完成一个函数,时间复杂度尽可能的低,输出该旋转数组的最小元素。并给出复杂度。

例如输入数组(4,5,6,7,8,10,1,2,3),输出 1。

<?php

$array = [4, 5, 6, 7, 8, 10, 1, 2, 3];

/**
 * 使用 min() 函数
 * 时间复杂度:O(N)
 * 源码:https://github.com/php/php-src/blob/master/ext/standard/array.c
 */
echo min($array), "\n";

/**
 * 使用二分查找法
 * 时间复杂度:O(log2N)
 */
function findMinimumNumberInArray($array, $start = 0, $end = null) {
    if ($end == null) {
        $end = count($array) - 1;
    }

    if ($start == $end) {
        return $array[$start];
    }

    $middle = floor(($start + $end) / 2);

    if ($array[$start] < $array[$end]) {
        return findMinimumNumberInArray($array, $start, $middle);
    } else {
        return findMinimumNumberInArray($array, $middle, $end);
    }
}

echo findMinimumNumberInArray($array), "\n";

3.输入一个字符串,输出该字符串中字符的所有组合。(不限编程语言,请注明你选择的语言)

下面是一个例子:

输入参数:字符串:“abc”

输出:“a”, “b”, “c”, “ab”, “ac”, “bc”, “abc”

<?php

$string = "abc";
$length = strlen($string);

/**
 * 使用二进制表示不同的排列组合
 * 
 * 0 0 1 a
 * 0 1 0 b
 * 0 1 1 ab
 * 1 0 0 c
 * 1 0 1 ac
 * 1 1 0 bc
 * 1 1 1 abc
 */
 for ($i = 1; $i < 1 << $length; $i++) {
     for ($j = 0; $j < $length; $j++) {
         if ($i & (1 << $j)) {
             echo $string[$j];
         }
     }
     echo "\n";
 }

参考:

剑指Offer面试题:2.二维数组中的查找

剑指Offer面试题:7.旋转数组的最小数字

剑指Offer面试题:26.字符串的排列

127 total views, 7 views today

GitLab CI/CD

Workflow

GitLab workflow example

准备工作

在开始使用 GitLab CI/CD 之前,我们需要完成以下准备工作。

  1. 安装 Gitlab 和 Gitlab Runer。
  2. 生成一对 SSH Private Key 和 SSH Public Key。

SSH Private Key 配置在 Setting > CI/CD > Variables 里面。

SSH Public Key 配置在要部署的服务器上的 ~/.ssh/authorized_keys 文件里面。


下面我们用两个例子来体验一下 GitLab CI / CD 配置文件 .gitlab-ci.yml 的语法。

PHP Examples

image: tanghengzhi/gitlab-deploy

before_script:
    # Add the private SSH key to the build environment
    - mkdir -p ~/.ssh
    - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config

stages:
    - test
    - deploy

test:
    stage: test
    script: echo 'PHP is the best language in the world'
    only:
        - master

deploy-dev-and-test:
    stage: deploy
    script:
        # Run git pull
        - ssh ec2-user@54.223.162.119 sudo git -C /opt/case/woof-go-waybill pull
        - ssh ec2-user@54.223.162.119 sudo git -C /opt/case/woof-go-waybill-beta pull
    only:
        - master

deploy-online-1:
    stage: deploy
    script:
        # Run git pull
        - ssh ec2-user@54.222.244.71 sudo git -C /opt/case/waybill-service pull
    when: manual
    only:
        - master

deploy-online-2:
    stage: deploy
    script:
        # Run git pull
        - ssh ec2-user@52.81.109.73 sudo git -C /opt/case/waybill-service pull
    when: manual
    only:
        - master

Java Examples

image: tanghengzhi/gitlab-deploy:java

before_script:
    # Add the private SSH key to the build environment
    - mkdir -p ~/.ssh
    - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa
    - chmod 600 ~/.ssh/id_rsa
    - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config

stages:
    - build
    - deploy

build:
    stage: build
    script:
        - ./gradlew build
    artifacts:
        paths:
          - build/libs/*.jar
    only:
        - master

deploy-dev:
    stage: deploy
    script:
        - rsync build/libs/*.jar ec2-user@54.223.162.119:/opt/case/waybill-service/build/libs/
        - ssh ec2-user@54.223.162.119 sudo service waybill-service restart
    only:
        - master

参考:

https://docs.gitlab.com/ee/ci/introduction/index.html

https://docs.gitlab.com/ee/ci/

https://github.com/tanghengzhi/gitlab-deploy

434 total views, 2 views today

PHP Interview Questions(10)

面试时间:2019 年 3 月 22 日,星期五,下午四点。


什么是命名空间?

https://www.php.net/manual/zh/language.namespaces.rationale.php

Redis 常见数据结构的使用场景。

https://my.oschina.net/manmao/blog/688230

如何基于 Redis 设计一个秒杀系统。

把商品库存放入 Redis 队列。

了解过 JWT 吗?

https://jwt.io/

了解过 Protocol Buffers 吗?

https://developers.google.com/protocol-buffers/

在实际项目中使用过 Swoole 吗?

https://www.swoole.com/

Go 语言中的 slice 和 map 是线程安全的吗?

https://halfrost.com/go_map_chapter_one/
https://halfrost.com/go_map_chapter_two/

遇到过 TCP 粘包问题吗?如何解决。

https://crossoverjie.top/2018/08/03/netty/Netty(3)TCP-Sticky/

214 total views, no views today

PHP Interview Questions(9)

面试时间:2019 年 3 月 22 日,星期五,下午四点。


审批流程数据库设计

https://www.cnblogs.com/yyy116008/p/8330076.html

MySQL 索引数据结构

Most MySQL indexes (PRIMARY KEY, UNIQUE, INDEX, and FULLTEXT) are stored in B-trees. Exceptions: Indexes on spatial data types use R-trees; MEMORY tables also support hash indexes; InnoDB uses inverted lists for FULLTEXT indexes.

 b-tree 和 b+tree 的区别

B-Tree
B+Tree

非聚集索引和聚集索引的区别

MySQL MyISAM Primary Key(非聚集索引)
MySQL MyISAM Secondary Key(非聚集索引)
MySQL InnoDB Primary Key(聚集索引)
MySQL InnoDB Secondray Key(聚集索引)

参考:

https://dev.mysql.com/doc/refman/8.0/en/mysql-indexes.html

http://blog.codinglabs.org/articles/theory-of-mysql-index.html

223 total views, 2 views today

Leetcode: 3 Sum

久违的刷一发 Leetcode。

3 Sum

PHP

class Solution {

    /**
     * @param Integer[] $nums
     * @return Integer[][]
     */
    function threeSum($nums) {
        sort($nums);
        $count = count($nums);
        $result = [];
        for ($i = 0; $i < $count - 2; $i++) {
            $j = $i + 1;
            $k = $count - 1;
            while ($j < $k) {
                $sum = $nums[$i] + $nums[$j] + $nums[$k];
                if ($sum === 0) {
                    $result[$nums[$i].",".$nums[$j].",".$nums[$k]] = [$nums[$i], $nums[$j], $nums[$k]];
                    $j++;
                    $k--;
                } elseif ($sum < 0) {
                    $j++;
                } else {
                    $k--;
                }
            }
        }
        return $result;
    }
}

246 total views, no views today

PHP Magic constants: Difference between __FUNCTION__ and __METHOD__

今天我们来比较一下两个 PHP 魔术常量:__FUNCTION__ 和 __METHOD__。

首先看一下官方文档的定义,然后再用几个简单的例子来比较。

__FUNCTION__The function name, or {closure} for anonymous functions.
__METHOD__The class method name.

1. Class 里面的方法

<?php

namespace App;

class Test {
	public static function run() {
		echo __FUNCTION__ , "\n";
		echo __METHOD__ , "\n";
                echo __CLASS__ , '::' , __FUNCTION__ , "\n";
	}
}

Test::run();
$ php Test.php
run
App\Test::run
App\Test::run

2. 函数和闭包

<?php

namespace App;

function test() {
	echo __FUNCTION__ , "\n";
	echo __METHOD__ , "\n";
}

$closure = function() {
	echo __FUNCTION__ , "\n";
	echo __METHOD__ , "\n";
};

test();
$closure();
$ php Test.php
App\test
App\test
App\{closure}
App\{closure}

3. 继承和Trait

<?php

namespace App;

class Papa {
	public static function test() {
		echo __FUNCTION__ . "\n";
		echo __METHOD__ , "\n";
		echo __CLASS__ , '::' , __FUNCTION__ , "\n";
	}
}

trait Mama
{
	public static function test() {
		echo __FUNCTION__ . "\n";
		echo __METHOD__ , "\n";
		echo __CLASS__ , '::' , __FUNCTION__ , "\n";
	}
}


class Test extends Papa {

	use Mama;

	public static function run() {
		parent::test();
		self::test();
	}
}

Test::run();
$ php Test.php
test
App\Papa::test
App\Papa::test
test
App\Mama::test
App\Test::test

总结

最后简单的总结一下:

不在 Class 里面__FUNCTION__ = __METHOD__
在 Class 里面(don‘t use trait)__CLASS__ . “::” . __FUNCTION__ = __METHOD__
在 Class 里面(use trait)只有 __METHOD__ 的结果是正确的。

所以不管什么情况,用 __METHOD__ 就对了。


参考:

http://php.net/manual/en/language.constants.predefined.php

307 total views, 2 views today

PHP Interview Questions(8)

面试时间:2018 年 9 月 21 日,星期五,下午三点。


单例模式

final class Singleton
{
    /**
     * @var Singleton
     */
    private static $instance;
    /**
     * gets the instance via lazy initialization (created on first usage)
     */
    public static function getInstance(): Singleton
    {
        if (null === static::$instance) {
            static::$instance = new static();
        }
        return static::$instance;
    }
    /**
     * is not allowed to call from outside to prevent from creating multiple instances,
     * to use the singleton, you have to obtain the instance from Singleton::getInstance() instead
     */
    private function __construct()
    {
    }
    /**
     * prevent the instance from being cloned (which would create a second instance of it)
     */
    private function __clone()
    {
    }
    /**
     * prevent from being unserialized (which would create a second instance of it)
     */
    private function __wakeup()
    {
    }
}

https://github.com/domnikl/DesignPatternsPHP/blob/master/Creational/Singleton/Singleton.php

https://phptherightway.com/pages/Design-Patterns.html

https://stackoverflow.com/questions/203336/creating-the-singleton-design-pattern-in-php5

MySQL 分区表

https://www.jianshu.com/p/89311703b320

258 total views, 1 views today

PHP Interview Questions(7)

面试时间:2018 年 9 月 14 日,星期五,下午六点。


MySQL 主从备份的作用是什么?

防止一台宕机。

PHP-FPM 的运行原理是什么?

master/worker架构。

MySQL 使用 delete 语句删除数据,空间没有释放怎么解决?

optmize table {name}

怎么设计 1000W 用户量的用户签到系统?

分库分表
中间件

240 total views, 1 views today

PHP Interview Questions(6)

面试时间:2018 年 9 月 13 日,星期五,下午 13 : 00。


存在两个时间,如何计算两个日期的天数差。

<?php
$dateStart = '2017-05-03 12:34:56';
$dateEnd = '2020-12-12 09:17:18';
// 计算两个时间天数差
return intval((strtotime($dateEnd) - strtotime($dateStart)) / (24 * 60 * 60));

PHP 中传值和引用的区别是什么?叙述下其应用场景和优劣。

http://php.net/manual/zh/language.references.php

请写一个正则表达式,用来验证手机号码的正确性。

\d{11}

请列举出常用的PHP魔术方法,并说明其应用场景。

http://php.net/manual/zh/language.oop5.magic.php

请写出 echo,print,printf,sprintf,print_r,var_dump 的差异。

http://php.net/manual/en/ref.strings.php

请无乱码的切割中文字符(实例字符:“布克大学,就要不凡”,截取“布克大学”)。

mb_substr("布克大学,就要不凡", 0, 4)
substr("布克大学,就要不凡", 0, 12)

PHP 中异常处理时(try catch finally),return 应该写在哪里?

都可以。

有如下三张表,请写出查询每个学生平均分数的 SQL 语句。

>>> 学生表/students:
id
name # 学生姓名

>>> 成绩表/scores:
id
student_id # 学生id@students.id
subject_id # 科目id@subjects.id
score # 分数

>>> 科目表/subjects:
id
name # 科目名称

结果要求输出 学生姓名 科目名称 平均分数

select students.name as student_name, subjects.name as subject_name, sum(scores.score)/count(students.id) as avg_score
from scores
join students on (students.id = scores.student_id)
join subjects on (subjects.id = scores.subject_id)
group by students.id

PHP 中创建多进程、多线程的方式有哪些,使用多线程、多进程有哪些优缺点。

多进程:
http://php.net/manual/zh/book.pcntl.php
多线程:
http://php.net/manual/en/book.pthreads.php

描述下 IoC 和 DI 的实现原理。

https://phptherightway.com/#dependency_injection

OAuth2 的工作原理是怎么样的?

https://laravel.com/docs/master/passport

(口述作答)根据你的经验,如何规划一个大流量、高并发的WEB站点。

http://network.51cto.com/art/201809/583103.htm

聊聊  MySQL 主从同步。

https://www.digitalocean.com/community/tutorials/how-to-set-up-master-slave-replication-in-mysql

聊聊 RESTful API 设计。

https://www.toptal.com/laravel/restful-laravel-api-tutorial

如果团队有一个消极的人怎么处理。如果团队成员玩手机被老板发现了怎么处理。能否带领一个 3 到 5 人的团队完成开发任务。

不处理。

252 total views, no views today

PHP Interview Questions(5)

面试时间:2018 年 9 月 12 日,星期三,下午两点。


PHP 怎么实现多继承?

trait

Git 怎么撤销上次提交?

git commit --amend

ls -l 命令的前十位代表什么?

drwxrwxrwx

解释什么是 XSS,CSRF,SQL 注入以及如何防范

http://www.cnblogs.com/leecong/p/5898370.html

高并发下如何锁库存,防止超卖?/ 支付回调如何防止重复写入。

乐观锁

Nginx location 匹配规则。

http://nginx.org/en/docs/http/ngx_http_core_module.html#location

Nginx 为什么比 Apache 快?

Nginx 采用 epoll 模型,异步非阻塞。
Apache 采用 select 模型,同步阻塞。

TCP 和 UDP 的区别都有哪些?

https://www.diffen.com/difference/TCP_vs_UDP

235 total views, no views today