嵌套循环递归的时间复杂度/大符号

时间:2020-01-25 11:44:44

标签: java time-complexity big-o nested-loops

我正在看下面的代码

BindingContext = vm;

var getamenities = vm.Amenities;

painfullist.ItemsSource = new List<Amenitys>(getamenities);

作者声明此代码的时间复杂度为√c。我不明白是怎么回事。

因此,假设我们给出了c = 20的示例。那么代码将运行15次,但是√20= 4.47

5 个答案:

答案 0 :(得分:8)

给定的代码段为O(n)Ω(√n),这意味着陈述的时间复杂度只是最好的情况。

enter image description here

* 对数垂直轴

答案 1 :(得分:2)

我只想看一些实际的跑步。 √c似乎是最好的情况。我怀疑在a = 0b * b = c时会发生这种情况,从而无需多次运行外部循环。

prints:
  i =           10      sqrt =      3   runs =            8
  i =          100      sqrt =     10   runs =           11
  i =        1,000      sqrt =     31   runs =          351
  i =       10,000      sqrt =    100   runs =          101
  i =      100,000      sqrt =    316   runs =        4,121
  i =      500,000      sqrt =    707   runs =       71,501
  i =    1,000,000      sqrt =  1,000   runs =        1,001
  i =    5,000,000      sqrt =  2,236   runs =      521,209
  i =   10,000,000      sqrt =  3,162   runs =      382,721
  i =   50,000,000      sqrt =  7,071   runs =    7,079,001
  i =  100,000,000      sqrt = 10,000   runs =       10,001

打印有:

public class StackOverflowTest {
  static int counter;

  public static void main(String[] args) {
    print(10);
    print(100);
    print(1000);
    print(10000);
    print(100000);
    print(500000);
    print(1000000);
    print(5000000);
    print(10000000);
    print(50000000);
    print(100000000);
  }

  static void print(int i) {
    new Solution().judgeSquareSum(i);
    String format = "  i = %,12d\tsqrt = %,6d\truns = %,12d\n";
    System.out.printf(format,i,(int)Math.sqrt(i),counter);

  }

  static class Solution { // only added a counter
      public boolean judgeSquareSum(int c) {
          counter = 0;
          for (long a = 0; a * a <= c; a++) {
              for (long b = 0; b * b <= c; b++) {
                  counter++;
                  if (a * a + b * b == c)
                      return true;
              }
          }
          return false;
      }
  }
}

答案 2 :(得分:-1)

这可以进一步优化为:

public boolean judgeSquareSum(final int c) {

    final long rootC = (long) Math.sqrt(c);

    if (c == rootC * rootC) {
        return true;
    }

    for (long a = 0; a <= rootC; a++) {

        final long aSquared = a * a;
        final long b        = (long) Math.sqrt(c - aSquared);

        if (aSquared + b * b == c) {
            return true;
        }
    }
    return false;
}

以上对于所有+ ve c产生与原始过帐相同的结果。

答案 3 :(得分:-1)

采用另一种方式:如果为a² + b² = c,则限制条件为:

a² + 0² = c(&当然是0²+b²= c,这是相似的)
-> a² = c
-> a = √c

因此,对于任何ba <= √c

最初发布的代码每次迭代都会检查a * a <= c
最好只评估一次极限值(因为它更快)。
如我们所见,a * a <= c可以重写为a <= √c

因此for循环可以如下编码:

final long rootC = (long) Math.sqrt(c);

for (long a = 0; a <= rootC; a++) {
    :
    :
}

...我希望可以使原始代码的√c复杂性声明清楚。

第二个for循环是不必要的,因为b可以凭经验计算

对于任何a
a² + b² = c(已知c的地方)
-> b² = c - a²
-> b = √(c - a²)
(仅接受b的整数值)

答案 4 :(得分:-5)

您的最大条件是

a * a <= c

b * b <= c

如果双方的平方根都为a <= √cb <= √c

因此,如果您优化代码以提高性能...
(即,不要在每次迭代中都计算最大值!)
...看起来像这样:

public boolean judgeSquareSum(final int c) {

    final long rootC = (long) Math.sqrt(c);

    for (    long a = 0; a <= rootC; a++) {
        for (long b = 0; b <= rootC; b++) {

            if (a * a + b * b == c) {
                return true;
            }
        }
    }
    return false;
}

所以现在您可以看到√c的复杂度要求从何而来。