简体   繁体   English

给定整数n,返回它可以表示为1和2之和的方式的数量

[英]Given an integer n, return the number of ways it can be represented as a sum of 1s and 2s

For example: 例如:

5 = 1+1+1+1+1

5 = 1+1+1+2

5 = 1+1+2+1

5 = 1+2+1+1

5 = 2+1+1+1


5 = 1+2+2

5 = 2+2+1

5 = 2+1+2

Can anyone give a hint for a pseudo code on how this can be done please. 任何人都可以提供关于如何做到这一点的伪代码的提示。 Honestly have no clue how to even start. 老实说,不知道如何开始。 Also this looks like an exponential problem can it be done in linear time? 这看起来像指数问题可以在线性时间内完成吗?

Thank you. 谢谢。

In the example you have provided order of addends is important. 在示例中,您提供的加数顺序很重要。 (See the last two lines in your example). (请参阅示例中的最后两行)。 With this in mind, the answer seems to be related to Fibonacci numbers. 考虑到这一点,答案似乎与斐波那契数字有关。 Let's F(n) be the ways n can be written as 1s and 2s. F(n)n可以写为1和2的方式。 Then the last addened is either 1 or 2. So F(n) = F(n-1) + F(n-2) . 然后最后加入的是1或2.所以F(n) = F(n-1) + F(n-2) These are the initial values: 这些是初始值:

F(1) = 1 (1 = 1)
F(2) = 2 (2 = 1 + 1, 2 = 2)

This is actually the (n+1)th Fibonacci number. 这实际上是第(n + 1)个斐波纳契数。 Here's why: 原因如下:

Let's call f(n) the number of ways to represent n. 让我们称f(n)表示n的方式的数量。 If you have n, then you can represent it as (n-1)+1 or (n-2)+2. 如果你有n,那么你可以把它表示为(n-1)+1或(n-2)+2。 Thus the ways to represent it are the number of ways to represent it is f(n-1) + f(n-2). 因此,表示它的方式是表示它的方式的数量是f(n-1)+ f(n-2)。 This is the same recurrence as the Fibonacci numbers. 这与Fibonacci数相同。 Furthermore, we see if n=1 then we have 1 way, and if n=2 then we have 2 ways. 此外,我们看到n = 1然后我们有1路,如果n = 2那么我们有2路。 Thus the (n+1)th Fibonacci number is your answer. 因此第(n + 1)个斐波那契数是你的答案。 There are algorithms out there to compute enormous Fibonacci numbers very quickly. 有很多算法可以非常快速地计算出巨大的斐波纳契数。

Permutations 排列

If we want to know how many possible orderings there are in some set of size n without repetition (ie, elements selected are removed from the available pool), the factorial of n (or n! ) gives the answer: 如果我们想要知道有多少可能的排序,那么在一些大小为n的情况下没有重复(即,从可用池中删除所选择的元素), n (或n! )的阶乘给出了答案:

double factorial(int n)
{
    if (n <= 0)
        return 1;
    else
        return n * factorial(n - 1);
}

Note: This also has an iterative solution and can even be approximated using the gamma function: 注意:这也有一个迭代解决方案,甚至可以使用gamma函数进行近似:

std::round(std::tgamma(n + 1)); // where n >= 0

The problem set starts with all 1s . 问题集以全1开始。 Each time the set changes, two 1s are replaced by one 2 . 每次设置更改时,两个1将替换为一个2 We want to find the number of ways k items (the 2s ) can be arranged in a set of size n . 我们想要找到k个项目( 2s )可以在一组大小n中排列的方式的数量。 We can query the number of possible permutations by computing: 我们可以通过计算来查询可能的排列数:

double permutation(int n, int k)
{
    return factorial(n) / factorial(n - k);
}

However, this is not quite the result we want. 但是,这不是我们想要的结果。 The problem is, permutations consider ordering, eg, the sequence 2,2,2 would count as six distinct variations. 问题是,排列考虑排序,例如,序列2,2,2将计为六个不同的变化。

Combinations 组合

These are essentially permutations which ignore ordering. 这些基本上是忽略排序的排列。 Since the order no longer matters, many permutations are redundant. 由于订单不再重要,许多排列都是多余的。 Redundancy per permutation can be found by computing k! 通过计算k可以找到每个排列的冗余 . Dividing the number of permutations by this value gives the number of combinations: 将排列数除以此值可得出组合数:

Note: This is known as the binomial coefficient and should be read as " n choose k ." 注意:这称为二项式系数 ,应理解为“ n选择k”

double combination(int n, int k)
{
    return permutation(n, k) / factorial(k);
}

int solve(int n)
{
    double result = 0;

    if (n > 0) {
        for ( int k = 0; k <= n; k += 1, n -= 1 )
            result += combination(n, k);
    }
    return std::round(result);
}

This is a general solution. 这是一般解决方案。 For example, if the problem were instead to find the number of ways an integer can be represented as a sum of 1s and 3s , we would only need to adjust the decrement of the set size ( n - 2 ) at each iteration. 例如,如果问题是找到整数可以表示为13之和的方式的数量,我们只需要在每次迭代时调整集合大小( n - 2 )的减量。

Fibonacci numbers 斐波纳契数

The reason the solution using Fibonacci numbers works, has to do with their relation to the binomial coefficients. 使用Fibonacci数的解决方案起作用的原因与它们与二项式系数的关系有关。 The binomial coefficients can be arranged to form Pascal's triangle , which when stored as a lower-triangular matrix, can be accessed using n and k as row/column indices to locate the element equal to combination(n,k) . 二项式系数可以被安排成形成Pascal三角形 ,当存储为下三角矩阵时,可以使用nk作为行/列索引来访问该二进制系数,以将该元素定位为等于组合(n,k)

