21
SureInterview PREPARATION ON DATA STRUCTURE http://www.sureinterview.com Mar 6, 2011 The latest version can be found at http://code.google.com/p/sureinterview/downloads

Sure interview datastructure-1103

Embed Size (px)

Citation preview

Page 1: Sure interview datastructure-1103

SureInterview

PREPARATION ON DATA STRUCTURE

http://www.sureinterview.com

Mar 6, 2011

The latest version can be found at http://code.google.com/p/sureinterview/downloads

Page 2: Sure interview datastructure-1103

Search

Search

Data Structure

How to implement your own HashSet by using ArrayList

How to implement your own HashSet by using ArrayList

submit my answer

Implement LRU cache algorithm

Implement the LRU cache algorithm. Given following interface.

The get and put can be done in O(n) time.

1 the data structure

The core of this algorithm is a double linked list that indexed by a hash map. The double link is implicitly sorted by the age ofthe data. Once the data is accessed, it is considered to be refreshed and thus moved to the head of the double linkedlist(age==0).

2 double linked list

For a double link, the insert and deletion only takes O(1). So, it is quite efficient to implement the LRU structure. The reason touse double linked list rather than the single linked one is to delete the note from the middle part.

By define the head and tail node, the insertion and deletion of a node can be simplified.

Initialize the head nodes.

Remove the note from the list.

Attach the node after head.

123456789

1011121314151617

interface CacheStrategy<K, T> { /** * get the data by key from cache. * * @param key * @return */ T get(K key); /** * put <key, data> pair to cache * * @param key * @param data */ void put(K key, T data);}

1234567

