Should this have time complexity of O(inputString.length * N) since append() copies the input string to the end of the StringBuilder N times?
Yes.
Why do we consider that append() takes O(1) time complexity whereas it should be considered as O(inputString.length)?
It is O(1) when appending single characters. A StringBuilder is like an ArrayList. When you append a single item the cost is O(1). Appending a string is like calling addAll()--the cost is proportional to the length of the string / the number of items being added.
It appears you understand everything correctly. The problem is people are often sloppy when discussing Big-O performance. It's endemic.
Answer from John Kugelman on Stack OverflowShould this have time complexity of O(inputString.length * N) since append() copies the input string to the end of the StringBuilder N times?
Yes.
Why do we consider that append() takes O(1) time complexity whereas it should be considered as O(inputString.length)?
It is O(1) when appending single characters. A StringBuilder is like an ArrayList. When you append a single item the cost is O(1). Appending a string is like calling addAll()--the cost is proportional to the length of the string / the number of items being added.
It appears you understand everything correctly. The problem is people are often sloppy when discussing Big-O performance. It's endemic.
I guess we are talking about appending single characters. Appending a string of length N would have an O(N).
Answer: Because with increasing length, copying becomes less frequent by the same factor by which it becomes more expensive.
Let's assume the capacity doubles when full. Doesn't matter, could be a factor of 1.1, 3, or whatever, but it's easier to talk about.
Doubling 1 needs to copy 1000 chars, which on average over these first 1000 means 1 char to copy per char appended.
Doubling 2 needs to copy 2000 chars, which on average over the past 1000 after the first copy means 2 chars to copy per char appended.
Doubling 3 needs to copy 4000 chars, which on average over the past 2000 means 2 chars to copy per char appended.
Doubling 4 needs to copy 8000 chars, which on average over the past 4000 means 2 chars to copy per char appended.
&c.
So before the first doubling, it's free, then you pay half the price, and the the price settles at 2 chars per char appended on average.
StringBuilder and Kotlin - Kotlin Discussions
java - Space complexity of the "add two binary strings" challenge - Code Review Stack Exchange
Appending character at the front in the StringBuilder
just do a .reverse on the sb.toString() at the end.. surely that's 10x more readable
More on reddit.comWhy Is StringBuilder O(n) In Java?
Videos
I have this piece of code
StringBuilder sb = new StringBuilder(); if(strX.charAt(i-1)==strY.charAt(j-1)){ sb.insert(0,strX.charAt(i-1)); }
I get error on the HackerRank that terminated due to timeout. If I remove this piece of code, everything else works fine.
I was wondering if
-
this is the optimized way to keep on appending characters at the front?
-
Does this approach work?
just do a .reverse on the sb.toString() at the end.. surely that's 10x more readable
-
Inserting at index 0 has a time complexity of O(n). So if you already have 500 characters in the internal array, it needs to shift those 500 chars over just to make space for the new char at the first index. So no, it is not.
-
Yes, it works.
Do what OffbeatDrizzle suggests, or simply create a function that will iterate over the StringBuilder in reverse and print out the contents- assuming this is what is required. If you need an object then reversing it at the end is the best way.
Here's some other points to consider.
Checking for empty string and null seems to be redundant. The compiler treats them the same.
Your check for null, only checks if both are null. For completion it would be better to also check if either is null.
I think it would be more performant to use a char array set to the longest length possible(length of longest string plus 1) and change the value at each index, rather than constantly appending to the StringBuilder.
You aren't checking for malformed strings.
You aren't handling strings of different lengths.
With all these taken into consideration your code could look something like this:
final static char ZERO_CHAR_VALUE = '0';
final static char ONE_CHAR_VALUE = '1';
final static char DEFAULT_CHAR_VALUE = '\0';
public static String AddBinary(String inValA, String inValB) {
if (inValA == null) {
if (inValB == null) {
return null;
}
return inValB;
}
if (inValB == null) {
return inValA;
}
int aIndex = inValA.length() - 1;
int bIndex = inValB.length() - 1;
int longestLength = Math.max(aIndex, bIndex) + 2;
char[] tempOutVal = new char[longestLength];
int tempOutIndex = tempOutVal.length - 1;
char aTemp;
char bTemp;
for (; aIndex >= 0 && bIndex >= 0; aIndex--, bIndex--, tempOutIndex--) {
aTemp = inValA.charAt(aIndex);
BinaryCharValidator(aTemp, inValA);
bTemp = inValB.charAt(bIndex);
BinaryCharValidator(bTemp, inValB);
SetValue(aTemp, bTemp, tempOutVal, tempOutIndex);
}
if (aIndex >= 0) {
for (; aIndex >= 0; aIndex--, tempOutIndex--) {
aTemp = inValA.charAt(aIndex);
BinaryCharValidator(aTemp, inValA);
bTemp = ZERO_CHAR_VALUE;
SetValue(aTemp, bTemp, tempOutVal, tempOutIndex);
}
}
if (bIndex >= 0) {
for (; bIndex >= 0; bIndex--, tempOutIndex--) {
aTemp = ZERO_CHAR_VALUE;
bTemp = inValB.charAt(bIndex);
BinaryCharValidator(bTemp, inValB);
SetValue(aTemp, bTemp, tempOutVal, tempOutIndex);
}
}
return new String(tempOutVal);
}
public static void SetValue(char aVal, char bVal, char[] outVal, int outIndex) {
if (outVal[outIndex] == DEFAULT_CHAR_VALUE) {
outVal[outIndex] = ZERO_CHAR_VALUE;
}
int aTemp = aVal - ZERO_CHAR_VALUE;
int bTemp = bVal - ZERO_CHAR_VALUE;
int outTemp = outVal[outIndex] - ZERO_CHAR_VALUE;
int sum = aTemp + bTemp + outTemp;
outVal[outIndex] = (char) ((sum % 2) + ZERO_CHAR_VALUE);
if (sum > 1) {
outVal[outIndex - 1] = ONE_CHAR_VALUE;
} else {
outVal[outIndex -1] = ZERO_CHAR_VALUE;
}
}
public static void BinaryCharValidator(char toCheck, String input) {
if (!(toCheck == ZERO_CHAR_VALUE || toCheck == ONE_CHAR_VALUE)) {
throw new IllegalArgumentException(String.format("Malformed string(only 1's and 0's allowed). The string is \"%s0\"", input));
}
}
I agree with you, space complexity should be \$O(n)\$, using StringBuilder should not matter because, internally it would store char in an array which would expand / shrink as needed.
Now some code-reviews.
Error check:
Null check?
xorycould benull. This(x == null || y == null)looks better.Your code says
"sumofbinary", but what if your string was"123" + "543"?
Name check:
sbis not a professional name, call itsum.
Syntax check:
while(i > = 0 || j >= 0) ..there is a space> =fori > = 0, but not forj.
Misc:
StringBuildercan be markedfinal.You end for loop when both
i&jare0. This has a drawback, ifiis longer thanj, you would waste error checking if (j > 0).