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

LeetCode977. 有序数组的平方

题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/

思路:看到题目的第一想法是使用暴力法:数组里的每个元素都平方一下,再排个序。

C++代码如下:

class Solution 
{
public:
    vector<int> sortedSquares(vector<int>& nums) 
    {
        for(int i = 0; i < nums.size(); i++)
        {
            nums[i] = nums[i]*nums[i];
        }
        sort(nums.begin(), nums.end());
        return nums;
    }
};

思考:可以使用双指针法。题目说了数组是有序的,那么该数组平方的最大值就在数组的两端,要么最左边,要么最右边,不可能在中间。

考虑用双指针法,i指向原数组起始位置,j指向原数组终止位置。

再定义一个新的数组,用于存放最终结果,和原数组一样的大小。

如果A[i]*A[i] ≤ A[j]*A[j],那么result[k] = A[j]*A[j],k- -,j- -;

如果A[i]*A[i] > A[j]*A[j],那么result[k] = A[i]*A[i],k- -,i++;

C++代码如下:

class Solution 
{
public:
    vector<int> sortedSquares(vector<int>& nums) 
    {
        vector<int> A(nums.size(), 0);  //最后的结果存放在这个新数组中
        int i = 0;
        int j = nums.size() - 1;
        int len = nums.size() - 1;

        while(i < j)
        {
            if((nums[i]*nums[i]) <= (nums[j]*nums[j]))
            {
                A[len] = nums[j]*nums[j];
                len--;
                j--;
            }
            else if((nums[i] * nums[i]) > (nums[j] * nums[j]))
            {
                A[len] = nums[i]* nums[i];
                len--;
                i++;
            }
        }
        A[0] = nums[i] * nums[i];
        return A;
    }
};

LeetCode209. 长度最小的子数组

题目链接:https://leetcode.cn/problems/minimum-size-subarray-sum/

思路:暴力法,用两层for循环,不断寻找符合条件的子序列,再找出长度最短的子序列。时间复杂度:O(n^2)。

C++代码如下:

class Solution 
{
public:
    int minSubArrayLen(int target, vector<int>& nums) 
    {
        int result = INT32_MAX;  //最终的结果
        int sum = 0;   //子序列的数值之和
        int subLength = 0; //子序列的长度

        for(int i = 0; i < nums.size(); i++)  //设置子序列起点为i
        {
            sum = 0;
            for(int j = i; j < nums.size(); j++)   //设置子序列终点位置为j
            {
                sum += nums[j];
                if(sum >= target)   //若子序列之和超过target,更新result
                {
                    subLength = j - i + 1;  //子序列长度
                    result = result < subLength ? result : subLength;
                    break;   //因为找的是符合条件的最短的子序列,所以符合条件后子序列没必要继续累加了。所以弹出该循环去更新子序列的起点找新的符合条件的子序列。
                }
            }

        }
        return result == INT32_MAX ? 0 : result;
    }
};

思考:

使用滑动窗口,其实我把它也理解成是双指针法(快慢指针法)

在上面的暴力法中,是一个for循环为滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环完成了一个不断搜索区间的过程。

我用双指针法在一个for循环下完成两个for循环的工作。

定义快慢指针

  • 快指针:指向子序列的终点位置

  • 慢指针:指向子序列的起始位置

每次fastIndex移动时,都会把子序列的数值累加起来与target比较,若小于target,则进入下一个循环,fastIndex继续移动,寻找符合条件的子序列;

当子序列的数值累加后大于等于target,即符合条件,计算当前子序列的长度,并与result比较,把较小的更新为最新的result。更新result之后子序列数值之和还要减去slowIndex指向的数值,并向前移动slowIndex,因为我们要寻找符合条件的最短的子序列:1.如果不移动slowIndex而是继续移动fastIndex,就没必要了,因为后面的子序列肯定比当前的要长;2.同时,有可能减去当前slowIndex指向的数值后的子序列仍旧符合条件,所以,在找到符合条件的子序列后要移动slowIndex,更新子序列再继续判断是否符合条件。

