I am given a list of strings and would like to find the middle element.
I want this middle element because I am constructing a binary search tree from this list, using the middle element as the root node.
How would I go about finding the middle element of standard list so I can recursively call the left and right sides to make the tree? I understand everything about the BST besides this part.
You could use size() and then dividing it by 2 and storing in an integer. Later if you want left or right side you just take that number and add a -1 or a +1
Related
I understand that set is implemented as tree structure internally in c++ . So, how does lower_bound gets performed on it? I mean I understand for vector that you pick the middle element using the start and end indexes and perform binary search, but how does it get implemented for tree like structures?
Finding the lower_bound in a set is almost the same as searching for an element in the set. At the end of the search (navigating the tree) you've either found the node where the element is, or you find an element that is greater than the one you're looking for, but there aren't any nodes with a lower value in its subtree (so this is where you'd want to insert the value if you were adding it, as the left child of this node).
Either way you've found the lower bound for the element.
I've built a circular two-way circular list and I want to find its length.
I am allowed to use the function only in the Pointer to list. In the list I have a binary field.
An idea how can I do this?
I have to use the binary field, I can not use the auxiliary pointer and I have to have it in good complexity.
Keep track of the element at which you start your traversal. Start walking along the list and check for each element if it is the one where you started. If it is not, you increment your count by one and continue on to the next element. If it is, you have visited every element and the current value of the count is your desired result.
You can browse your list in a way, counting how many elements you have until you come back to the starting element !
A bit hard to explain what I'm planning, but here it goes. I have a doubly linked list of objects which are ordered alphabetically by a member attribute called name. I wish to remove a Node with a specific name, but I would like to remove it in such a way that it is more likely to start looking for it on the side of the list closer to it.
So I was thinking that I would have to find the 'midpoint' between the first Node's name and the last Node's name. Then I will check to see if that midpoint is less than the name of the Node. If it is less, I will start from the tail, otherwise I will start from the head.
The problem I am having is that I am unable to convert a string directly into an int. My potential solution is this:
Convert each individual character in the head and tail to an int
Put each conversion into an int array, one array for the head, one for the tail
Convert each int into a string again and put them into a new array
Make each converted string have a length of 3 by inserting 0s into them if they have less than a length of 3
Add the strings in each array together
Convert the strings to int again and find the difference between the two ints and divide that by 2
Add the new value to the first Node's converted name
Find if this 'midpoint' is less than the name of the Node I want to remove
If it is, start searching from the tail
Else, search from the head
Is there any easier way to go about doing this?
Alf's comment is realistically what you want. In order to decide which end to be on, you are getting maximum resolution by simply finding the first different character and then picking based on the midpoint.
Algorithm idea
list = ["apple", "banana", "orange"]
word_to_search_for = ["banana"]
index = 0
while list[0][index] == list[last][index]:
if word_to_search_for[index] != list[0][index]:
return "word not in list"
++index
spread = list[last][index] - list[0][index]
if (word_to_search_for[index] - list[0][index])> spread/2:
start at last
else:
start at 0
As others have already alluded, your main problem is that you're using the wrong data structure. Your question shouldn't be "How do I make a double linked list operate in a manner that is distinctly unlike a double linked list?", it should be "What is the best data structure for {insert your specific use case}?".
Reading between the lines, it appears that you're after something that allows for insertions, removals and relatively high speed scans. This leads me to suggest a Left Leaning Red Black Tree: see https://en.wikipedia.org/wiki/Left-leaning_red%E2%80%93black_tree
You could create an array of pointers to some sub-set of nodes in the list, like pointers to the first, middle, and last node of a list. You could use more pointers to reduce the search time, perhaps 4 to 16 pointers. Sort of a hierarchical overall structure. The array would need to be updated as nodes are deleted (at least the pointers to deleted nodes, pick the node before or after if this happens, or shrink the array). At some point, a tree like structure would be better.
I have been wanting to write remove() method for my Binary Search Tree (which happens to be an array representation). But before writing it, I must consider all cases. Omitting all cases (since they are easy) except when the node has two children, in all the explanations I have read so far, most of the cases I see remove an element from an already balanced binary search tree. In the few cases where I have seen an element being removed from an unbalanced binary search tree, I find that they balance it through zigs and zags, and then remove the element.
Is there a way that I can possibly remove an element from an unbalanced binary search tree without having to balance it beforehand?
If not, would it be easier to write an AVL tree (in array representation)?
You don't need to balance it, but you do need to recursively go down the tree performing some swaps here and there so you actually end up with a valid BST.
Deletion of a node with 2 children in an (unbalanced) BST: (from Wikipedia)
Call the node to be deleted N. Do not delete N. Instead, choose either its in-order successor node or its in-order predecessor node, R. Copy the value of R to N, then recursively call delete on R until reaching one of the first two cases.
Deleting a node with two children from a binary search tree. First the rightmost node in the left subtree, the inorder predecessor 6, is identified. Its value is copied into the node being deleted. The inorder predecessor can then be easily deleted because it has at most one child. The same method works symmetrically using the inorder successor labelled 9.
Although, why do you want an unbalanced tree? All operations on it take on it take longer (or at least as long), and the additional overhead to balance doesn't change the asymptotic complexity of any operations. And, if you're using the array representation where the node at index i has children at indices 2i and 2i+1, it may end up fairly sparse, i.e. there will be quite a bit of wasted memory.
Given a input a tree we need to answer the queries of the type,
a) given a node of the above tree, which is the node which is at the longest distance from that node.
b) remove a particular set of edges from the tree.
I have been trying this for a long time but the best solution I could come up with was,
For a query of type a call dfs function which would return the farthest node in O(N), but i need to do better.
For a query of type b, just update the tree [remove edge if exists].
So my solution above is roughly O(K*N) where K is the number of queries and N is the number of Nodes.
Since your tree is a general tree, i.e., it has no notion of being balanced or even having a root, the best you can do for a one-off query is O(n). However, I think you can set up the tree once taking O(n) time and then have each following query take constant time.
The idea is to find the "middle" of the tree which separate the tree into to roughly equal sized trees, calling the parts arbitrary, e.g., left and right. You then label all nodes in their respective parts with the part they are in and store a left and a right node which are farthest away from the middle. When you get a query for a node you just look at the node's label and report the stored node on the other side.
Given the comment [and the unwarranted downvote] it seems the solution requires a bit more explanation. First off, the furthest apart node for a given node is, in general, not unique. Imagine for example a path with exactly three nodes. There are two furthest away nodes for the middle node. Either one of them is a solution. Based on that, the idea is to find a node in the tree which is located in the middle of the path between the two farthest apart nodes in the tree (of the distance between these nodes is odd, a node on either side can be chosen such that the distances differ by just one): If the farthest apart nodes are l nodes apart, the middle node has a path of length l/2 to both of them or a path of l/2 to one and l/2+1 to the other.
Using this middle node to separate the tree into two halves, randomly called the left and the right half, makes it possible to determine the farthest apart node for any given node if each node knows whether it is in the left or the right half: the longest path will go through the middle node into the other half and from there to the node farthest away from the middle. Let's call the length of the longest path in the left part ll and the length of the longest path in the right part lr. Without loss of generality, have lr < ll (just swap the names around). The respective farthest apart nodes from the middle are called nl and nr. Note that it is OK if there are multiple subtrees leading from the middle node which are considered part of the right part as long as one of the longest path (or the longest path if it is unique) is in the left part.
There are three cases to consider when you want to state the furthest apart node from a node n:
The node n is the middle node. In this case, the furthest apart node is clearly nl.
The node n is in the right part of the tree. The longest path you can construct travels to the middle and then to nl, i.e., the furthest apart node is clearly nl, too
The node n is in the left part of the tree. Again, the longest path you can construct travels to the middle but from there to nr.
The only question remaining is how to find the middle node in O(n) time:
Find all leaf nodes and put them into a queue, labeling them with 1 and giving them a distance of 0. This can be done in O(n) time [and space].
Read (but don't extra, yet) the first node from the queue and find all adjacent nodes. If there is a node with a label which is less than its number of adjacent nodes, increment the label. If the label now matches the number of adjacent nodes, add the node to the queue and give it a distance one bigger than the first node from the queue.
If there is only one node in the queue, this node is the middle node and this step terminates.
Otherwise, extract the front node and continue processing the queue (i.e., step 2).
As a final pass, find the adjacent node with the biggest distance label and consider the tree hanging off this node the left tree. While labeling the nodes as left nodes with a BFS keep track of the last node in the queue to find nl. Consider all other subtrees right trees and label them with BFS, too, as right nodes, also finding nr.
I guess, the preprocessing of the tree can be done more elegantly, possibly using few passes, too, but I'm sure the above approach does work.