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

力扣题目链接:977.有序数组的平方

看到题目,第一眼想到的就是暴力解法,直接先求数组的平方,然后进行排序。

暴力解法代码:

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;
        
        }
};

这题用双指针法非常奇妙,我们可以看到题目中给出的数组是有序数组(非单调递减数组),这就说明,我们要返回的数组中最大的数一定在最左边和最右边。所以我们只需要每次比较左右两端元素的平方值,就可以知道最大值。具体操作如下,我们可以创建一个新的数组result,数组大小和我们要处理的数组一样。然后可以创建三个指针,其中一个指针k用来控制新创建的数组result,用来给result赋值,其指向result的最后一个元素,每经过一次比较,result往前走一位,直到给result赋值完毕。另外两个指针用来比较要处理的数组nums,其中一个为左指针left和右指针right,通过比较左右指针所指元素的平方值可以得出最大值,将最大值通过k指针放入result的最后一位,如果左指针所指元素大则将左指针向后移动,右指针所指元素大则将右指针向前移动。具体代码如下:

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
            vector<int> result(nums.size());
            int k = nums.size()-1;
            int left = 0;
            int right = nums.size()-1;
            while(left<=right)
            {
                if(nums[left]*nums[left]<nums[right]*nums[right])
                {
                    result[k] =nums[right]*nums[right];
                    k--;
                    right--;
                }
                else
                {
                    result[k]=nums[left]*nums[left];
                    k--;
                    left++;
                }
            
            }
               
            return result;
        
        }
};

冒泡排序中for循环的含义:

第一个for循环控制要比较次数的次数,第一次比较为N-1次,第二次比较为N-2次,第二个for循环控制比较次数。

for(int i =0;i<N-1;i++)
{
    for(int j=0;j<N-1-i;j++)
    {
        if(nums[j]>nums[j+1];
        {

        int temp = nums[j];
        nums[j] = nums[j+1]
        nums[j+1] = temp;
        }
    }
}

力扣题目链接:209. 长度最小的子数组

一眼暴力解法。但是暴力解法也有许多需要注意的地方。因为题目要求是寻找长度最小得连续子数组,所以你需要将所有符合条件的子数组穷举出来,然后比较长度,最后输出最小的值。

具体解法如下:首先得定义一个需要输出得结果result,用来保存最后的输出。然后定义一个计算数组长度的值len,用来保存符合条件的数组的长度,还需定义一个sum用来求数组和,用作判断条件。

两层循环:外层循环范围为(0,nums.size()),这个没什么好说的,就是控制数组中的数一个一个后移。内存循环有一点说法,它的范围是(i,nums.size()),而不是(0,nums.size()),可以想想为啥不是从0开始,因为从0开始的话其实一直在重复第一次循环的操作,从而无法找出穷举出所有的子数组。

然后是判断条件,当sum>=target的时候,我们需要记录数组的长度也就是len=j-i+1。然后去不断更新result的长度,我们可以将result定义为最大值,然后去和数组长度比较,如果小于数组长度就令result=len,从而达到不断更新result。最后直接break跳出内层循环。

暴力解法代码如下:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) 
    {
        int len =0;
        int result = INT32_MAX;
        for(int i = 0;i<nums.size();i++)
        {
            int sum = 0;
            for(int j =i;j<nums.size();j++)
            {
                sum = sum+nums[j];
                if(sum >= target)
                {
                    len = j-i+1;
                    result = result<len? result:len;
                    break;
                }

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

神奇的滑动窗口法:滑动窗口法其实也是双指针法的一种,上面的暴力解法需要两个for循环把所有结果穷举出来,时间复杂度非常大。

其原理为:设置两个指针指向第一个元素,其中一个先往前移动,后一个先不动。后一个在达到判断条件的时候再动。即在sum>=target的时候,这个时候我们还是会和暴力解法做一样的操作,就是记录子数组的长度,然后将他与result比较,与暴力解法不同的是,我们因为前面还预设了一个指针,我们可以通过往前移动指针,然后用sum-nums[i]来移动窗口,这样做就避免了将所有的子数组全部找出来。讲不清楚,画了个图大概就是这么个意思

滑动窗口法代码如下:

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) 
    {
        int result = INT32_MAX;
        int i = 0;
        int sum = 0;
        for(int j = 0;j<nums.size();j++)
        {
            
            sum = sum+nums[j];
            while(sum>=target)
            {
                int len = j-i+1;
                result = result<len? result:len;
                sum = sum - nums[i];
                i++;

            }

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

力扣题目链接:59. 螺旋矩阵 II

这题挺难的,对新手非常不友好。

做这题,我们要先明确,n×n数组要转多少圈,我们可以统一是n/2圈不管是奇数还是偶数,区别在于奇数转了n/2圈后会留下一个中心点,中心点的数组下标为(n/2,n/2),如果n为奇数我们可以将其单独赋值为n*n。

所谓转圈,其实就是通过四个方向给数组赋值,可以通过四个循环来实现,但是其需要注意的是,循环的边界问题。为了不使四个循环发生边界冲突,我们可以统一标准都为,左闭右开。

具体的循环操作,我们可以定义两个索引值来作为起点,也就是一个横轴x=0和一个纵轴y=0,由此可见第一圈的循环的的范围为[x,n-1),[y,n-1),[n-1,x),[n-1,y)。每次经过一圈,x++,y++。我们还可以定义一个变量index=1来控制圈数的大小。具体过程如下图:

代码如下:

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0));
        int loop = n/2;
        int mid = n/2;
        int x = 0;
        int y = 0;
        int index = 1;
        int count = 1;
        while(loop--)//转圈次数
        {
            int i = x;
            int j = y;
            for(j;j<n-index;j++)
            {
                //赋值
                res[x][j]=count++;
            }
            for(i;i<n-index;i++)
            {
                res[i][j]=count++;
            }
            for(j;j>y;j--)
            {
                res[i][j]=count++;
            }
            for(i;i>x;i--)
            {
                res[i][j]=count++;
            }
            x++;
            y++;
            index=index+1;
        }
        if(n%2)
        {
            res[mid][mid]=n*n;
        }
        return res;

    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值