[英]Calculating Time Complexity of recursive function with iteration
I am trying to understand the time complexity for this code which calculates IP addresses given a string by splitting the string into 4 parts.我试图了解这段代码的时间复杂度,它通过将字符串分成 4 部分来计算给定字符串的 IP 地址。 Each part is separated by a period ie
.
每个部分由句点分隔,即
.
public List<String> restoreIpAddresses(String s, int parts) {
List<String> result = new ArrayList<>();
if (parts == 1) {
if (isValidPart(s)) result.add(s);
return result;
}
for (int i = 0; i < s.length(); i++) {
String first = s.substring(0, i);
if (!isValidPart(first)) {
continue;
}
List<String> previous = restoreIpAddresses(s.substring(i, s.length()), parts - 1);
for (String str: previous) {
StringBuilder sb = new StringBuilder();
result.add(first + "." + str);
}
}
return result;
}
private boolean isValidPart(String part) {
if ( (part.length() > 1 && part.startsWith("0")) ||
(part.length() > 3) || (part.length() == 0)
(Integer.valueOf(part) > 255) ) return false;
return true;
}
}
Since the for loop is O(n)
, n being the length of the string, and in each iteration the for loop executes for the substring that was passed in the parent for loop, so O(n - 1)
.由于 for 循环是
O(n)
,n 是字符串的长度,并且在每次迭代中,for 循环都会为在父 for 循环中传递的子字符串执行,所以O(n - 1)
。 So by this logic, the time complexity should be n(n-1)(n-2) ....1
ie n!
所以按照这个逻辑,时间复杂度应该是
n(n-1)(n-2) ....1
即n!
in the worst case, right?在最坏的情况下,对吧?
However if I look around (eg. here or here ), I see people posting constant time complexity.但是,如果我环顾四周(例如here或here ),我会看到人们发布恒定的时间复杂度。 I am unable to understand.
我无法理解。 Can someone help me break it down?
有人可以帮我分解一下吗?
Consider this for generating the IP adresses from above algorithm we have two constraints.考虑到从上述算法生成 IP 地址,我们有两个约束。
Now consider a string 111 111 111 111
of length 12
现在考虑一个长度为
12
的字符串111 111 111 111
How many way can you form the first octet?你有多少种方式可以形成第一个八位字节? => minimum 1 , maximum 3 ways out of 12 characters.
=> 最少 1 ,最多 3 种方式,共 12 个字符。
complexity:- O(3)
How many way can you form the second octet?你有多少种方式可以形成第二个八位字节? => minimum 0 maximum 3 ways out of 9 character, considering 3 characters are used by first octet.
=> 9 个字符中的最小 0 最大 3 种方式,考虑到第一个八位字节使用了 3 个字符。
complexity:- O(3)
How many way can you form the third octet?你有多少种方式可以形成第三个八位字节? => minimum 0 maximum 3 ways from 6 character, considering 6 characters are used by first and second octet.
=> 最少 0 最多 3 种方式,从 6 个字符开始,考虑到第一个和第二个八位字节使用 6 个字符。
complexity:- O(3)
How many way can you form the fourth octet with the remaining characters?你有多少种方法可以用剩余的字符组成第四个八位字节? => There is only one way to form an octet from the remaining 3 characters.
=> 只有一种方法可以从剩余的 3 个字符形成一个八位字节。 considering 9 characters are used by the first, second, and third octet.
考虑到第一个、第二个和第三个八位字节使用了 9 个字符。
O(1)
Time complexity Calculation.时间复杂度计算。
Time Complexity = product of complexities of each recursive function
= O(3)*O(3)*O(3)*O(1)
= 3*O(3) = O(1) = [constant-time] complexity
So no matter what string you will give as an input all the valid IP addresses can be counted in 27
iterations.因此,无论您提供什么字符串作为输入,所有有效 IP 地址都可以计算为
27
次迭代。 Therefore this algorithm is a constant time O(1)
.因此这个算法是一个常数时间
O(1)
。
Considering the above understanding the code can be re-written following way考虑到以上理解,代码可以按照以下方式重写
public static List<String> restoreIpAddresses(String s, int position, int parts) {
List<String> result = new ArrayList<>();
// O(1) time complexity
if (parts == 1) {
if (position < s.length() && isValidPart(s.substring(position))) {
result.add(s.substring(position));
}
return result;
}
// Iterate only thrice in each recursive function. O(3) time complexity
for (int i = position; i <= position + 3; i++) {
if (i > s.length()) {
continue;
}
String first = s.substring(position, i);
if (!isValidPart(first)) {
continue;
}
List<String> previous = restoreIpAddresses(s, i , parts - 1);
for (String str : previous) {
StringBuilder sb = new StringBuilder();
result.add(first + "." + str);
}
}
return result;
}
Note that the above algorithm is one examples of classic backtracking problems
.请注意,上述算法是经典
backtracking problems
一个例子。 From wiki.来自维基。
Backtracking is a general algorithm for finding solutions to some computational problems, notably constraint satisfaction problems, that incrementally builds candidates to the solutions, and abandons a candidate ("backtracks") as soon as it determines that the candidate cannot possibly be completed to a valid solution
回溯是一种通用算法,用于寻找某些计算问题的解决方案,特别是约束满足问题,它逐步构建解决方案的候选者,并在确定候选者不可能完成到有效的时立即放弃候选者(“回溯”)解决方案
PS:- The example 111 111 111 111
is an extreme example and there is only one valid IP 111.111.111.111
address that can be formed from this string. PS:- 示例
111 111 111 111
是一个极端示例,只有一个有效的 IP 地址111.111.111.111
可以从该字符串中形成。 However, the loop/recursion evaluation will happen a maximum of 81 times.但是,循环/递归评估最多会发生 81 次。
Given n
, the length of input string and i
, the number of parts.给定
n
,输入字符串的长度和i
,部分的数量。 the time-complexity
of the code is obtained by below formula:代码的
time-complexity
由以下公式获得:
The formula is recursive because the code is recursive.该公式是递归的,因为代码是递归的。 On the right hand side, the second Sigma denotes the
time-complexity
of each for-loop
(substring).Moreover, by solving the latter sigma like below:在右侧,第二个 Sigma 表示每个
for-loop
(子字符串)的time-complexity
。此外,通过求解后一个 Sigma,如下所示:
we reach to this equation:我们得出这个等式:
Consider we are at Level-0
and we move to Level-1
.考虑我们在
Level-0
并且我们移动到Level-1
。 Therefore, the equation turns to:因此,方程变为:
Approximately we have (see this link for more info):我们大约有(有关更多信息,请参阅此链接):
The equation turns to:方程变为:
if we move at next level which is Level-2
(I just write Simplicable part):如果我们进入下一个级别,即
Level-2
(我只写简单部分):
the equation turns to:方程变为:
with the help of mathematical induction
we can say:借助
mathematical induction
我们可以说:
my assumptions and formulations may be wrong.我的假设和表述可能是错误的。 However, I enjoy playing with math.
不过,我喜欢玩数学。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.