python从数组中找出所有和为M的组合

根据该文算法,改写为python代码《改进,从一个数组中找出 N 个数,其和为 M 的所有可能》

目录

    • 按位运算
    • 按字符串运算

按位运算

import time

def count_1(num):  # 计算二进制数中包含1的个数
    count = 0
    while num:
        if num & 1:  # 按位与运算,末尾为1则个数+1
            count += 1
        num >>= 1    # 按位右移动1,后赋值
    return count

def search(list, count, sum):
    # list待查找数值列表, count要求元素个数, sum待查找的和m
    length = len(list)  # 列表元素个数
    bin = 1 << (length-1)  # 判断二进制数1的位置使用,当前列表最大合适值
    res = []  # 空列表,存放 “和为sum的所有组合” 
    for i in range(1, 1 << length):  # 遍历所有组合(1-2的length次方减1)
        if count_1(i) == count:  # 判断组合内元素数量与count是否一致
            s = 0
            temp = []
            for k in range(0, length):  # 遍历该组合,对应列表
                if i & (bin >> k):  # 或if i & (1 << (length-1-k)):
                    s += list[k]
                    temp.append(list[k])
            if s == sum:
                res.append(temp)  # 将正确的组合嵌套至列表

    return res

#print(search([1,2,3,4], 2, 5))  # 结果[[2, 3], [1, 4]]

if __name__ == '__main__':
    start_time = time.time()
    list_100 = list(range(1,21))  # 1-20的列表
    print(search(list_100, 2, 15))
    end_time = time.time()
    print(end_time - start_time)  # 程序用时,秒

运行结果:
运行十分缓慢,列表每多一个元素,耗时翻一倍
以下为测试用时:

列表范围 组合数 耗时
[1 : 20] 1048576 2.7s
[1 : 21] 2097152 5.7s
[1 : 22] 4194304 12s
[1 : 23] 8388608 25s
[1 : 24] 16777216 52s
[1 : 25] 33554432 109s
[1 : 26] 67108864 227s
[1 : 27] 134217728 472s

按字符串运算

python代码按位运算缓慢,改为遍历组合字符串,运行速度得到明显提升,按理说按位运算速度是最快的,这就是python吗?

import time

def search(list, count, sum):
    # list待查找数值列表, count要求元素个数, sum待查找的和m
    length = len(list)  # 列表元素个数
    res = []  # 空列表,存放 “和为sum的所有组合” 
    bin = '{:0xb}'.replace('x', str(length))  # 二进制高位补0,二进制位数一致
    for i in range(1, 1 << length):  # 遍历所有组合(1-2的length次方减1)
        bin_str = bin.format(i)  # 将数值转为二进制
        if bin_str.count('1') == count:  # 判断组合内元素数量与count是否一致
            s = 0
            temp = []
            for k in range(0, length):  # 左闭右开,遍历该组合,对应列表
                if bin_str[k] == '1':
                    s += list[k]
                    temp.append(list[k])
            if s == sum:
                res.append(temp)  # 将正确的组合嵌套至列表

    return res

#print(search([1,2,3,4], 2, 5))  # 结果[[2, 3], [1, 4]]

if __name__ == '__main__':
    start_time = time.time()
    list_100 = list(range(1,21))  # 1-20的列表
    print(search(list_100, 2, 15))
    end_time = time.time()
    print(end_time - start_time)  # 程序用时,秒

运行结果:运行速度提高了4-5倍

列表范围 原耗时 现耗时
[1 : 20] 2.7s 0.66s
[1 : 21] 5.7s 1.34s
[1 : 22] 12s 2.68s
[1 : 23] 25s 5.36s
[1 : 24] 52s 10.89s
[1 : 25] 109s 22s
[1 : 26] 227s 43.82s
[1 : 27] 472s 87.76s

你可能感兴趣的:(python,python)