算法训练Day02 数组

文章介绍了如何使用双指针法和滑动窗口思想处理两个与数组相关的问题:有序数组的平方按非递减顺序排序,以及找到满足和大于等于目标值的最小连续子数组的长度。解决方案包括暴力解法和高效算法实现。
摘要由CSDN通过智能技术生成

977.有序数组的平方

给你一个按 非递减顺序 排序的整数数组 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]

暴力解法(略

先把每个元素都平方一遍,在排个序

双指针法

题目说的时每个元素的平方,则表明最大值肯定在这个数组的两端之一

两个指针分别在首和尾,每次判断两个谁大,再依次赋值给新的数组

注:一个指针指向过的元素赋值过后,指针下一步要指向中间的元素

class Solution {
    public int[] sortedSquares(int[] nums) {
            int right = nums.length - 1;
        int left = 0;
        int[] result = new int[nums.length];
        int index = result.length - 1;
        while (left <= right) {
            if (nums[left] * nums[left] > nums[right] * nums[right]) {
                // 正数的相对位置是不变的, 需要调整的是负数平方后的相对位置
                result[index--] = nums[left] * nums[left];
                left++;
            } else {
                result[index--] = nums[right] * nums[right];
                right--;
            }
        }
        return result;
    }
}

209.长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

暴力解法(超时

双重循环,遍历每个元素时,以这个元素为首进入第二重循环累加达到target值

一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置

计算出每个子序列的长度,用if来判断最短的子序列长度

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int result = nums.length +1; //结果
         for(int i=0;i<nums.length;i++){
             int sum=0;  //子序列的和
             for(int j = i; j<nums.length;j++){
                 sum += nums[j];
                 if (sum >= target){//当sum累加到符合值时
                     int sublength = j-i +1;
                        if ( sublength<result ){
                            result = sublength; //进一步判断是否为最短
                        }
                 }
             }
         }
         return result == nums.length+1 ? 0:result;
    }
}

滑动窗口

双指针思想

  • 在每次加入元素后,检查当前子数组的元素和是否大于等于 target
    • 如果满足条件,执行以下操作:
      • 更新 result,将其更新为当前子数组的长度与 result 的较小值
      • 移动左指针 left 向右,将当前子数组的最左侧元素移除,并更新 sum(精髓)
      • sum -= nums[left++];
  • 如果不满足条件,则继续向右移动右指针 right

class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int sum = 0;
        int result = nums.length+1;
        for (int right = 0; right < nums.length; right++) {
            sum += nums[right];
            while (sum >= target) {
                result = Math.min(result, right - left + 1);
                sum -= nums[left++];
            }
        }
        return result == nums.length +1 ? 0 : result;
    }
}

59.螺旋矩阵II

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

示例 1:

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

示例 2:

输入:n = 1
输出:[[1]]

解法

涉及算法不深,题中给出矩阵

可以把该矩阵拆分一圈一圈,因此将一圈作为一次循环,循环的次数为n/2(一圈中最左和最右占两个,因此把n看成有几个2之和,就是几次循环--配合图形理解)

由(startx,starty)为作为一圈的起点,循环一次都改变起点位置

注意①理解差量的意义②n为奇数时,最里的不可看做圈,是一个元素,此时需要额外去赋值

class Solution {
    public int[][] generateMatrix(int n) {
        int startx = 0 , starty= 0;   // 每次循环的起点
        int loop = 0;   //循环次数
        int offset = 1;    //实现左闭右开的差量
        int count = 1;    //填充数组元素
        int [][] result = new int[n][n];
        int i = 0,j = 0;

        while(loop++ < n/2){
            for (j = startx ; j < n - offset; j++) {
                result[startx][j]= count++;  //每次循环的首行
            }

            for (i = starty; i < n-offset; i++) {
                result[i][j] = count++;  // 尾列
            }
            for (; offset - 1 < j; j--) {
                result[i][j] = count++;  // 尾行
            }
            for (; offset - 1 <i; i--) {
                result[i][j]  = count++; //首列
            }
            offset ++;
            startx++;
            starty++;

        }
        if (n%2 == 1){
            result[n/2][n/2] = count;
        }
        return result;
    }
}

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值