数据结构与算法6 - 分治法(上)

Posted lvxiaoning

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数据结构与算法6 - 分治法(上)相关的知识,希望对你有一定的参考价值。

分治法:

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))

 

以上是关于数据结构与算法6 - 分治法(上)的主要内容,如果未能解决你的问题,请参考以下文章

数据结构与算法--分治法归并排序

数据结构与算法--分治法归并排序

数据结构与算法--分治法归并排序

递归与分治法

数据结构与算法分析——分治法

高效(初级算法)大纲