LeetCode 1365-寻找比O(n ^ 2)更好的解决方案

时间:2020-05-15 21:37:13

标签: java algorithm

我正在工作leetcode问题编号1365。这是下面用斜体字符显示的问题:

给出数组nums,对于每个nums [i]找出数组中比其小的数字。也就是说,对于每个nums [i],您都必须计算有效j的数量,以使j!= i,并且nums [j]

https://leetcode.com/problems/how-many-numbers-are-smaller-than-the-current-number/

我能够使用蛮力完成O(n ^ 2)时间的任务。有没有更快的方法来编码此问题?

code_lowered

2 个答案:

答案 0 :(得分:2)

一个简单的O(nlgn)空间为O(n)的解决方案是:

  1. 将数组复制到临时数组O(n)
  2. 排序新数组O(ngln)
  3. 遍历原始数组
    • 对于每个元素,对排序后的数组进行二进制搜索,并获取该元素的第一个索引。
    • 索引将是您想要的计数。

答案 1 :(得分:1)

有一种更好的O(n^2)方法,您只比较每对索引一次并相应地更新计数:

public static int[] smallerNumbersThanCurrent(int[] nums)
{
    int[] result = new int[nums.length];

    for (int x = 0; x < nums.length; x++)
    {
        for (int y = x + 1; y < nums.length; y++)
        {
            if (nums[y] < nums[x])
                result[x]++;
            else if (nums[y] > nums[x])
                result[y]++;
        }
    }
    return result;
}

但是,我们可以在O(ngln)中进行操作,方法是对原始数组的索引进行排序,然后遍历这些排序的索引,从而相应地更新计数,这需要付出额外的数组代价。唯一的麻烦在于处理重复的数字,例如您示例中的2s。

public static int[] smallerNumbersThanCurrent(int[] nums)
{
    Integer[] idx = new Integer[nums.length];
    for(int i=0; i<idx.length; i++) idx[i] = i;
    Arrays.sort(idx, (a, b) -> (nums[a]-nums[b]));

    int[] res = new int[nums.length];

    for(int i=1; i<idx.length; i++) 
    {
        if(nums[idx[i]] == nums[idx[i-1]])
            res[idx[i]] = res[idx[i-1]];
        else
            res[idx[i]] = i;
    }

    return res;
}

测试:

int[] nums = new int[] {8,1,2,2,3};
System.out.println(Arrays.toString(smallerNumbersThanCurrent(nums)));

输出:

[4, 0, 1, 1, 3]