这不是家庭作业,而是课堂上练习的问题。我知道没有解决方案的关键。我想看看我做得对。另外,我如何找到时间复杂度?以下是我在此底部的解决方案。
确定以下程序片段的Big Oh复杂性
1)
void sum1(int n){
sum1 = 0;
for(i=1; i<=n; i++)
for (j=1; j<=n; j++)
sum1++;
}
2)
void sum2(int n){
sum2 = 0;
for(i=1; i<=n; i++)
for (j=1; j<=i; j++)
sum2++;
}
3)
float useless(a){
n = a.length;
if (n==1){
return a[0];
}
// let a1, a2 be arrays of size n/2
for (i=0; i <= (n/2)-1; i++){
a1[i] = a[i];
a2[i] = a[n/2 +i];
}
for (i=0; i<=(n/2)-1; i++){
for (j = i+1; j<=(n/2) -1; j++){
if(a1[i] == a2[j])
a2[j] = 0;
}
}
b1 = useless(a1);
b2 = useless(a2);
return max(b1,b2);
}
4)
void sum3(int n) {
sum = 0;
for(i=0; i<sqrt(n)/2; i++)
sum++;
for(j=0; j<sqrt(n)/4; j++)
sum++;
for(k=0; k<8+j; k++)
sum++;
}
5)
void sum4(int n){
sum = 0;
for(i=0; i<sqrt(n)/2; i++)
for(j=1; j<8+i; j++)
for(k=j; k<8+j; k++)
sum++;
}
下面是我的解决方案,&#39;?&#39;意味着我不知道该放什么
1)
void sum1(int n){
sum1 = 0; --> 1
for(i=1; i<=n; i++) --> n
for (j=1; j<=n; j++) --> n^(2)
sum1++; --> ?
}
答案:O(n ^(2))
2)
void sum2(int n){
sum2 = 0; --> 1
for(i=1; i<=n; i++) --> n
for (j=1; j<=i; j++) --> n^(2)
sum2++; --> ?
}
答案:O(n ^(2))
3)
float useless(a){
n = a.length; --> ?
if (n==1){
return a[0]; --> ?
}
// let a1, a2 be arrays of size n/2
for (i=0; i <= (n/2)-1; i++){ --> n
a1[i] = a[i]; --> ?
a2[i] = a[n/2 +i]; --> ?
}
for (i=0; i<=(n/2)-1; i++){ ---> n+n = n
for (j = i+1; j<=(n/2) -1; j++){ ---> n^(2)
if(a1[i] == a2[j])
a2[j] = 0; --> 1
}
}
b1 = useless(a1); --> ?
b2 = useless(a2); --> ?
return max(b1,b2); --> ?
}
我非常坚持这个......
4)
void sum3(int n) {
sum = 0; --> 1
for(i=0; i<sqrt(n)/2; i++) --> n
sum++; --> ?
for(j=0; j<sqrt(n)/4; j++) --> n^(2)
sum++; --> ?
for(k=0; k<8+j; k++) --> n^(3)
sum++; --> ?
}
答案:O(n ^(3))
5)
void sum4(int n){
sum = 0; --> 1
for(i=0; i<sqrt(n)/2; i++) --> n
for(j=1; j<8+i; j++) --> n^(2)
for(k=j; k<8+j; k++) --> n^(3)
sum++; --> ?
}
答案:O(n ^(3))
答案 0 :(得分:1)
让我们考虑一下你已经解决的问题:
void sum2(int n){
sum2 = 0;
for(i=1; i<=n; i++)
for (j=1; j<=i; j++)
sum2++;
}
我们计算在sum2
上完成的增量数量:sum2++
为1增量。因此,我们得到以下条款:
sum i from 1 to n of [ sum j from 1 to i of (1) ]
= sum i from 1 to n of (i)
= n(n-1)/2
in O(n^2)
让我们考虑3)
float useless(a){
n = a.length;
// B: breaking condition
if (n==1) return a[0];
// L1: first loop
// let a1, a2 be arrays of size n/2
for (i=0; i <= (n/2)-1; i++) {
a1[i] = a[i];
a2[i] = a[n/2 +i];
}
// L2: second loop
for (i=0; i<=(n/2)-1; i++) {
for (j = i+1; j<=(n/2) -1; j++) {
if(a1[i] == a2[j])
a2[j] = 0;
}
}
// R: recursion
b1 = useless(a1);
b2 = useless(a2);
return max(b1, b2);
}
我们正在计算aX
的分配数量:a[j] = 0;
是1个分配,a1[i] = a[i];
也是。aX[I]
。 (注意,我们可以很容易地计算数组访问次数A(n)
)。我们将此号码称为n
,其中a
是输入数组A
的长度。我们注意到A(1) = 0
A(n) = ... n > 1
的两个目标案例:
R
在考虑递归之前,让我们看看我们对一般情况的成本(评论B executes 0 assignments
L1 executes 2*n/2 == n assignments
L2 executes at worst (if all elements are 0) n*(n-1)/2 assignments
thus A executes n(n+1)/2 assignments total before reaching R
):
A
然后跟随两个输入大小的一半递归 - 所以对于A(1) = 0
A(n) = n(n+1)/2 + 2 * A(n/2) n > 1
= n(n+1)/2 + 2 * ((n/2)((n/2)+1)/2 + 2 * A(n/4))
= n(n+1)/2 + 2 * ((n/2)((n/2)+1)/2 + 2 * ((n/4)((n/4)+1)/2 + 2 * A(n/8)))
= ...
= n(n+1)/2 + sum i from 1 to x of ( 2^i * (n/(2^i))((n/(2^i))+1)/2 )
= sum i from 0 to x of ( 2^i * (n/(2^i))((n/(2^i))+1)/2 )
我们现在得到:
x
递归发生B
次,直到达到中断条件n == 1
并且n := 2^k
。对于k
,这恰好在x := log2(n)
步骤之后发生 - 通常我们使用n
,因为n(n+1)/2
进入无穷大。从这里它的代数到达一个封闭的形式解决方案。
请注意,有一些技巧可以让这更容易:因为我们对计算确切的分配数量不感兴趣,我们可以将n^2
简化为O(n^2)
,因为它们都在A(n) = n^2 + 2 * A(n/2)
。您可以求解确切的数字或近似DECLARE @Temp TABLE
(
UserId nvarchar(128),
DateCreated Date,
DOfYear int
)
INSERT INTO @Temp (UserId, DateCreated) values ('uid123', '2016-01-19');
INSERT INTO @Temp (UserId, DateCreated) values ('uid123', '2016-01-24');
INSERT INTO @Temp (UserId, DateCreated) values ('uid123', '2016-01-28');
INSERT INTO @Temp (UserId, DateCreated) values ('uid123', '2016-01-29');
INSERT INTO @Temp (UserId, DateCreated) values ('uid123', '2016-02-01');
INSERT INTO @Temp (UserId, DateCreated) values ('uid123', '2016-02-02');
INSERT INTO @Temp (UserId, DateCreated) values ('uid123', '2016-02-03');
INSERT INTO @Temp (UserId, DateCreated) values ('uid123', '2016-02-07');
INSERT INTO @Temp (UserId, DateCreated) values ('uid123', '2016-02-19');
WITH CTE AS (
SELECT
DateCreated,
StartDate = Dateadd(day,-ROW_NUMBER() OVER (ORDER BY DateCreated), DateCreated)
FROM @Temp
)
SELECT
[LastDate] = MAX(DateCreated),
TotalDays = COUNT(1)
FROM CTE
GROUP BY StartDate
Order By StartDate desc
,它们都在相同的复杂性类别中。
答案 1 :(得分:1)
我认为你已经拥有的一些一般原则(大部分):
现在问题#4:
这不是O(n ^ 3):请注意,循环不嵌套。每个都包含一个增量语句O(1)。前两个循环是O(sqrt(n));第三个使用 j 的最终值加上一个常量,因此它也是O(sqrt(n))。特别注意O(sqrt(n))&lt; O(n),你用过的。平方根是n ^(1/2)。
问题#5:
每个循环都是O(sqrt(n)),但它们现在是嵌套的。这给你sqrt(n)^ 3,或n ^(3/2)。
将来要注意的最后一个细节是sqrt(n)不一定是O(1);这取决于实施。现代芯片在板上具有sqrt功能,可在O(n)时间内处理所有本机整数和浮点数。但是,有一些任意大的浮点数和整数的数据类型,其实现是O(log(n))。如果您的老师没有对该操作做出总结性决定,请留意sqrt - 以及其他超越函数 - 潜入循环体。