find target in tree, delete whole tree if target not found - search

This is more of a logic problem I'm having a hard time figuring out, I'll post psuedo code, please let me know if anything is unclear.
I'm trying to write a function that will search for multiple instances of a target in an N-array tree (each node has 0 to N children).
If it finds 1 or more instances, it prints them all.
If it finds no instances of the target, the whole tree must be deleted
I'm trying to solve this recursively, this is what I have:
bool foo(node){
bool found = false
if node.value = target:
print target
return true
else:
return false
for child in node.children:
found = found or foo(child)
if not found:
*run deletion process*
}
The problem with this is the very first if statement:
if node.value = target:
print target
return true
else:
return false
As soon as it finds the first instance of the target, it returns and stops running. But I want it to find and print ALL instances. But doing this recursively, I'm having a hard time figuring out how to order the code.

As I understand your requirements (delete entire tree if not found), you can't delete the tree from within the recursion. You have to process the entire tree first, then delete it if the target was not found.
So:
bool foo(node){
bool found = false
if node.value = target:
print target
found = true
for child in node.children:
found = found or foo(child)
return found
}
Then
if not foo(root)
*run deletion process*
Note that when you actually implement this, some languages will skip the recursive call to foo in found = found or foo(child) once found is true, and so only ever print the first occurrence. In this case, just swap the arguments around: found = foo(child) or found to force it to recurse each time.

Related

Flatten a multilevel doubly LinkedList in Python

I am working on LeetCode problem 430. Flatten a Multilevel Doubly Linked List:
You are given a doubly linked list, which contains nodes that have a
next pointer, a previous pointer, and an additional child pointer.
This child pointer may or may not point to a separate doubly linked
list, also containing these special nodes. These child lists may have
one or more children of their own, and so on, to produce a multilevel
data structure as shown in the example below.
Given the head of the first level of the list, flatten the list so
that all the nodes appear in a single-level, doubly linked list. Let
curr be a node with a child list. The nodes in the child list should
appear after curr and before curr.next in the flattened list.
Return the head of the flattened list. The nodes in the list must have
all of their child pointers set to null.
My Approach
This is what I intended to do:
Traverse through the head node and wherever a child node appears, change the link of the current node to the child node.
Then, add all the nodes traversed to a separate LList (in my code it is ll). I have kept dummy at the head of the new LList.
While reaching at every child node, add that node address to a stack. So, when doing a pop() operation, the last child node added will be retrieved first.
After that, pop and iterate through that child node till None and add new nodes to new LList i.e. ll. Lastly, return dummy.next
My Code
class Solution:
def flatten(self, head: 'Optional[Node]') -> 'Optional[Node]':
curr = head
ll = dummy = ListNode(0)
stack = []
while curr:
if curr.child:
stack.append(curr)
ll.next = curr
curr.next = curr.child
else:
ll.next = curr
ll = ll.next
curr = curr.next
while stack:
curr_node = stack.pop()
while curr_node:
ll.next = curr_node
ll = ll.next
curr_node = curr_node.next
return dummy.next
The Problem
I am getting a Time Limit Exceeded warning. Can someone please tell me if I am correct with my approach and where I am going wrong?
The second part of your code is creating a cycle in the ll list. The node that you pop from the stack was already put in the ll list at the time you pushed that node on the stack. But you append it again to the ll list, making a cycle. And so while curr_node: is becoming an infinite loop.
The general idea for the algorithm is fine though, but push the next node on the stack, instead of the current node.
Furthermore, you should:
Clear the child reference once you have processed it
Adapt the prev references, so they are consistent with the changes to some of the next references. Remember: it is a doubly linked list you get and need to return.
I would not:
Lag behind with a separate ll reference. You can just work with curr
Use the dummy node. Although I understand its utility, once you have dealt with the case of the empty list (as a boundary case), there is really no benefit anymore
So here is how I would do it:
class Solution:
def flatten(self, head: 'Optional[Node]') -> 'Optional[Node]':
if not head:
return
stack = []
current = head
while current:
if current.child:
if current.next:
stack.append(current.next)
current.next = current.child
current.next.prev = current
current.child = None
elif not current.next and stack:
current.next = stack.pop()
current.next.prev = current
current = current.next
return head

