php面试题

真实面试题

文章目录

php基础

1、什么是 PHP?如何安装和配置 PHP?

PHP是一种开源的服务器端脚本语言,可用于创建动态网页和 Web 应用程序。安装和配置 PHP 取决于您使用的操作系统和 Web 服务器。

2、请解释 HTTP 协议及其工作原理

HTTP 是超文本传输协议。它通过互联网传输数据,并使用客户端/服务器模型工作。

3、请简要解释 MVC 模式及其在 PHP 中的应用

MVC 模式是 Model-View-Controller 的缩写,是一种软件设计模式,将应用程序分为三个核心部分:模型、视图和控制器。在 PHP 中,MVC 这些部分通常对应数据库、前端 UI 和后端逻辑

4、您如何防止 PHP 应用程序遭受 XSS 和 SQL 注入等攻击

防止 XSS (跨站脚本攻击) 和 SQL 注入攻击的方法包括在输入验证中使用过滤器和转义字符不信任用户输入并确保处理用户输入的方式正确

5、 PHP 中的 isset() 和 empty() 函数有什么区别(两个是反过来的)

isset()函数检查变量是否存在且不为NULL,而empty()函数检查值是否为空。isset()返回布尔值true或false,而empty()可以像isset()一样返回布尔值,也可以返回整数0或字符串“0”。

isset() : 确定变量是否已设置且不为空;换句话说,仅当变量不为null时才返回true

empty() 函数是用于确定变量是否为空;换句话说,如果变量是空字符串,falsearray(),NULL,“0”,0和未设置的变量,它将返回true

6、tp和laravel框架之间的优缺点

TP框架擅长运行简单应用,而Laravel适合复杂项目。
但是Laravel的执行速度较慢,因为Laravel使用了大量的抽象层以及许多预处理程序等技术。

7、 您如何处理 PHP 代码中的错误和异常?

PHP 中的错误通过设置错误报告级别来处理。 可以通过在PHP代码中使用try和catch块获取并处理异常信息。

8、如何调试 PHP 代码并查找问题?

使用Xdebug地址调试PHP代码,并使用var_dump()和echo等函数查找问题,可输出变量值和状态信息,帮助您找到代码中的错误和问题。

9、请说明 PHP 中传值与传引用的区别,什么时候传值什么时候传引用

区别:

传值是参数的副本,不影响原始变量。
传引用是参数的引用,直接影响原始变量。

适用的场景:

传值适用于不需要修改原始变量的情况。
传引用适用于需要修改原始变量的情况。

10、什么是面向对象?主要特征是什么?

"面向对象是一种编程范式
它将程序设计看作是对象的集合,通过封装、继承和多态等特性来组织和管理代码

主要特征:
包括封装(隐藏内部细节)继承(实现代码的重用和扩展)多态(同一操作产生不同行为)
面向对象的编程方法可以提高代码的安全性、可维护性和重用性,并提供更灵活和可扩展的代码架构。"

11、SESSION 与 COOKIE的区别是什么

Session:

存储在服务器端(运行着网站应用程序的计算机或服务器)相对安全,可以存储较大量的数据,但会在用户关闭浏览器或长时间不活动后过期

Cookie:
存储在客户端(用户使用的设备和浏览器),用户可以查看和修改COOKIE内容,存储容量较小,但可以设置过期时间在指定时间之前一直存在

12、 表单中get和post提交方式的区别

GET:
   将数据附加在URL的查询字符串中传输,适合传输少量的非敏感数据可以被缓存,但数据暴露在URL中存在安全风险

POST:
    将数据放在请求的正文中传输,适合传输大量数据和敏感信息,数据不会暴露在URL中,不会被缓存,可以引起服务器状态变化

13、语句include和require的区别是什么,为避免多次包含同一文件,可用什么语句代替它们?

include:
    如果include引入的文件不存在或引入过程中发生错误,PHP会发出警告,但脚本会继续执行。在执行过程中,如果多次引入同一个文件,PHP会发出多个警告,但脚本仍会继续执行。

require:
require引入的文件不存在或引入过程中发生错误,PHP会发出致命错误,并停止脚本的执行,如果多次引入同一个文件,PHP只会引入一次,不会发出错误。

可使用:require_onceinclude_once 来之引入一次

使用场景:

使用require语句: 被包含的文件对于脚本的执行非常重要,且缺少该文件会导致脚本无法正常运行。

使用include语句: 如果被包含的文件只是提供了一些可选功能或资源,且缺少该文件不会导致脚本运行错误,

14、PHP的基本变量类型

  1. 字符串(String)
  2. 整数(Integer)
  3. 浮点数(Float)
  4. 布尔值(Boolean)
  5. 数组(Array)
  6. 对象(Object)
  7. 空值(Null)
  8. 资源(Resource):用于表示外部资源(如数据库连接、文件句柄等)的引用。

15、静态化如何实现的?伪静态如何实现?

