How can I generate the following tree of permutations in C++? - c++

Suppose we have the string ABCD
I would like to create the following tree:
ABCD <------ level 1
ABC ABD ACD BCD <------ level 2
AB AC AD BC BD CD <------ level 3
A B C D <------ level 4
And save it inside a vector in the following order:
ABCD->ABC->ABD->ACD->BCD->AB->AC->AD->BC->BD->CD->A->B->C->D
So from the starting point, I want to generate the nodes of the next level, store them inside the vector, then generate the nodes of the next level and do the same thing for all the remaining levels
I have created the following program to generate level 2 from level 1.
void test(int dimensions, vector<string> & nodes, const char* currentNode){
int i,j;
for(i=dimensions-1;i>=0;i--){
char *temp = new char[dimensions];
int counter = 0;
for(j=0;j<dimensions;j++){
if(j!=i){
temp[counter] = currentNode[j];
counter++;
}
}
temp[counter] = '\0';
nodes.push_back(temp);
}
}
which is called from main:
vector<string> nodes;
int dimension = 4;
nodes.push_back("ABCD");
test(dimension, nodes, "ABCD");
This gives me the following:
As you can see the nodes of the level 2 are added successfully, however if I try to apply recursion here, for example for node "ABC"
I would get as a result:
AB -> AC -> BC
These will be saved successfully, however if the recursion keeps going, for example for node AB now it will find A -> B
so the the resulting order of the nodes saved in the vector won't be how I described in the beginning.
Instead of
ABCD->ABC->ABD->ACD->BCD->AB->AC->AD->BC->BD->CD->...
it will be
ABCD->ABC->ABD->ACD->BCD->AB->AC->A->B->...
Finally, I would like the computation of this tree to be generalized for any number of dimensions. For example the initial node could be ABCD or ABCDEFGHIJKLM.
For some reason I believe this is very difficult to do, however I'm not exactly certain about it. Note that I don't want to use any external libraries for computing the permutations, I need to understand 100% the code in order to proceed with the algorithm that I want to implement.
Thank you in advance

As stated in the comments, I don't see how this is remotely related to permutations, but here's the code for what I think you're trying to achieve:
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
typedef std::vector<std::string> Layer;
Layer getNextLayer(const Layer &);
int main()
{
std::vector<Layer> layers;
layers.push_back(Layer());
layers[0].push_back("ABCDE");
while ( layers.back().back().size() > 1 )
{
layers.push_back(getNextLayer(layers.back()));
for ( size_t i = 0; i < layers.back().size(); ++i )
{
std::cout << layers.back()[i] << " ";
}
std::cout << "\n";
}
}
Layer getNextLayer(const Layer &layer)
{
Layer result;
for ( size_t i = 0; i < layer.size(); ++i )
{
const std::string item = layer[i];
for ( size_t j = 0; j < item.size(); ++j )
{
std::string new_item = item;
new_item.erase(new_item.begin() + j); // erase j^th charachter from item
result.push_back(new_item);
}
}
std::sort(result.begin(), result.end());
result.erase(std::unique(result.begin(), result.end()), result.end()); // erase duplicates
return result;
}
This creates each layer based on the last one. To store it all in one vector, you just have to merge all these layers.

Related

C++ permutation tree