Using DFS Recursively to Find a Particular Path

I am attempting to use DFS to solve a graph problem, and have ran into a wall. This is my implementation in Python3. unvisited is an array of ints, start and end are ints in unvisited, path is an empty array filled out as the DFS goes, and edges is a dictionary of edges.
def traverse(unvisited, start, end, path, edges):
copy_unvisited = unvisited.copy()
copy_path = path.copy()
current = start
copy_unvisited.remove(current)
copy_path.append(current)
if current == end and len(copy_unvisited)==0:
#print is just for me to check my answers
print(copy_path)
return copy_path
for i in edges[current]:
if i in copy_unvisited:
return traverse(copy_unvisited, i, end, copy_path, edges)
The goal is to find a path that starts on start and visits every int in unvisited until ending on end. Therefore, I'm running into a problem with the recursion (I think) because in cases where the path is wrong, I don't want to return anything; instead, I want the DFS to continue. With the way the code is written now, I'm getting "None" returned, even though the correct solution is being printed (because of my print statement). How can I fix this issue?
Thanks in advance!
Edit: If unvisited = [1,3,4,5], start = 4, end = 5, edges = {1: (4,5), 3: (1), 4: (1,3,5), 5: (1,4)},
traverse(unvisited, 4, 5, [], edges) should return [4,3,1,5], but instead I get None. traverse does not have a return type if a wrong path is followed, which is why I think I'm getting None. It eventually finds the right path and prints it.
I have found a solution by introducing a new parameter sol, and when the correct path is reached, I copy each entry of copy_path into sol. Then, I return sol at the END, after the recursive call. I also removed the return statement for the recursive call.
def traverse(unvisited, start, end, path, edges,sol):
copy_unvisited = unvisited.copy()
copy_path = path.copy()
current = start
copy_unvisited.remove(current)
copy_path.append(current)
if current == end and len(copy_unvisited)==0:
for i in copy_path:
sol.append(i)
for i in edges[current]:
if i in copy_unvisited:
traverse(copy_unvisited, i, end, copy_path, edges,sol)
return sol
Feels a little inelegant, so I'm open to better ways to solve this problem!
First of all, with the input that you gave, the output should be [4 1 5], since the first edge linked to the vertex 4 is 1 and at the time of the first execution of the DPS 1 still in the unvisited list.
The main problem with your original code is these two instructions:
The
len(copy_unvisited)==0:
in the first if and the
if i in copy_unvisited:
at the end.
Basically you have this:
First call of the function:
node 4, unvisited (uv): [1,3,4,5], path=[]
At the for: 4 uv: [1,3,5] edges: (1, 3, 5)
So i=1, i is in uv, then:
Second call of the function:
node 1, uv: [1,3,5], path=[4]
At the for: 1 uv: [3,5] edges: (4,5)
So i=4, but 4 is not in uv,
So i=5, 5 is in uv, then:
Third call of the function *OBS1*
node 5, uv: [3,5], path=[4,1]
it will not enter in the first if, because len(uv) is not equals 0.
At the for: 5 uv: [3] edges: (1,4)
So i=1, but 1 is not in uv
So i=4, but 4 is not in uv
The for ends, so the function ends and not call itself, neither return a value.
I am pretty sure the DPS should end when you get in the wanted node, or, when you have no more nodes to visit. In the first case, it should return the path it found, if not, it means the end node there is no path from the start node to the end node (you have it in a disconnected graph).
I tried modify your implementation, but I found it difficult to deal with this "unvisited" variable and with the path being updated in this way. I don't think you are conceptually incorrect, both in the overview of how DFS should work, and in how to update the recurrence, but I was unable to make it work that way and so I modified the algorithm so that it updated the path to as it unstack the functions, instead of doing so while it calls the functions.
def traverse(start,end,edges,visited=[],path = []):
if start == end:
path.append(start)
return path
if start not in visited:
visited.append(start)
if start not in edges:
return path
for i in edges[start]:
path = traverse(i,end,edges,visited,path )
if len(path)>0:
break
if len(path)>0 and start not in path:
path.append(start)
return path
This will return the path, written in reverse, if you want in the normal order just take the final result of the function, which will be a list and apply the .reverse () method on it.
This implementation above is a slight modification of the one I found here: https://likegeeks.com/depth-first-search-in-python/ I just added the part of finding a path between two specific points.
Your "sol" solution work, partially, because, when the DFS get into the the third call and left the for without calling the function again, it, at least can return a empty list, then the third call leaves the stack and the algorithm continues to the next i of the second function call, that is 3. The problem with this implementation is the DFS will read all nodes before return a path to the destination.

