Leetcode题解-数组相关-977. 有序数组的平方/209. 长度最小的子数组/59. 螺旋矩阵 II

977.有序数组的平方

题目描述

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

示例 1:
输入:nums = [-4,-1,0,3,10]
输出:[0,1,9,16,100]
解释:平方后,数组变为 [16,1,0,9,100]
排序后,数组变为 [0,1,9,16,100]

思路

本题关键要清楚数组的特点,非递减顺序说明平方后数组的最大值只能出现在两头,不可能出现在中间。这是解本题的关键。通过比较两头元素的大小,取大值放入新数组中。由此可以想到双指针法。

算法核心

1.指定一个头指针left,一个尾指针right。
2.比较两个指针指向的元素,大值赋值给新数组,并移动相应的指针。
3.循环条件,left <= right。

代码&复杂度

public int[] sortedSquares(int[] nums) {
        int[] results = new int[nums.length];
        int index = results.length - 1;
        for(int left = 0, right = nums.length - 1; left <= right;){
        	int head = nums[left]*nums[left];
        	int tail = nums[right]*nums[right];
            if(head > tail){
                results[index--] = head;
                left++;
            }else{
                results[index--] = tail;
                right--;
            }
        }
        return results;
    }

时间复杂度: O(n)
空间复杂度: O(1)

注意

  1. 看清楚题目要求,返回要一个新数组,所以不是在元素组上面操作,别走入误区。

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

示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

思路

核心思想是找到所有和大于等于target的集合。要借助双指针来达到目的。一个指针用来遍历所有元素,找到和大于等于target的集合,另一个指针用来定位该集合中符合条件的子集合。这个方法又叫滑动窗口。

算法核心

1.定义两个指针,right指针用来遍历所有元素,并作为窗口的末端。left指针作为窗口的起始端。
2.在right指针移动的过程中,一旦所遍历元素和大于等于target,则把此集合的长度和最小长度初始值比较,哪个小就更新给最小长度。
3.注意在此符合条件的集合中,可能会存在子集合也符合条件,所以需要通过移动left指针找到符合条件的子集合,此过程是一个循环的过程。
4.重复2,3
5.right指针的移动要遍历所有元素,只要集合的元素和满足条件,left指针就要向右滑动。

代码&复杂度

public int minSubArrayLen(int target, int[] nums) {
		int minLen = Integer.MAX_VALUE;
		int sum = 0;
		int left = 0;
		
		for(int right = 0; right < nums.length; right++) {
			sum += nums[right];
			while(sum >= target) {
				// 之所以是while不是if,因为一个符合条件的集合内,有可能有子集合也符合条件。如[1,1,1,100]和大于等于100的集合不止一个。
				minLen = Math.max(minLen, right - left + 1);
				left++;
				sum -= nums[left-1];
			}
		}
		
		if(minLen == Integer.MAX_VALUE) {
			minLen = 0; 
		}
		
		return minLen;
    }

时间复杂度: O(n)
空间复杂度: O(1)

注意

  1. 方法中涉及两个循环,时间复杂度为什么不是O(n2)呢?
    while循环在最坏情况下使每个元素多遍历了一遍,所以复杂度为O(2n),视为O(n)。
  2. 注意没找时,要把minlen赋为0,在写代码的时候要注意一些特殊情况。

59. 螺旋矩阵 II

题目描述

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

示例 1:
在这里插入图片描述
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

示例 2:
输入:n = 1
输出:[[1]]

思路

该题核心思想是模拟行为,也就是根据顺时针方向一行一行的赋值。每行的边界问题遵循同样的规则,保持规则的一致性,这样边界就不会乱套。

算法核心

  1. 该解法其实就是完成几个圈所经过的元素的赋值,如果n为奇数,最后一个元素不成圈,单个赋值。
  2. 在绕圈中要经过四条边,每条边所经过的元素通过for循环赋值,注意for循环中的边界条件。

代码&复杂度

public static int[][] generateMatrix(int n) {
		int[][] matrix = new int[n][n];
		int firstValue = 1;
		int startX = 0, startY = 0; //转圈的起始位置,每个圈的起始位置不同
		int offset = 1; //赋值的统一规则[)左闭右开,如n=4时,[0,1,2,3),3位置不赋值,在下个循环中赋值。
		int loop = 1; //圈的计数
		while(loop <= n/2) {//圈数=n/2
			int i = startX;
			int j = startY;
			//上侧从左到右赋值
			for(; j < n-offset; j++) {
				matrix[i][j] = firstValue++;
			}
			//右侧从上到下赋值
			for(; i < n-offset; i++) {
				matrix[i][j] = firstValue++;
			}
			//下侧从右到左赋值
			for(; j > startY; j--) {
				matrix[i][j] = firstValue++;
			}
			//左侧从下到上赋值
			for(; i > startX; i--) {
				matrix[i][j] = firstValue++;
			}
			loop++;
			startX++;
			startY++;
			offset++;
		}
		
		if(n % 2 == 1) {//如果n为基数,则最后有一个数不成圈,单独赋值
			matrix[n/2][n/2] = firstValue;
		}
		
		return matrix;
    }

时间复杂度: O(n2)
空间复杂度: O(1)

注意

  1. for循环中的边界条件很容易乱,一是要保持规则的统一性,二可以借助画图来确保正确性。
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值