Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I was asked to implement a stack that pops the most frequently added item in an interview. I gave him the below answer but he was not happy with the solution.
class stack
{
// Map of value and count
map<int,int> Cntmap;
public:
void push(int val)
{
// Find val in map
// if found then increment map count
// else insert a pair (val,1)
}
int pop( )
{
// Find the Key in Cntmap with max value
// using std::max_element
// Decrement the Cntmap count for the popped val
}
}
Can anyone help me with the correct approach?
It's an interesting question, because in push, you look up
using the key, and in pop, using the mapped value. std::map
supports the first immediately: all you have to do is:
++ CntMap[ val ];
The [] operator will insert an entry if the key isn't
present, initializing the mapped type with its default
constructor, which for an int results in 0. You don't even
need the if.
The second is more difficult. The comments, however, give the
solution: all you need is a custom Compare, which takes two
std::pair<int, int>, and compares the second element.
std::max_element will return an iterator to the entry you're
interested in, so you can use it directly. So far so good (and
very simple), but you have to consider error conditions: what
happens if Cntmap is empty. And you might want to remove the
element if the count goes down to 0 (again, simple, since you
have an iterator designating the entry, with both the key and
the value).
Finally, if this is an interview question, I would definitly
point out that the pop operation is O(n), and that it might
be worthwhile (although significantly more complicated) to
maintain a secondary index, so that I could find the maximum
element more quickly. (If I were interviewing, that would be my
next question. Clearly for advanced programmers, however.)
The problem with only using a single (simple) data structure is that one of the operations will have to be linear (it has to search through all the elements), which is not good enough. In your case, I believe the linear-time operation is pop.
My attempt:
Have a linked-list (which will be ordered by frequency).
Have a map of values to nodes in the linked-list.
To push, look up the value in the map to get the linked-list node.
If found, increment the frequency and move the node appropriately to keep the linked-list sorted.
If not found, set the frequency to one and insert into the linked-list in the appropriate place.
To pop, decrement the frequency of first node of the linked-list and move it appropriately to keep the linked-list sorted, and return the applicable value.
You could have some pretty bad worst-case behaviour if there are many nodes with the same frequency. It should be possible to get constant time add / increment / decrement by having some sort of linked-list of linked-lists, with each node in the large linked-list representing a specific frequency and each linked-list from there representing all nodes having that frequency.
With the above optimization, pop can be O(1) and push can be O(log n). If you use an unordered_map (C++11), push can be O(1).
Another (probably slightly simpler) option is to do something similar to the above, but with a heap instead of a linked-list.
I think instead of a Map, Max-Heap will be better in your case. You can maintain a counter in a similar way. Note that the key of the heap will be the count rather than the actual value itself. When you have to insert a value, search for that value, if found, increment it's key, else, insert the value with key as 1.
Hope this helps.
The solution could be to wrap Boost.Bimap (does the organisation uses boost?). With this you could create a container which gives ordered access in one direction and hashed in the other. Your implementation of push and pop would use replace function of bimap.
Related
Consider I have a min priority queue with the smallest value on the top, I hope to reduce the value on the top so that the property of the queue would still be maintained and time complexity would be O(1). How to do that?
I have seen the question here how to change the value of std::priority_queue top()?
Where take the value out, modify it and push it back basically would be O(logN) complexity, I wonder can I make use of the property of reducing the value so that there is no need to push the value back again?
The standard priority queue doesn't support changing the keys.
What you are looking for is something similar to another data structure called Indexed Priority Queue, often used by Dijkstra algorithm.
The Indexed Prioirty queue supports 2 more methods in it's API: increaseKey and decreaseKey enabling modifying the key's itself.
The STL doesnt define indexed priority queue. You'd probably need to implement one by yourself or look for some third party implementation.
I see the point of this question differently from others. Based on this question,
I have a min priority queue with the smallest value on the top, I hope to reduce the value on the top so that the property of the queue would still be maintained and time complexity would be O(1).
With std::priority_queue, you can't. We may try a hack like const_cast<int &>(pq.top()) = lesser_value_than_top. It could work in some implementations, but it is NOT safe.
So, I would like to suggest building your own PQ with an array-based heap, and you can just change the top's value without log(N) work, as long as it is a value equal or less than the current top.
I am tasked with programming an A* Search Algorithm for an assignment that involves solving an '8-Puzzle'.
One of the algorithm's steps is to:
Add all the extended paths to Q. If the descendant state is already in Q, keep only the shorter path to state in Q (where Q is a Priority Queue (PQ)).
As such, I will need to search the PQ if an identical state exists but has a shorter path. If an identical state already exists but it has a longer path, I will need to delete this state from the PQ.
I have been directed to use an STL PQ, not my own implementation. I have managed to implement other types of searches using the below to create a Min PQ - which works as desired.
auto cmp = [](Puzzle* a, Puzzle* b) {
return a->getHCost() > b->getHCost();
};
std::priority_queue<Puzzle*, std::vector<Puzzle*>, decltype(cmp)> Q(cmp);
How can I extend my implementation so that...
I can perform a brute force search - looping through each element of the STL PQ?
I can delete an element somewhere in the STL PQ by its index? - shuffling elements 'upwards' if appropriate.
You could have a secondary array named shortest[] where shortest[i] would be the shortest known path to the state i. Then whenever you get in the top of the PQ an element with state x, you check shortest[x] if it is indeed the shortest found and do whatever you want to it, else delete the element from the top of the PQ.
However, given that the states are from an 8-puzzle, you'd have to come up with an efficient way to give them a unique identifying number and ability to get it back efficiently.
It is possible to do both such things in O(1). I'm not sure if I should spoil my personal idea yet, given it is after all an assignment and you should undertake such a challenge.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
The community reviewed whether to reopen this question 6 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I made a program recently that dealt with a lot of if/else statements to return particular values. Someone recommended using lookup tables instead. My question is,
How do they work and how do you implement them?
What is the difference between a map, hash table, and lookup table.
My question is, how do they work and how do you implement it? What is
the difference between stl map, hash tables, and lookup tables.
What you're looking for is an efficient mechanism by which you can look up the value that corresponds to a given key.
Your current mechanism (a long list of if/else-if commands) is rather inefficient, in that if you have N possible values to choose from, you will (on average) have to compare your candidate key against (N/2) other keys before you find the one that matches and you can stop looking. (This is known as O(N) complexity)
So what are the other choices?
The simplest one is literally just an array of values, e.g.
const char* const myLookupTable[1000] = {
"zero",
"one",
"two",
[...]
"nine hundred and ninety-nine"
};
... with a lookup table like that, you take a key (which in this case is a number between 0 and 999, inclusive), and look up the corresponding value with a single array-lookup:
const char* val = myLookupTable[myKeyIndex];
That's super-efficient (O(1) complexity -- it always finishes in constant time, regardless of how big the array is!), but it only works in cases where your keys are unsigned integers in a continuous (and relatively small) range of values. For example, if your keys were strings, this approach wouldn't apply.
For more flexibility, the next option would be STL's std::map. std::map gives you fast key->value lookups from any key-type to any value-type. Internally it is implemented as a tree: each key-value pair is inserted into the tree in such a way that the tree remains sorted with the smallest keys at the left of the tree and the largest keys at the right. Because of that, looking up a key (and its associated value) in a std::map is just a matter of starting at the tree's root node and comparing the key at that node to the key you are looking up: is it less than your key? Then move to the right-hand child. Or it greater than your key? Then move to the left-hand child. Repeat that until you get to the bottom of the tree, at which point you'll either find the key-value pair you were looking for or you'll find that it's not present. This is an algorithm of O(log(N)) complexity, because for a tree with N values in it, it takes log(N) comparisons for the lookup to complete. O(log(N)) is considered pretty good efficiency.
The final data structure you mentioned is a hash table (as seen in std::unordered_map). A hash table does things a bit differently -- internally it is an array, but in order to avoid the limitations of the lookup-table approach, it also comes with an algorithm for figuring out where in its array a given key/value pair is to be stored. It does this by calculating a hash code for the key-object you pass in -- and then using that code to compute an offset into the array (e.g. int array_offset = hash_code % array_size) and looking at that slot in the array to see if the requested key-value pair is there. If it is, then it's done (O(1) performance again!); or if the slot is empty, then it knows that your key isn't in the table and can return failure immediately (O(1) again). If the slot is occupied by some other key/value pair, then the hashtable will need to fall back to another algorithm to sort out the hash collision; different hash tables handle that different ways but it's generally still fairly efficient.
Your question is really to broad since StackOverflow is not a tutorial site, but I feel kind this morning...
A "lookup table" is simply a container (any kind of container) that contains values you look up, and usually map to some other value.
In its simplest form, consider the following:
struct MapIntToString
{
int value;
char* string;
};
MapIntToString my_map[] = {
{ 1, "one" },
{ 2, "two" },
{ 3, "three" },
// ...
};
The above could be considered a lookup table. You can iterate (loop) over my_map to find (look up) the integer 2 and then pick the string "two" from it.
Depending on your need and use-case the above example might not be enough. The code above is basically how it is commonly done in plain C, not C++. For C++ there are better containers for mapping values, like std::map and std::unordered_map.
However sometimes the standard types might not be enough, and there are many other data-structures that could be implemented for looking up things.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 5 years ago.
Improve this question
Assume I have a multiset as {1,3,5,7,9}. I want to find what is the 3rd element in this multiset using C++. How can I do that without using a loop?
A multiset is normally implemented as a tree, so you have to traverse through it node by node to find a particular node in order. In other words, regardless of how you express it (loop or otherwise) it's going to take N operations to get to the Nth item in the tree.
If your interest is purely in avoiding writing the loop, you can...disguise it by using something like:
auto p = mySet.begin();
std::advance(p, 2);
...but that will only hide the loop inside of advance, not really eliminate it. std::next will do the job as well, but (again) just hides the loop, doesn't eliminate it.
Although std::set/std::multiset don't provide it, if you need to do this a lot, there is specialized variant of a tree that supports finding the Nth element in O(log N) time (with O(N) space overhead).
Along with the data normally in the tree, in each node, you store the number of elements in that node's sub-trees. You start by finding the index of the root by subtracting the size of its left sub-tree from its own size. If the index you're looking for is greater than that, you descend to the right. If it's less, you descend to the left (and if its equal, you've found the node you're looking for).
As you descend, you need to keep a running count of your location. You've already figured out the index of the root, so you keep that in the running count. Then when you descend into a node, if you're descending to the right you add the 1 + size of new node's left sub-tree. If you're descending to the left, you subtract 1 + size of right sub-tree.
To maintain the counts, as you're inserting anytime you descend through a node you increment its count (and as you're deleting, you decrement its count--but only after verifying that the value to be deleted was present).
If you want to search for more details, this is normally called an "order statistic tree".
this one should point to the 2th element of the array
int a[] = {1,3,5,7,9}; int *p = a; std::cout << *(++a) <
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I am writing a chess engine in c++, and am trying to make as clean and correct code as possible, as this is a learning exercise.
Currently, I have a move class, which defines a possible move. The AI then scores every possible move. What is the best way to pair the score of the move with the move itself in a data structure?
It has to be able to have more than one move per a score (two moves can both have score of 735). I think that rules out std::map?
It should also be quickly sortable, so I can look ahead and recursively do this for the best moves.
Any help would be appreciated, including links. thanks!
Your question isn't entirely clear. On one hand, you say you want a sorted container, but on the other, the way you talk about things is that you're going to generate moves, put them into a container, then sort them according to criteria defined by your AI.
Let's consider those separately. For the first, we'll assume you want to use the scores as a key, and look up the moves that go with particular scores. In this scenario, you'll generate a move, the AI will score that move, then you'll store the move, with its score as the key. Since you can have multiple moves with the same score (i.e., equivalent keys), the data structure you want for this case is an std::multimap.
The other possibility would be that you generate all the moves, put them all into a data structure, score them all, then sort them all by score. For this scenario, you probably want to use an std::vector<std::pair<score_type, move>>. In this case, when you generate each move you'd probably assign it a score of something like 0. Then you'd walk through the vector and have the AI generate a score for each move. Then you'd sort them, using a comparison function that only considers the score.
Either of these could work. The one that's preferable would depend on circumstances. Using a vector is likely minimize overhead--that is, it'll use the least memory and least CPU time to get from raw moves to a vector with all the moves stored in sorted order.
The strength of an std::multiset is that it stays sorted all the time. For example, if you want to generate moves until you reach some time limit, it'll let you accomplish that quite cleanly--generate a move, score it, insert it into the multiset. No matter when you stop, all the moves you generated up to that point are already sorted, so (for example) if the person playing against your program can force the AI to make a move immediately, the AI always has a record of the best move its found yet, so it can immediately make the move it "thinks" is best.
Another possibility would be to use a priority queue. In a typical case for chess, one thing you'll do is generate (say) a couple dozen or possible next moves. Then you'll pick the best of those, and score possible counter-moves to those. Then you'll pick the best of those and score the counters to those moves, and so on until you've scored (say) 4 or 5 full moves deep.
For this, you don't really care about having all the moves in order--you just want to be able to retrieve the N best moves quickly. For that case, a priority queue works quite well. You can retrieve the N best moves, then ignore the rest. This means you only fully sort the N best moves (the ones you care about) and minimize the overhead for the rest, but only doing enough to verify that they have lower scores.
I should also mention that if this is what you really want, you can accomplish the same in the array case. Instead of using sort to sort all the moves into order by score, you can use nth_element to find only the N best scores. nth_element arranges an array/vector into two groups: those that would sort before some selected element, then the selected element, then the ones that would sort after that selected element. For example, given 100 moves, of which you want to keep the top 5, you'd use nth_element to arrange them into the 95 lesser moves, the 95th element, then the other 4. No attempt is made at ordering the items within each group though.
The advantage of this is that it can be completed in O(N) time instead of the O(N log N) needed for a complete sort.
Between these two possibilities (priority_queue vs. nth_element) we get much the same tradeoff as between set::multiset and std::vector with std::sort: the priority_queue maintains its order at all times. It remains quite efficient, even if you intermingle insertions and removals more or less arbitrarily. With a std::vector and std::nth_element, you normally want to insert all the elements, then call nth_element, then consider the top items. If you were going to mix the two (insert some elements, then remove a few of the best, insert some more, remove a few more, etc.) you'd have to call nth_element every time you transitioned from inserting to removing, which could kill the efficiency fairly quickly.
It sounds like what you are looking for is a priority queue.
They are usually implemented using Heap (Fibonacci heap if you want efficiency). The heap itself is not completely sorted, but you are guaranteed to get the best move at the top, at any given moment.
Boost has a Fibonacci heap implementation.
You can look at this question. MyType in that question can be a std::pair of Data and Priority
std::set does what you need. std::set > where X is the score and Y is the class object or you can define your own custom comparator. see this: Using custom std::set comparator