代码随想录—数组

75 阅读3分钟

数组

1. 二分查找:循环不变量

思路: 确定左右区间边界后通过比较中间值与目标值大小一步步缩小范围最后确认目标值位置

区间选择代码实现
左闭右闭while(l <= r) if (nums[mid] > target) {r = mid - 1}
左闭右开while(l < r) if (nums[mid] > target) {r = mid}

例题: 35. 搜索插入位置 carbon.png

2. 移除元素: 双指针(快慢指针)

思路: 数组在内存中实际是存储在连续的地址空间,不能单一释放元素,所以删除元素不能简单的直接删除而要通过覆盖实现删除操作。双指针移除数组中元素的解法,实际上是用快指针判断新数组的值,再将值赋给慢指针指向的位置

例题: 27. 移除元素 image.png

3. 最小子数组:滑动窗口

思路: 滑动窗口主要思想是剪枝掉了暴力循环遍历中的冗余部分,通过“窗口”的终止位置来驱动窗口的移动,以“窗口”的起始位置来控制窗口的长度

如果按照结尾的索引 j 来搜索,对于每一个 j ,暴力搜索就是把 i0j 都搜索了一遍。 而滑动窗口的方法中,对于每一个 j ,剪枝掉的部分是:

  1. i 过大的部分:如果有一个 i 都不满足条件了,那么更大的 i 更不可能满足,自然没必要继续 i++ 了,这一点很好理解
  2. i 过小的部分:以移动后的 j 为结尾,更小的 i 也可能会满足 >target 的条件,但当我们增加 j ,直到再一次遇到符合条件的最小滑动窗口的时候, j 至少增加了 1i 如果向前移动,那么窗口一定会比上次遇到的窗口长

例题:209. 长度最小的子数组 image.png

4. 螺旋矩阵:循环不变量

思路: 将每圈大循环拆分为4条边的小循环,要注意每个小循环的边界条件,题目中是n * n的正方形矩阵,需要额外考虑n为奇数时矩阵中间留空的情况

例题1:59. 螺旋矩阵 II image.png

思路: 更普遍的思路,不会被限制在n * n矩阵中,将每圈大循环拆分为4条边的小循环,为四条边分别初始化一个边界条件来限制,必须在每条边的小循环完成后都判断是否越界

例题2:54. 螺旋矩阵 image.png

5. 区间求和:前缀和

思路: 重复利用计算过的子数组之和,从而降低区间查询需要累加计算的次数来简化暴力算法的全部遍历

为目标数组 vec[] 构建一个前缀和数组 pre[] ,目标区间,例如 vec[2]vec[5] 的累加和即为 pre[5] - pre[1]

p[1] = vec[0] + vec[1];

p[5] = vec[0] + vec[1] + vec[2] + vec[3] + vec[4] + vec[5];

p[5] - p[1] = vec[2] + vec[3] + vec[4] + vec[5];

例题1:58. 区间和 image.png

思路: 从一维数组推广到二维数组,思路是一致的,就是分成横向和纵向分别求两边行和列的数值总和,再求差值找最小值即可;也可以在暴力算法的基础上优化,即在行遍历求和时,遇到行末就统计求差值,列遍历同理

例题2:44. 开发商购买土地 image.png