二分法思想及其时间复杂度的求解
先说二分法使用条件
1.有序数组
2.从某种角度看是有序数组
二分法算法思想
(从小到大的有序)每次将有序数组对半,取出中间索引的值与目标值进行判断
若相等,直接输出中间索引
若目标比中间值大,那一定位于右区间,起始索引的值变成中间索引+1,结束索引不变
若目标比中间值小,那一定位于左区间,起始索引的值不变,结束索引成中间索引-1
重复
结束条件,找到元素,直接return,没找到起始索引会大于结束索引
二分法算法代码实现
public int binarySearch(int[] nums, int key) {
int l = 0, h = nums.length - 1;
while (l <= h) {
int m = l + (h - l) / 2; //起始索引+(总数)/2
if (nums[m] == key) {
return m;
} else if (nums[m] > key) {
h = m - 1;
} else {
l = m + 1;
}
}
return -1;
}
二分法的时间复杂度的求解
1.找 (语句执行次数最多的那条语句,一般为最内循环体中的语句)基本操作
在二分法中while()循环体为最内循环,基本操作为int m = l + (h - l) / 2;
2.确定 (即1中的基本操作执行的次数与什么有关)问题规模n
在二分法中基本操作 int m = l + (h - l) /2;的执行次数与循环判断条件l<=h有关,即与h有关。
h就是问题规模。h确定以后,循环的结束还与l有关,用来总结执行次数函数f(n)表达式。
3.定 执行次数函数f(n)表达式,假定执行次数Q,那么Q与问题规模n有关,就是函数Q=f(n)
当算法先执行1次时 ,总执行次数表达式为:
f
(
h
)
=
1
+
f
(
l
+
(
h
−
1
)
/
2
)
f(h)=1+f(l+(h-1)/2)
f(h)=1+f(l+(h−1)/2)
当算法先执行2次时,总执行次数表达式为:
f
(
h
)
=
2
+
f
(
[
l
+
(
h
−
1
)
/
2
−
l
]
/
2
+
l
)
f(h)=2+f([l+(h-1)/2-l]/2+l)
f(h)=2+f([l+(h−1)/2−l]/2+l)
=
2
+
f
(
(
h
−
l
)
/
2
2
+
l
)
=2+f((h-l)/2^2+l)
=2+f((h−l)/22+l)
当算法先执行3次时,总执行次数表达式为:
f
(
h
)
=
3
+
f
(
[
(
h
−
l
)
/
2
2
+
l
−
l
]
/
2
+
l
)
f(h)=3+f([(h-l)/2^2+l-l]/2+l)
f(h)=3+f([(h−l)/22+l−l]/2+l)
=
3
+
f
(
(
h
−
l
)
/
2
3
+
l
)
=3+f((h-l)/2^3+l)
=3+f((h−l)/23+l)
…
当算法先执行i次时,总执行次数表达式为:
f
(
h
)
=
i
+
f
(
(
h
−
l
)
/
2
i
+
l
)
f(h)=i+f((h-l)/2^i+l)
f(h)=i+f((h−l)/2i+l)
时间复杂度O(n),n是问题规模,O(n)等于总执行次数f(n)中的n最高次幂前系数置1.
e
g
:
f
(
n
)
=
5
n
2
+
n
+
9
eg: f(n)=5n^2+n+9
eg:f(n)=5n2+n+9
O
(
n
)
=
n
2
O(n)=n^2
O(n)=n2
因为O(n)与只跟n有关,将l看成常数
f
(
h
)
=
i
+
f
(
(
h
)
/
2
i
)
f(h)=i+f((h)/2^i)
f(h)=i+f((h)/2i)
h可以表示为
h
=
2
i
+
k
h=2^i+k
h=2i+k(k为常数),所以
f
(
h
)
=
i
+
f
(
(
2
i
+
k
)
/
2
i
)
f(h)=i+f((2^i+k)/2^i)
f(h)=i+f((2i+k)/2i)
f
(
h
)
=
i
+
f
(
1
+
k
/
2
i
)
f(h)=i+f(1+k/2^i)
f(h)=i+f(1+k/2i)
将i转换成h的形式,取对数
log
2
h
=
i
+
K
\log_2h=i+K
log2h=i+K
带入
f
(
h
)
=
log
2
h
f(h)=\log_2h
f(h)=log2h
(所有常数忽略了,反正最后都不要)所以
O
(
n
)
=
log
2
n
O(n)=\log_2n
O(n)=log2n