代码随想录算法训练营第二天 | leetcode:有序数组的平方,长度最小的子数组 ,螺旋矩阵II

Problem: 977. 有序数组的平方

需要注意的问题

  1. 给定题目数组包含负数,负数平方为正数。需要注意平方后的排序。
  2. php解法需要初始化新数组键值位置,否则容易出现结果倒序输出的问题
    代码随想录算法训练营第一天 | leetcode 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

解题方法

观察数据趋势,平方后从两边往中间是从大到小趋势。故而可以使用左右双指针方法,依次往中间移动,比较大小后,选择大的数插入新数组,并移动同向指针移动。直到循环结束完成排序。

复杂度

时间复杂度:

O(n)

空间复杂度:

O(n)

左闭右闭写法

function sortedSquares($nums) {
        if(count($nums) <= 0){
            return false;
        }
        $newArr = [];
        $newIndex = count($nums)-1;

        //需要初始化数组索引位置,不然输出结果为倒叙
        for ($i = 0; $i < $newIndex; $i++) {
            $newArr[$i] = 0;
        }

        $left = 0;
        $right = count($nums)-1;
        //双指针相向而行
        while($left <= $right){
            $leftDub = pow($nums[$left] , 2);
            $rightDub = pow($nums[$right] , 2);
            //如果左边比右边大 则把左边的值移入新数组 $newIndex-- $left++;
            if($leftDub > $rightDub){
                $newArr[$newIndex--] = $leftDub;
                $left++;
            }else{
                //如果右边比左边大 则把右边的值移入新数组 $newIndex-- $right++;
                $newArr[$newIndex--] = $rightDub;
                $right--;
            }

        }
        return $newArr;
    }

Problem: 209. 长度最小的子数组

需要注意的问题

  1. 需要考虑兼容数组所有数总和小于目标数的情况。如:target = 11。nums = [1,1,1,1,1,1,1,1];可以设置一个最大int常量数:PHP_INT_MAX,减少计算。
  2. 什么是滑动窗口:滑动窗口是双指针的一种特例,可以称为左右指针,在任意时刻,只有一个指针运动,而另一个保持静止。
  3. 需要考虑滑动窗口移动方式。如果用一个for循环,那么遍历指针应该表示滑动窗口的起始位置,还是终止位置。

解题方法

  1. 滑动窗口for循环遍历指针应该是对应滑动窗口的终止位置。
  2. 从0开始移动快指针寻找第一个大于target的目标区间,达到区间时(快指针不动),移动慢指针往快指针方向移动,寻找符合条件的更小区间。当慢指针移动时出现不满足大于target区间时,快指针继续移动,重复动作,更新最小区间值。直到遍历完成。

复杂度

时间复杂度:

O(n)

空间复杂度:

O(1)

Code

function minSubArrayLen($target, $nums) {
        if (count($nums) <= 0) {
            return 0;
        }
        $slow = 0;
        $min = PHP_INT_MAX;//要用大于数组长度的值
        //快指针先找到第一组比target大的数组长度
           for($fast = 0; $fast <= count($nums)-1; $fast++){
            //计算快指针移动区间总和
            $sum += $nums[$fast];
            //找到之后移动慢指针逐渐缩小区间找到最小长度
            while($sum >= $target){
                //区间长度包含首尾是闭区间,需要+1
                $len = $fast - $slow + 1;
                $min = min($min,$len);
                //注意更新sum值:慢指针往快指针移动一步,区间减小,sum需要减去区间外的值
                $sum -= $nums[$slow];
                $slow++;
            }
        }
        //适配数组内没有符合长度的情况
        return $min == PHP_INT_MAX ? 0 : $min;
    }

Problem: 59. 螺旋矩阵 II

需要注意的问题

  1. 循环矩阵四条边时,需要遵循统一的,循环不变量规则。即上期二分法中,左闭右闭与左闭右开。
  2. 一定一定要画一个矩阵的数组下标图,非常有助于理解循环过程的边界。
  3. 圈数为单数时,需要单独处理中心点。

解题方法

模拟顺时针画矩阵的过程,每一条边都要坚持一致的左闭右开:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上
    这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。
    代码随想录算法训练营第二天 | 977.有序数组的平方,209.长度最小的子数组 ,59.螺旋矩阵II

复杂度

时间复杂度:

O(n^2)

空间复杂度:

O(1)

关于为啥空间复杂度是O(1)。关于空间复杂度的定义(摘自百度百科):空间复杂度(Space Complexity)是对一个算法在运行过程中临时占用存储空间大小的量度,记做S(n)=O(f(n))。
题目需要我们输出一个n x n的矩阵数组,所以,这里不算临时占用的空间。而解法中没有其余跟n成线性关系的空间开辟,所以空间复杂度为O(1);

Code

function generateMatrix($n) {
        //使用循环不变量,左闭右开原则
        $startX = 0;//起始X
        $startY = 0;//起始Y
        $res = [];//结果集
        $count = 1;//计数
        $offset = 1;//边界偏移量
        $round = floor($n/2);//循环圈数
        //初始化数组默认值
        for($k = 0; $k < $n; $k++){
            for($v = 0;$v < $n; $v++){
                $res[$k][$v] = null;
            }
        }

        while($round > 0){
            //上边 (0,0) (0,1)
            for($j = $startY; $j < ($n - $offset); $j++){
                $res[$startX][$j] = $count++;
            }
            //右边 (0,2) (1,2)
             for($i = $startX; $i < ($n - $offset); $i++){
                $res[$i][$j] = $count++;
            }
            //下边  (2,2) (2,1)
            for(; $j > $startY; $j--){
                $res[$i][$j] = $count++;
            }
            //左边 (2,0) (1,0)
            for(; $i > $startX; $i--){
                $res[$i][$j] = $count++;
            }
            //X,Y +1改变起始位置,进入内圈
            $startX++;
            $startY++;
            //内圈循环偏移量需要+1
            $offset++;
            //圈数--
            $round--;
        };
        //处理单圈数中点
        if($n%2 == 1){
            $res[$startX][$startY] = $count;
        }
        return $res;
    }
本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!