Skip to content

Commit b995ea5

Browse files
committed
35
1 parent 7649057 commit b995ea5

File tree

2 files changed

+109
-0
lines changed

2 files changed

+109
-0
lines changed

SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,5 @@
3535
* [32. Longest Valid Parentheses](leetCode-32-Longest-Valid-Parentheses.md)
3636
* [33. Search in Rotated Sorted Array](leetCode-33-Search-in-Rotated-Sorted-Array.md)
3737
* [34. Find First and Last Position of Element in Sorted Array](leetCode-34-Find-First-and-Last-Position-of-Element-in-Sorted-Array.md)
38+
* [35. Search Insert Position](leetCode-35-Search-Insert-Position.md)
3839
* [79. Word Search](leetCode-79-Word-Search.md)

leetCode-35-Search-Insert-Position.md

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# 题目描述(简单难度)
2+
3+
![](https://windliang.oss-cn-beijing.aliyuncs.com/35.jpg)
4+
5+
给定一个有序数组,依旧是二分查找,不同之处是如果没有找到指定数字,需要返回这个数字应该插入的位置。
6+
7+
这道题比较简单,在二分查找的基础上,只要想清楚返回啥就够了。想的话,就考虑最简单的情况如果数组只剩下 2 5,target 是 1, 3, 6 的时候,此时我们应该返回什么就行。
8+
9+
```java
10+
public int searchInsert(int[] nums, int target) {
11+
int start = 0;
12+
int end = nums.length - 1;
13+
if (nums.length == 0) {
14+
return 0;
15+
}
16+
while (start < end) {
17+
int mid = (start + end) / 2;
18+
if (target == nums[mid]) {
19+
return mid;
20+
} else if (target < nums[mid]) {
21+
end = mid;
22+
} else {
23+
start = mid + 1;
24+
}
25+
}
26+
//目标值在不在当前停的位置的前边还是后边
27+
if(target>nums[start]){
28+
return start + 1;
29+
}
30+
//如果小于的话,就返回当前位置,跑步超过第二名还是第二名,所以不用减 1。
31+
else{
32+
return start;
33+
}
34+
}
35+
```
36+
37+
时间复杂度:O(log(n))。
38+
39+
空间复杂度:O(1)。
40+
41+
这道题不难,但是对于二分查找又有了一些新认识。
42+
43+
首先,一定要注意,数组剩下偶数个元素的时候,中点取的是左端点。例如 1 2 3 4,中点取的是 2。正因为如此,我们更新 start 的时候不是直接取 mid ,而是 mid + 1。因为剩下两个元素的时候,mid 和 start 是相同的,如果不进行加 1 会陷入死循环。
44+
45+
然后上边的算法,返回最终值的时候,我们进行了一个 if 的判断,那么能不能避免呢。
46+
47+
* 第一种思路,参考[这里](https://leetcode.com/problems/search-insert-position/discuss/15080/My-8-line-Java-solution)
48+
49+
首先为了让 start 在循环的时候多加 1,我们将循环的 start < end 改为 start <= end。
50+
51+
这样就会出现一个问题,当 start == end,此时 mid 不仅等于了 start 还会等于 end,所以之前更新 end 是直接赋 mid,现在需要改成 end = mid - 1,防止死循环。这样就达到了目标。
52+
53+
```java
54+
public int searchInsert(int[] nums, int target) {
55+
int start = 0;
56+
int end = nums.length - 1;
57+
if (nums.length == 0) {
58+
return 0;
59+
}
60+
while (start <= end) {
61+
int mid = (start + end) / 2;
62+
if (target == nums[mid]) {
63+
return mid;
64+
} else if (target < nums[mid]) {
65+
end = mid - 1;
66+
} else {
67+
start = mid + 1;
68+
}
69+
}
70+
71+
return start;
72+
73+
}
74+
```
75+
76+
77+
* 第二种思路,参考[这里](https://leetcode.com/problems/search-insert-position/discuss/15110/Very-concise-and-efficient-solution-in-Java)
78+
79+
我们开始更新 start 的时候,是 mid + 1,如果剩两个元素,例如 2 4,target = 6 的话,此时 mid = 0,start = mid + 1 = 1,我们返回 start + 1 = 2。如果 mid 是右端点,那么 mid = 1,start = mid + 1 = 2,这样就可以直接返回 start 了,不需要在返回的时候加 1 了。
80+
81+
怎么做到呢?最最开始的时候我们取 end 的时候是 end = nums.length - 1。如果我们改成 end = nums.length,这样每次取元素的时候,如果和之前对比,取到的就是右端点了。这样的话,最后返回的时候就不需要多加 1 了。
82+
83+
```java
84+
public int searchInsert(int[] nums, int target) {
85+
int start = 0;
86+
int end = nums.length;
87+
if (nums.length == 0) {
88+
return 0;
89+
}
90+
while (start < end) {
91+
int mid = (start + end) / 2;
92+
if (target == nums[mid]) {
93+
return mid;
94+
} else if (target < nums[mid]) {
95+
end = mid;
96+
} else {
97+
start = mid + 1;
98+
}
99+
}
100+
101+
return start;
102+
103+
}
104+
```
105+
106+
#
107+
108+
虽然题很简单,但对二分查找有了更多的理解。

0 commit comments

Comments
 (0)