分治策略

分治策略

分治法步骤

分治法在每一层递归上都有三个步骤:

分解:将原问题分解为若干个规模较小,相互独立,与原问题形式相同的子问题;

解决:若子问题规模较小而容易被解决则直接解,否则递归地解各个子问题;

合并:将各个子问题的解合并为原问题的解。

分治法:可以看作是二叉树的递归

  1. 全排列

    问题:计算从1,2,…,n的n个数的全排列

    思路:分解:首先从1至n中依次选出一个数,然后对剩余的n-1个数再依次选出一个数,重复上述过程,直到只剩下一个数时,递归结束,这是分的过程。

    合并:对拆分的结果依次跟选出来的某个数进行合并,即可得到一个排列结果。

    def permute(arr):
        if len(arr)==1:
            return [arr]
        res = []
        for i in range(len(arr)):
            num = arr[i]
            rest = arr[:i]+arr[i+1:]
            for rest_permute in permute(rest):
                res.append([num]+rest_permute)
        return res
        
    arr = list(range(1,4))
    res = permute(arr)
    for i in res:
        print(i)   
    

    运行结果:

    [1, 2, 3]
    [1, 3, 2]
    [2, 1, 3]
    [2, 3, 1]
    [3, 1, 2]
    [3, 2, 1]
    
  2. 归并排序

    思路:可以看作是二叉树的后根遍历

    终止条件:当数组中只有一个元素时,遍历终止,并返回数组本身

    如果数组的长度大于1,则从中间将数组拆分成左右两个子数组,可看作是左右子树,拆分到数组的长度小于等于1为止。

    然后对拆分后的左右两个子数组合并,合并时小数字在前,大数字在后

    分解:将数组依次从中间分成左右两半,直到分解成单个元素为止

    合并:依次将分解后的两个数组按照大小合并,最终得到的就是排序后的结果

    def merge(arr1, arr2):
        i, j = 0, 0
        res = []
        while i<len(arr1) and j<len(arr2):
            if arr1[i]<arr2[j]:
                res.append(arr1[i])
                i+=1
            else:
                res.append(arr2[j])
                j+=1
        if i<len(arr1):
            res.extend(arr1[i:])
        if j<len(arr2):
            res.extend(arr2[j:])
        return res
    
    def merge_sort(arr):
        if len(arr)<=1:
            return arr
        l = 0
        r = len(arr)
        m = (l+r)//2
        l_arr = merge_sort(arr[l:m])
        r_arr = merge_sort(arr[m:r])
        res = merge(l_arr, r_arr)
        return res
    import numpy
    arr = numpy.random.randint(0,20,8)
    arr = list(arr)
    # arr = [3,6,2,4,7]
    print(arr)
    arr_sort = merge_sort(arr)
    print(arr_sort)
    
  3. 多数元素

    思路:卡伊看作是二叉树的后根遍历

    递归的结束条件:当数组中只有一个元素的时候,返回该元素

    如果数组的长度大于1, 将数组从中间分成左右两个子数组(即左右子树)

    先调用左子树,再调用右子树

    最后是根节点,当左右子树的多数元素相同时返回,否则分别统计左右子树的多数元素在整个数组中出现的次数,出现次数最多的就是最终得到的多数元素。

    class Solution:
        def majorityElement(self, nums: List[int]) -> int:
            def helper(nums, l, r):
                if l==r:
                    return nums[l]
                mid = (l+r)//2
                left = helper(nums, l, mid)
                right = helper(nums, mid+1, r)
                if left == right:
                    return left 
                left_count = sum([1 for i in range(l,r+1) if nums[i]==left])
                right_count = sum([1 for i in range(l, r+1) if nums[i]==right])
                return left if left_count>right_count else right 
            return helper(nums, 0, len(nums)-1)
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值