Skip to content

Commit f4e4e24

Browse files
committed
week4 assignment-2 update NOTE.md&T33
1 parent a2f0d59 commit f4e4e24

2 files changed

Lines changed: 82 additions & 49 deletions

File tree

Week04/33.search.js

Lines changed: 67 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -42,39 +42,86 @@
4242
* @param {number} target
4343
* @return {number}
4444
*/
45+
/**@sponge
46+
* 解法一:暴力
47+
* 思路:将给定的数组还原成排序数组,再进行二分查找。
48+
* 但如果单纯用暴力解法还原数组需要从头到尾遍历所以需要O(n)的时间复杂度,可用下面方法简化成O(logn)
49+
* 1.找到第一个无序的位置还原成排序数组,用O(logn)实现,
50+
* 2.再用二分查找O(logn)
51+
* time:O(logn)
52+
* space:O(1)
53+
* runtime:72ms 56%
54+
* memory usage:33.3MB 100%
55+
*/
56+
var search = function (nums, target) {
57+
if (!nums.length) return -1;
58+
59+
let l = 0;
60+
let r = nums.length - 1;
61+
let mid = 0;
62+
//暴力还原排序数组,找到第一个无序的位置(用二分查找实现)
63+
while (l < r) {
64+
mid = Math.floor((l + r) / 2);
65+
if (nums[mid] > nums[r]) {
66+
l = mid + 1;
67+
} else {
68+
r = mid;
69+
}
70+
}
71+
//找到第一个无序的位置,即最小的值
72+
let min = l;
73+
l = 0;
74+
r = nums.length - 1;
75+
//判断target是否在min~r之间
76+
if (target <= nums[r]) l = min;
77+
else r = min - 1;
78+
//按二分查找模板搜索target
79+
while (l <= r) {
80+
mid = Math.floor((l + r) / 2);
81+
if (nums[mid] == target) return mid;
82+
if (nums[mid] < target) l = mid + 1;
83+
else r = mid - 1;
84+
}
85+
return -1;
86+
};
4587

4688
/**@sponge
47-
* 解法一:二分查找
48-
* 根据nums[mid]与nums[l]的关系判断mid在左段还是右段
89+
* 解法二:二分查找
90+
* 根据nums[mid]与nums[r]的关系判断mid在左段还是右段,
91+
* 或者nums[mid]与nums[l]的关系判断mid在左段还是右段
4992
* 再判断target是在mid的左边还是右边
5093
* time:O(logn)
5194
* space:O(1)
95+
* runtime:72ms
96+
* memory usage:33.1MB
5297
*/
53-
var search = function(nums, target) {
98+
var search = function (nums, target) {
99+
if (!nums.length) return -1;
100+
54101
let l = 0;
55-
let r = nums.length-1;
102+
let r = nums.length - 1;
56103

57-
while (l<=r) {
58-
let mid = Math.floor((l+r)/2);
59-
if (target==nums[mid]) return mid;
60-
// 先根据 nums[mid] 与 nums[lo] 的关系判断 mid 是在左段还是右段
61-
if (nums[mid] >= nums[l]) {
62-
// 再判断 target 是在 mid 的左边还是右边,从而调整左右边界 lo 和 hi
63-
if (target >= nums[l] && target < nums[mid]) {
64-
r = mid - 1;
104+
while (l <= r) {
105+
let mid = Math.floor((l + r) / 2);
106+
if (target == nums[mid]) return mid;
107+
// 先根据 nums[mid] 与 nums[r] 的关系判断 mid 是在左段还是右段
108+
if (nums[mid] < nums[r]) {
109+
// 再判断 target 是在 mid 的左边还是右边,从而调整左右边界 l 和 r
110+
// mid ~ r 之间有序
111+
if (target > nums[mid] && target <= nums[r]) {
112+
l = mid + 1;
65113
} else {
66-
l = mid + 1;
114+
r = mid - 1;
67115
}
68116
} else {
69-
if (target > nums[mid] && target <= nums[r]) {
70-
l = mid + 1;
117+
if (target < nums[mid] && target >= nums[l]) {
118+
r = mid - 1;
71119
} else {
72-
r = mid - 1;
120+
l = mid + 1;
73121
}
74-
}
75-
122+
}
123+
76124
}
77125
return -1;
78126
};
79-
// @lc code=end
80-
127+
// @lc code=end

Week04/NOTE.md

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,8 @@ def DFS(self, tree):
111111
一旦一个问题可以通过贪心法来解决,那么贪心法一般是解决这个问题的最好方法。由于贪心法的高效性以及其所求得得答案比较接近最优结果,贪心法也可以用作辅助算法或者直接解决一些结果不那么精确的问题。
112112

113113
- 近似算法
114-
115-
- - 判断近似算法的优劣标准如下:
116-
117-
- - 速度有多快
114+
- 判断近似算法的优劣标准如下:
115+
- 速度有多快
118116
- 得到的近似解与最优解的接近程度
119117

120118
可以用来求图中的最小生成树、哈夫曼编码等。
@@ -133,38 +131,26 @@ def DFS(self, tree):
133131

134132

135133

136-
#### [33. 搜索旋转排序数组](https://leetcode-cn.com/problems/search-in-rotated-sorted-array/)
137-
138-
暴力解法
139-
140-
思路:将给定的数组还原成排序数组,再进行二分查找。
134+
#### **练习:**
141135

142-
但如果单纯用暴力解法还原数组需要从头到尾遍历所以需要O(n)的时间复杂度,可用下面方法简化成O(logn)
136+
使用二分查找,寻找一个半有序数组 [4, 5, 6, 7, 0, 1, 2] 中间无序的地方
137+
**思路:**
143138

144-
1.找到第一个无序的位置还原成排序数组,用O(logn)实现。
145-
146-
2.再用二分查找O(logn)。
139+
- 找到第一个无序的地方,即找到最小的值
147140

148141
```javascript
149-
var search = function(nums, target) {
150-
if(!nums.length) return -1;
151-
142+
var search = function(nums) {
152143
let l = 0;
153144
let r = nums.length - 1;
154-
let mid = 0;
155-
156-
//暴力还原排序数组,即找到第一个无序的位置(用二分查找实现)
157-
while (l<=r) {
145+
let mid = Math.floor((l+r)/2);
146+
while (l < r) {
147+
//如果nums[mid] > nums[r],说明mid~r之间无序,所以l要mid的右边移动继续查找最小值
148+
if (nums[mid] > nums[r]) l=mid+1;
149+
//否则r
150+
else r = mid;
158151
mid = Math.floor((l+r)/2);
159-
if (nums[mid]>nums[mid+1])
160-
break;
161-
if (nums[mid]>=nums[l]) {
162-
l = mid + 1;
163-
}else {
164-
r = mid - 1;
165-
}
166152
}
167-
return -1;
168-
}
153+
return mid;
154+
};
169155
```
170156

0 commit comments

Comments
 (0)