【问题标题】:Get the elents whose summ are close to a given number and the number of sum does not exceed the given maximum value [closed]获取总和接近给定数且总和数不超过给定最大值的元素[关闭]
【发布时间】:2021-05-25 05:06:19
【问题描述】:

我有一个完整的整数列表(它没有排序),我有 2 个输入: -input no.1 我想得到的总和 -input no.2 获得总和的最大可用元素数

总和不能高于给定值(输入编号 1),但可以小于 -10。列表中已使用元素的数量可以等于或小于给定值(输入编号 2)。

from random import choice
def Diff(li1, li2):
    return (list(list(set(li1)-set(li2)) + list(set(li2)-set(li1))))



def find_the_elements(current_sum, wanted_sum, used_elements, max_number_of_elements, n_o_elements):
    solution = 0
    while solution != 1:

        elemnt=choice(Diff(elemts, used_elements))
        used_elements.append(elemnt)
        current_sum+=elemnt
        n_o_elements+=1
        if max_number_of_elements<=max_number_of_elements and current_sum in wanted_sum:
            return used_elements
        elif n_o_elements>max_number_of_elements or current_sum>wanted_sum.stop:
            return -1
        else:
            x=find_the_elements(current_sum=current_sum, wanted_sum=wanted_sum, used_elements=used_elements, n_o_elements=n_o_elements, max_number_of_elements=max_number_of_elements)
            if x!=-1:
                return used_elements
            elif x==-1:
                return -1

elemts = [535, 508, 456, 612, 764, 628, 530, 709, 676, 546, 579, 676,
          564, 565, 742, 657, 577, 514, 650, 590, 621, 642, 684, 567, 670, 609, 571, 655, 681, 615, 617, 569, 656, 615,
          542, 711, 777, 763, 663, 657, 532, 630, 636, 445, 495, 567, 603, 598, 629, 651, 608, 653, 669, 603, 655, 622,
          578, 551, 560, 712, 642, 637, 545, 631, 479, 614, 710, 458, 615, 659, 636, 578, 629, 622, 584, 582, 650, 636,
          693, 527, 577, 711, 601, 530, 1028, 683, 589, 590, 670, 409,582, 635, 558, 607, 648, 542, 726, 534, 540, 590, 649, 482, 664, 629, 555, 596, 613, 572, 516, 479, 562, 452,
          586]

max_no_elements = int(input())
wanted_sum = int(input())
solution = -1
while solution == -1:
    solution = find_the_elements(current_sum=0, wanted_sum=range(wanted_sum - 10, wanted_sum + 1), used_elements=[], max_number_of_elements=max_no_elements, n_o_elements=0)
print(solution) 

这是我的解决方案,但我认为我应该采取不同的做法,因为最初我使用的是一个更大的列表,并且列表中的每个元素(整数)都要大 10-20 倍。

【问题讨论】:

标签: python python-3.x list recursion


【解决方案1】:

带有记忆的递归(即动态编程)可能是最好的方法:

def closeSum(A,S,N,p=0,memo=None):
    if not N: return [],0
    if memo is None: memo = dict()          # memoization
    if (S,N,p) in memo: return memo[S,N,p]
    best,bestSum = [],0
    for i,a in enumerate(A[p:],p):  # combine remaining elements for sum
        if a>S: continue            # ignore excessive values
        if a == S: return [a],a     # end on perfect match 
        r   = [a] + closeSum(A,S-a,N-1,i+1,memo)[0] # extend sum to get closer
        sr  = sum(r)
        if sr+10>=S and sr>bestSum: # track best so far
            best,bestSum = r,sr 
    memo[S,N,p]=(best,sum(best))    # memoization
    return best,sum(best)

输出:

elemts = [535, 508, 456, 612, 764, 628, 530, 709, 676, 546, 579, 676,
          564, 565, 742, 657, 577, 514, 650, 590, 621, 642, 684, 567, 670, 609, 571, 655, 681, 615, 617, 569, 656, 615,
          542, 711, 777, 763, 663, 657, 532, 630, 636, 445, 495, 567, 603, 598, 629, 651, 608, 653, 669, 603, 655, 622,
          578, 551, 560, 712, 642, 637, 545, 631, 479, 614, 710, 458, 615, 659, 636, 578, 629, 622, 584, 582, 650, 636,
          693, 527, 577, 711, 601, 530, 1028, 683, 589, 590, 670, 409,582, 635, 558, 607, 648, 542, 726, 534, 540, 590, 649, 482, 664, 629, 555, 596, 613, 572, 516, 479, 562, 452,
          586]

closeSum(elemts,1001,3) 
[456, 545], 1001

closeSum(elemts,5522,7) 
[764, 742, 777, 763, 712, 1028, 726], 5512

closeSum(elemts,5522,10) 
[535, 508, 456, 612, 764, 628, 530, 546, 409, 534], 5522

当存在完全匹配时,它的工作速度相对较快,但如果不匹配,则较大的值/项目计数仍需要一段时间。

请注意,仍有一些优化空间,例如跟踪剩余元素的总数(从位置 p 开始)并在它们加起来不能达到目标总和时退出。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多