Skip to content

Commit f901f17

Browse files
committed
add T704,T34,T137,T155
1 parent 0a6d295 commit f901f17

File tree

5 files changed

+270
-12
lines changed

5 files changed

+270
-12
lines changed

基础算法篇/二分搜索.md

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
### 二分搜索
2+
3+
#### 二分搜索模板
4+
5+
给一个**有序数组**和目标值,找第一次/最后一次/任何一次出现的索引,如果没有出现返回-1
6+
7+
模板四点要素
8+
9+
- 1、初始化:start=0、end=len-1
10+
- 2、循环条件:start <= end
11+
- 3、比较中点和目标值:A[mid] ==、 <、> target
12+
- 4、判断最后两个元素是否符合:A[start]、A[end] ? target
13+
14+
时间复杂度 O(logn),使用场景一般是有序数组的查找
15+
16+
##### 704.二分查找 [binary-search](https://leetcode-cn.com/problems/binary-search/)
17+
18+
```js
19+
// 二分搜索最常用模板
20+
var search = function(nums, target) {
21+
let left = 0, mid = 0, right = nums.length-1;
22+
while(left + 1 < right){
23+
mid = left + ((right-left) >> 2);
24+
if(nums[mid] === target){
25+
return mid;
26+
}
27+
if(nums[mid] > target){
28+
right = mid - 1;
29+
} else {
30+
left = mid + 1;
31+
}
32+
}
33+
// 最后剩下两个元素,手动判断
34+
if (nums[left] === target) {
35+
return left;
36+
}
37+
if (nums[right] === target) {
38+
return right;
39+
}
40+
return -1;
41+
};
42+
```
43+
44+
大部分二分查找类的题目都可以用这个模板,然后做一点特殊逻辑即可。
45+
46+
**模板 #1** (left <= right)
47+
48+
二分查找的最基础和最基本的形式。
49+
查找条件可以在不与元素的两侧进行比较的情况下确定(或使用它周围的特定元素)。
50+
不需要后处理,因为每一步中,你都在检查是否找到了元素。如果到达末尾,则知道未找到该元素。
51+
52+
**模板 #2** (left < right)
53+
54+
一种实现二分查找的高级方法。
55+
查找条件需要访问元素的直接右邻居。
56+
使用元素的右邻居来确定是否满足条件,并决定是向左还是向右。
57+
保证查找空间在每一步中至少有 2 个元素。
58+
需要进行后处理。 当你剩下 1 个元素时,循环 / 递归结束。 需要评估剩余元素是否符合条件。
59+
60+
**模板 #3** (left + 1 < right)
61+
62+
实现二分查找的另一种方法。
63+
搜索条件需要访问元素的直接左右邻居。
64+
使用元素的邻居来确定它是向右还是向左。
65+
保证查找空间在每个步骤中至少有 3 个元素。
66+
需要进行后处理。 当剩下 2 个元素时,循环 / 递归结束。 需要评估其余元素是否符合条件。
67+
68+
如果是最简单的二分搜索,不需要找第一个、最后一个位置、或者是没有重复元素,可以使用**模板#1**,代码更简洁:
69+
70+
```js
71+
var search = function(nums, target) {
72+
let start = 0, mid = 0, end = nums.length-1;
73+
while(start <= end){
74+
mid = start + ((start+end)>>2);
75+
if(nums[mid] === target){
76+
return mid;
77+
}
78+
if(nums[mid] > target){
79+
end = mid - 1;
80+
} else {
81+
start = mid + 1;
82+
}
83+
}
84+
return -1;
85+
};
86+
```
87+
88+
JS 用 indexOf 也可以:
89+
90+
```js
91+
var search = function(nums, target) {
92+
return nums.indexOf(target);
93+
};
94+
```
95+
96+
##### 34.在排序数组中查找元素的第一个和最后一个位置 [find-first-and-last-position-of-element-in-sorted-array](https://leetcode-cn.com/problems/find-first-and-last-position-of-element-in-sorted-array/)
97+
98+
给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。
99+
100+
如果数组中不存在目标值 target,返回 [-1, -1]
101+
102+
**进阶:**
103+
104+
- 你可以设计并实现时间复杂度为 `O(log n)` 的算法解决此问题吗?
105+
106+
> 输入:nums = [5,7,7,8,8,10], target = 8
107+
> 输出:[3,4]
108+
109+
```js
110+
var searchRange = function(nums, target) {
111+
if(target<nums[0] || target>nums[nums.length-1]){
112+
return [-1,-1];
113+
}
114+
let res = [-1,-1];
115+
let left = 0, mid = 0, right = nums.length-1;
116+
while(left <= right){
117+
mid = left + ((right-left) >> 1);
118+
if(nums[mid] >= target){
119+
if(mid === 0 || (nums[mid] === target && nums[mid-1]<target)){
120+
res[0] = mid;
121+
break;
122+
}else{
123+
right = mid - 1;
124+
}
125+
}else{
126+
left = mid + 1;
127+
}
128+
}
129+
if(res[0]!==-1 && nums[res[0]]===target){
130+
if(res[0]===nums.length-1){
131+
res[1] = res[0];
132+
} else {
133+
for(let i=res[0]+1;i<nums.length;i++){
134+
if(nums[i] !== target){
135+
res[1] = i-1;
136+
break;
137+
}
138+
if(i===nums.length-1 && nums[i]===target){
139+
res[1] = i;
140+
}
141+
}
142+
}
143+
}
144+
return res;
145+
};
146+
```
147+
148+
```js
149+
var searchRange = function(nums, target) {
150+
return [nums.indexOf(target),nums.lastIndexOf(target)]; //使用内置方法,运行更快
151+
};
152+
```
153+