I have tasks and I want to calculate the most profitable order to arrange them.
Instead of checking every permutation and doing n*n! calculations, I want to build a tree of permutations, that is, the number of children at each level decreases by 1, and at each node the sub-permutation that has already been calculated will be saved and not recalculated.
For example, if I have 4 tasks, the tree will look like this:
My attached code is missing. I don't know how to build the tree and the give nodes the indexes as in the figure. I know how to deal with a binary tree, but not with a tree where the number of children is different at each lavel.
(The value of each task depends on its location.
I know how to do that, so I didn't include it in the question).
int n = 4;
struct node
{
int task_index = -1;
double value;
struct node **next;
};
void build_tree(node *current_node, int current_level = 0)
{
if (current_level < 1 || current_level >= n)
return;
// current_node->task_index = ? ;
current_node->next = new node *[n - current_level];
for (int i = 0; i < n - current_level; i++)
{
build_tree(current_node->next[i], current_level + 1);
}
}
void print_tree(node *current_node, int current_level = 0)
{
// print indexes
}
void delete_tree(node *current_node, int current_level = 0)
{
// delete nodes
}
int main()
{
struct node *root = new node;
build_tree(root);
print_tree(root);
delete_tree(root);
delete root;
return 0;
}
void build_tree(node *current_node, int current_level = 0)
{
if (current_level < 1 || current_level >= n)
return;
// current_node->task_index = ? ;
current_node->next = new node *[n - current_level];
for (int i = 0; i < n - current_level; i++)
{
build_tree(current_node->next[i], current_level + 1);
}
}
When called with the default parameter of current_level = 0, as you illustrate in your code below, this function exits on the first line without doing anything. You need to decide whether you are indexing starting from 0 or from 1.
Other than that, the general outline of the algorithm looks okay, although I did not explicitly check for correctness.
Now, more broadly: is this an exercise to see if you can write a tree structure, or are you trying to get the job done? In the latter case you probably want to use a prebuilt data structure like that in the boost graph library.
If it's an exercise in building a tree structure, is it specifically an exercise to see if you can write code dealing with raw pointers-to-pointers? If not, you should work with the correct C++ containers for the job. For instance you probably want to store the list of child nodes in a std::vector rather than have a pointer-to-pointer with the only way to tell how many child nodes exist being the depth of the node in the tree. (There may be some use case for such an extremely specialized structure if you are hyper-optimizing something for a very specific reason, but it doesn't look like that's what's going on here.)
From your explanation what you are trying to build is a data structure that reuses sub-trees for common permutations:
012 -> X
210 -> X
such that X is only instantiated once. This, of course, is recursive, seeing as
01 -> Y
10 -> Y
Y2 -> X
If you look at it closely, there are 2^n such subtrees, because any prefix can have any one of the n input tasks used or not. This means you can represent the subtree as an index into an array of size 2^n, with a total footprint O(n*2^n), which improves on the vastly larger >n! tree:
struct Edge {
std::size_t task;
std::size_t sub;
};
struct Node {
std::vector<Edge> successor; // size in [0,n]
};
std::vector<Node> permutations; // size exactly 2^n
This will have this structure:
permutations: 0 1 2 3 4 ...
|-^
|---^
|-------^
|---^
|-^
Where the node at, e.g., location 3 has both task 0 and 1 already used and "points" to all (n-2) subtrees.
Of course, building this is not entirely trivial, but it compressed the search space and allows you re-use results for specific sub-trees.
You can build the table like this:
permutations.resize(1<<n);
for (std::size_t i = 0; i < size(permutations); ++i) {
permutations[i].successor.reserve(n); // maybe better heuristic?
for (std::size_t j = 0; j < n; ++j) {
if (((1<<j) & i) == 0) {
permutations[i].successor.push_back({j,(1<<j)|i});
}
}
}
Here is a live demo for n=4.
The recursive way to generate permutations is if you have n items then all of the permutations of the items are each of the n items concatenated with the permutations of the n-1 remaining items. In code this is easier to do if you pass around the collection of items.
Below I do it with an std::vector<int>. Once using a vector it makes more sense to just follow the "rule of zero" pattern and let the nodes have vectors of children and then not need to dynamically allocate anything manually:
#include <vector>
#include <algorithm>
#include <iostream>
struct node
{
int task_index = -1;
double value;
std::vector<node> next;
};
std::vector<int> remove_item(int item, const std::vector<int>& items) {
std::vector<int> output(items.size() - 1);
std::copy_if(items.begin(), items.end(), output.begin(),
[item](auto v) {return v != item; }
);
return output;
}
void build_tree(node& current_node, const std::vector<int>& tasks)
{
auto n = static_cast<int>(tasks.size());
for (auto curr_task : tasks) {
node child{ curr_task, 0.0, {} };
if (n > 1) {
build_tree(child, remove_item(curr_task, tasks));
}
current_node.next.emplace_back(std::move(child));
}
}
void print_tree(const node& current_node)
{
std::cout << "( " << current_node.task_index << " ";
for (const auto& child : current_node.next) {
print_tree(child);
}
std::cout << " )";
}
int main()
{
node root{ -1, 0.0, {} };
build_tree(root, { 1, 2, 3 });
print_tree(root);
return 0;
}

Getting a floating point exception error while doing text frequency analysis?

