Python 從列表中選取任意個元素求和

2022-09-14 11:03:10 字數 3208 閱讀 4698

碰到乙個比較好玩的問題,我有許多小額的發票,需要從這些發票中湊出乙個指定的整數來。怎麼去實現呢?

這些小額發票,我們可以用乙個列表來表示。比如a = [1, 3, 5, 6, 8]。那麼這個列表的元素可能產生多少種組合呢?由於列表裡面每乙個元素都可能有,也可能沒有。所以這裡面就有2的5次方種變化。**驗證(ps:**參考csdn)。

a = [1, 3, 5, 6, 8]

all_subset =

for i in range(len(a)):

for j in range(len(all_subset)):

print(all_subset)

print(len(all_subset)) # 32

似乎我只需要對上面的二維陣列裡面每乙個元素,即一維陣列求和即可。列表中有5個數,有32種可能性,這麼操作可行。但是,假如是10個數則有1024(2的10次方)種可能性,20個數就有1048576(2的20次方)種可能性,30個數則有1073741824(2的30次方)種可能性。組合的可能性可是指數翻番,電腦根本存不下這麼長的列表。那就得再想其它辦法。

現在的問題是,在沒有這個長列表的情況下,我怎麼去遍歷這些所有組合呢。我們用多層巢狀的方式求解。

a = [1, 3, 5, 6, 8]

ran2 = range(2)

sum = 0

for d0 in ran2:

for d1 in ran2:

for d2 in ran2:

for d3 in ran2:

for d4 in ran2:

data = a[0]*d0 + a[1]*d1 + a[2]*d2 + a[3]*d3 + a[4]*d4

sum += 1

print(sum) # 32

這樣我們就不用存這個長列表,只要把每乙個data跟設定的總數進行對比即可。但是問題又來了,如果給了我30張發票,我要寫30個巢狀迴圈嗎?那畫面簡直無法想象。

我們注意到,列表裡面每個元素,只有兩種狀態,即有和沒有。那麼可以再建立乙個列表,表示狀態,0表示沒有,1表示有。即

a = [1, 3, 5, 6, 8]

coefficient = [0, 0, 0, 0, 0]

這樣就只需要更改coefficient裡面每個元素的狀態即可。為了實現coefficient這個列表各種可能性,我們可以採用把數字轉為二進位制,然後將二進位制數每個數字位分開的方式。

**如下。

a = [1, 3, 5, 6, 8]

for i in range(0, 2**len(a)):

coefficient = list(str(bin(i))[2:].rjust(len(a), '0'))

print(coefficient)

結果如下:

['0', '0', '0', '0', '0']

['0', '0', '0', '0', '1']

['0', '0', '0', '1', '0']

['0', '0', '0', '1', '1']

['0', '0', '1', '0', '0']

....

['1', '1', '1', '1', '0']

['1', '1', '1', '1', '1']

這樣就只需要把列表a和列表coefficient的每個元素相乘累加即可。

最後呈現的**如下,我有29張發票,要求得到的值是180。

#!/usr/bin/env python

# coding=utf-8

import time

from functools import reduce

# 原列表

nums = [1.68, 37.27, 14.78, 12.84, 15.26, 4.86, 10.06, 25.6, 8.42, 20.27,

6.46, 29.68, 6.13, 18.48, 4.98, 7.88, 4.77, 8.61, 5.75, 4.3, 7.76,

3.13, 11.11, 5.1, 2.91, 3.55, 6.45, 55.27, 8.76]

# 期待求和的值

expect_data = 180

# 對陣列進行排序

nums.sort()

# 縮小陣列範圍,將比設定值大的元素拋棄

narrow_nums =

for i in nums:

if i > expect_data:

break

# 把陣列倒序

narrow_nums.sort(reverse=true)

start_time = time.time()

# 開始計算

for i in range(0, 2**len(narrow_nums)):

# 將迴圈的值轉變為引數列表

nums_coefficient = list(str(bin(i))[2:].rjust(len(narrow_nums), '0'))

# 將引數列表和原陣列進行乘積運算得到新的列表

combine_list = list(map(lambda x: x[0] * int(x[1]), zip(narrow_nums, nums_coefficient)))

# 對列表進行求和取值

sumdata = reduce(lambda x, y: x + y, combine_list)

if abs(sumdata - expect_data) < 1e-6:

print(list(filter(lambda x: x > 0, combine_list)))

break

end_time = time.time()

print('運算了{}次,耗時{}'.format(i, round(end_time - start_time, 2)))

以下是結果:

[20.27, 18.48, 14.78, 12.84, 11.11, 10.06, 8.76, 8.61, 8.42, 7.88, 7.76, 6.46, 6.45, 5.75, 5.1, 4.98, 4.86, 4.77, 4.3, 3.55, 3.13, 1.68]

運算了29359101次,耗時591.0

介紹了如何將多層巢狀轉化為一維陣列進行運算

Python文字中選取地點位置

1.固定格式求地點 location str 長沙開區橄欖城小區 data zhuti qumin tq 1 投訴長沙開區橄欖城小區車位違建 徐匯區虹漕路461號58號樓 泉州市洛江區萬安塘西工業區 朝陽區北苑華貿城 import addressparser df addressparser.tra...

從 N 個元素中選取 M 個元素, 有多少種組合

演算法 從 n 個數字中選取 m 個,列印所有可能組合 使用乙個輔助陣列 aux 1.m 用來記錄 input 1.n 中被選中元素的索引 比如 input i 被選中,那麼中會有一項 aux i 從後向前計算 基本思想是,從 n 個元素中選取 m 個,首先選取第 m 個,然後在從剩下的選取 m 1...

BASH 如何從選項列表中選擇

問題 如何提供給使用者選項列表,並且只有在必要的時候,使用者才需要進行選擇 解決方案 使用bash內建的select命令來建立選項列表,使用者通過對應的序號進行選擇。bin bash cookbook filename select dir directorylist finished ls ps3...