Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

String concatenation complexity in C++ and Java [duplicate]

Consider this piece of code:

public String joinWords(String[] words) {     String sentence = "";     for(String w : words) {         sentence = sentence + w;     }     return sentence; } 

On each concatenation a new copy of the string is created, so that the overall complexity is O(n^2). Fortunately in Java we could solve this with a StringBuffer, which has O(1) complexity for each append, then the overall complexity would be O(n).

While in C++, std::string::append() has complexity of O(n), and I'm not clear about the complexity of stringstream.

In C++, are there methods like those in StringBuffer with the same complexity?

like image 906
ethanjyx Avatar asked Mar 14 '13 03:03

ethanjyx


People also ask

What is the time complexity of string concatenation in Java?

On each concatenation a new copy of the string is created, so that the overall complexity is O(n^2). In Java, the complexity of s1. concat(s2) or s1 + s2 is O(M1 + M2) where M1 and M2 are the respective String lengths.

Is string concatenation slow in Java?

Let me say the reason that string concatenation is slow is because strings are immutable. This means every time you write "+=", a new String is created. This means the way you build up your string is in the worst case, O(n2).

Is string format faster than concatenation Java?

Therefore, concatenation is much faster than String.

Why is string concatenation N 2 in Java?

String concatenation It can be a bit surprising, but this code actually runs in O(N2) time. The reason is that in Java strings are immutable, and as a result, each time you append to the string new string object is created. The loop in the code does 1 + 2 + 3 + ... + N = N * (N + 1) / 2 = O(N2) operations.


1 Answers

C++ strings are mutable, and pretty much as dynamically sizable as a StringBuffer. Unlike its equivalent in Java, this code wouldn't create a new string each time; it just appends to the current one.

std::string joinWords(std::vector<std::string> const &words) {     std::string result;     for (auto &word : words) {         result += word;     }     return result; } 

This runs in linear time if you reserve the size you'll need beforehand. The question is whether looping over the vector to get sizes would be slower than letting the string auto-resize. That, i couldn't tell you. Time it. :)

If you don't want to use std::string itself for some reason (and you should consider it; it's a perfectly respectable class), C++ also has string streams.

#include <sstream> ...  std::string joinWords(std::vector<std::string> const &words) {     std::ostringstream oss;     for (auto &word : words) {         oss << word;     }     return oss.str(); } 

It's probably not any more efficient than using std::string, but it's a bit more flexible in other cases -- you can stringify just about any primitive type with it, as well as any type that has specified an operator <<(ostream&, its_type&) override.

like image 85
cHao Avatar answered Oct 11 '22 11:10

cHao