分治算法目录
目录
分治算法目录一、分治算法是什么?二、实现步骤1.二分法2.递归3.合并排序,归并排序等...
三、使用要求四、练习1.指数练习:2.查找任意一个峰值:3.查找所有峰值:4.数组集合:5.计算逆序对:
总结
一、分治算法是什么?
分治算法,就两个字:分和治。 分:通过一些规律把一个大问题分成若干小问题 治:把这些小问题以此解决,然后返回结果
举个例子:计算1-100的和,在没有求和公式的情况下都会从1+2+3+…+99+100。通过发现得到1+100=2+99=3+98…=49+ 50,而这些我们就相当于把这个大问题换成了若干小问题。
二、实现步骤
1.二分法
上一篇提到的二分搜索其实就是实现分治算法的一种,可以说二分搜索是分治算法的一个子集;二分法的使用
2.递归
使用分治法最多的还是使用递归来解决问题。附上一篇关于递归的文章:递归讲解
3.合并排序,归并排序等…
三、使用要求
该问题的规模缩小到一定的程度就可以容易地解决
该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质。
利用该问题分解出的子问题的解可以合并为该问题的解;
该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
四、练习
1.指数练习:
利用递归解决指数问题
def pow(x
, n
):
if n
<= 0:
return 1
elif n
== 1:
return x
elif n
% 2:
return pow(x
* x
, n
// 2) * x
else:
return pow(x
* x
, n
// 2)
print(pow(5, 25))
2.查找任意一个峰值:
在一个数组中可能有多个峰值,请任意找一个并返回下标
def search(listt
):
return num
(listt
, 0, len(listt
) - 1)
def num(listt
, start
, end
):
if start
== end
:
return start
elif start
+ 1 == end
:
if listt
[start
] > listt
[end
]:
return start
else:
return end
mid
= (start
+ end
) // 2
if listt
[mid
- 1] < listt
[mid
] < listt
[mid
+ 1]:
return num
(listt
, mid
+ 1, end
)
elif listt
[mid
+ 1] < listt
[mid
] < listt
[mid
- 1]:
return num
(listt
, start
, mid
- 1)
elif listt
[mid
] > listt
[mid
- 1] and listt
[mid
] > listt
[mid
+ 1]:
return mid
n
= [0, 1, 9, 2, 3, 4, 8, 7, 5, 11, 6, 20, 23, 21]
print(search
(n
))
3.查找所有峰值:
def search(nums
):
i
= 1
index
= []
while i
< len(nums
):
if nums
[i
- 1] < nums
[i
]and nums
[i
] > nums
[i
+ 1]:
index
.append
(i
)
i
+= 1
return index
n
= [0, 1, 9, 2, 3, 4, 8, 7, 5, 11, 6, 20, 23, 21]
print(search
(n
))
4.数组集合:
两个长短不一的数组找集合,可能会有重复的数字,将他们全部输出
def search(nums1
, nums2
):
index
= []
i
, j
= 0, 0
while True:
if nums2
[j
] == nums1
[i
]:
index
.append
(nums2
[j
])
i
+= 1
j
+= 1
else:
i
+= 1
if i
== len(nums1
) - 1 or j
== len(nums2
) - 1:
break
return index
nums1
= [1, 2, 2, 2, 1]
nums2
= [2, 2, 3]
nums1
.sort
()
nums2
.sort
()
print(search
(nums1
, nums2
))
5.计算逆序对:
在一个无序数组中 a[i]>a[j] 且 i<j 这两个数就是一个逆序对
def merge(left
, right
):
result
= list()
i
, j
= 0, 0
inv_count
= 0
while i
< len(left
) and j
< len(right
):
if left
[i
] < right
[j
]:
result
.append
(left
[i
])
i
+= 1
elif right
[j
] < left
[i
]:
result
.append
(right
[j
])
j
+= 1
inv_count
+= (len(left
)-i
)
result
+= left
[i
:]
result
+= right
[j
:]
return result
, inv_count
def conut(nums
):
if len(nums
) < 2:
return nums
, 0
mid
= len(nums
) // 2
left
, inv_left
= conut
(nums
[:mid
])
right
, inv_right
= conut
(nums
[mid
:])
merged
, counts
= merge
(left
, right
)
counts
+= (inv_left
+ inv_right
)
return merged
, counts
nums
= [1, 20, 3, 5, 4]
print(conut
(nums
))
总结
提示:这里对文章进行总结:分治法作为三大算法之一,必有它的难点和独特之处。拿到题时多加思考和分析,理解+勤练习。