论坛首页 Java企业应用论坛

论String操作时间复杂度

浏览 17739 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2013-05-11   最后修改:2013-05-11
算法复杂度纯粹是从数学的角度来分析的。
是指随问题规模扩大的增长趋势,线性的、指数的、对数...等。
O(10N)也好(N/10)也好,都是O(N),就是线性的。

机器怎么优化或执行根本与这无关。
一个从1+...到N的循环累加算法,假设机器把他优化成数列公式来计算,难道说复杂度是O(1)么。

就楼主这个问题,就是O(N),因为是线性增长的。
0 请登录后投票
   发表时间:2013-05-15  
池中物 写道
算法复杂度纯粹是从数学的角度来分析的。
是指随问题规模扩大的增长趋势,线性的、指数的、对数...等。
O(10N)也好(N/10)也好,都是O(N),就是线性的。

机器怎么优化或执行根本与这无关。
一个从1+...到N的循环累加算法,假设机器把他优化成数列公式来计算,难道说复杂度是O(1)么。

就楼主这个问题,就是O(N),因为是线性增长的。


method1里面
s += "a";
这一句实际上还隐含着一个循环,实际上翻译为
s = s + "a";

编译后可能实际执行的是
s = new StringBuilder(s).append("a").toString();

而StringBuilder(s)里面是执行数组拷贝(System.arraycopy()),数组拷贝的时间复杂度是O(N),再加上外面的for循环,总体时间复杂度是O(N!),即N的阶乘。如果数组拷贝的时间复杂度为常量(即,与拷贝的字符串长度无关),这样method1的时间复杂度才是O(N)。

method2时间复杂度为O(N)我认为没有问题

我理解这是考官的真实意图。

0 请登录后投票
   发表时间:2013-05-21  
O(1)和O(N!)都出来了,太搞笑了。快回去查查时间复杂度的定义吧!

还“还隐含着”。照这个意思看,时间复杂度竟然还和语言有关系。哈哈。。。

这里引用下池中物的话
引用

算法复杂度纯粹是从数学的角度来分析的。
是指随问题规模扩大的增长趋势,线性的、指数的、对数...等。

0 请登录后投票
   发表时间:2013-05-21   最后修改:2013-05-21
dohkoos 写道
O(1)和O(N!)都出来了,太搞笑了。快回去查查时间复杂度的定义吧!

还“还隐含着”。照这个意思看,时间复杂度竟然还和语言有关系。哈哈。。。

这里引用下池中物的话
引用

算法复杂度纯粹是从数学的角度来分析的。
是指随问题规模扩大的增长趋势,线性的、指数的、对数...等。


时间复杂度的严格定义,还真没查过,只是凭感觉,让达人见笑了。
等我学习完成之后,持续更新本回复。
不过,方法1和2把循环次数改为100000后在我的机器上执行花费时间如下:

method1 cost 15344 ms
method2 cost 16 ms

单独针对方法1测试
   loop      time(ms)
   1000             0
  10000           157
100000         14938
1000000   等得太久,放弃(超过5分钟的等待)

经过重新考虑,个人认为method1()的时间复杂度为O(N^2)。因为for循环内部语句数组拷贝是O(N),加上for循环的O(N)。

0 请登录后投票
   发表时间:2013-05-21  
@mike.liu

再把池中物的这句话回复你
引用

算法复杂度纯粹是从数学的角度来分析的。
是指随问题规模扩大的增长趋势,线性的、指数的、对数...等。


时间复杂度和语言无关。所以你那个拷贝什么的都不算时间复杂度。

去查查定义再说这个行不!
0 请登录后投票
   发表时间:2013-05-21   最后修改:2013-05-21

我理解,有算法的地方,就有时间复杂度。

 

如果语言中有算法,则一定有时间复杂度。

 

甚至一条机器指令,也有时间复杂度,比如加法指令时间复杂度是常数,而除法指令则与除数和被除数有关。

 

像Java这种内建支持String类型的语言,所有的String操作都有其时间复杂度。因为即使表面上看起来好像只有一条语句(s += "a";),也有其实现方式,也就是算法,所以必然有时间复杂度。也就是说:当s为很短的字符串时所花的时间,与s为很长时所花的时间肯定是不一样的。

 

如果不理解这一点,就会写出小数据量下可以工作,大数据量下停止响应的代码。

 

比如method1(),当循环次数达到10^5次时,需要十几秒钟的时间,勉强可以忍受;达到10^6次时,我以最大的耐心都等不到结果(超过10分钟的等待)。

 

