Min stack solution not working for leetcode - python

I'm trying a leetcode min stack problem and my code is not working, tried finding a solution but can't see what's wrong. It seems to work for most inputs but fails "
["MinStack","push","push","push","top","pop","getMin","pop","getMin","pop","push","top","getMin","push","top","getMin","pop","getMin"]
[[],[2147483646],[2147483646],[2147483647],[],[],[],[],[],[],[2147483647],[],[],[-2147483648],[],[],[],[]]" .
class MinStack:
def __init__(self):
"""
initialize your data structure here.
"""
self.stack = []
self.count = 0
self.minEle = -1
def push(self, x: int) -> None:
if self.count == 0:
self.minEle = x
self.stack.append(x)
elif x < self.minEle:
self.stack.append(2*x - self.minEle)
self.minEle = x
elif x >= self.minEle:
self.stack.append(x)
self.count += 1
def pop(self) -> None:
y = self.stack.pop()
if y < self.minEle:
self.minEle = 2*self.minEle - y
self.count -= 1
def top(self) -> int:
if self.count >=1:
return self.stack[(self.count - 1)]
else:
return 0
def getMin(self) -> int:
return self.minEle

Try:
class MinStack:
def __init__(self):
self.sc = []
self.sm = []
# #param x, an integer
# #return an integer
def push(self, x):
self.sc.append(x)
if x <= self.getMin():
self.sm.append(x)
return x
# #return nothing
def pop(self):
if self.sc.pop() == self.getMin():
self.sm.pop()
# #return an integer
def top(self):
return self.sc[-1]
# #return an integer
def getMin(self):
try:
return self.sm[-1]
except IndexError:
return self.top()
obj = MinStack()
obj.push(-2)
obj.push(0)
obj.push(-3)
print(obj.getMin())
obj.pop()
print(obj.top())
print(obj.getMin())
param_3 = obj.top()
param_4 = obj.getMin()

Related

Implement B-balancing of the search tree

