【问题标题】:split a number n as sum of k distinct numbers将数字 n 拆分为 k 个不同数字的总和
【发布时间】:2017-04-22 00:56:29
【问题描述】:

我有一个数字 n,我必须把它分成 k 个数字,这样所有 k 个数字都是不同的,k 个数字的总和等于 n,k 是最大值。例如,如果 n 是 9,那么答案应该是 1,2,6。如果 n 是 15,那么答案应该是 1,2,3,4,5。
这是我尝试过的 -

void findNum(int l, int k, vector<int>& s)
{
    if (k <= 2 * l) {
        s.push_back(k);
        return;
    }
    else if (l == 1) {
        s.push_back(l);
        findNum(l + 1, k - 1, s);
    }
    else if(l == 2) {
        s.push_back(l);
        findNum(l + 2, k - 2, s);
    }
    else{
        s.push_back(l);
        findNum(l + 1, k - l, s);
    }

}

最初 k = n 和 l = 1。结果数字存储在 s 中。该解决方案即使将数字 n 作为 k 个不同数字的总和返回,但它不是最佳解决方案(k 不是最大的)。 n = 15 的示例输出为 1,2,4,8。应该进行哪些更改才能获得正确的结果?

【问题讨论】:

  • 这里有什么问题 - output for n = 15 is 1,2,4,8??
  • @WasiAhmad 8 可以拆分为 5 和 3,结果总数将是 5 而不是 4。
  • 动态规划

标签: c++ algorithm


【解决方案1】:

贪心算法适用于这个问题。只需从 1 开始总结到 m,这样 sum(1...m) &lt;= n。一旦超过,将超出部分添加到m-1。从 1 到 m|m-1 的数字就是答案。

例如。

18
1+2+3+4+5 < 18
+6 = 21 > 18
So, answer: 1+2+3+4+(5+6-(21-18))

28
1+2+3+4+5+6+7 = 28
So, answer: 1+2+3+4+5+6+7

伪代码(恒定时间,复杂度 O(1))

Find k such that, m * (m+1) > 2 * n
Number of terms = m-1
Terms: 1,2,3...m-2,(m-1 + m - (sum(1...m) - n))

【讨论】:

  • 求 k 使得 m * (m+1) > 2 * m?在这一切中,k 在哪里?
  • k 保留其含义,即。没有条款。对于这个等式,k 最终将等于 m-1
【解决方案2】:

如果 min(k)

min(k) = 1 + 2 + .. + k = (k*(k+1))/2

max(k,m) = m + (m-1) + .. + (m-k+1) = k*m - (k*(k-1))/2

所以,你可以使用下面的伪代码:

fn solve(n, k, sum) -> set or error
  s = new_set()
  for m from n down to 1:
    # will the problem be solvable if we add m to s?
    if min(k-1) <= sum-m <= max(k-1, m-1) then
      s.add(m), sum-=m, k-=1
  if s=0 and k=0 then s else error()

【讨论】:

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