Home > Algorithm > 2024 > ๐Ÿ“ฆ[DS,Algorithm] Deque(๋ฐํฌ, ๋ฑ)

๐Ÿ“ฆ[DS,Algorithm] Deque(๋ฐํฌ, ๋ฑ)
DataStructure Algorithm

1๏ธโƒฃ Deque(๋ฑ, Double Ended Queue)

Deque(๋ฑ, Double Ended Queue)๋Š” ์–‘์ชฝ ๋์—์„œ ์‚ฝ์ž…๊ณผ ์‚ญ์ œ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋Š” ์ž๋ฃŒ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

Java์—์„œ๋Š” java.util ํŒจํ‚ค์ง€์—์„œ ์ œ๊ณตํ•˜๋Š” Deque ์ธํ„ฐํŽ˜์ด์Šค์™€ ์ด๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์ธ ArrayDeque ์™€ LinkedList ๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Deque ๋Š” ํ(Queue)์™€ ์Šคํƒ(Stack)์˜ ๊ธฐ๋Šฅ์„ ๋ชจ๋‘ ํฌํ•จํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

1๏ธโƒฃ ๋ฐํฌ ๊ธฐ๋ณธ ๊ตฌ์กฐ

  • ๋ฐํฌ์˜ ๊ธฐ๋ณธ ๊ตฌ์กฐ๋Š” ์–‘๋ฐฉํ–ฅ์—์„œ ์‚ฝ์ž… ์‚ญ์ œ ๊ฐ€๋Šฅํ•œ ๊ตฌ์กฐ

  • ์ผ๋ถ€ ๊ธฐ๋Šฅ์„ ์ œํ•œํ•˜์—ฌ ์šฉ๋„์— ๋งž๊ฒŒ ๋ณ€ํ˜• ๊ฐ€๋Šฅ

  • add๋‚˜ remove ๊ณ„์—ด์€ ์˜ˆ์™ธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
    • ๋•Œ๋ฌธ์— ์˜ˆ์™ธ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • offer์ด๋‚˜ poll ๊ณ„์—ด์€ null์ด๋‚˜ false๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    • ๋•Œ๋ฌธ์— return๊ฐ’ (๋ฐ˜ํ™˜๊ฐ’)์„ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ Deque์˜ ์ฃผ์š” ๋ฉ”์„œ๋“œ.

1๏ธโƒฃ ์‚ฝ์ž… ์—ฐ์‚ฐ.

  • addFirst(E e) : ์ง€์ •๋œ ์š”์†Œ๋ฅผ ๋ฑ์˜ ์•ž์ชฝ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • addLast(E e) : ์ง€์ •๋œ ์š”์†Œ๋ฅผ ๋ฑ์˜ ๋’ค์ชฝ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • offerFirst(E e) : ์ง€์ •๋œ ์š”์†Œ๋ฅผ ๋ฑ์˜ ์•ž์ชฝ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.
  • offerLast(E e) : ์ง€์ •๋œ ์š”์†Œ๋ฅผ ๋ฑ์˜ ๋’ค์ชฝ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

2๏ธโƒฃ ์‚ญ์ œ ์—ฐ์‚ฐ.

  • removeFirst() : ๋ฑ์˜ ์•ž์ชฝ์—์„œ ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • removeLast() : ๋ฑ์˜ ๋’ค์ชฝ์—์„œ ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • pollFirst() : ๋ฑ์˜ ์•ž์ชฝ์—์„œ ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • pollLast() : ๋ฑ์˜ ๋’ค์ชฝ์—์„œ ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

3๏ธโƒฃ ์กฐํšŒ ์—ฐ์‚ฐ.

  • getFirst() : ๋ฑ์˜ ์•ž์ชฝ์— ์žˆ๋Š” ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • getLast() : ๋ฑ์˜ ๋’ค์ชฝ์— ์žˆ๋Š” ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • peekFirst() : ๋ฑ์˜ ์•ž์ชฝ์— ์žˆ๋Š” ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • peekLast() : ๋ฑ์˜ ๋’ค์ชฝ์— ์žˆ๋Š” ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

