算法思想 - Divide and Conquer
- Divide:把问题划分成二到多个子问题
- Conquer: 解决每一个子问题
- Combine: 把每个子问题的解合并成主问题的解
- 适用于问题被划分到足够小的时候非常容易解决的情况
应用举例
多项式相乘
Divide 策略:
如何把 n 次多项式拆分成任务量接近的两个子多项式呢?
A
(
x
)
=
a
0
+
a
1
x
+
a
2
x
2
+
.
.
.
.
+
a
n
x
n
令
:
A
0
(
x
)
=
a
0
+
a
1
x
+
.
.
.
.
+
a
n
−
1
2
x
n
−
1
2
A
1
(
x
)
=
a
n
2
+
.
.
.
+
a
n
x
n
2
则
A
(
x
)
=
A
0
(
x
)
+
A
1
(
x
)
∗
x
n
2
故问题可以改写为
A
(
x
)
B
(
x
)
=
A
0
(
x
)
B
0
(
x
)
+
A
0
(
x
)
B
1
(
x
)
x
n
2
+
A
1
(
x
)
B
0
(
x
)
x
n
2
+
A
1
(
x
)
B
1
(
x
)
=
A
0
(
x
)
B
0
(
x
)
+
(
A
0
(
x
)
B
1
(
x
)
+
A
1
(
x
)
B
0
(
x
)
)
x
n
2
+
A
1
(
x
)
B
1
(
x
)
A(x) = a_0 + a_1x + a_2x^2 + .... + a_nx^n \\ 令: A_0(x) = a_0 + a_1x + .... + a_\frac{n-1}{2}x^\frac{n-1}{2} \\ A_1(x) = a_\frac{n}{2} + ... +a_n x^\frac{n}{2} \\ 则 \space A(x) = A_0(x) + A_1(x) * x^\frac{n}{2} \\ \textbf{故问题可以改写为} \\ A(x)B(x) = A_0(x)B_0(x) + A_0(x)B_1(x)x^\frac{n}{2} + A_1(x)B_0(x)x^\frac{n}{2} + A_1(x)B_1(x) \\ =A_0(x)B_0(x) + (A_0(x)B_1(x) + A_1(x)B_0(x))x^\frac{n}{2} + A_1(x)B_1(x)
A(x)=a0+a1x+a2x2+....+anxn令:A0(x)=a0+a1x+....+a2n−1x2n−1A1(x)=a2n+...+anx2n则 A(x)=A0(x)+A1(x)∗x2n故问题可以改写为A(x)B(x)=A0(x)B0(x)+A0(x)B1(x)x2n+A1(x)B0(x)x2n+A1(x)B1(x)=A0(x)B0(x)+(A0(x)B1(x)+A1(x)B0(x))x2n+A1(x)B1(x)
divide 策略优化:
在上面的步骤中,我们将要进行四次 T(n/2) 的乘法运算,而我们可以观察到
A
0
(
x
)
B
1
(
x
)
+
A
1
(
x
)
B
0
(
x
)
=
(
A
0
(
x
)
+
A
1
(
x
)
)
(
B
0
(
x
)
+
B
1
(
x
)
)
−
A
0
(
x
)
B
0
(
x
)
−
A
1
(
x
)
B
1
(
x
)
A_0(x)B_1(x) + A_1(x)B_0(x) = (A_0(x) + A_1(x))(B_0(x) + B_1(x)) - A_0(x)B_0(x) - A_1(x)B_1(x)
A0(x)B1(x)+A1(x)B0(x)=(A0(x)+A1(x))(B0(x)+B1(x))−A0(x)B0(x)−A1(x)B1(x)
所以只需进行三次 T(n/2) 乘法运算
故整体算法如下:
快速排序
Divide 策略:先花 O(n) 的时间为数组中某一个的元素(可以为队首、队尾、随机元素)找好他应该在的位置,再根据他的位置把数组分为两个部分(一部分都比他小,一部分都比他大)。
以队尾元素为例,其分块算法如下:
// Input A[p....r]
x = A[r];
i = p - 1;
for (j = p; j <= r-1; j++) {
if (A[j] <= x) {
i++;
swap(i, j);
}
}
swap(i+1, r);
return i+1;
图解演示
因为 A[j] < A[r],所以 i++ A[j] 和 A[i] 交换(刚好是它自己)
因为 A[j] > A[r],所以 i 不变 j 继续遍历,A[j] = 7 的时候也同理
因为 A[j] < A[r],所以 i++ 交换 A[i] 和 A[j],也就是把 1 放到前面那个部分去。
所以整体算法
// quicksort(A, p, r)
if p < r:
q = Partition(A, p, r)
quicksort(A, p, q - 1)
quicksort(A, q + 1, r)
end
return A