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

LeetCode977.有序数组的平方

基本思路:使用双指针,一个指向数组的头(left),一个指向数组的尾(right),还有一个指针指 ansIndex 向结果数组的末尾(方便进行倒插),对 left 和 right 指向的值的平方进行比较,会有三种情况:

(1)当 left * left < right * right 的时候,将 right * right 放入到结果数组的ansIndex上(这样反着放,出来的结果就是升序,当然也可以不这样,把left放到第一的位置也可以),然后right向左移动一位,left不变,ansIndex向左移动一位。

(2)当 left * left > right * right 的时候,将left * left 的值放入到结果数组的ansIndex上,然后left右移,right不变,ansIndex向左移动一位。

(3)当 left * left == right * right 的时候,随便取两个值中的一个放入到结果数组的ansIndex位置上,然后对应移动(选left就右移,选right就左移),另外一个指针不动,ansIndex向左移动一位。

上述流程写到一个while循环内,循环的终止条件为left >= right(其实只会是等于),当循环结束之后,ansIndex会来到数组的第一个位置(ansIndex == 0),这个时候left 和 right 指向同一个数,随便选择一个,然后再平方放入到ansIndex位置上,最后将结果返回。

Java代码如下:

public int[] sortedSquares(int[] nums) {
    	int n = nums.length - 1;
    	int[] ans = new int[n+1];
    	int left = 0;
    	int right = n;
    	while(left < right) 
    	{
    		if(nums[left] * nums[left] <= nums[right] * nums[right]) 
    		{
    			ans[n--] = nums[right] * nums[right];
    			right--;
    		}
    		else 
    		{
    			ans[n--] = nums[left] * nums[left];
    			left++;
    		}
    	}
    	ans[n] = nums[left] * nums[left];
    	return ans;
    }

 时间复杂度:O(n)

空间复杂度:O(1)

LeetCode209.长度最小的子数组

基本思路:维护一个滑动窗口,需要返回的结果就是滑动窗口的长度(left - right + 1)。滑动窗口就是用两个指针(left,right),left指向滑动窗口的头,right指向滑动窗口的尾,维护一个滑动窗口内的数的和(初始值为0),滑动窗口每次移动的时候就会对和进行加减,刚开始的时候left和right相等。

步骤1:每次循环开始时都将滑动窗口的右边界扩大一位,和也随之扩大。

步骤2:当和大于目标值,将滑动窗口左边界右移一位(滑动窗口缩小),和也减去除去那一位。因为题目需要的是最小的子数组,那么需要维护一个全局的最小子数组长度,minAns(初始值为Integer.MAX_VALUE,这样会在取两者较小值的时候被重新赋值),取minAns和当前滑动窗口的长度的较小值就可以了。这个步骤需要放到一个while循环中,终止条件为 和>=目标值(因为存在减了几次和依然大于目标值的情况)。如果和小于目标值就进入下一轮循环。

上述两个步骤需要放到一个while循环中,终止条件为right >= 数组的长度,当循环结束,返回minAns之前需要判断一下这个值是否为Integer.MAX_VALUE,如果是的话说明没有最小子数组,返回0,反之返回minAns。

Java代码如下:

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

时间复杂度:O(n)

空间复杂度:O(1)

 LeetCode59.螺旋矩阵||

基本思路:从左到右,从上到下,从右到左,从下到上,为一圈,需要注意圈数,每完成一圈,下一圈矩阵的长宽就会减小2,假设给的长度为4,第一圈结束后,第二圈开始的长宽就变成2了,这一圈结束以后就遍历完毕了,所以圈数就等于4 / 2 = 2圈(相当于4能够减去多少个2,就有多少圈)。用一个start变量表示开始的下标,每转一圈,就加一,因为外圈已经遍历完毕了。变量loop表示现在是第几圈。

(1)从左到右,设 i 为行,j 为列,写一个for循环,j = start(因为每转一圈开始位置会缩小),终止条件为 j < n - loop,j++。n - loop 的含义为当前需要填充的数量,需要 - loop 是因为要把最后一个位置的数留给从上到下的流程处理,保证流程的统一性,每个边的遍历都是左闭右开的形式。循环结束后,i 没有改变,j来到了这一行的最后一位进行下一个流程。

(2)从上到下,现在i,j 所在的位置为矩阵的右上角,执行从上到下的流程,写一个for循环,j 保持不变,i = start ,终止条件为 i > n - loop ,i++ 原理同上。循环结束以后来到了矩阵的右下角,进行下一个流程。

(3)从右到左,现在i,j的位置在矩阵的右下角,写一个for循环,i 保持不变 ,j 现在的值是当前行的最后一位(从左到右的流程给j的值),终止的条件为  j < loop (边界会随着当前的圈数缩小),j--。循环结束之后来到矩阵的左下角,进行下一个流程。

(4)从下到上,现在i,j的位置在矩阵的左下角,写一个for循环,j保持不变,i现在的值为当前矩阵的最后一列,向上遍历,终止条件为 i < loop(原理同上),i--。循环结束之后,当前圈结束。

(5)start++,开始位置向下移动一位。

上述流程写入到一个while循环中,循环的条件为 loop++ < n / 2。++是因为圈数要从1开始,也可以初始化的时候就给1。为什么要除2,原因上面已经讲过了。

当给的n为基数的时候,中心位置会有一个空,需要特殊处理一下,如果是奇数的话,在矩阵的start,start位置单独赋值为count(count是填充的数字,每填充一个就++),为什么是start,start位置呢,因为每一圈start都++,到了最后一圈结束以后,start,start位置就加到了中心位置。

最后将结果返回。

Java代码如下:

    public int[][] generateMatrix(int n) {
		int i = 0;
		int j = 0;
		int loop = 0;
		int[][] ans = new int[n][n];
		int start = 0;
		int count = 1;

		while (loop++ < n / 2) {
			for (j = start; j < n - loop; j++) {
				ans[start][j] = count++;
			}
			for (i = start; i < n - loop; i++) {
				ans[i][j] = count++;
			}
			for (; j >= loop; j--) {
				ans[i][j] = count++;
			}
			for (; i >= loop; i--) {
				ans[i][j] = count++;
			}

			start++;

		}

		if (n % 2 == 1) {
			ans[start][start] = count;
		}

		return ans;
    }

时间复杂度:O(n^2)

空间复杂度:O(1) 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值