Got a task: to implement a dictionary based on a search tree with B-balancing, in which the data is stored in leaves.
I wrote a dictionary class: B-balanced segment tree. I understand that a search tree with keys k1, k2, k3 ... kn corresponds to a segment tree with segments, or rather, half-intervals (-inf,k1) [k1, k2) [k2, k3) ... [kn, inf) , but I don't understand how to implement it in terms of my class. I would really appreciate any help.
class Node:
def __init__(self, segment,value = None,children = []):
self.segment = segment
self.value = value
self.children = children
self.exist = 1
class Dict():
def __init__(self):
self.root = None
self.len = 0
self.t = 4
self.combine = sum
def __len__(self):
return self.len
def __getitem__(self, key):
if not self.root:
raise KeyError()
else:
return self.get(self.root, key)
def __contains__(self, key):
try:
self.__getitem__(key)
return True
except:
return False
def __setitem__(self, key, value):
if not self.root:
self.root = self.make_branch([self.make_leaf(key,value)])
self.len += 1
else:
if key not in self:
self.len += 1
self.root = self.tree_put(self.root, key, value)
def __delitem__(self, key):
if key not in self:
raise KeyError()
else:
self.delete(self.root, key)
self.len -= 1
def get(self,tree,key):
if key == tree.segment[0] and key == tree.segment[1] and tree.exist == 1:
return tree.value
elif tree.segment[0] != tree.segment[1]:
i = 0
while i < len(tree.children):
if tree.children[i].segment[0] > key: break
i+=1
try:
return self.get(tree.children[i-1],key)
except:
raise KeyError()
raise KeyError()
def delete(self, tree, key):
if key == tree.segment[0] and key == tree.segment[1] and tree.exist == 1:
tree.exist = 0
return
elif tree.segment[0] != tree.segment[1]:
i = 0
if len(tree.children) > 0:
while i < len(tree.children):
if tree.children[i].segment[0] >= key: break
i+=1
try:
return self.delete(tree.children[i],key)
except:
return self.delete(tree.children[i-1],key)
raise KeyError()
def make_leaf(self, key, value): return Node((key, key), self.combine([value]), [] )
def make_branch(self, trees):
segments = [ tree.segment for tree in trees ]
left = segments[0][0]
right = segments[-1][1]
value = self.combine([ tree.value for tree in trees ])
return Node((left, right), value, trees[:])
def tree_segment_value(self, tree, a, b):
ta, tb = tree.segment
if a <= ta and tb <= b: return tree.value
to_combine = []
for child in tree.children:
ta, tb = child.segment
if tb < a: continue
if ta > b: break
if a <= ta and tb <= b: to_combine.append(child.value)
else: to_combine.append(tree_segment_value(child, a, b))
return self.combine(to_combine)
def tree_put_rec(self,tree,key,value):
if tree == None:
return [self.make_branch([self.make_leaf(key,value)])]
i = 0
while i < len(tree.children):
if tree.children[i].segment[0] > key: break
i+=1
if i > 0: i-=1
left_children = tree.children[:i]
right_children = tree.children[i+1:]
child = tree.children[i]
if len(child.children) == 0:
new_leaf = self.make_leaf(key,value)
child_key = child.segment[0]
if child_key < key: mid_children = [child,new_leaf]
elif child_key > key: mid_children = [new_leaf,child]
else: mid_children = [new_leaf]
else:
mid_children = self.tree_put_rec(child,key,value)
new_children = left_children+mid_children+right_children
N = len(new_children)
if N > self.t: to_wrap = [new_children[:N//2],new_children[N//2:]]
else: to_wrap = [new_children]
return [self.make_branch(subtrees) for subtrees in to_wrap]
def tree_put(self, tree,key,value):
new_trees = self.tree_put_rec(tree,key,value)
if len(new_trees) < 2: return new_trees[0]
return self.make_branch(new_trees)

Printing BST in Python

I have made the BST in Python, but I have a problem with printing it. When I try to print it like this: tree.BSTinOrder(Node(4)), it prints only 4 and below "None".
Generally I'd expect it to be printed "fine" so it can somehow draw the tree or at least that I could see which node is connected with other.
If I want to print whole tree, should I do some kind of loop?
My code:
class Node:
def __init__(self,x):
self.key = x
self.left = None
self.right = None
self.p = None
class BST:
def __init__(self):
self.root = None
def BSTsearch(self,k):
x = self.root
while x!=None and x.key!=k:
if k<x.key:
x=x.left
else:
x=x.right
return x
def BSTinsert(self, z):
x = self.root
y = None
while x != None:
y=x
if z.key<x.key:
x=x.left
else:
x=x.right
z.p=y
if y==None:
self.root=z
else:
if z.key<y.key:
y.left=z
else:
y.right=z
def bstDelete(self, z):
if z.left == None and z.right == None:
if z == self.root:
self.root = None
else:
if z == z.p.left:
z.p.left = None
else:
z.p.right = None
elif z.left != None and z.right != None:
y = self.bstMinimum(z.right)
z.key = y.key
self.bstDelete(y)
else:
if z.left != None:
z.left.p=z.p
if z==self.root:
self.root=z.left
else:
if z==z.p.left:
z.p.left=z.left
else:
z.p.right=z.left
else:
z.right.p=z.p
if z==self.root:
self.root=z.right
else:
if z==z.p.left:
z.p.left=z.left
else:
z.p.right=z.left
def bstMinimum(self, x):
while x.left != None:
x = x.left
return x
def BSTinOrder(self, x):
if x == None: return
self.BSTinOrder(x.left)
print(x.key)
self.BSTinOrder(x.right)
tree = BST()
tree.BSTinsert(Node(5))
tree.BSTinsert(Node(3))
tree.BSTinsert(Node(7))
tree.BSTinsert(Node(2))
tree.BSTinsert(Node(4))
tree.BSTinsert(Node(9))
tree.BSTinsert(Node(8))
Try this:
class Node:
def __init__(self, x):
self.key = x
self.left = None
self.right = None
self.p = None
class BST:
def __init__(self):
self.root = None
def BSTsearch(self, k):
x = self.root
while x != None and x.key != k:
if k < x.key:
x = x.left
else:
x = x.right
return x
def BSTinsert(self, z):
x = self.root
y = None
while x != None:
y = x
if z.key < x.key:
x = x.left
else:
x = x.right
z.p = y
if y == None:
self.root = z
else:
if z.key < y.key:
y.left = z
else:
y.right = z
def bstDelete(self, z):
if z.left == None and z.right == None:
if z == self.root:
self.root = None
else:
if z == z.p.left:
z.p.left = None
else:
z.p.right = None
elif z.left != None and z.right != None:
y = self.bstMinimum(z.right)
z.key = y.key
self.bstDelete(y)
else:
if z.left != None:
z.left.p = z.p
if z == self.root:
self.root = z.left
else:
if z == z.p.left:
z.p.left = z.left
else:
z.p.right = z.left
else:
z.right.p = z.p
if z == self.root:
self.root = z.right
else:
if z == z.p.left:
z.p.left = z.left
else:
z.p.right = z.left
def bstMinimum(self, x):
while x.left != None:
x = x.left
return x
def BSTinOrder(self, x):
if x == None: return
self.BSTinOrder(x.left)
print(x.key)
self.BSTinOrder(x.right)
def bstGetRoot(self):
return self.root
tree = BST()
tree.BSTinsert(Node(5))
tree.BSTinsert(Node(3))
tree.BSTinsert(Node(7))
tree.BSTinsert(Node(2))
tree.BSTinsert(Node(4))
tree.BSTinsert(Node(9))
tree.BSTinsert(Node(8))
tree.BSTinOrder(tree.bstGetRoot())
Output:
2
3
4
5
7
8
9
I think you misunderstood how to traverse through a tree. You would need the root for that. Notice how I added a method to retrieve the tree's root, and then passed it to the inoder traversal funtion, which worked just fine.

Why does self variable lose value after method invocation

I have this code to implement queue and stack data structures. The QueueT by itself works as desired.
When I call st.push(1), it agreeable calls push(self, v) and this in turn calls the enqueue method.
The issue I am facing is that after the statement self._q1.enqueue(v) is executed, self._q1 does not retain the value v.
Code for class QueueT:
class QueueT:
def __init__(self):
self._CAPACITY = 6
self._data = [None] * self._CAPACITY
self._length = 0
self._first = 0
def enqueue(self, val):
if self.size() == self._CAPACITY:
self._resize(self._CAPACITY * 2)
self.enqueue(val)
else:
new_place = (self._first + self.size()) % self._CAPACITY
self._data[new_place] = val
self._length += 1
def size(self):
return self._length
def _resize(self, new_capacity):
old = self._data
old_capacity = len(old)
self._data = [None] * new_capacity
k = self._first
self._first = 0
for j in range(self._length):
self._data[j] = old[k]
k = (1 + k) % old_capacity
self._CAPACITY = new_capacity
Now code from StackFromQ:
class StackFromQ:
def __init__(self):
self._q1 = QueueT()
self._top = -1
def push(self, v):
self._q1.enqueue(v)
self._top += 1
Caller function:
def stack_of_q():
st = StackFromQ()
st.push(1)
st.push(2)
Finally invocation:
stack_of_q()

Remove Method Linked List

I am working on a doubly linked list and I can't get my remove function to work correctly. I want to return the value that it is being removed. I have tried various times, with no success. An extra pair of eye would be appreciated.
class DoublyLinked_List:
class __Node:
def __init__(self, val):
self.val = val
self.next = None
self.prev = None
def __init__(self):
self.__header = self.__Node(None)
self.__trailer = self.__Node(None)
self.__header.next = self.__trailer
self.__trailer.prev = self.__header
self.__size = 0
def __len__(self):
return self.__size
def remove_element_at(self, index):
if index > self.__size or index < 0 or index == self.__size:
raise IndexError
current = self.__header.next
if index == 0:
self.__header.next = self.__header.next.next
else:
for i in range(0, index-1):
current = current.next
current.next = current.next.next
self.__size -= 1
return current.val

Circular Queue Structure ( array-backed)

I need some help in writing a python program that will implement a circular queue data structure (array-backed). I've completed a few of the methods already but I'm a bit stumped when it comes to adding and taking things away from the queue, as well as checking the values within it. I believe this is of the first-in-first-out structure. Here's what I have for the body so far
class Queue:
''' Constructor '''
def __init__(self, limit):
self.limit = limit
self.data = [None] * limit
self.queue = []
self.head = -1
self.tail = -1
self.count = 0
def dequeue(self):
if self.count == 0:
raise RuntimeError
else:
self.head = 0
x = self.queue.pop(0)
if self.head == self.tail:
self.head = -1
self.tail = -1
else:
self.tail -= 1
self.count -= 1
#self.head += 1
return x
def enqueue(self, item):
if self.count == self.limit:
raise RuntimeError
else:
self.count += 1
self.queue.append(item)
self.tail += 1
def __str__(self):
return " ".join([str(v) for v in self.queue])
def resize(self, new_limit):
new_q = [None]*self.limit
old_q = self.queue
for i in range(len(old_q)):
new_q[i] = old_q[i]
self.limit = new_limit
self.queue = new_q
def empty(self):
return 0 == self.count
def iter(self):
listt = []
for v in self.queue:
listt.append(v)
return listt
What I 've written thus far makes the most sense to me but if I were to test this with the following code block I'd get an error saying 10 != 4. This code will fail the 9th line of the test, tc.assertEqual(q.data.count(None), 4) I'm unsure why my code is producing the value 10 at this time. What would allow for this class to pass the given test?
from unittest import TestCase
tc = TestCase()
q = Queue(10)
for i in range(6):
q.enqueue(i)
tc.assertEqual(q.data.count(None), 4)
for i in range(5):
q.dequeue()
tc.assertFalse(q.empty())
tc.assertEqual(q.data.count(None), 9)
tc.assertEqual(q.head, q.tail)
tc.assertEqual(q.head, 5)
for i in range(9):
q.enqueue(i)
with tc.assertRaises(RuntimeError):
q.enqueue(10)
for x, y in zip(q, [5] + list(range(9))):
tc.assertEqual(x, y)
I'm pretty sure that all the code using self.queue is wrong. That attribute isn't needed at all. The whole point of the data attribute is to use it to store the values. Use the indexes head and tail to figure out where in data to put things (and where to take them from):
class Queue:
''' Constructor '''
def __init__(self, limit):
self.limit = limit
self.data = [None] * limit
self.head = 0
self.tail = -1
self.count = 0
def dequeue(self):
if self.count == 0:
raise RuntimeError
else:
x = self.data[self.head]
self.head = (self.head + 1) % self.limit
self.count -= 1
return x
def enqueue(self, item):
if self.count == self.limit:
raise RuntimeError
else:
self.count += 1
self.tail = (self.tail + 1) % self.limit
self.data[self.tail] = item
def __str__(self):
return " ".join([str(v) for v in self]) # use __iter__
def resize(self, new_limit):
if new_limit < self.count:
raise RuntimeError
new_data = [None]*new_limit
for i, item in enumerate(self):
new_data[i] = item
self.data = new_data
self.head = 0
self.tail = self.count - 1
def empty(self):
return 0 == self.count
def __bool__(self): # this is better than empty()
return self.count != 0
def __iter__(self): # renamed from iter so you can use it in a for loop
for i in range(self.count):
return self.data[(self.head + i) % self.limit]
You should probably also have a __len__ method.
I'd get an error stating that the Queue class doesn't have a data attribute
I don't have the error you mention when running your test on your code.
If for some reasons you don't want to use built-in collections.deque module, here is an example of how you can implement your own circular buffer:
"""
Example of circular buffer using regular list
"""
class CircularBuffer:
def __init__(self, size):
self.buffer = [None] * size
self.size = size
self.count = 0
self.tail = 0
self.head = 0
#property
def is_empty(self):
return self.count == 0
#property
def is_full(self):
return self.count == self.size
def __len__(self):
return self.count
def add(self, value):
# if buffer is full overwrite the value
if self.is_full:
self.tail = (self.tail + 1) % self.size
else:
self.count += 1
self.buffer[self.head] = value
self.head = (self.head + 1) % self.size
def remove(self):
if self.count == 0:
raise Exception("Circular Buffer is empty")
value = self.buffer[self.tail]
self.tail = (self.tail + 1) % self.size
self.count -= 1
return value
def __iter__(self):
index = self.tail
counter = self.count
while counter > 0:
yield self.buffer[index]
index = (index + 1) % self.size
counter -= 1
def __repr__(self):
return "[]" if self.is_empty else "[" + ",".join(str(i) for i in self) + "]"

Categories

Resources