[英]How do I use a recursive algorithm to determine whether the array contains two elements that sum to a given integer?
好的,谢谢大家的帮助! 特别感谢@pjs,它为我提供了实现方法的思路。 这是我的新代码,但是由于某种原因,它无法达到基本情况之一。 抱歉,如果我删除了旧代码,这是我第一次在这里发布,并且不确定是否应该使用新代码回答我自己的问题。
//initialized int start = 0
//initialized int end = length of the array
//here goes the constructor
public boolean kPairSum(Integer k) {
if (sortedIntegerArray.length < 2) { //if array is less than two return false
return false;
}
else if (start == end) { //once the start and the end meets. This is the base case that doesn't seem to work for me.
return false;
}
else {
int currentStart = sortedIntegerArray[start]; //get first int in the array
int currentEnd = sortedIntegerArray[end-1]; //get the very last int in the array
int sum = currentStart + currentEnd; //get the sum
if (k.equals(sum)) { //compare sum and k if equal
return true;
}
else if (sum <k) { //if sum is less than k then increment value of start
start++;
return kPairSum(k);
}
else if (sum > k) { //if sum is greater than k then it decrements value of end
end--;
return kPairSum(k);
}
else { //not sure if this is right, should I just get rid of the else if statement for sum > k and change it to just an else? I wrote this down cause it has to return a type of boolean.
return kPairSum(k);
}
}
您的递归调用永远不会调用:
if (sum == k) { //compare to given k
return true;
} else if (xx == sortedIntegerArray.length-1 || sum != k) {
return false;
}
请注意,您基本上有两个选择: sum==k
,然后-返回true,或sum!=k
然后返回false。 递归调用无法实现。
使用哈希表可以实现O(n)
(平均情况)解决方案。 这个想法是在迭代时将每个元素添加到哈希表中,并检查是否有一个完整的元素完成k
。
for each element e in arr:
if e is in table:
return true
table.add(k-e)
return false //no pair was found that sums to k
检查所有对的递归解决方案基本上是蛮力,类似于嵌套的for循环。
//i is the index we are now checking, b is a boolean indicating we have already reduced one element
kSum(k,i,b):
if i == arr.length
return false
if b == true && k == 0:
return true
if b == false:
return kSum(k-arr[i],i+1,true) || kSum(k,i+1,false)
else:
return kSum(k,i+1,b)
您的数组称为sortedIntegerArray
,但您似乎并未利用这一事实。
首先求和数组的两端。 如果总和小于k
,则总和的两个元素之一必须更大。 因为元素是有序的,所以只能通过增加较低的索引来获得较大的值。 类似地,如果总和大于k
,则两个元素之一必须较小,因此您需要减小高位索引。 在这两种情况下,问题的结构都是相同的,但是您现在正在对数组的一个子集进行操作,该子集由您递增/递减的索引指定。 基本情况是,您找到了两个总和为k
值,或者索引在某处相遇。 递归应该对您有效。 由于每个递归调用都会递增或递减边界索引,直到它们在中间相遇为止,因此它是O(n)。
我在这里有两种实现方式:一种是我最初开始工作的,随着Amit的回答,我进一步改进了它。 它还prints/return
组成sum
的indices
。 可与O(n)中的排序数组和未排序数组一起使用。 当然,这不是recursive
。
public static void sumArray2(int[] arr, int sum){
Map <Integer, Integer> map = new HashMap<>();
for (int i=0; i < arr.length;i++){
map.put(arr[i], i);
}
for (int i =0; i < arr.length;i++){
int diff = sum-arr[i];
if (map.containsKey(diff) && i!=map.get(diff)) {
System.out.printf("The two indices are %s and %s%n ",i,map.get(diff));
return ;
}
}
System.out.printf("The sum:%s cannot be formed with given array:%s",sum,Arrays.toString(arr));
return ;
}
//returns a boolean if sum could be formed.
public static boolean sumArray3(int[] arr, int sum){
Map <Integer, Integer> map = new HashMap<>();
for (int i =0; i < arr.length;i++){
int diff = sum-arr[i];
if (map.containsKey(arr[i])) {
System.out.printf("The two indices are %s and %s%n ",i,map.get(arr[i]));
return true;
}
map.put(diff,i);
}
System.out.printf("The sum:%s cannot be formed with given array:%s",sum,Arrays.toString(arr));
return false;
}
不知道如何添加带格式的注释,因此这里是增强版本,比Amit提供的版本更适合O(n):)
def check(source, need):
target = [need-i for i in source]
target.reverse()
i = 0
j = 0
# walk thru lists same "merge" to find a match
for i in xrange(0, len(source)):
while j < len(target) and source[i] > target[j]:
j=j+1
if i != len(source)-j-1 and j < len(target) and source[i] == target[j]:
return True
return False
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.