代码随想录训练营day2,有序数组平方,长度最小的子数组,螺旋矩阵

第二天开始上难度了,坚持就完事了

有序数组平方:
思路:

暴力解法:全部平方之后,再快排,这一块由于我基础比较薄弱,时间复杂度为O(nLogn),所以暂时不是很理解, 自己之后看完韩顺平之后再回过头来分析:

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


双指针:这是今天的主角,再次用到双指针的思想,不过是一个在左,一个在右,由于是有序的,所以最大值肯定在数组的最左或者最右,也就是指针的位置left和right,对指针定义后,判断,如果左边的平方,大于右边的平方,那么就把左边的平方赋值到新数组的最右边;否则,如果右边的平方大,或者等于,就把右边的覆给新数组,接下来是自己写的时候出现的问题和注意点:
1. 要明确解题要什么东西,一个left指针,一个right指针,一个空数组,和一个数组的index从右边开始num.len-1

2. 记住left就是0, 但是right是num.length-1 (因为是从0开始的)

3.while判断条件注意是 left <= right, 这可以保证两个元素相等时也被处理了

4.给数组赋值,所以是result [k] = 平方和

7.写一个条件else就行了,因为等于时left,right都可

5.同时k--,保证新数组向左移动

6.如果过是左边大,那就left++,向右移动,反则right--

class Solution {
    public int[] sortedSquares(int[] num) {
        int [] result = new int[num.length];
        int k = num.length - 1;
        int left = 0;
        int right = num.length - 1;
        while (left <= right){
            if(num[left]*num[left] > num[right]*num[right]){
                result[k] = num[left]*num[left];
                k--;
                left++;
            } else {     //这里直接else就行了,因为等于时,left和right都可以
                result[k] = num[right]*num[right];
                k--;
                right--;          

            }
        }
        return result;
    }
}

==================================================================================================================================================

长度最小的子数组

这道题开始上难度了,来了一道medium难度的,题目看了很久才懂什么意思,rm写了好几遍才对(太折磨了......),也有暴力算法,用两个for循环,更好的使用滑动窗口的方法,该方法用一个循环就可以发挥两个循环的作用.

滑动窗口

思路和注意事项:

1. 明确需要什么,left起始指针,right终止指针, 一个result定义集合长度,需要取最大值

2.首先用for循环让尾指针开始遍历,然后需要 a.头尾之前集合的大小sum; b.符合target的集合长度

3.接下来判断, 前面算的sum是否大于等于target,如果是就滑动窗口, 严格遵守步骤:

        a. 首先算出现在的target长度 subL = right - left +1;

        b.更新sum = sum - nums[left] (之前已定义sum的右边间不断向右,这里修改左边界即可)

        c.前面收集了所有的subL, 这里利用Math.min来不断更新最小的subL, 也就是我们要的长度

        d.如果大于target, left起始指针也会继续向右更新,看新的窗口是否符合要求

4.记得最后return的时候要加个三元,防止一开始的target不在范围内
(right指针和之前的remove element一样会不停向右, left指针是只有大于等于target才会向右动,保证窗口的滑动, 继续寻找长度subL, 遍历完之后, 利用min来判断哪个长度最小)

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
       int left = 0;      //定义左起始指针
       int sum = 0;       //定义集合间的sum
       int result = Integer.MAX_VALUE;  //定义窗口长度,取最大值
       for(int right = 0; right < nums.length; right++){
           sum += nums[right];
           while(sum >= target) {       
               int subL = right - left + 1; 
               //要-1因为len是子数组的长度,不是间隔长度
               sum = sum - nums[left];
               result = Math.min(result, subL);
               left++;          
           }
       }
    return result==Integer.MAX_VALUE? 0 : result;
    }
}

==================================================================================================================================================

螺旋矩阵II

这道题也比较复杂, 虽然没有涉及太多的算法,但是对细节,边界的把握十分重要, 这里也和二分法的左闭右开有异曲同工之妙, 对四个边的细节调整非常重要. 我这里并没有完全按照carl的思路来进行,但总体来说是相同的

思路:

创建一个二维数组,利用左闭右开, 四个边界,然后往里面填充数字

操作细节:

1.想清楚需要什么,一个空的二维数组,左右上下四个border, 一个开始值start, 一个结束值end

2.首先建立一个while循环,条件是start<=end.

3.然后利用左右上下的border来对四条边的数值进行填充, 注意,由于使用左闭右开, bottom和right应该赋值为n-1

4.上边: 条件就是 i<=right, 然后mat[t][i] = start++, 因为纵坐标不变,横坐标随改变

5.右边:条件是i<=bottom, 这里是横坐标不变,纵坐标随着i改变

6.下边:是反方向移动,条件是i>=left, mat[b][i], 改变边界就是b--
7. 就是在for循环里,每个边填满数字,填满后将边界缩小.

(还是会忘记创建对象 int XXX = ......)

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] mat = new int[n][n];
        int l = 0, t = 0, r = n - 1, b = n - 1;
        int start = 1;
        int end = n*n;
        while(start <= end){
            for(int i = l; i <= r ; i++ ) //最上面的边
                mat[t][i] = start++;     //for不加括号就执行后面一句
                t++;
            for(int i = t; i <= b ; i++)  //右边
                mat[i][r] = start++;
                r--;
            for(int i = r; i >= l; i-- )  //下边
                mat[b][i] = start++;
                b--;
            for(int i = b; i >= t; i--)   //左边
                mat[i][l] = start++;
                l++;
        }
        return mat;
    }
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值