静态化:
动态生成的网页或内容转化为静态文件的技术手段,以提升网站性能和访问速度,

实现:使用缓存技术反向代理 实现

伪静态:
将动态URL转化为静态URL,以改善搜索引擎优化和用户体验
实现 : 包括URL重写MVC框架的路由配置

16、说一下单引号双引号?

单引号字符串:
    变量不会被解析,而会被直接输出。特殊字符(如换行符、制表符)会被转义,但其他转义字符(如 \n\t)不会生效

双引号字符串:
    变量会被解析并替换为其对应的值。特殊字符会被转义,同时转义字符也会生效

17、PHP 数组排序

sort():
    按升序对数组的值进行排序,保持键与值的关联。该函数会改变原始数组会重新索引数组的键

rsort():
    按降序对数组的值进行排序,保持键与值的关联。该函数会改变原始数组会重新索引数组的键

asort() ,arsort(): 分别对应升序和降序,都会改变原数组,不会重新索引数组的键

18、PHP支持多继承吗

直接的多继承是不被支持的,但是可以通过接口和特质来实现类似多继承的功能

通过接口,一个类可以实现一个或多个接口,从而拥有多个接口的行为和功能

19、array_merge和array+array的区别

键名为数字时:

array_merge()不会覆盖掉原来的值,
array+array合并数组则会把最先出现的值作为最终结果返回,而把后面的数组拥有相同键名的那些值"抛弃"掉(不是覆盖),array+array 不会重新索引

20、php安全性攻击(sql注入,xss攻击,CSRF攻击)

1、SQL注入

使用PHP的内置mysql_real_escape_string()函数用作任何用户输入的包装器。这个函数 对字符串中的字符进行转义,使字符串不可能传递撇号等特殊字符并让MySQL根据特殊字符进行操作。

2、跨站点脚本攻击(XSS攻击)
使用strip_tags()函数,这个函数可以清除任何包围在HTML标记中的内容或者使用htmIlspecialchars()函数。

3、跨站点请求伪造(CSRF)
Laravel框架中避免CSRF攻击很简单: Laravel自动为每个用户Session生成了一个CSRF Token该Token可用于验证登录用户和发起请求者是否是同一人,如果不是则请求失败。

21、HTTP 状态中302、403、 500代码含义?

一二三四五原则:
(即一:消息系列;二:成功系列; 三:重定向系列;四:请求错误系列;五:服务器端错误系列。)
302: 临时转移成功,请求的内容已转移到新位置
403: 禁止访问
500: 服务器内部错误
401: 代表未授权。

22、error_reporting这个函数有什么作用?

设置PHP的报错级别并返回当前级别。

23、AJAX的优势是什么?

ajax是异步传输技术,可以通过javascript实现,也可以通过JQuery框架实现,实现局部刷新,减轻了服务器的压力,也提高了用户体验

24、foo()和@foo()之间有什么区别?

@代表所有warning忽略

* 25、php的垃圾回收机制

php中的变量存储在变量容器zval中zval中除了存储变量类型和值外,还有is_refrefcount字段

refcount: 表示指向变量的元素个数
is_ref: 表示变量是否有别名
如果refcount为0时,就回收该变量容器
如果一个zval的refcount减1之后大于0,它就会进入垃圾缓冲区
缓冲区达到最大值后,回收算法会循环遍历zval,判断其是否为垃圾,并进行释放处理

26、echo、print_r、print、var_dump区别

echo: 语句结构;
print: 是函数,有返回值,用于输出字符串
print_r: 能打印数组,对象
var_dump: 能打印对象数组,并且带数据类型

27、PHP如何实现页面跳转

php函数跳转:
缺点,header头之前不能有输出,跳转后的程序继续执行,可用exit中断执行后面的程序。

header("Location:网址");//直接跳转
header("refresh:3;url=http://www.jsdaima.com");//三秒后跳转

28、如果需要原样输出用户输入的内容,在数据入库前,要用哪个函数处理?

htmlspecialchars或者htmlentities

(重要) 29、简述 private、 protected、 public修饰符的访问权限。

private : 私有成员, 只在类的内部才可以访问。
protected : 保护成员,该类内部和继承类中可以访问。
public : 公共成员,完全公开,没有访问限制。

30、常用的魔术方法有哪些?举例说明

php规定以两个下划线(__)开头的方法都保留为魔术方法

__construct() : 实例化类时自动调用。
__destruct() : 类对象使用结束时自动调用。
__set() : 在给未定义的属性赋值的时候调用。
__get() : 调用未定义的属性时候调用。
__isset()  :使用isset()empty()函数时候会调用。
__unset()  :使用unset()时候会调用。
__sleep()  :使用serialize序列化【将php序列化成字符】时候调用。
__wakeup()  :使用unserialize反序列化的时候调用。
__call()  :调用一个不存在的方法的时候调用。
__callStatic() :调用一个不存在的静态方法是调用。
__toString()  :把对象转换成字符串的时候会调用。比如 echo__invoke()  :当尝试把对象当方法调用时调用。
__set_state()  :当使用var_export()函数时候调用。接受一个数组参数。
__clone()  : 当使用clone复制一个对象时候调用。

