Leetcode algorithm interview sprint practice 11 (queue)

Posted by rcarr on Thu, 03 Feb 2022 09:56:47 +0100

40. Implement queue with stack

As stated in the title, you can only use two stacks to implement some operations of the queue. The queue should support push(element), pop() and top(), where pop is the first (foremost) element in the pop-up queue. Both pop and top methods should return the value of the first element.



class MyQueue:
    
    def __init__(self):
        # do intialization if necessary
        self.stack1 = []
        self.stack2 = []

    """
    @param: element: An integer
    @return: nothing
    """
    def push(self, element):
        # write your code here
        self.stack1.append(element)

    """
    @return: An integer
    """
    def pop(self):
        # write your code here
        if self.stack2:
            return self.stack2.pop()
        else:
            while self.stack1:
                self.stack2.append(self.stack1.pop()) 
            return self.stack2.pop()


    """
    @return: An integer
    """
    def top(self):
        # write your code here
        if self.stack2:
            return self.stack2[-1]
        else:
            while self.stack1:
                self.stack2.append(self.stack1.pop()) 
            return self.stack2[-1]

Here is the official answer, which is similar to what I wrote:

class MyQueue:

    def __init__(self):
        self.stack1 = []
        self.stack2 = []

    def stack1_to_stack2(self):
        # If stack2 is not empty, do not reverse stack1
        if self.stack2:
            return
        while self.stack1:
            self.stack2.append(self.stack1.pop())
                
    def push(self, element):
        self.stack1.append(element)

    def top(self):
        self.stack1_to_stack2()
        return self.stack2[-1]

    def pop(self):
        self.stack1_to_stack2()
        return self.stack2.pop()

493 · maintenance queue II

Queue is realized through linked list. Provide the following basic methods:

  • push_front(item). Adds a new item to the front of the queue.
  • push_back(item). Add a new item to the back of the queue.
  • pop_front(). Remove the first item from the queue and return it.
  • pop_back(). Remove the last item from the queue and return it.


I wrote for an hour, but I didn't write it out

class ListNode():

    def __init__(self, val=None):
        self.val = val
        self.next = None


class Dequeue:

    def __init__(self):
        # do intialization if necessary
        self.beforehead = self.tail = ListNode(-1)

    """
    @param: item: An integer
    @return: nothing
    """

    def push_front(self, item):
        # write your code here
        self.tail.next = ListNode(item)
        self.beforetail = self.tail
        self.tail = self.tail.next

    """
    @param: item: An integer
    @return: nothing
    """

    def push_back(self, item):
        # write your code here
        node = ListNode(item)
        node.next = self.beforehead.next
        self.beforehead.next = node
        self.tail = self.tail.next


    """
    @return: An integer
    """

    def pop_front(self):
        # write your code here
        tail_val = self.tail.val
        self.tail = self.beforetail
        self.tail.next = None
        return tail_val

    """
    @return: An integer
    """

    def pop_back(self):
        # write your code here

        if self.beforehead.next is not None:
            head_val = self.beforehead.next.val
            self.beforehead.next = self.beforehead.next.next
            return head_val
        else:
            return False


The official answer uses a two-way linked list

class Dequeue(object):

    def __init__(self):
        # do some intialize if necessary
        self.first, self.last = None, None

    # @param {int} item an integer
    # @return nothing
    def push_front(self, item):
        # Write yout code here
        if self.first is None:
            self.first = Node(item)
            self.last = self.first
        else:
            tmp = Node(item)
            self.first.prev = tmp
            tmp.next = self.first
            self.first = tmp

    # @param {int} item an integer
    # @return nothing
    def push_back(self, item):
        # Write yout code here
        if self.last is None:
            self.first = Node(item)
            self.last = self.first
        else:
            tmp = Node(item)
            self.last.next = tmp
            tmp.prev = self.last
            self.last = tmp

    # @return an integer
    def pop_front(self):
        # Write your code here
        if self.first is not None:
            item = self.first.val
            self.first = self.first.next
            if self.first is not None:
                self.first.prev = None
            else:
                self.last = None
            return item

        return -12

    # @return an integer
    def pop_back(self):
        # Write your code here
        if self.last is not None:
            item = self.last.val
            self.last = self.last.prev
            if self.last is not None:
                self.last.next = None
            else:
                self.first = None
            return item

        return -12

class Node():

    def __init__(self, _val):
        self.next = self.prev = None
        self.val = _val

546. Implement queue by interface

Implement queue by interface
The interface class tells you what method to implement. You only need to write the name of the method, that is, the name of the interface in the future.
Then implement specific methods in the following classes.

class InterfaceQueue:
    def push(self, element):
        pass

    # define an interface for pop method
    # write your code here
    def pop(self):
        pass

    # define an interface for top method
    # write your code here
    def top(self):
        pass

class MyQueue(InterfaceQueue):
    # you can declare your private attributes here
    def __init__(self):
        # do initialization if necessary
        self.before_head = self.tail = ListNode(-1)
		
    # implement the push method
    # write your code here
    def push(self, val):
        self.tail.next = ListNode(val)
        self.tail = self.tail.next
		
    # implement the pop method
    # write your code here
    def pop(self):
        if self.before_head.next is not None:
            res_val = self.before_head.next.val
            self.before_head = self.before_head.next
            return res_val
        else:
            return -1

    	
	# implement the top method
    # write your code here
    def top(self):
        return self.before_head.next.val
        