4๏ธโƒฃ ๊ธฐํƒ€ ์—ฐ์‚ฐ.

  • size() : ๋ฑ์— ์žˆ๋Š” ์š”์†Œ์˜ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • isEmpty() : ๋ฑ์ด ๋น„์–ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

3๏ธโƒฃ ์‹œ๊ฐ„ ๋ณต์žก๋„.

Deque ์ธํ„ฐํŽ˜์ด์Šค์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋Š” ์ด๋ฅผ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์— ๋”ฐ๋ผ ๋‹ฌ๋ผ์ง‘๋‹ˆ๋‹ค.

Java์—์„œ๋Š” ์ฃผ๋กœ ArrayDeque ์™€ LinkedList ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Deque ๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

1๏ธโƒฃ ArrayDeque

  • ์‚ฝ์ž…๊ณผ ์‚ญ์ œ ์—ฐ์‚ฐ (์•ž๊ณผ ๋’ค ๋ชจ๋‘): ํ‰๊ท ์ ์œผ๋กœ O(1)
  • ์กฐํšŒ ์—ฐ์‚ฐ (์•ž๊ณผ ๋’ค ๋ชจ๋‘): O(1)
  • ArrayDeque ๋Š” ๋ฐฐ์—ด์„ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌํ˜„๋˜๊ธฐ ๋•Œ๋ฌธ์—, ๋ฐฐ์—ด์ด ๊ฝ‰ ์ฐจ๋ฉด ์ž๋™์œผ๋กœ ํฌ๊ธฐ๋ฅผ ๋Š˜๋ฆฌ์ง€๋งŒ, ์ด ๊ณผ์ •์€ amortized O(1)๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค.

2๏ธโƒฃ LinkedList

  • ์‚ฝ์ž…๊ณผ ์‚ญ์ œ ์—ฐ์‚ฐ (์•ž๊ณผ ๋’ค ๋ชจ๋‘): O(1)
  • ์กฐํšŒ ์—ฐ์‚ฐ (์•ž๊ณผ ๋’ค ๋ชจ๋‘): O(1)
  • LinkedList ๋Š” ์ด์ค‘ ์—ฐ๊ฒฐ ๋ฆฌ์ŠคํŠธ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์–ด ๊ฐ ๋…ธ๋“œ๊ฐ€ ์ด์ „๊ณผ ๋‹ค์Œ ๋…ธ๋“œ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

LinkedList๋Š” ๊ฐ ๋…ธ๋“œ๊ฐ€ ์ด์ „ ๋…ธ๋“œ์™€ ๋‹ค์Œ ๋…ธ๋“œ์˜ ์ฐธ์กฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์–ด ์‚ฝ์ž…๊ณผ ์‚ญ์ œ๊ฐ€ O(1)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง‘๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ ํƒ์ƒ‰์—๋Š” O(n)์˜ ์‹œ๊ฐ„์ด ์†Œ์š”๋ฉ๋‹ˆ๋‹ค.

ArrayDeque๋Š” ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ ๋‚ด๋ถ€์ ์œผ๋กœ ๊ตฌํ˜„๋˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฝ์ž…๊ณผ ์‚ญ์ œ ์‹œ์—๋„ ํ‰๊ท ์ ์œผ๋กœ O(1)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๋ฅผ ๊ฐ€์ง€๋ฉฐ,
ํŠนํžˆ ํ์˜ ๋์—์„œ์˜ ์—ฐ์‚ฐ์ด ๋น ๋ฆ…๋‹ˆ๋‹ค.

๋‹ค๋งŒ, ๋‚ด๋ถ€์ ์œผ๋กœ ๋ฐฐ์—ด์ด ๊ฐ€๋“ ์ฐจ๋ฉด ํฌ๊ธฐ๋ฅผ ์กฐ์ •ํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ตœ์•…์˜ ๊ฒฝ์šฐ O(n)์˜ ์‹œ๊ฐ„ ๋ณต์žก๋„๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Deque ๋Š” ๋‹ค์–‘ํ•œ ์ƒํ™ฉ์—์„œ ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ๋Š” ์œ ์šฉํ•œ ์ž๋ฃŒ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.
ํŠนํžˆ ์–‘์ชฝ ๋์—์„œ์˜ ๋น ๋ฅธ ์‚ฝ์ž…๊ณผ ์‚ญ์ œ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