而method2(),在我的机器上,即使执行10^7次,也才仅仅消耗328ms,都还在可接受的程度范围(再尝试10^8导致OutOfMemory异常了,因此放弃)。

 

我理解,这就是时间复杂度的威力,也是为什么我们要分析时间复杂度的原因。

 

下面是我的测试代码:

 

public class Main {
	public static void main(String...args) {
		System.out.format("method2\n");
		// 循环次数不能再多,否则OutOfMemory异常:
		for (long i = 10; i<=10000000; i*=10) {
			System.out.format("%1$ 10d%2$ 10d\n", i, method2(i));
		}
		
		// 循环次数不能再多,否则要等待很久才能得到结果:
		System.out.format("method1\n");
		for (long i = 10; i<=1000000; i*=10) {
			System.out.format("%1$ 10d%2$ 10d\n", i, method1(i));
		}
	}

    public static long method1(long count) {
    	long t0 = System.currentTimeMillis();
        String s = "";  
        for (long i = 0; i < count; i++) {  
            s += "a";  
        }  
  
        return (System.currentTimeMillis()-t0);
    }  
  
    public static long method2(long count) {  
    	long t0 = System.currentTimeMillis();
        StringBuilder sb = new StringBuilder();  
        for (long i = 0; i < count; i++) {  
            sb.append("a");  
        }  
        return (System.currentTimeMillis()-t0);
    }  
}

 测试结果汇总:

         N   method1 ms   method2( ms)

        10         0         0
       100         0         0
      1000         0         0
     10000       141         0
    100000     14140         0
   1000000   2117750        31

  10000000       n/a       328

 

此结果支持下列说法:

method1与N不是线性关系,时间复杂度肯定不是O(N)

method2与N基本是线性关系,时间复杂度为O(N)

0 请登录后投票
   发表时间:2013-05-21  
@mike.liu

再次再次把池中物的这句话回复你
引用

算法复杂度纯粹是从数学的角度来分析的。
是指随问题规模扩大的增长趋势,线性的、指数的、对数...等。


时间复杂度 != 运行时间

时间复杂度是个理论问题
运行时间是个实际问题

sb.append("a");
s += "a"
都是基本操作,谈时间复杂度的时候是不算时间的。

for (int i = 0; i < 100; i++) ;
for (int i = 0; i < 10000; i++) ;
照你的逻辑,你给说说这两个算法的时间复杂度呢!

还是那句话,先去查查定义再说!
0 请登录后投票
   发表时间:2013-05-21  
dohkoos 写道
@mike.liu

再次再次把池中物的这句话回复你
引用

算法复杂度纯粹是从数学的角度来分析的。
是指随问题规模扩大的增长趋势,线性的、指数的、对数...等。


时间复杂度 != 运行时间

时间复杂度是个理论问题
运行时间是个实际问题

sb.append("a");
s += "a"
都是基本操作,谈时间复杂度的时候是不算时间的。

for (int i = 0; i < 100; i++) ;
for (int i = 0; i < 10000; i++) ;
照你的逻辑,你给说说这两个算法的时间复杂度呢!

还是那句话,先去查查定义再说!


呵呵,这样理解的话,我说的是另外一个时间复杂度,与您说的这个不同。我那个和实际执行时间有关。暂取名为“菜鸟的时间复杂度”吧,以免与您定义的时间复杂度冲突。
0 请登录后投票
   发表时间:2013-05-21  
你就说代码的执行时间呗。
0 请登录后投票
   发表时间:2013-05-21  
dohkoos 写道
你就说代码的执行时间呗。

通过与各位的讨论,我梳理了一下我对我所谓的“时间复杂度”的认识。
最早接触这个概念,应该是从《计算机程序设计艺术》这部书(只是大致看了下,认真阅读都算不上)。只记得里面作者自己定义了一套类似机器指令的东西,每条指令都是一个时间单位。然后他所有的算法都是基于这套机器指令集。这样,每个算法要执行多少步是明确的,所以在他那里定义的时间复杂度是明确的,没有问题的,基本上等于执行的步数。这是因为没有抽象语句。每个抽象语句,在底层都可能翻译为若干机器指令,很多还与具体的数据量有关(比如:s+="a"这种语句)。忽略抽象语句本身有时间复杂度问题,会使算法时间复杂度的分析失去其意义。

如果抽象语句本身不考虑时间复杂度问题,则我与您意见一致。但是,我认为这样的时间复杂度分析没有多大实际用途。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics