分治法:
1. 将问题拆分为几个子问题,并且这些子问题和原问题相似只是量级上小一些。
2. 递归地解决每一个子问题,然后结合这些子问题的解决方案构造出原问题的解决方案。
我们已经遇到过的问题:
1. 二分搜索
2. 归并排序
3. 快速排序
分治法例子:
练习1:快速指数:
能够快速计算出a的n次方
def Fast_pow(a, n): if n == 0: return 1.0 elif n < 0: return 1 / Fast_pow(a, -n) elif n % 2: # 奇数 return Fast_pow(a * a, n // 2) * a else: # 偶数 return Fast_pow(a * a, n // 2) print(Fast_pow(2, 5))
练习2:搜索峰值
数组中没有重复数,但可能存在多个峰值,返回任意一个峰值的index
You may imagine that num[-1] = num[n] = -∞.
def search_peak(alist): return peak_helper(alist, 0, len(alist) - 1) def peak_helper(alist, start, end): if start == end: return start if (start + 1 == end): if alist[start] > alist[end]: return start return end mid = (start + end) // 2 if alist[mid] > alist[mid - 1] and alist[mid] > alist[mid + 1]: return mid if alist[mid - 1] > alist[mid] and alist[mid] > alist[mid + 1]: return peak_helper(alist, start, mid - 1) return peak_helper(alist, mid + 1, end)
alist = [1, 2, 4, 4, 2, 5, 2]
print(search_peak(alist)+1)
练习3: 两数组交集:
给出2个大小不一的数组,找出这两个数组的交集
要求:输出中不能有重复
give nums1 = [1 2 2 1], nums2 = [2, 2], return[2]
def find_extra_fast(arr1, arr2): index = len(arr2) # left and right are end points denoting # the current range. left, right = 0, len(arr2) - 1 while (left <= right): mid = (left + right) // 2; # If middle element is same of both # arrays, it means that extra element # is after mid so we update left to mid+1 if (arr2[mid] == arr1[mid]): left = mid + 1 # If middle element is different of the # arrays, it means that the index we are # searching for is either mid, or before # mid. Hence we update right to mid-1. else: index = mid right = mid - 1; # when right is greater than left our # search is complete. return index
练习4: 计算逆序对
对数组做逆序对计数 - 距离数组的排序结果还有多远。如果一个数组已经排好序,那么逆序对个数为0
在形式上,如果有两个元素a[i], a[j],如果a[i]>a[j],且i<j,那么a[i],a[j]构成一个逆序对
例如序列2,4,1,3,5, 有三个逆序对,分别为(2,1),(4,1),(4,3)
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 left[i] > right[j]: result.append(right[j]) j += 1 inv_count += len(left) - i result += left[i:] result += right[j:] return result, inv_count def count_invert(nums): if len(nums) < 2: return nums, 0 mid = len(nums)//2 left, inv_left = count_invert(nums[:mid]) right, inv_right = count_invert(nums[mid:]) merged, count = merge(left, right) count += (inv_left + inv_right) return merged, count arr = [1, 20, 4, 6, 5] print(count_invert(arr))
原文地址:https://www.cnblogs.com/lvxiaoning/p/11638628.html
时间: 2024-10-09 22:33:44