从序列中选择三个数字,使其总和小于一个值

时间:2014-08-21 13:45:11

标签: algorithm

假设我有一系列数字:

  

1,2,3,4,5,2,4,1

我想知道算法可以说 存在多少种可能的方法从上面的序列中选择3个数字,这样它们的总和不会超过7?

我被要求编写一个程序来解决问题。我可以使用任何程序技术吗?

我将非常感谢你的回答!

4 个答案:

答案 0 :(得分:2)

要获得最低的3和,您只需选择最低的3个数字。如果这个数字低于给定的数字 - 你就完成了。否则你可以回答 - 没有这样的解决方案,因为你获得的每一笔金额都大于你刚刚找到的金额,它本身的金额大于所需数字。

如果你想找出"有多少不同的总和,那么数字小于给定的数字",这是一个不同的问题,可以使用Dynamic Programming来解决O(n*number*3) = O(n*number)

f(x,i,3) = (x <+ 0 ? 0 : 1)
f(_,n,_) = 0 //out of bound
f(x,i,used) = f(x-arr[i],i+1, used + 1) + f(x,i+1,used)

使用f(number,0,0)

进行调用

答案 1 :(得分:1)

以下用Python 3.4.1编写的程序提供了一个可以帮助您解决问题的解决方案。

NUMBERS = 1, 2, 3, 4, 5, 2, 4, 1
TARGET = 7
USING = 3

def main():
    candidates = sorted(NUMBERS)[:USING]
    if sum(candidates) <= TARGET:
        print('Your numbers are', candidates)
    else:
        print('Your goal is not possible.')

if __name__ == '__main__':
    main()

修改

根据您想要所有可能解决方案的评论,以下内容提供此信息以及唯一解决方案的数量。如果两个解决方案中的数字相同(无论顺序如何),则认为解决方案与另一解决方案相同。

import itertools

NUMBERS = 1, 2, 3, 4, 5, 2, 4, 1
TARGET = 7
USING = 3

def main():
    # Find all possible solutions.
    solutions = []
    for candidates in itertools.combinations(NUMBERS, USING):
        if sum(candidates) <= TARGET:
            print('Solution:', candidates)
            solutions.append(candidates)
    print('There are', len(solutions), 'solutions to your problem.')
    # Find all unique solutions.
    unique = {tuple(sorted(answer)) for answer in solutions}
    print('However, only', len(unique), 'answers are unique.')
    for answer in sorted(unique):
        print('Unique:', answer)

if __name__ == '__main__':
    main()

答案 2 :(得分:0)

使用递归。 C ++解决方案:

void count(std::vector<int>& arr, int totalTaken, int index, int currentSum, int expectedSum, int *totalSolutions){
        if (index == arr.size()) return;
        if (totalTaken == 3)
            if (currentSum <= expectedSum)
                (*totalSolutions)++;
            else return;
        count(arr, totalTaken++, idex++, curentSum+arr[index],expectedSum, totalSolutions)
        count(arr, totalTaken, index++, currentSum, expectedSum, totalSolutions)
    }

在功能完成后,使用count(your_vector,0,0,0,expectedSum,ptr2int)致电,您的结果将存储在*ptr2int

答案 3 :(得分:0)

使用两个指针技术可以获得O(n ^ 2)时间复杂度:

  1. 对数字进行排序。
  2. 让我们修复中间数字。让我们假设它的索引是中等的。
  3. 对于固定的中间,您可以保持两个指数:低和高。它们对应于总和中的最小和最大数字。最初,低=中 - 1和高=中+ 1。
  4. 现在你可以在一个循环中将高增加1并且只要3个数的总和大于S就减少。对于固定的高和中,低,显示可以添加多少个数到[mid]和a [高]使得它的和是&lt; = S.注意,对于固定的中间,高可以递增O(n)次,而低可以仅递减O(n)次。因此,时间复杂度为O(n ^ 2)。
  5. 此算法仅需要额外的O(1)空间(低,中和高指数)。