-
Notifications
You must be signed in to change notification settings - Fork 3
/
180_Google_Interleave_Stack.py
executable file
·145 lines (106 loc) · 3.81 KB
/
180_Google_Interleave_Stack.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
"""
This problem was asked by Google.
Given a stack of N elements, interleave the first half of the stack with the second half reversed
using only one other queue. This should be done in-place.
Recall that you can only push or pop from a stack, and enqueue or dequeue from a queue.
For example, if the stack is [1, 2, 3, 4, 5], it should become [1, 5, 2, 4, 3].
If the stack is [1, 2, 3, 4], it should become [1, 4, 2, 3].
Hint: Try working backwards from the end state.
"""
from queue import SimpleQueue
from math import ceil
class Stack:
def __init__(self):
self._stack = [] # top of stack will be the end of the list.
def push(self, value):
self._stack.append(value)
def pop(self):
return self._stack.pop()
def size(self):
return len(self._stack)
def push_from_list(self, l):
for val in l:
self.push(val)
def reverse(self):
self._stack.reverse()
def interleave_stack(self):
def pop_from_stack_to_queue(num_of_times):
for _ in range(num_of_times):
queue.put(self.pop())
def push_from_queue_to_stack(num_of_times):
for _ in range(num_of_times):
self.push(queue.get())
# create queue
queue = SimpleQueue()
# reverse stack
self.reverse()
size_of_stack = self.size()
for i in range(size_of_stack, 1, -1):
pop_from_stack_to_queue(num_of_times=i)
push_from_queue_to_stack(num_of_times=i)
def interleave_stack_redux(self):
"""
This follows a different approach
Thing to note in a stack of [1,2,3,4,5] the resultant
interleaved stack is the result of the stack [3,2,1] and the queue (5, 4)
If we do the following:
[3, 2, 1], (5, 4)
[3, 2, 1], (5, 4, 1)
[3, 2], (4, 1, 5)
[3, 2], (4, 1, 5)
[3], [4, 1, 5, 2]
[3], [1, 5, 2, 4]
[], [1,5,2,4,3]
[1, 5, 2, 4, 3]
First to get to the state [3, 2, 1], (5, 4)
[1, 2, 3, 4, 5]
put all stack to queue [], (5,4,3,2,1)
pop len(stack)//2 from queue back into queue -> (3,2,1,5,4)
pop ceil(stack/2) from queue into stack -> [3, 2, 1], (5,4)
Now do the above steps
"""
queue = SimpleQueue()
size_of_stack = self.size()
# step 1: move all elements to queue
while self._stack:
queue.put(self.pop())
# step 2: Rotate queue for size_of_stack//2 elements
for _ in range(size_of_stack//2):
queue.put(queue.get())
# step 3: put ceil(size_of_stack/2) elements back to queue
for _ in range(ceil(size_of_stack/2)):
self.push(queue.get())
# step 4: interleave the stack
for _ in range(size_of_stack//2):
# pop from stack then get from queue
queue.put(self.pop())
queue.put(queue.get())
if self._stack:
# if any remaining pop to queue
queue.put(self.pop())
# step 5: pop to stack
while not queue.empty():
self.push(queue.get())
def __repr__(self):
stack_str = ""
# using stack s a list here
for val in self._stack[::-1]:
stack_str = stack_str + "| " + str(val) + " |\n"
stack_str += "|===|"
return stack_str
if __name__ == '__main__':
stack_1 = Stack()
stack_1.push_from_list([1, 2, 3, 4, 5])
print(stack_1)
print("\nAfter interleaving:")
# stack_1.interleave_stack()
stack_1.interleave_stack_redux()
print(stack_1)
print("\n-----------\n")
stack_2 = Stack()
stack_2.push_from_list([1, 2, 3, 4])
print(stack_2)
print("\nAfter interleaving:")
# stack_2.interleave_stack()
stack_2.interleave_stack_redux()
print(stack_2)