分治

分治算法

二分查找

问题: 在有序的序列中找数, 找到返回下标, 找不到返回-1.
思路:跟中间数进行比较, 每次序列减半再递归查找.
python code

def part_find(A, n, start_idx):
    if not A:
        return -1

    mid = len(A)//2

    if A[mid] == n:
        return mid+start_idx
    elif A[mid] > n:
        return part_find(A[:mid], n, start_idx)
    elif A[mid] < n:
        return part_find(A[mid+1:], n, start_idx+mid+1)


A = [i for i in range(10)]
idx = part_find(A, 1, 0)
print(idx)

排序

问题: 将无序的序列排成有序.

归并排序

思路: 不断将已有序的子序列合并, 最后得到完全有序的序列.
python code

def merge_sort(A):
    if len(A) <= 1:
        return A
    mid = len(A)//2
    left = merge_sort(A[:mid])
    right = merge_sort(A[mid:])

    def merge(left, right):
        T = []
        while left and right:
            T.append(left.pop(0) if left[0] <= right[0] else right.pop(0))
        while left:
            T.append(left.pop(0))
        while right:
            T.append(right.pop(0))
        return T

    return merge(left, right)


A = [5, 3, 4, 7, 2, 1, 9, 8, 6, 0]
B = merge_sort(A)
print(B)

快速排序

思路: 将序列分成两部分, 一部分的所有数据都比另外一部分的所有数据小, 然后再按此方法对这两部分数据分别进行这种排序方法.
python code

def quick_sort(A):
    if not A:
        return []
    key = A[0]
    lesser = quick_sort([n for n in A if n < key])
    greater = quick_sort([n for n in A if n > key])
    return lesser + [key] + greater

A = [5, 3, 4, 7, 2, 1, 9, 8, 6, 0]
B = quick_sort(A)
print(B)

排列组合

排列数

问题:求出1~N的所有排列情况
思路: 从序列中分离一个数, 和其他位置交换, 递归未分离的序列直到剩下一个数为止.
python code

N = 3
L = [i for i in range(1, N+1)]

def A(cur):
    if cur == len(L)-1:
        print(L)
        return

    for i in range(cur, len(L)):
        L[cur], L[i] = L[i], L[cur]
        A(cur+1)
        L[cur], L[i] = L[i], L[cur]

A(0)

组合数

问题:求出1~N中选取M个的所有组合情况
思路:同排列数, 但不需要交换, 用递减来选出组合数.
python code

N, M = 5, 3
L = [None for i in range(M)]

def C(n, m):
    for i in range(n, m-1, -1):
        L[m-1] = i
        if m > 1:
            C(i-1, m-1)
        else:
            print(L)

C(N, M)

棋盘覆盖

问题: 在一个2^K个方格组成的棋盘中, 有一个方格是特殊方格, 要用三个特殊方格组成的L形状(形状可任意旋转, 数量不限)来覆盖给定棋盘中的所有方格, 不能重叠.
思路: 递归每次分割成4个区域, 确定特殊方块的区域后, 在其余区域放置一个横跨三个区域的L形状.
python code

N, CNT = 4, 0

M = [[0 for j in range(N)] for i in range(N)]

def chess_fill(bx, by, x, y, size):
    if size == 1:
        return

    global CNT
    CNT += 1
    cnt = CNT
    size //= 2
    ex, ey = bx+size, by+size

    # left top area
    if x<ex and y<ey:
        chess_fill(bx, by, x, y, size)
    else:
        M[ex-1][ey-1] = cnt
        chess_fill(bx, by, ex-1, ey-1, size)

    # right top area
    if x>=ex and y<ey:
        chess_fill(ex, by, x, y, size)
    else:
        M[ex][ey-1] = cnt
        chess_fill(ex, by, ex, ey-1, size)

    # left bottom area
    if x<ex and y>=ey:
        chess_fill(bx, ey, x, y, size)
    else:
        M[ex-1][ey] = cnt
        chess_fill(bx, ey, ex-1, ey, size)

    # right bottom area
    if x>=ex and y>=ey:
        chess_fill(ex, ey, x, y, size)
    else:
        M[ex][ey] = cnt
        chess_fill(ex, ey, ex, ey, size)


x, y = 1, 1
chess_fill(0, 0, x, y, N)

for i in range(len(M)):
    for j in range(len(M[i])):
        print(M[i][j], end=' ')
    print()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值