您最好使用嵌套的for循环/递归。但是,如果您熟悉3SUM问题,则会知道一些技巧来降低此类算法的时间复杂度!如果您有n个范围,则在做出第一个n-1个选择后,您知道必须从第n个范围中选择哪个数字!
我将使用一个示例来说明我的建议。
如果我们的总和为10,我们有一个大小为3的int数组,其中第一个数字可以在1到4之间,第二个数字可以在2到4之间,第三个数字可以在5到6之间。
首先,让我们处理数据使其更易处理。我个人喜欢使用从0开始的范围的想法,而不是任意数字!因此,我们将下限从上限中减去:
(1 to 4) -> (0 to 3)
(2 to 4) -> (0 to 2)
(5 to 6) -> (0 to 1)
当然,现在我们需要调整目标总和以反映新的范围。因此,我们也要从目标总和中减去原始下限!
TargetSum = 10-1-2-5 = 2
现在我们只需要表示上限,因为它们共享一个下限!因此,范围数组将如下所示:
RangeArray = [3,2,1]
让我们先对此进行排序(稍后会更明显为什么)。所以我们有:
RangeArray = [1,2,3]
太好了!现在进入算法的核心...求和!目前我将使用for
循环,因为它更容易用于示例目的。您将需要使用递归。Yeldar的代码应该为您提供一个良好的起点。
result = []
for i from 0 to RangeArray[0]:
SumList = [i]
newSum = TargetSum - i
for j from 0 to RangeArray[1]:
if (newSum-j)>=0 and (newSum-j)<=RangeArray[2] then
finalList = SumList + [j, newSum-j]
result.append(finalList)
请注意内部循环。这是受3SUM算法启发的。我们利用了一个事实,即我们知道必须从第三个范围中选择哪个值(因为它由我们的前两个选择定义)。
从这里开始,当然需要通过将原始下限添加到来自相应范围的值来将结果重新映射回原始范围。
请注意,现在我们明白为什么对于
RangeList
进行排序可能是个好主意。最后一个范围被吸收到倒数第二个范围的循环中。我们希望最大的范围不参与循环。
我希望这可以帮助您入门!如果您需要将我的伪代码翻译成C#,请随时询问 :)