So for a school project, we are being asked to do a word frequency analysis of a text file using dictionaries and bucket hashing. The output should be something like this:
$ ./stats < jabberwocky.txt
READING text from STDIN. Hit ctrl-d when done entering text.
DONE.
HERE are the word statistics of that text:
There are 94 distinct words used in that text.
The top 10 ranked words (with their frequencies) are:
1. the:19, 2. and:14, 3. !:11, 4. he:7, 5. in:6, 6. .:5, 7.
through:3, 8. my:3, 9. jabberwock:3, 10. went:2
Among its 94 words, 57 of them appear exactly once.
Most of the code has been written for us, but there are four functions we need to complete to get this working:
increment(dict D, std::str w) which will increment the count of a word or add a new entry in the dictionary if it isn't there,
getCount(dict D, std::str w) which fetches the count of a word or returns 0,
dumpAndDestroy(dict D) which dumps the words and counts of those words into a new array by decreasing order of count and deletes D's buckets off the heap, and returns the pointer to that array,
rehash(dict D, std::str w) which rehashes the function when needed.
The structs used are here for reference:
// entry
//
// A linked list node for word/count entries in the dictionary.
//
struct entry {
std::string word; // The word that serves as the key for this entry.
int count; // The integer count associated with that word.
struct entry* next;
};
// bucket
//
// A bucket serving as the collection of entries that map to a
// certain location within a bucket hash table.
//
struct bucket {
entry* first; // It's just a pointer to the first entry in the
// bucket list.
};
// dict
//
// The unordered dictionary of word/count entries, organized as a
// bucket hash table.
//
struct dict {
bucket* buckets; // An array of buckets, indexed by the hash function.
int numIncrements; // Total count over all entries. Number of `increment` calls.
int numBuckets; // The array is indexed from 0 to numBuckets.
int numEntries; // The total number of entries in the whole
// dictionary, distributed amongst its buckets.
int loadFactor; // The threshold maximum average size of the
// buckets. When numEntries/numBuckets exceeds
// this loadFactor, the table gets rehashed.
};
I've written these functions, but when I try to run it with a text file, I get a Floating point exception error. I've emailed my professor for help, but he hasn't replied. This project is due very soon, so help would be much appreciated! My written functions for these are as below:
int getCount(dict* D, std::string w) {
int stringCount;
int countHash = hashValue(w, numKeys(D));
bucket correctList = D->buckets[countHash];
entry* current = correctList.first;
while (current != nullptr && current->word < w) {
if (current->word == w) {
stringCount = current->count;
}
current = current->next;
}
std::cout << "getCount working" << std::endl;
return stringCount;
}
void rehash(dict* D) {
// UNIMPLEMENTED
int newSize = (D->numBuckets * 2) + 1;
bucket** newArray = new bucket*[newSize];
for (int i = 0; i < D->numBuckets; i++) {
entry *n = D->buckets->first;
while (n != nullptr) {
entry *tmp = n;
n = n->next;
int newHashValue = hashValue(tmp->word, newSize);
newArray[newHashValue]->first = tmp;
}
}
delete [] D->buckets;
D->buckets = *newArray;
std::cout << "rehash working" << std::endl;
return;
void increment(dict* D, std::string w) {
// UNIMPLEMENTED
int incrementHash = hashValue(w, numKeys(D));
entry* current = D->buckets[incrementHash].first;
if (current == nullptr) {
int originalLF = D->loadFactor;
if ((D->numEntries + 1)/(D->numBuckets) > originalLF) {
rehash(D);
int incrementHash = hashValue(w, numKeys(D));
}
D->buckets[incrementHash].first->word = w;
D->buckets[incrementHash].first->count++;
}
while (current != nullptr && current->word < w) {
entry* follow = current;
current = current->next;
if (current->word == w) {
current->count++;
}
}
std::cout << "increment working" << std::endl;
D->numIncrements++;
}
entry* dumpAndDestroy(dict* D) {
// UNIMPLEMENTED
entry* es = new entry[D->numEntries];
for (int i = 0; i < D->numEntries; i++) {
es[i].word = "foo";
es[i].count = 0;
}
for (int j = 0; j < D->numBuckets; j++) {
entry* current = D->buckets[j].first;
while (current != nullptr) {
es[j].word = current->word;
es[j].count = current->count;
current = current->next;
}
}
delete [] D->buckets;
std::cout << "dumpAndDestroy working" << std::endl;
return es;
A floating-point exception is usually caused by the code attempting to divide-by-zero (or attempting to modulo-by-zero, which implicitly causes a divide-by-zero). With that in mind, I suspect this line is the locus of your problem:
if ((D->numEntries + 1)/(D->numBuckets) > originalLF) {
Note that if D->numBuckets is equal to zero, this line will do a divide-by-zero. I suggest temporarily inserting a line like like
std::cout << "about to divide by " << D->numBuckets << std::endl;
just before that line, and then re-running your program; that will make the problem apparent, assuming it is the problem. The solution, of course, is to make sure your code doesn't divide-by-zero (i.e. by setting D->numBuckets to the appropriate value, or alternatively by checking to see if it is zero before trying to use it is a divisor)

How to go about making a "Sorted Array to Balanced BST" recursion algorithm to an iterative one?

I've searched around but can't really understand or find help, since this iterative algorithm will require two stacks (to contain a left_Index and right_Index).
The main recursive way involves having it one side until the left_Index >= right_Index, and recursively doing so for both sides and per subsection (if that makes sense), which I don't understand how to do so exactly since I'm maintaining two stacks and need to see how exactly they relate to one another.
This problem is mostly due to me not understanding the way the normal recursive method words, although when looking at them side by side to see how to approach it, I always get stuck on what to do.
The backstory as to why I'm doing this:
Trying to solve the word ladder problem to go from A to B and decided to make a BST where the connections are connected by singular character differences and lengths. I'm getting the words from a text file containing a lot of the dictionary, and since I'm using a BST as the master list with all vertices the fact that this is a dictionary means every insert will be in order so the tree is right-leaning (so the speeds are slow for inserting O(n^2) which is a big hinderance). I was planning on storing data in an array then making a balanced BST from that since I believe speeds should go faster since insertion will be O(n*logn) which seems great. The problem with that is that I can't use a recursive approach since there's a lot of data leading to stack overflows, so I need to make it iteratively with stacks and loops, but am finding it too difficult.
My bad attempt at a start:
while (lindx.the_front() < rindx.the_back())
{
mid =(lindx.the_front() + rindx.the_back()) / 2;
dictionary.addVertex(vector[mid]);
std::cout << "Pushed " << vector[mid] << '\n';
rindx.push(mid - 1);
}
That basically gets the 1/2's from the left half of the program from a linked stack I made. "the_front()" is the first insertion, "the_back()" is the final/latest insert into the list. The main problem I have is understanding how to make it repeat per half to get all the values.
I need to find my past homework where I've done this but the code is something along the lines of...
void array2balanced(int array[], int lIndex, int rIndex)
{
//base case
if(lIndex > rIndex)
{
return;
}
//recursive cals
else
{
mid = (lIndex+rIndex)/2;
tree.insert(array[mid]);
array2balanced(array, lIndex, mid-1);
array2balanced(array, mid+1, rIndex);
}
}
UPDATE:
Progress so far
void balancedTree(std::vector<std::string> vector, dictionaryGraph &dictionary) // divide and conquer into tree?
{
linkedStack<int> lindx, rindx, midX;
unsigned int l_Index{ 0 }, r_Index{ vector.size() - 1 }, mid{ (l_Index + r_Index) / 2 };;
lindx.push(l_Index);
rindx.push(r_Index);
midX.push(mid);
int testCount{ 0 };
std::cout << "There are " << vector.size() << " words.\n";
while (!midX.empty())
{
mid = midX.pop();
l_Index = lindx.pop();
r_Index = rindx.pop();
std::cout << "inputted " << vector[mid] << '\n';
dictionary.addVertex(vector[mid]);
testCount++;
if (r_Index > l_Index)
{
midX.push((l_Index + mid) / 2);
lindx.push(l_Index);
rindx.push(mid - 1);
}
if (l_Index < r_Index)
{
midX.push((mid + r_Index) / 2);
lindx.push(mid + 1);
rindx.push(r_Index);
}
}
std::cout << testCount << " words were inputted...\n"; // To see how many were inserted
system("pause");
}
Problem I have is some inputs get repeated and some missed.
I don't think you need two stacks. You just need either a one stack or one queue.
Below codes can be tested on Leetcode
Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
One Stack Method
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
if not nums:
return None
l = len(nums)
node = TreeNode(0)
head = node
s = collections.deque([(node, 0, l)])
while s:
node, left, right = s.pop()
mid = (right + left) // 2
node.val = nums[mid]
if mid < right-1:
node.right = TreeNode(0)
s.append((node.right, mid+1, right))
if left < mid:
node.left = TreeNode(0)
s.append((node.left, left, mid))
return head
One Queue Method
def sortedArrayToBST(self, nums: List[int]) -> Optional[TreeNode]:
if not nums:
return None
l = len(nums)
node = TreeNode(0)
head = node
q = collections.deque([(node, 0, l)])
while q:
node, left, right = q.popleft()
mid = (right + left) // 2
node.val = nums[mid]
if left < mid:
node.left = TreeNode(0)
q.append((node.left, left, mid))
if mid < right-1:
node.right = TreeNode(0)
q.append((node.right, mid+1, right))
return head
They are implemented using deque. Notice popleft() returns the first element(like stack) and pop() returns the last element(like queue).
This problem is mostly due to me not understanding the way the normal
recursive method words, although when looking at them side by side to
see how to approach it, I always get stuck on what to do.
It takes practice ... and maybe reviewing other peoples work.
require two stacks (to contain a left_Index and right_Index).
My apologies, I do not understand why the OP thinks this. My demo below has only 1 stack called 'todo', perhaps you will find the idea useful.
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <vector>
#include <cassert>
#include "./BTree.hh" // code not provided, used in this MCVE to
// conveniently provide "showTallTreeView()"
typedef std::vector<int> IVec_t;
class T607_t
{
IVec_t m_sortedIVec; // sorted - created with for loop
IVec_t m_recursiveIVec; // extract from sorted by recursion
IVec_t m_iterativeIVec; // extract from sorted by iteration
public:
T607_t() = default;
~T607_t() = default;
int exec(int , char** )
{
fillShowSortedIVec();
fillShowRecursiveIVec();
fillShowIterativeIVec();
showResults();
return 0;
}
private: // methods
The vectors are in class T607_t, so that each is available to any member function.
For this MCVE, I simply create "IVec_t m_sortedIVec;" and fill with a simple for loop:
void fillShowSortedIVec()
{
for (int i=0; i<15; ++i)
m_sortedIVec.push_back (i*100); // create in sorted order
showIVec(m_sortedIVec, "\n m_sortedIVec :");
}
Next (in this MCVE) is the recursive fill and show, and my adaptation of the OP's recursive method to produce the recursive insert sequence:
// ///////////////////////////////////////////////////////////////
void fillShowRecursiveIVec()
{
assert(m_sortedIVec.size() > 0);
int max = static_cast<int>(m_sortedIVec.size()) - 1;
// use OP's recursive insert
array2balancedR (m_sortedIVec, 0, max);
// NOTE - 'sequence' is inserted to 'm_recursiveIVec'
// instead of into tree the op did not share
showIVec(m_recursiveIVec, "\n m_recursiveIVec:");
}
// recursive extract from: m_sortedIVec to: m_recursiveIVec
// my adaptation of OP's recursive method
void array2balancedR(IVec_t& array, int lIndex, int rIndex)
{
//base case
if(lIndex > rIndex)
{
return;
}
else //recursive calls
{
int mid = (lIndex+rIndex)/2;
m_recursiveIVec.push_back(array[mid]); // does this
// tree.insert(array[mid]); // instead of this
array2balancedR(array, lIndex, mid-1); // recurse left
array2balancedR(array, mid+1, rIndex); // recurse right
}
}
Note: I left the "IVec_t& array" as a parameter to this function, because the OP's code has it. Within this 'class' wrapper, the function need not pass the array 'through the recursion', because each method has access to the instance data.
Next (in this MCVE) is a fill and show action using one possible iterative approach. I styled this iterative approach carefully to match the OP's recursive effort.
First, I added a 'tool' (IndxRng_t) to simplify the 'stack' capture of iterations for later processing. (i.e. "todo").
// //////////////////////////////////////////////////////////////
// iterative extract from m_sortedIVec to: m_iterativeIVec
class IndxRng_t // tool to simplify iteration
{
public:
IndxRng_t() = delete; // no default
IndxRng_t(int li, int ri)
: lIndx (li)
, rIndx (ri)
{}
~IndxRng_t() = default;
// get'er and set'er free. also glutton free. gmo free.
bool done() { return (lIndx > rIndx); } // range used up
int mid() { return ((lIndx + rIndx) / 2); } // compute
IndxRng_t left(int m) { return {lIndx, m-1}; } // ctor
IndxRng_t right(int m) { return {m+1, rIndx}; } // ctor
private:
int lIndx;
int rIndx;
};
void fillShowIterativeIVec()
{
assert(m_sortedIVec.size() > 0);
int max = static_cast<int>(m_sortedIVec.size()) - 1;
array2balancedI(m_sortedIVec, 0, max);
// 'sequence' inserted to 'm_iterativeIVec'
showIVec(m_iterativeIVec, "\n m_iterativeIVec:");
}
void array2balancedI(IVec_t& array, int lIndex, int rIndex)
{
std::vector<IndxRng_t> todo;
todo.push_back({lIndex, rIndex}); // load the first range
// iterative loop (No recursion)
do
{
if (0 == todo.size()) break; // exit constraint
// no more ranges to extract mid from
// fetch something to do
IndxRng_t todoRng = todo.back();
todo.pop_back(); // and remove from the todo list
if(todoRng.done()) continue; // lIndex > rIndex
int mid = todoRng.mid();
m_iterativeIVec.push_back(array[mid]); // do this
// tree.insert(array[mid]); // instead of this
todo.push_back(todoRng.right(mid) ); // iterate on right
todo.push_back(todoRng.left(mid) ); // iterate on left
}while(1);
}
And this mcve generates a result display:
void showResults()
{
assert(m_recursiveIVec.size() == m_sortedIVec.size());
assert(m_iterativeIVec.size() == m_sortedIVec.size());
std::cout << std::endl;
std::stringstream ss; // for btree use only
std::cout << "\n demo:\n create a BTree, "
<< std::flush;
std::cout << "\n Insert IVec_t " << std::endl;
BBT::BTree_t btree(ss);
std::cout << std::flush;
for (size_t i=0; i<m_iterativeIVec.size(); ++i)
btree.insertPL(m_iterativeIVec[i]);
std::cout << "\n iterative result:\n\n"
<< btree.showTallTreeView();
}
void showIVec(IVec_t& ivec, std::string lbl)
{
std::cout << lbl << std::endl;
for (auto it : ivec)
std::cout << std::setw(5) << it << std::flush;
std::cout << std::endl;
}
}; // class T607_t
int main(int argc, char* argv[])
{
T607_t t607;
return t607.exec(argc, argv);
}
My output (on Ubuntu 17.10, g++ 7.2.0),
m_sortedIVec :
0 100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400
m_recursiveIVec:
700 300 100 0 200 500 400 600 1100 900 800 1000 1300 1200 1400
m_iterativeIVec:
700 300 100 0 200 500 400 600 1100 900 800 1000 1300 1200 1400
demo:
create a BTree,
Insert IVec_t
iterative result:
BTree_t::showTallTreeView(): (balance: 0 sz: 15)
0
100
200
300
400
500
600
700
800
900
1000
1100
1200
1300
1400
-----------------
Iterative JavaScript implementation of converting sorted array to Binary Search Tree (BST):
function sortedArrayToBstIteratively(nums) {
// use stack to iteratively split nums into node tuples and reuse values
const stack = []
// add root node to tree
const tree = { first: 0, last: nums.length - 1 }
stack.push(tree)
// split array in the middle and continue with the two halfs
while (stack.length > 0) {
const node = stack.pop()
if (node.last >= node.first) {
if (node.last === node.first) {
// node reaches a single leaf value (last == first)
node.value = nums[node.first]
} else {
// node has still valid indices to further split the array (last > first)
const middle = Math.ceil((node.first + node.last) / 2)
node.value = nums[middle]
node.left = { first: node.first, last: middle - 1 }
node.right = { first: middle + 1, last: node.last }
stack.push(node.left)
stack.push(node.right)
}
} else {
// node has no more valid indices (last < first), create empty leaf
node.value = null
}
delete node.first
delete node.last
}
// console.log(JSON.stringify(tree))
return tree
}

Algorithm - Make Highest Tower

I've a problem that I could not resolve. I've thought many solutions but no one seems to work.
So that's my problem:
You're given n1, n2, .... nk LEGOs, each one with a even number of faces.
Every LEGO can be stacked up another one only if :
the upper LEGO has the same face of the LEGO under it;
the upper LEGO must have a number of faces that is less or equal to the number of faces of the LEGO under it.
In addition to this every face has an opposite face which is inserted by input after the first one;
example: LEGO1 - face1, face2, face3, face4 (face1 and face2 are opposites such as face3 and face4).
The problem asks to make the highest tower with these LEGOs using each LEGO only once.
The tower must have only 1 direction so it can go only from left to right or from bottom to the top.
Thanks a lot and sorry for my bad English :/
INPUT EXAMPLE:
Lego1 - f1, f2, f3, f4, f5, f6
Lego2- f33, f47, f98, f123
Lego3 - f4,f127
OUTPUT EXAMPLE:
2
Resembles a task I had long ago. Idea of the algorithm was:
put items (legos) in circular list (closed single-linked list);
make function which
in loop
takes next element from the list (deletes it)
recursively cals itself
inserts previously deleted element
advances to the next element
When list gets empty You have got one of possible lego sequences. Algorithm builds all possible seaquences using each list element only once.
Working code:
#include <stdio.h>
#define MAX 4
struct CList{
int d;
struct CList *next;
};
void search(struct CList *pstart);
void result(struct CList *v[MAX], const int nv);
int main(){
static struct CList lst[MAX];
struct CList *p = lst;
int i;
for( i = 0; i < MAX - 1; i++){
lst[i].d = i;
lst[i].next = lst + i + 1;
}
lst[MAX-1].d = MAX - 1;
lst[MAX-1].next = lst;
search( p );
return 0;
}
void search(struct CList *pstart){
struct CList *p, *pp;
static struct CList *v[MAX];
static int nv = 0;
if( pstart->next == pstart ){
v[nv++] = pstart;
result( v, nv );
nv--;
return;
}
nv++;
p = pstart;
do{
pp = p;
p = p->next;
v[nv-1] = p;
pp->next = p->next;
search( pp );
p->next = pp->next;
pp->next = p;
} while( p != pstart );
nv--;
}
void result(struct CList *v[MAX], const int nv){
int i;
for( i = 0; i < nv; i++ ){
printf(" %d ", v[i]->d);
}
puts( "" );
}
In Your case further optimization may be possible (for example breaking the recurson when current element dosn't stack).

Efficient Computation of Frequent and Top-k Elements in Data Streams

Here is the pseduo code for this algorithm.
Following is how I have implemented this.
#include <iostream>
#include <fstream>
#include <string>
#include <map>
typedef std::map<std::string, int> collection_t;
typedef collection_t::iterator collection_itr_t;
collection_t T;
collection_itr_t get_smallest_key() {
collection_itr_t min_key = T.begin();
collection_itr_t key = ++min_key;
while ( key != T.end() ) {
if ( key->second < min_key->second )
min_key = key;
++key;
}
return min_key;
}
void space_saving_frequent( std::string &i, int k ) {
if ( T.find(i) != T.end())
T[i]++;
else if ( T.size() < k ) {
T.insert(std::make_pair(i, 1 ));
} else {
collection_itr_t j = get_smallest_key();
int cnt = j->second + 1;
T.erase(j);
T.insert(std::make_pair(i, cnt));
}
}
int main ( int argc, char **argv) {
std::ifstream ifs(argv[1]);
if ( ifs.peek() == EOF )
return 1;
std::string line;
while( std::getline(ifs,line) ) {
std::string::size_type left = line.rfind('=') + 1;
std::string::size_type length = line.length();
std::string i = line.substr(left, length - left - 1);
space_saving_frequent(i, 5);
}
ifs.close();
return 0;
}
Original paper link : http://dimacs.rutgers.edu/~graham/pubs/papers/freqcacm.pdf
But code does not work, and I am no able to figure out where I am wrong.
If the items with least count are two or more, you can simply break ties arbitrarily by choosing, for instance, the item with lowest index stored in your data structure, or a random one among those of lowest count etc.
If you want to compare your implementation with a reference one, take a look at the implementation of Cormode and Hadjieleftheriou that you will find here. The code is more complex than yours, because you are not actually implementing the stream summary data structure. Their code also includes implementations for several other frequent items algorithms, and the authors compared the performances of those algorithms. Space saving proved to be in the majority of the cases, the best algorithm, with regard to several metrics such as precision, recall, update speed, space used etc. You will also find a paper discussing this experimental comparison. An improved version of this paper appeared later in Communications of the ACM. Here you can access a pdf version.