PHP中的一些小算法

1.数组反转函数
/**
 *  数组反转函数
 *  @param array arr  
 *  @return array
 */
function reverse($arr)
{
    $count = count($arr);
    $left = 0;
    $right = $count - 1;
    // 第一个和最后一个互换,第二个和倒数第二个互换,依次反转
    while ($left < $right)
    {
        $temp = $arr[$left];
        $arr[$left++] = $arr[$right];
        $arr[$right--] = $temp;
    }
    return $arr;
}
2.找出两个有序数字元素数组中的相同元素
/**
 *  找出两个有序数字元素数组中的相同元素
 *  @param array $arr1
 *  @param array $arr2
 *  @return array
 */
function find_common($arr1, $arr2)
{
    $i = $j = 0;
    $common = array();
    $count1 = count($arr1);
    $count2 = count($arr2);
    // 因为是有序数组,从arr1和arr2的第一个元素开始相比,比完没有则执行一遍,有相等的从相等的后一个开始继续比
    while ($i < $count1 && $j < $count2)
    {
        if ($arr1[$i] < $arr2[$j]) {
            $i++;
        } elseif ($arr1[$i] > $arr2[$j]) {
            $j++;
        } else {
            $common[] = $arr1[$i];
            $i++;
            $j++;
        }
    }
    // 移除数组中重复的值
    return array_unique($common);
}
3.将数组中的元素随机打乱
 /**
  *  将数组中的元素打乱
  *  @param array $arr
  *  @return array
  */
function custom_shuffle($arr)
{
    $count = count($arr);
    // 从数组中随机获取一个和当前元素交换,最多交换的次数等于该数组的元素个数
    for ($i = 0; $i < $count; $i++)
    {
        $rand_pos = mt_rand(0,$count);
        if ($rand_pos != $i) {
            $temp = $arr[$i];
            $arr[$i] = $arr[$rand_pos];
            $arr[$rand_pos] = $temp;
        }
    }
    return $arr; 
 }
4.一个数字字母相连的字符串,让数字和字母对应
 /**
  * 将一个数字字母相连的字符串,使数字和字母对应
  * @param $str
  */
 function nember_alphabet($str)
 {
     // 通过正则表达式将字符串分割成数组,-1、0、null表示不限制个数,否则显示设置的个数,最后一个将返回剩余的子串
     $number = preg_split('/[a-z]+/', $str, -1, PREG_SPLIT_NO_EMPTY);
     $alphabet = preg_split('/d+/', $str, -1, PREG_SPLIT_NO_EMPTY);
     $count = count($number);
     for ($i = 0; $i < $count; $i++)
     {
         echo $number[$i].':'.$alphabet[$i].'<br>';
     }
 }

 $str = '1a3bb44a2ac';
 number_alphabet($str); // 1:a 3:bb 44:a 2:ac
5.求n以内的质数
 /**
  * 求n以内的质数
  * 想到高中时老默写不出来,后来死记硬背,哈哈,唉,岁月如歌
  * @param int $n
  * @return array
  */
function get_prime($n)
{
    // n以内的质数数组
    $prime = array(2);
    // 所有的偶数都不是质数,所以去掉
    for ($i = 3; $i < $n; $i += 2)
    {
        // 先将n开平方根
        $sqrt = intval(sqrt($i));
        // 计算3到平方根之间的数能否被整除
        for ($j = 3; $j <= $sqrt; $j += 2)
        {
            if ($i % $j == 0) {
                break;
            }
        }
        // 如果是质数,加入数组
        if ($j > $sqrt) {
            array_push($prime, $i);
        }
    }
    return $prime;
}
6.约瑟夫环问题
/**
 *  获取最后那个数
 *  算法的魅力就是打开你的新世界,这个算法就有点精髓
 *  @param int $n
 *  @param int $m
 *  @return int
 */
function get_king_mokey($n, $m)
{
    // 生成从1到$n的自然数数组
    $arr = range(1, $n);
    $i = 0;
    while (count($arr) > 1)
    {
        $i++;
        // 删除第一个元素,并返回被删除的值
        $survice = array_shift($arr);
        // 如果这个值不是第$m值,再将值插入到数组后面
        if ($i % $m != 0) {
            array_push($arr, $survice);
        }
    }
    return $arr[0];
}
7.寻找一个数组里最小的k个数
/**
 * 从n个整数中获取最小的k个数
 * @param  array $arr
 * @param  int $k
 * @return array
 */
