php演算法實現(一)

瘦瘦鴨發表於2019-02-16

記錄所有演算法相關知識。寫演算法時,可以先寫test case,這樣比較容易把握和思考。
以下演算法都可以直接跑。
1.冒泡演算法

    <?php
    
    $arr = [2,1,4,3,8,9,7,6,5];
    print_r(bubbleSort($arr));
    
    function bubbleSort($arr) 
    {
        $length = count($arr);
        for($i=0;$i<$length;$i++) {
            for($j=$i+1;$j<$length;$j++) {
                if ($arr[$i] > $arr[$j]) {
                    //這種形式比較簡便易讀
                    list($arr[$i], $arr[$j]) = array($arr[$j], $arr[$i]);
                }
            }
        }
        return $arr;
    }

2.快速排序。簡單思路,隨機挑選一個陣列中的值,以它為標準,小於他的放在她的左邊,大於他的放在他的右邊。之後遞迴,最後所有的值都會排列好。

<?php

$arr = [8,7,6,5,4,0, -1, -3,3,2,1];
print_r(quickSort($arr));

function quickSort($arr)
{
    $length = count($arr);
    //判斷結束的標準,單一變數
    if ($length <= 1) return $arr;
    //取random整數,隨機防止特殊情況時間複雜度升為n^2
    $index = rand(0, $length - 1);
    $reference = $arr[$index];
    $left = $right = array();
    //注意是小於length即可
    for ($i=0;$i<$length;$i++) {
        if ($i!=$index) {
            if ($arr[$i] <= $reference) {
                array_push($left, $arr[$i]); 
            } else {
                array_push($right, $arr[$i]);
            }
        }
    }
    $left = quickSort($left);
    $right = quickSort($right);
    return array_merge($left, [$reference], $right);
}

3.從兩個陣列中找出相同的數

<?php

$arr1 = [5,4,3,2,1];
$arr2 = [4,5,6,7,8];
print_r(uniqueNumber($arr1, $arr2));

function uniqueNumber($arr1, $arr2)
{
    sort($arr1);
    sort($arr2);
    $length1 = count($arr1);
    $length2 = count($arr2);
    $index1 = $index2 = 0;
    $container = [];
    while ($index1 < $length1 && $index2 < $length2) {
        if($arr1[$index1] < $arr2[$index2]) {
            $index1++;
        } else if ($arr1[$index1] > $arr2[$index2]) {
            $index2++;
        } else {
            $container[] = $arr1[$index1];
            //放入container之後,不要忘記增加index
            $index1++;
            $index2++;
        }
    }
    return array_unique($container);
}

4.重寫shuffle函式,打亂一個陣列

<?php

$arr = [2,3,4,5,6,7,8,9];
print_r(shuffleRewrite($arr));

//這邊不能用shuffle,因為是內建函式。
function shuffleRewrite($arr)
{
    $length = count($arr);
    for($i=0;$i<$length;$i++) {
        $index = rand(0, $length-1);
        list($arr[$i], $arr[$index]) = array($arr[$index], $arr[$i]);
    }
    return $arr;
}

5.分離字母和數字。一個string中有字母數字,分離並用:分割

<?php

$numAlpha = "abc123dfg4jkl567ddd";
print_r(numAlphaSplit($numAlpha));

function numAlphaSplit($numAlpha)
{
    $number = preg_split(`/[a-z]+/`, $numAlpha, -1, PREG_SPLIT_NO_EMPTY);
    $alpha = preg_split(`/d+/`, $numAlpha, -1, PREG_SPLIT_NO_EMPTY);
    $result = ``;
    for($i=0;$i<count($number);$i++) {
        $result .= $number[$i] . `:` . $alpha[$i];
    }
    //不要忘了其中一個可能會多,有沒有更好的方法?
    $result .= isset($alpha[count($number)])?$alpha[count($number)]:``;
    return $result;
}

6.約瑟夫環問題
相關題目:一群猴子排成一圈,按1,2,…,n依次編號。然後從第1只開始數,數到第m只,把它踢出圈,從它後面再開始數, 再數到第m只,在把它踢出去…,如此不停的進行下去, 直到最後只剩下一隻猴子為止,那隻猴子就叫做大王。要求程式設計模擬此過程,輸入m、n, 輸出最後那個大王的編號。

<?php 

$m = 3; $n = 3;
echo roundCount($m, $n);

function roundCount($m, $n)
{
    $roundTable = range(1, $m);
    while (count($roundTable) > 1) {
        for ($i=0;$i<$n-1;$i++) {
            $pop = array_shift($roundTable);
            array_push($roundTable, $pop);
        }
        array_shift($roundTable);
    }
    return $roundTable[0];
}

7.二分法

<?php

$arr = [1,3,5,7,9,11,13];
echo binarySearch($arr, 11);

function binarySearch($arr, $index)
{
    $length = count($arr);
    $left = 0;
    $right = $length-1;
    
    while ($left <= $right) {
        //注意要在while裡邊求mid值
        $mid = intval(($left+$right)/2);
        //用arr[$mid]和要找的值比較,用mid來增減位置
        if ($arr[$mid] > $index) {
            $right = $mid - 1;
        } else if ($arr[$mid] < $index) {
            $left = $mid + 1;
        } else {
            return $mid;
        }
    }
    return -1;
}

8.找出一組數中連續的最大和

<?php

$arr = [-4, -2, 4, -3, 6, -2, 9, -3];
echo maxSum($arr);

function maxSum($arr)
{
    $currentSum = 0;
    $maxSum = 0;//陣列元素全為負的情況,返回最大數

    for ($i = 0; $i < count($arr); $i++) { 
        if ($currentSum >= 0) {
            if ($maxSum < $currentSum) 
                $maxSum = $currentSum;
            $currentSum += $arr[$i];
        } else {
            $currentSum = $arr[$i];
        }
    }
    return $maxSum;
}

9.3sum. 排序好的數列,複雜度n^2。如果沒有排列好,可以先用sort

<?php

$arr = [-8,-7,-6,-4,-2,0,1,2,3,4,5,6,7];
print_r(sum3($arr));

function sum3($arr)
{
    $result = [];
    for ($i=0;$i<count($arr)-1;$i++) {
        //左邊的從index之後開始就可以,會覆蓋前面的
        $left = $i + 1;
        $right = count($arr) -1;
        //有這個right>left,所以不用擔心i,left,right相等
        while ($right > $left) {
            $sum = $arr[$left] + $arr[$i] + $arr[$right];
            if ($sum < 0) {
                $left++;
            } else if ($sum > 0) {
                $right--;
            } else {
                $set = array($arr[$left], $arr[$i], $arr[$right]);
                $result[] = $set;
                //不要忘記++,否則死迴圈
                $left++;
                $right--;
            }
        }
    }
    return $result;
}

相關文章