【发布时间】:2014-10-20 06:22:04
【问题描述】:
在我看来,它应该是常数(O(1)) 时间复杂度。但是有人告诉我,在调用 stringBuilder.substring() 方法时必须实例化一个新的 String 对象。 (这不是静态方法)。如果这是真的,我怎样才能在恒定的时间复杂度内得到一个子字符串?
【问题讨论】:
标签: java string substring time-complexity stringbuilder
在我看来,它应该是常数(O(1)) 时间复杂度。但是有人告诉我,在调用 stringBuilder.substring() 方法时必须实例化一个新的 String 对象。 (这不是静态方法)。如果这是真的,我怎样才能在恒定的时间复杂度内得到一个子字符串?
【问题讨论】:
标签: java string substring time-complexity stringbuilder
您不可能在恒定时间内从StringBuilder 创建String 并保持其不变性。此外,从 Java 7 Update 25 开始,即使 String#substring() 也是线性时间,因为结构共享实际上造成的麻烦比它避免的要多:巨大字符串的子字符串保留了对巨大 char 数组的引用。
【讨论】:
在我看来,时间复杂度应该是常数(O(1))。
这是不可能的。由于 Java 字符串是不可变的,而 StringBuilders 是可变的,所有产生 String 的操作都必须进行复制。
如果这是真的,我怎样才能在恒定的时间复杂度内得到一个子字符串?
你不能。如果没有副本,更改子字符串中的字符会改变 String,这是不允许的。
【讨论】:
StringBuilder.substring() 返回String 的子类,而不是由char[] 支持,而是由父String 支持和一个偏移量告诉它从哪里开始/结束?无需复制。
String。有一个父 StringBuilder,它是可变的。
String 是 final。当您收到来自调用者的String 时,您希望确定其不变性是有保证的属性。
StringBuilder 的子字符串实际上将字符从开始索引复制到结束索引,因此它尝试将子字符串长度(即结束索引-开始索引)的字符的数组副本。这将是此操作 O(substringlength) 的时间复杂度,因为循环从开始索引运行到结束索引,这是无法避免的。有了这个子字符串 char[],字符串对象将被实例化。
【讨论】: