feat: Add PHP Codes for chapter_computational_complexity
This commit is contained in:
parent
e1e0668e0f
commit
422694cf2c
76
codes/php/chapter_computational_complexity/iteration.php
Normal file
76
codes/php/chapter_computational_complexity/iteration.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* File: iteration.php
|
||||
* Created Time: 2024-05-19
|
||||
* Author: DoWake (admin@mengxing.cc)
|
||||
*/
|
||||
|
||||
/* for 循环 */
|
||||
function forLoop($n)
|
||||
{
|
||||
$res = 0;
|
||||
// 循环求和 1, 2, ..., n-1, n
|
||||
for ($i = 1; $i <= $n; $i++) {
|
||||
$res += $i;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/* while 循环 */
|
||||
function whileLoop($n)
|
||||
{
|
||||
$res = 0;
|
||||
$i = 1; // 初始化条件变量
|
||||
// 循环求和 1, 2, ..., n-1, n
|
||||
while ($i <= $n) {
|
||||
$res += $i;
|
||||
$i++; // 更新条件变量
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/* while 循环(两次更新) */
|
||||
function whileLoopII($n)
|
||||
{
|
||||
$res = 0;
|
||||
$i = 1; // 初始化条件变量
|
||||
// 循环求和 1, 4, 10, ...
|
||||
while ($i <= $n) {
|
||||
$res += $i;
|
||||
// 更新条件变量
|
||||
$i++;
|
||||
$i *= 2;
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/* 双层 for 循环 */
|
||||
function nestedForLoop($n)
|
||||
{
|
||||
$res = '';
|
||||
// 循环 i = 1, 2, ..., n-1, n
|
||||
for ($i = 1; $i <= $n; $i++) {
|
||||
// 循环 j = 1, 2, ..., n-1, n
|
||||
for ($j = 1; $j <= $n; $j++) {
|
||||
$res .= '(' . $i . ', ' . $j . '), ';
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
$n = 5;
|
||||
$res = 0;
|
||||
|
||||
$res = forLoop($n);
|
||||
echo "\nfor 循环的求和结果 res = {$res}" . PHP_EOL;
|
||||
|
||||
$res = whileLoop($n);
|
||||
echo "\nwhile 循环的求和结果 res = {$res}" . PHP_EOL;
|
||||
|
||||
$res = whileLoopII($n);
|
||||
echo "\nwhile 循环(两次更新)求和结果 res = {$res}" . PHP_EOL;
|
||||
|
||||
$resStr = nestedForLoop($n);
|
||||
echo "\n双层 for 循环的遍历结果 {$resStr}" . PHP_EOL;
|
||||
80
codes/php/chapter_computational_complexity/recursion.php
Normal file
80
codes/php/chapter_computational_complexity/recursion.php
Normal file
@ -0,0 +1,80 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* File: recursion.php
|
||||
* Created Time: 2024-05-19
|
||||
* Author: DoWake (admin@mengxing.cc)
|
||||
*/
|
||||
|
||||
/* 递归 */
|
||||
function recur($n)
|
||||
{
|
||||
// 终止条件
|
||||
if ($n === 1) {
|
||||
return 1;
|
||||
}
|
||||
// 递:递归调用
|
||||
$res = recur($n - 1);
|
||||
// 归:返回结果
|
||||
return $n + $res;
|
||||
}
|
||||
|
||||
/* 使用迭代模拟递归 */
|
||||
function forLoopRecur($n)
|
||||
{
|
||||
// 使用一个显式的栈来模拟系统调用栈
|
||||
$stack = [];
|
||||
$res = 0;
|
||||
// 递:递归调用
|
||||
for ($i = $n; $i > 0; $i--) {
|
||||
// 通过“入栈操作”模拟“递”
|
||||
array_push($stack, $i);
|
||||
}
|
||||
// 归:返回结果
|
||||
while (!empty($stack)) {
|
||||
// 通过“出栈操作”模拟“归”
|
||||
$res += array_pop($stack);
|
||||
}
|
||||
// res = 1+2+3+...+n
|
||||
return $res;
|
||||
}
|
||||
|
||||
/* 尾递归 */
|
||||
function tailRecur($n, $res)
|
||||
{
|
||||
// 终止条件
|
||||
if ($n === 0) {
|
||||
return $res;
|
||||
}
|
||||
// 尾递归调用
|
||||
return tailRecur($n - 1, $res + $n);
|
||||
}
|
||||
|
||||
/* 斐波那契数列:递归 */
|
||||
function fib($n)
|
||||
{
|
||||
// 终止条件 f(1) = 0, f(2) = 1
|
||||
if ($n === 1 || $n === 2) {
|
||||
return $n - 1;
|
||||
}
|
||||
// 递归调用 f(n) = f(n-1) + f(n-2)
|
||||
$res = fib($n - 1) + fib($n - 2);
|
||||
// 返回结果 f(n)
|
||||
return $res;
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
$n = 5;
|
||||
$res = 0;
|
||||
|
||||
$res = recur($n);
|
||||
echo "\n递归函数的求和结果 res = {$res}" . PHP_EOL;
|
||||
|
||||
$res = forLoopRecur($n);
|
||||
echo "\n使用迭代模拟递归求和结果 res = {$res}" . PHP_EOL;
|
||||
|
||||
$res = tailRecur($n, 0);
|
||||
echo "\n尾递归函数的求和结果 res = {$res}" . PHP_EOL;
|
||||
|
||||
$res = fib($n);
|
||||
echo "\n斐波那契数列的第 {$n} 项为 {$res}" . PHP_EOL;
|
||||
117
codes/php/chapter_computational_complexity/space_complexity.php
Normal file
117
codes/php/chapter_computational_complexity/space_complexity.php
Normal file
@ -0,0 +1,117 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* File: space_complexity.php
|
||||
* Created Time: 2024-05-19
|
||||
* Author: DoWake (admin@mengxing.cc)
|
||||
*/
|
||||
|
||||
require_once '../utils/ListNode.php';
|
||||
require_once '../utils/TreeNode.php';
|
||||
require_once '../utils/PrintUtil.php';
|
||||
|
||||
/* 函数 */
|
||||
function func()
|
||||
{
|
||||
// 执行某些操作
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 常数阶 */
|
||||
function spaceConstant($n)
|
||||
{
|
||||
// 常量、变量、对象占用 O(1) 空间
|
||||
define('A', 0);
|
||||
$b = 0;
|
||||
$nums = array_fill(0, 10000, 0);
|
||||
$node = new ListNode(0);
|
||||
// 循环中的变量占用 O(1) 空间
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$c = 0;
|
||||
}
|
||||
// 循环中的函数占用 O(1) 空间
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
func();
|
||||
}
|
||||
}
|
||||
|
||||
/* 线性阶 */
|
||||
function linear($n)
|
||||
{
|
||||
// 长度为 n 的数组占用 O(n) 空间
|
||||
$nums = array_fill(0, $n, 0);
|
||||
// 长度为 n 的列表占用 O(n) 空间
|
||||
$nodes = [];
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$nodes[] = new ListNode($i);
|
||||
}
|
||||
// 长度为 n 的哈希表占用 O(n) 空间
|
||||
$map = [];
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$map[$i] = strval($i);
|
||||
}
|
||||
}
|
||||
|
||||
/* 线性阶(递归实现) */
|
||||
function linearRecur($n)
|
||||
{
|
||||
echo "递归 n = {$n}" . PHP_EOL;
|
||||
if ($n === 1) {
|
||||
return;
|
||||
}
|
||||
linearRecur($n - 1);
|
||||
}
|
||||
|
||||
/* 平方阶 */
|
||||
function quadratic($n)
|
||||
{
|
||||
// 矩阵占用 O(n^2) 空间
|
||||
$numMatrix = array_fill(0, $n, array_fill(0, $n, 0));
|
||||
// 二维列表占用 O(n^2) 空间
|
||||
$numList = [];
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$tmp = [];
|
||||
for ($j = 0; $j < $n; $j++) {
|
||||
$tmp[] = 0;
|
||||
}
|
||||
$numList[] = $tmp;
|
||||
}
|
||||
}
|
||||
|
||||
/* 平方阶(递归实现) */
|
||||
function quadraticRecur($n)
|
||||
{
|
||||
if ($n <= 0) {
|
||||
return 0;
|
||||
}
|
||||
// 数组 nums 长度为 n, n-1, ..., 2, 1
|
||||
$nums = array_fill(0, $n, 0);
|
||||
echo "递归 n = {$n} 中的 nums 长度 = " . count($nums) . PHP_EOL;
|
||||
return quadraticRecur($n - 1);
|
||||
}
|
||||
|
||||
/* 指数阶(建立满二叉树) */
|
||||
function buildTree($n)
|
||||
{
|
||||
if ($n === 0) {
|
||||
return null;
|
||||
}
|
||||
$root = new TreeNode(0);
|
||||
$root->left = buildTree($n - 1);
|
||||
$root->right = buildTree($n - 1);
|
||||
return $root;
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
$n = 5;
|
||||
// 常数阶
|
||||
spaceConstant($n);
|
||||
// 线性阶
|
||||
linear($n);
|
||||
linearRecur($n);
|
||||
// 平方阶
|
||||
quadratic($n);
|
||||
quadraticRecur($n);
|
||||
// 指数阶
|
||||
$root = buildTree($n);
|
||||
PrintUtil::printTree($root);
|
||||
184
codes/php/chapter_computational_complexity/time_complexity.php
Normal file
184
codes/php/chapter_computational_complexity/time_complexity.php
Normal file
@ -0,0 +1,184 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* File: time_complexity.php
|
||||
* Created Time: 2024-05-19
|
||||
* Author: DoWake (admin@mengxing.cc)
|
||||
*/
|
||||
|
||||
|
||||
/* 常数阶 */
|
||||
function timeConstant($n)
|
||||
{
|
||||
$count = 0;
|
||||
$size = 100000;
|
||||
for ($i = 0; $i < $size; $i++) {
|
||||
$count++;
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/* 线性阶 */
|
||||
function linear($n)
|
||||
{
|
||||
$count = 0;
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$count++;
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/* 线性阶(遍历数组) */
|
||||
function arrayTraversal($nums)
|
||||
{
|
||||
$count = 0;
|
||||
// 循环次数与数组长度成正比
|
||||
foreach ($nums as $num) {
|
||||
$count++;
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/* 平方阶 */
|
||||
function quadratic($n)
|
||||
{
|
||||
$count = 0;
|
||||
// 循环次数与数据大小 n 成平方关系
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
for ($j = 0; $j < $n; $j++) {
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/* 平方阶(冒泡排序) */
|
||||
function bubbleSort($nums)
|
||||
{
|
||||
$count = 0; // 计数器
|
||||
// 外循环:未排序区间为 [0, i]
|
||||
for ($i = count($nums) - 1; $i > 0; $i--) {
|
||||
// 内循环:将未排序区间 [0, i] 中的最大元素交换至该区间的最右端
|
||||
for ($j = 0; $j < $i; $j++) {
|
||||
if ($nums[$j] > $nums[$j + 1]) {
|
||||
// 交换 nums[j] 与 nums[j + 1]
|
||||
$tmp = $nums[$j];
|
||||
$nums[$j] = $nums[$j + 1];
|
||||
$nums[$j + 1] = $tmp;
|
||||
$count += 3; // 元素交换包含 3 个单元操作
|
||||
}
|
||||
}
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/* 指数阶(循环实现) */
|
||||
function exponential($n)
|
||||
{
|
||||
$count = 0;
|
||||
$base = 1;
|
||||
// 细胞每轮一分为二,形成数列 1, 2, 4, 8, ..., 2^(n-1)
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
for ($j = 0; $j < $base; $j++) {
|
||||
$count++;
|
||||
}
|
||||
$base *= 2;
|
||||
}
|
||||
// count = 1 + 2 + 4 + 8 + .. + 2^(n-1) = 2^n - 1
|
||||
return $count;
|
||||
}
|
||||
|
||||
/* 指数阶(递归实现) */
|
||||
function expRecur($n)
|
||||
{
|
||||
if ($n === 1) {
|
||||
return 1;
|
||||
}
|
||||
return expRecur($n - 1) + expRecur($n - 1) + 1;
|
||||
}
|
||||
|
||||
/* 对数阶(循环实现) */
|
||||
function logarithmic($n)
|
||||
{
|
||||
$count = 0;
|
||||
while ($n > 1) {
|
||||
$n = $n / 2;
|
||||
$count++;
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/* 对数阶(递归实现) */
|
||||
function logRecur($n)
|
||||
{
|
||||
if ($n <= 1) {
|
||||
return 0;
|
||||
}
|
||||
return logRecur($n / 2) + 1;
|
||||
}
|
||||
|
||||
/* 线性对数阶 */
|
||||
function linearLogRecur($n)
|
||||
{
|
||||
if ($n <= 1) {
|
||||
return 1;
|
||||
}
|
||||
$count = linearLogRecur($n / 2) + linearLogRecur($n / 2);
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$count++;
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/* 阶乘阶(递归实现) */
|
||||
function factorialRecur($n)
|
||||
{
|
||||
if ($n === 0) {
|
||||
return 1;
|
||||
}
|
||||
$count = 0;
|
||||
// 从 1 个分裂出 n 个
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$count += factorialRecur($n - 1);
|
||||
}
|
||||
return $count;
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
// 可以修改 n 运行,体会一下各种复杂度的操作数量变化趋势
|
||||
$n = 8;
|
||||
echo "输入数据大小 n = {$n}" . PHP_EOL;
|
||||
|
||||
$count = timeConstant($n);
|
||||
echo "常数阶的操作数量 = {$count}" . PHP_EOL;
|
||||
|
||||
$count = linear($n);
|
||||
echo "线性阶的操作数量 = {$count}" . PHP_EOL;
|
||||
$count = arrayTraversal(array_fill(0, $n, 0));
|
||||
echo "线性阶(遍历数组)的操作数量 = {$count}" . PHP_EOL;
|
||||
|
||||
$count = quadratic($n);
|
||||
echo "平方阶的操作数量 = {$count}" . PHP_EOL;
|
||||
$nums = [];
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$nums[$i] = $n - $i; // [n,n-1,...,2,1]
|
||||
}
|
||||
$count = bubbleSort($nums);
|
||||
echo "平方阶(冒泡排序)的操作数量 = {$count}" . PHP_EOL;
|
||||
|
||||
$count = exponential($n);
|
||||
echo "指数阶(循环实现)的操作数量 = {$count}" . PHP_EOL;
|
||||
$count = expRecur($n);
|
||||
echo "指数阶(递归实现)的操作数量 = {$count}" . PHP_EOL;
|
||||
|
||||
$count = logarithmic($n);
|
||||
echo "对数阶(循环实现)的操作数量 = {$count}" . PHP_EOL;
|
||||
|
||||
$count = logRecur($n);
|
||||
echo "对数阶(递归实现)的操作数量 = {$count}" . PHP_EOL;
|
||||
|
||||
$count = linearLogRecur($n);
|
||||
echo "线性对数阶(递归实现)的操作数量 = {$count}" . PHP_EOL;
|
||||
|
||||
$count = factorialRecur($n);
|
||||
echo "阶乘阶(递归实现)的操作数量 = {$count}" . PHP_EOL;
|
||||
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* File: worst_best_time_complexity.php
|
||||
* Created Time: 2024-05-19
|
||||
* Author: DoWake (admin@mengxing.cc)
|
||||
*/
|
||||
|
||||
/* 生成一个数组,元素为 { 1, 2, ..., n },顺序被打乱 */
|
||||
function randomNumbers($n)
|
||||
{
|
||||
$nums = [];
|
||||
// 生成数组 nums = { 1, 2, 3, ..., n }
|
||||
for ($i = 0; $i < $n; $i++) {
|
||||
$nums[$i] = $i + 1;
|
||||
}
|
||||
// 随机打乱数组元素
|
||||
shuffle($nums);
|
||||
return $nums;
|
||||
}
|
||||
|
||||
/* 查找数组 nums 中数字 1 所在索引 */
|
||||
function findOne($nums)
|
||||
{
|
||||
foreach ($nums as $key => $value) {
|
||||
// 当元素 1 在数组头部时,达到最佳时间复杂度 O(1)
|
||||
// 当元素 1 在数组尾部时,达到最差时间复杂度 O(n)
|
||||
if ($value === 1) {
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Driver Code */
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$n = 100;
|
||||
$nums = randomNumbers($n);
|
||||
$index = findOne($nums);
|
||||
echo "\n数组 [ 1, 2, ..., n ] 被打乱后 = [" . join(', ', $nums) . "]" . PHP_EOL;
|
||||
echo "数字 1 的索引为 {$index}" . PHP_EOL;
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user