3๏ธโƒฃ ์ง์ ‘ Deque ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„.

๊ฐ„๋‹จํ•œ ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ Deque ๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class SimpleArrayDeque<E> {
  private static final int DEFALT_CAPACITY = 10;
  private E[] elements;
  private int head;
  private int tail;
  private int size;

  public SimpleArrayDeque() {
    elements = (E[]) new Object[DEFALT_CAPACITY];
    head = 0;
    tail = 0;
    size = 0;
  }

  public void addFirst(E e) {
    if (size == elements.length) {
      resize();
    }
    head = (head - 1 + elements.length) % elements.length;
    elements[head] = e;
    size++;
  }

  public void addLast(E e) {
    if (size == elements.length) {
      resize();
    }
    elements[tail] = e;
    tail = (tail + 1) % elements.length;
    size++;
  }

  public E removeFirst() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
    E element = elements[head];
    elements[head] = null; // for garbege collection
    head = (head + 1);
    size--;
    return element;
  }

  public E removeLast() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
    tail = (tail - 1 + elements.length) % elements.length;
    E element = elements[tail];
    elements[tail] = null; // for garbage collection
    size--;
    return element;
  }

  public E getFirst() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
    return elements[head];
  }

  public E getLast() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
    return elements[(tail - 1 + elements.length) % elements.length];
  }

  public int size() {
    return size;
  }

  public boolean isEmpty() {
    return size == 0;
  }

  private void resize() {
    int newCapacity = elements.length * 2;
    E[] newElements = (E[]) new Object[newCapacity];
    for (int i = 0; i < size; i++) {
      newElements[i] = elements[(head + i) % elements.length];
    }
    elements = newElements;
    head = 0;
    tail = size;
  }

  public ArrayList<E> toArrayList() {
    return IntStream.range(0, size)
                    .mapToObj(i -> elements[(head + i) % elements.length])
                    .collect(Collectors.toCollection(ArrayList::new));
  }
}

// Main
import java.util.ArrayList;

public class Main {

  public static void main(String[] args) {
    SimpleArrayDeque<Integer> deque = new SimpleArrayDeque<>();
    deque.addFirst(1);
    deque.addLast(2);
    deque.addFirst(0);
    deque.addLast(3);

    ArrayList<Integer> dequeList = deque.toArrayList();
    System.out.println("=== dequeList === ");
    System.out.println(dequeList);


    System.out.println("First element: " + deque.getFirst());
    System.out.println("Last element: " + deque.getLast());
    System.out.println("=== dequeList === ");
    dequeList = deque.toArrayList();
    System.out.println(dequeList);

    System.out.println("Removed first element: " + deque.removeFirst());
    System.out.println("Remove last element: " + deque.removeLast());
    System.out.println("=== dequeList === ");
    dequeList = deque.toArrayList();
    System.out.println(dequeList);

    System.out.println("Deque size: " + deque.size());
    System.out.println("Is deque empty? " + deque.isEmpty());
    System.out.println("=== dequeList === ");
    dequeList = deque.toArrayList();
    System.out.println(dequeList);
  }
}

/*
=== ์ถœ๋ ฅ ===
=== dequeList === 
[0, 1, 2, 3]
First element: 0
Last element: 3
=== dequeList === 
[0, 1, 2, 3]
Removed first element: 0
Remove last element: 3
=== dequeList === 
[1, 2]
Deque size: 2
Is deque empty? false
=== dequeList === 
[1, 2]
*/

4๏ธโƒฃ ์ž…๋ ฅ ์ œํ•œ Deque(Input-Restricted Deque).