class Node { Node prev; //double link Node next; T data; //data and key K key;}Map<K, Node> map; //node is indexed the key to support node access in O(1).

12345

//hook up the head and tail nodeshead = new Node(null, null);tail = new Node(null, null);head.next = tail;tail.prev = head;

12345

private void detach(Node node) { // detach it from the queue node.prev.next = node.next; node.next.prev = node.prev;}

?

?

?

?

Page 3: Sure interview datastructure-1103

Search

Search

3 maintain the cache

Get the data from the cache needs to move the node from middle to the head.

Besides a fresh, putting data into the cache also needs to maintain the size and content of the cache.

Code

Code can be found at: http://code.google.com/p/sureinterview/source/browse/src/solution/misc/CacheStrategies.java#47

implement a queue with stack(s)

implement a queue with stack(s)

submit my answer

Design a class that supports insert, delete, and get random element.

Given a collection of integer, design a class that supports:

1. add(data) - insert an element2. delete(data) - delete an element3. getRandom(data) - return a random element

General Idea

The commonly used data structures do not efficiently satisfy all of the features. So we should hook up multiple data structuresto provide an efficient solution.

Because the getRandom is most demanding -- only array can support getRandom(), the array should be used to let getRandompart work. The array is not quite good at deleting data in the middle, so the data should be stored in some other data

1234567

private void attach(Node head, Node node) { // add note behind the head. node.prev = head; node.next = head.next; node.next.prev = node; node.prev.next = node;}

123456789

10111213141516

@Overridepublic T get(K key) { Node node = map.get(key); if (node == null) return null; if (map.size() == 1) return node.data; // refresh // - detach it from the queue detach(node); // - attach it to head attach(head, node); return node.data;}

123456789

1011121314151617181920212223242526

/** * put <key,data> into cache. */@Overridepublic void put(K key, T data) { if (maxsize <= 0) return; Node node = map.get(key); if (node != null) { // hit, just update data detach(node); attach(head, node); node.data = data; } else { // miss, create new data node = new Node(key, data); map.put(key, node); attach(head, node); if (map.size() > maxsize) { // overflow, remove the tail detach(tail.prev); map.remove(tail.prev.key); } }}

?

?

?

Page 4: Sure interview datastructure-1103

structure. Here, the link list won't work either because the delete function needs to randomly access the data. A betterstructure is the hash table. So, we can use a hash table to save the data and an array to provide random access function.

implementation

when all data elements are unique

Here is the pseudo code. Note that this version does not support duplicated data.

when there is duplicated data

The existence of duplicated data is further conflict with the hash table structure. To keep the up the high performance, theconflict can be resolved by a linked list (or, separate chain). But with this change, the getRandom is not random any more. Theduplicated data put extra weight on each element, so the element picked is biased. To solve this problem, each duplicatedelement has to appear in the index array. Considering the requirements, the rndAry can implement multiple link lists to store theconflict data. In that way, the data are still in an array but it has internal linked list structure to resolve the confliction.

So, we can first define a new data structure:

When adding a non-existing data, new entries will be added in both dataArr and rndArr. If the data already exits in the hashtable, only put a new entry in rndArr and hook up to the existing one as a chain. When deleting a data, if the data is stillduplicated, we will remove the element from the head linked list. As we did before, the last element in rndAry should be movedto fill the gap where the data is deleted. The hash table and the rndAry should be adjusted to maintain the data integrity. If thedata being deleted is the last one in the hash table, the entry in hash table also needs to be deleted. To get a random data, wejust need to randomly pick up one element. Nothing is changed here.

Unit test

To test the getRandom, we can set the random seed so the random process can be repeated. Or simply overwrite (overload)the method with a non-random version so the behavior is totally controlled.

123456789

101112131415161718192021222324252627282930313233343536373839404142434445464748495051

class AClassSupportsGetRandom<T> { class Data { T data; int idx; } Data dataArr[]; // for hashing data final int HASH_SIZE = 0x100000 - 1; int rndArr[]; // the array for getting random data. int size;; void add(T data) { int pos = hashFunction(data); // get the insert position dataArr[pos].data = data; dataArr[pos].idx = size; // append to the tail of the index array. hook two structures together. rndArr[size] = pos; size++; } public int getSize() { return size; } private final int hashFunction(T data) { int pos = Math.abs(data.hashCode()) % HASH_SIZE; // handle conflict, size, etc. return pos; } T getRandomData() { int rnd = getAValidRandomNumber(); return dataArr[rndArr[rnd]].data; } //delete void delete(T data) { if( isEmpty() ) return; int pos = hashFunction(data); T dat = dataArr[pos].data; dataArr[pos].data = null; //to avoid moving large data block left, the data at the tail is moved to middle instead. //so the pointers needs to be adjusted. size--; rndArr[pos] = rndArr[size]; //move pointer to middle dataArr[rndArr[size]].idx = pos; // adjust the pointer in data array. }}

1234

class Data { T data; int prev, next; // for the linked list structure in rndArr }

?

?

Page 5: Sure interview datastructure-1103

Search

Search

phone book

1. given name, find the phone number.2. given first name, find the last name and phone number.3. both direction4. wild card support.

submit my answer

compare data structures

Compare different data structures, such as link, vector, list, queue, stack, set, and map.

What are their pros and cons?

submit my answer

Page 6: Sure interview datastructure-1103

Search

Search

Search

Search

Search

Search

Graph

Design data structure to store and operate on very sparse matrix.

Design data structure to store and operate on very sparse matrix, which supports following operation:

1. multiply.2. subtract.3. check if links exists in the matrix.

orig

submit my answer

teams of best friends

http://www.mitbbs.com/article_t/JobHunting/31617589.html

submit my answer

bipartite matching problem

A binary matrix is like below:

A B Ca 1 0 1b 0 1 1c 1 1 1

let's say person a is available for job A can you write a program to list all possible assignment combinations in a format likebelow:

A B Ca b ca c bc b a

( each person can only be assigned to one job)

submit my answer

shortest path algorithm

explain shortest path algorithm

submit my answer

Design a game which transform a word to the target word. one letter is replaced at each step.

Design a game: which transform a word to a target word. for example: from he ad to tail, each step, you just can replace onecharacter, and the word must be valid.

oirg

submit my answer

Graph traversal

http://www.mitbbs.com/article_t/JobHunting/31650275.html

Page 7: Sure interview datastructure-1103

Search

submit my answer

minimal set of words to understand half of the sentences

There's a book and each sentence consists of several words. How to find the minimal set of words which can used by thereader to understand half of total number of the sentences. Each sentence is readable if the reader know all the words.

submit my answer

Page 10: Sure interview datastructure-1103

Search

Link

Copy a link list with extra random pointers.

There is a singly linked list with an extra pointer on each node. Those extra pointers can point to any other nodes, as shown inthe red arrows below.

Duplicate this link list with O(1) space complexity.

General Idea

This question is very good for practising the deletion and insertion ofnodes in linked list.

Suppose the original link is {A1, ..., A5} and the copied result is {B1,..., B5} with the same structure.

1. The first step is to insert the nodes after the original node. The{Ai, Bi} can be treated as a group and all operations can be doneon those groups.

2. The next step is to mirror the extra link on Ai to Bi.3. Finally, the merged link is split into two separate links. The newly

created link list has the same structure as in the original one.

The above steps can be generalized

The idea grouping the new and old node together can be easily apply toother data structure. For example, suppose we have a binary tree withextra link on each node, and we want to duplicate the structure.

1. We can first create a new node and put it as the left child of theoriginal node. Imagine this new node is invisible, the tree is thesame as previous one.

2. Then we can mirror all links of the original tree to the newstructure.

3. Finally, detach the new tree from the merged one.

code

The following code in Java is to copy a linked list with extra random link.

123456789

1011121314151617181920212223242526

LinkNode copyLink(LinkNode link) { if (link == null) return null; // (1) copy the link list and hook up after the original node. LinkNode p = link; do { LinkNode p2 = new LinkNode(); p2.value = new String(p.value.toLowerCase()); p2.next = p.next; p.next = p2; p = p2.next; // NOTE: p = p.next.next; } while (p != null); // (2) copy the link list and hook up after the original node. p = link; do { if (p.extra != null) { p.next.extra = p.extra.next; } p = p.next.next; // NOTE: p = p.next.next; } while (p != null); // (3) split the two link lists apart. p = link; LinkNode link2 = p.next;

?

Page 11: Sure interview datastructure-1103

Search

Search

Search

Code

Code can be found at: http://code.google.com/p/sureinterview/source/browse/src/solution/list/CopyLinkWithExtraPointer.java

Reverse single linked list.

requires:

1. recursive method2. iterative method

submit my answer

how to find a circle/loop in a linked list?

1. check if a linked list has a loop.2. if there is a loop, find the starting point of the loop.

General Idea

The "tortoise and hare" algorithm uses two pointers (tortoise and hare), which move through the link at different speeds. Thetortoise moves 1 step at a time and the hare moves 2 steps at a time. If there is a loop, the hare will meet the tortoise.

To find the starting position of the loop, put the hare back to head and let it move 1 step at a time. When the hare and thetortoise meet again, the node is the starting point of the loop (Am).

Proof

The proof of this method is very interesting. Denote the length of the non-loop is m, and the length of the loop part is n. Thehare and the tortoise meet at Ai=A2*i. For the tortoise, it passes i=m+a*n+c. For the hare, it passes 2*i = 2*(m+a*n+c) =m+b*n+c. c is the offset in the loop, because they are not necessarily meet at the beginning of the loop. So, m + (2a-b)*n + c= 0.

After they met, the hare is set back to head and starts over again (step = 1). When the hare is moved to the head of the loop(Am), the tortoise is moved to Ai+m=Am+a*n+c+m=Am+(b-a)*n=Am, which is also the head of the head of the loop.

find the middle of a single linked list.

find the middle of a single linked list.

submit my answer

2627282930313233

LinkNode link2 = p.next; while (p.next != null) { LinkNode q = p.next; p.next = q.next; p = q; } return link2;}

Page 12: Sure interview datastructure-1103

Search

Search

List

Longest Increasing sequence (LIS)

Find a subsequence of a given sequence in which the subsequence elements are in sorted order, lowest to highest, and in whichthe subsequence is as long as possible. This subsequence is not necessarily contiguous, or unique.

Algorithms

Check the efficient solution of longest increasing subsequence. The code can be found in algorithmist.

Quick recap of the idea

The pseudo code:

As a quick recap of the algorithm in wiki, here is an example that explains the major steps:

Alternative solution

Sort the list in O(n logn) and find the longest common subsequence in O(n2).

Maximum in sliding window

Input: A large integer array A[]

Output: An array B[], where B[i] is the maximum value of from A[i] to A[i+w-1]

General Idea

If extra space is allowed, it should be used as a queue rather than a max heap.

Check how to implement a queue with getMax operation. The sliding window is a special usage of the queue.

Following is the Java implementation.

1234567

L = 0for i = 1, 2, ... n: binary search for the largest positive j <= L such that X[M[j]] < X[i] (or set j = 0 if no such value exists) P[i] = M[j] if j == L or X[i] < X[M[j+1]]: M[j+1] = i L = max(L, j+1)

123456789

1011121314151617

1 3 5 7 4 6 8 <- X: the data array, M: an index array working like a stack, L: the length of M. 1 3 5 7 4 6 8 ^ processed here0 1 2 3 <- M: an index array holding an increasing subsequence (replaced with smaller data).- 0 1 2 <- P: the index for tracing back. Currently it is: M(L)=3 -> P(M(L))=2 -> P(P(M(L))= 1 -> P(P(P(M(L)))= 1 3 5 7 4 6 8 ^ processed here0 1 4 3 <- M: In M[2], 2 is replaced by 4, because X[4]=4 < X[2]=5. Note that the length of M is not changed.- 0 1 2 1 <- P: not changed. Still is: (3) -> 2 -> 1 -> 0 1 3 5 7 4 6 8 ^ processed here0 1 4 5 6 <- M: replace 3 with 5. append 6- 0 1 2 1 4 5 <- P: (6) -> 5 -> 4 -> 1 -> 0 (done)

12345

public Integer[] getMaxInSlideWindow(Integer[] A, Integer w) { // invalid input if (A == null || w <= 0 || A.length - w + 1 <= 0) return null;

?

?

?

Page 13: Sure interview datastructure-1103

Search

Search

Code

Code can be found at: http://code.google.com/p/sureinterview/source/browse/src/solution/search/MaximumInSlideWindow.java

Find the min and max in a list

Find the min and max in a list

Finding max needs n-1 comparison. Finding min needs additional n-2 comparison.

But by splitting the number into to halves, we can save n/2 comparisons, as shown below. So the total number of comparisonis (3/2)*n - 2.

8 | 4 8 | |2 4 6 8| | | | <- save n/2 comparison.1 3 5 7 -- | | \ 1 5 n/2-1 | / 1 --

Implement a queue with getMax operation.

Implement a queue with following operations:

removeFirst - remove the first elementgetFirst - get the value of first elementaddLast - append the value to the end of queue.getMax - get the maximum value of the queue.

General Idea

If extra space is available, the extra space should be used as a auxiliary queue, which is a subset of the original one and keepsorted in descending order. The head stores the current maximum value. The tail stores the last inserted element.

The auxiliary queue also makes sure that each element is the largest after the previous element is popped out.

Implementation

56789

101112131415161718192021222324252627282930313233

Integer[] B = new Integer[A.length - w + 1]; // auxiliary queue that is sorted in descending order LinkedList<Integer> q = new LinkedList<Integer>(); for (int i = 0; i < A.length; i++) { // enqueue. Remove those smaller values int data = A[i]; while (!q.isEmpty() && q.getLast() < data) { q.removeLast(); } q.add(data); if (i < w - 1) { continue; } // dequeue. If the current number is the maximum. Also remove it // from the queue Integer max = q.get(0); B[i - w + 1] = max; if (A[i - w + 1] == max) { q.removeFirst(); } } return B;}

1234567

public void addLast(T data) { // insert data to the data queue. dataQ.add(data); // adjust the auxiliary queue. while (!auxiQ.isEmpty() && auxiQ.getLast().compareTo(data) < 0) { auxiQ.removeLast();

?

Page 14: Sure interview datastructure-1103

Code

Code can be found at: http://code.google.com/p/sureinterview/source/browse/src/solution/list/QueueWithMax.java

Also check maximum in sliding window for its application and a related problem implement a stack with min/max operation.

789

101112131415161718192021222324252627

auxiQ.removeLast(); } auxiQ.add(data); //append to the end.} public T getMax() { return auxiQ.getFirst();} public T removeFirst() { T data = dataQ.removeFirst(); // adjust the auxiliary queue. Because the previous max is removed, the // head (which is the current max) should be removed too. if (data == auxiQ.getFirst()) { auxiQ.removeFirst(); } return data;}

Page 16: Sure interview datastructure-1103

Search

Stack

Implement an algorithm to check whether brace expressions are valid or not

Implement an algorithm to check whether brace expressions are valid or not

1. stack2. the stack is empty after all string are read.

test case:

orig

submit my answer

1 boolean isGood(String s, String braces); //assume braces are valid,{}[]()

123456

()()()(()))()

?

?

Page 17: Sure interview datastructure-1103

Search

Search

Search

Algorithms on tree, such as traversal.

Given the pre-order and in-order traversing result of a binary tree, write a function to rebuild the tree

Given the pre-order and in-order traversing result of a binary tree, write a function to rebuild the tree.

submit my answer

How to turn a binary search tree into a sorted array?

How to turn a binary search tree into a sorted array?

Node definition:

submit my answer

Tree serialization and deserialization

Serialize and deserialize a tree.

General idea

The tree serialization is to save its data structure into a flat file, from which the original tree can be recovered (deserialized).

There are a few ways to serialize a tree.

1 Serialize the nodes

A common method of serialize a tree or graph is to save the node values and their relationship. Forexample, given the tree on the right. Each node can be represented by 4 elements, (#, value, #left,#right). By listing all notes, the tree can be serialized as:

Actually, this is also the general way to serialize a graph. Following code draws this example tree inDOT language. The graph (tree) breaks down into nodes and edges, which can have differentproperties.

During the serialization process, we need to assign each node a unique id. To efficiently look up that id, the mapping fromobject to id can be saved into a hash table. If the tree is stored in a list or array, the index of the node can be used as the idinstead. Similar hash table mapping from id to object can be used in deserialization.

2 Tree traversal

The traversal result of a tree also implicitly determine its topology. For example, the pre-order traversal uniquely describe theexample tree above as.

12345

struct Node { Node* left; Node* right; int value;};

1234

0, "a", 1, 21, "b", 3, ^2, "c", ^, ^3, "d", ^, ^

123456789

10

digraph{ node [style=bold, label="\N", shape=record]; node0 [label="<l> | <v>A | <r>"]; node1 [label="<l> | <v>B | <r>"]; node2 [label="<l> | <v>C | <r>"]; node3 [label="<l> | <v>D | <r>"]; node0:l -> node1; node0:r -> node2; node1:l -> node3;}

?

?

?

Page 18: Sure interview datastructure-1103

Search

The "^" is for empty node, which is necessary to recover the tree. Because a tree with n nodes has n+1 empty nodes, to savespace, multiple empty nodes can be noted as ^#. For example, the above serialized result can be revised to:

Check a slide for serializing trees.

A combination of preorder and inorder traversal can also uniquely describe a tree. The example tree has preorder and inordertraversal as follows:

The first node in preorder list is the root. By searching the root in the inorder list, the traversals are partitioned into left branchand right branch. The branches can be recovered in the same way recursively. This method is not efficient in term of time andspace complexity. Saving tree size is better but is still not quite efficient.

3 Newick format

Newick format is widely used in bioinformatics. It is a human readable format but needs more effort to serialize and deserialize.

Following code is to deserialize the tree in format of value(<left branch>,<right branch>). The example above is serialized as0(1(2,),3).

Code

Code can be found at: http://code.google.com/p/sureinterview/source/browse/src/lib/tree/TreeUtil.java#172

binary tree lowest common ancestor

Given two nodes in a binary tree, find the the lowest common ancestor of the two nodes.

1. Each node has a parent node link.2. No parent link, but the tree is binary search tree.3. Each node also knows the level in the tree.

General idea

1 a b d ^ ^ ^ c ^ ^

1 a b d ^3 c ^2

12345

a b d c //preorderd b a c //inorder a (b d) [c] //preorder(d b) a [c] //inorder

123456789

10111213141516171819202122232425262728293031

private BNode makeTreeRec() throws Exception { // 1. setup BNode root = new BNode(); char c = treeStr[pos]; root.value = 0; while (c >= '0' && c <= '9') { root.value *= 10; root.value += c - '0'; c = treeStr[++pos]; } // 2 left, root, right if (c == '(') { c = treeStr[++pos]; if (c != ',') { root.left = makeTreeRec(); } if (treeStr[pos] != ',') throw new Exception("',' expected at position " + pos); c = treeStr[++pos]; // skip "," if (c != ')') { root.right = makeTreeRec(); } if (treeStr[pos] != ')') throw new Exception("')' expected at position " + pos); ++pos; // --> ) } return root;}

?

?

?

?

Page 19: Sure interview datastructure-1103

1. If the parent node link is given, we can trace each node back to the root. The problem is to check where those two linksmerge. 2. If it is a binary search tree (BST), we needs to find the node whose branch covers both nodes. Each node in BST hasa min and a max that covers some certain range.

1. Given parent node

If the parent node link is given, the problem is to check where two links merge starting from given nodes. So, we first trace onelink back to root and put the nodes into a set. Then we trace another one back to find the first merged node, which is thelowest common ancestor.

If the level of each note is given, the problem is still to find the first merged node, but the set is not necessary.

2. Binary search tree (BST)

If the tree is BST without parent link, we need to start from root and check the relationship of current node and the two givennodes. If both nodes are on the left side of given node, we should move to left child. Dito for the right node.

Assume the BST is defined as left < root <= right.

123456789

10111213141516171819

public BNode getLCA2(BNode root, BNode a, BNode b) { // 1. trace one node to the root Set<BNode> set = new HashSet<BNode>(); BNode t = a; while (t != null) { set.add(t); t = t.parent; } // 2. trace another node towards to root. The common ancestors are those // nodes also in the set from step 1. t = b; while (t != null) { if (set.contains(t)) return t; t = t.parent; } return null; // not found}

123456789

10111213141516171819202122232425262728293031323334353637383940414243

public BNode getLCA(BNode root, BNode a, BNode b) { if (root == null || a == null || b == null) return null; // input is not valid BNode lca = null; // let la <= lb. Integer ia = (a.value < b.value ? a.value : b.value); Integer ib = (a.value + b.value - ia); BNode curNode = root; while (curNode != null) { /* * val is the value of current node. */ // case 1. val < a <= b. Because val is on the root, the lowest // common ancestor must be on the right branch. if (curNode.value < ia) { curNode = curNode.right; continue; } // case 2. val == a <= b if (curNode.value.equals(ia)) { do { lca = curNode; if (lca == a) break; curNode = curNode.right; if (curNode == null || !curNode.value.equals(ia)) return null; // the node a does not exist. } while (true); // double check if note b is really in the tree if (getInBST(lca, ib) == null) { lca = null; } return lca; } // case 3. a < val < b if (curNode.value < ib) {

?

?

Page 20: Sure interview datastructure-1103

Search

Search

Search

Search

Code

Code can be found at: solution/tree/LowestCommonAncestor.java

How to detect a tree is a subtree of another tree?

How to detect a tree is a subtree of another tree?

submit my answer

Find the n-th smallest element in a binary search tree (BST).

if the size of the tree is unknown.if the size of the tree is known.

General Idea

To find the n-th smallest node in a binary search tree is equivalent to finding the n-th node in a general binary tree. So we justneed to return the n-th node during the inorder traversal. If the size of each branch is known, we need to depth search for then-th node based on the size.

If the size of each branch is unknown

Inorder transversal the tree and return the node when found. Note:

1. remember to return to upper layer when the result is found.2. pay attention how the result is kept and returned.

If the size of each branch is known

When the size is known, get the n-th node is like find a node in a binary search tree.

Code

Code can be found at: http://code.google.com/p/sureinterview/source/browse/src/solution/tree/NthSmallestInBST.java

check a tree if it is BST.

orig

submit my answer

re-balance BST

re-balance BST

submit my answer

43444546474849505152535455565758596061626364

if (curNode.value < ib) { lca = curNode; if (getInBST(lca, ia) == null || getInBST(lca, ib) == null) { lca = null; } return lca; } // case 4. a < val == b if (curNode.value == ib) { lca = curNode; if (getInBST(lca, ia) == null) { lca = null; } return lca; } // case 5. a <= b < val curNode = curNode.left; } return null;}

Page 21: Sure interview datastructure-1103

Search

Search

Search

Search

Given a sorted array, build a BST and make sure the height is minimal.

Given a sorted array, build a BST and make sure the height is minimal.

Prove it.

submit my answer

enumerate operator tree

put operators in a list of numbers so that the result equals to a number. Give you an array of integers, ask you to writeprogram to put operators (+ - * / %) between the integers (you may put in braces wherever you want too), to have theequation equals to the result.

eg: 5 * (3 + 8) % 9 = 6

submit my answer

check if 2 tree nodes are related (ancestor/descendant)

check if 2 tree nodes are related (i.e. ancestor-descendant)

solve it in O(1) time, with O(N) space (N = # of nodes)pre-processing is allowed

submit my answer

How to turn a sorted double linked list into a binary search tree?

How to turn a sorted double linked list into a binary search tree?

submit my answer