Re: is it the best solution?
Help has been given for this elsewhere.
Re: is it the best solution?
Quote:
Originally Posted by
atikot
can anyone help me come up with more reasonable solution?
This really isn't a C question but a data structures & algorithms question.
The standard solution is to introduce a table of counters, one for each search item (letter). Generally a hash table is used but if the range of the search items (letters) is limited an array can be used instead.
This procedure will turn an O(N*N) algorithm into an O(N) one. A huge improvement. You can build a successful consulting carreer on this piece of knowledge alone.
In this particular case you need to sort the result afterwards because of the order requirement. Alternatively, and favourably, the table of counters is inherently sorted. Then no post processing will be needed. You just print the table from beginning to end.
Re: is it the best solution?
Quote:
Originally Posted by
nuzzle
This really isn't a C question but a data structures & algorithms question.
The standard solution is to introduce a table of counters, one for each search item (letter). Generally a hash table is used but if the range of the search items (letters) is limited an array can be used instead.
This procedure will turn an O(N*N) algorithm into an O(N) one. A huge improvement. You can build a successful consulting carreer on this piece of knowledge alone.
In this particular case you need to sort the result afterwards because of the order requirement. Alternatively, and favourably, the table of counters is inherently sorted. Then no post processing will be needed. You just print the table from beginning to end.
Wouldnt it be easier in this case to just sort the string first and then browse the string to merge consequent equivalent characters to fit the requirement.
Basically it would transform this string "bhiihbBHIIHB" to this "bbBBhhHHiiII" and then to this "2b, 2B, 2h, 2H, 2i, 2I".
I think that at the very least this algorithm would be equally as efficient as what you suggested.
Re: is it the best solution?
Quote:
Originally Posted by
blaurent
I think that at the very least this algorithm would be equally as efficient as what you suggested.
You solution will be O(N*logN) whereas the standard solution is just O(N).
The OP's problem is special due to the alphabetic ordering requirement. Generally it would require an extra sort step to be performed after the standard solution has finished which would result in a worst(*) total complexity of O(N*logN). But if an array is used as table and the letter entries appear in wanted sort order the sort step is avoided and the algorithm stays O(N).
So in summary the standard solution is the fastest. Even with a post-sort it's likely be faster and at the worst equally fast to what you suggested.
(*) The complexity actually is O(N) + O(K*logK) where K is the number of unique letters among the total input of N letters. This becomes O(N*logN) in the worst case when there are no repeated letters that is when K is equal to N.
Re: is it the best solution?
Quote:
Originally Posted by
nuzzle
You solution will be O(N*logN) whereas the standard solution is just O(N).
The OP's problem is special due to the alphabetic ordering requirement. Generally it would require an extra sort step to be performed after the standard solution has finished which would result in a total complexity of O(N*logN). But if an array is used as table and the letter entries appear in wanted sort order the sort step is avoided and the algorithm stays O(N).
So in summary the standard solution is the fastest and even with a post-sort it's not slower than what you suggested.
Yes actually the sort step of your algorithm is just a supplement and not an integral part so you can always drop it off in case the requirement changes.
Still I believe that there's a way to optimize your algorithm, say with a preinitialized map which dictates the sort order, say charCounts{'a','b','c','d','e','f','g','h',....} which stores for each entry an integer. Then once you've initialized the counts for each entry, you just iterate once over the items and generate the result string. This would then give an approximate complexity of O(2*N).
With this you could just drop the entire sort feature. On the downside of course the charCounts array needs to be maintained....
Re: is it the best solution?
Quote:
Originally Posted by
blaurent
Yes actually the sort step of your algorithm is just a supplement and not an integral part so you can always drop it off in case the requirement changes.
Still I believe that there's a way to optimize your algorithm, say with a preinitialized map which dictates the sort order, say charCounts{'a','b','c','d','e','f','g','h',....} which stores for each entry an integer. Then once you've initialized the counts for each entry, you just iterate once over the items and generate the result string. This would then give an approximate complexity of O(2*N).
With this you could just drop the entire sort feature. On the downside of course the charCounts array needs to be maintained....
In this solution you suggest using a map as table. This will slow down the algorithm to O(N*logN).
The reason is that in the standard solution accesses to the table is O(1). This is the case when the table is hash based or an array. But it's not the case when the table is a map as you suggest. A map is tree based and has O(logN) accesses. One O(N) pass with O(logN) accesses results in an O(N*logN) algorithm (and not O(2*N)).
So the standard solution is hard to beat here. It's O(N) and even with a post-sort step it will be O(N*logN) at the most (when all letters are different but the more repeated letters there are the more it will tend towards O(N)).
Re: is it the best solution?
Quote:
Originally Posted by
nuzzle
In this solution you suggest using a map as table. This will slow down the algorithm to O(N*logN).
The reason is that in the standard solution accesses to the table is O(1). This is the case when the table is hash based or an array. But it's not the case when the table is a map as you suggest. A map is tree based and has O(logN) accesses. One O(N) pass with O(logN) accesses results in an O(N*logN) algorithm (and not O(2*N)).
So the standard solution is hard to beat here. It's O(N) and even with a post-sort step it will be O(N*logN) at the most (when all letters are different but the more repeated letters there are the more it will tend towards O(N)).
Ah yes of course! You're right.
Thanks for the explanation.