有没有办法使用单个循环比较数组中的每个元素?

时间:2018-11-11 15:13:49

标签: algorithm optimization array-algorithms

我需要打印一个int数组的任何两个元素之间的最小差异。

数组A的每个元素小于其长度。

1 <= A[i] <= A.length;

我已经在Java中尝试了以下指定方法- 但是,在给定数组大小〜10 ^ 5的情况下,要花1秒钟以上的时间才能找到结果。

我认为这可能是一种幼稚的方法。有什么办法可以进一步优化它? 可以在O(n)时间复杂度内完成吗?

static int findResult(int[] arr)
        {
                 int max =  Integer.MAX_VALUE;
                 HashSet<Integer> hs = new HashSet<Integer>();
                 for(int obj : arr)
                 {
                     hs.add(obj);
                 }
                if(hs.size()==1 )
                {
                    return 0;             // if all elements are same
                }
                 for(int i=0; i<arr.length; i++)
                 {  
                     for(int j=i+1; j<arr.length; j++)
                     {
                         int value = Math.abs(a[i]-a[j]);
                         if(value<max)
                         {
                            max = value;
                         }

                      }         
                }
        return max;  // returns the smallest positive difference
    }

3 个答案:

答案 0 :(得分:4)

With 1≤x i ≤n O(n)

因为每个 x i 都认为1≤x i ≤n,所以,由于 pigeonhole原理,所有值要么精确地存在一次,要么重复存在两次或多次。

在前一种情况下,差异为1(对于大于1个元素的数组),在后一种情况下,结果为0,因为那时有两个项完全相等

因此,我们可以遍历数组并跟踪数字。如果一个数字已经存在一次,则返回0,否则,返回1,例如:

// only if it holds that for all i, 1 <= arr[i] <= arr.length
static int findResult(int[] arr) {
    bool[] found = new bool[arr.length]
    for(int i = 0; i < arr.length; i++) {
        if(found[arr[i]-1]) {
            return 0;
        } else {
            found[arr[i]-1] = true;
        }
    }
    return 1;
}

对于满足 n 个元素的条件的随机数组,在 n!/ n n 的情况下,它将返回{ {1}},在其他情况下,它将返回1,因此随机输入的平均值为 n!/ n n 。随着 n 越来越大,几乎没有“碰撞”的可能性越来越小,因此,随着@YvesDaoust says的出现,0的近似值非常可能。

没有1≤x i ≤n O(n log n)

如果我们删除约束,我们可以首先对数组进行排序,在这种情况下,我们对连续的元素进行迭代:

0

答案 1 :(得分:1)

我假设A是整数,否则条件1 <= A[i] <= A.len不相关。

然后使用直方图提供一个O(n)解决方案。

  1. 声明一个大小为A.length的计数器数组;

  2. 计算A元素的多重性;

  3. 扫描此直方图以找到最近的非空垃圾箱。


请注意,此解决方案假定仅考虑非零差异。如果零差计算在内,那么威廉的答案会更好。

答案 2 :(得分:0)

(添加到以上答案中)

如果需要使用O(1)多余的空间来执行此操作,则可以对输入序列A使用以下技巧:

for a in A[1...n]:        // a is an element in A; A is 1-indexed; 1 <= a <= n
    if M < A[a % M]:
        return 0
    A[a % M] += M
return 1

这里M(> n)使得M + n不会溢出。可以轻松地修改技巧,改为使用小于-n的M。

注意事项:

  1. 需要对A的元素进行随机(即O(1))访问。
  2. 不适合缓存。