์ž…๋ ฅ ์ œํ•œ Deque(Input-Restricted Deque)์€ ๋ฑ์˜ ํ•œ์ชฝ ๋์—์„œ๋งŒ ์‚ฝ์ž…์ด ๊ฐ€๋Šฅํ•˜๊ณ , ์–‘์ชฝ ๋์—์„œ ์‚ญ์ œ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ž๋ฃŒ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class InputRestrictedDeque<E> {
  private static final int DEFAULT_CAPACITY = 10;
  private E[] elements;
  private int head;
  private int tail;
  private int size;

  @SuppressWarnings("unchecked")
  public InputRestrictedDeque() {
    elements = (E[]) new Object[DEFAULT_CAPACITY];
    head = 0;
    tail = 0;
    size = 0;
  }

  public void addLast(E e) {
    if (size == elements.length) {
      resize();
    }
    elements[tail] = e;
    tail = (tail + 1) % elements.length;
    size++;
  }

  public E removeFirst() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
    E element = elements[head];
    elements[head] = null; // for garbage collection
    head = (head + 1) % elements.length;
    size--;
    return element;
  }

  public E removeLast() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
    tail = (tail - 1 + elements.length) % elements.length;
    E element = elements[tail];
    elements[tail] = null; // for gatbage collection
    size--;
    return element;
  }

  public E getFirst() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
    return elements[head];
  }

  public E getLast() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
    return elements[(tail - 1 + elements.length) % elements.length];
  }

  public int size() {
    return size;
  }

  public boolean isEmpty() {
    return size == 0;
  }

  private void resize() {
    int newCapacity = elements.length * 2;
    @SuppressWarnings("unchecked")
    E[] newElements = (E[]) new Object[newCapacity];
    for (int i = 0; i < size; i++) {
      newElements[i] = elements[(head + i) % elements.length];
    }
    elements = newElements;
    head = 0;
    tail = size;
  }

  public ArrayList<E> toArrayList() {
    return IntStream.range(0, size)
                    .mapToObj(i -> elements[(head + i) % elements.length])
                    .collect(Collectors.toCollection(ArrayList::new));
  }
}

// Main
import java.util.ArrayList;

public class Main {

  public static void main(String[] args) {
    InputRestrictedDeque<Integer> deque = new InputRestrictedDeque<>();
    deque.addLast(1);
    deque.addLast(2);
    deque.addLast(3);

    ArrayList<Integer> dequeList = deque.toArrayList();
    System.out.println("=== dequeList ===");
    System.out.println(dequeList);

    System.out.println("First element: " + deque.getFirst());
    System.out.println("Last element: " + deque.getLast());
    System.out.println("=== dequeList ===");
    dequeList = deque.toArrayList();
    System.out.println(dequeList);

    System.out.println("Remove first element: " + deque.removeFirst());
    System.out.println("Remove last elment: " + deque.removeLast());
    System.out.println("=== dequeList ===");
    dequeList = deque.toArrayList();
    System.out.println(dequeList);

    System.out.println("Deque size: " + deque.size());
    System.out.println("Is deque empty? " + deque.isEmpty());
  }
}
/*
=== ์ถœ๋ ฅ ===
=== dequeList ===
[1, 2, 3]
First element: 1
Last element: 3
=== dequeList ===
[1, 2, 3]
Remove first element: 1
Remove last elment: 3
=== dequeList ===
[2]
Deque size: 1
Is deque empty? false
*/

1๏ธโƒฃ ์ฝ”๋“œ ์„ค๋ช….

  1. ๋ฐฐ์—ด ์ดˆ๊ธฐํ™” : DEFAULT_CAPACITY ํฌ๊ธฐ์˜ ๋ฐฐ์—ด์„ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , head, tail, size ๋ณ€์ˆ˜๋ฅผ ์ดˆ๊ธฐํ™”ํ•ฉ๋‹ˆ๋‹ค.

  2. ์‚ฝ์ž… ์—ฐ์‚ฐ(addLast) : ์š”์†Œ๋ฅผ ๋ฑ์˜ ๋งˆ์ง€๋ง‰ ์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์—ด์ด ๊ฐ€๋“ ์ฐจ๋ฉด ํฌ๊ธฐ๋ฅผ ๋‘ ๋ฐฐ๋กœ ๋Š˜๋ฆฝ๋‹ˆ๋‹ค.

  3. ์‚ญ์ œ ์—ฐ์‚ฐ(removeFirst, removeLaste) : ์ฒซ ๋ฒˆ์งธ ์š”์†Œ์™€ ๋งˆ์ง€๋ง‰ ์š”์†Œ๋ฅผ ๊ฐ๊ฐ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

  4. ์กฐํšŒ ์—ฐ์‚ฐ(getFirst, getLast) : ์ฒซ ๋ฒˆ์งธ ์š”์†Œ์™€ ๋งˆ์ง€๋ง‰ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  5. ๊ธฐํƒ€ ๋ฉ”์„œ๋“œ : size ์™€ isEmpty ๋ฉ”์„œ๋“œ๋Š” ๋ฑ์˜ ํฌ๊ธฐ์™€ ๋ฑ์ด ๋น„์–ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  6. ๋ฐฐ์—ด ํฌ๊ธฐ ์กฐ์ • (resize) : ๋ฐฐ์—ด์ด ๊ฐ€๋“ ์ฐฐ ๋•Œ ํ˜ธ์ถœ๋˜๋ฉฐ, ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๋ฅผ ๋‘ ๋ฐฐ๋กœ ๋Š˜๋ฆฌ๊ณ  ์š”์†Œ๋ฅผ ์ƒˆ ๋ฐฐ์—ด๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์ด ์˜ˆ์ œ์—์„œ๋Š” ์š”์†Œ๋ฅผ ๋ฑ์˜ ๋์—๋งŒ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๋Š” ์ž…๋ ฅ ์ œํ•œ ๋ฑ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.
