数组是数据结构的基本模块之一,因为字符串是由字符数组形成的,所以二者是相似的。
数组简介
-
集合、列表、数组,三者的区别
-
集合的
定义
: 一个或多个确定元素所构成的整体
, 比如商店的东西,或桌面上的物品 -
集合的
特点
:1 集合里的元素类型不一定相同 2 元素没有顺序
-
列表(又称线性列表)的定义:是一种由数据项构成的
有限序列
,按照一定的线性顺序,组成一个数据项的集合 -
列表的特点:1 有顺序 2 长度可变
-
列表可看成是一个购物清单, 1 条目类型可能不同 2 但按照顺序排序 3 长度可变,可往清单里增加、删除条目
-
列表最常见的表现形式有
数组和链表
,特殊的表现形式有栈和队列
-
数组是列表的表现形式之一,在不同的编程语言有一定的差别,比如c++和Java中数组的元素类型必须
保持一致
,Python中则可以不同,Python中的数组叫做List
,有更多高级功能 -
如何
区别
列表和数组? ---有无索引
-
数组中的元素是在内存中是
连续存储
的(javaScript则不连续
,哈希映射
),且每个元素所占内存大小相同
-
-
数组的操作都有哪些
- 读取元素
-
通过索引来读取,一般从0开始,时间复杂度是常数,
O(1)
-
- 查找元素
-
查找数组是否包含某个元素,从数组从开头往后查看,最快的情况数组不包含这个元素,需查n次,n为数组的长度,时间复杂度为
O(n)
-
- 插入元素
-
若在末尾插入,只需通过数组的长度和位置计算出需要插入的内存地址,然后插入到指定位置即可
-
若在中间插入,则部分靠后的元素需要逐个
往后排列
,为腾出空间,再插入
-
- 删除元素
-
删除和插入类似,删除元素会留下一段
空缺
,需要后面的元素进行依次填补
操作
-
- 读取元素
-
寻找数组的中心索引
-
给你一个整数数组 nums,请编写一个能够返回数组 “中心下标” 的方法。
数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。
如果数组不存在中心下标,返回 -1 。如果数组有多个中心下标,应该返回最靠近左边的那一个。
注意:中心下标可能出现在数组的两端。
-
/**
* @param {number[]} nums
* @return {number}
*/
var pivotIndex = function(nums) {
function sum(items) {
if (items.length === 0) {
return 0;
}
return items.reduce((a, b)=> {
return a + b;
})
};
var center = -1;
for(let i = 0; i < nums.length;i++) {
if (sum(nums.slice(0,i)) === sum(nums.slice(i+1))) {
center = i;
break;
}
}
return center;
};
-
搜索插入位置
-
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。
示例 1:
输入: [1,3,5,6], 5 输出: 2 示例 2:
输入: [1,3,5,6], 2 输出: 1
-
/**
* @param {number[]} nums
* @param {number} target
* @return {number}
*/
var searchInsert = function(nums, target) {
if (nums.indexOf(target) !== -1) {
return nums.indexOf(target)
}
const index = nums.findIndex(i => i >= target);
if (index !== -1) {
return index > 0 ? index : 0;
}
return nums.length;
};
-
合并区间
-
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。
以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。
示例 1:
输入:intervals = [[1,3],[2,6],[8,10],[15,18]] 输出:[[1,6],[8,10],[15,18]] 解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]. 示例 2:
输入:intervals = [[1,4],[4,5]] 输出:[[1,5]] 解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。
-
/**
* @param {number[][]} intervals
* @return {number[][]}
*/
var merge = function(intervals) {
intervals.sort((a, b) => a[0] - b[0]);
const items = [intervals[0]];
for (let i = 1; i < intervals.length;i++) {
if (intervals[i][1] <= items[items.length - 1][1]) {
continue;
}
if (intervals[i][0] <= items[items.length - 1][1]) {
items[items.length - 1][1] = intervals[i][1];
} else {
items.push(intervals[i]);
}
}
return items
}
}
二维数组
-
二维数组简介
- 一种结构比较特殊的数组,只是将每个元素变成了一维数组
- 本质上还是一维数组,从索引0开始,可看做是一个矩阵
-
旋转矩阵
-
给你一幅由
N × N
矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。不占用额外内存空间能否做到?
-
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
matrix.map((n, i) => {
matrix.push([]);
let m = n.length;
while (m > 0) {
m--;
matrix[n.length + i].push(matrix[m][i]);
};
});
matrix.splice(0, matrix.length / 2);
-
零矩阵
- 编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零。
输入:
[
[1,1,1],
[1,0,1],
[1,1,1]
]
输出:
[
[1,0,1],
[0,0,0],
[1,0,1]
]
var setZeroes = function(matrix) {
const indexes = [[], []];
matrix.map((n, m) => {
n.map((i, j) => {
if (i === 0) {
if (!indexes[0].includes(m)) {
indexes[0].push(m);
}
if (!indexes[1].includes(j)) {
indexes[1].push(j);
}
}
})
})
indexes[0].map(n => {
matrix[n].fill(0);
});
indexes[1].map(n => {
matrix.map((m ,i) => {
matrix[i][n] = 0;
})
})
};
字符串
-
最长公共前缀
- 编写一个函数来查找字符串数组中的最长公共前缀,如果不存在公共前缀,返回空字符串
""
。
- 编写一个函数来查找字符串数组中的最长公共前缀,如果不存在公共前缀,返回空字符串
输入:strs = ["flower","flow","flight”]
输出:”fl”
输入:strs = ["dog","racecar","car”]
输出:""
解释:输入不存在公共前缀。
var longestCommonPrefix = function(strs) {
let object = [], maxLength = 0;
strs.map((s, t) => {
maxLength = Math.max(s.length, maxLength);
})
for (let i = 0; i < maxLength; i++) {
strs.map(n => {
if (object[i]) {
object[i].push(n[i] || '');
} else {
object[i] = [n[i] || ''];
}
})
};
let str = [];
for (let index = 0; index < object.length;index++) {
if (index !== str.length) {
break;
}
if (object[index].every(m => m === object[index][0])) {
str.push(object[index][0]);
}
}
object = null;
maxLength = null;
return str.join('');
};
-
翻转字符串里的单词
-
给你一个字符串 s ,逐个翻转字符串中的所有 单词 , 单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开, 请你返回一个翻转 s 中单词顺序并用单个空格相连的字符串。
分以下几步:
-
先取出左右两边的空格,防止影响
-
根据多个空格切割成数组
-
利用数组的反转,倒叙
-
切割成字符串
-
-
var reverseWords = function(s) {
s = s.replace(/(^\s+)|(\s+$)/g, '');
return s.split(/\s+/).reverse().join(' ');
};
-
实现strStr
输入: haystack = "hello", needle = "ll"
输出: 2
输入: haystack = "aaaaa", needle = "bba"
输出: -1
// 第一种方法
var strStr = function(haystack, needle) {
let s = -1;
if (!needle) {
return 0;
}
for (let i = 0; i < haystack.length; i++) {
if (haystack[i] === needle[0]) {
if (haystack.slice(i, i + needle.length) === needle) {
s = i;
break;
}
}
}
return s;
};
// 第二种方法
var strStr = function(haystack, needle) {
return haystack.indexOf(needle)
}
双指针技巧
-
数组拆分
- 给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从 1 到 n 的 min(ai, bi) 总和最大,返回该最大总和 。
输入:nums = [1,4,3,2]
输出:4
解释:所有可能的分法(忽略元素顺序)为:
1. (1, 4), (2, 3) -> min(1, 4) + min(2, 3) = 1 + 2 = 3
2. (1, 3), (2, 4) -> min(1, 3) + min(2, 4) = 1 + 2 = 3
3. (1, 2), (3, 4) -> min(1, 2) + min(3, 4) = 1 + 3 = 4
所以最大总和为 4
输入:nums = [6,2,6,5,1,2]
输出:9
解释:最优的分法为 (2, 1), (2, 5), (6, 6). min(2, 1) + min(2, 5) + min(6, 6) = 1 + 2 + 6 = 9
var arrayPairSum = function(nums) {
nums.sort((a, b) => a - b);
let i = 0, j = 1, n = 0;
while(j < nums.length) {
n += Math.min(nums[i], nums[j]);
i += 2;
j += 2;
}
return n;
};