Estructura de datos y algoritmo (5) - Cola y sus algoritmos relacionados

Conceptos básicos de la cola

Introducción

Como se muestra en la imagen ( la imagen proviene de la columna "La belleza de la estructura de datos y el algoritmo" de Geek Time )

inserte la descripción de la imagen aquí

Solo la cola de la cola puede ingresar a la cola, y la cabeza de la cola se descarga (es decir, la estructura de almacenamiento de primero en entrar, primero en salir).

cola secuencial

La cola implementada usando una matriz, la cola que a menudo se prueba en las entrevistas generales es una cola circular (la implementación se describe a continuación). Las características de esta cola son:

  1. tamaño de cola fijo
  2. La complejidad de tiempo de dequeue y enqueue es O(1)

cola encadenada

Una cola implementada en forma de lista enlazada.Las características de la cola son:

  1. Tamaño de cola ilimitado
  2. La complejidad de tiempo de dequeue y enqueue es O(1)

algoritmo común

implementar una cola circular

La cola circular se realiza mediante punteros dobles cabeza y cola que apuntan a la cabeza y la cola de la cola respectivamente. Al implementar una cola circular, se debe prestar atención al juicio de si la cola está vacía y si la cola está llena. Las condiciones son las siguientes:

La cola está vacía: cabeza == cola

La cola está llena: (cola + 1)% de capacidad == cabeza

el código se muestra a continuación:

class LoopQueue{

          int[] queue = null;
          int capacity = 0;
          int head = 0;
          int tail = 0;

          public LoopQueue(int capacity) {
              this.capacity = capacity;
              queue = new int[capacity];
          }

          public void add(int val){
              if((tail + 1) % capacity == head){
                  System.out.println("队列已满");
              }else {
                  System.out.println("插入值:"+val);
                  tail = tail%capacity;
                  queue[tail] = val;
                  tail++;
              }
          }

          public void remove(){
              if(head%capacity == tail){
                  System.out.println("队列已空");
              }else {
                  head = head%capacity;
                  int val = queue[head];
                  System.out.println("删除的值为:"+val);
                  head++;
              }
          }
      }

Diseño de cola circular de dos extremos

设计实现双端队列。
你的实现需要支持以下操作:

MyCircularDeque(k):构造函数,双端队列的大小为k。
insertFront():将一个元素添加到双端队列头部。 如果操作成功返回 trueinsertLast():将一个元素添加到双端队列尾部。如果操作成功返回 truedeleteFront():从双端队列头部删除一个元素。 如果操作成功返回 truedeleteLast():从双端队列尾部删除一个元素。如果操作成功返回 truegetFront():从双端队列头部获得一个元素。如果双端队列为空,返回 -1getRear():获得双端队列的最后一个元素。 如果双端队列为空,返回 -1isEmpty():检查双端队列是否为空。
isFull():检查双端队列是否满

示例:
MyCircularDeque circularDeque = new MycircularDeque(3); // 设置容量大小为3
circularDeque.insertLast(1);			        // 返回 true
circularDeque.insertLast(2);			        // 返回 true
circularDeque.insertFront(3);			        // 返回 true
circularDeque.insertFront(4);			        // 已经满了,返回 false
circularDeque.getRear();  				// 返回 2
circularDeque.isFull();				        // 返回 true
circularDeque.deleteLast();			        // 返回 true
circularDeque.insertFront(4);			        // 返回 true
circularDeque.getFront();				// 返回 4

el código se muestra a continuación:

class MyCircularDeque {
    
    

   class Node{
    
    
       Node next;
       int value;
       Node(int value){
    
    
         this.value = value;
       }
   }

   Node head;
   Node tail;
   int count = 0;
   int capcity;

    /** Initialize your data structure here. Set the size of the deque to be k. */
    public MyCircularDeque(int k) {
    
    
       head = new Node(-1);
       tail = new Node(-1);
       capcity = k;
    }
    
    /** Adds an item at the front of Deque. Return true if the operation is successful. */
    public boolean insertFront(int value) {
    
    
        if(count >= capcity)return false;
        Node next = new Node(value);
         if(count == 0){
    
    
             head.next = next;
             tail.next = next;
         }else{
    
    
             Node p = head.next;
             head.next = next;
             next.next = p;
         }
         count++;
         return true;
    }
    
