Skip to content

Commit 356796e

Browse files
committed
在排序数组中查找数字
1 parent 29d21d8 commit 356796e

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed

在排序数组中查找数字.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# 题目描述
2+
数字在排序数组中出现的次数。
3+
4+
统计一个数字在排序数组中出现的次数。例如输入排序数组{1,2,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4。
5+
6+
# 测试用例
7+
* 功能测试(数组中包含要查找的数字;数组中没有要查找的数字;要查找的数字在数组中出现一次/多次)
8+
* 边界值测试(查找数组中的最大值、最小值;数组中只有一个数字)
9+
* 特殊输入测试(表示数组的指针为空指针)
10+
11+
# 题目考点
12+
* 考察应聘者的只是迁移能力。
13+
* 考察应聘者对二分查找算法的理解程度。
14+
15+
16+
# 解题思路
17+
一看到在排序数组中查找,大家一定能想到二分查找法,但是怎么用可以减少复杂度,that is problem.
18+
19+
1. 利用二分查找法找出最早(左)出现的k的下标
20+
2. 利用二分查找法找出最晚(右)出现的k的下标
21+
22+
# 自己解题
23+
```Java
24+
/**
25+
* 在排序数组中查找数字
26+
* @Author rex
27+
* 2018/9/6
28+
*/
29+
public class Solution {
30+
/**
31+
* 垃圾算法,还是和普通遍历一样的复杂度
32+
* @param array
33+
* @param k
34+
* @return
35+
*/
36+
public int getNumberOfK(int [] array , int k) {
37+
int count = 0;
38+
if (array == null || array.length == 0) {
39+
return count;
40+
}
41+
int index = getNumberOfKCore(array, k, 0, array.length - 1);
42+
int temp = index;
43+
while (temp >=0 && array[temp] == k) {
44+
count++;
45+
temp--;
46+
}
47+
temp = index + 1;
48+
while (temp <= array.length - 1 && array[temp] == k) {
49+
count++;
50+
temp++;
51+
}
52+
return count;
53+
}
54+
55+
/**
56+
* 二分查找
57+
* @param array
58+
* @param k
59+
* @param start
60+
* @param end
61+
* @return
62+
*/
63+
public int getNumberOfKCore(int[] array, int k, int start, int end) {
64+
if (start == end) {
65+
return start;
66+
}
67+
int mid = (start + end) >> 1;
68+
if (array[mid] < k) {
69+
return getNumberOfKCore(array, k, start, mid - 1);
70+
} else if (array[mid] > k){
71+
return getNumberOfKCore(array, k, mid + 1, end);
72+
} else {
73+
return mid;
74+
}
75+
}
76+
}
77+
```
78+
# 参考解题
79+
```Java
80+
/**
81+
* 在排序数组中查找数字
82+
* @Author rex
83+
* 2018/9/6
84+
*/
85+
public class Solution1 {
86+
/**
87+
* 重复利用二分查找
88+
*
89+
* @param array
90+
* @param k
91+
* @return
92+
*/
93+
public int getNumberOfK(int [] array , int k) {
94+
int count = 0;
95+
if (array == null || array.length == 0) {
96+
return count;
97+
}
98+
int first = getFirstK(array, k, 0, array.length - 1);
99+
int last = getLastK(array, k, 0, array.length - 1);
100+
if (first != -1 && last != -1) {
101+
count = last - first + 1;
102+
}
103+
return count;
104+
}
105+
106+
/**
107+
* 找到第一个K的下标
108+
* @param array
109+
* @param k
110+
* @param start
111+
* @param end
112+
* @return
113+
*/
114+
public int getFirstK(int[] array, int k, int start, int end) {
115+
if (start > end) {
116+
return -1;
117+
}
118+
int middleIndex = (start + end) >> 1;
119+
int middleData = array[middleIndex];
120+
if (middleData == k) {
121+
if (middleIndex > 0 && array[middleIndex - 1] < k) {
122+
return middleIndex;
123+
} else {
124+
end = middleIndex - 1;
125+
}
126+
} else if (middleData > k) {
127+
end = middleIndex - 1;
128+
} else {
129+
start = middleIndex + 1;
130+
}
131+
return getFirstK(array, k, start, end);
132+
}
133+
134+
/**
135+
* 找到最后一个K的下标
136+
* @param array
137+
* @param k
138+
* @param start
139+
* @param end
140+
* @return
141+
*/
142+
public int getLastK(int[] array, int k, int start, int end) {
143+
if (start > end) {
144+
return -1;
145+
}
146+
int middleIndex = (start + end) >> 1;
147+
int middleData = array[middleIndex];
148+
if (middleData == k) {
149+
if (middleIndex < array.length - 1 && array[middleIndex + 1] > k) {
150+
return middleIndex;
151+
} else {
152+
start = middleIndex + 1;
153+
}
154+
} else if (middleData < k) {
155+
start = middleIndex + 1;
156+
} else {
157+
end = middleIndex - 1;
158+
}
159+
return getLastK(array, k, start, end);
160+
}
161+
}
162+
```
163+
164+
# 补充
165+
看到排序数组就应该想到二分查找法,但是在判断的时候需要灵活变通。

0 commit comments

Comments
 (0)