数据结构篇/二叉树.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
1-
104.二叉树的最大深度[二叉树的最大深度](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/)
1+
### 二叉树
2+
3+
##### 104.二叉树的最大深度[二叉树的最大深度](https://leetcode-cn.com/problems/maximum-depth-of-binary-tree/)
24

35
给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。**说明:** 叶子节点是指没有子节点的节点。
46

57
> 给定二叉树 [3,9,20,null,null,15,7]
68
>
7-
> 3
8-
> / \
9-
> 9 20
10-
> / \
11-
> 15 7
9+
> 3
10+
> / \
11+
> 9 20
12+
> / \
13+
> 15 7
14+
>
1215
> 返回它的最大深度 3 。
1316
1417
```js

数据结构篇/二进制.md

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
### 二进制
2+
3+
JS二进制基础知识: [二进制](https://wangdoc.com/javascript/operators/bit.html)
4+
5+
##### 136.只出现一次的数字 [single-number](https://leetcode-cn.com/problems/single-number/)
6+
7+
给定一个**非空**整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。
8+
9+
> 输入: [2,2,1]
10+
> 输出: 1
11+
>
12+
> 4 ^ 1 ^ 2 ^ 1 ^ 2 = 4
13+
14+
思路:a === a ^ b ^ b
15+
16+
```js
17+
var singleNumber = function(nums) {
18+
let res = 0;
19+
for(let num of nums){
20+
res ^= num;
21+
}
22+
return res;
23+
};
24+
```
25+
26+
##### 137.只出现一次的数字 II [single-number-ii](https://leetcode-cn.com/problems/single-number-ii/)
27+
28+
给定一个**非空**整数数组,除了某个元素只出现一次以外,其余每个元素均出现了三次。找出那个只出现了一次的元素。
29+
30+
> 输入: [2,2,3,2]
31+
> 输出: 3
32+
33+
```js
34+
var singleNumber = function(nums) {
35+
let seenOnce = 0, seenTwice = 0;
36+
for(let num of nums){
37+
seenOnce = ~seenTwice & (seenOnce ^ num);
38+
seenTwice = ~seenOnce & (seenTwice ^ num);
39+
}
40+
return seenOnce;
41+
};
42+
```
43+

数据结构篇/栈和队列.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
### 栈和队列
2+
3+
#### 简介
4+
5+
栈的特点是后入先出,根据这个特点可以临时保存一些数据,之后用到依次再弹出来,常用于 DFS 深度搜索
6+
7+
队列一般常用于 BFS 广度搜索,类似一层一层的搜索。
8+
9+
#### Stack 栈
10+
11+
##### 155.最小栈 [min-stack](https://leetcode-cn.com/problems/min-stack/)
12+
13+
> 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。
14+
15+
思路:用两个栈实现,一个最小栈始终保证最小值在顶部
16+
17+
```js
18+
/**
19+
* initialize your data structure here.
20+
*/
21+
var MinStack = function() {
22+
this.stack = []; // JS用数组表示栈
23+
this.minStack = [Infinity];
24+
};
25+
26+
/**
27+
* @param {number} x
28+
* @return {void}
29+
*/
30+
MinStack.prototype.push = function(x) {
31+
this.stack.push(x);
32+
this.minStack.push(Math.min(this.minStack[this.minStack.length-1],x));
33+
};
34+
35+
/**
36+
* @return {void}
37+
*/
38+
MinStack.prototype.pop = function() {
39+
this.stack.pop();
40+
this.minStack.pop();
41+
};
42+
43+
/**
44+
* @return {number}
45+
*/
46+
MinStack.prototype.top = function() {
47+
return this.stack[this.stack.length-1];
48+
};
49+
50+
/**
51+
* @return {number}
52+
*/
53+
MinStack.prototype.getMin = function() {
54+
return this.minStack[this.minStack.length-1];
55+
};
56+
```
57+

数据结构篇/链表.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
#### 练习
1515

16-
83. 删除排序链表中的重复元素 [remove-duplicates-from-sorted-list](https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/)
16+
##### 83.删除排序链表中的重复元素 [remove-duplicates-from-sorted-list](https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/)
1717

1818
> 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次。
1919
@@ -43,7 +43,7 @@ var deleteDuplicates = function(head) {
4343
};
4444
```
4545

