第一章 数组 part02

977. 有序数组的平方

1. 题目

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

2. 自己的思考

先数组平方,然后再使用排序算法排序。最后的时间复杂度、空间复杂度与排序算法有关。

3. 代码

class Solution {
    public int[] sortedSquares(int[] nums) {
        for (int i = 0; i < nums.length; i++) {
            nums[i] = nums[i] * nums[i];
        }
        System.out.println("1"+Arrays.toString(nums));
        // 遍历的轮数
        for (int i = 0; i < nums.length - 1; i++) {
            // 应该遍历到的最后一个元素的前一个元素
            for (int j = 0; j < nums.length -1 - i; j++) {
                if (nums[j] > nums[j+1]) {
                    int temp = nums[j+1];
                    nums[j+1] = nums[j];
                    nums[j] = temp;
                }
            }
        }
        System.out.println(Arrays.toString(nums));
        return nums;
    }
}

209. 长度最小的子数组

1. 题目

给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [nums], numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

2. 自己的思考

2.1 暴力解法

从第一个数字,开始遍历,记录 >=target 的数组的长度。每次更新最小长度。如果从当前数字一直加到最后一个数,都不满足 >= target,那么就结束遍历。如果最小长度<=arr.length,就返回最小长度;否则就返回0。

2.2 双指针法

左右两个指针,左指针开始一直向右移动,当记录 < target 时,就不再移动左指针;右指针开始一直向左移动,当记录 < target 时,就不再移动右指针。如果左右指针没有移动,并且记录 < target,就返回0,否则就返回最终的左右指针之间的长度。

3. 代码

3.1 暴力解法
public int minSubArrayLen2(int target, int[] nums) {
        // 数组长度
        int n = nums.length;
        // 最小长度
        int minLeng = Integer.MAX_VALUE;
        // 累计和
        int sum = 0;
        // 满足条件的长度
        int leng = 0;

        // 边界条件
        if (n == 0) {
            return -1;
        }
        // 遍历的趟数
        for (int j = 0; j < n; j++) {
            // 每趟从哪个数字开始
            for (int i = j; i < n; i++) {
                sum += nums[i];
                leng++;
                // 查询出了最小长度
                if (sum >= target && leng < minLeng) {
                    minLeng = leng;
                }
                // 没有最小长度
                if (leng == n && sum < target) {
                    return 0;
                }
            }
            sum = 0;
            leng = 0;
        }
        // 存在最小长度
        if (minLeng < Integer.MAX_VALUE) {
            return minLeng;
        }
        return -1;
    }
3.2 双指针法
// 双指针法
    public int minSubArrayLen3(int target, int[] nums) {
        // 最小长度
        int minLength = Integer.MAX_VALUE;
        // 子序列总和
        int sum = 0;

        for (int j = 0, i = 0; j < nums.length; j++) {
            // 计算子序列总和
            sum += nums[j];
            // 滑动窗口
            while (sum >= target) {
                // 计算最小长度
                minLength = Math.min(minLength, j - i + 1);
                // 不断的变更子序列的起始位置
                sum -= nums[i++];
            }
        }
        return minLength == Integer.MAX_VALUE ? 0 : minLength;
    }

4. 遇到的问题

4.1 双指针法
1. 什么是滑动窗口

只需要一个 for 循环
窗口里的内容是什么:满足条件的数据
如何移动起始位置:当满足 sum >= target 的时候,就可以删除起始位置的数据
如何移动结束位置:for 循环作为结束位置。通过不断的减去起始位置的数据,来保证滑动窗口中有长度最小的子数组。

59. 螺旋矩阵 II

1. 题目

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。

2. 遇到的问题

2.1 什么时候结束循环

螺旋矩阵,是一圈一圈的创建矩阵。我们只需要知道需要循环几圈。

2.2 i,j 和 startx,starty 的区别

i,j 是用来遍历矩阵的;而 startx,starty 是用来记录每圈循环矩阵的开始位置。

2.3 应该以什么样的顺序循环,每次循环多少

就是按照顺时针来进行循环的。为了使边界的判断更加统一,采用左闭右开,每个边界点都作为起始点。

2.4 每轮循环的个数不同,如何解决

设置偏移值 offset。刚开始偏移值 offset = 1,之后 offset 逐渐增大。

2.5 每轮循环的起始位置是

nums[startx][starty],y = starty,y 不断发生改变

2.6 奇数个元素,其中心位置如何确定

nums[startx][starty]

3. 代码

public class Solution {
    public static void main(String[] args) {
        Solution solution = new Solution();
        int n = 6;
        int[][] nums = solution.generateMatrix(n);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                System.out.print(nums[i][j] + "\t");
            }
            System.out.println();
        }
    }

    /**
     * 什么时候结束循环?
     * 转几圈能把矩阵填满
     *
     * @param n
     * @return
     */
    public int[][] generateMatrix(int n) {
        // 结果数组
        int[][] nums = new int[n][n];
        // 圈数
        int turns = 0;
        // 起始位置
        int startx = 0, starty = 0;
        // 循环的位置
        int i = 0, j = 0;
        // 偏移值
        int offset = 1;
        // 数值
        int count = 1;

        // 循环的圈数
        while (turns < n/2) {
            // 从左到右
            for (j = starty; j < n - offset; j++) {
                // 这里 i 应该为 startx,即 x 的起始位置
                nums[startx][j] = count++;
            }
            // 从右到下
            for (i = startx; i < n - offset; i++) {
                nums[i][j] = count++;
            }
            // 从右到左
            for (; j > starty; j--) {
                nums[i][j] = count++;
            }
            // 从下到上
            for (; i > startx; i--) {
                nums[i][j] = count++;
            }
            startx++;
            starty++;
            offset++;
            turns++;
        }

        // 如果是奇数个元素构成的矩阵,最后的中心位置需要单独处理
        if (n % 2 == 1) {
            // 最后的起始位置就是「矩阵的中心位置」
            nums[startx][starty] = count;
        }
        return nums;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员_动次动次

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值