3Sum的时间复杂度较小

时间:2017-06-03 02:20:42

标签: algorithm big-o

LeetCode上的一个名为3Sum Smaller的问题是:

  

给定一组n整数numstarget,找到满足条件{{1}的i, j, k索引三元组0 <= i < j < k < n的数量}}

     

你能在O(n ^ 2)运行时解决它吗?

常见的O(n ^ 2)solution people agree upon是:

nums[i] + nums[j] + nums[k] < target

我不明白这是怎么回事O(n ^ 2)。当然,该算法使用了一些方便的快捷方式来节省时间(主要是通过排序和使用我们的优势),但我不知道它是如何确保O(n ^ 2)。

是否有一些数学原因,这是O(n ^ 2)而不是O(n ^ 3),如果是这样,请你解释一下它背后的原理,以便我能发现这种行为再次?

2 个答案:

答案 0 :(得分:1)

确定这一点的一种非常简单的方法是n ^ 2算法正在查看循环。

外(for)循环最多迭代n次(技术上是n-2但无论如何)。内循环取决于左和右的值。 left是在LEAST 1,右边是MOST len = n(技术上是len-1但是无论如何)内部循环仅在left < right时执行,所以在最坏的情况下内部循环在MOST迭代n次。

外循环最多迭代n次。对于外循环的每次迭代,内循环最多迭代n次。算法是O(n ^ 2)。此算法也是O(n ^ 3),因为O(n ^ 2)= O(n ^ 3)。

另一个不在恒定时间内运行的语句是:

Arrays.sort(nums);

假设有效的排序算法,此操作在O(nlog n)中运行,该操作在O(n ^ 2)中,因此它不会影响最终的时间复杂度。

进行时间复杂度分析时的一个技巧。忘记算法应该做什么,只查看循环以及它们可能运行的程度。

答案 1 :(得分:1)

public class Solution {
    int count; //constant operation

    public int threeSumSmaller(int[] nums, int target) {
        count = 0; //constant operation
        Arrays.sort(nums); //sorting is generally considered O(nlogn)
        int len = nums.length; //constant operation

        for(int i=0; i<len-2; i++) { //O(n) operation
            int left = i+1, right = len-1; //two constant operations
            while(left < right) { //O(n) operation
                if(nums[i] + nums[left] + nums[right] < target) { //constant operation
                    count += right-left; //constant operation
                    left++; //constant operation
                } else { 
                    right--; //constant operation
                }
            }
        }
        return count; //constant operation
    }
}

上面我已经用每行的基本运行时间注释掉了你的代码块。如您所见,有两个O(n)操作和一个O(nlogn)操作。通常假设排序为O(nlogn)。您的功能每次调用都会执行一次此操作。 O(n)操作是嵌套的,因此对于前N个操作,它执行N个后续操作。这是O(n ^ 2)。你的程序是O(nlogn)+ O(n ^ 2),这使得总数为O(n ^ 2),因为只有最高阶项很重要。