mirror of
https://github.com/krahets/hello-algo.git
synced 2025-07-23 01:10:06 +08:00
build
This commit is contained in:
26
docs-en/chapter_computational_complexity/index.md
Normal file
26
docs-en/chapter_computational_complexity/index.md
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
comments: true
|
||||
icon: material/timer-sand
|
||||
---
|
||||
|
||||
# 第 2 章 Complexity Analysis
|
||||
|
||||
<div class="center-table" markdown>
|
||||
|
||||
{ width="600" }{ class="cover-image" }
|
||||
|
||||
</div>
|
||||
|
||||
!!! abstract
|
||||
|
||||
Complexity analysis is like a space-time guide in the vast universe of algorithms.
|
||||
|
||||
It leads us to explore deeply in the dimensions of time and space, in search of more elegant solutions.
|
||||
|
||||
## 本章内容
|
||||
|
||||
- [2.1 Evaluating Algorithm Efficiency](https://www.hello-algo.com/chapter_computational_complexity/performance_evaluation/)
|
||||
- [2.2 Iteration and Recursion](https://www.hello-algo.com/chapter_computational_complexity/iteration_and_recursion/)
|
||||
- [2.3 Time Complexity](https://www.hello-algo.com/chapter_computational_complexity/time_complexity/)
|
||||
- [2.4 Space Complexity](https://www.hello-algo.com/chapter_computational_complexity/space_complexity/)
|
||||
- [2.5 Summary](https://www.hello-algo.com/chapter_computational_complexity/summary/)
|
1756
docs-en/chapter_computational_complexity/iteration_and_recursion.md
Normal file
1756
docs-en/chapter_computational_complexity/iteration_and_recursion.md
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,53 @@
|
||||
---
|
||||
comments: true
|
||||
---
|
||||
|
||||
# 2.1 Evaluation Of Algorithm Efficiency
|
||||
|
||||
In algorithm design, we aim to achieve two goals in succession:
|
||||
|
||||
1. **Finding a Solution to the Problem**: The algorithm needs to reliably find the correct solution within the specified input range.
|
||||
2. **Seeking the Optimal Solution**: There may be multiple ways to solve the same problem, and our goal is to find the most efficient algorithm possible.
|
||||
|
||||
In other words, once the ability to solve the problem is established, the efficiency of the algorithm emerges as the main benchmark for assessing its quality, which includes the following two aspects.
|
||||
|
||||
- **Time Efficiency**: The speed at which an algorithm runs.
|
||||
- **Space Efficiency**: The amount of memory space the algorithm consumes.
|
||||
|
||||
In short, our goal is to design data structures and algorithms that are both "fast and economical". Effectively evaluating algorithm efficiency is crucial, as it allows for the comparison of different algorithms and guides the design and optimization process.
|
||||
|
||||
There are mainly two approaches for assessing efficiency: practical testing and theoretical estimation.
|
||||
|
||||
## 2.1.1 Practical Testing
|
||||
|
||||
Let's consider a scenario where we have two algorithms, `A` and `B`, both capable of solving the same problem. To compare their efficiency, the most direct method is to use a computer to run both algorithms while monitoring and recording their execution time and memory usage. This approach provides a realistic assessment of their performance, but it also has significant limitations.
|
||||
|
||||
On one hand, it's challenging to eliminate the interference of the test environment. Hardware configurations can significantly affect the performance of algorithms. For instance, on one computer, Algorithm `A` might run faster than Algorithm `B`, but the results could be the opposite on another computer with different specifications. This means we would need to conduct tests on a variety of machines and calculate an average efficiency, which is impractical.
|
||||
|
||||
Furthermore, conducting comprehensive tests is resource-intensive. The efficiency of algorithms can vary with different volumes of input data. For example, with smaller data sets, Algorithm A might run faster than Algorithm B; however, this could change with larger data sets. Therefore, to reach a convincing conclusion, it's necessary to test a range of data sizes, which requires excessive computational resources.
|
||||
|
||||
## 2.1.2 Theoretical Estimation
|
||||
|
||||
Given the significant limitations of practical testing, we can consider assessing algorithm efficiency solely through calculations. This method of estimation is known as 'asymptotic complexity analysis,' often simply referred to as 'complexity analysis.
|
||||
|
||||
Complexity analysis illustrates the relationship between the time (and space) resources required by an algorithm and the size of its input data. **It describes the growing trend in the time and space required for the execution of an algorithm as the size of the input data increases**. This definition might sound a bit complex, so let's break it down into three key points for easier understanding.
|
||||
|
||||
- In complexity analysis, 'time and space' directly relate to 'time complexity' and 'space complexity,' respectively.
|
||||
- The statement "as the size of the input data increases" highlights that complexity analysis examines the interplay between the size of the input data and the algorithm's efficiency.
|
||||
- Lastly, the phrase "the growing trend in time and space required" emphasizes that the focus of complexity analysis is not on the specific values of running time or space occupied, but on the rate at which these requirements increase with larger input sizes.
|
||||
|
||||
**Complexity analysis overcomes the drawbacks of practical testing methods in two key ways:**.
|
||||
|
||||
- It is independent of the testing environment, meaning the analysis results are applicable across all operating platforms.
|
||||
- It effectively demonstrates the efficiency of algorithms with varying data volumes, particularly highlighting performance in large-scale data scenarios.
|
||||
|
||||
!!! tip
|
||||
|
||||
If you're still finding the concept of complexity confusing, don't worry. We will cover it in more detail in the subsequent chapters.
|
||||
|
||||
Complexity analysis provides us with a 'ruler' for evaluating the efficiency of algorithms, enabling us to measure the time and space resources required to execute a given algorithm and to compare the efficiency of different algorithms.
|
||||
|
||||
Complexity is a mathematical concept that might seem abstract and somewhat challenging for beginners. From this perspective, introducing complexity analysis at the very beginning may not be the most suitable approach. However, when discussing the characteristics of a particular data structure or algorithm, analyzing its operational speed and space usage is often inevitable.
|
||||
|
||||
Therefore, it is recommended that before diving deeply into data structures and algorithms, **one should first gain a basic understanding of complexity analysis. This foundational knowledge will facilitate the complexity analysis of simple algorithms.**
|
||||
|
2034
docs-en/chapter_computational_complexity/space_complexity.md
Normal file
2034
docs-en/chapter_computational_complexity/space_complexity.md
Normal file
File diff suppressed because it is too large
Load Diff
53
docs-en/chapter_computational_complexity/summary.md
Normal file
53
docs-en/chapter_computational_complexity/summary.md
Normal file
@ -0,0 +1,53 @@
|
||||
---
|
||||
comments: true
|
||||
---
|
||||
|
||||
# 2.5 Summary
|
||||
|
||||
### 1. Highlights
|
||||
|
||||
**Evaluation of Algorithm Efficiency**
|
||||
|
||||
- Time and space efficiency are the two leading evaluation indicators to measure an algorithm.
|
||||
- We can evaluate the efficiency of an algorithm through real-world testing. Still, it isn't easy to eliminate the side effects from the testing environment, and it consumes a lot of computational resources.
|
||||
- Complexity analysis overcomes the drawbacks of real-world testing. The analysis results can apply to all operating platforms and reveal the algorithm's efficiency under variant data scales.
|
||||
|
||||
**Time Complexity**
|
||||
|
||||
- Time complexity is used to measure the trend of algorithm running time as the data size grows., which can effectively evaluate the algorithm's efficiency. However, it may fail in some cases, such as when the input volume is small or the time complexities are similar, making it difficult to precisely compare the efficiency of algorithms.
|
||||
- The worst time complexity is denoted by big $O$ notation, which corresponds to the asymptotic upper bound of the function, reflecting the growth rate in the number of operations $T(n)$ as $n$ tends to positive infinity.
|
||||
- The estimation of time complexity involves two steps: first, counting the number of operations, and then determining the asymptotic upper bound.
|
||||
- Common time complexities, from lowest to highest, are $O(1)$, $O(\log n)$, $O(n)$, $O(n \log n)$, $O(n^2)$, $O(2^n)$, and $O(n!)$.
|
||||
- The time complexity of certain algorithms is not fixed and depends on the distribution of the input data. The time complexity can be categorized into worst-case, best-case, and average. The best-case time complexity is rarely used because the input data must meet strict conditions to achieve the best-case.
|
||||
- The average time complexity reflects the efficiency of an algorithm with random data inputs, which is closest to the performance of algorithms in real-world scenarios. Calculating the average time complexity requires statistical analysis of input data and a synthesized mathematical expectation.
|
||||
|
||||
**Space Complexity**
|
||||
|
||||
- Space complexity serves a similar purpose to time complexity and is used to measure the trend of space occupied by an algorithm as the data volume increases.
|
||||
- The memory space associated with the operation of an algorithm can be categorized into input space, temporary space, and output space. Normally, the input space is not considered when determining space complexity. The temporary space can be classified into instruction space, data space, and stack frame space, and the stack frame space usually only affects the space complexity for recursion functions.
|
||||
- We mainly focus on the worst-case space complexity, which refers to the measurement of an algorithm's space usage when given the worst-case input data and during the worst-case execution scenario.
|
||||
- Common space complexities are $O(1)$, $O(\log n)$, $O(n)$, $O(n^2)$ and $O(2^n)$ from lowest to highest.
|
||||
|
||||
### 2. Q & A
|
||||
|
||||
!!! question "Is the space complexity of tail recursion $O(1)$?"
|
||||
|
||||
Theoretically, the space complexity of a tail recursion function can be optimized to $O(1)$. However, most programming languages (e.g., Java, Python, C++, Go, C#, etc.) do not support auto-optimization for tail recursion, so the space complexity is usually considered as $O(n)$.
|
||||
|
||||
!!! question "What is the difference between the terms function and method?"
|
||||
|
||||
A *function* can be executed independently, and all arguments are passed explicitly. A *method* is associated with an object and is implicitly passed to the object that calls it, allowing it to operate on the data contained within an instance of a class.
|
||||
|
||||
Let's illustrate with a few common programming languages.
|
||||
|
||||
- C is a procedural programming language without object-oriented concepts, so it has only functions. However, we can simulate object-oriented programming by creating structures (struct), and the functions associated with structures are equivalent to methods in other languages.
|
||||
- Java and C# are object-oriented programming languages, and blocks of code (methods) are typically part of a class. Static methods behave like a function because it is bound to the class and cannot access specific instance variables.
|
||||
- Both C++ and Python support both procedural programming (functions) and object-oriented programming (methods).
|
||||
|
||||
!!! question "Does the figure "Common Types of Space Complexity" reflect the absolute size of the occupied space?"
|
||||
|
||||
No, that figure shows the space complexity, which reflects the growth trend, not the absolute size of the space occupied.
|
||||
|
||||
For example, if you take $n = 8$ , the values of each curve do not align with the function because each curve contains a constant term used to compress the range of values to a visually comfortable range.
|
||||
|
||||
In practice, since we usually don't know each method's "constant term" complexity, it is generally impossible to choose the optimal solution for $n = 8$ based on complexity alone. But it's easier to choose for $n = 8^5$ as the growth trend is already dominant.
|
3369
docs-en/chapter_computational_complexity/time_complexity.md
Normal file
3369
docs-en/chapter_computational_complexity/time_complexity.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user