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

977.有序数组的平方

参考视频和详解

代码随想录

我的想法

暴力法,为什么时间复杂度是O(n + nlogn)???

优解思路

双指针法

  1. i 指向数组头,j 指向数组尾
  2. 创建一个和原数组长度一样的新数组result,让result指针n指向新数组的尾部
  3. 比较nums[i]*nums[i]和nums[j]*nums[j]的大小,大的值添加到新数组。大的值对应的指针进行移动
  • nums[i]*nums[i] > nums[j]*nums[j]
    • nums[n--] = nums[i]*nums[i]
    • i++
  • else:

        nums[n--] = nums[j]*nums[j]

        j--

Time Complexity

O(n)

代码实现

1. 定义双指针

        int i = 0; (数组头)

        int j = nums.length - 1 (数组尾)

2. 定义新数组

        int[] result = new int[nums.length]

3. 定义新数组的指针

        int n = result.length - 1 (数组尾)

4. while循环结束条件

        while(i <= j)

5.循环体

        比较nums[i]和nums[j]的平方,将大数添加到新数组尾,依次向前添加。

        注意,添加完大数后,将原数组中对应的指针进行移动。最后,将新数组指针n往前移(n--)

        while(i <= j){

            if(nums[j] * nums[j] > nums[i] * nums[i]){

                result[n--] = nums[j] * nums[j]; //给新数组添加元素

                j--;  //在原数组中移动大数对应的指针

            }else{

                result[n--] = nums[i] * nums[i];

                i++;

6. 返回新数组

        return result

遇到的问题

1. 应该如何移动指针?

        谁的平方数大移动哪个指针

2. 循环结束条件?

        当两个指针交锋,即left>right时,循环结束

3. 一些细节问题

        往新数组result中放入元素时,应该放的是nums[i]或nums[j]的平方值,而不是nums[i]或nums[j]

4. java语法不熟悉

  • 排序:Arrays.sort()没有返回值,返回类型是void
  • 创建新数组:int[] array = new arrar[array.len]

209.长度最小的子数组

参考视频和详解

代码随想录

我的想法

暴力法,时间复杂度O(n2)

优解思路

滑动窗口

1. 窗口内是什么?

        满足sum >= target的长度最小的连续子数组

2. i 和 j 到底谁指向窗口的终止位置?

        j 指向滑动窗口的终止位置,起始位置动态移动

3. 如何移动起始位置?

        j指针先找右边,找到右边再收缩左边,j 继续找更优解

代码实现

1. 定义双指针

        int i = 0 (用来定义窗口的起点)

        int j = 0 (在for循环处定义窗口的终点)

2. 定义最小值和初始化sum

        int minVal = Integer.MAX_VALUE (用来保存最小长度)

        int sum = 0

3. 循环条件:用窗口终点 j 遍历数组

for(int j = 0; j < nums.length; j++)

4. 取最小长度子数组

//j指针向右移,找到右边收缩左边(i向右移),j继续找更优解(j++)

for(int j = 0; j < nums.length; j++){

sum += nums[j];

while(sum >= target){

int len = j-i+1;

if(len < minVal){

minVal = len;

}

sum = sum - nums[i];

i++;

}

}

5. 返回值

        判断有没有找到minVal,没找到返回0,找到返回minVal

遇到的问题

1. 如何比较并保存最小长度的值

int minVal = Integer.MAX_VALUE

If (len < minVal){

minVal = len

}

Integer.MAX_VALUE是java中Integer类的一个常量,代表了int类型能够表示的最大值

2. 没有考虑数组所有元素和都小于target的情况,比如target = 11, nums=[1, 1, 1, 1, 1,1]

        应该考虑有没有找到minVal,没有找到返回0

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

59. 螺旋矩阵II 

参考视频和详解

代码随想录

优解思路

坚持一个规则来处理每一条边(循环不变量)

左闭右开:最后一个节点留给下一条边来处理

代码实现

1. 循环起始位置定义

        起始位置不断变化,所以不能在for循环里面定义

        startX = 0;

        startY = 0;

2. 临界点处理

        定义一个临界值变量, n-offest表示不包含最后一个节点

        offset = 1

3. 定义count,用来给值计数

        count = 1

4. 定义 i, j 更新行列坐标

        注意 i, j 要定义在循环体外

5. while循环结束条件:

        while(n / 2)

        n是边长,n/2是圈数。偶数被整除,奇数会留下中间一个点。

        只需要在最后判断一下,如果n是奇数,nums[][]=val单独赋值

6. 循环模拟矩阵走向

  • 遍历最上行 (0,0)(0,1)(0,2)

        for(j = startY; j < n - offset; j++){

                 arr[startX][j] = count++;

       }

  • 遍历最右列 (0,2)(1,2)(2,2)

        for(i = startX; i < n - offset; i++){

                 arr[i][j] = count++;

       }

  • 遍历最下行 (2,2)(2,1)(2,0)

        for(;j > startY; j--){

             arr[i][j] = count++;

        }

  • 遍历最左列 (2,2)(2,1)(2,0)

        for(; i > startX; i--){

              arr[i][j] = count++;

        }

7. 更新定义值

        每转一圈,startX++, startY++, offset++

8. 如果n为奇数, 需要对中间的值单独赋值

        nums[startX][startY] = count

遇到的问题

1. 行列坐标如何更新,混淆了行列坐标

        用i代表行,j代表列

2. startX, startY, offset的作用是什么?

  • (startX, startY)更新每一轮矩阵循环的起始点

        将这一轮循环的 I 初始化为startX, j 初始化为startY

  • offset用来更新每条边的终点

3. 如果n为奇数,怎么处理?

把最后一个点赋值给arr[][],那么最后一个点怎么表示呢?

如图,奇数到了最后一个循环,只会剩余起始点(startX, startY)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值