데크
- Double-Ended-Queue의 줄임말로, 글자 그대로 양쪽 끝을 모두 추출할 수 있는, 큐를 일반화한 형태의 추상 자료형(ADT)이다.
- 양쪽에서 삽입과 삭제를 모두 처리할 수 있으며, 스택과 큐의 특징을 모두 갖고 있다.
- 이중 연결 리스트(Doubly Linked List)로 구현
- 양쪽으로 head와 tail이라는 이름의 두 포인터를 갖고 있다가 새로운 아이템이 추가될 때마다 앞쪽 또는 뒤쪽으로 연결해주기만 하면 된다.
- 자바에서 데크를 구현하는 Deque 자료형은 Queue와 마찬가지로 인터페이스이며, Queue를 확장해 정의되어 있다 ,
- 실제 구현은 LinkedList 또는 ArrayDeque로 할 수 있다.
//데크 선언
Deque<Integer> deque = new LinkedList<>();
https://leetcode.com/problems/design-circular-deque/description/
- 다음 연산을 제공하는 원형 데크를 디자인 하라
MyCircularDeque(k) : 데크 크기를 k로 지정하는 생성자
insertFront() : 데크 처음에 아이템을 추가하고 성공할 경우 true를 리턴
insertLast() : 데크 마지막에 아이템을 추가하고 성공할 경우 true를 리턴
deleteFront() : 데크 처음에 아이템을 삭제하고 성공할 경우 true를 리턴
deleteLast() : 데크 마지막에 아이템을 삭제하고 성공할 경우 true를 리턴
getFront() : 데크의 첫 번째 아이템을 가져온다. 데크가 비어 있다면 -1을 리턴
getRear() : 데크의 마지막 아이템을 가져온다. 데크가 비어 있다면 -1을 리턴
isEmpty() : 데크가 비어 있는지 여부를 판별
isFull() : 데크가 가득 차 있는지 여부를 판별
풀이 1) 이중 연결 리스트를 이용한 데크 구현
1) 이중 연결 리스트를 사용할 클래스 정의
- 문제 풀이 클래스의 중첩 클래스(Nested Class)로 선언과 초기화
- 전체 큐의 크기를 k로 바독, 현재 큐의 크기는 len으로 정해서 매번 계산한다.
- 2개의 연결 리스트를 미리 선언하고 서로 연결한 상태에서 시작
//이중 연결 리스트로 사용할 클래스 선언
static class DoublyLinkedList {
//왼쪽으로 연결할 이중 연결 리스트
DoublyLinkedList left;
//오른쪽으로 연결할 이중 연결 리스트
DoublyLinkedList right;
int val;
public DoublyLinkedList(int val)
{
this.val = val;
}
}
int len; //현재 큐의 크기
int k; //전체 큐의 크기
DoublyLinkedList head; //이중 연결 리스트 head 노드
DoublyLinkedList tail; //이중 연결 리스트 tail 노드
2) insertFront
- 만약 큐가 꽉 차 있다면 false를 리턴하고 종료
- head의 바로 오른쪽에 노드를 삽입하고 이중으로 연결한다.
- 그렇게 해서 head는 맨 앞을, tail은 맨 뒤를 유지하며 중간에 노드가 삽입되고 삭제되는 구조를 띤다.
public boolean insertFront(int value) {
//꽉 차 있으면 진행하지 않음
if(isFull())
return false;
DoublyLinkedList node = new DoublyLinkedList(value);
//신규 노드는 head 바로 오른쪽에 삽입
node.right = head.right;
node.left = head;
head.right.left = node;
head.right = node;
len++;
return true;
}
3) insertLast
- 맨 뒤에 노드를 추가할 때는 tail의 바로 왼쪽에 노드를 삽입하고 마찬가지로 이중으로 연결한다,
- 그러면서 tail은 다시 맨 뒤로 간다.
public boolean insertLast(int value) {
//꽉 차 있으면 진행하지 않음
if(isFull())
return false;
DoublyLinkedList node = new DoublyLinkedList(value);
//신규 노드는 tail 바로 왼쪽에 삽입
node.left = tail.left;
node.right = tail;
tail.left.right = node;
tail.left = node;
len++;
return true;
}
class MyCircularDeque {
//이중 연결 리스트로 사용할 클래스 선언
static class DoublyLinkedList {
//왼쪽으로 연결할 이중 연결 리스트
DoublyLinkedList left;
//오른쪽으로 연결할 이중 연결 리스트
DoublyLinkedList right;
int val;
public DoublyLinkedList(int val)
{
this.val = val;
}
}
int len; //현재 큐의 크기
int k; //전체 큐의 크기
DoublyLinkedList head; //이중 연결 리스트 head 노드
DoublyLinkedList tail; //이중 연결 리스트 tail 노드
public MyCircularDeque(int k) {
//이중 연결 리스트 2개 생성
head = new DoublyLinkedList(0);
tail = new DoublyLinkedList(0);
//서로 연결
head.right = tail;
tail.left = head;
//전체 큐의 크기 지정
this.k = k;
//현재 큐의 크기 지정
this.len = 0;
}
public boolean insertFront(int value) {
//꽉 차 있으면 진행하지 않음
if(isFull())
return false;
DoublyLinkedList node = new DoublyLinkedList(value);
//신규 노드는 head 바로 오른쪽에 삽입
node.right = head.right;
node.left = head;
head.right.left = node;
head.right = node;
len++;
return true;
}
public boolean insertLast(int value) {
//꽉 차 있으면 진행하지 않음
if(isFull())
return false;
DoublyLinkedList node = new DoublyLinkedList(value);
//신규 노드는 tail 바로 왼쪽에 삽입
node.left = tail.left;
node.right = tail;
tail.left.right = node;
tail.left = node;
len++;
return true;
}
public boolean deleteFront() {
//텅 비어 있다면 진행하지 않음
if(isEmpty())
return false;
//head 바로 오른쪽 노드를 연결에서 끊음
head.right.right.left = head;
head.right = head.right.right;
len--;
return true;
}
public boolean deleteLast() {
//텅 비어 있다면 진행하지 않음
if(isEmpty())
return false;
//tail 바로 왼쪽 노드를 연결에서 끊음
tail.left.left.right = tail;
tail.left = tail.left.left;
len--;
return true;
}
public int getFront() {
//맨 앞(head 오른쪽)의 값을 가져온다.
return (isEmpty())?-1:head.right.val;
}
public int getRear() {
//맨 뒤(tail 왼쪽)의 값을 가져온다.
return (isEmpty())?-1:tail.left.val;
}
public boolean isEmpty() {
//현재 큐의 크기가 0이면 비어 있음
return len == 0;
}
public boolean isFull() {
//현재 큐의 크기가 처음 선언한 큐의 크기와 일치하면 꽉 차 있음
return len == k;
}
}
/**
* Your MyCircularDeque object will be instantiated and called as such:
* MyCircularDeque obj = new MyCircularDeque(k);
* boolean param_1 = obj.insertFront(value);
* boolean param_2 = obj.insertLast(value);
* boolean param_3 = obj.deleteFront();
* boolean param_4 = obj.deleteLast();
* int param_5 = obj.getFront();
* int param_6 = obj.getRear();
* boolean param_7 = obj.isEmpty();
* boolean param_8 = obj.isFull();
*/
5밀리초
'Java > 알고리즘' 카테고리의 다른 글
[자바 알고리즘 인터뷰] ch 10. 데크, 우선순위 큐 (3) - 원점에서 가장 가까운 k개의 점 (0) | 2024.05.11 |
---|---|
[자바 알고리즘 인터뷰] 10장 데크, 우선순위 큐 (2) k개 정렬 리스트 병합 (0) | 2024.05.10 |
[자바 알고리즘 인터뷰] 9장 스택,큐 (6) 원형 큐 디자인 (0) | 2024.05.10 |
[자바 알고리즘 인터뷰] 9장 큐,스택 (5) 스택을 이용한 큐 구현 (0) | 2024.05.10 |
[자바 알고리즘 인터뷰] 9장 스택,큐 (4) 큐를 이용한 스택 구현 (0) | 2024.05.10 |