31、$this和self、parent这三个关键词分别代表什么?在哪些场合下使用?

$this : 当前对象(使用->调用属性和方法)
self : 当前类 (使用 :: 调用)
parent : 当前类的父类

32、作用域操作符::如何使用?都在哪些场合下使用?

  • 调用类常量
  • 调用静态方法

(重要)33、PHP遍历文件夹下所有文件(删除所有图片)

34、strtotime()函数的用法

第一个参数: 只要你能想到的英文日期他都有

**第二个参数:**基于哪个时间作为基准


// 将日期时间字符串转换为UNIX时间戳
$timestamp = strtotime('2023-05-30 10:30:00', time());
echo $timestamp; // 输出:1693205400

// 使用相对日期时间字符串
$nextWeek = strtotime('+1 week', time());
echo $nextWeek; // 输出:1693804400

// 使用相对日期时间字符串
$previousSunday = strtotime('-1 sunday', time());
echo $previousSunday; // 输出:1692924000
function deleteFiles($dir, $extensions) {
    if ($handle = opendir($dir)) { // 打开目录句柄
        while (false !== ($entry = readdir($handle))) { // 读取目录列表项
            if ($entry == '.' || $entry == '..') { // 忽略 . 和 .. 目录
                continue;
            }
            $path = $dir . '/' . $entry; // 获取文件的完整路径
            if (is_dir($path)) { // 如果是目录,则递归调用自身处理子目录
                deleteFiles($path, $extensions);
            } else { // 如果是文件,并且扩展名匹配,则删除文件
				/** 操作一: 单纯遍历文件
				echo '文件:'.$path.'<br>';
				**/

            	/** 操作二:删除图片
                $ext = pathinfo($path, PATHINFO_EXTENSION); // 获取文件扩展名
                if (in_array(strtolower($ext), $extensions)) { // 如果扩展名匹配,则删除文件
                    unlink($path);
                }
                **/
            }
        }
        closedir($handle); // 关闭目录句柄
    }
}

// 示例调用:删除jpg、png、gif类型的文件
deleteFiles('/path/to/directory', array('jpg', 'png', 'gif'));

mysql面试题

mysql必练笔试题

1、MySQL为什么使用B+树来作为其索引结构

  • 因为是一颗有序树,并且B+树的叶子节点通过链表连接起,所以B+树支持高效的范围查询:
    B+树按照键值大小有序地存储数据每个叶子节点在同一层级上,可以支持非常高效的范围查询

  • B+树对于数据库随机写入性能极佳
    因为每个节点可以存储多个键和数据指针,**使得每次插入、删除或更新操作只需要修改少量节点(更少的磁盘io操作)**即可完成,这样就大大降低了写入时的开销。

  • B+树更适合写密集型场景(大量读写操作的场景)
    由于非叶子节点仅保存索引信息,相比B树可以容纳更多子节点,因此B+树更适用于写密集型场景。

2、mysql中常见的锁

1、什么是行锁?:
行锁允许一个事务独占一行数据,其他事务无法修改该行数据直到该事务释放锁。

2、什么是表锁
表锁是针对整张表的锁允许一个事务独占该表的所有数据,其他事务无法修改该表的任何数据直到该事务释放锁。

3、什么是页锁
页锁是针对数据页(一个存储块)的锁允许一个事务独占某个数据页的所有数据,其他事务无法修改该数据页中任何数据直到该事务释放锁。

4、什么是共享锁
共享锁是允许多个事务同时读取同一份数据但是不能同时修改该数据。共享锁可以提高并发读取性能。

5、什么是排他锁?
排他锁是一种独占锁,只允许一个事务修改数据。当一个事务持有排他锁时,其他事务无法对该数据进行读取或修改操作。

6、乐观锁悲观锁【逻辑层面】 ?

上述几种锁都是属于悲观锁(并发访问比较频繁且冲突概率较高的场景)
为数据可能会被其他事务修改,因此在读取或修改数据时会先对数据进行加锁,其他事务无法修改该数据直到当前事务释放锁

7、乐观锁:(多读少写的场景)
假设(原理)多个事务访问同一份数据的概率很小,因此在进行更新操作时并不对数据进行加锁,而是先读取数据,并且记录下数据版本号
然后在写入数据时先检查数据版本是否与读取时记录的相同, 来判断本次操作是否可以成功执行。

3、该如何优化自己的sql

在这里插入图片描述

4、mysql有哪几种常见的索引

  • Unique Index(唯一索引)
  • Spatial Index(空间索引)
  • Normal Index(普通索引) B-tree索引或哈希索引
  • 聚簇索引
  • 非聚簇索引

5、什么场景需要设计索引

