繁体   English   中英

如何使用递归算法确定数组是否包含两个总和为给定整数的元素?

[英]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组成sumindices 可与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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM