【问题标题】:Searching for a sum in an array在数组中搜索总和
【发布时间】:2014-10-21 16:07:27
【问题描述】:

我有一个方法可以计算数组包含多少个等于 0 的 3 个元素的总和。我需要帮助找到停止计算循环中相同的三胞胎的方法。比如1 + 3 - 4 = 0,还有3 - 4 +1 = 0。方法如下:

private static int counter(int A[])
    {   
         int sum;
         int e = A.length;
         int count = 0;
         for (int i=0; i<e; i++)
         {
             for (int j=i+1; j<e; j++)
             {
                 sum=A[i]+A[j];
                 if(binarySearch(A,sum))
                 {
                      count++;
                 }
             }  
         }
         return count;

编辑:我必须使用二进制搜索(数组已排序)。 这是 binarySearch 代码:

   private static boolean binarySearch(int A[],int y)
    {   
        y=-y;
        int max = A.length-1;
        int min = 0;
        int mid;
        while (max>=min)
        {      
            mid = (max+min)/2;
            if (y==A[mid])
            {
                return true;
            }   
            if (y<A[mid]) 
            {
                max=mid-1;
            }
            else
            {
                min=mid+1;
            }
        }
        return false;

【问题讨论】:

  • 实际上你的 binarySearch 没有给出正确的输出。
  • 我又做了一些编辑...(binarySearch int --->bolean)。

标签: java arrays binary-search


【解决方案1】:

您可以通过假设我们需要查找具有x &lt; y &lt; zA[x] + A[y] + A[z] == 0 的三元组 (x,y,z) 来避免计算不同的三元组。

所以你需要做的是修改binarySearch函数返回大于y且有A[z] == -(A[x] + A[y])的索引个数

private static int binarySearch(int A[],int y, int index)
    {   
        y=-y;
        int max = A.length-1;
        int min = index + 1;
        int mid;
        int start = A.length;
        int end = 0;
        while (max>=min)
        {      
            mid = (max+min)/2;
            if (y==A[mid])
            {
                start = Math.min(start, mid);
                max = mid - 1;
            } else  
            if (y<A[mid]) 
            {
                max=mid-1;
            }
            else
            {
                min=mid+1;
            }
        }
        int max = A.length - 1;
        int min = index + 1;
        while (max>=min)
        {      
            mid = (max+min)/2;
            if (y==A[mid])
            {
                end = Math.max(end, mid);
                min= mid + 1;
            } else if (y<A[mid]) 
            {
                max=mid-1;
            }
            else
            {
                min=mid+1;
            }
        }
        if(start <= end) 
           return end - start + 1;
        return 0;
}

所以新函数binarySearch将返回大于index且值等于y的索引总数。

所以剩下的工作就是计算答案

private static int counter(int A[])
{   
     int sum;
     int e = A.length;
     int count = 0;
     for (int i=0; i<e; i++)
     {
         for (int j=i+1; j<e; j++)
         {
             sum=A[i]+A[j];
             count += binarySearch(A,sum, j);

         }  
     }
     return count;
}

注意我是如何使用两次二分搜索来查找所有大于y的值的开始和结束索引!

【讨论】:

  • 感谢您的帮助,我没想到用 2 次二进制搜索会出现这种情况。
【解决方案2】:
private static int counter(int A[]) {
    int e = A.length;
    int count = 0;
    for (int i = 0; i < e; i++) {
        for (int j = 1; (j < e - 1) && (i != j); j++) {
            for (int k = 2; (k < e - 2) && (j != k); k++) {
                if (A[i] + A[j] + A[k] == 0) {
                    count++;
                }
            }
        }
    }
    return count;
}

【讨论】:

  • 我想使用二分查找来加快执行时间。
  • 但是你不是说你的数组是有序的吗?? @DiVersi0n
  • 对不起,我忘了...数组已排序。这就是为什么我可以使用二分搜索。
【解决方案3】:
private static int counter(int ints[]) {
  int count = 0;
  for (int i = 0; i < ints.length; i++) {
    for (int j = 0; j < ints.length; j++) {
      if (i == j) {
        // cannot sum with itself.
        continue;
      }
      for (int k = 0; k < ints.length; k++) {
        if (k == j) {
          // cannot sum with itself.
          continue;
        }

        if ((ints[i] + ints[j] + ints[k]) == 0) {
          count++;
        }
      }
    }
  }

  return count;
}

【讨论】:

  • 感谢您的回答,但正如我上面所说,我必须使用二进制搜索来找到三胞胎。
【解决方案4】:

解决二分查找问题
您的代码几乎是正确的。你需要做的只是替换

if (sum == binarySearch(A,sum)) {

有了这个

if (binarySearch(A,sum)) {


我假设您的 binarySearch(A, sum) 方法将返回 true 如果它会在 A 数组中找到 sum 否则 false

private static int counter(int A[]) {   
    int sum;
    int e = A.length;
    int count = 0;
    for (int i=0; i<e; i++) {
        for (int j=i+1; j<e; j++) {
            sum=A[i]+A[j];
            if (binarySearch(A,sum)) {
                count++;
            }  
        }  
    }
    return count;
}

【讨论】:

  • 我的 binarySearch 方法返回一个 int,它等于其他 2 个 int 的 -sum。
  • 那您面临的问题是什么?
  • 你能用java.util.Arrays.binarySearch吗?
【解决方案5】:

这是我的解决方案,假设数组已排序并且没有重复元素,我使用了您提供的二进制搜索功能。输入数组是否包含重复元素?你能提供一些测试用例吗?

为了不在循环中计算相同的三元组,我们应该有一种检查重复元素的方法,我在这里使用的主要思想是拥有一个 int[] 数组列表,保存{A[i],A[j],-sum} 的排序整数.然后在每次迭代中,我将新的 A[i] 和 A[j] 与列表中的记录进行比较,从而消除重复的记录。

    private static int counter(int A[]){   
     int sum;
     int e = A.length;
     int count = 0;
     List<int[]> elements = new ArrayList<>();
     boolean mark = false;
     for (int i=0; i<e; i++)
     {
         for (int j=i+1; j<e; j++)
         {
             sum=A[i]+A[j];

             if (-sum == binarySearch(A,sum)){
                 int[] sort = {A[i],A[j],-sum};
                 if(-sum == A[i] || -sum == A[j]){
                     continue;
                 }else{
                     Arrays.sort(sort);
                     //System.out.println("sort" + sort[0] + " " + sort[1]+ " " + sort[2]);
                     for (int[] element : elements) {
                         if((element[0] == sort[0] && element[1] == sort[1]) && element[2] == sort[2])
                             mark = true;
                     }
                     if(mark){
                         mark = false;
                         continue;
                     }else{
                         count++;
                         elements.add(sort);
                         //System.out.println("Else sort" + sort[0] + " " + sort[1]);
                     }
                 }
             }  
         }  
     }
     return count;
}

【讨论】:

  • 您的代码正在运行,但执行需要更多时间...我想减少它...(是的,数组已排序并且没有重复的元素)。
【解决方案6】:

您可以使用辅助数组,存储指示是否使用元素的标志; 代码如下:

private static int counter(int A[])
{   
     int sum;
     int e = A.length;
     int count = 0;
     // assisted flag array
     List<Boolean> flagList = new ArrayList<Boolean>(e);
     for (int k = 0; k < e; k++) {
        flagList.add(k, false);// initialization
     }
     for (int i=0; i<e; i++)
     {
         for (int j=i+1; j<e; j++)
         {
             sum=A[i]+A[j];
             // if element used, no count
             if(binarySearch(A,sum)&& !flagList.get(i)&& !flagList.get(j))
             {
                  count++;
                  flagList.set(i, true);
                  flagList.set(j, true);
             }
         }  
     }
     return count;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-26
    相关资源
    最近更新 更多