代码随想录算法训练营第二天| 977.有序数组的平方、209.长度最小的子数组、59.螺旋矩阵II

977.有序数组的平方

链接:LeetCode977有序数组的平方

题目:给你一个按 非递减顺序 排序的整数数组 nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。

示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

示例 2:
输入:nums = [-7,-3,2,3,11]
输出:[4,9,9,49,121]

思路:

  1. 最暴力的就是将数组中的每一个元素都变成原来的平方,之后直接对数组进行排序。时间复杂度为O(nlogn)。
  2. 如果所给数组的元素全都是非负数(如果第一个元素大于等于0,那么数组中元素都是非负数),那么从头遍历数组,将数组中的每一个元素都变成原来的平方即可。如果所给数组的元素都是非正数(如果最后一个元素小于等于0,那么数组中元素都是非正数),那么倒序遍历数组,从起始位置开始加入新的数组即可。如果所给数组的元素有正有负,需要先将数组一分为二,一部分为正,一部分为负,指针1倒序遍历负的部分,指针2正序遍历正的部分,两个指针所指的元素进行比较,谁的平方小,将谁先加入新的数组。(这个操作就像是,归并排序的是的合并操作)。
  3. 通过第二个方法得到的启发:可以通过双指针来做。具体做法如下:
    指针1从头到尾遍历数组,指针2从尾到头遍历数组,谁的平方大就将谁加入新的数组(从新数组的末尾位置开始加入新元素)。
class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        vector<int>ans(nums.size(),0);
        int mv=nums.size()-1;
        int i=0,j=nums.size()-1;
        while(i<j){//i==j时,只剩下一个元素没必要和谁进行比较
            int n1 = nums[i]*nums[i];
            int n2 = nums[j]*nums[j];
            if(n1>=n2) {ans[mv--] = n1;++i;}
            else {ans[mv--] = n2;--j;}
        }  
        ans[mv] = nums[i]*nums[i];
        return ans;
    }
};

209.长度最小的子数组

题目:
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

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

示例 2:
输入:target = 4, nums = [1,4,4]
输出:1

示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

思路:

  1. 暴力解法。双循环遍历数组,外层循环表示满足条件连续子数组的起始位置,内层循环表示满足条件连续子数组的终止位置,时间按复杂度为O(n2)。
  2. 优化暴力解法。其实暴力解法时间复杂度之所以高是因为,做了很多重复计算,就像外层循环的第一次遍历和第二次遍历做了很多重复计算。为了规避这些重复计算,尝试着将双层循环降为单层循环。将元素放在一个大小不固定的数组中,元素和小于target就将其加入到窗口中,然后往后走。元素和大于等于target就将窗口起始元素从窗口中剔除。并且不断记录并比较窗口的长度。(用两个前后指针表示滑动窗口);
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int i=0,j=0;//i表示窗口的起始位置,j表示窗口的终止位置
        int sum=0;//窗口内元素和
        int minlength=nums.size()+1;//窗口长度
        for(;j<nums.size();++j){
            sum+=nums[j];
            while(sum>=target){
                minlength = min(minlength,j-i+1);
                sum-=nums[i++];
            }
        }
        //这种情况是数组中的所有元素之和小于target
        if(minlength == nums.size()+1)  return 0;
        return minlength;
    }
};

59.螺旋矩阵II

链接:LeetCode59螺旋矩阵II

题目:给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

思路:
当n为奇数时,最中间的元素手动填充。
当填充行的时候,保持行不动,只移动指向列的指针。
当填充列的时候,保持列不动,只移动指向行的指针。
采用左闭右开(如果采用左闭右闭的写法,会导致下一次填充的区间变成左开右闭。为了保持变量唯一性,故采用左闭右开的写法)的方法遍历填充数组。

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> ans(n,vector<int>(n,0));
        //n为奇数
        if(n&1) ans[n/2][n/2] = n*n;

        int num = 1;//填充的数字从0开始

        //cou记录循环的圈数
        for(int cou=0;cou<n/2;++cou){
            int row = cou,col = cou;
            
            //填充上行
            for(;col<n-cou-1;++col) ans[row][col] = num++;

            //填充右列
            for(;row<n-cou-1;++row) ans[row][col] = num++;

            //填充下行
            for(;col>cou;--col) ans[row][col] = num++;

            //填充左列
            for(;row>cou;--row) ans[row][col] = num++;
        }
        return ans;
    }
};

你可能感兴趣的:(算法与数据结构,算法,矩阵,leetcode,数据结构,c++)