在已排序的数组

时间:2015-09-03 14:19:26

标签: arrays algorithm sorting

取自谷歌面试问题here

假设您有一个排序的整数数组(正数或负数)。您希望将形式为f(x)= a * x ^ 2 + b * x + c的函数应用于数组的每个元素x,以便仍然对结果数组进行排序。用Java或C ++实现它。输入是初始排序数组和函数参数(a,b和c)。

你认为我们可以在小于O(n log(n))时间的情况下就地进行,其中n是数组大小(例如,在对数组进行排序后,将函数应用于数组的每个元素)?

4 个答案:

答案 0 :(得分:1)

二次变换可能导致部分值“折叠”到其他值。你必须改变他们的顺序,这可以很容易就地完成,但是你需要合并这两个序列。

线性时间内的就地合并是可能的,但这是一个困难的过程,通常超出了面试问题的范围(除非教师在Algorithmics中的位置)。

看一下这个解决方案:http://www.akira.ruc.dk/~keld/teaching/algoritmedesign_f04/Artikler/04/Huang88.pdf

我想主要的想法是保留数组的一部分,允许交换对其包含的数据进行加扰。您可以使用它在阵列的其余部分上执行部分合并,最后对数据进行排序。 (合并缓冲区必须足够小,以便不需要超过O(N)来对其进行排序。)

答案 1 :(得分:1)

如果a是&gt; 0,然后在x = -b /(2a)处出现最小值,并且值将从[0]到[n-1]按正向顺序复制到输出数组。如果&lt; 0,然后在x = -b /(2a)处出现最大值,并且值将以[n-1]到[0]的相反顺序复制到输出数组。 (如果a == 0,那么如果b> 0,则执行正向复制,如果b <0,则执行反向复制,如果a == b == 0,则不需要执行任何操作)。我认为排序的数组可以二进制搜索O(log2(n))中最接近-b /(2a)的值(否则它是O(n))。然后将此值复制到输出数组,并将之前的值(递减索引或指针)和之后的值(递增索引或指针)合并到输出数组中,花费O(n)时间。

答案 2 :(得分:0)

我认为这可以在线性时间内完成。因为函数是二次函数,它将形成抛物线,即值减小(假设&#39; a&#39;的正值)下降到某个最小点,然后在此之后将增加。所以算法应该遍历排序的值,直到我们达到/传递函数的最小点(可以通过简单的微分来确定),然后对于每个值,在最小值之后,它应该向后走过前面的值,寻找插入该值的正确位置。使用链接列表可以允许项目就地移动。

答案 3 :(得分:0)

static void sortArray(int arr[], int n, int A, int B, int C)
    {
       // Apply equation on all elements
        for (int i = 0; i < n; i++)
            arr[i] = A*arr[i]*arr[i] + B*arr[i] + C;

        // Find maximum element in resultant array
        int index=-1;
        int maximum = -999999;
        for (int i = 0; i< n; i++)
        {
            if (maximum < arr[i])
            {
                index = i;
                maximum = arr[i];
            }
        }

        // Use maximum element as a break point
        // and merge both subarrays usin simple
        // merge function of merge sort
        int i = 0, j = n-1;
        int[] new_arr = new int[n];
        int k = 0;
        while (i < index && j > index)
        {
            if (arr[i] < arr[j])
                new_arr[k++] = arr[i++];
            else
                new_arr[k++] = arr[j--];
        }

        // Merge remaining elements
        while (i < index)
            new_arr[k++] = arr[i++];
        while (j > index)
            new_arr[k++] = arr[j--];

        new_arr[n-1] = maximum;

        // Modify original array
        for (int p = 0; p < n ; p++)
            arr[p] = new_arr[p];
    }