1、经常搜索的列:如果某个列经常被包含在 WHERE 或 JOIN 子句中,那么为该列添加索引可以提高查询速度
2、频繁排序的列:
3、外键列: 外键列经常用于 JOIN 操作中,因此为其添加索引可以提高连接操作的速度
4、唯一性约束列: 如用户ID 或电子邮件地址等,为其添加唯一性索引可以确保数据的完整性,避免重复数据的插入。
5、多表查询列: 如果查询需要多个表之间的联合,为跨表连接使用缩减查询时间和资源消耗的复合索引。

6、聚簇索引和非聚簇索引的区别

  • 聚簇索引(表数据与聚簇索引放在同一个B树节点里面):
    查询效率高,找到了索引相当于找到了数据,但插入及更新操作的性能较低,因为需要重新排序

  • 非聚簇索引叶子节点不存储数据,存的是地址,即单独建立的另外一个B树持有索引数据
    插入和更新的性能更好,但是查询时则需要进行两次IO,先读取索引再读取数据,因此查询速度相对聚簇索引稍慢一些

7、InnoDB 和 MyISM数据库引擎之间的区别

  1. InnoDB支持事务处理,而MyISAM不支持
    (事务是对一组操作进行的原子性、一致性等保证,可以保证数据操作的正确性、可靠性和完整性)

2、InnoDB采用了行级锁定,而MyISAM采用的是表级锁定, 所以InnoDB并发操作时锁定的范围更小,从而提高了并发性能。

3、InnoDB支持 “外键” ,而 MyISAM 不支持

4、InnoDB使用B+树作为索引结构,支持聚簇索引
     MyISAM使用B树或者哈希表作为索引结构,不支持聚簇索引,所以要先查索引文件在查数据文件。

8、事务的四大基本特性和隔离级别

事务的四大基本特性(ACID):

  • 原子性: 事务作为一个整体,要么全部执行成功,要么全部失败回滚
  • 一致性: 事务执行前后,数据库都必须保持一致状态,不能破坏数据完整性和约束条件
  • 隔离性:事务之间的操作互不干扰,每个事务应该感觉不到其他并发事务的存在
  • 持久性: 一旦事务提交成功,所做的修改将会永久保存在数据库中

首先介绍一下mysql出现三种事务问题

幻读(Phantom Read)【别的事务插入和删除导致的】
是指在一个事务中,重复执行同一查询语句返回的结果集却不一致。通常是由于其他事务已插入或删除了符合该查询条件的数据。

脏读(Dirty Read)【读到未提交】
是指在一个事务中,读取到了另一个未提交的事务中更新的数据。如果另一个事务最终回滚,则当前事务读到的数据就是无效的。

不可重复读(Non-repeatable Read)【别的事物修改导致的】
是指在同一个事务中,重复执行同一查询语句,返回的结果集有所不同。通常是由于其他事务在两次查询之间修改了符合该查询条件的数据。

数据库的隔离级别有四种:

  • 读未提交: 一个事务可以读取另一个事务尚未提交的数据,并可能导致脏读幻读不可重读的问题;
  • 读已提交: 一个事务只能读取另一个事务已经提交的数据避免了脏读的问题,但仍可能出现幻读不可重读的问题;
  • 可重复读: 一个事务在执行过程中多次读取同一行数据时,其结果是一致的,避免了脏读和不可重复读问题,但仍可能出现幻读的问题;
  • 串行化: 所有事务都是串行执行的,避免了并发问题,但是会带来效率上的问题

9、MySQL数据库中的字段类型varchar和char的主要区别是什么?

1.存储方式:

varchar是可变长度的,根据实际内容动态分配空间
char是固定长度的,始终占用预先分配的固定存储空间

空格处理:

CHAR会默认切掉字符串末尾的空格,而varchar不会

* 10、MySQL 遇到过死锁问题吗,你是如何解决的?

为了解决死锁,我采取了以下措施:
优化事务并发性优化查询语句和索引使用合理的事务管理策略引入锁超时和重试机制以及调整数据库配置参数。通过这些方法,我成功降低了死锁发生的概率

11、MySQL 索引使用有哪些注意事项呢?

  • 选择合适的列进行索引,针对常用的查询、连接和排序操作进行索引优化。
  • 注意索引列的顺序,将最频繁使用的列放在索引的前面,以提高查询性能。
  • 谨慎使用索引合并,评估是否使用索引合并来加速查询。
  • 避免过度索引化,权衡索引数量和类型,避免过多索引对写操作的开销
  • 注意索引的维护成本,确保索引的收益超过维护成本。
  • 定期分析和优化索引,识别潜在的性能问题并根据需求进行优化和重建。
  • 使用合适的索引类型,根据查询需求和数据特性选择普通索引、唯一索引、主键索引等。

* 12、说说分库与分表的设计

都是数据库水平拆分的常用技术,用于解决大数据量和性能瓶颈问题

分库:数据按规则分散到多个数据库实例中,
考虑: 数据一致性和跨库事务

分表:表按规则拆分为多个物理表,提升查询和写入性能,
考虑: 注意跨表查询的复杂性

