根据操作次数,找出递归关系!
a = N;
var = 0;
while (a > 1)
{
var = var + a;
num = 2 * var;
a = a / 2;
}
我认为将形成的重现关系是:(分配操作不计算在内)
T(n)= (from a=1 to N)Σ(3)
我是对的吗?
现在使用这种递归关系,如何找到它的复杂性。
答案 0 :(得分:1)
你想要做的是找出这个操作被调用多少次,所以考虑一下:每次调用后a除以2,所以如果M = N / 2则T(M)= T(N) - 1
现在,此循环的每次迭代再次划分N,以便您获得以下内容:
T(N) = T(N/2) + 1 = ... = k + T(N/(2^k))
停止条件为:a>1
因此您需要检查何时N/(2^k) <= 1
N/2^k = 1 -> log (n) = k
所以T(N) = log(n) + T(1) = log(n)
这是“大O”符号的答案。
答案 1 :(得分:1)
经验方法:
首先通过简化代码来减少代码中的“教育噪音”并添加迭代计数器(c)。然后查看结果(N,计数),经过一段时间后,您会看到[^ 1,2,4,8,16,...]中所有N的2 ^ count = N.
因此复杂性Compl(loop)= O(log_2(N))。
let rec loop a c =
match a with
| x when x > 1 ->
let a1 = a / 2
loop a1 (c+1)
| _ -> (a,c)
// after staring at the result of the computation we came up with this theory:
let theory n = int (System.Math.Log10(float n) / System.Math.Log10(2.0))
[1..64]
|> List.map (fun a -> a,loop a 0, theory a)
|> List.map (fun (a0,(a,c),aa) -> a0,c,aa)
数据:
[(1,0,0); (2,1,1); (3,1,1); (4,2,2); (5,2,2); (6,2,2); (7,2,2); (8,3,3); (9,3,3); (10,3,3); (11,3,3); (12,3,3); (13,3,3); (14,3,3); (15,3,3); (16,4,4); (17,1,4); (18,4,4); (19,4,4); (20,4,4); (21,4,4); (22,4,4); (23,4,4); (24,4,4); (25,4,4); (26,4,4); (27,4,4); (28,4,4); (29,4,4); (30,4,4); (31,4,4); (32,5,5); (33,5,5); (34,5,5); (35,5,5); (36,5,5); (37,5,5); (38,5,5); (39,5,5); (40,5,5); (41,5,5); (42,5,5); (43,4,5); (44,4,5); (45,5,5); (46,5,5); (47,5,5); (48,5,5); (49,5,5); (50,5,5); (51,5,5); (52,5,5); (53,5,5); (54,5,5); (55,5,5); (56,5,5); (57,5,5); (58,5,5); (59,5,5); (60,5,5); (61,5,5); (62,5,5); (63,5,5); (64,6,6)]
答案 2 :(得分:1)
重现关系是:
T(1) = a
T(n) = b + T(n/2)
第一部分来自循环变量等于1的情况,在这种情况下,只执行循环顶部的比较。第二行来自循环体中完成的恒定工作量b,加上使用更新的循环变量值执行循环的时间。
前几个词是:
n T
1 a
2 a + b
4 a + 2b
8 a + 3b
基于此,我们可以猜出一般形式:
T(n) = a + b log n
证明这是一项运动;但你可以将其插入到递归关系中,看它是否满足要求。
渐近复杂度是对数的。