function get_min_array($arr, $k)
{
    $n = count($arr);
    $min_array = array();
    for ($i = 0; $i < $n; $i++) {
        // 默认前k个为最小
        if ($i < $k) {
            $min_array[$i] = $arr[$i];
        } else {
            if ($i == $k) {
                // 取出最大值的位置
                $max_pos = get_max_pos($min_array);
                // 获取$min_array数组中最大的数
                $max = $min_array[$max_pos];
            }
            // 如果比最大的小,则替换掉$min_array数组中最大的值
            if ($arr[$i] < $max) {
                $min_array[$max_pos] = $arr[$i];
                // 重新获取$min_array数组中最大的值跟$arr数组中的剩下的数继续比对
                $max_pos = get_max_pos($min_array);
                $max = $min_array[$max_pos];
            }
        }
    }

    return $min_array;
}

/**
 * 获取最大的位置
 * @param  array $arr
 * @return array
 */
function get_max_pos($arr)
{
    $pos = 0;
    for ($i = 1; $i < count($arr); $i++) {
        if ($arr[$i] > $arr[$pos]) {
            $pos = $i;
        }
    }

    return $pos;
}

$array = [1, 100, 20, 22, 33, 44, 55, 66, 23, 79, 18, 20, 11, 9, 129, 399, 145, 2469, 58];

$min_array = get_min_array($array, 10);

print_r($min_array);
8.二分查找
/**
 * 二分查找
 * @param  array $array 数组
 * @param  int $n 数组数量
 * @param  int $value 要寻找的值
 * @return int
 */
function binary_search($array, $n, $value)
{
    $left = 0;
    $right = $n - 1;

    while ($left <= $right) {
        // 找到中间位置的下标
        $mid = intval(($left + $right) / 2);
        if ($value > $mid) {
            $right = $mid + 1;
        } elseif ($value < $mid) {
            $left = $mid - 1;
        } else {
            return $mid;
        }
    }
    return -1;
}
9.给定一个有序整数序列,找出绝对值最小的元素
/**
 * 获取绝对值最小的元素
 * @param  array $arr
 * @return int  
 */
function get_min_abs_value($arr)
{
    //如果符号相同,直接返回
    if (is_same_sign($arr[0], $arr[$n - 1])) {
        return $arr[0] >= 0 ? $arr[0] : $arr[$n - 1];
    }

    //二分查找
    $n = count($arr);
    $left = 0;
    $right = $n - 1;

    while ($left <= $right) {
        if ($left + 1 === $right) {
            return abs($arr[$left]) < abs($arr[$right]) ? $arr[$left] : $arr[$right];
        }

        $mid = intval(($left + $right) / 2);

        if ($arr[$mid] < 0) {
            $left = $mid + 1;
        } else {
            $right = $mid - 1;
        }
    }
}

/**
 * 判断符号是否相同
 * @param  int  $a
 * @param  int  $b
 * @return boolean  
 */
function is_same_sign($a, $b)
{
    if ($a * $b > 0) {
        return true;
    } else {
        return false;
    }
}
10.找出有序数组中随机3个数和为0的所有情况
/**
 *  @param $arr
 */
function three_sum($arr)
{
    $n = count($arr);
    $return = array();
    for ($i=0; $i < $n; $i++) {
        $left = $i + 1;
        $right = $n - 1;

        while ($left <= $right) {
            $sum = $arr[$i] + $arr[$left] + $arr[$right];

            if ($sum < 0) {
                $left++;
            } elseif ($sum > 0) {
                $right--;
            } else {
                $numbers = $arr[$i] . ',' . $arr[$left] . ',' . $arr[$right];
                if (!in_array($numbers, $return)) {
                    $return[] = $numbers;
                }

                $left++;
                $right--;
            }
        }
    }

    return $return;
}

$arr = [-10, -9, -8, -4, -2, 0, 1, 2, 3, 4, 5, 6, 9];
var_dump(three_sum($arr));
11.编写一个PHP函数,求任意n个正负整数里面最大的连续和,要求算法时间复杂度尽可能低。
/**
 * 获取最大的连续和
 * @param  array $arr
 * @return int
 */
function max_sum_array($arr)
{
    $currSum = 0;
    $maxSum = 0; // 数组元素全为负的情况,返回最大数
    $n = count($arr);
    for ($i = 0; $i < $n; $i++) {
        if ($currSum >= 0) {
            $currSum += $arr[$i];
        } else {
            $currSum = $arr[$i];
        }
    }

    if ($currSum > $maxSum) {
        $maxSum = $currSum;
    }

    return $maxSum;
}

原文链接:http://coffeephp.com/articles/4

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值