Java 如何计算以下代码段的复杂性?
我是一个有着大O符号和算法复杂性的初学者。我试图计算以下两个java方法的复杂性,这两个方法都做相同的事情。但是一个会稍微快一点Java 如何计算以下代码段的复杂性?,java,algorithm,Java,Algorithm,我是一个有着大O符号和算法复杂性的初学者。我试图计算以下两个java方法的复杂性,这两个方法都做相同的事情。但是一个会稍微快一点 ArrayList<Person> filter1(Person x, ArrayList<Person> people){ ArrayList<Person> friends = new ArrayList<Person(); for (Person y: people) friends.add(y); for
ArrayList<Person> filter1(Person x, ArrayList<Person> people){
ArrayList<Person> friends = new ArrayList<Person();
for (Person y: people) friends.add(y);
for (Person y: people) if (!x.knows(y)) friends.remove(y);
return friends;
}
ArrayList<Person> filter2(Person x, ArrayList<Person> people){
ArrayList<Person> friends = new ArrayList<Person();
for (Person y: people) if (x.knows(y)) friends.add(y);
return friends;
}
ArrayList过滤器1(人员x,ArrayList人员){
ArrayList friends=new ArrayListBig-O只关心曲线的一般形状,而不关心应用于曲线的系数
因此,如果计算复杂度O(n+n)
,则应将其简化为O(2n)
,然后删除O(n)
的系数
你的两个例子都是在与人数成线性关系的时间内运行的。从大O的角度来看,这两个过滤器是等价的
说filter1需要O(n+n)时间(这可以简化为O(n)吗?)而filter2需要O(n)时间是正确的吗
O(n+n)确实可以简化为O(n),但是filter()
不是O(n)
首先,引用ArrayList
中关于时间复杂性的一段话(重点是我的):
size、isEmpty、get、set、iterator和listIterator操作以固定时间运行。add操作以摊销固定时间运行,也就是说,添加n个元素需要O(n)个时间。所有其他操作以线性时间运行(粗略地说)
让我们分析filter1()
的代码:
所以filter2()
是O(n)
现在,为了澄清两个功能相同但运行时间不同的函数的混淆,考虑以下函数:
- h1(n)=n=O(n)
- h2(n)=1000·n=O(n)
h1(n)和h2(n)都是O(n)的事实并不意味着它们的运行速度必须一样快。事实上,h2(n)的运行时间是h1(n)的1000倍。具有O(n)时间复杂性只是意味着这两个函数都随着n值的增加而线性增加
以大O定义为例:
f(n)=O(g(n))意味着c·g(n)是f(n)的上界,因此存在一些常数c,使得f(n)总是≤ c·g(n),对于足够大的n
为了将定义应用于h1(n),考虑到f(n)=n和g(n)=n,我们需要找到一个常数c,使得对于所有足够大的n,f(n)≤ c·g(n)。在这种情况下,n≤ c·n表示任何c≥ 我们证明了h1(n)=O(n)
现在对于h2(n),考虑到f(n)=1000·n和g(n)=n,我们需要找到一个常数c,使得对于所有足够大的n,f(n)≤ c·g(n)。在这种情况下,1000·n≤ c·n表示任何c≥ 1000,所以我们证明h2(n)=O(n)。你说得对,O(n+n)=O(2n)
可以简化为O(n)
对于filter1()
:
每个for循环都需要O(n)
,因此O(n)+O(n)=O(n)
,但根据这一点,好友。remove
也需要O(n)
,因为它必须遍历整个列表才能找到项目并将其删除。然而,好友.add
需要O(1)才能添加项目
所以,复杂度计算是这样的
(O(n) * O(1)) + (O(n) * O(n))
= O(n) + O(n^2)
= O(n^2)
对于filter2()
它是(O(n)*O(1))=O(n)
第一个实际上在O(n^2)
中,因为add
插入y
,所以remove
将遍历整个列表。如果你想让它成为O(n)
,请转到friends.remove(friends.size()-1)
。首先要做的是(n+n)是O(n)。现在,保持简单…在filter1中,您首先添加然后删除(添加和删除需要时间),但在filter2中,您是根据某些条件直接添加的,所以您不认为这会运行得更快吗?您假设两种算法都处于O(n)中
基于一个错误的假设,即循环中的所有操作都在O(1)
范围内。请参阅关于ArrayList.remove()的其他答案好的调用,我错过了。
List<Person> filter2(Person x, List<Person> people){
List<Person> friends = new ArrayList<>();
for (Person y: people) { // O(n)
if (x.knows(y)) {
friends.add(y); // amortized constant time
}
}
return friends;
}
(O(n) * O(1)) + (O(n) * O(n))
= O(n) + O(n^2)
= O(n^2)