我遇到了一个挑战,即为一项任务制作最有效的算法。现在我来到了n * logn的复杂性。我想知道是否有可能做得更好。所以基本上任务是有孩子们有一个计数游戏。您将获得数字n,即孩子的数量,以及您在执行之前跳过某人的次数。您需要返回一个给出执行顺序的列表。我尝试这样做你使用跳过列表。
Current = m
while table.size>0:
executed.add(table[current%table.size])
table.remove(current%table.size)
Current += m
我的问题是这样的吗?是n * logn,你能做得更好吗?
答案 0 :(得分:3)
这是对的吗?
没有。
从表中删除元素时,table.size
会减少,current % table.size
表达式通常会指向另一个不相关的元素。
例如,44 % 11
为0
,44 % 10
为4
,这是一个完全不同的元素。
是n * logn吗?
没有。
如果table
只是一个随机访问数组,则可以执行n
次操作来删除元素。
例如,如果m = 1
,程序在修复上述点后,将始终删除数组的第一个元素。
当一个数组实现足够天真时,每次重新定位数组需要table.size
个操作,总共会导致大约n^2 / 2
个操作。
现在,如果n log n
被备份,将 table
,例如,通过具有隐式索引而不是键的平衡二进制搜索树,以及拆分和合并原语。这就是一个例子,here是快速搜索英文来源的结果。
这样的数据结构可以用作访问,合并和拆分成本O(log n)
的数组。
但到目前为止,没有任何迹象表明情况如此,并且在大多数语言中都没有这样的数据结构。标准库。
你能做得更好吗?
更正:部分,是;完全,也许。
如果我们向后解决问题,我们会遇到以下子问题。
让一群k
个孩子,并且指针当前处于小孩t
。
我们知道,就在刚才,有一群k + 1
小孩,但我们不知道指针在哪个小孩x
。
然后我们计算到m
,删除了孩子,指针最终在t
。
我们刚刚删除了哪些,什么是x
?
结果是"什么是x
"部分可以在O(1)
中解决(绘图在这里很有帮助),因此找到最后一个孩子可以在O(n)
中找到。
正如评论中所指出的那样,整个事情被称为Josephus Problem,其变体被广泛研究,例如Knuth等人的具体数学。
但是,每步O(1)
,这只会找到最后一个站着孩子的号码。
它不会自动给出计算孩子的整个顺序。
肯定有办法让每一步O(log(n))
,O(n log(n))
总计。
但至于O(1)
,我现在还不知道。
答案 1 :(得分:1)
算法的复杂性取决于操作的复杂性
table.remove(..)
和executed.add(..)
。
如果它们都具有 O(1)的复杂性,则您的算法具有 O(n)的复杂性,因为循环在 n 步骤。
虽然可以在 O(1)中轻松实现table.remove(..)
,但[# Children's IQ scores are normally distributed with a
# mean of 100 and a standard deviation of 15. What
# proportion of children are expected to have an IQ between
# 80 and 120?
mean=100; sd=15
lb=80; ub=120
x <- seq(-4,4,length=100)*sd + mean
hx <- dnorm(x,mean,sd)
plot(x, hx, type="n", xlab="IQ Values", ylab="",
main="Normal Distribution", axes=FALSE)
i <- x >= lb & x <= ub
lines(x, hx)
polygon(c(lb,x\[i\],ub), c(0,hx\[i\],0), col="red")
area <- pnorm(ub, mean, sd) - pnorm(lb, mean, sd)
result <- paste("P(",lb,"< IQ <",ub,") =",
signif(area, digits=3))
mtext(result,3)
axis(1, at=seq(40, 160, 20), pos=0)]
需要更多思考。
您可以在O(n):
中创建将您的人员存储在 LinkedList 中,并将最后一个元素与第一个元素连接起来。删除元素需要花费 O(1)。 选择下一个选择的人将花费 O(m),但这是一个常数= O(1)。
这种算法的复杂度为 O(n * m) = O(n)(对于常数m)。