Python求子集和问题

该博客介绍了如何使用Python编程生成一个集合的所有子集,并找出子集和等于特定数值的子集。通过循环和位运算,实现了从列表生成所有可能的子集,以及筛选出和为给定整数的子集。示例中展示了对于集合[5,-2,4,2],分别得到了所有子集和子集和为2、7的情况。
摘要由CSDN通过智能技术生成

习题 子集和问题-1:写出集合A = [5, -2, 4, 2]的所有子集。

1.定义一个函数get_sub(list),传入参数为一个列表list:
def get_subs(list):   # 定义函数,传入一个参数
    res = []   # 用于保存所有的子集
    for i in range(2**len(list)):  # 循环遍历从1到该集合长度的平方的所有整数
        sub = []   # 用于保存一个子集
        for j in range(len(list)):   # 用于移位运算(方便移位的自增)
            if (i >> j) % 2 == 1:  # 移位运算,将二进制位作为传入参数list集合的倒序映射
                sub.append(list[j])     # (7)0111,有1的部位表示子集中list[0]、list[1]、list[2]存在,list[3]不存在
        res.append(sub)  # 调用列表的append()方法将得出的子集添加到结果中
    return res  # 返回结果
2.在主函数中调用该函数:
if __name__ == "__main__":  # 定义主函数
    A = [5, -2, 4, 2]   # 定义一个列表
    list1 = get_subs(A)    # 调用函数求子集和
    print(list1)  # 输出结果
3.最后的结果为:
[[], [5], [-2], [5, -2], [4], [5, 4], [-2, 4], [5, -2, 4], [2], [5, 2], [-2, 2], [5, -2, 2], [4, 2], [5, 4, 2], [-2, 4, 2], [5, -2, 4, 2]]

习题 子集和问题-2:写出集合A = [5, -2, 4, 2]中,子集和等于k(整数)的所有子集的集合。

1.定义一个函数get_sub_equals_sum(items, k),传入参数为一个集合items和一个整数k:
def get_sub_equals_sum(items, k):  # 定义函数,传入两个参数
    result = []    # 用于保存满足条件的子集
    N = len(items)   # 获得传入的集合items的长度
    for i in range(2**N):  # i从0~2的N次方循环(包括0,不包括2的N次方)
        sub = []   # 定义一个列表,用于临时保存每个子集的元素
        for j in range(N):   # 可移位的范围是0~N(包括0,不包括N)
            if(i >> j) % 2 == 1:   #  右移位运算,二进制数最低位为1,则不能被2整除,所以该位置元素存在(右移j位,则在二进制数左边添加j个0,右边去掉j位)
                sub.append(items[j])  # 当集合中对应的下标第j位元素存在,则被添加到sub中形成子集
        if sum(sub) == k:  # 调用sum(iterable)函数求可遍历的sub中所有元素的和(即子集和),若子集和等于k
            result.append(sub)   # 则将该子集添加到结果列表中
    return result   # 返回结果列表
2.在主函数中调用该方法求得结果:
if __name__ == "__main__":  # 定义主函数
    A = [5, -2, 4, 2]   # 定义一个列表
    list2 = get_sub_equals_sum(A, 2)
    list3 = get_sub_equals_sum(A, 7)
    
3.输出结果为:
[[-2, 4], [2]]
[[5, -2, 4], [5, 2]]
  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用回溯算法来解决这个问题。基本思路是从集合X中依次选择每个元素,如果选择了该元素后能够满足要,则加入Y中;否则不加入,并继续选择下一个元素。在整个过程中,需要记录当前已经选择的元素的和以及当前已经选择的元素,当和等于y时,找到了一个满足条件的子集。同时,为了避免重复选择,需要规定每个元素只能选择一次。 以下是Python代码实现: ```python def subset_sum(X, y): n = len(X) chosen = [False] * n res = [] def backtrack(start, sum): if sum == y: res.append([X[i] for i in range(n) if chosen[i]]) return if sum > y or start == n: return for i in range(start, n): if not chosen[i]: chosen[i] = True backtrack(i + 1, sum + X[i]) chosen[i] = False backtrack(0, 0) return res ``` 其中,X表示输入的正整数集合,y表示目标和。chosen数组记录每个元素是否已经被选择,res用于存储满足条件的子集。backtrack函数是回溯的核心部分,其中start表示从哪个位置开始选择元素,sum表示当前已经选择的元素的和。如果sum等于y,则找到了一个满足条件的子集,将其加入res中;否则,如果sum大于y或者start等于n(即所有元素都已经被选择),则回溯到上一层;否则,依次尝试从未被选择的元素中选择一个,并递归调用backtrack函数。 可以通过以下代码测试: ```python X = [1, 2, 3, 4, 5] y = 8 res = subset_sum(X, y) print(res) ``` 输出结果为: ``` [[1, 2, 5], [1, 3, 4], [2, 6], [3, 5]] ``` 表示存在4个满足条件的子集,分别为{1, 2, 5},{1, 3, 4},{2, 6}和{3, 5}。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值