# Your MyQueue object will be instantiated and called as such:
# MyQueue queue = new MyQueue();
# queue.push(123);
# queue.top(); will return 123;
# queue.pop(); will return 123 and pop the first element in the queue

Notice here, I wrote it at the beginning

Error:
self.before_head.next = self.before_head.next.next
 correct:
self.before_head = self.before_head.next

642 · average value of data flow sliding window

Give a string of integer streams and window sizes, and calculate the average value of all integers in the sliding window.

Double ended queue creation method:

import collections
d = collections.deque()
import collections
class MovingAverage(object):
    """
    @param: size: An integer
    """
    def __init__(self, size):
        # do intialization if necessary
        self.deque = collections.deque()
        self.size = size

    """
    @param: val: An integer
    @return:  
    """
    def next(self, val):
        # write your code here
        if len(self.deque) < self.size:
            self.deque.append(val)
            return sum(self.deque) / len(self.deque)
        else:
            self.deque.popleft()
            self.deque.append(val)
            return sum(self.deque) / self.size



# Your MovingAverage object will be instantiated and called as such:
# obj = MovingAverage(size)
# param = obj.next(val)

Here are the official answers:

from collections import deque


class MovingAverage(object):

    def __init__(self, size):
        self.queue = deque([])
        self.size = size
        self.sum = 0.0
        

    def next(self, val):
        if len(self.queue) == self.size:
            self.sum -= self.queue.popleft()
            
        self.sum += val
        self.queue.append(val)
        return self.sum / len(self.queue)

1166 · recommended results scattered

A recommendation system will recommend a list of video and picture elements. x represents the element number, and V is used for video_ x indicates that the picture is represented by P_x means. Now you need to break up these elements. The rules are as follows:

  1. The position where the first [picture P] appears remains unchanged;
  2. Starting from the first [picture P], exactly one [picture P] appears in every n elements;
  3. The relative order between pictures remains unchanged;

Elements that cannot meet the fragmentation rule need to be discarded. Given the element list and the value of n, please return the scattered element list.


I wrote for a long time, but I didn't write it out

from typing import (
    List,
)

class Solution:
    """
    @param elements: A list of recommended elements.
    @param n: [picture P] can appear at most 1 in every n
    @return: Return the scattered result.
    """
    def scatter(self, elements: List[str], n: int) -> List[str]:
        # write your code here
        temp = []
        res = []
        cur = 0
        mark = -100

        while cur < len(elements):
            index = len(res) - 1
            if index == mark:
                if temp != []:
                    res.append(temp.pop(0))
                    cur += 1
                else:
                    break

            if elements[cur][0] == 'V':
                if index == mark:
                    if temp != []:
                        res.append(temp.pop(0))
                        cur += 1
                    else:
                        break
                else:
                    res.append(elements[cur])
                    cur += 1
            elif elements[cur][0] == 'P':
                if mark == -100:
                    res.append(elements[cur])
                    mark = index + n
                    cur += 1
                elif index != mark:
                    temp.append(elements[cur])
                    cur += 1
                elif index == mark:
                    if temp != []:
                        res.append(temp.pop(0))
                        cur += 1
                    else:
                        break
            
        return res

Read an answer, use two queue s to store P and V respectively, and then break up according to his rules.

import queue


class Solution:
    """
    @param elements: A list of recommended elements.
    @param n: [picture P] can appear at most 1 in every n
    @return: Return the scattered result.
    """

    def scatter(self, elements, n):
        # write your code here
        #  Define double queues to store picture element P and video element V respectively
        queueP = queue.Queue()
        queueV = queue.Queue()

        #  Where the first picture P appears
        firstP = -1
        for i in range(0, len(elements)):
            if elements[i][0] == 'P':
                #  First picture P
                if firstP == -1:
                    firstP = i
                #  P join the queue
                queueP.put(elements[i])
            else:
                #  This element is added to the V queue
                queueV.put(elements[i])

        # Define the result sequence after fragmentation
        result = []

        # Store the V element before the first P into the result sequence
        while firstP > 0:
            firstP -= 1
            result.append(queueV.get())

        while queueP.empty() == False:
            #  Exactly one P is required in every n elements
            result.append(queueP.get())

            # Auxiliary variable
            step = n

            # Store n-1 V elements into the result sequence
            while queueV.empty() == False and step > 1:
                result.append(queueV.get())
                step -= 1

            # If the requirements for breaking up cannot be met at present, it can be ended directly
            if step > 1:
                break

        return result

Another answer is similar:

def scatter(self, elements, n):
        # write your code here
        q_V = collections.deque()
        q_P = collections.deque()
        first_p = -1
        res = []
        for i in range(len(elements)):
            if elements[i][0] == "P":
                first_p = i
                break
        res = elements[:first_p]

        for i in range(first_p, len(elements)):
            if elements[i][0] == "P":
                q_P.append(elements[i])
            else:
                q_V.append(elements[i])
        
        while q_P: # break while loop when q_P is empty
            res.append(q_P.popleft())
            temp = n 
            while q_V and temp > 1:
                res.append(q_V.popleft())
                temp -= 1
            
            if temp > 1: # q_V is empty, break loop, even if q_P is not empty
                break

        return res

Topics: Algorithm leetcode Interview