数组

71 阅读1分钟

数组理论基础

常见题

二分法

  1. 注意区间的选择(左闭右开、左闭右闭)所对应的left、right下标的初始化以及更新。
  2. 加法加算时,使用int mid = left + (right - left)/2;,可以防止数据溢出。
        while (left <= right) { // 当left==right,区间[left, right]依然有效,所以用 <=
            int middle = left + ((right - left) / 2);// 防止溢出 等同于(left + right)/2
            if (nums[middle] > target) {
                right = middle - 1; // target 在左区间,所以[left, middle - 1]
            } else if (nums[middle] < target) {
                left = middle + 1; // target 在右区间,所以[middle + 1, right]
            } else { // nums[middle] == target
                return middle; // 数组中找到目标值,直接返回下标
            }
        }

双指针法

  1. 快慢指针: 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
    快指针遍历时,用慢指针做记录,不会影响快指针的遍历过程。

    题目 leetcode.cn/problems/re…

  2. 首尾指针:首尾指针一起遍历,作比较记录结果。

    题目 leetcode.cn/problems/sq…

滑动窗口

滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果
题目 leetcode.cn/problems/mi…
题目 leetcode.cn/problems/fr…

image.png

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

  • 窗口内是什么?
  • 如何移动窗口的右边界? 外层for循环
  • 如何移动窗口的左边界? 内层while循环

模板

  • 最大窗口模板
for (int right = 0; right < nums.length; right ++) {
    处理窗口新来元素right;
    while (窗口不满足条件) {
        处理窗口最左边元素left;
        left += 1  // 最保守的压缩i,一旦满足条件了就退出压缩i的过程,使得滑窗尽可能的大
    }
    更新结果;(注意在while外更新!)
}
  • 最小窗口模板
for (int right = 0; right < nums.length; right ++) {
    处理窗口新来元素right;
    while (窗口满足条件) {
        更新结果;(在while内更新!)
        处理窗口最左边元素left;
        left += 1  // 最大程度的压缩i,满足条件就一直压缩i,使得滑窗尽可能的小
    }
}

螺旋矩阵

方法一(模拟法,设定边界,代码简短清晰)
首先是定义上下左右四个边界(l,r,t,b),按照(上右下左)t, r, b, l遍历每条边,每次走完一条边压缩边界并进行判断break;if (++t > b) break;注意是先++,

        while (true) {
            for (int x = l; x <= r; x++) res[t][x] = count++;
            if (++t > b) break;
            for (int x = t; x <= b; x++) res[x][r] = count++;
            if (--r < l) break;
            for (int x = r; x >= l; x--) res[b][x] = count++;
            if (--b < t) break;
            for (int x = b; x >= t; x--) res[x][l] = count++;
            if (++l > r) break;
        }

image.png

方法二(每圈重新定义边界,比较麻烦,不推荐)

  • 每条边左闭右开,按圈循环遍历,总圈数n/2;
  • 定义变量;
        int startx = 0, starty = 0; // 定义每循环一个圈的起始位置
        int loop = n / 2; // 每个圈循环几次,n为奇数时矩阵中间的值需要单独处理
        int count = 1; // 用来给矩阵中每一个空格赋值
        int offset = 1; // 需要控制每一条边遍历的长度,每次循环右边界收缩一位
        int i,j; // 循环赋值时用到的变量res[i][j]