我需要编写一段代码来测试未排序的数组 a 是否包含值 x ,从开始到结束,包括在内。
这是我到目前为止所做的:
boolean linearSearch(int[] a, int x, int start, int end){
boolean result = false;
if(a[start]==x){
result = true;
} else {
linearSearch(a,x,++start,end-1);
}
return result;
}
这个当前代码抛出一个数组越界异常,我似乎无法弄清楚它为什么不起作用。任何人都可以给我一个正确方向的推动吗?提前谢谢!
答案 0 :(得分:4)
您遇到的问题是因为您没有进行足够的约束检查。您需要确保的限制是:
start
小于数组a
的长度。end
小于数组a
的长度。end
大于start
。即使这样,由于这一行,你的递归也存在问题:
linearSearch(a,x,++start,end-1);
每次递归到此函数时,end
值都会递减。这意味着end
的原始输入实际上不是最后检查的索引。
进行递归时,最好考虑基本情况。在这种情况下,如果您的数组为空,会发生什么?你必须返回`false:
boolean linearSearch(int[] a, int x, int start, int end){
if (a.length == 0) { return false; }
// Do other things
}
我们还需要确定我们是否超过了end
点。结果与基本情况相同:
boolean linearSearch(int[] a, int x, int start, int end){
if ((a.length == 0) || (end == 0)) { return false; }
// Do other things
}
现在确定阵列的head
(第一个元素)是否是start
位置是一个问题。如果没有,你跳过检查是否相等,如果是,你执行它:
boolean linearSearch(int[] a, int x, int start, int end){
if ((a.length == 0) || (end == 0)) { return false; }
if (start <= 0) { //We are within the correct part of the array
//check for equality
} // else recurse without checking
}
检查相等性只是if (head == x)
:
boolean linearSearch(int[] a, int x, int start, int end){
if ((a.length == 0) || (end == 0)) { return false; }
if (start <= 0) { //We are within the correct part of the array
if (a[0] == x) { return true; }
}
//recurse
}
现在我们检查了基本案例和相等案例,我们只需要使用适当的变量进行递归。在这里,我们可以递减start
和end
,因为我们通过删除head
将数组的整个长度减少一个。这会减少每个元素的索引以及start
和end
的索引。这可以确保我们的基本情况保持正确。
boolean linearSearch(int[] a, int x, int start, int end){
if ((a.length == 0) || (end == 0)) { return false; }
if (start <= 0) { //We are within the correct part of the array
int head = a[0]; //The head is the first part of an array
if (head == x) { return true; }
}
// The tail is everything but the head
int[] tail = Arrays.copyOfRange(a, 1, a.length); //Be careful of off-by-one errors!
return linearSearch(tail, x, start - 1, end - 1);
}
让我们回顾一下我们的约束:
start
小于数组a
的长度。
start
大于数组的长度,则返回false
,因为我们检查以确保数组中首先包含一些元素。如果我们已经递归到数组为空的点,但start
中的值更高,我们仍会返回。start
为零或更小,我们将检查相等条件。 end
小于数组a
的长度。
end
将始终小于数组的末尾或找到的变量。 (我在这里作弊有点因为它不清楚预期的行为是什么。)end
大于start
。
end
小于start
,我们会在false
有机会被检查之前返回start
。当然,它有助于测试,因此我们将它打包在一个带有main
的类中并组合一些有用的测试:
import java.util.Arrays;
public class LinearSearch {
public static boolean linearSearch(int[] a, int x, int start, int end){
if ((a.length == 0) || (end == 0)) { return false; }
if (start <= 0) { //We are within the correct part of the array
int head = a[0]; //The head is the first part of an array
if (head == x) { return true; }
}
// The tail is everything but the head
int[] tail = Arrays.copyOfRange(a, 1, (a.length)); //Be careful of off-by-one errors!
return linearSearch(tail, x, start - 1, end - 1);
}
public static final void main(String[] args){
int[] test_arr1 = {1,2,3,4,5};
int[] test_arr2 = {3,2,3,1,5};
int[] test_arr3 = {};
// Basic success test
System.out.println("Expect true Found " + LinearSearch.linearSearch(test_arr1, 1, 0, 5));
System.out.println("Expect true Found " + LinearSearch.linearSearch(test_arr1, 2, 0, 5));
System.out.println("Expect true Found " + LinearSearch.linearSearch(test_arr1, 3, 0, 5));
System.out.println("Expect true Found " + LinearSearch.linearSearch(test_arr1, 4, 0, 5));
System.out.println("Expect true Found " + LinearSearch.linearSearch(test_arr1, 5, 0, 5));
// Test that order doesn't matter
System.out.println("Expect true Found " + LinearSearch.linearSearch(test_arr2, 1, 0, 5));
System.out.println("Expect true Found " + LinearSearch.linearSearch(test_arr2, 2, 0, 5));
System.out.println("Expect true Found " + LinearSearch.linearSearch(test_arr2, 3, 0, 5));
System.out.println("Expect false Found " + LinearSearch.linearSearch(test_arr2, 4, 0, 5));
System.out.println("Expect true Found " + LinearSearch.linearSearch(test_arr2, 5, 0, 5));
// Test that a sub array works correctly
System.out.println("Expect true Found " + LinearSearch.linearSearch(test_arr1, 3, 2, 4));
System.out.println("Expect true Found " + LinearSearch.linearSearch(test_arr1, 4, 2, 4));
System.out.println("Expect false Found " + LinearSearch.linearSearch(test_arr1, 1, 2, 4));
System.out.println("Expect false Found " + LinearSearch.linearSearch(test_arr1, 2, 2, 4));
System.out.println("Expect false Found " + LinearSearch.linearSearch(test_arr1, 5, 2, 4));
// Test empty array
System.out.println("Expect false Found " + LinearSearch.linearSearch(test_arr3, 3, 1, 2));
// Test start after finish
System.out.println("Expect false Found " + LinearSearch.linearSearch(test_arr1, 3, 2, 1));
}
}
答案 1 :(得分:1)
分配是递归吗?因为用for循环来做它会容易得多!
但是,在确定错误的方面,考虑使用for循环来实现它可以帮助你弄清楚你的递归实现缺失了什么!
for (int i = 0; i < a.length(), i++) {
boolean result = false;
if (a[start] == x) {
result = true;
}
}
return result;
在for循环中,中间条件限制循环发生的次数,这基本上就是你在结束时所做的事情。但是,您实际上并未验证结束是否已更改。
End与数组的长度相同,或者只是您希望它停止搜索的某个索引。递归地,结束作为递减计数。一旦end减少到0,意味着它已经检查了数组的每个元素或你指定的任何索引结束。
你需要添加一个额外的条件来检查end == 0(你已经完成了所有元素)。
boolean result = false;
if (end == 0) {
return result;
}
else if (a[start] == x) {
result = true;
**return result;**
}
else {
// do recursive search again
}
请记住在形成时将逻辑转换为英语:“好的,如果我们已经完成了每个元素的搜索,那么返回。不,好吧,如果我们找到了元素,将结果设置为true并返回。不,搜索下一个元件。
**编辑:有人指出我的答案中有一部分有点不清楚。您收到的越界异常是由于您尝试访问大于数组长度的索引。我提供的解决方案没有检查这个,因为它假定函数的用户正在为函数提供负责任的输入。
处理此案例有两种选择: 1.在第一个条件中添加额外的检查(如果x大于数组的长度减去1或者结束等于0) 2.在方法声明中,添加它会抛出Out of Bounds异常,以便函数的用户负责验证它们的输入和函数的输出。
有许多不同的书籍和材料讨论这两个选项,哪些应该或不应该使用。我会留给你调查并自己决定。**
答案 2 :(得分:0)
为什么不搜索有效的方式?
boolean linearSearch(int[] a, int x){
for(int y = 0; y < a.length; y++)
if(a[y] == x)
return true;
return false;
}
如果你想在指定的范围内搜索(例如在元素4
和元素8
之间搜索而不是整个数组),你可以使用这段代码:
boolean linearSearch(int[] a, int x, int start, int end){
for(int y = start; y < end; y++)
if(a[y] == x)
return true;
return false;
}
至于你的问题,
boolean linearSearch(int[] a, int x, int start, int end){
boolean result = false;
if(start == a.length-1)
return false; // If result still not validated and length limit is reached, return false
if(a[start] == x){ // When start equals a.length, it throws OFB Exception
result = true;
} else{
linearSearch(a,x,++start,end-1);
}
return result;
}
答案 3 :(得分:0)
这有用吗?看起来它会更简单。
boolean linearSearch(int[] a, int x, int start, int end){
a = Arrays.copyOfRange(a, start, end);
return Arrays.asList(a).contains(x);
}