Skip to content

Commit eb8a731

Browse files
committed
把「二分查找」的代码做了重新编排。
1 parent 66e57fb commit eb8a731

File tree

73 files changed

+570
-299
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+570
-299
lines changed

02-Binary-Search/Type-1/0004-median-of-two-sorted-arrays/src/Solution.java

100644100755
File mode changed.

02-Binary-Search/Type-1/0004-median-of-two-sorted-arrays/src/Solution2.java

100644100755
File mode changed.

02-Binary-Search/Type-1/0033-search-in-rotated-sorted-array/src/Solution.java

100644100755
Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,37 @@ public int search(int[] nums, int target) {
1111
int left = 0;
1212
int right = len - 1;
1313
while (left < right) {
14-
// 根据分支的逻辑将中位数改成右中位数
14+
// 根据分支的逻辑将中间数改成上取整
1515
int mid = left + (right - left + 1) / 2;
1616
if (nums[mid] < nums[right]) {
17-
// 先写落在有序数组区间里的情况
17+
// 此时 [mid..right] 有序
1818
if (nums[mid] <= target && target <= nums[right]) {
19+
// 如果 target 的值落在这个区间里,下一轮搜索区间是 [mid..right],此时设置 left = mid;
1920
left = mid;
2021
} else {
22+
// 否则,下一轮搜索区间是 [left..mid - 1],此时设置 right = mid - 1;
2123
right = mid - 1;
2224
}
2325
} else {
24-
// 先写落在有序数组区间里的情况
26+
// 此时 nums[mid] >= nums[right],注意此时 mid 可能与 right 重合
27+
// 数组前半部分有序,即 [left..mid] 有序,为了与上一个分支的逻辑一致,认为 [left..mid - 1] 有序
2528
if (nums[left] <= target && target <= nums[mid - 1]) {
29+
// 如果 target 的值落在区间 [left..mid - 1] 里,设置 right = mid - 1;
2630
right = mid - 1;
2731
} else {
32+
// 否则,下一轮搜索区间是 [mid..right],此时设置 left = mid;
2833
left = mid;
2934
}
35+
36+
// 补充说明:由于中间数上取整,在区间只剩下两个元素的时候,mid 与 right 重合,逻辑走到 else 分支里
37+
// 此时恰好 if 这个分支看到的是 left 和 mid - 1 ,用到的都是 == 号,等价于判断 nums[left] == target
38+
// 因此依然可以缩减区间,注意这里 if 里面的 nums[left] <= target && target <= nums[mid - 1] ,
39+
// 不可以写成 nums[left] <= target && target < nums[mid]
3040
}
3141
}
32-
return nums[left] == target ? left : -1;
42+
if (nums[left] == target) {
43+
return left;
44+
}
45+
return -1;
3346
}
3447
}

02-Binary-Search/Type-1/0033-search-in-rotated-sorted-array/src/Solution4.java

100644100755
File mode changed.

02-Binary-Search/Type-1/0033-search-in-rotated-sorted-array/src/Solution5.java

100644100755
File mode changed.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
public class Solution6 {
2+
3+
public int search(int[] nums, int target) {
4+
int n = nums.length;
5+
if (n == 0) {
6+
return -1;
7+
}
8+
if (n == 1) {
9+
return nums[0] == target ? 0 : -1;
10+
}
11+
12+
// 第一次「二分」:从中间开始找,找到满足 >=nums[0] 的分割点(旋转点)
13+
int l = 0, r = n - 1;
14+
while (l < r) {
15+
int mid = l + r + 1 >> 1;
16+
if (nums[mid] >= nums[0]) {
17+
l = mid;
18+
} else {
19+
r = mid - 1;
20+
}
21+
}
22+
23+
// 第二次「二分」:通过和 nums[0] 进行比较,得知 target 是在旋转点的左边还是右边
24+
if (target >= nums[0]) {
25+
l = 0;
26+
} else {
27+
l = l + 1;
28+
r = n - 1;
29+
}
30+
31+
System.out.println(l);
32+
System.out.println(r);
33+
34+
while (l < r) {
35+
int mid = l + r >> 1;
36+
if (nums[mid] >= target) {
37+
r = mid;
38+
} else {
39+
l = mid + 1;
40+
}
41+
}
42+
return nums[l] == target ? l : -1;
43+
}
44+
45+
public static void main(String[] args) {
46+
Solution6 solution6 = new Solution6();
47+
int[] nums = new int[]{1, 3};
48+
int target = 0;
49+
int res = solution6.search(nums, target);
50+
System.out.println(res);
51+
}
52+
}

02-Binary-Search/Type-1/0034-find-first-and-last-position-of-element-in-sorted-array/src/Solution.java

