代码随想录day02

1.有序数组的平方

题目

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

示例 1:

  • 输入:nums = [-4,-1,0,3,10]

  • 输出:[0,1,9,16,100]

  • 解释:平方后,数组变为 [16,1,0,9,100],排序后,数组变为 [0,1,9,16,100]

示例 2:

  • 输入:nums = [-7,-3,2,3,11]

  • 输出:[4,9,9,49,121]

注意点

  1. 题目给的数组是有顺序的,问题出在可能存在负数,负数平方之后可能变成最大的,就会导致数组顺序被打乱

  2. 负数平方之后可能变成最大值,但因为原来的数组有序,所以平方之后最大元素一定是在两边

    • 例如{-3,1,2,3,4}或者{-5,-3,1,2,3,4}

双指针思路

思路

  1. 定义双指针从两头向中间取,也就是将数组中的数从大到小取出来.

伪代码

int[] result//创建一个新的数组来装结果
    //定义一个索引下标
    //因为我们取数是从大到小,但是题目要求按照递增排序,所以索引从大到小更新
    k = numsize -1//numsize是原来数组的长度
    for(i=0,j=numsize-1;i<=j;){//i++和j--是不能写在循环条件里的.因为i++和j--是取决于谁取到最大值,才发生变化,而不是每次循环都发生变化
        if(num[i]*num[i]>=num[j]*num[j]){//num[i]表示原来数组中索引为i的元素
            result[k] = num[i]*num[i];//把最大值放在新数组中的最后一位上
            k--;//新数组的索引减小
            i++;//因为i取到了最大值,所以i发生变化,j不动
        }else{
            result[k] = num[j]*num[j];//把最大值放在新数组中的最后一位上
            k--;//新数组的索引减小
            j--;//因为i取到了最大值,所以i发生变化,j不动
        }
    }
return result;

JAVA解法

public static int[] arrRank(int[] nums) {
        //1.创建一个新的数组存储结果
        //不知道存储的结果用动态初始化
        int[] result = new int[nums.length];
        //2.创建双指针
        int leftIndex = 0;
        int rightIndex = nums.length - 1;
        //3.创建新的数组的索引
        int k = nums.length - 1;
        //3.遍历数组
        while (leftIndex <= rightIndex) {
            if (nums[leftIndex] * nums[leftIndex] >= nums[rightIndex] * nums[rightIndex]) {
                result[k] = nums[leftIndex] * nums[leftIndex];
                k--;
                leftIndex++;
            } else {
                result[k] = nums[rightIndex] * nums[rightIndex]
                k--;
                rightIndex--;
            }
        }
        return result;
    }

时间复杂度为O(n).

2.长度最小的数组

题目

给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的 连续 子数组,并返回其长度。如果不存在符合条件的子数组,返回 0。

示例:

  • 输入:s = 7, nums = [2,3,1,2,4,3]

  • 输出:2

  • 解释:子数组 [4,3] 是该条件下的长度最小的子数组

注意点

  1. 循环里的索引表示的是终止位置

伪代码

int i = 0;
int sum = 0;
int result = max;
for(j=0;j<=numsize;j++){
    sum = sum + num[j];
    while(sum>=s){
        subL = j - i + 1;//滑动窗口的长度
        //不断更新找出最小的
        result = min(result,subL)
            sum = sum - num[i];//起始位置移动要把第一个位置的元素减去
            i++;//起始位置移动
    }
    return result;
}

JAVA解法

public int minSubArrayLen(int target, int[] nums) {
        int startIndex = 0;
        int sum = 0;
        int result = Integer.MAX_VALUE;//拿出最大的数
        for (int endIndex = 0; endIndex < nums.length; endIndex++) {
            sum = sum + nums[endIndex];
            while (sum >= target){
                int arrLength = endIndex - startIndex + 1;
                result = Math.min(result,arrLength);
                //startIndex=0时,已经找到满足条件了最小的长度,那么就把startIndex=0上的元素减去,继续寻找满足要求的集合长度
                sum = sum - nums[startIndex];
                startIndex++;
            }
        }
        return result == Integer.MAX_VALUE ? 0 : result;
    }

3.螺旋矩阵

题目

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

示例:

输入: 3 输出: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ]

注意点

  1. 处理边界问题

思路

解本题依然是要坚持循环不变量原则。

模拟顺时针画矩阵的过程:

  • 填充上行从左到右

  • 填充右列从上到下

  • 填充下行从右到左

  • 填充左列从下到上

由外向内一圈一圈这么画下去。

这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。

JAVA代码

 public int[][] generateMatrix(int n) {
        int[][] nums = new int[n][n];
        int startX = 0, startY = 0;  // 每一圈的起始点
        int offset = 1;
        int count = 1;  // 矩阵中需要填写的数字
        int loop = 1; // 记录当前的圈数
        int i, j; // j 代表列, i 代表行;
​
        while (loop <= n / 2) {
​
            // 顶部
            // 左闭右开,所以判断循环结束时, j 不能等于 n - offset
            for (j = startY; j < n - offset; j++) {
                nums[startX][j] = count++;
            }
​
            // 右列
            // 左闭右开,所以判断循环结束时, i 不能等于 n - offset
            for (i = startX; i < n - offset; i++) {
                nums[i][j] = count++;
            }
​
            // 底部
            // 左闭右开,所以判断循环结束时, j != startY
            for (; j > startY; j--) {
                nums[i][j] = count++;
            }
​
            // 左列
            // 左闭右开,所以判断循环结束时, i != startX
            for (; i > startX; i--) {
                nums[i][j] = count++;
            }
            startX++;
            startY++;
            offset++;
            loop++;
        }
        if (n % 2 == 1) { // n 为奇数时,单独处理矩阵中心的值
            nums[startX][startY] = count;
        }
        return nums;
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值