Pythonic way of creating if statement for nested if statements

I'm kind of newbie as programmer, but I wish to master Python and I'm developing open source application. This application has function to gather some information. This function takes 1 parameter. This parameter can be 0, 1 or 2. 0 = False, 1 = True, 2 = Multi. Also I have an if statement that does 2 actions. 1st - (when False) gathers single type value, 2nd - (when True) gathers multiple type values and when parameter is 2 (multi) then it will gather single type (1st) and multiple types (2nd). My if statement looks like this:
if False:
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
elif True:
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)
else:
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)
Is there maybe better way of avoiding this kind of coding, like in last else statement when I call both single and multiple.
Thank you in advance.
One thing I learned from Python is that although it lacks the Switch operator, you can use dictionary in a similar fashion to get things done since everything is an object:
def get_single():
# define your single function
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
def get_multi():
# define your multi function
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)
actions = {
0: [get_single],
1: [get_multi],
2: [get_single, get_multi]
}
parameter = 0 # replace this line with however you are capturing the parameter
for action in actions[parameter]:
action()
This way you avoid c+p your code everywhere and have it referenced from the function, and your "actions" dictionary define the function to be used based on the parameter given.
In this case since you have multiple functions you want to call, I kept all dictionary items as a list so the structure is consistent and it can be iterated through to perform any number of actions.
Ensure you use leave out the () in the dictionary so that the functions aren't instantiated when the dictionary is defined. And remember to add () when you are actually calling the function from the dictionary to instantiate it.
This is something you will often encounter and it is pretty much always bad practice to be repeating code. Anyway, the way to do this is use two if-statements. This way, even if the first case passes, the second case can still pass. Oh, and assuming your variable that can be 0, 1 or 2 is called x, then we could either use or and two checks:
if x == 0 or x == 2:
but, personally, I prefer using in on a tuple:
if x in (0, 2):
get_single_type = code.of.action
generators.generate_data(False, get_single_type)
if x in (1, 2):
get_multiple_type = code.of.action
generators.generate_data(True, get_multiple_type)

Short-circuiting in functional Groovy?

