행렬과 연산

Lv. 4

Solution

type Operation = 'Rotate' | 'ShiftRow';
 
class Node<T> {
  value: T;
  prev: Node<T> | null;
  next: Node<T> | null;
 
  constructor(value: T, prev: Node<T> | null = null, next: Node<T> | null = null) {
    this.value = value;
    this.prev = prev;
    this.next = next;
  }
}
 
export class Deque<T> {
  private size: number = 0;
  private firstNode: Node<T> | null = null;
  private lastNode: Node<T> | null = null;
 
  constructor(arr: T[] = []) {
    arr.forEach((value) => {
      this.push(value);
    });
  }
 
  get length() {
    return this.size;
  }
 
  get first(): T | undefined {
    return this.firstNode?.value;
  }
 
  get last(): T | undefined {
    return this.lastNode?.value;
  }
 
  push(value: T): void {
    const last = this.lastNode;
    this.lastNode = new Node(value, last);
    if (last !== null) {
      last.next = this.lastNode;
    }
    if (this.firstNode === null) {
      this.firstNode = this.lastNode;
    }
    this.size += 1;
  }
 
  pushLeft(value: T): void {
    const first = this.firstNode;
    this.firstNode = new Node(value, null, first);
    if (first !== null) {
      first.prev = this.firstNode;
    }
    if (this.lastNode === null) {
      this.lastNode = this.firstNode;
    }
    this.size += 1;
  }
 
  pop(): T | undefined {
    if (this.size === 0 || this.firstNode === null || this.lastNode === null) {
      return;
    }
    const last = this.lastNode;
    this.lastNode = last.prev;
    if (this.lastNode !== null) {
      this.lastNode.next = null;
    }
    if (this.firstNode === last) {
      this.firstNode = null;
    }
    this.size -= 1;
    return last.value;
  }
 
  popLeft(): T | undefined {
    if (this.size === 0 || this.firstNode === null || this.lastNode === null) {
      return;
    }
    const first = this.firstNode;
    this.firstNode = first.next;
    if (this.firstNode !== null) {
      this.firstNode.prev = null;
    }
    if (this.lastNode === first) {
      this.lastNode = null;
    }
    this.size -= 1;
    return first.value;
  }
 
  rotate(): void {
    if (this.size === 0) {
      return;
    }
    this.pushLeft(this.pop()!);
  }
 
  *[Symbol.iterator]() {
    let currentNode = this.firstNode;
    while (currentNode !== null) {
      yield currentNode.value;
      currentNode = currentNode.next;
    }
  }
}
 
export function matrixAndOpertaion(rc: number[][], operations: Operation[]): number[][] {
  const [m, n] = [rc.length, rc[0].length];
  const left = new Deque<number>();
  const right = new Deque<number>();
  const mid = new Deque<Deque<number>>();
 
  rc.forEach((row) => {
    left.push(row[0]);
    right.push(row[n - 1]);
    mid.push(new Deque(row.slice(1, -1)));
  });
 
  const shiftRow = () => {
    left.rotate();
    right.rotate();
    mid.rotate();
  };
 
  const rotate = () => {
    mid.first!.pushLeft(left.popLeft()!);
    right.pushLeft(mid.first!.pop()!);
    mid.last!.push(right.pop()!);
    left.push(mid.last!.popLeft()!);
  };
 
  operations.forEach((op) => {
    if (op === 'ShiftRow') {
      shiftRow();
    } else {
      rotate();
    }
  });
 
  const answer: number[][] = [];
  for (let i = 0; i < m; i++) {
    answer.push([left.popLeft()!, ...mid.popLeft()!, right.popLeft()!]);
  }
 
  return answer;
}