Basic Time Complexity
Considering this is the first chapter, I will not provide an exhaustive explanation of time and space complexity. A detailed Practical Guide to Algorithm Time and Space Complexity Analysis is scheduled for after you've learned the core frameworks of several common algorithms. By then, your knowledge base will allow you to easily understand various scenarios of time and space complexity analysis.
Since this chapter will guide you through implementing common sorting algorithms and data structures, I will analyze their time complexities. Therefore, it is essential to introduce the concepts of time/space complexity and the simplified methods of analysis in advance to avoid confusion for beginners.
For beginners, you only need to remember the following points:
Time and space complexity are expressed using Big O notation (like , etc.). These are estimates, not precise calculations, and only the highest growth term is retained.
For example, is equivalent to , and is equivalent to .
When analyzing the complexity of an algorithm, we generally consider the worst-case complexity.
Time complexity measures an algorithm's execution efficiency, while space complexity measures its memory consumption. The lower they are, the better.
For instance, an algorithm with a time complexity of is more efficient than one with , and an algorithm with a space complexity of consumes less memory than one with .
Of course, we generally need to specify what this
n
represents, such as the length of the input array.How to estimate? For now, you can simply understand that time complexity is often determined by the maximum nesting level of for loops, and space complexity is determined by how much space the algorithm allocates to store data.
Note
Some details in the above methods are not entirely rigorous:
Estimating time complexity by the nesting level of for loops is a simplified method and not completely accurate.
While we often analyze the worst-case complexity, for data structure API complexity, we also consider average complexity.
A comprehensive complexity analysis method will be specifically introduced in the Practical Guide to Algorithm Time and Space Complexity Analysis. The estimation methods above are sufficient for learning the content of this chapter.
Let's look at a few examples for clearer understanding.
Time/Space Complexity Case Analysis
Example One: Time Complexity , Space Complexity :
// input an integer array, return the sum of all elements
int getSum(int[] nums) {
int sum = 0;
for (int i = 0; i < nums.length; i++) {
sum += nums[i];
}
return sum;
}
算法包含一个 for 循环遍历 nums
数组,所以时间复杂度是 ,其中 n
代表 nums
数组的长度。
我们的算法只使用了一个 sum
变量,这个 nums
是题目给的输入,不算在我们算法的空间复杂度里面,所以空间复杂度是 。
示例二,时间复杂度 ,空间复杂度 :
// Calculate the sum when n is a multiple of 10, otherwise return -1
int sum(int n) {
if (n % 10 != 0) {
return -1;
}
int sum = 0;
for (int i = 0; i <= n; i++) {
sum += i;
}
return sum;
}
其实只有当 n
是 10 的倍数时,算法才会执行 for 循环,时间复杂度是 。其他情况下算法会直接返回,时间复杂度是 。
但是算法复杂度只考察最坏情况,所以这个算法的时间复杂度是 ,空间复杂度是 。
示例三,时间复杂度 ,空间复杂度 :
// Does the array contain two numbers whose sum is target?
boolean hasTargetSum(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
return true;
}
}
}
return false;
}
The algorithm contains two nested for loops, so the time complexity is , where n
represents the length of the nums
array.
Our algorithm only uses the variables i
and j
, which is a constant level of space usage, so the space complexity is .
You might say that the inner for loop doesn't iterate through the entire array and may return early, so the actual execution count of the algorithm should be less than . Is the time complexity still ?
Yes, it is still . As mentioned before, Big O notation is an estimate and does not require exact calculations. For different inputs, the actual execution count of the algorithm may indeed be less than , but we don't need to worry about that.
Simply put: When you see nested for loops, the time complexity is .
Example Four, Time Complexity , Space Complexity :
void exampleFn(int n) {
int[] nums = new int[n];
}
This function creates an array of size n
, so the space complexity is .
Allocating space for the array and initializing it also takes time, so the time complexity is as well.
Time complexity is not only reflected in visible for loops; every line of code can have hidden time complexity. Therefore, understanding the implementation principles of common data structures is fundamental to accurately analyzing time complexity.
Example Five, Time Complexity , Space Complexity :
// input an integer array, return a new array where each element is
// the square of the corresponding element in the original array
int[] squareArray(int[] nums) {
int[] res = new int[nums.length];
for (int i = 0; i < nums.length; i++) {
res[i] = nums[i] * nums[i];
}
return res;
}
Initializing the res
array in the algorithm requires a time complexity of , which includes a for loop, also having a time complexity of . Therefore, the total time complexity remains , where n
represents the length of the nums
array.
We declare a new array res
with the same length as the nums
array, so the space complexity is .
For beginners, understanding these basic analyses of time and space complexity is sufficient for now. Let's continue learning.