    /** Adds an item at the rear of Deque. Return true if the operation is successful. */
    public boolean insertLast(int value) {
    
    
       if(count >= capcity)return false;
        Node next = new Node(value);
         if(count == 0){
    
    
             head.next = next;
             tail.next = next;
         }else{
    
    
             Node p = tail.next;
             tail.next = next;
             p.next = next;
         }
         count++;
         return true;
    }
    
    /** Deletes an item from the front of Deque. Return true if the operation is successful. */
    public boolean deleteFront() {
    
    
       if(count == 0)return false;
       if(count == 1){
    
    
         head.next = null;
         tail.next = null; 
       }else{
    
    
         Node p = head.next;
         head.next = p.next;
         p.next = null;
       }
       count--;
       return true;
    }
    
    /** Deletes an item from the rear of Deque. Return true if the operation is successful. */
    public boolean deleteLast() {
    
    
       if(count == 0)return false;
       if(count == 1){
    
    
         head.next = null;
         tail.next = null; 
       }else{
    
    
         Node p = tail.next;
         Node root = head.next;
         while(root!=null&&root.next != p)root = root.next;
         tail.next = root;
         root.next = null;
       }
       count--;
       return true;
    }
    
    /** Get the front item from the deque. */
    public int getFront() {
    
    
      if(count == 0)return -1;  
      Node node = head.next;
      return node.value;
    }
    
    /** Get the last item from the deque. */
    public int getRear() {
    
    
      if(count == 0)return -1;  
      Node node = tail.next;
      return node.value;
    }
    
    /** Checks whether the circular deque is empty or not. */
    public boolean isEmpty() {
    
    
       return count == 0;
    }
    
    /** Checks whether the circular deque is full or not. */
    public boolean isFull() {
    
    
      return count == capcity;
    }
}

El valor máximo de la ventana deslizante.

给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值。

示例:

输入: nums = [1,3,-1,-3,5,3,6,7], 和 k = 3
输出: [3,3,5,5,6,7] 
解释: 

  滑动窗口的位置                最大值
---------------               -----
[1  3  -1] -3  5  3  6  7       3
 1 [3  -1  -3] 5  3  6  7       3
 1  3 [-1  -3  5] 3  6  7       5
 1  3  -1 [-3  5  3] 6  7       5
 1  3  -1  -3 [5  3  6] 7       6
 1  3  -1  -3  5 [3  6  7]      7

Idea de implementación:

Piense en la ventana como una cola, y cada deslizamiento es una operación de sacar y poner en cola.

Método 1: si el valor máximo en la cola se obtiene por comparación cada vez, dado que el tamaño de la cola es k, la complejidad del tiempo es O (n * k).

Método 2: cuando el valor de eliminación de cola de la ventana deslizante es el elemento opuesto de la cola, deje que el elemento opuesto en la cola se elimine de la cola; cuando el valor de la ventana deslizante que ingresa a la cola es mayor que el elemento al final de la cola , deje que el elemento al final de la cola se elimine de la cola, sin parar Bucle hasta que el elemento al final de la cola sea mayor que el elemento que ingresa a la cola o la cola esté vacía, y luego inserte un elemento al final del cola. De esta manera, los valores en la cola se pueden ordenar en orden inverso, y cada vez solo se debe tomar el elemento correcto como valor máximo.

el código se muestra a continuación:

class Solution {
    
    
    public int[] maxSlidingWindow(int[] nums, int k) {
    
    
       if(nums.length == 0)return new int[0]; 
       if(k == 1)return nums;
       int[] res = new int[nums.length - k + 1];
       Deque<Integer> l = new LinkedList<>();
       for(int i = 0;i < k;i++){
    
    
           if(l.isEmpty())l.add(nums[i]);
           else{
    
    
               while(!l.isEmpty() && nums[i] > l.peekLast()){
    
    
                  l.pollLast();
               }
               l.add(nums[i]);
           }
       }
       res[0] = l.peekFirst();
       for(int i = k;i < nums.length;i++){
    
    
            if(nums[i - k] == l.peekFirst())l.pollFirst();
            while(!l.isEmpty() && nums[i] > l.peekLast()){
    
    
                l.pollLast();
            }
            l.add(nums[i]);
            res[i - k + 1] = l.peekFirst();
       }
       return res;
    }
}

Implementación de código que debe dominarse

  • Implementar una cola secuencial con una matriz
  • Implementar una cola encadenada con una lista enlazada
  • implementar una cola circular

Preguntas algorítmicas relacionadas con colas que a menudo se prueban en entrevistas

Supongo que te gusta

Origin blog.csdn.net/lichukuan/article/details/127063398
Recomendado
Clasificación