由于我对java比较热衷,所以我就在java编译器里面演示代码。链表的题那种有指针的我再在clion里面演示。
先来看看复杂度分析的题吧。
2023
对于链表来说,插入或者删除。都需要使指针位移到节点处,虽然比顺序表要快,但是时间复杂度仍为O(n)。对于顺序表而言,查找包含特定值元素的值,虽然比链表快,但不可能到达常数级。因此,顺序表通常采用数组存储,数组可以直接通过下标访问,因此D正确。
2022
public static void main(String[] args) {
int sum=0;
int n=10;
for (int i = 1; i < n; i*=2) {
System.out.println("i="+i);
for (int j = 0; j < i; j++) {
sum++;
}
}
System.out.println("sum="+sum);//输出
}
看输出结果我们能知道,sum执行的次数其实就是一个等比数列。然后i是以2倍乘增加的,所以答案就很好理解了。其实也就是内层循环的次数,我们抓住循环次数最多的那个变量就行了
2019
public static void main(String[] args) {
int x=0;
int n=100;
int count=0;
while (n>=(x+1)*(x+1))
{
x=x+1;
count++;
}
System.out.println("count="+count);
}
这题我拿count计数了,其实敲一遍就很清楚了
看到这个结果其实答案分析我都不用贴了,但我觉得,对于代码初学者来说,debug比直接的结果更容易让人接受。当然我这题以n=100为例。
当循环内x为9时,因为循环条件是大于等于,所以下次扔满足循环条件。当内循环x=9+1=10的时候,再去看循环条件,显然不满足了,因为11的平方显然大于100.
2017
public static void main(String[] args) {
System.out.println(func(100));
}
static int func(int n){
int i=0,sum=0;
while (sum<n)sum+=++i;//循环体内的代码 sum += ++i;
//实现了每次将i递增并添加到sum上。
//++i操作符会先将i递增1,然后返回递增后的值。
return i;
}
我们可以观察到,每次循环的i的值递增是从1开始的。在sum小于n之前,i的值会逐渐增加,直到sum大于等于n。因此,循环次数至多为n的平方根。
其实自己列10个就能看看了。时间复杂度肯定不会比14小,所以A肯定排除了,C和D又大的离谱,当然能理解这个debug过程肯定更好。
2015
这题并不是考时间复杂度,说实话这题就送分题。
public static void main(String[] args) {
System.out.println(s(1));
}
static int s(int n){
return n<=0?0:s(n-1)+n;
}
System.out.println这个其实就是c++的输出,其实看到print就应该能猜到吧。看到这种题,main函数一定是栈底的,因为如果main函数出栈了,程序不就结束了。
其实这样就很明显了,这就是底层栈的顺序,其实debug一下很清楚的。
2014
public static void main(String[] args) {
int count=0;
int n=100;
for (int k = 1; k <n ; k*=2)
for (int j = 1; j <=n; j++) {
count++;
}
System.out.println(count);
}
外层不管取什么数,内层都要执行n次的。外层显然不用执行n次。所以答案其实很好选。
本题当n为100时,外层可以取七个数,分别是1、2、4、8、16、32、64
所以最后的count=100*7=700
2013
在最坏情况下,我们需要遍历两个升序链表的所有节点,并将它们按照降序的方式合并为一个新的链表。这需要比较每个节点的值,并确定它在新链表中的位置。链表移动到下一个结点需要的时间是常数级别,因此忽略。所以我们只要管比较的时间就行了。因此最多比较m+n次。也就是O(m + n)。我看了一下答案,答案写的是O(m + n)=O(max(m,n))。为此我在国外的论坛上查了一下这两者区别:
在时间复杂度表示法中,O(m + n)表示算法的时间复杂度与输入规模 m 和 n 成正比。这种表示方式常用于描述两个不同输入的问题,并将两个输入的规模进行相加。而O(max(m ,n))表示算法的时间复杂度与输入规模 m 和 n 中较大者成正比。这种表示方式常用于描述两个输入规模相同但可能具有不同取值的问题。举个例子,假设有两个链表的长度分别为 m = 100 和 n = 200,那么对于 O(m + n) 的时间复杂度来说,复杂度为 O(100 + 200) = O(300),而对于 O(max(m ,n)) 的时间复杂度来说,复杂度为 O(max(100 ,200)) = O(200)。
因此,虽然两个表示法都考虑了两个输入规模,但 O(m + n) 更准确地描述了算法时间复杂度与输入规模的关系。而 O(max(m ,n)) 则更适用于描述两个输入规模相同但取值不同的情况。
无论是王道还是别的考研机构,都不会去解释这两者的区别。如果有m+n的选项的话,我认为那个更合适。当然在本题,D是相对最好的答案。
2012
递归函数的时间复杂度等于递归的深度乘以每次递归中的操作复杂度。
递归深度无疑是n,每次递归中的操作复杂度常数级,忽略。
这是栈内结构,自下向上 main 、5、4、3、2、1
2011
public static void main(String[] args) {
int x=2;
int n=100;
int count=0;
while (x<n/2) {
x = 2 * x;
count++;
}
System.out.println(count);
}
输出为5,答案就出来了,其实这种题,自己引入一个变量count,自己计数,最后count的值就是循环里执行的次数了。
在这道题就直接理解成 x乘几次2才能超过50(n/2)。x初始为2,因此x分别为2、4、8、16、32、64(结束)共计5次。