概述
作为一名程序员,对于数组都不陌生,可能第一个学习的数据结构就是它了。它作为一种线性的数据结构,通过索引可以直接获取到它的值,查询任意索引的时间复杂度是O(1), 插入任意位置的时间为O(n), 当然如果插入到其最后一位,那么它的时间复杂度就是O(1)。因此,这么一个看似这么简单的数据结构,当我们在求解某一些算法的过程中体验又如何呢?
对于数组来说,在求解的过程中,大致有两种思路。一种是多指针,最明显的就是快排,尤其像三路快排。另一种思路就是滑动窗口,遇到的最多的是求字符串的子串这种类型。这里说一下,其实抽象的来看,字符串和数组的区别不大,都是线性递增的一种数据结构,因此这里将其归为一类。
那么先来看第一种思路的题解。
leetcode 283. 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。必须在原数组上操作,不能拷贝额外的数组
- 输入 [0,1,0,3,12]
- 输出 [1,3,12,0,0]
对于这道题,我们可以理解为一个指针x初始指向最前面,代表非零元素的临界点, 则[0, x)表示非零元素。[x, len)表示0元素。
那看代码:
1 | const moveZeroes = function(nums) { |
leetcode 26题 给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度。不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
- 输入 [0,0,1,1,1,2,2,3,3,4]
- 输出 5 并且入参数组前5个元素为[0, 1, 2, 3, 4]
对于这道题其实是去重的一个子问题,这是有序的数组去重,我们需要一个指针x指向正确的非重复的元素,即[0, x]表示非重复元素,至于x之后的我们就可以不用在乎。代码如下
1 | const removeDuplicates = function(nums) { |
因此对于随机的数组,可以先用快排排序,之后去重即可删除任意数组的重复元素。
leetcode 215 在未排序的数组中找到第 k 个最大的元素, 请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。你可以假设 k 总是有效的,且 1 ≤ k ≤ 数组的长度。
- 输入 [3,2,1,5,6,4] k = 2
输出 5
对于这道题,就是可以使用快排的思路来解决。
1 | const partition = (left, right, nums) => { |
对于第二种思路的解法:滑动窗口
滑动窗口也是使用两个指针left和right表示一个滑动窗口,窗口未包含需要的子串的时候,增大right指针,直到包含了子串的时候,增大left指针。
leetcode 76. 最小覆盖子串.给你一个字符串 S、一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串。
- 输入 S = “ADOBECODEBANC”, T = “ABC”
- 输出 “BANC”
这道题,我们首先想到的是应该有一个数组记录每个字母的出现的次数,当然还需要一个变量记录当前还需要多少个字符才能包含子串,当该变量为0的时候,此时窗口包含了子串,开始增大左指针。代码如下
1 | var minWindow = function(s, t) { |