ํ•„์š”์— ๋”ฐ๋ผ ์ด ๊ตฌํ˜„์„ ํ™•์žฅํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜์—ฌ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

5๏ธโƒฃ ์ถœ๋ ฅ ์ œํ•œ Deque(Output-Restricted Deque).

์ถœ๋ ฅ ์ œํ•œ Deque(Output-Restricted Deque)์€ ์–‘์ชฝ ๋์—์„œ ์‚ฝ์ž…์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, ํ•œ์ชฝ ๋์—์„œ๋งŒ ์‚ญ์ œ๊ฐ€ ๊ฐ€๋Šฅํ•œ ์ž๋ฃŒ ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

์ด ๊ตฌ์กฐ๋Š” ์–‘์ชฝ ๋์—์„œ ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์‚ญ์ œ๋Š” ํ•œ์ชฝ ๋์—์„œ๋งŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class OutputRestrictedDeque<E> {
  private static final int DEFAULT_CAPACITY = 10;
  private E[] elements;
  private int head;
  private int tail;
  private int size;

  @SuppressWarnings("unchecked")
  public OutputRestrictedDeque() {
    elements = (E[]) new Object[DEFAULT_CAPACITY];
    head = 0;
    tail = 0;
    size = 0;
  }

  public void addFirst(E e) {
    if (size == elements.length) {
      resize();
    }
    head = (head - 1 + elements.length) % elements.length;
    elements[head] = e;
    size++;
  }

  public void addLast(E e) {
    if (size == elements.length) {
      resize();
    }
    elements[tail] = e;
    tail = (tail + 1) % elements.length;
    size++;
  }

  public E removeFirst() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
    E element = elements[head];;
    elements[head] = null; // for garbage collection
    head = (head + 1) % elements.length;
    size--;
    return element;
  }

  public E getFirst() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
    return elements[head];
  }

  public E getLast() {
    if (size == 0) {
      throw new NoSuchElementException();
    }
    return elements[(tail - 1 + elements.length) % elements.length];
  }

  public int size() {
    return size;
  }

  public boolean isEmpty() {
    return size == 0;
  }

  private void resize() {
    int newCapacity = elements.length * 2;
    @SuppressWarnings("unchecked")
    E[] newElements = (E[]) new Object[newCapacity];
    for (int i = 0; i < size; i++) {
      newElements[i] = elements[(head + 1) % elements.length];
    }
    elements = newElements;
    head = 0;
    tail = size;
  }

  public ArrayList<E> toArrayList() {
    return IntStream.range(0, size)
                    .mapToObj(i -> elements[(head + i) % elements.length])
                    .collect(Collectors.toCollection(ArrayList::new));
  }
}

// Main
import java.util.ArrayList;

public class Main {

