算法记录-有序数组平方长度最小的子数组和螺旋矩阵

249 阅读3分钟

上次的博客,我们记录数组中常见的算法题目,今天我们来讨论另外三种常见的算法题型: 分别是 有序数组平方,长度最小的子数组和螺旋矩阵。

其LeetCode对应题目分别是:有序数组的平方长度最小的子数组59. 螺旋矩阵 II

有序数组的平方

这道题目的可以暴力来做,但是如果达到最优时间复杂度,可以使用双指针的方法。 定义两个指针left和right,和我们二分法的时候一样,边界条件也是类似,关键点就是二分法的条件发生了改变。if(nums[left]*nums[left]>=nums[right]*nums[right])和<这两种情况,那种条件大就把谁的值赋给result,同时result指针从大向小移动。

下面是我的代码实现并且了注释,其时间复杂度O(N),空间复杂度O(N)。

lass Solution {
    public int[] sortedSquares(int[] nums) {
        //首先要求时间复杂度O(N)应该是数组的原地移动,要求非递减顺序
        //这个可以理解为target等于所有数组元素的移动移动不再是fast元素了而是从两头进行移动也就是因为
        //从两头向中间进行移动移动
        int left=0;
        int right=nums.length-1;
        int [] result=new int[nums.length];
        int rresult=nums.length-1;
        while(left<=right){
            if(nums[left]*nums[left]>=nums[right]*nums[right]){//当左指针的数据平方大于等于右指针的数据的平方  
            result[rresult]=nums[left]*nums[left];
            left=left+1;

            }

            else{
                //当左指针的数据平方大于等于右指针的数据的平方
             result[rresult]=nums[right]*nums[right];
            right=right-1;

            }
            rresult--; //我们将数据放到result,result索引左移
        }
        return result;
    }

}

运行结果:

image.png

长度最小子数组

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

示例:

  • 输入:s = 7, nums = [2,3,1,2,4,3]
  • 输出:2
  • 解释:子数组 [4,3] 是该条件下的长度最小的子数组。

提示:

  • 1 <= target <= 10^9
  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5

这道题目如果不是暴力解法的话,需要使用滑动窗口的解法,前后两个指针进行扫描,实现最快的检索。

首先我先写一下我的暴力解法代码,时间超时。

 int sub_result;
        for(int i=0;i<nums.length;i++){
            //对每一个元素进行遍历
            sub_result=0;
            for(int j=i;j<nums.length;j++){
                //
                sub_result=+sub_result+nums[j];
                
                if(sub_result>=target){
                    if(sub_length>j-i+1){
                        sub_length=j-i+1;
                        break;
                    }

                }
            }
        }
        return sub_length==Integer.MAX_VALUE?0:sub_length;

下面是滑动窗口的代码实现

 int left=0;
        int result=0;
        int sublength=Integer.MAX_VALUE;
        for(int right=0;right<nums.length;right++){
            result+=nums[right];
            while(result>=target){
                sublength=Math.min(sublength,right-left+1);
                result=result-nums[left];
                left++;
            }
            
            
        }
          return sublength == Integer.MAX_VALUE ? 0 : sublength;

其核心点在于 result专门存储结果,当result的值大于target的时候,left指针移动移动到result的值小于target为止,这时候right指针进行移动。两者互相切换,时间复杂度O(N)空间复杂度O(1)。 这里的result>=target记住不要写错,并且是while循环,需要left指针一直左移直到result<target而非移动一次.

运行结果截图:

image.png

螺旋矩阵

给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。

示例:

输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]

这道题目是一道模拟题目,需要对边界条件有很好的把控,不要很容易写错。这里需要注意你需要确定你使用的是什么区间,一直使用下去。

//一道经典的模拟题目
        
        int loop=0;//循环次数
        int start=0;//每次的起始点
        int [][]result=new int[n][n];//结果矩阵
        int i,j;// i代表行,j代表列

        int count=1;//定义开始时候要填的值,刚开始我们从1开始执行
        while(loop++<n/2){
            for(j=start;j<n-loop;j++){ 
                result[start][j]=count++;
            }
            for(i=start;i<n-loop;i++){
            //
                result[i][j]=count++;
            }
             for(;j>=loop;j--){
                result[i][j]=count++;
            }
            
            for(;i>=loop;i--){
                result[i][j]=count++;
            }
           
        start++;

        }
        //如果n是奇数那么中间会有一个值,需要我们单独处理
        if(n%2==1){
              result[start][start]=count;
        }
      
        return result;
    }

我们着重说一下模拟的四种情况,最上面一行向右运动->//start 行不动,对于列进行移动,移动次数是n-loop次,接下来是列不同,也就是j不动,行向下移动,移动次数也是n-loop。接下来向左移动,这时候也是j运动,这时候J的运动次数不再是n-loop,而是大于等于loop。因为我们是一个螺旋。最后向上运动,同样也是大于等于loop,不过i是不断减小的。

最后一点就是如果是层数是奇数个,中间位置的数字很有可能取不到,因此我们一般直接填入。

image.png

总结

数组方面做的题目常考的面试算法题目主要是这五个种题型,LeetCode上面也有大量的变种,大家可以去刷一下题目。最后祝愿大家算法全部AK。