1. 程式人生 > >2018/08/24 《輕松學算法》 學習筆記(八)

2018/08/24 《輕松學算法》 學習筆記(八)

長度 ont 操作 com bcb 旋轉 bst dcb 建立

推薦一首歌

  《陌生人》 丁倩倩

  第七章《字符串》

總結

1:字符串的全排列問題

  - 字典表排列,也是數字組合的排列

  - 字符串也可以受用下標 123 代替,那麽等於我們直接對 123...排序在連接在字符串上去了

  - 一種實現方式如下

<?php

$arr = [1,2,3];

function x($arr, $str) {

    $count = count($arr);

    if ($count == 1) {
        echo $str . $arr[0]."</br>";
    }
    else {
        
for ($i=0; $i < $count; $i++) { list($arr[0],$arr[$i]) = [$arr[$i], $arr[0]]; x(array_slice($arr, 1), $str . $arr[0]); } } } x($arr, ‘‘);

2:字符串反轉問題。

  - 這裏要註意的是,如果是中文字符反轉,使用$str[$i] 直接獲取是不行的,需要使用 mb_string 函數來操作

  -

<?php

$str = 一二三四五六七八九;

function strrev1($str) {

    $count 
= strlen($str); $new_str = ‘‘; for ($i = $count - 1; $i >= 0 ; $i--) { $new_str .= mb_substr($str,$i,1,utf-8); } echo $new_str; } strrev1($str);

3:關於指定位置旋轉字符串問題。

  - 比如一個字符串為 abcdefg 需要從第三個字符開始旋轉 得到的結果是 efgabcd

  - 我們也可以像之前一樣,使用簡單排序,讓 e 排到第一個,f在排....

  - 但是這樣需要很大的時間復雜讀,這裏介紹一種,叫三步反轉法

    - 第一步 反轉 abcd 成為 dcba

    - 第二部 反轉 efg 成為 gfe

    - 第三部 連接 dcbagfe 整體反轉,得到字符串。

  -

<?php

$str = abcdefg;

function strrev1($str, $target) {

    // 第一部分
    $left = mb_substr($str, 0, $target);
    $right = mb_substr($str, $target);

    for ($i = strlen($left) - 1; $i >= 0; $i--) { 
        $new_left .= $left[$i];
    }

    for ($i = strlen($right) - 1; $i >= 0; $i--) { 
        $new_right .= $right[$i];
    }

    $str = $new_left . $new_right;

    for ($i = strlen($str) - 1; $i >= 0; $i--) { 
        $new_str .= $str[$i];
    }

    echo $new_str;
}

strrev1($str, 4);

4:字符串回文問題

  - 什麽是回文,就是正著讀和反著讀是一樣的。

    - 比如 abcba

  - 那麽如何判斷是否是回文字符串呢

  - 我們可以使用折半來判斷

    - 這裏需要特別註意中軸的計算,如果長度為7,那麽下標為[0-6],中軸就為3,如果為8,下標[0-7],這裏中軸應該選擇3。

    - 中軸下標計算公式 (n - 1) / 2

    - 7個數,中軸為3,0對應的就應該是6,8個數,中軸為3,0對應的應該為7

    - 所以,對應的計算公式為 n-1-k

-

<?php

$str = 123-1-321;

function strUtils($str) {

    $legth = strlen($str);

    $middle = floor(($legth-1) / 2);

    for ($i=0; $i < $middle; $i++) { 
        if ($str[$i] != $str[$legth-1-$i]) {
            return false;
        }
    }
    
    return true;
}

var_dump(strUtils($str));

5:查找最大回文字符串

  - 尋找字符串中最長的回文字符串,例如 abcdedc ,最大回文字符串為 cdedc

  - 這裏的最簡單的辦法也就是,把每一個點都單做是中軸點,來看最長的匹配

  - 這裏是我自己的想法,找出最大回文的開始和結束,最夠同意輸出字符串

<?php

$str = abcdedc;

function strUtils($str) {

    $legth = strlen($str);

    // 最大回文開始
    $str_strart = 0;

    // 最大回文結束
    $str_end = 0;

    // 臨時字段,確認誰是相隔最大的回文
    $tmp = 0;

    // 遍歷,認為每個點都是中軸點
    for ($i=0; $i < $legth; $i++) { 
        
        // 獲取中軸點
        $middle = $i;
        if ($middle == 0 || $middle == $legth -1) continue;

        for ($k=0; $k < $middle; $k++) { 

            if ($str[$i - $k] != $str[$i+ $k]) {
                break;
            }
            // 循環-找到差距最大的組
            else {
                // 回文開始和結束,最大間隔
                if ((2 * $k) > $tmp) {
                    $str_strart = $i - $k;
                    $str_end = $i + $k;
                }
            }
        }
    }

    // 輸出回文字符串
    for ($i = $str_strart; $i <= $str_end; $i++) { 
        $result .= $str[$i];
    }

    if (strlen($result) < 2) return false;

    return $result;
}

var_dump(strUtils($str));

6:字符串包含問題

  - 可以使用正常的遍歷,但是會導致時間度非常大O(M * N)

  - 這裏使用HashTable做排序,適合重復字符串不多的字符串

  -

<?php

$str1 = 123;
$str2 = 123456789;

function strExists($str1, $str2) {

    $str2_arrays = str_split($str2);

    // 建立$str1的HashTable
    foreach ($str2_arrays as $key => $str2_array) {
        $HashTable[$str2_array] = $key;
    }

    for ($i=0; $i < strlen($str1); $i++) {

        $data = $HashTable[$str1[$i]];
        
        $exists[] = $data;
    }

    for ($k=0; $k < count($exists) - 1; $k++) { 

        if (($exists[$k] + 1) != $exists[$k + 1]) {
            return false;
        }
    }

    return true;
}
var_dump(strExists($str1, $str2));

2018/08/24 《輕松學算法》 學習筆記(八)