仅使用递归将数字从1设置为所选数字

时间:2019-01-06 18:28:08

标签: java recursion

大约连续7个小时后,我确实需要一些帮助,我需要从递归中返回选项数量,该选项可以通过将数字从1设置为所选数字(最大数字)来实现,禁止使用循环/数组,只能递归,数字都是正数(大于0),并且只能正数进行,例如:好:{1,2},坏:{2,1}。

示例:

n = 3 , max = 2 

n:应在行中的数字 ,max:该行中可以包含的最大数量。

{1,1,1}
{1,1,2}
{1,2,2}
{2,2,2}

该示例应返回4,因为存在3个数字的4个选项,其值最大为2。

另一个:

n=2
max=3

{1,1}
{1,2}
{1,3}
{2,2}
{2,3}
{3,3}

在该示例中,它应该返回6,因为有6个选项。

3 个答案:

答案 0 :(得分:1)

一开始很难理解递归,但是一旦知道了,就很容易阅读。缺点是,与基本for循环(Space complexity of recursive function)相比,递归需要更多的空间。对于某些问题,首先编写递归版本然后将其写为for循环会更容易。另外,如果空间不是问题,则有助于使代码整洁(没有for循环!)

我做了一些基本的递归,至少为您写下的两个示例给出了正确的答案。我可能错过了一个极端的案例:也许是写每个函数调用和一些(前卫的)测试案例的好习惯。

public int recursiveWrapper(int n, int max) {
    return recursive(n, max, 1, 1);
}

public int recursive(int n, int max, int lower, int current) {
//        // for your convenience
//        System.out.println("n:" + n + " max:" + max + " lowerbound:" + lower + " current:" + current);

    // Base case
    if (n <= 1 && lower == max) {
        return 1;
    }

    // Recursive step
    // Sequence complete, move to next column
    if (current == max) {
        // Make sure the lower bound does not go beyond the max. number
        int updatedLower = (lower + 1 > max) ?  lower : lower + 1;

        return 1 + recursive(n - 1, max, updatedLower, updatedLower);
    }

    return 1 + recursive(n, max, lower, current + 1);
}

简而言之: 在第二个示例中:

  

n = 2       max = 3

{1,1}
{1,2}
{1,3}
{2,2}
{2,3}
{3,3}

请注意由于规则(从左到右必须等于或大于),因此出现的数字模式: 第二列:1> 2> 3> 2> 3> 3 第一栏:1> 1> 1> 2> 2> 3

递归中的“下限”参数基本上是新的“序列”可以采用的最低编号(每个序列为lower bound -> max number)。然后,基本情况是下限等于上限,并且每一列都完成了所有的“排序”。可能不是很清楚的解释-也许当您看到我复制粘贴的代码中的注释行打印出的内容时会有所帮助。

注意:也许可以使用较少的参数进行递归。确保阅读很多有关递归的内容(例如wikipedia或您的学习手册?)。递归使查找解决方案和理解复杂的抽象问题变得更加容易。

答案 1 :(得分:1)

如果没有先验知识,即使对于有经验的数学家来说,这也可能是一个具有挑战性的问题。它是multisets的计数,它是组合学的基本组成部分之一。我将解释我对Wikipedia中的递归关系的想法的理解。

通常k用于多集基数(您的问题称为n),而n用作集合的基数(不是multiset < / em>)(您问题中的max)中进行选择。

对于f(n, k),基本情况是:

f(n, 0) = 1
one way to fill the empty multiset

然后

f(0, k) = 0
no ways to choose from an empty set

对于常规情况,我们考虑第n个元素(来自选择集)。我们想计算包含它的所有组合以及所有缺少它的组合。对没有第n个元素的所有组合进行计数很容易:我们将相同的多集计数功能应用于k,但选择较少:

f(n - 1, k)

现在要计算至少包含第n个元素的组合,我们设想采取所有方式从n个项目中进行选择(其中某些项目将不包含第n个项目元素),但在每个组合中保留一个位置,我们将在第n个元素中放置一个元素,因此最终得到:

f(n, k - 1)

将它们放在一起:

function f(n, k){
  if (n == 0)
    return 0;
  if (k == 0)
    return 1;

  return f(n - 1, k) + f(n, k - 1);
}

console.log(f(2, 3));
console.log(f(3, 2));

答案 2 :(得分:0)

由于时间的关系,我编写了一些效率较低的代码,请尝试看一下,我希望它会给你dir

package com.exercise;

import java.util.Arrays;

public class Permutation {

public static void permutation(String str) {
    permutation("", str);
}

private static void permutation(String prefix, String str) {
    int n = str.length();
    if (n == 0)
        System.out.println(prefix);
    else {
        for (int i = 0; i < n; i++)
            permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i + 1, n));
    }
}

private static void permutationOnInt(String prefix, String str, int max) {

    int n = str.length();

    if (n == 0)
        System.out.println(prefix);
    else {
        for (int i = 0; i <= n; i++)
            permutation(prefix + str.charAt(i), str.substring(0, i) + str.substring(i + 1, n));
    }
}

public static int[] return_Array(int length) {
    int[] a = new int[length];
    for (int i = 0; i < length; i++) {
        a[i] = i + 1;
    }
    return a;

}

public static void main(String[] args) {
    String fn = Arrays.toString(return_Array(3));
    String apple = String.join(",", fn.replace("[", "").replace("]", "").replace(",", "").replaceAll("\\s+", ""));
    permutationOnInt("", apple, 3);
}
}

获得结果后,可以将其转换回数组。 重要:此代码完全未优化。我将在以后发布优化