组合算法笔记2

组合算法笔记1

传送门 => 传送门 =>

三、直观递归

利用直观方式进行递归组合,从左到右,依次选择每个元素

  • 为了避免组合重复,组合结果要按照第一组的前m个元素和后m个元素,即首位元素的遍历范围序号是[1,n-m]
  • 找到首位元素后,其余候选元素的组合即为相同问题的子问题,进而递归
  1. 组合遍历
def testsample(srclist, num):
    if num > 1:
        rlist = []
        for i in range(len(srclist) - num + 1):
            ret = testsample(srclist[i + 1:], num - 1) # 组合剩余元素
            for r in ret:	# 每个剩余元素组合都接上当前选择的元素
                r.insert(0, srclist[i])
            rlist.extend(ret)
        return rlist # 返回当前的所有组合
    else: # 1个元素时每个剩余元素都是一个组合
        return [[i] for i in srclist]

t = testsample([1, 2, 3, 4, 5, 6], 3)

print(t)
for i in t:
    print(i)
  • 缺点:产生的中间list过多,且不够精简
  1. 根据组合元素的扫描顺序,可以将所有的组合遍历共用一个list,减少大量的临时list
def combination(srclist, num) :
    def comb(srclist, num, result):
        for i in range(len(srclist), num - 1, -1):
            result[num - 1] = srclist[i - 1]
            if (num > 1):
                comb(srclist[:i-1], num - 1, result)
            else:
                print(result)
    comb(srclist, num, [0] * num)


combination(srclist, 3)
  • 进阶版,根据python语言特性,优化精简代码
def combination(srclist, num):
    ret = [0] * num
    def comb(srclist, num, ret):
        for i in range(len(srclist) - num + 1):
            ret[-num] = srclist[i]
            if num > 1:
                yield from com(srclist[i + 1:], num - 1, ret)
            else:
                yield list(ret)
    yield from com(srclist, num, ret)

t = test(srclist, 3) # 返回一个生成器对象
for i in t:
    print(i)

# 优化
def combine(src, num):
    ret = [0] * num
    num -= 1    # -1 mark the max combination index

    def comb(index, start):
        '''
        param::index 组合元素预留索引位置
        param::start 源序列元素索引起始点
        '''
        for si in range(start, len(src) + index - num):
            ret[index] = src[si]
            if index < num:
                yield from comb(index + 1, si + 1)
            else:
                yield ret
    yield from comb(0, 0)
  • yieldyield from关键字是python语言的功能,不方便转换成其他语言
def test(srclist, num):
    ret = [0] * num
    def com(srclist, num, ret):
        r = []
        for i in range(len(srclist) - num + 1):
            ret[-num] = srclist[i]
            if num > 1:
                r.extend(com(srclist[i + 1:], num - 1, ret))
            else:
               r.append(list(ret))
        return r
    return com(srclist, num, ret)

t = test(srclist, 3)	# 返回的是list[list]

print(t)
for i in t:
    print(i)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值