递归 - 如果java中有数字的连续性

时间:2016-06-11 08:10:53

标签: java recursion

我有一个练习,我得到一个错误,并希望帮助解决错误以及如何解决锻炼。

  

编写一个递归函数,接收一组数字和一个数字   在9-1之间。如果存在连续性,则该函数返回true   数字从1到数字,否则返回false。

它总是让我真实,没有错误。

  

示例:

     

对于数组3,1,2,3,4,6,3,数字4将返回true

     

对于数组3,1,2,1,2,3,5,数字4将返回false

代码:

public static boolean continuityOfnumbers(int[] arr, int n) {
    int counter = 0;
    int index = arr.length - 1;

    if (n == 0)
            return true;

    if (arr[index] - 1 == arr[index - 1])
        counter += 1;

    index--;

    return continuityOfnumbers(arr, n - 1);
}

3 个答案:

答案 0 :(得分:0)

您的示例代码始终返回true,因为这是它返回的唯一值。基本上,您的方法会使用n-1递归调用自己,直到n = 0return true

您需要将问题分成以下子问题:

数字n的连续性意味着

  1. 号码n-1
  2. 的连续性
  3. n包含在数组
  4. public static boolean continuityOfnumbers(Integer[] arr, int n) {
        if (n == 0)
            return true;
        return continuityOfnumbers(arr, n - 1) && contains(arr, n);
    }
    
    private static boolean contains(Integer[] arr, Integer n) {
        return Arrays.asList(arr).contains(n);
    }
    

    我使用Integer []而不是int []只是在一行中编写 contains 部分。这是关于代码简单性,而不是效率。它是关于如何以简单的方式使用递归。

    但是,如果您的问题需要数字1-n,则这不是正确的解决方案。

答案 1 :(得分:0)

这是O(n)运行时和存储复杂性解决方案。它生成一个布尔连续性数组并检查它和递归的结束。

不要只是复制粘贴它,请确保阅读代码中的注释以查看逻辑是什么,并确保您理解它。

它还进行了一些预验证检查,以确保在进行递归之前,n实际上是在数组中包含和可访问的。

private static boolean continuityOfnumbers(int[] arr, int n) {
    // Max sure we can reach N
    if (n >= arr.length) return false;

    // Make sure N is in the array
    boolean findN = false;
    // Also find the max value in the array
    int max = Integer.MIN_VALUE;
    for (int x : arr) {
        if (x == n) findN = true;
        if (max < x) max = x;
    }
    // If N is not found or we still cant reach N, return false
    if (!findN || n > max) return false;

    // Build a continuity array of all false
    boolean[] contArr = new boolean[n];

    // Start recursion
    return continuityOfnumbers(arr, n, contArr, 0);
}

private static boolean continuityOfnumbers(int[] arr, int n, boolean[] contArr, int index) {
    // Base case - we reached the end of the array
    if (index >= arr.length) {
        // Check that all values up to N are true
        for (int i = 0; i < n; i++) {
            if (!contArr[i]) return false;
        }
        // Here, we know the values are continuous
        return true;
    }

    // Set the index of the continuity array to a non-zero value
    int val = arr[index];
    if (val <= n && !contArr[val-1]){
        contArr[val-1] = true;
    }

    // Recurse with the next index
    return continuityOfnumbers(arr, n, contArr, index+1);
}

对于带有3, 1, 2, 3, 4, 6, 3的函数n = 4,以下是0falsetrue1的示例调试运行。

start:  [0, 0, 0, 0]
Set 3:  [0, 0, 1, 0]
Set 1:  [1, 0, 1, 0]
Set 2:  [1, 1, 1, 0]
Set 4:  [1, 1, 1, 1]
true

n = 6相同的数字(应该从false返回5并不存在)。

start:  [0, 0, 0, 0, 0, 0]
Set 3:  [0, 0, 1, 0, 0, 0]
Set 1:  [1, 0, 1, 0, 0, 0]
Set 2:  [1, 1, 1, 0, 0, 0]
Set 4:  [1, 1, 1, 1, 0, 0]
Set 6:  [1, 1, 1, 1, 0, 1]
false

答案 2 :(得分:0)

正如其他人所说,你的解决方案的问题是,你永远不会返回虚假,所以你总是得到真实的。

这是因为当您找到起始编号但序列未完成时,您从未正确处理过该案例。您需要重置搜索值,然后从失败的位置重新开始。

在以下代码中,set是您正在检查的数字集,initial是序列的起始编号。 search是下一个要搜索的号码(序列中的下一个号码)。 lastIdx是数组中的索引,我们目前正在查看。

停止条件是到达序列的结尾(成功,搜索== 1在set中的lastIdx)或者如果lastIdx到达集合的结尾(fail,lastIdx&lt; 0)。

特殊角色是step变量。重置部分序列时需要step:如果是下一个序列的开头,则需要再次检查当前正在查看的位置。如果您尚未启动序列,则已经检查了索引,您需要前进到下一个。

该集合从一端到另一端遍历,因为您的方法也是如此。

boolean continuityOfNumber(int[] set, int initial, int search, int lastIdx) {
    if(lastIdx < 0)
        return false;

    if( set[lastIdx] == search ) {
        if( search == 1 )
            return true;

        return continuityOfNumber(set, initial, search - 1, lastIdx - 1);
    }

    int step = (initial == search) ? 1 : 0;

    return continuityOfNumber(set, initial, initial, lastIdx - step);
}


final int[] testSet = {0, 1, 2, 3, 4, 2, 3, 4, 1, 2, 3, 2, 0};
final int[] testSet2 = {0, 2, 3, 4, 2, 3, 4, 1, 2, 3, 2, 0};
assertTrue(con.continuityOfNumber(testSet, 4, 4, testSet.length-1));
assertFalse(con.continuityOfNumber(testSet2, 4, 4, testSet2.length-1));