Skip to content

Commit e61a987

Browse files
committed
🎨 update: array
1 parent 2b36c5d commit e61a987

16 files changed

+968
-8
lines changed

docs/.vuepress/config.js

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,6 @@ module.exports = {
3535
'/dataStructure/二叉树/树的子结构',
3636
]
3737
},
38-
{
39-
title: '堆',
40-
children: [
41-
'/dataStructure/堆/堆的基本操作',
42-
'/dataStructure/堆/数据流中的中位数',
43-
'/dataStructure/堆/最小的k个数',
44-
]
45-
},
4638
{
4739
title: '链表',
4840
children: [
@@ -57,6 +49,34 @@ module.exports = {
5749
'/dataStructure/链表/删除链表中的节点or重复的节点',
5850
]
5951
},
52+
{
53+
title: '数组',
54+
children: [
55+
'/dataStructure/数组/把数组排成最小的数',
56+
'/dataStructure/数组/第一个只出现一次的字符',
57+
'/dataStructure/数组/调整数组顺序使奇数位于偶数前面',
58+
'/dataStructure/数组/构建乘积数组',
59+
'/dataStructure/数组/和为S的连续正整数序列',
60+
'/dataStructure/数组/和为S的两个数字',
61+
'/dataStructure/数组/连续子数组的最大和',
62+
'/dataStructure/数组/两数之和',
63+
'/dataStructure/数组/扑克牌顺子',
64+
'/dataStructure/数组/三数之和',
65+
'/dataStructure/数组/数组中出现次数超过数组长度一半的数字',
66+
'/dataStructure/数组/数组中的逆序对',
67+
'/dataStructure/数组/顺时针打印矩阵',
68+
'/dataStructure/数组/四数之和',
69+
'/dataStructure/数组/在排序数组中查找数字',
70+
]
71+
},
72+
{
73+
title: '堆',
74+
children: [
75+
'/dataStructure/堆/堆的基本操作',
76+
'/dataStructure/堆/数据流中的中位数',
77+
'/dataStructure/堆/最小的k个数',
78+
]
79+
},
6080
]
6181
}
6282
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
---
2+
{
3+
"title": "三数之和",
4+
}
5+
---
6+
7+
## 题目
8+
9+
给定一个包含 `n` 个整数的数组` nums`,判断 `nums` 中是否存在三个元素` a,b,c` ,使得 `a + b + c = 0 ?`找出所有满足条件且不重复的三元组。
10+
11+
注意:答案中不可以包含重复的三元组。
12+
13+
```js
14+
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
15+
16+
满足要求的三元组集合为:
17+
[
18+
[-1, 0, 1],
19+
[-1, -1, 2]
20+
]
21+
```
22+
23+
## 思路
24+
25+
题目中说明可能会出现多组结果,所以我们要考虑好去重
26+
27+
- 1.为了方便去重,我们首先将数组排序
28+
- 2.对数组进行遍历,取当前遍历的数`nums[i]`为一个基准数,遍历数后面的数组为寻找数组
29+
- 3.在寻找数组中设定两个起点,最左侧的`left`(`i+1`)和最右侧的`right`(`length-1`)
30+
- 4.判断`nums[i] + nums[left] + nums[right]`是否等于0,如果等于0,加入结果,并分别将`left``right`移动一位
31+
- 5.如果结果大于0,将`right`向左移动一位,向结果逼近
32+
- 5.如果结果小于0,将`left`向右移动一位,向结果逼近
33+
34+
注意整个过程中要考虑去重
35+
36+
## 代码
37+
38+
39+
```js
40+
var threeSum = function (nums) {
41+
const result = [];
42+
nums.sort((a, b) => a - b);
43+
for (let i = 0; i < nums.length; i++) {
44+
// 跳过重复数字
45+
if (i && nums[i] === nums[i - 1]) { continue; }
46+
let left = i + 1;
47+
let right = nums.length - 1;
48+
while (left < right) {
49+
const sum = nums[i] + nums[left] + nums[right];
50+
if (sum > 0) {
51+
right--;
52+
} else if (sum < 0) {
53+
left++;
54+
} else {
55+
result.push([nums[i], nums[left++], nums[right--]]);
56+
// 跳过重复数字
57+
while (nums[left] === nums[left - 1]) {
58+
left++;
59+
}
60+
// 跳过重复数字
61+
while (nums[right] === nums[right + 1]) {
62+
right--;
63+
}
64+
}
65+
}
66+
}
67+
return result;
68+
}
69+
```
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
---
2+
{
3+
"title": "两数之和",
4+
}
5+
---
6+
7+
## 题目
8+
9+
10+
给定一个整数数组 `nums` 和一个目标值 `target`,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。
11+
12+
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
13+
14+
示例:
15+
16+
```js
17+
给定 nums = [2, 7, 11, 15], target = 9
18+
19+
因为 nums[0] + nums[1] = 2 + 7 = 9
20+
所以返回 [0, 1]
21+
```
22+
23+
## 思路
24+
25+
使用一个`map`将遍历过的数字存起来,值作为`key`,下标作为值。
26+
27+
对于每一次遍历:
28+
29+
-`map`中查找是否有`key``target-nums[i]`的值
30+
- 如果取到了,则条件成立,返回。
31+
- 如果没有取到,将当前值作为`key`,下标作为值存入`map`
32+
33+
时间复杂度:`O(n)`
34+
35+
空间复杂度`O(n)`
36+
37+
## 代码
38+
39+
```js
40+
var twoSum = function (nums, target) {
41+
const map = {};
42+
if (Array.isArray(nums)) {
43+
for (let i = 0; i < nums.length; i++) {
44+
if (map[target - nums[i]] != undefined) {
45+
return [map[target - nums[i]], i];
46+
} else {
47+
map[nums[i]] = i;
48+
}
49+
}
50+
}
51+
return [];
52+
};
53+
```
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
---
2+
{
3+
"title": "和为S的两个数字",
4+
}
5+
---
6+
7+
## 题目
8+
9+
输入一个递增排序的数组和一个数字`S`,在数组中查找两个数,使得他们的和正好是`S`,如果有多对数字的和等于`S`,输出两个数的乘积最小的。
10+
11+
## 思路
12+
13+
> 数组中可能有多对符合条件的结果,而且要求输出乘积最小的,说明要分布在两侧 比如 `3,8 ` `5,7` 要取`3,8`
14+
15+
看了题目了,很像`leetcode`的第一题【两数之和】,但是题目中有一个明显不同的条件就是数组是有序的,可以使用使用大小指针求解,不断逼近结果,最后取得最终值。
16+
17+
- 设定一个小索引`left`,从`0`开始
18+
- 设定一个大索引`right`,从`array.length`开始
19+
- 判断`array[left] + array[right]`的值`s`是否符合条件
20+
- 符合条件 - 返回
21+
- 大于`sum``right`向左移动
22+
- 小于`sum``left`向右移动
23+
-`left=right`,没有符合条件的结果
24+
25+
> 类似【两数之和】的解法来求解,使用`map`存储另已经遍历过的`key`,这种解法在有多个结果的情况下是有问题的,因为这样优先取得的结果是乘积较大的。例如 `3,8 ` `5,7` ,会优先取到`5,7`
26+
27+
28+
## 代码
29+
30+
```js
31+
function FindNumbersWithSum(array, sum) {
32+
if (array && array.length > 0) {
33+
let left = 0;
34+
let right = array.length - 1;
35+
while (left < right) {
36+
const s = array[left] + array[right];
37+
if (s > sum) {
38+
right--;
39+
} else if (s < sum) {
40+
left++;
41+
} else {
42+
return [array[left], array[right]]
43+
}
44+
}
45+
}
46+
return [];
47+
}
48+
```
49+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
---
2+
{
3+
"title": "和为S的连续正整数序列",
4+
}
5+
---
6+
7+
## 题目
8+
9+
输入一个正数`S`,打印出所有和为S的连续正数序列。
10+
11+
例如:输入`15`,有序`1+2+3+4+5` = `4+5+6` = `7+8` = `15` 所以打印出3个连续序列`1-5``5-6``7-8`
12+
13+
## 思路
14+
15+
- 创建一个容器`child`,用于表示当前的子序列,初始元素为`1,2`
16+
17+
- 记录子序列的开头元素`small`和末尾元素`big`
18+
19+
- `big`向右移动子序列末尾增加一个数 `small`向右移动子序列开头减少一个数
20+
21+
- 当子序列的和大于目标值,`small`向右移动,子序列的和小于目标值,`big`向右移动
22+
23+
## 代码
24+
25+
```js
26+
function FindContinuousSequence(sum) {
27+
const result = [];
28+
const child = [1, 2];
29+
let big = 2;
30+
let small = 1;
31+
let currentSum = 3;
32+
while (big < sum) {
33+
while (currentSum < sum && big < sum) {
34+
child.push(++big);
35+
currentSum += big;
36+
}
37+
while (currentSum > sum && small < big) {
38+
child.shift();
39+
currentSum -= small++;
40+
}
41+
if (currentSum === sum && child.length > 1) {
42+
result.push(child.slice());
43+
child.push(++big);
44+
currentSum += big;
45+
}
46+
}
47+
return result;
48+
}
49+
```
50+
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
---
2+
{
3+
"title": "四数之和",
4+
}
5+
---
6+
7+
## 题目
8+
9+
给定一个包含 `n` 个整数的数组` nums`,判断 `nums` 中是否存在四个元素` a,b,c,d` ,使得 `a + b + c + d = 0 ?`找出所有满足条件且不重复的四元组。
10+
11+
注意:答案中不可以包含重复的四元组。
12+
13+
14+
```js
15+
给定数组 nums = [1, 0, -1, 0, -2, 2],和 target = 0
16+
17+
满足要求的四元组集合为:
18+
[
19+
[-1, 0, 0, 1],
20+
[-2, -1, 1, 2],
21+
[-2, 0, 0, 2]
22+
]
23+
```
24+
25+
## 思路
26+
27+
你已经经历了两数之和、三数之和,玩玩没想到,还有四数之和...
28+
29+
其实,后面还有五数之和,六数之和...
30+
31+
到这里其实我们就能发现一些规律,我们可以像[三数之和](https://github.com/ConardLi/awesome-coding-js/blob/master/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E5%88%86%E7%B1%BB/%E6%95%B0%E7%BB%84/%E4%B8%89%E6%95%B0%E4%B9%8B%E5%92%8C.md)那样,我们可以通过大小指针来逼近结果,从而达到降低一层时间复杂度的效果。
32+
33+
不管是几数之和,我们都用这种方法来进行优化。
34+
35+
## 代码
36+
37+
38+
```js
39+
var fourSum = function (nums, target) {
40+
if (nums.length < 4) {
41+
return [];
42+
}
43+
nums.sort((a, b) => a - b);
44+
const result = [];
45+
for (let i = 0; i < nums.length - 3; i++) {
46+
if (i > 0 && nums[i] === nums[i - 1]) {
47+
continue;
48+
}
49+
if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
50+
break;
51+
}
52+
for (let j = i + 1; j < nums.length - 2; j++) {
53+
if (j > i + 1 && nums[j] === nums[j - 1]) {
54+
continue;
55+
}
56+
let left = j + 1,
57+
right = nums.length - 1;
58+
while (left < right) {
59+
const sum = nums[i] + nums[j] + nums[left] + nums[right];
60+
if (sum === target) {
61+
result.push([nums[i], nums[j], nums[left], nums[right]]);
62+
}
63+
if (sum <= target) {
64+
while (nums[left] === nums[++left]);
65+
} else {
66+
while (nums[right] === nums[--right]);
67+
}
68+
}
69+
}
70+
}
71+
return result;
72+
};
73+
```

0 commit comments

Comments
 (0)