The pattern of n and k as they change over the lifetime of solve , plot a diagonal when viewed as coordinates on a 2-D grid. nk的模式随着它们在求解的生命周期中的变化而变化,当在2-D网格上作为坐标观察时绘制对角线。 The result of summing values along a diagonal of Pascal's triangle is a Fibonacci number. 沿Pascal三角形的对角线求和值的结果是斐波那契数。 If the pattern changes (eg, when finding sums of 1s and 3s ), this will no longer be the case and this solution will fail. 如果模式改变(例如,当找到13的总和时),则不再是这种情况,并且该解决方案将失败。

Interestingly, Fibonacci numbers can be computed in constant time. 有趣的是,Fibonacci数可以在恒定时间内计算。 Which means we can solve this problem in constant time simply by finding the (n+ 1 )th Fibonacci number. 这意味着我们只需找到第(n + 1 )个 Fibonacci数就可以在恒定时间内解决这个问题。

int fibonacci(int n)
{
    constexpr double SQRT_5 = std::sqrt(5.0);
    constexpr double GOLDEN_RATIO = (SQRT_5 + 1.0) / 2.0;

    return std::round(std::pow(GOLDEN_RATIO, n) / SQRT_5);
}

int solve(int n)
{
    if (n > 0)
        return fibonacci(n + 1);
    return 0;
}

As a final note, the numbers generated by both the factorial and fibonacci functions can be extremely large. 最后,由factorialfibonacci函数生成的数字可能非常大。 Therefore, a large-maths library may be needed if n will be large. 因此,如果n很大,则可能需要大型数学库。

Here is the code using backtracking which solves your problem. 这是使用回溯的代码,它可以解决您的问题。 At each step, while remembering the numbers used to get the sum so far(using vectors here), first make a copy of them, first subtract 1 from n and add it to the copy then recur with n-1 and the copy of the vector with 1 added to it and print when n==0. 在每一步,同时记住到目前为止用于获得总和的数字(使用此处的向量),首先制作它们的副本,首先从n中减去1并将其添加到副本然后用n-1和副本重复向量添加1并在n == 0时打印。 then return and repeat the same for 2, which essentially is backtracking. 然后返回并重复2,这基本上是回溯。

#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
int n;
void print(vector<int> vect){
    cout << n <<" = ";
    for(int i=0;i<vect.size(); ++i){
       if(i>0)
           cout <<"+" <<vect[i];
       else cout << vect[i];
    }
    cout << endl;
}

void gen(int n, vector<int> vect){
   if(!n)
      print(vect);
   else{
      for(int i=1;i<=2;++i){
          if(n-i>=0){
              std::vector<int> vect2(vect);
              vect2.push_back(i);
              gen(n-i,vect2);
          }
      }
   }
}

int main(){
   scanf("%d",&n);
   vector<int> vect;
   gen(n,vect);
}

This problem can be easily visualized as follows: 这个问题可以很容易地显示如下:

Consider a frog, that is present in front of a stairway. 考虑一只青蛙,它出现在楼梯前面。 It needs to reach the n-th stair, but he can only jump 1 or 2 steps on the stairway at a time. 它需要到达第n-th楼梯,但他一次只能在楼梯上跳1或2步。 Find the number of ways in which he can reach the n-th stair? 找出他可以到达第n-th楼梯的方式?

Let T(n) denote the number of ways to reach the n-th stair. T(n)表示到达第n-th楼梯的方式的数量。

So, T(1) = 1 and T(2) = 2 (2 one-step jumps or 1 two-step jump, so 2 ways) 所以, T(1) = 1T(2) = 2 (2个一步跳跃或1个两步跳跃,所以2种方式)

In order to reach the n-th stair, we already know the number of ways to reach the (n-1)th stair and the (n-2)th stair. 为了到达第n-th楼梯,我们已经知道到达第(n-1)th楼梯和第(n-2)th楼梯的方式的数量。

So, once can simple reach the n-th stair by a 1-step jump from (n-1)th stair or a 2-step jump from (n-2)th step... 因此,一旦从第(n-1)th阶梯跳过​​一步或从第(n-2)th阶段跳出两步就可以简单地到达第n-th阶梯......

Hence, T(n) = T(n-1) + T(n-2) 因此, T(n) = T(n-1) + T(n-2)

Hope it helps!!! 希望能帮助到你!!!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 计算将整数n分解为4个平方之和的方法数量 - Count the number of ways to decompose integer n into sum of 4 squares 如何检查给定数字是否可以表示为2个偶数的总和? - How to check if a given number can be represented as the sum of 2 even numbers? 2s是补数存储负数的方法吗? - Is 2s complement a way to store negative number? 给定一个 integer,将其表示为 s 平方和 - Given an integer, represent it as s sum of squares 递归 function 查找以 0 开头并具有 0 和 1 的奇数序列的长度为 N 的二进制字符串的数量 - Recursive function that finds the number of binary strings of length N that starts with 0 and have odd sequences of 0s and 1s 在C ++中n位二进制到十进制 - n bit 2s binary to decimal in C++ 为什么我的函数代码中有一个不明确的地方,它计算十进制 n 的二进制表示中的 1 的数量 - Why is there an ambiguous in my code of my function that count the number of 1s in a binary representation of decimal n C/C++ 方法中最快/最短的方法来计算二进制中的数字总和/也就是二进制中的 1 数 - Quickest/Shortest in C/C++ method to calculate sum of digits in binary/aka number of 1s in binary 在随机位置上生成固定数量的1s - Generate a fixed number of 1s on random positions 在 C++ 中将 24 位整数(2s 补码)转换为 32 位整数 - Converting 24 bit integer (2s complement) to 32 bit integer in C++
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM