理论

考察数组的一般重在代码,思维不难,实现可能比较难。

几点注意:

  • 数组的下标都是0开始
  • 数组的内存空间地址是连续的
  • 数组元素不能删除,只能覆盖

在属于数组考点系列的题目中,划分为四个常考问题:子数组问题、矩阵问题、O(n)类型问题和思维转换类型问题。1

  • 子数组问题:就是给定一个数组,围绕该数组的子数组列出诸多难题,等待我们来解答
  • 矩阵问题:给定一个矩阵(或者称为二维数组),围绕该矩阵列出不同方式遍历矩阵中元素等难题,等待我们来解答
  • O(n)类型问题:O(n)是指时间复杂度为O(n),给定的题目题意一般很容易理解,其一般解法(俗称暴力解法,时间复杂度一般为O(n^2),甚至更高)也很简单,但是题目要求你的解法时间复杂度为O(n)。看到这些题目的某些解答后,会让我们忍不住夸赞:真乃神人、好厉害、奇异特解、巧妙、强、优雅
  • 思维转换类型问题:其解答不属于上述三种类型问题,但是解答方式有点巧妙,或者说该类型题目较为基础,很可能考察你的快速应用代码能力的题目。

二分查找

https://leetcode-cn.com/problems/binary-search/

区间区分好就可以
区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。

第一种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public int search(int[] nums, int target) {
// 避免当 target 小于nums[0] nums[nums.length - 1]时多次循环运算!
if (target < nums[0] || target > nums[nums.length - 1]) {
return -1;
}
int left = 0, right = nums.length - 1;
while (left <= right) {
int mid = left + ((right - left) >> 1); //右移一位就是除2
if (nums[mid] < target)
left = mid + 1;
else if (nums[mid] > target)
right = mid - 1;
else return mid;
}
return -1;
}
}

第二种:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int search(int[] nums, int target) {
int left = 0;
int right = nums.length; // 定义target在左闭右开的区间里,所以右边的开边界不用减一
while(left < right){
int mid = left + (right-left)/2;
if (nums[mid] < target){
left = mid +1;
}
else if (nums[mid] > target){
right = mid ;
}
else return mid;
}
return -1;
}
}

移除元素

https://leetcode-cn.com/problems/remove-element/

双指针法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int removeElement(int[] nums, int val) {
// 快慢指针
int fastIndex = 0;
int slowIndex;
for (slowIndex = 0; fastIndex < nums.length; fastIndex++) {
if (nums[fastIndex] != val) {
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;

}
}

优化(左右开弓):如果要移除的元素恰好在数组的开头,例如序列 [1,2,3,4,5],当 val 为 1 时,我们需要把每一个元素都左移一位。注意到题目中说:「元素的顺序可以改变」。实际上我们可以直接将最后一个元素 5 移动到序列开头,取代元素 1,得到序列 [5,2,3,4],同样满足题目要求。这个优化在序列中 val 元素的数量较少时非常有效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public int removeElement(int[] nums, int val) {
int left = 0;
int right = nums.length;
while (left < right) {
if (nums[left] == val) {
nums[left] = nums[right - 1];
right--;
//这里不能加left++;因为有可能nums[right - 1]也等于val,所以还得继续判断当前的left元素。
} else {
left++;
}
}
return left;
}
}

有序数组的平方

https://leetcode-cn.com/problems/squares-of-a-sorted-array/

同双指针:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public int[] sortedSquares(int[] nums) {
int l = 0;
int r = nums.length - 1;
int[] res = new int[nums.length];
int k = nums.length - 1;
while(l <= r){
if(nums[l] * nums[l] > nums[r] * nums[r]){
res[k--] = nums[l] * nums[l++];
}else{
res[k--] = nums[r] * nums[r--];
}
}
return res;
}
}

长度最小的子数组

https://leetcode-cn.com/problems/minimum-size-subarray-sum/

滑动窗口
重要的三点内容:

  • 窗口内是什么
  • 窗口的开始位置
  • 窗口的结束位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {

// 滑动窗口
public int minSubArrayLen(int s, int[] nums) {
int left = 0;
int sum = 0;
int result = Integer.MAX_VALUE;
for (int right = 0; right < nums.length; right++) {
sum += nums[right];
while (sum >= s) {
result = Math.min(result, right - left + 1);
sum -= nums[left++];
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}

螺旋矩阵

https://leetcode-cn.com/problems/spiral-matrix-ii/

并不涉及到什么算法,就是模拟过程,但却十分考察对代码的掌控能力。

主要遵循循环不变量原则
每画一条边都要坚持一致的左闭右开,或者左开又闭的原则,这样这一圈才能按照统一的规则画下来

这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。
这也是坚持了每条边左闭右开的原则。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class Solution {
public int[][] generateMatrix(int n) {
int[][] res = new int[n][n];
int loop = n/2; // 循环几个圈
int mid = n/2;
int offset = 1;
int count = 1;
int startx = 0, starty = 0;

while(loop>0){
int x = startx, y = starty;
for(;y < starty + n - offset; y++){
res[startx][y] = count++;
}
for(;x < startx + n - offset; x++){
res[x][y] = count++;
}
for(;y > starty; y--){
res[x][y] = count++;
}
for(;x > startx; x--){
res[x][y] = count++;
}
offset += 2; // offset 控制每一圈里每一条边遍历的长度
startx++;
starty++;
loop--;
}
// 如果n为奇数的话,需要单独给矩阵最中间的位置赋值
if (n % 2 == 1){
res[mid][mid] = n*n;
}
return res;
}
}

Reference:

https://programmercarl.com
1https://www.cnblogs.com/liuzhen1995/p/11789339.html
https://leetcode-cn.com/problems/remove-element/solution/yi-chu-yuan-su-by-leetcode-solution-svxi/