46-
82.删除排序链表中的重复元素Ⅱ(删除重复数字的节点,只保留没有重复数字的节点)[remove-duplicates-from-sorted-list-ii](https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/)
46+
##### 82.删除排序链表中的重复元素Ⅱ(删除重复数字的节点,只保留没有重复数字的节点)[remove-duplicates-from-sorted-list-ii](https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/)
4747

4848
> 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现的数字。
4949
@@ -72,7 +72,7 @@ var deleteDuplicates = function(head) {
7272
};
7373
```
7474

75-
206.反转一个单链表(头插法)。[reverse-linked-list](https://leetcode-cn.com/problems/reverse-linked-list/)
75+
##### 206.反转一个单链表(头插法)。[reverse-linked-list](https://leetcode-cn.com/problems/reverse-linked-list/)
7676

7777
> 输入: 1->2->3->4->5->NULL
7878
> 输出: 5->4->3->2->1->NULL
@@ -91,7 +91,7 @@ var reverseList = function(head) {
9191
};
9292
```
9393

94-
92. 反转链表Ⅱ [reverse-linked-list-ii](https://leetcode-cn.com/problems/reverse-linked-list-ii/)
94+
##### 92.反转链表Ⅱ [reverse-linked-list-ii](https://leetcode-cn.com/problems/reverse-linked-list-ii/)
9595

9696
反转从位置 *m**n* 的链表。请使用一趟扫描完成反转。**说明:**1 ≤ *m**n* ≤ 链表长度。
9797

@@ -117,7 +117,9 @@ var reverseBetween = function(head, m, n) {
117117
};
118118
```
119119

120-
21.合并两个有序链表 [merge-two-sorted-lists](https://leetcode-cn.com/problems/merge-two-sorted-lists/),将两个升序链表合并为一个新的 **升序** 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
120+
##### 21.合并两个有序链表
121+
122+
将两个升序链表合并为一个新的 **升序** 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
121123

122124
> 输入:1->2->4, 1->3->4
123125
> 输出:1->1->2->3->4->4
@@ -159,7 +161,7 @@ var mergeTwoLists = function(l1, l2) {
159161
};
160162
```
161163

162-
86.分隔链表 [分隔链表](https://leetcode-cn.com/problems/partition-list/)
164+
##### 86.分隔链表 [分隔链表](https://leetcode-cn.com/problems/partition-list/)
163165

164166
给定一个链表和一个特定值 *x*,对链表进行分隔,使得所有小于 *x* 的节点都在大于或等于 *x* 的节点之前。你应当保留两个分区中每个节点的初始相对位置。
165167

0 commit comments

Comments
 (0)