数据结构与算法 | 数组 (Array)
数组(Array)
数组(Array)应该是最基础的数据结构之一,它由相同类型的元素组成的集合,并按照一定的顺序存储在内存中。每个元素都有一个唯一的索引,可以用于访问该元素。
基本概念
数组基本概念 —— 数组索引、数组元素、数组长度
数组索引(Index): 数组中的每个元素都有一个唯一的整数索引,从 0 开始计数。索引用于访问数组中的元素。
数组元素(Element): 数组中的元素必须是相同类型的数据,可以是整数、浮点数、字符、对象等。
数组长度(Length): 数组的长度是指数组中包含的元素数量。
其具备一些性质:
连续存储(Contiguous Memory): 数组中的元素在内存中是连续存储的,这意味着通过索引可以直接计算出元素的地址。
随机访问时间(Constant Time Access): 由于元素的连续存储和索引的存在,通过索引访问数组中的某个元素通常只需要常数时间 O(1)。( PS: 什么叫随机访问? 是计算机领域的一个重要概念,指的是能够以大致相等的时间访问存储介质中的任何数据元素,而不受其物理存储位置顺序的限制。通俗点说,随便获取任意一个元素。)
基本应用(Basic)
数组的结构本身比较简单,在解决常见面试算法问题中灵活应用数组索引来访问数据是关键。
Leetcode 26. 删除有序数组中的重复项【简单】
给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。
LeetCode 674. 最长连续递增序列【简单】
给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。
连续递增的子序列 可以由两个下标 l 和 r(l < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。
双指针(Two Pointers)
一些资料上也有说双指针算法,笔者看来更倾向于是一种技巧,定义的两个索引指针 通过操作两个索引指针来获取问题答案。(PS:为什么这里叫指针?指针更多的是 C 语言中的概念,最早 C 语言解决算法问题比较多。)
根据指针移动 或者 所指位置不同,也有不少其他种分类的说法比如:对撞指针、快慢指针、分离指针等等;但其技巧本质都是在于操作两个指针索引,大可不必严格定义这些名称,需要的是抓住重点操作两个指针。
LeetCode 167. 两数之和 II - 输入有序数组【中等】
给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从数组中找出满足相加之和等于目标数 target 的两个数。如果设这两个数分别是 numbers[index1] 和 numbers[index2] ,则 1 <= index1 < index2 <= numbers.length 。
以长度为 2 的整数数组 [index1, index2] 的形式返回这两个整数的下标 index1 和 index2。你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
LeetCode 15. 三数之和【中等】
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
前缀和(Prefix Sum)
对于一些算法问题直接求解的思路可能计算量比较大,可以思考利用预处理一组特定的中间数据来进求解。类比就如同初中解一些几何题通过几条辅助线的解法,如果回顾学习辅助线的画法,往往先了解常见的画法;对于算法,前缀和就是“常见的辅助线画法”。
针对一些算法问题需要快速计算数组某个连续区间的数值和时,先计算前缀和数组会是一个很好的策略。相关推导如下:
LeetCode 1343. 大小为 K 且平均值大于等于阈值的子数组数目【中等】
给你一个整数数组 arr 和两个整数 k 和 threshold 。请你返回长度为 k 且平均值大于等于 threshold 的子数组数目。
示例 1:输入:arr = [2,2,2,2,5,5,5,8], k = 3, threshold = 4 输出:3 解释:子数组 [2,5,5],[5,5,5] 和 [5,5,8] 的平均值分别为 4,5 和 6 。其他长度为 3 的子数组的平均值都小于 4 (threshold 的值)。
总结下
介绍了数组的基本结构,三个基本概念: 数组索引、数组元素、数组长度;
数组类基础题,关键在于灵活的三个基本概念;
利用操作两个数组索引的编程技巧来解决问题(双指针);
解决算法问题,求解 C,可以先 A->B->C 来进行思考,前缀和就是典型一种示例。
版权声明: 本文为 InfoQ 作者【Java研究者】的原创文章。
原文链接:【http://xie.infoq.cn/article/3e96177d305980a9a545a5e5a】。文章转载请联系作者。
评论