【问题标题】:A recursive algorithm to find two integers in an array that sums to a given integer一种递归算法,用于在总和为给定整数的数组中查找两个整数
【发布时间】:2012-02-21 10:41:57
【问题描述】:

我需要一种算法来确定一个数组是否包含两个元素之和为给定整数的元素。

数组已排序。

算法应该是递归的并且在O(n)中运行。

递归步骤应该基于总和,这意味着该方法通过总和并根据最终结果返回真或假(如果找到两个元素 - 返回真,否则 - 返回假)

只能使用线性数据结构。

任何想法都值得赞赏..

【问题讨论】:

  • @akf:我想出了一个非递归方法,但我不明白如何将其转换为递归方法。非递归方法如下: 1. 创建两个变量 sum,start 和 end,start=数组的第一个元素,end=数组的最后一个元素... 2. sum=Array[start]+Array[ end]... 3. if (sum>k) 其中 k 是给定的整数,则递减 end... 4. else if (sum
  • 现在您应该将步骤 3 和 4 转换为函数的递归调用,返回值将与返回的递归调用相同。

标签: java algorithm recursion


【解决方案1】:

这里是执行 groupSum 的递归方法

public boolean groupSum(int start, int[] nums, int target) 
{
    if (start >= nums.length) {
    return (target == 0);
}
return groupSum(start + 1, nums, target - nums[start]) || groupSum(start + 
1,nums,target) 
}

【讨论】:

    【解决方案2】:

    这很容易。 array排序很重要。

    O(n)时间复杂度和没有额外空间的正确算法是:

    public static boolean isContainsSum(int[] arr, int sum) {
        for (int i = 0, j = arr.length - 1; i < j; ) {
            if (arr[i] + arr[j] == sum)
                return true;
            if (arr[i] + arr[j] < sum)
                i++;
            else
                j--;
        }
    
        return false;
    }
    

    要使其递归,您只需将 ij 迭代替换为递归调用:

    public static boolean isContainsSumRecursive(int[] arr, int sum) {
        return isContainsSumRecursive(arr, sum, 0, arr.length - 1);
    }
    
    private static boolean isContainsSumRecursive(int[] arr, int sum, int i, int j) {
        if (i == j)
            return false;
        if (arr[i] + arr[j] == sum)
            return true;
        if (arr[i] + arr[j] < sum)
            return isContainsSumRecursive(arr, sum, i + 1, j);
        return isContainsSumRecursive(arr, sum, i, j - 1);
    }
    

    【讨论】:

      【解决方案3】:

      这是我的解决方案:我迭代直到第一个数字大于预期总和,然后直到第二个数字或两个的总和大于预期总和。如果我不想要正确答案,我会返回 {-1,-1}(假设所有数字都是正整数)

      {
      
      private static int[] sumOfTwo(int[] input, int k) {
          for (int i = 0; i < input.length - 1; i++) {
              int first = input[i];
              for (int j = 1; j < input.length; j++) {
                  int second = input[j];
                  int sum = first + second;
                  if (sum == k) {
                      int[] result = {first, second};
                      return result;
                  }
                  if (second > k || sum > k) {
                      break;
                  }
              }
              if (first > k) {
                  break;
              }
          }
          int[] begin = {-1, -1};
          return begin;
      }
      

      }

      【讨论】:

        【解决方案4】:

        这是一个考虑重复条目的解决方案。它是用 javascript 编写的,并假定数组已排序。该解决方案在 O(n) 时间内运行,并且除了变量之外不使用任何额外的内存。

        var count_pairs = function(_arr,x) {
          if(!x) x = 0;
          var pairs = 0;
          var i = 0;
          var k = _arr.length-1;
          if((k+1)<2) return pairs;
          var halfX = x/2; 
          while(i<k) {
            var curK = _arr[k];
            var curI = _arr[i];
            var pairsThisLoop = 0;
            if(curK+curI==x) {
              // if midpoint and equal find combinations
              if(curK==curI) {
                var comb = 1;
                while(--k>=i) pairs+=(comb++);
                break;
              }
              // count pair and k duplicates
              pairsThisLoop++;
              while(_arr[--k]==curK) pairsThisLoop++;
              // add k side pairs to running total for every i side pair found
              pairs+=pairsThisLoop;
              while(_arr[++i]==curI) pairs+=pairsThisLoop;
            } else {
              // if we are at a mid point
              if(curK==curI) break;
              var distK = Math.abs(halfX-curK);
              var distI = Math.abs(halfX-curI);
              if(distI > distK) while(_arr[++i]==curI);
              else while(_arr[--k]==curK);
            }
          }
          return pairs;
        }
        

        我在一家大公司的面试中解决了这个问题。他们拿走了,但我没有。 所以这里适合所有人。

        从数组的两侧开始,慢慢地向内工作,确保计算重复项(如果存在)。

        它只计算对,但可以重做

        • 使用递归
        • 找到配对
        • 找对
        • 找到对 > x

        享受吧!

        【讨论】:

          【解决方案5】:

          我觉得hash还可以,比如1,3,7,9,12,14,33...

          如果我们想要 sum=21,我们将这些数字散列到一个散列表中,所以,O(n)。

          我们迭代它们,当我们得到 7 时,我们让 21-7=14,所以我们散列 14,我们可以找到它。所以 7+14=21,

          我们明白了!

          【讨论】:

            【解决方案6】:

            通常我会使用 Map,但由于其中一个要求是使用线性数据结构,我认为这被排除在外,所以我会使用布尔数组。

            public boolean hasSum( int[] numbers, int target )
            {
                boolean[] hits = new boolean[ target + 1 ];
                return hasSumRecursive( 0, numbers, target, hits );
            }
            
            public boolean hasSumRecursive( int index, int[] numbers, int target, boolean[] hits )
            {
                ...
            }
            

            希望这是一个足够好的提示。

            【讨论】:

              【解决方案7】:

              对数组进行排序。搜索每个数字的补码(sum-number)。复杂度 O(nlogn)。

              【讨论】:

                【解决方案8】:

                您可以使用(例如)tail recursion 将任何迭代算法转换为递归算法。如果不是家庭作业,我会更广阔。我想你会从其他帖子中理解它。

                【讨论】:

                  猜你喜欢
                  • 2018-12-10
                  • 1970-01-01
                  • 2012-12-05
                  • 1970-01-01
                  • 2013-12-06
                  • 2010-10-01
                  • 2020-06-30
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多