萌新刷力扣——数组篇

本文详细介绍了数组这一基本数据结构,包括创建、遍历、统计和改变等操作。重点讲解了如何利用前缀和、滚动数组等技巧解决LeetCode中的数组问题,涉及排序、查找、统计和原地修改等算法。同时,还探讨了二维数组的处理,如图像平滑、矩阵旋转等,并强调了在有限空间内进行原地算法的重要性。
摘要由CSDN通过智能技术生成

刷题顺序是根据:有没有人一起从零开始刷力扣 - 力扣(LeetCode)

数组的定义:

数组是最简单的数据结构之一。数组,即元素的序列,可以按特定顺序存储元素。元素可以是整数,浮点数,字符,各种结构体等等。

我们可以选择以下两种方式创建数组,同理可得多维数组的创建方式。

dataType[] arrayRefVar = new dataType[arraySize];
dataType[] arrayRefVar = {value0, value1, ..., valuek};

当然解决数组问题也要掌握其他已有的工具,比如List、Map的创建:

Java中List的详细用法_Barcon的博客-CSDN博客_list用法

Java中Map详解_朱 江的博客-CSDN博客_mapjava

数组题目分类:

数组的遍历:

遍历数组过程中常用方法

//对数组nums进行排序
Arrays.sort(nums);

//对数组nums进行翻转
reverse(nums);

//数组nums的长度
nums.length

链接
485. 最大连续1的个数
495. 提莫攻击
414. 第三大的数
628. 三个数的最大乘积

统计数组中的元素:

如何统计元素出现的次数?


元素个数的统计,若元素最大值与最小值之间相差不大(百万级别或以下),我们就可以用一个数组times[i]来表示i出现的次数,即times[nums[i]]++;


如何统计元素在数组中出现的最左和最右的位置?


我们可以参照元素出现次数的统计方法,用额外的数组l[i]和r[i]代表数字i出现的最左边和最右边的位置,在顺序遍历数组nums的第i个元素时,使r[nums[i]]=i,之后逆序遍历数组nums,使l[nums[i]]=i,可参考如下代码:
 

for (int i = 0; i < nums.size(); i++) {
    r[nums[i]] = i;
}
for (int i = nums.size() - 1; i >= 0; i--) {
    l[nums[i]] = i;
}


如何统计元素有没有出现,有没有重复出现?

可以根据上面统计元素出现的次数得知是否有重复出现,或者在原有的数组里面进行信息的丰富。我们可以想办法修改原数组,使得原数组包含每个数是否出现的信息。

例如每个数都是在[1,n]范围内的,那说明每个数都是正数,而且原数组和我们想用的cnt数组的长度时相同的,我们可以想办法修改原数组,使得原数组包含每个数是否出现的信息,比如在遍历至nums[i]时,使nums[nums[i]-1]变为负数,因为nums[i]原来是大于0的,所以在遍历完数组后,nums[i]小于0,说明i+1这个数出现过。

链接
645. 错误的集合
697. 数组的度
448. 找到所有数组中消失的数字
442. 数组中重复的数据
41. 缺失的第一个正数
274. H 指数

数组的改变、移动:

数组的改变和移动主要体现在插入、删除、交换。

处理这一类题目首先要理清题意,并根据题目归路进行思路整理。

链接
453. 最小移动次数使数组元素相等
665. 非递减数列
283. 移动零

二维数组思路整理:

二维数组通常要和图像进行结合,往往很多的解题是和图像挂钩的。我们要通过图像对二维数组元素之间的关系进行分析。

二维数组特定顺序解析:

int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; // 右下左上

二维数组结构储存:

在二维数组中,每个元素都是一个一维数组。有的时候,二维数组的某些元素并不是在整个运算过程中都要用到的。可能只需要用到前一个或前两个一维数组,此时,我们可以用到滚动数组。在滚动数组中,我们用若干个(k)一维数组保存原二维数组中的倒数k个一维数组,并在运算过程中更新这k个一维数组。

二维数组问题解决:

不论是根据图像或者是其他规律,最本质的数学表达式变化要找到,这是解决题目的根本,不管是数组的解决还是其他的算法题解决。

使用额外数组进行辅助解决问题:额外数组的目的是在不方便在原数组上面进行操作时储存信息,其信息的储存能帮助我们对解题思路的理解。

原地算法:二维数组的变换是数组篇中最难的一节,其难度在于如何尽量不用额外空间对二维数组中进行修改、旋转及统计。一般来说,原地算法要求我们在原有的空间(数组)内进行操作,不能额外地新建数组,这就需要我们对数组元素特点进行分析。

链接
118. 杨辉三角
119. 杨辉三角 II
661. 图片平滑器
598. 范围求和 II

419. 甲板上的战舰

54. 螺旋矩阵
59. 螺旋矩阵 II
498. 对角线遍历
566. 重塑矩阵
48. 旋转图像
73. 矩阵置零
289. 生命游戏

前缀和数组


在前缀和数组,第i位存放原数组中前i个元素的和。

前缀和数组有什么用?


前缀和数组一般可用于访问数组的部分和,即第数组中第i到第j个元素的和。有了前缀和数组sum以后,第i到第j个元素的和可以表示位前j个元素的和减前i-1个元素的和,即sum[j]-sum[i-1]。

链接
303. 区域和检索 - 数组不可变
304. 二维区域和检索 - 矩阵不可变
238. 除自身以外数组的乘积

请问您需要的是两个数组的交集元素还是交集元素的数量? 如果是交集元素,可以采用双指针的方式,先将两个数组排序,然后设定两个指针 i 和 j,分别指向两个数组的开头,比较两个指针所指向的元素的大小,如果相等,则说明找到了一个交集元素,将其存到结果数组中;如果不相等,则将指向小的元素的指针向后移动一位,直到其中一个指针越界为止。 代码实现如下: ```c int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){ int i = 0, j = 0, k = 0; int* res = (int*)malloc(sizeof(int) * (nums1Size > nums2Size ? nums2Size : nums1Size)); // 排序 qsort(nums1, nums1Size, sizeof(int), cmp); qsort(nums2, nums2Size, sizeof(int), cmp); while (i < nums1Size && j < nums2Size) { if (nums1[i] == nums2[j]) { res[k++] = nums1[i]; i++; j++; } else if (nums1[i] < nums2[j]) { i++; } else { j++; } } *returnSize = k; return res; } int cmp(const void* a, const void* b) { return *(int*)a - *(int*)b; } ``` 如果是交集元素的数量,可以采用哈希表的方式,用一个哈希表来记录第一个数组中的元素出现的次数,然后遍历第二个数组,在哈希表中查找是否存在相同的元素,如果存在,则说明找到了一个交集元素,将其计数并从哈希表中删除该元素,最后返回计数结果即可。 代码实现如下: ```c int* intersect(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){ int i = 0, j = 0, k = 0; int* res = (int*)malloc(sizeof(int) * (nums1Size > nums2Size ? nums2Size : nums1Size)); int* hash = (int*)malloc(sizeof(int) * 1001); // 由于题目条件限制在 [0, 1000] 范围内,所以哈希表可以开得比较小 memset(hash, 0, sizeof(hash)); for (i = 0; i < nums1Size; i++) { hash[nums1[i]]++; } for (j = 0; j < nums2Size; j++) { if (hash[nums2[j]] > 0) { res[k++] = nums2[j]; hash[nums2[j]]--; } } *returnSize = k; return res; } ``` 希望这些代码能够帮到您,如有疑问请随时问我~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ikkkp

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值