我有一个练习,我得到一个错误,并希望帮助解决错误以及如何解决锻炼。
编写一个递归函数,接收一组数字和一个数字 在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);
}
答案 0 :(得分:0)
您的示例代码始终返回true,因为这是它返回的唯一值。基本上,您的方法会使用n-1
递归调用自己,直到n = 0
和return true
。
您需要将问题分成以下子问题:
数字n
的连续性意味着
n-1
n
包含在数组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
,以下是0
为false
且true
为1
的示例调试运行。
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));