S X Answer - ------ -- ------- 0 "0" 1 0 1 "10" 9 1: Only "10" 2 "471" 47 2: "471" and "71" 3 "2222" 97 3: "2222" and both instances of "222"
What's the Big-O here? O(n2) substrings when the string is size n. Substring extraction and conversion is O(n). So the lame solution is O(n3). With n capped at 20, I think we're good to go -- we don't need to do anything smart.
I suspect that the reason that only 63% of the coders got this one is due to two reasons:
for (i = 0; i < S.size(); i++) { for (j = 0; j < i; j++) { // Starting index is j. // Ending index is i. |
for (i = 0; i < S.size(); i++) { for (j = i+1; j <= S.size(); j++) { // Starting index is i. // Ending index is j. |
for (i = 0; i < S.size(); i++) { for (j = 1; i + j <= S.size(); j++) { // Starting index is i. // Size is j. |
I'm going to suggest to you that the third is the best, largely because it then makes it easy to extract the substring with S.substr(i,j).
As far as converting to a long long, I'd use sscanf() from C stdio library. You don't need to error check, because S is guaranteed to hold digits and fit into a long long. In the topcoder version of the problem, atoi() will work, since it returns in int.
If you're not using sscanf(), then you'll need to use a stringstream.
The most efficient solution here is to use C entirely, and to enumerate the starting and ending indices. Then, you store the ending character, change it to the null character, call sscanf(), and change the ending character back. That avoids all the substring copying of the C++ solutions.
Regardless, the constraints here are so small that it doesn't matter.
I'll put all three solutions below:
int DigitStringDiv2::count(string S, int X) { int start, size; int total; string sub; long long val; istringstream ss; total = 0; /* Enumerate all starting positions and sizes. */ for (start = 0; start < S.size(); start++) { if (S[start] != '0') { for (size = 1; start+size <= S.size(); size++) { /* Extract the substring and turn it into a number. */ sub = S.substr(start, size); ss.clear(); ss.str(sub); ss >> val; /* Add one to the total if the number is big enough. */ if (val > X) total++; } } } /* Return the total. */ return total; } |
/* Enumerate all starting positions and sizes. */ for (start = 0; start < S.size(); start++) { if (S[start] != '0') { for (size = 1; start+size <= S.size(); size++) { /* Extract the substring and turn it into a number. */ sub = S.substr(start, size); sscanf(sub.c_str(), "%lld", &val); if (val > X) total++; } } } /* Return the total. */ return total; } |
int DigitStringDiv2::count(string S, long long X) { int i, j; int c; char *s; int total; long long val; /* Make a C-string copy of the string */ s = strdup(S.c_str()); total = 0; /* Enumerate all starting and ending indices: */ for (i = 0; i < S.size(); i++) { if (s[i] != '0') { for (j = i+1; j <= S.size(); j++) { /* Copy the end character, set it to the null character, convert with sscanf and restore the end character. */ c = s[j]; s[j] = '\0'; sscanf(s+i, "%lld", &val); if (val > X) total++; s[j] = c; } } } /* Return the total. Since you want to avoid memory leaks, you should free s too. */ free(s); return total; } |