普林斯顿Algorithms-1.4-算法分析

时间分析

本节以一个常见的算法题:

 3sum 为例阐述算法分析的过程:

科学家理解自然世界的方法对研究计算机程序的运行时间同样有效:

Observe some feature of the natural world, generally with precise measurements.

Hypothesize a model that is consistent with the observations.

Predict events using the hypothesis.

Verify the predictions by making further observations.

Validate by repeating until the hypothesis and observations agree.

Observations.

Our first challenge is to determine how to make quantitative measurements of the running time of our programs. Stopwatch.java is a data type that measures the elapsed running time of a program.

最简单的实现方法,复杂度 N^3.


Stopwatch⏲,每次double

Mathematical models.

The total running time of a program is determined by two primary factors: the cost of executing each statement and  the frequency of execution of each statement.


波浪号近似


Designing faster algorithms.

One of the primary reasons to study the order of growth of a program is to help design a faster algorithm to solve the same problem. Using mergesort and binary search, we develop faster algorithms for the 2-sum and 3-sum problems.

2-sum. The brute-force solution TwoSum.java takes time proportional to N^2. TwoSumFast.java solves the 2-sum problem in time proportional to N log N time.

N log N

3-sum. ThreeSumFast.java solves the 3-sum problem in time proportional to N^2 log N time.

N^2 log N 

空间分析

 To estimate how much memory our program uses, we can count up the number of variables and weight them by the number of bytes according to their type. For a typical 64-bit machine,

Primitive types. the following table gives the memory requirements for primitive types.

Objects. To determine the memory usage of an object, we add the amount of memory used by each instance variable to the overhead associated with each object, typically 16 bytes. Moreover, the memory usage is typically padded to be a multiple of 8 bytes (on a 64-bit machine).

一个对象占用的内存 = 实例变量占用内存 + 对象本身开销(指向对象类的引用 ,垃圾收集信息,同步信息)

另外还有填充字节来占位,因为内存的分配都是8的倍数(64位机器)


References. A reference to an object typically is a memory address and thus uses 8 bytes of memory (on a 64-bit machine). 指向对象的引用是8个字节

Linked lists. A nested non-static (inner) class such as our Node class requires an extra 8 bytes of overhead (for a reference to the enclosing instance).

Arrays. Arrays in Java are implemented as objects, typically with extra overhead for the length. An array of primitive-type values typically requires 24 bytes of header information (16 bytes of object overhead, 4 bytes for the length, and 4 bytes of padding) plus the memory needed to store the values.

Strings. A Java 7 string of length N typically uses 32 bytes (for the String object) plus 24 + 2N bytes (for the array that contains the characters) for a total of 56 + 2N bytes.

Depending on context, we may or may not count the memory references by an object (recursively). For example, we count the memory for the char[] array in the memory for a String object because this memory is allocated when the string is created. But, we would not ordinarily count the memory for the String objects in a StackOfStrings object because the String objects are created by the client. 

你可能感兴趣的:(普林斯顿Algorithms-1.4-算法分析)