  public static void main(String[] args) {
    OutputRestrictedDeque<Integer> deque = new OutputRestrictedDeque<>();
    deque.addFirst(1);
    deque.addLast(2);
    deque.addFirst(0);
    deque.addLast(3);

    ArrayList<Integer> dequeList = deque.toArrayList();
    System.out.println("=== dequeList === ");
    System.out.println(dequeList);

    System.out.println("First element: " + deque.getFirst());
    System.out.println("Last element: " + deque.getLast());
    System.out.println("=== dequeList === ");
    dequeList = deque.toArrayList();
    System.out.println(dequeList);

    System.out.println("Remove first element: " + deque.removeFirst());
    System.out.println("=== dequeList === ");
    dequeList = deque.toArrayList();
    System.out.println(dequeList);

    System.out.println("Deque size: " + deque.size());
    System.out.println("Is deque empty? " + deque.isEmpty());
    System.out.println("=== dequeList === ");
    dequeList = deque.toArrayList();
    System.out.println(dequeList);
  }
}

/*
=== ์ถœ๋ ฅ ===
=== dequeList ===
[0, 1, 2, 3]
First element: 0
Last element: 3
=== dequeList ===
[0, 1, 2, 3]
Remove first element: 0
=== dequeList ===
[1, 2, 3]
Deque size: 3
Is deque empty? false
=== dequeList ===
[1, 2, 3]
*/

1๏ธโƒฃ ์ฝ”๋“œ ์„ค๋ช….

  1. ๋ฐฐ์—ด ์ดˆ๊ธฐํ™” : DEFAULT_CAPACITY ํฌ๊ธฐ์˜ ๋ฐฐ์—ด์„ ์ดˆ๊ธฐํ™”ํ•˜๊ณ , head, tail, size ๋ณ€์ˆ˜๋ฅผ ์ดˆ๊ธฐํ™” ํ•ฉ๋‹ˆ๋‹ค.

  2. ์‚ฝ์ž… ์—ฐ์‚ฐ(addFirst, addLast) : ์š”์†Œ๋ฅผ ๋ฑ์˜ ์ฒซ ๋ฒˆ์งธ ๋˜๋Š” ๋งˆ์ง€๋ง‰์— ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค. ๋ฐฐ์—ด์ด ๊ฐ€๋“ ์ฐจ๋ฉด ํฌ๊ธฐ๋ฅผ ๋‘ ๋ฐฐ๋กœ ๋Š˜๋ฆฝ๋‹ˆ๋‹ค.

  3. ์‚ญ์ œ ์—ฐ์‚ฐ(removeFirst) : ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ์ œ๊ฑฐํ•ฉ๋‹ˆ๋‹ค. ์ถœ๋ ฅ ์ œํ•œ ๋ฑ์—์„œ๋Š” ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋งŒ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  4. ์กฐํšŒ ์—ฐ์‚ฐ(getFirst, getLast) : ์ฒซ ๋ฒˆ์งธ ์š”์†Œ์™€ ๋งˆ์ง€๋ง‰ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  5. ๊ธฐํƒ€ ๋ฉ”์„œ๋“œ : size ์™€ isEmpty ๋ฉ”์„œ๋“œ๋Š” ๋ฑ์˜ ํฌ๊ธฐ์™€ ๋ฑ์ด ๋น„์–ด ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  6. ๋ฐฐ์—ด ํฌ๊ธฐ ์กฐ์ •(resize) : ๋ฐฐ์—ด์ด ๊ฐ€๋“ ์ฐฐ ๋•Œ ํ˜ธ์ถœ๋˜๋ฉฐ, ๋ฐฐ์—ด์˜ ํฌ๊ธฐ๋ฅผ ๋‘ ๋ฐฐ๋กœ ๋Š˜๋ฆฌ๊ณ  ์š”์†Œ๋ฅผ ์ƒˆ ๋ฐฐ์—ด๋กœ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค.

์ด ์˜ˆ์ œ์—์„œ๋Š” ์š”์†Œ๋ฅผ ๋ฑ์˜ ์–‘์ชฝ ๋์—์„œ ์‚ฝ์ž…ํ•  ์ˆ˜ ์žˆ๊ณ , ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋งŒ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๋Š” ์ถœ๋ ฅ ์ œํ•œ ๋ฑ์„ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.
ํ•„์š”์— ๋”ฐ๋ผ ์ด ๊ตฌํ˜„์„ ํ™•์žฅํ•˜๊ฑฐ๋‚˜ ์ˆ˜์ •ํ•˜์—ฌ ์š”๊ตฌ์‚ฌํ•ญ์— ๋งž๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.