代码随想录算法训练营第2天 | 数组part2_977. 209. 59.

第2天,今天数组加强,加油
—————————————
文章讲解: 代码随想录

因为是平方,所以最大元素在数组两端都有可能出现,利用双指针从两边寻找最大元素开始,到i=j停止

时间复杂度O(n),比暴力解法用快排sort(A.begin() ,B.end()) 的O(n+nlogn)好不少

注意巩固vector容器的基础

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        //定义一个的储存排序后元素的新数组
        //注意vector动态数组初始化,vector<数组类型> 数组名 (数组大小,值);
        //如vector<int> A (100,0) 即设置大小为100且所有数为0的整型动态数组A
        vector<int> result(nums.size(),0);
        //因为新数组是从找最大元素开始,所以新数组的下标从最大开始向前移动,这里初始化
        int k = nums.size()-1;
        //双指针开始遍历,i从左往右由小到j,j从右往左由大到i
        for (int i=0,j=nums.size()-1;i<=j;)
        {
            if(nums[i]*nums[i]>nums[j]*nums[j])
            {
                result[k--]=nums[i]*nums[i];
                i++;   //i由小到j
            }
            else
            {
                result[k--]=nums[j]*nums[j];
                j--;   //j由大到i
            }
        }
        return result;
    }
};

LeetCode 209.长度最小的子数组
文章讲解:代码随想录

for*for 暴力解法,即利用 i 轮遍历计算每种达到target的组合方式nums[j]+nums[j+1]...中,哪种组合最短,时间复杂度O(n^2)

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        //考虑到极限的结果是需要无限多个数的和才能大于等于target,所以初始化result为最大int
        int result = INT32_MAX;
        //初始化指针,和
        int i=0 ,sum=0, sublength=0;
        //遍历开始
        for (i=0;i<nums.size();i++)
        {
            sum = 0;
            for (int j=i, j<nums.size();j++)
            {
                sum+=nums[j];
                if (sum >= target) { // 发现sum>=target,更新result
                    sublength = j - i + 1; // 取子序列的长度
                    result = result < subLength ? result : subLength;
                    break; // 找符合条件最短的子序列,所以一旦符合条件就break
                }
             }
        }
        //判断result是否较于赋值的INT32_MAX有变化
        return result == INT32_MAX?0:result; 
    }
};

双指针滑动窗口解法

思想:用i和j双指针组成类似“窗口”一样的区间,用尽可能小的窗口去切割出区间sum为target,最后返回最小区间长度

多多注意数组长度为下标长度+1

注意执行取result,再滑动i去缩小窗口

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        //考虑到极限的结果是需要无限多个数的和才能大于等于target,所以初始化result为最大int
        int result = INT32_MAX;
        //初始化
        int i=0 ,j=0 ,sum=0, sublength=0;
        //遍历开始
        for (j=0;j<nums.size();j++)
        {
            //j开始向右滑动收集元素
            sum+=nums[j];
            //如果sum>=target了,就开始右移i指针,缩小窗口范围,以尽可能少元素(短数组)sum成target
            while(sum>=target)
            {
                sublength = j-i+1;
                //不断刷新保留最少元素(最短数组)的结果,即用尽可能小的窗口去切割出target
                result = min(result,sublength);
                sum=sum-nums[i]; 
                i++;
            }    
        }
        //判断result是否较于赋值的INT32_MAX有变化
        return result == INT32_MAX?0:result; 
    }
};

LeetCode 59.螺旋矩阵II

文章讲解:代码随想录

方法一:画完一圈缩边界

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n, vector<int>(n, 0));
        int offset=1;
        int startx;
        int starty;
        int val=1;
        int loop = n/2;
        int mid = n/2;
 
        while(loop--)
        {
            int i=startx;
            int j=starty;

        //从左上往右上
        for(j;j<n-offset;j++){
            res[i][j]=val++;
        }

        //从右上到右下
        for(i;i<n-offset;i++){
            res[i][j]=val++;
        }

        //从右下到左下,这里是++后的j
        for(;j>starty;j--){
            res[i][j]=val++;
        }

        //从左下到左上,这里是++后的i
        for(;i>startx;i--){
            res[i][j]=val++;
        }
            startx++; //下一圈,起始坐标各加一
            starty++;
            // offset 控制每一圈里每一条边遍历的长度
            offset++;
        }

        // 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
        if (n % 2) {
            res[mid][mid] = val;
        }
        return res;
    }
};

方法二:扫描线,画一边缩一次边界

class Solution {
public:
    vector<vector<int>> generateMatrix(int n) {
        vector<vector<int>> res(n,vector<int>(n,0));
        int num =1, matrix = n*n; //确认元素区间[num,n*n]
        //初始化四面边界
        int top = 0;  
        int bot = n-1;
        int left = 0;
        int right = n-1;

        while(num<=matrix)
        {
            //矩阵中我们习惯:[行][列]
            //固定top,用left当扫描线向right扫描并逐个填入[列]
            for (int i = left; i <= right; i++) res[top][i]=num++;
            //上界下缩
            top++; 

            //固定right,用top当扫描线向bot扫描并逐个填入[行]
            for (int i = top; i <= bot; i++) res[i][right]=num++;
            //右界左缩
            right--;
                
            //固定bot,用right当扫描线向left扫描并逐个填入[列]
            for (int i = right; i >= left; i--) res[bot][i]=num++;
            //下界上缩                 
            bot--;

            //固定left,用bot当扫描线向top扫描并逐个填入[行]
            for (int i = bot; i>=top; i--) res[i][left]=num++; 
            //左界右缩
            left++;
        }
        return res;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值