"When you've found the treasure, stop digging!"
I'm wanting to use more functional programming in Groovy, and thought rewriting the following method would be good training. It's harder than it looks because Groovy doesn't appear to build short-circuiting into its more functional features.
Here's an imperative function to do the job:
fullyQualifiedNames = ['a/b/c/d/e', 'f/g/h/i/j', 'f/g/h/d/e']
String shortestUniqueName(String nameToShorten) {
def currentLevel = 1
String shortName = ''
def separator = '/'
while (fullyQualifiedNames.findAll { fqName ->
shortName = nameToShorten.tokenize(separator)[-currentLevel..-1].join(separator)
fqName.endsWith(shortName)
}.size() > 1) {
++currentLevel
}
return shortName
}
println shortestUniqueName('a/b/c/d/e')
Result: c/d/e
It scans a list of fully-qualified filenames and returns the shortest unique form. There are potentially hundreds of fully-qualified names.
As soon as the method finds a short name with only one match, that short name is the right answer, and the iteration can stop. There's no need to scan the rest of the name or do any more expensive list searches.
But turning to a more functional flow in Groovy, neither return nor break can drop you out of the iteration:
return simply returns from the present iteration, not from the whole .each so it doesn't short-circuit.
break isn't allowed outside of a loop, and .each {} and .eachWithIndex {} are not considered loop constructs.
I can't use .find() instead of .findAll() because my program logic requires that I scan all elements of the list, nut just stop at the first.
There are plenty of reasons not to use try..catch blocks, but the best I've read is from here:
Exceptions are basically non-local goto statements with all the
consequences of the latter. Using exceptions for flow control
violates the principle of least astonishment, make programs hard to read
(remember that programs are written for programmers first).
Some of the usual ways around this problem are detailed here including a solution based on a new flavour of .each. This is the closest to a solution I've found so far, but I need to use .eachWithIndex() for my use case (in progress.)
Here's my own poor attempt at a short-circuiting functional solution:
fullyQualifiedNames = ['a/b/c/d/e', 'f/g/h/i/j', 'f/g/h/d/e']
def shortestUniqueName(String nameToShorten) {
def found = ''
def final separator = '/'
def nameComponents = nameToShorten.tokenize(separator).reverse()
nameComponents.eachWithIndex { String _, int i ->
if (!found) {
def candidate = nameComponents[0..i].reverse().join(separator)
def matches = fullyQualifiedNames.findAll { String fqName ->
fqName.endsWith candidate
}
if (matches.size() == 1) {
found = candidate
}
}
}
return found
}
println shortestUniqueName('a/b/c/d/e')
Result: c/d/e
Please shoot me down if there is a more idiomatic way to short-circuit in Groovy that I haven't thought of. Thank you!
There's probably a cleaner looking (and easier to read) solution, but you can do this sort of thing:
String shortestUniqueName(String nameToShorten) {
// Split the name to shorten, and make a list of all sequential combinations of elements
nameToShorten.split('/').reverse().inject([]) { agg, l ->
if(agg) agg + [agg[-1] + l] else agg << [l]
}
// Starting with the smallest element
.find { elements ->
fullyQualifiedNames.findAll { name ->
name.endsWith(elements.reverse().join('/'))
}.size() == 1
}
?.reverse()
?.join('/')
?: ''
}

i made the following binary search algorithm, and I am trying to improve it. suggestions?

i am doing a homework assignment where I have to check large lists of numbers for a given number. the list length is <= 20000, and I can be searching for just as many numbers. if the number we are searching for is in the list, return the index of that number, otherwise, return -1. here is what I did.
i wrote the following code, that outputsthe correct answer, but does not do it fast enough. it has to be done in less than 1 second.
here is my binary search code:`I am looking for suggestions to make it faster.
def binary_search(list1, target):
p = list1
upper = len(list1)
lower = 0
found = False
check = int((upper+lower)//2)
while found == False:
upper = len(list1)
lower = 0
check = int(len(list1)//2)
if list1[check] > target:
list1 = list1[lower:check]
check= int((len(list1))//2)
if list1[check] < target:
list1 = list1[check:upper]
check = int((len(list1))//2)
if list1[check] == target:
found = True
return p.index(target)
if len(list1)==1:
if target not in list1:
return -1`
grateful for any help/
The core problem is that this is not a correctly written Binary Search (see the algorithm there).
There is no need of index(target) to find the solution; a binary search is O(lg n) and so the very presence of index-of, being O(n), violates this! As written, the entire "binary search" function could be replaced as list1.index(value) as it is "finding" the value index simply to "find" the value index.
The code is also slicing the lists which is not needed1; simply move the upper/lower indices to "hone in" on the value. The index of the found value is where the upper and lower bounds eventually meet.
Also, make sure that list1 is really a list such that the item access is O(1).
(And int is not needed with //.)
1 I believe that the complexity is still O(lg n) with the slice, but it is a non-idiomatic binary search and adds additional overhead of creating new lists and copying the relevant items. It also doesn't allow the correct generation of the found item's index - at least without similar variable maintenance as found in a traditional implementation.
Try using else if's, for example if the value thats being checked is greater then you don't also need to check if its smaller.

Resources