* 13、在高并发情况下,如何做到安全的修改同一行数据?

乐观锁:
    使用版本号或时间戳,在更新前先读取数据并比较版本号确保一致后再执行更新操作

悲观锁:
   使用数据库的锁机制获取独占锁来限制并发访问

分布式锁:
   使用分布式锁工具或基于数据库的锁机制,确保只有一个线程可以修改数据

队列化操作:
   通过消息队列按顺序处理需要修改同一行数据的操作,避免并发冲突。

14、如何通俗地理解三个范式?

用来规范化数据库设计的原则

第一范式:对属性的原子性约束,要求属性具有原子性,每一列的数据不可再分解
第二范式:是对记录的惟一性约束,要求记录有惟一标识,即实体的惟一性,即非主键列完全依赖于表的主键
第三范式:是对字段冗余性的约束,即任何字段不能由其他字段派生出来,它要求字段没有冗余。

php框架:TP

1、thinkphp5底层原理是什么

它的底层原理基于 MVC 架构模式。它通过路由系统将请求分发到对应的控制器和方法,处理用户请求和调度。同时,它提供了强大的请求和响应处理机制,方便解析请求参数和生成响应内容。此外,它还支持数据库访问和 ORM 功能(将数据库中的表映射为程序中的对象,使开发人员可以使用面向对象的方式操作数据),可以便捷地进行数据库操作。

2、thinkphp5 是怎么实现前后端分离

可以通过提供接口配置路由处理数据格式支持跨域以及配合独立的前端框架等方式来实现前后端之间的协作

3、为什么tp5不用写路由,thinkphp5 怎么写接口

ThinkPHP 5框架内置了一种约定的路由规则,可以根据URL的路径和命名规则自动映射到对应的控制器和方法

需要创建一个控制器定义接口方法在方法中处理接口的逻辑和参数,返回相应的数据

4、thinkphp5请求类型是怎么设置的

可以使用 request->method('get'/’post‘) 来修改请求的类型

5、如何开启调试模式?调试模式有什么好处?

通过在 应用配置文件config.php中设置 app_debug 参数为 true 来开启调试模式, 供详细的错误信息、SQL查询跟踪、自动重载代码等功能

6、TP中系统变量有哪些?如何获取系统变量

$_SERVER:包含了服务器和执行环境的信息,如请求的URL、请求方法、服务器IP等。可以使用$_SERVER[‘变量名’]来访问。

$ _GET:包含通过GET方法提交的参数。可以使用$ _GET[‘变量名’]来访问。

$ _POST:包含通过POST方法提交的参数。可以使用$ _POST[‘变量名’]来访问。

$ _REQUEST:包含通过GET、POST和COOKIE方法提交的参数。可以使用$_REQUEST[‘变量名’]来访问。

$ _SESSION:包含当前会话中的会话变量。可以使用$ _SESSION[‘变量名’]来访问。

$ _COOKIE:包含通过COOKIE方法提交的参数。可以使用$ _COOKIE[‘变量名’]来访问。

$ _ENV:包含系统环境变量。可以使用$ _ENV[‘变量名’]来访问。

$ _FILES:包含通过文件上传提交的文件信息。可以使用$ _FILES[‘变量名’]来访问。

7、tp框架的联表操作

正向的:

  1. 一对一关联:hasOne()

    $related:关联的关联模型类名。
    $foreignKey:关联的外键字段,默认为当前模型名加 _id。
    $localKey:本地模型的主键字段,默认为 id。

  2. 一对多关联:hasMany()
    $related:关联的关联模型类名。
    $foreignKey:关联的外键字段,默认为当前模型名加 _id。
    $localKey:本地模型的主键字段,默认为 id。

反向的:belongsTo():
$related:关联的主模型类名。
$foreignKey:关联的外键字段,默认为关联模型名加 _id。
$localKey:本地模型的主键字段,默认为 id。

PHP框架:laravel

开发实际问题

1、大流量的网站,采用什么样的方法来解决访问量问题?

可以采用增加服务器资源负载均衡数据库优化缓存技术异步处理静态资源优化代码优化等方法来解决 访问量问题
通过增加服务器能力平衡负载优化数据库使用缓存等手段,可以提高网站的 并发处理能力 、减轻服务器压力,并提升用户体验

2、对缓存技术的了解?redis?

将计算结果、数据或对象存储在快速访问的存储介质中,缓存可以显著提高系统的响应速度和吞吐量减少对后端数据源(如数据库)的访问次数,从而降低系统的负载

redis:

  • 高性能: Redis将数据存储在内存中,因此具有极高的读写性能和低延迟。
  • 数据持久化: Redis支持将数据持久化到磁盘,以防止数据丢失。

多数据结构支持: Redis支持多种数据结构和丰富的操作命令,使其适用于各种应用场景。

发布-订阅模式: Redis提供了发布-订阅功能,可以实现实时消息传递和事件通知

