代码随想录算法训练营第二天 | 977.有序数组的平方 ,209.长度最小的子数组 ,59.螺旋矩阵II

 977.有序数组的平方

题目链接:. - 力扣(LeetCode)

题目描述

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

思路分析

一、暴力解法

  1. 先创建一个与 传进来的nums数组长度 一样的新数组arr
  2. 通过一层for循环去遍历nums数组,定义一个变量number,根据nums数组的下标拿到相对应的元素 赋值给变量number(其实也可以不用,就是定义变量能更加简洁,不容易搞错,因为有两个数组)
  3. 将变量number平方赋值给新数组的对应下标的元素
  4. 退出循环,将新数组arr的元素进行排列(Java的util包中有一个类->Arrays类)
  5. 最后返回排列好的新数组arr

二、双指针法

  1. 首先定义两个指针 left 和 right,分别代表 数组的起始位置 和 数组的最后位置
  2. 定义一个新的数组来存放元素,新数组长度 与 传进来的数组 的长度要保持一致,之后定义一个指向新数组下标的变量index,把这个变量放到新数组的最后位置(之后的while循环中,通过  传进来的数组 中 两个指针指向的值 比较大小,大的值就放在后面->即从右往左填充数据)
  3. while循环,条件是左闭右闭 left <= right
  4. 通过if判断语句,如果right指针指向的值比left指针指向的值大,则赋值给新数组中index位置,right指针需要往前移动->right--,index变量也需要往前移动index--(容易忘记)
  5. 如果 left 指针指向的值比 right 指针指向的值大,则赋值给新数组中index位置,left 指针需要往前移动-> left++,index变量也需要往前移动index--(容易忘记)
  6. 最后返回arr数组

代码实现(Java) 

//暴力解法
class Solution {
    public int[] sortedSquares(int[] nums) {
        int[] arr = new int[nums.length];
        for(int i = 0;i < nums.length;i++){
            int number = nums[i];
            arr[i] = number * number;
       }
       Arrays.sort(arr);
       return arr;
    }
}
//双指针法
class Solution {
    public int[] sortedSquares(int[] nums) {
        int left = 0;
        int right = nums.length - 1;
        int[] arr = new int[nums.length];
        int index = arr.length - 1;
        while(left <= right){
            if(nums[right] * nums[right] > nums[left] * nums[left]){
                arr[index] = nums[right] * nums[right];
                right--;
                index--;
            }else{
                arr[index] = nums[left] * nums[left];
                left++;
                index--;
            }
        }
        return arr;
    }
}

209.长度最小的子数组 

题目链接:. - 力扣(LeetCode)

题目描述

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

找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组

 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

思路分析

一、暴力解法

  1. 两个for循环,然后不断的寻找符合条件的子序列
  2. 时间复杂度是O(n^2)

二、滑动窗口

  1. 先定义一个指向数组起始位置的变量 left 和 滑动窗口的总和 sum
  2. 初始化 result 变量为 Integer.MAX_VALUE(result变量是为了存储找到的最短子数组的长度)
  3. 使用一层for循环,以 right 为迭代器,循环内部,将当前元素 nums[right] 添加到 sum 中,当sum 大于或等于 target 时,进入while循环(不能是if,因为要缩小窗口)
  4. 通过Math类中的min方法,比较 result 和 滑动窗口的长度 ,取两者间的最小值,更新 result
  5. 然后从 sum 中减去 nums[left](从左侧缩小窗口),left 一定要向前移动。直到sum小于target时,退出循环
  6. 循环结束后,检查 result 是否仍然是 Integer.MAX_VALUE。如果是,则意味着没有找到满足要求的子数组,返回0;否则,则返回 result

代码实现(Java) 

//暴力解法
class Solution {
public:
    int minSubArrayLen(int s, vector<int>& nums) {
        int result = INT32_MAX; // 最终的结果
        int sum = 0; // 子序列的数值之和
        int subLength = 0; // 子序列的长度
        for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为i
            sum = 0;
            for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为j
                sum += nums[j];
                if (sum >= s) { // 一旦发现子序列和超过了s,更新result
                    subLength = j - i + 1; // 取子序列的长度
                    result = result < subLength ? result : subLength;
                    break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
                }
            }
        }
        // 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
        return result == INT32_MAX ? 0 : result;
    }
};
//滑动窗口
class Solution {
    public int minSubArrayLen(int target, int[] nums) {
        int left = 0;
        int sum = 0;
        int result = Integer.MAX_VALUE;
        for(int right = 0;right < nums.length;right++){
            sum = sum + nums[right];
            while(sum >= target){
                result = Math.min(result,right - left + 1);
                sum = sum - nums[left];
                left++;
            }
        }
        return result == Integer.MAX_VALUE ? 0:result;
    }
}

59.螺旋矩阵II

题目链接:. - 力扣(LeetCode)

题目描述

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

思路分析

  1. 创建一个n x n的二维数组来存储螺旋矩阵。
  2. int startX = 0, startY = 0; 设置起始点的坐标,初始为(0,0)。
  3. int offset = 1; 设置偏移量,用于控制每一圈螺旋的边界。
  4. int count = 1; 设置计数器,用于填充矩阵中的数字。
  5. int loop = 1; 设置循环计数器,用于控制螺旋的圈数。
  6. int i, j; 定义循环变量i和j,分别代表行和列。

接下来是一个while循环,用于生成螺旋矩阵:

  1. while (loop <= n / 2) 循环直到loop大于n/2,这意味着完成了所有完整的螺旋圈。

在循环内部,分别处理四个方向:

  1. for (j = startY; j < n - offset; j++) { nums[startX][j] = count++; } 填充当前圈的最上面一行,从左到右。
  2. for (i = startX; i < n - offset; i++) { nums[i][j] = count++; } 填充当前圈的右面一列,从上到下。
  3. for (; j > startY; j--) { nums[i][j] = count++; } 填充当前圈的最下面一行,从右到左。
  4. for (; i > startX; i--) { nums[i][j] = count++; } 填充当前圈的左面一列,从下到上。

每次循环结束后,更新起始点坐标和偏移量:

  1. startX++; startY++; offset++; loop++; 分别将起始点坐标向内移动,增加偏移量,并增加圈数。

最后,如果n是奇数,中心位置需要单独处理:

  1. if (n % 2 == 1) { nums[startX][startY] = count; } 在矩阵中心填入最后一个数字。

最后,返回填充好的二维数组nums

代码实现(Java)

class Solution {
    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;
    }
}

  • 35
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组平方",和Leetcode 209 "长度最小数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小数组,使得数组的和大于等于给定的目标值。这里可以使用滑动窗口的方法来解决问题。使用两个指针来表示滑动窗口的左边界和右边界,通过移动指针来调整滑动窗口的大小,使得滑动窗口中的元素的和满足题目要求。具体实现的代码如下: ```python def minSubArrayLen(self, target: int, nums: List[int]) -> int: left = 0 right = 0 ans = float('inf') total = 0 while right < len(nums): total += nums[right] while total >= target: ans = min(ans, right - left + 1) total -= nums[left] left += 1 right += 1 return ans if ans != float('inf') else 0 ``` 以上就是第二十二天的算法训练营的内容。通过这些题目的练习,可以提升对双指针和滑动窗口等算法的理解和应用能力。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值