【问题标题】:Sum of two numbers equal to the given number两个数字之和等于给定数字
【发布时间】:2015-07-07 00:54:24
【问题描述】:

我有一个随机排列的正整数数组。一个数字 x 从给定的列表中,我们需要在列表中找到任意两个数字 总和等于 x。运行时间必须小于 n^2。

{编辑} 我所做的是,我将所有小于 x 一半的数字放在一个数组中,将大于一半的 x 放在另一个数组中,所有大于 x 的数字都被丢弃,然后想法是所需的两个数字必须来自两个数组(不是来自单个数组)并且通过迭代我可以得到这两个数字。

现在对于最坏的情况,我有点困惑,这种方法是好的吗?或者如果有人指导我做比这更好的事情,我们也可以实现 log nn *log n 吗?

【问题讨论】:

  • 这不是骗子。这个问题是相关的,但 OP 在这里有一个不同的问题。他有一个特定的(不同的)解决方案,并询问它的复杂性。

标签: java arrays performance algorithm sorting


【解决方案1】:

你的解决方案都错了,在O(n^2)

  1. 这是错误的,因为考虑 x=5arr=[1,2,3,5] - 所需的两个数字来自一个数组,而不是来自两个数组。
    如果arr=[3,3,6]x=6,你会将3s 放在一个列表中(例如不大于x/2),并且找不到3+3=6
  2. 您的算法在O(n^2) 中运行,因为假设恰好有一半元素大于x1,而一半小于x。然后,您必须检查的组合数量是(n/2*n/2) /2 = n^2/8

要在O(nlogn) 中解决它,想想如果你对数据进行排序,给定一个数字arr[i],如果现在排序的数组中有一个数字x-arr[i],你能有效地找到吗?

您甚至可以通过将元素放入哈希集中将上述情况提高到O(n) 的平均情况,现在,给定一个数字y,如果x-y 也在集合中,您能有效地找到吗?

编辑:
由于 OP 编辑​​了问题,删除的部分不再相关,而是添加了一个新的关注原因。


(1) 比编辑问题中的x/2

【讨论】:

  • 先生,我忘记了我编辑过的解决方案中的一点,即 x 的一半
  • @amit 如果数组已经排序或者可以在线性时间排序(例如使用计数排序),则另一个有趣的选项是在线性时间解决问题。然后,您可以通过使用两个索引变量并对数字进行单次迭代来解决问题。
  • @IvayloStrandjev 是的,但是(1)这是一个不同的问题,(我没有回答)。 (2) 这很容易落入can you find efficiently if there is a number x-arr[i] in the now sorted array?的how to
  • @SSH 你的方法对于小角落的情况仍然是错误的(虽然可以处理),而且效率仍然很低。请参阅编辑后的答案。
  • @amit 先生需要你的 cmets 来解决这个问题stackoverflow.com/questions/29914913/…
【解决方案2】:

这里是 O(n) 解决方案,用于找到总和为预期目标的数组的第一对索引。解决方案将在找到前 2 个总和为目标的索引时停止,如果您需要所有加起来为目标的对,那么您可以使用 ArrayList 甚至是 Map,处理完整的数组和将其与所有索引对一起返回。有一个明显的假设,即 Map 的 hashcode 函数非常好,并且没有太多的冲突,因此 map 操作在 O(1) 时间内执行。

import java.util.*;

public class Solution {

    public static void main(String[] args) {
        int[] array = new int[] {1,2,4,7,12,67,12,5,9,1,10};
        System.out.println(Arrays.toString(sum(array, 68)));
    }

    public static int[] sum(int[] array, int target) {
        int[] result = new int[2];
        Map<Integer, Integer> map = new HashMap<Integer, Integer>();
        // n iterations
        for (int index = 0; index < array.length; index++) {
            // constant
            if (map.containsKey(target - array[index])) {
                result[1] = index;
                // constant
                result[0] = map.get(target - array[index]);
                return result;
            }
            // constant
            map.put(array[index], index);
        }
        return result;
    }
}

【讨论】:

    【解决方案3】:

    给你,

    使用归并排序对数组进行排序(时间复杂度:n logn)。取两个指针/计数器,比如ij,一个从索引0 开始,另一个从n-1 开始(假设n 数组的大小是n)。

    if array[i]+array[j]=sum 
          return;
        else if (array[i]+array[j]<sum) i++;
        else j--;
    

    直到i&gt;j

    总体时间复杂度:n logn

    【讨论】:

      【解决方案4】:

      /* 时间复杂度 = O(n)-因为 HashMap 操作需要 O(1) 时间*/

      public static ArrayList<Integer> twoSum(int[] arr , int target){
      
          if (arr == null){
              throw new IllegalArgumentException();
          }
          ArrayList<Integer> targetHolder = new ArrayList<>();
          HashMap<Integer, Integer> map = new HashMap<>();
      
          for (int i = 0 ; i < arr.length ; i++){
      
              if (map.containsKey(arr[i])){
                  int index = map.get(arr[i]);
                  targetHolder.add(index+1);
                  targetHolder.add(i+1);              
              }
              else{
                  map.put(target-arr[i], i);              
              }   
      
          }
          return targetHolder;    
      }
      public static void main(String[] args) {        
          int[] A = {1,2,3,4,5,6};
          System.out.println(twoSum(A, 6));
      }
      }
      

      【讨论】:

        【解决方案5】:

        public void function(int[] array, int sum){

             for(int i = 0; i < array.length/2; i ++){
                for(int j = array.length-1;; j--){
                    if(array[i]+array[j] < sum) break;
                    if(array[i]+array[j] == sum) System.out.println(array[i]+" + "+array[j]+" = "+sum);
                }
            }
        }
        

        【讨论】:

        • 它都不会工作,并且在 O(n^2) 中。此外,仅代码的答案几乎没有价值,因为他们实际上并没有学习 OP 任何东西,只是给他答案而没有解释。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-12
        • 1970-01-01
        相关资源
        最近更新 更多