高可用性: Redis支持主从复制集群模式,以提供高可用性和容错能力。

* 3、redis和memcacahe、mongoDB的区别?

数据模型:

Redis 是键值存储系统,支持多种数据类型;
Memcache 也是键值存储系统,但仅支持简单的键值对;
MongoDB 是文档数据库,以类似JSON的BSON格式存储数据。

数据持久性:
Redis 可以将数据持久化到磁盘,支持数据恢复
Memcache 不提供数据持久化功能,重启后数据丢失
MongoDB 可以将数据持久化到磁盘,并支持数据复制和故障恢复

查询和索引:
Redis 具有灵活的查询功能,支持索引和范围查询
Memcache 不支持查询,只能通过键获取值
MongoDB 支持复杂的查询语言和高级查询操作

算法

1、快速排序

<?php
function quick_sort(&$nums, $l, $r) {
    if ($l >= $r) return;
    $x = $nums[($l + $r) >> 1];
    $i = $l - 1;
    $j = $r + 1;
    while ($i < $j) {
        do $i++; while ($nums[$i] < $x);
        do $j--; while ($nums[$j] > $x);
        if ($i < $j) {
            $temp = $nums[$i];
            $nums[$i] = $nums[$j];
            $nums[$j] = $temp;
        }
    }
    quick_sort($nums, $l, $j);
    quick_sort($nums, $j + 1, $r);
}

$nums = [1,5,2,4,9,3,7];

quick_sort($nums, 0, $n - 1);

foreach ($nums as $num) {
    echo $num . ' ';
}
?>

2、冒泡排序

主要是注意第二重循环的次数为 $n - $i – 1 即可

function bubbleSort($arr) {
    $n = count($arr);
    
    for ($i = 0; $i < $n - 1; $i++) {
        $swapped = false;
        
        for ($j = 0; $j < $n - $i - 1; $j++) {
            if ($arr[$j] > $arr[$j + 1]) {
                // 交换位置
                $temp = $arr[$j];
                $arr[$j] = $arr[$j + 1];
                $arr[$j + 1] = $temp;
                
                $swapped = true;
            }
        }
        
        // 如果没有发生交换,说明数组已经有序,可以提前结束排序
        if (!$swapped) {
            break;
        }
    }
    return $arr;
}
// 测试示例
$nums = [5, 3, 8, 2, 1, 4];
$sortedNums = bubbleSort($nums);
print_r($sortedNums);

3、最接近的三数之和

思路:
1、首先对数据进行排序
2、定义一个循环,再定义两个双指针start和end,
3、在该循环下while一下,琼剧每次计算当前下标和两个指针之下的值相加是多少
3、多就左移动end,少就右移动start
<?php
function threeSumClosest($nums, $target) {
        sort($nums);
        $count = count($nums);
        $ans = $nums[0] + $nums[1] + $nums[2];
	
        for( $i=0;$i<$count;$i++) {
            $start = $i+1; $end = $count - 1;
			
            while($start < $end) {
                $sum = $nums[$start] + $nums[$end] + $nums[$i];
                if(abs($target - $sum) < abs($target - $ans)){
					$ans = $sum;
				}   
                if($sum > $target){
				 	$end--;
				}
                else if($sum < $target){
					$start++;
				}  
                else{
				 	return $ans;
				}
            }
        }
        return $ans;        
    }

var_dump(threeSumClosest(array(-1,2,1,-4,0),1));
?>

4、(重点) 实现链表反转

<?php
//定义链表节点
class Node
{
    private $value;
    private $next;

    public function __construct($value = null)
    {
        $this->value = $value;
    }

    public function getValue()
    {
        return $this->value;
    }

    public function setValue($value)
    {
        $this->value = $value;
    }

    public function getNext()
    {
        return $this->next;
    }

    public function setNext($next)
    {
        $this->next = $next;
    }
}

//方法一:遍历,将当前节点的下一个节点缓存后更改当前节点指针 
function reverse($head)
{
    if ($head == null) {
        return $head;
    }
    $pre = $head;//注意: 对象的赋值
    $cur = $head->getNext();
    $next = null;
    while ($cur != null)                       {
        $next = $cur->getNext();
        $cur->setNext($pre);
        $pre = $cur;
        $cur = $next;
    }
    //将原链表的头节点的下一个节点置为null,再将反转后的头节点赋给head  
    $head->setNext(null);
    $head = $pre;
    return $head;
}


function test()
{
    $head = new Node(0);
    $tmp = null;
    $cur = null;
    // 构造一个长度为10的链表,保存头节点对象head   
    for($i=1;$i<10;$i++){
        $tmp = new Node($i);
        if($i == 1){
            $head->setNext($tmp);
        }else{
            $cur->setNext($tmp);
        }
        $cur = $tmp;
    }
    //print_r($head);exit;
    $tmpHead = $head;
    while ($tmpHead != null) {
        echo $tmpHead->getValue().' ';
        $tmpHead = $tmpHead->getNext();
    }
    echo "\n";
    //$head = reverse($head);
    $head = reverse2($head);
    while($head != null){
        echo $head->getValue().' ';
        $head = $head->getNext();
    }
}
test();
?>

