算法的运行时间优化

时间:2016-04-28 13:38:12

标签: algorithm optimization time while-loop big-o

我正试图找到一种优化算法的方法,使运行时间为O(n²)(Big O Notation)。

输入是一个包含n个元素的数组,只有正整数和负整数。我们可以假设数组已经排序了。

我必须确定:对于每个r(数组的元素),是否r = s + t,其中s和t也是数组的元素,并且可以是相同的(s == t),或者也是零。

我试图通过检查当前数字是正数还是负数来减少我必须检查的元素数量,但是运行时间仍然太长。问题是我使用了3个while循环,这意味着在最坏的情况下运行时间为O(n³)。

这是我的代码:

public static void Checker(int[] array) {
    List<Integer> testlist = new ArrayList<Integer>();
    int i = 0;
    while (i < array.length) {
        int current = array[i];
        if (attached(current, array)) {
            testlist.add(current);
        }
        i++;
    }
}

public static boolean attached(int current, int[] array) {
    boolean result = false;
    int i = 0;
    while (i < array.length && !result) {
        int number1 = array[i];
        int j = 0;
        while (j < array.length && !result) {
            int number2 = array[j];
            if (number1 + number2 == current) {
                result = true;
            }
            j++;
        }
        i++;
    }
    return result;
}

2 个答案:

答案 0 :(得分:2)

  1. 计算所有可能的s + t总和,并将结果放入 =&gt; O(n 2
  2. 迭代每个r并检查是否存在与r =&gt; O(n)匹配的总和,因为set.contains在恒定时间内运行。

答案 1 :(得分:2)

您可以开始对数组O(nlogn)进行排序(如果没有),然后对于数组中的每个元素,您可以检查是否有两个元素的总和等于O(n²)中的数字。< / p>

代码位于 C#

public static bool Solve(int[] arr)
{
    Array.Sort(arr);    //If not already sorted

    foreach (var num in arr)
        if (!FindTwoThatSumN(arr, num))
            return false;

    return true;
}

public static bool FindTwoThatSumN(int[] arr, int num)
{
    int min = 0;
    int max = arr.Length - 1;

    while (true)
    {
        if (min == max) break;

        int sum = arr[min] + arr[max];

        if (sum < num) min++;
        if (sum > num) max--;
        if (sum == num) return true;
    }

    return false;
}

检查数组中是否有两个数字(必须进行排序)的想法是从最小值(min = 0)和最大值(max = arr.Length)开始,然后是每次迭代:

  • 如果总和低于数字,请增加min索引。
  • 如果总和大于数字,请减少max索引。
  • 如果总和等于数字,那么你找到了解决方案。
  • 如果min索引达到max,那么就没有解决方案。

您可以参考此question/answers了解更多详情和证明。

整体解决方案的时间复杂度为O(n²)

  • 对数组进行排序:O(nlogn)
  • 对已排序的数组进行迭代:O(n)
  • 找到两个总和值的数字:O(n)

所以,O(n²)归因于FindTwoThatSumN的嵌套调用。

如果您愿意,可以将索引而不是数字传递给FindTwoThatSumN方法,以避免额外检查使用数字本身作为解决方案的一部分。