Lines changed: 30 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -5,52 +5,58 @@ public int[] searchRange(int[] nums, int target) {
55
if (len == 0) {
66
return new int[]{-1, -1};
77
}
8-
98
int firstPosition = searchFirstPosition(nums, target);
109
if (firstPosition == -1) {
1110
return new int[]{-1, -1};
1211
}
13-
14-
// 能走到这里,一定是数组中存在目标元素
12+
// 能走到这里,数组中一定存在目标元素
1513
int lastPosition = searchLastPosition(nums, target);
1614
return new int[]{firstPosition, lastPosition};
1715
}
1816

19-
private int searchLastPosition(int[] nums, int target) {
20-
int left = 0;
21-
int right = nums.length - 1;
22-
while (left < right) {
23-
int mid = (left + right + 1) / 2;
24-
if (nums[mid] > target) {
25-
// mid 以及 mid 的右边一定不是目标元素最后一次出现的位置
26-
// 下一轮搜索的区间是 [left, mid - 1]
27-
right = mid - 1;
28-
} else {
29-
// 下一轮搜索的区间是 [mid, right]
30-
left = mid;
31-
}
32-
}
33-
return left;
34-
}
35-
3617
private int searchFirstPosition(int[] nums, int target) {
3718
int left = 0;
3819
int right = nums.length - 1;
20+
// 在 nums[left..right] 里查找 target 第一次出现的元素
3921
while (left < right) {
4022
int mid = (left + right) / 2;
23+
// int mid = left + (right - left) / 2;
24+
// int mid = (left + right) >>> 1;
4125
if (nums[mid] < target) {
26+
// 小于一定不是解
4227
// mid 以及 mid 的左边一定不是目标元素第 1 次出现的位置
43-
// 下一轮搜索的区间是 [mid + 1, right]
28+
// 下一轮搜索的区间是 [mid + 1..right]
4429
left = mid + 1;
4530
} else {
46-
// 下一轮搜索的区间是 [left, mid]
31+
// 下一轮搜索的区间是 [left..mid]
4732
right = mid;
4833
}
4934
}
50-
35+
// 退出循环以后 left 与 right 重合
5136
if (nums[left] == target) {
5237
return left;
5338
}
5439
return -1;
5540
}
56-
}
41+
42+
private int searchLastPosition(int[] nums, int target) {
43+
int left = 0;
44+
int right = nums.length - 1;
45+
while (left < right) {
46+
int mid = (left + right + 1) / 2;
47+
// int mid = left + (right - left + 1) / 2;
48+
// int mid = (left + right + 1) >>> 1;
49+
if (nums[mid] > target) {
50+
// 大于一定不是解
51+
// mid 以及 mid 的右边一定不是目标元素最后一次出现的位置
52+
// 下一轮搜索的区间是 [left..mid - 1]
53+
right = mid - 1;
54+
} else {
55+
// 下一轮搜索的区间是 [mid..right]
56+
left = mid;
57+
}
58+
}
59+
// 不用做特殊判断,能执行到这个方法,说明数组中一定存在 target
60+
return left;
61+
}
62+
}

02-Binary-Search/Type-1/0034-find-first-and-last-position-of-element-in-sorted-array/src/Solution2.java

Lines changed: 0 additions & 65 deletions
This file was deleted.

02-Binary-Search/Type-1/0034-find-first-and-last-position-of-element-in-sorted-array/src/Solution3.java

Lines changed: 0 additions & 66 deletions
This file was deleted.

02-Binary-Search/Type-1/0035-search-insert-position/src/Solution.java

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,25 @@ public class Solution {
22

33
public int searchInsert(int[] nums, int target) {
44
int len = nums.length;
5-
// 题目没有说输入数组的长度可能为 0,因此需要做特殊判断
6-
if (len == 0) {
7-
return 0;
8-
}
9-
5+
// 特殊判断
106
if (nums[len - 1] < target) {
117
return len;
128
}
9+
// 程序走到这里一定有 target <= nums[len - 1]
1310
int left = 0;
1411
int right = len - 1;
15-
16-
// 在区间 [left, right] 查找插入元素的位置
12+
// 在区间 nums[left..right] 里查找第 1 个大于等于 target 的元素的下标
1713
while (left < right) {
1814
int mid = left + (right - left) / 2;
19-
if (nums[mid] < target){
20-
// 下一轮搜索的区间是 [mid + 1, right]
15+
// 找 >= target 的第 1 个数
16+
if (nums[mid] < target) {
17+
// 下一轮搜索的区间 [mid + 1..right]
2118
left = mid + 1;
2219
} else {
23-
// 下一轮搜索的区间是 [left, mid]
20+
// 下一轮搜索的区间是 [left..mid]
2421
right = mid;
2522
}
2623
}
27-
// 由于程序走到这里 [left, right] 里一定存在插入元素的位置
28-
// 且退出循环的时候一定有 left == right 成立,因此返回 left 或者 right 均可
2924
return left;
3025
}
3126
}

0 commit comments

Comments
 (0)