美文网首页
PHP之高频考点算法合辑

PHP之高频考点算法合辑

作者: 后厂村村长 | 来源:发表于2022-01-05 10:45 被阅读0次

    有效括号

    LC: Valid Parentheses - LeetCode
    题解:每遇到一个左括号时,在后续遍历中需要有一个相同类型的右括号将其闭合才行。由于后遇到的左括号要先闭合,因此可以将这个左括号放入栈顶,后进先出,正好符合此要求。另外,PHP由于其语言特性,使用数组函数array_pop来 mock 栈操作。

    function isValid($s) {
        $rcp = [
            ')' => '(',
            '}' => '{',
            ']' => '[',
        ];
        $stack = [];
        $sarr = str_split($s);
        $slen = count($sarr);
        if ($slen%2!==0) {
            return false;
        }
        for ($i=0; $i < $slen; $i++) {
            if (isset($rcp[$sarr[$i]])) {
                $leftBracket = array_pop($stack);
                if ($leftBracket !== $rcp[$sarr[$i]]) {
                    return false;
                }
            } else {
                $stack[] = $sarr[$i];
            }
        }
        return empty($stack);
    }
    $s = "(}";
    var_dump(isValid($s));
    

    螺旋矩阵 I

    LC: Spiral Matrix - LeetCode
    题解:
    其实,就是转圈循环,将矩阵看成一个 回字形 de套娃,每一圈作为一层,先循环最外层,然后次外层、、、以此类推;
    每一层的循环顺序:上(top)、右(right)、下(bot)、左(left);每个方位循环完成后对应的值加1;

    /**
         * @param Integer[][] $matrix
         * @return Integer[]
         */
        function spiralOrder($matrix) {
            $output=[];
            $cnt = count($matrix);
            $horCnt = count($matrix[0]);
            $top = 0;
            $bot = $cnt-1;
            $left = 0;
            $right = $horCnt - 1;
            $eleNum = $cnt * $horCnt;
            while ($eleNum > 0) {
                for ($i=$left; $i <= $right && $eleNum > 0; $i++) { 
                    $output[]=$matrix[$top][$i];
                    $eleNum--;
                }
                $top++;
    
                for ($i=$top; $i <= $bot && $eleNum > 0; $i++) { 
                    $output[]=$matrix[$i][$right];
                    $eleNum--;
                }
                $right--;
    
                for ($i=$right; $i >= $left && $eleNum > 0; $i--) { 
                    $output[]=$matrix[$bot][$i];
                    $eleNum--;
                }
                $bot--;
    
                for ($i=$bot; $i >= $top && $eleNum > 0; $i--) { 
                    $output[]=$matrix[$i][$left];
                    $eleNum--;
                }
                $left++;
            }
            return $output;
        }
    

    螺旋矩阵 II

    LC: Spiral Matrix II - LeetCode
    题解:
    参考上面的 螺旋矩阵-I 的解法,按顺序转圈循环赋值即可。
    注意: 由于PHP本身是弱类型语言,其数组的实现方式不同于其他类型语言,是以 hash table 实现的(可参考:https://phper.shujuwajue.com/shu-zu/phpshu-zu-de-nei-bu-shi-xian),所以不能像其他类型语言一般,直接给一个 n*n 的矩阵数组赋初值。
    所以本文采用了两种方式赋初值:
    1、双循环遍历初值(耗时较多,LC 判定的);
    2、单层循环,子数组使用 range 赋初值,或者按题目要求赋值完成后,执行 ksort 排序;

    /**
         * @param Integer $n
         * @return Integer[][]
         */
        function generateMatrix($n) {
        $ret=[];
        $eleNum=$n*$n;
        // for ($i=0; $i < $n; $i++) { 
        //     $ret[$i] = range(0, $n-1);
        // }
        $iniNum = 1;
        $top=0;
        $bot=$n-1;
        $left=0;
        $right=$n-1;
        while ($eleNum>=$iniNum) {
            for ($i=$left; $i<=$right && $eleNum>=$iniNum; $i++) { 
                $ret[$top][$i]=$iniNum;
                $iniNum++;
            }
            $top++;
    
            for ($i=$top; $i<=$bot && $eleNum>=$iniNum; $i++) { 
                $ret[$i][$right]=$iniNum;
                $iniNum++;
            }
    
            $right--;
    
            for ($i=$right; $i>=$left && $eleNum>=$iniNum; $i--) {
                $ret[$bot][$i]=$iniNum;
                $iniNum++;
            }
            $bot--;
    
            for ($i=$bot; $i>=$top && $eleNum>=$iniNum; $i--) {
                $ret[$i][$left]=$iniNum;
                $iniNum++;
            }
            $left++;
        }
        for ($i=0; $i < $n; $i++) { 
            ksort($ret[$i]);
        }
        return $ret;
        }
    

    剑指offer-05:替换字符串

    题目:

    请实现一个函数,把字符串 s 中的每个空格替换成"%20"。
    示例 1: 输入:s = "We are happy."
    输出:"We%20are%20happy."

    题解:

    首先扩充数组到每个空格替换成"%20"之后的大小。
    然后从后向前替换空格,也就是双指针法:i指向旧长度的末尾,j指向新长度的末尾。

    注意:由于PHP的数组本质为hash table,所以返回前需要对数组进行排序;

    So,为什么要从后向前填充,从前向后填充不行么?

    从前向后填充就是 O(n^2) 的复杂度了:
    因为每次添加元素都要将添加元素之后的所有元素向后移动。
    其实很多数组填充类的问题,都可以先预先给数组扩容带填充后的大小,然后在从后向前进行操作。
    这么做有两个好处:
    不用申请新数组;
    从后向前填充元素,避免了从前先后填充元素要来的 每次添加元素都要将添加元素之后的所有元素向后移动。

    function replaceSpace($s) {
        $slist = str_split($s);
        $spaceCnt = 0;
        for ($i=0; $i < count($slist); $i++) { 
            if ($slist[$i]===' ') {
                $spaceCnt++;
            }
        }
        $oldCnt = count($slist);
        $newCnt = $oldCnt + $spaceCnt * 2;
        $i=$oldCnt-1;
        $j=$newCnt-1;
        while ($i>=0 && $j>=0) {
            if ($slist[$i]===' ') {
                $slist[$j]='0';
                $slist[$j-1]='2';
                $slist[$j-2]='%';
                $j = $j-2;
            } else {
                $slist[$j]=$slist[$i];
            }
            $i--;
            $j--;
        }
        ksort($slist);
        return $slist;
    }
    

    旋转图像

    LC:Rotate Image - LeetCode
    题解:
    其实只需要执行两次数据调换;
    先水平翻转数据;
    再调换主对角线[1]两侧的矩阵数据即可;

    function newrotate(&$matrix) {
        $cnt = count($matrix);
        // 水平翻转
        for ($i=0; $i < $cnt/2; $i++) {
            $swapi = $cnt-1-$i;
            if ($swapi<=$i) {
                break;
            }
            for ($j=0; $j < $cnt; $j++) { 
                list($matrix[$i][$j], $matrix[$swapi][$j]) = [$matrix[$swapi][$j], $matrix[$i][$j]];
            }
        }
        // 主对角线两侧de数据对调
        for ($i=0; $i < $cnt; $i++) { 
            for ($j=0; $j < $i; $j++) { 
                list($matrix[$i][$j], $matrix[$j][$i]) = [$matrix[$j][$i], $matrix[$i][$j]];
            }
        }
        return $matrix;
    }
    $matrix = [[1,2,3],[4,5,6],[7,8,9]];
    print_r(newrotate($matrix));
    

    无重复字符的最长子字符串

    LC链接:https://leetcode.com/problems/longest-substring-without-repeating-characters/
    题解:

    // 传统动态规划方法
    function lengthOfLongestSubstring($s) {
            $slen = strlen($s);
            if ($slen<2) {
                return $slen;
            }
            $sarr = str_split($s);
            $charAt=[];
            $ans=1;
            for ($i=0; $i < $slen; $i++) { 
                for ($j=$i; $j < $slen; $j++) { 
                    if (isset($charAt[$sarr[$j]])) {
                        $ans = max($ans, count($charAt));
                        $charAt=[];
                        break;
                    }
                    $charAt[$sarr[$j]]=$j;
                }
            }
            return $ans;
     }
    $s="dvdf";
    print_r([lengthOfLongestSubstring($s)]);die;
    
    // 优化后的算法
    function mySolution($s) {
        $l = strlen($s);
        if ($l<2) {
            return $l;
        }
        $ans = 0;
        $slist = str_split($s);
        $tmp = [];
        $start = 0;
        while ($start < $l) {
            for ($i = $start; $i < $l; $i++) { 
                $si = $s[$i];
                if (isset($tmp[$si])) {
                    $ans = max($ans, count($tmp));
                    $start = $i + 1;
                    reset($tmp);
                    $flag = 0;
                    $newTmp = [];
                    foreach ($tmp as $tk => $tval) {
                        if ($flag > 0) {
                            $newTmp[$tk] = $tval;
                        }
                        if ($tk === $si) {
                            $flag = 1;
                        }
                    }
                    $tmp = $newTmp;
                    $tmp[$si] = $i;
                    break;
                }
                $tmp[$si] = $i;
            }
        }
        return $ans;
    }
    $s="dvdf";
    print_r([mySolution($s)]);die;
    

    1. 在一个n阶方阵(或是n阶行列式)中,从左上角到右下角这一斜线方向上的n 个元素所在的对角线,叫做n 阶方阵(或行列式)的主对角线。

    相关文章

      网友评论

          本文标题:PHP之高频考点算法合辑

          本文链接:https://www.haomeiwen.com/subject/ymuhcrtx.html