5、有效的括号

核心思路: 遇到左括号就压栈,遇到右括号就从栈中弹出匹配

function isValid($s) {
	$length = strlen($s);
	if ($length <= 1) {
		return false;
	}

	//如果其中有空字符串或者字符串长度为奇数则为false
	$ts = str_replace(" ",'',$s);
	$tlen = strlen($ts);
	if($length != $tlen || $length%2 != 0){
		return false;
	}
	
	$tmp_arr = [")" => "(", "}" => "{", "]" => "["];
	$arr = [];
	for ($i=0; $i<$length; $i++) {
		if (isset($tmp_arr[$s[$i]]) && $tmp_arr[$s[$i]] == end($arr)) {
			array_pop($arr);
		} else {
			array_push($arr, $s[$i]);
		}
	}
	return empty($arr) ? true : false;
}

var_dump($this->isValid("{[{]}"));

6、判断链表是否有环

核心思路:快慢指针

function hasCycle($head){
    if($head == null) return null;
    $slow = $head;
    $fast = $head->next;
    while($slow != $fast){
        if($fast == null || $fast->next == null){
            return false;//如果一直走没有环,从这个返回了
        }
        $slow = $slow->next;
        $fast = $fast->next->next;
    }
    return true;
}

7、用php求取一个字符串中不重复的最长子串的方式

思路:
1、创建两个空数组,一个用于最终记录结果,一个用于记录当前的最长数组。
array_key_exists(): 检查某个键名是否存在于数组中:
array_keys() : 返回所有的键名
2、循环遍历,并且每一次循环都更新结果数组

<?php
 
$string = "1234567abcdaefaedkqatlmtx";
$len = strlen($string);
$resArr =[];
$tmp = [];
$i = 0;
while ($i < $len){
	$char = $string{$i};
	if(!array_key_exists($char, $tmp)){
		$tmp[$char]= $i;
		$i++;
		if($i !== $len) continue;
	}

	//从重复值下个开始
	$i = $tmp[$char]+1;
	if( count($tmp) > count($resArr) ){
		$resArr = $tmp;
	}
	$tmp = [];
} 
echo implode(array_keys($resArr));  //结果:1234567abcd
?>

8 、统计两个数组相同数据的组数

在这里插入图片描述

思路:
1、定义一个临时数组先记录其中一个数组的值的出现情况
2、在用这个临时数组比较另外一个临时数组的数据出现情况

<?php
$f = [1, 3, 4, 7, 9];
$g = [3, 5, 7, 8, 10];
$temp = array();
foreach ($f as $val) {
    $temp[$val] = isset($temp[$val]) ? ($temp[$val] + 1) : 1;
}
$count = 0;
foreach ($g as $val) {
    if (isset($temp[$val])) {
        $count += 1;
    }
}
var_dump($count);

9、对两个升序数组进行合并

array_merge(数组1,数组2)

10、输入一个已经按升序排序过的数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。

如果有多对满足要求,输出任意一对即可

思路:
1、先排好序,定义两个指针位于数组两端
2、开始循环,每次循环都判断一下当前位于指针的值加入来是否等于目标值
3、如果比目标值要大,右指针 - 1; 如果比目标值要小,左指针 + 1;

<?php
function twoSum($arr,$len,$sum)
{
     $beg = 0;
      $end = $len-1;
      $curSum = 0;
      while($beg < $end)
     {
         $curSum = $arr[$beg] + $arr[$end];
         if($curSum == $sum)
         {
				var_dump($arr[$beg] ,$arr[$end],$sum);   
             $beg++;
             $end--;
         }
         else if($curSum < $sum)
             $beg++;
        else
             $end--;
     }
}

$arr = [1,2,4,7,9,11,15,20,28,34];
twoSum($arr,count($arr),32);

计算机网络

一、浏览器输入URL到页面加载发生了什么

1、DNS解析:
把域名解析成对应的ip

2、浏览器与网站建立TCP连接(三次握手)
第一次握手:客户端向服务器端发送请求(SYN=1【表示请求建立连接】)等待服务器确认;

第二次握手:服务器收到请求并确认,回复一个指令(SYN=1【表示同意建立连接】,ACK=1) ;

第三次握手:
客户端收到服务器的回复指令并返回确认(ACK=1,SYN=0 【表示连接已经建立】)

通过三次握手,建立了客户端服务器之间的连接,现在可以请求和传输数据了。

客户端问服务器:哥们你吃饭了么?
服务器回答客户端并且反问:我吃饭了,你呢?
客户端回答服务器:我也吃了。

3、请求和传输数据

4、浏览器渲染页面

5.链接结束(四次挥手):
客户端-→>服务端:请求完毕
服务端-→客户端:知道请求完毕
服务端->客户端:发送完毕
客户端→服务端:知道发送完毕

