Day2 数据结构与算法(Java)----数组(双指针),滑动窗口

一,题977. 有序数组的平方(双指针法)

题目链接:
力扣

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

可以考虑双指针法,i指向起始位置,j指向终止位置。

定义一个新数组result,和A数组一样的大小,让k指向result数组终止位置。

如果A[i] * A[i] < A[j] * A[j] 那么result[k--] = A[j] * A[j]; 。

如果A[i] * A[i] >= A[j] * A[j] 那么result[k--] = A[i] * A[i];

class Solution {
    public int[] sortedSquares(int[] nums) {
    int left=0;
    int right=nums.length-1;
    int k=nums.length-1;
    int [] result=new int[nums.length];
    while(left<=right)
    {
        if(nums[left]*nums[left]<nums[right]*nums[right])
        {
            result[k]=nums[right]*nums[right];
            right--;
            k--;
        }
        else
        {
            result[k]=nums[left]*nums[left];
            left++;
            k--;
        }

    }
    return result;
    }
}

fc0e80f0a93e49b7958310bd4d432c6b.jpeg

其中

     result[k]=nums[right]*nums[right];
            right--;
            k--;

 可以简写为如下代码

result[k--]=nums[right]*nums[right--];

二,209.长度最小的子数组

题目链接:

力扣

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

在本题中实现滑动窗口,主要确定如下三点:

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?

窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。

窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引

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

f659cd1870854f7c97926c45c2e3c09b.jpeg

Integer.MAX_VALUE表示int数据类型的最大取值数:2 147 483 647
Integer.MIN_VALUE表示int数据类型的最小取值数:-2 147 483 648

补充:
Integer.MAX_VALUE+1=Integer.MIN_VALUE

因为:
Integer.MAX_VALUE的二进制是0111 1111 1111 1111 1111 1111 1111 1111
Integer.MIN_VALUE的二进制是 1000 0000 0000 0000 0000 0000 0000 0000

0111 1111 1111 1111 1111 1111 1111 1111+1=1000 0000 0000 0000 0000 0000 0000 0000

其中Integer.MAX_VALUE可以换成一个较大的值,如99999999。

最后一行不能删除,否则报错,分析一下这种情况:

d3a685c652de418bb1259b2b7ed50fcf.png

此时永远不会满足 while(sum>=target),直接遍历完数组,不会执行while语句中的值,result的值还是之前默认的那个很大的数。而实际上没有找到满足的子数组result应该返回0。所以最后不能直接返回result,而是

return result ==Integer.MAX_VALUE? 0 : result;

324e79885d2e44f49154984c38dc01b1.png

以下三种写法都是等效的

 result = Math.min(result, length);
 result = (result<length)?result:length;
if(result>length) result=length;

最后,不要以为for里放一个while就以为是O(n^2)啊, 主要是看每一个元素被操作的次数,每个元素在滑动窗后进来操作一次,出去操作一次,每个元素都是被操作两次,所以时间复杂度是 2 × n 也就是O(n)。像上面那种极端的情况下直接不进入到while中,只被操作一次,时间复杂度是  n,也就是O(n)。

4bb5ada8c4864442a56609bb77ac4fc4.png

三,59.螺旋矩阵II(注意保持左闭右开区间原则)

题目链接:力扣

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

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

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

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

class Solution {
    public int[][] generateMatrix(int n) {
    int [][]nums=new int[n][n];
    int start=0;
    int count=1;
    int loop=0;
    int i,j;
    while(loop++<n/2)
    {
     for(j=start,i=start;j<n-loop;j++)
     nums[i][j]=count++;
     for(;i<n-loop;i++)
     nums[i][j]=count++;
     for(;j>=loop;j--)
     nums[i][j]=count++;
     for(;i>=loop;i--)
     nums[i][j]=count++;
     start++;
    }
    if(n%2==1)
    {
     nums[start][start]=count;
    }
    return nums;
    }
}

0f60341120264763989977c64547492e.jpeg

注意: while(loop++<n/2)中的loop++不能放到循环末尾,也不能直接改成++loop,否则会报错;

8162f8c41de54bf0b25563d659faa082.png

可改为

while(++loop<=n/2)

也可以直接放在循环的第一行

while(loop<n/2)
{
  loop++; /++loop;
.......
}

 但是改为下面这样会报错

 while(loop<=n/2)
    {
          ++loop;
.....
}

加入输出语句,可以看出运行过程。可以看到多了一次循环,但是下标已经不对了,start变为了2,应该是nums[1][1]=9(即nums[start][start]=9)

6be8bf9536b84eb780655c2461e1ec5b.png

正确的运行结果如下:

3e6413c660a84c56a50a88256fd3a766.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值