C++代码如下:

class Solution 
{
public:
    int minSubArrayLen(int target, vector<int>& nums) 
    {
        int sum = 0;  //子序列元素之和
        int slowIndex = 0;
        int fastIndex = 0; 
        int subLength = 0;   //子序列长度
        int result = INT32_MAX;

        for(fastIndex = 0; fastIndex < nums.size(); fastIndex++)
        {
            sum += nums[fastIndex];
            while(sum >= target)
            {
                subLength = fastIndex - slowIndex + 1;
                result = result < subLength ? result : subLength;
                sum -= nums[slowIndex];
                slowIndex++;
            }
            if((fastIndex==nums.size()-1)&&(slowIndex==0)&&(sum < target))   //如果整个数组都加起来也小于target,则直接返回0。
            {
                result = 0;
            }
        }
        return result;
    }
};

LeetCode59. 螺旋矩阵II

题目链接:https://leetcode.cn/problems/spiral-matrix-ii/

思路:一开始的想法是把n=1~5全部列出来,再找规律,但是后来没有写出来。现做法就是模拟过程,一步一步写出来。

模拟顺时针画矩阵的过程:

  • 填充上行从左到右

  • 填充右列从上到下

  • 填充下行从右到左

  • 填充左列从下到上

由外向内一圈圈画下去。

代码中画的每一条边,都按照左闭右开的原则:

这里每一种颜色,代表一条边,可以看到每一个拐角处的处理规则,拐角处让给新的一条边来继续画,此处都是按照左闭右开的原则。

C++代码如下:

class Solution 
{
public:
    vector<vector<int>> generateMatrix(int n) 
    {
        vector<vector<int>> res(n, vector<int>(n, 0));   //使用vector定义一个二维数组,vector<int>(n, 0)指初始化一个vector<int>类型数组,容量为n,初始值为0
        int startx = 0, starty = 0;  //定义每循环一个圈的起始位置
        int loop = n / 2;  //每个圈循环几次,例如n为奇数3,那么loop = 1只是循环一圈,矩阵中间的值需要单独处理
        int mid = n / 2;   //矩阵中间的位置,例如:n为3,中间的位置就是(1,1), n为5,中间的位置就是(2,2)
        int count = 1;     //用来给矩阵中每一个空格赋值
        int offset = 1;    //需要控制每一条边遍历的长度,每次循环右边界收缩一位
        int i, j;

        while(loop--)
        {
            i = startx;
            j = starty;

            //下面开始的四个for就是模拟转了一圈
            //模拟填充上行从左到右(左闭右开)
            for(j = starty; j < n - offset; j++)
            {
                res[startx][j] = count;
                count++;
            }
            //模拟填充右列从上到下(左闭右开)
            for(i = startx; i < n - offset; i++)
            {
                res[i][j] = count;
                count++;
            }
            //模拟填充下行从右到左(左闭右开)
            for(; j > starty; j--)
            {
                res[i][j] = count;
                count++;
            }
            //模拟填充左列从下到上(左闭右开)
            for(; i > startx; i--)
            {
                res[i][j] = count;
                count++;
            }

            //第二圈开始的时候,起始位置要各自加1,例如:第一圈起始位置是(0,0),第二圈起始位置是(1,1)
            startx++;
            starty++;

            //offset 控制每一圈里每一条边遍历的长度
            offset += 1;
        }
        //如果n为奇数,需要单独给矩阵最中间的位置赋值
        if(n % 2)
        {
            res[mid][mid] = count;
        }
        return res;
    }
};

今日总结:螺旋矩阵不熟,要多练习。长度最小的子数组这题,倒是想到了用双指针法,后续可再回顾。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组平方",和Leetcode 209 "长度最小数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小数组
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值