java如何计算以下代码片段的复杂性?
我是一个有着大O符号和算法复杂性的初学者。我试图计算以下两个java方法的复杂性,这两个方法都做相同的事情。但是一个会稍微快一点
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;
}
(knows()是一个布尔方法,如果x是y的朋友,则返回true,否则返回false)
我最初认为filter1和filter2都将在O(n)时间运行,但回顾一下,说filter1将花费O(n+n)时间是否正确(这可以简化为O(n)?)过滤器2需要O(n)时间,因为它只在人身上迭代一次
还是我完全没有抓住要点
# 1 楼答案
Big-O只关心曲线的一般形状,而不关心应用于曲线的系数
因此,如果计算复杂性
O(n + n)
,则应将其简化为O(2n)
,然后删除O(n)
的系数你的两个例子都与人数成线性关系。从大O的角度来看,这两个过滤器是等效的
# 2 楼答案
O(n+n)确实可以简化为O(n)。但是
filter()
不是O(n)首先,引用
ArrayList
documentation(重点矿山)中关于时间复杂性的一段话:让我们分析一下
filter1()
的代码:因此,由于}是O(n+n2)=O(n2)
List.remove()
是O(n),{现在是
filter2()
代码:所以
现在,为了澄清两个功能相同但运行时间不同的函数的混淆,考虑以下函数:filter2()
是O(n)h1(n)和h2(n)都是O(n)这一事实并不意味着它们必须彼此跑得一样快。事实上,h2(n)运行时间比h1(n)大一千倍。具有O(n)时间复杂度意味着这两个函数随着n值的增加而线性增加
<> E>大O.EEM>定义:为了将定义应用于h1(n),考虑到f(n)=n和g(n)=n,我们需要找到一个常数c,以便对于所有足够大的n,f(n)≤ c·g(n)。在这种情况下,n≤ 任何c的c·n≥ 1,所以我们证明了h1(n)=O(n)
现在对于h2(n),考虑到f(n)=1000·n和g(n)=n,我们需要找到一个常数c,使得对于所有足够大的n,f(n)≤ c·g(n)。在这种情况下,1000·n≤ 任何c的c·n≥ 1000,所以我们证明了h2(n)=O(n)
# 3 楼答案
你说得对
O(n+n) = O(2n)
可以简化为O(n)
对于
filter1()
:每个for循环都需要
O(n)
,所以O(n) + O(n) = O(n)
,但是根据这个document,friends.remove
也需要O(n)
,因为它必须遍历整个列表才能找到该项并将其删除。但是,friends.add
需要O(1)来添加项目link所以,复杂度计算是这样的
对于
filter2()
,它是(O(n) * O(1)) = O(n)