算法练习Day2| 209.长度最小的子数组 59. 螺旋矩阵 II

#算法练习#数组#LeetCode

今天练习的题目是leetcode 209(209. 长度最小的子数组 - 力扣(LeetCode))和59(59. 螺旋矩阵 II - 力扣(LeetCode)),依然数数组的题目,螺旋矩阵是对二位数组的处理。

 209.长度最小的子数组

这道题目有两种解法,我看到题目第一感觉暴力解法,两个循环,挨个子数组求和然后跟target做比较,但是因为粗心,这里耗费了一点时间,求和时将sum = sum + nums[j] 直接写成了下标:sum = sum + j ,时间就是金钱,难受啊。这个是第一版(粗心报错版):

public int minSubArrayLen(int target, int[] nums) {
        if(null == nums) {
           return  0;
        }
        int length = nums.length;
        int min = length + 1;
        int sum = 0;
        //violent solution
        for(int i = 0; i < length; i++) {
            sum = nums[i];
            if(sum >= target) {
                min = 1;
            }
            for(int j = i+1; j < length; j++) {
                sum = sum+j;		// 这里写错了,查了半天,看代码逻辑应该不会错呀
                if(sum >= target) {
                    min = Math.min(min, (j-i+1));
                    break;
                }
            }
        }
        return min>length ? 0:min;
    }

暴力解法最终完成代码:

public int minSubArrayLen(int target, int[] nums) {
        if(null == nums) {
           return  0;
        }
        int length = nums.length;
        int min = length + 1;
        int sum = 0;
        //violent solution
        for(int i = 0; i < length; i++) {
            sum = nums[i];
            if(sum >= target) {
                min = 1;
                break;
            }
            for(int j = i+1; j < length; j++) {
                sum = sum+nums[j];
                if(sum >= target) {
                    min = Math.min(min, (j-i+1));
                    break;
                }
            }
        }
        return min>length ? 0:min;
}

虽然暴力解法逻辑是合理的,但是时间复杂度是O(n平方),leetcode提交是超时的,过不了。也跟其他大神做了下比较,代码还是有点冗余,但是几乎没有做改动,主要是记录当时自己的想法。

另一种方法就是卡尔推荐的滑动窗口,也是一种双指针的解法,只是这个双指针的移动比较特殊和巧妙。通过双指针pre和cur,pre记录滑动窗口结束的位置,cur记录开始的位置,也就是不断搜索的位置,找到子数组的和大于target时,通过移动cur来缩小窗口,找最小的目标子数组。具体代码:

public int minSubArrayLen(int target, int[] nums) {
        if(null == nums) {
           return  0;
        }
        int length = nums.length;
    

        //two pointers or slide window algorithm
        int cur = 0;
        int sum = 0;
        int res = length + 1;
        for(int pre = 0; pre < length; pre++) {
            sum += nums[pre];
            while(sum >= target) {
                res = Math.min(res, (pre-cur +1));
                sum -= nums[cur];
                cur++;
            }
        }
        return res>length ? 0:res;
    }

59.螺旋矩阵 II

这道题开始看到题目是比较懵的,因为平时很少用到二维数组,也没有将矩阵和二位数组联系在一起,早上上班的地铁上一直在琢磨是怎么处理,突然一下就想通了,这个不就是二维数组吗,现在的目标就是如何找到对应的数组下标的值,也就是解决螺旋的问题。

首先是几次螺旋,通过观察,螺旋次数 = n/2.

每一次螺旋就是针对四条边的处理,以i和j作为数组下标,即:

i不变,j从起始位置到目标位置

j不变,i从起始位置到目标位置

i不变,j从当前位置到起始位置前一个位置(因为这里有个偏移量,也就是区间是左闭右开区间)

j不变,i从当前位置到其实为止前一个位置。

具体的代码:

public int[][] generateMatrix(int n) {
        int[][] res = new int[n][n];
        int num = 1;
        int startX = 0, startY = 0;       //螺旋的起始位置 
        int offset = 1;                   //偏移量,每一次螺旋的大是在减小的
        int loopCount = n/2;              //螺旋次数
        int i,j;                          //坐标
        while(loopCount > 0) {
            for(j = startY; j < n-offset; j++) {
                res[startX][j]= num++;
            }
            for(i = startX; i < n-offset; i++) {
                res[i][j]= num++;
            }
            for(;j > startY; j--) {
                res[i][j]= num++;
            }
            for(;i > startX; i--) {
                 res[i][j]= num++;
            }
            loopCount--;
            offset++;
            startX++;
            startY++;
        }
        if(n%2 == 1) {
            int center = n/2;          //奇数位最后一个补齐的坐标(center, center),偶数位无需 补齐
            res[center][center]= num;
        }
        return res;
    }

个人感觉想通了思路不是很难,主要是很多细节需要注意,整个debug过程还是会耗费一定的时间。

后面的练习继续加油吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值