Redis

redis支持哪些数据结构

Redis支持字符串、哈希、列表、集合、有序集合和地理空间索引等数据结构

Linux

1、将本地某个端口映射到另外一个服务器的3306端口

使用ssh隧道进行端口的转发

ssh -L  3307:remote_server_ip:3306  user@local_server_ip

3307:remote_server_ip:3306:
表示将本地服务器的 3307 端口与远程服务器的 3306 端口进行映射。
这里的 remote_server_ip 需要替换为实际的远程服务器 IP 地址或域名。这个命令的作用是将本地服务器的 3307 端口转发到远程服务器的 3306 端口。

user@local_server_ip:
表示登录到本地服务器的用户名和 IP 地址。这里的 user 需要替换为实际的用户名,local_server_ip 需要替换为实际的本地服务器 IP 地址

2 、如何在Linux系统上查看和编辑文件?

查看文件内容:
cat filenamemore filenamehead filenametail filename等。
编辑文件:
可以使用文本编辑器如vi、nano、vim等打开文件并进行编辑。

3、如何在Linux系统上查看和管理进程?

ps命令:

  1. ps aux:显示详细的进程列表,包括用户、CPU使用情况、内存占用等信息。
  2. ps -ef:显示更简洁的进程列表,包括进程ID(PID)和父进程ID(PPID)等基本信息。

结束进程:
kill PID命令可以终止具有特定进程ID(PID)的进程。

4、Linux中的权限管理是如何工作的?如何更改文件或目录的权限?

Linux中的权限管理是通过访问权限位来实现的,每个文件和目录都有所有者、所属组和其他用户的权限。可以使用chmod命令来更改文件或目录的权限

5、linux的定时任务怎么设置

  • 输入以下命令以编辑当前用户的cron表
crontab -e
  • 根据cron表的格式,在打开的编辑器中添加定时任务。每一行代表一个定时任务,格式如下:
    五个位置的符号分别对应(从左到右数)
  • 分钟(Minute):取值范围为0-59,表示每小时的第几分钟执行任务。
  • 小时(Hour):取值范围为0-23,表示每天的第几个小时执行任务。
  • (Day of month):取值范围为1-31,表示每月的第几天执行任务。
  • (Month):取值范围为1-12,表示每年的第几个月执行任务。
  • 星期几(Day of week):取值范围为0-7(0和7都表示星期日),表示每周的第几天执行任务。

还可以使用以下 特殊字符 来表示时间字段的含义:

星号(*):匹配任意值,表示该字段不限制。

逗号(,):用于分隔多个值,表示在指定的多个值中任选一个。

中划线(-):用于表示范围,表示在指定范围内的所有值都满足条件。

正斜杠(/):用于指定步长,表示按照指定的步长增加值。
* * * * *:每分钟执行一次。

0 * * * *:每小时的第0分钟执行一次。

0 0 * * *:每天的凌晨0点执行一次。

0 0 * * 1:每周一的凌晨0点执行一次。

0 0 1 * *:每个月的1号凌晨0点执行一次。

0 0 1,15 * *:每个月的1号和15号凌晨0点执行一次。

0 0-8/2 * * *:每天的凌晨0点到8点之间,每隔2小时执行一次

(重要) 6、如何在Linux系统上查找文件或目录

  1. 使用find命令:
    find命令递归地在指定路径下查找文件或目录
find <路径> -name "<文件名或通配符>"

“<路径>”是要查找的起始路径,“<文件名或通配符>”是要查找的文件名或通配符模式。

例如:find . -name "*.txt"

2. 使用locate命令:
locate命令通过搜索系统的数据库来查找文件或目录。它通常比find命令快速,但可能不会显示最新创建的文件。
3. 使用grep命令:
grep命令用于在文件中搜索匹配指定模式的行。可以与其他命令(如find)结合使用来过滤查找结果。

经常用到的参数有:

-r:递归地搜索目录及其子目录中的文件。
-n:显示匹配行的行号。
-w:只匹配整个单词,而不是匹配包含模式的部分。
grep -rnw '<路径>' -e '<匹配模式>'

例如:grep -rnw '.' -e 'example'   
(在当前目录及其子目录下查找包含关键字"example"的文件内容:)

7、 要在 Linux 中查找某一个进程(使用ps结合grep)

ps aux | grep <进程名或关键字>
例如:查找名为 "nginx" 的进程:
ps aux | grep nginx

8、使用ssh来连接服务器

ssh username@hostname :
username 是您在远程主机上的用户名,hostname 是远程主机的 IP 地址或域名,按下回车后就会显示输入密码

杂项

1、 Saas模式下的系统有什么不一样

SaaS模式下,用户不需要购买软件的许可证,而是通过订阅的方式使用软件。用户可以通过网页浏览器或特定的客户端应用程序访问云端的软件,并在云端进行数据存储和处理。
所以说,SaaS系统通常会使用云服务提供商来托管应用程序和数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值